Skip to content
Snippets Groups Projects
Commit 08e4cc85 authored by Siena Richard's avatar Siena Richard Committed by Pat Tjin
Browse files

FROMLIST: drivers: soc: add mutex to prevent response being processed twice


Add a mutex to prevent two threads from processing the same response
at the same time. This ensures responses are processed completely and
sequentially.

Bug: 34088848
CRs-Fixed: 1116015
Change-Id: Id2ef32edb939f8af2850b54bd6f6f447939c0732
Signed-off-by: default avatarSiena Richard <sienar@codeaurora.org>
Signed-off-by: default avatarSiqi Lin <siqilin@google.com>
(am from https://source.codeaurora.org/quic/la/kernel/msm-4.4/commit/?id=d3237316314c3d6f75a58192971f66e3822cd250)
parent a4d7a2b9
No related branches found
No related tags found
No related merge requests found
/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
......@@ -42,6 +42,12 @@ struct voice_svc_prvt {
struct list_head response_queue;
wait_queue_head_t response_wait;
spinlock_t response_lock;
/*
* This mutex ensures responses are processed in sequential order and
* that no two threads access and free the same response at the same
* time.
*/
struct mutex response_mutex_lock;
};
struct apr_data {
......@@ -467,6 +473,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg,
goto done;
}
mutex_lock(&prtd->response_mutex_lock);
spin_lock_irqsave(&prtd->response_lock, spin_flags);
if (list_empty(&prtd->response_queue)) {
......@@ -480,7 +487,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg,
pr_debug("%s: Read timeout\n", __func__);
ret = -ETIMEDOUT;
goto done;
goto unlock;
} else if (ret > 0 && !list_empty(&prtd->response_queue)) {
pr_debug("%s: Interrupt recieved for response\n",
__func__);
......@@ -488,7 +495,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg,
pr_debug("%s: Interrupted by SIGNAL %d\n",
__func__, ret);
goto done;
goto unlock;
}
spin_lock_irqsave(&prtd->response_lock, spin_flags);
......@@ -507,7 +514,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg,
__func__, count, size);
ret = -ENOMEM;
goto done;
goto unlock;
}
if (!access_ok(VERIFY_WRITE, arg, size)) {
......@@ -515,7 +522,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg,
__func__);
ret = -EPERM;
goto done;
goto unlock;
}
ret = copy_to_user(arg, &resp->resp,
......@@ -525,7 +532,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg,
pr_err("%s: copy_to_user failed %d\n", __func__, ret);
ret = -EPERM;
goto done;
goto unlock;
}
spin_lock_irqsave(&prtd->response_lock, spin_flags);
......@@ -539,6 +546,8 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg,
ret = count;
unlock:
mutex_unlock(&prtd->response_mutex_lock);
done:
return ret;
}
......@@ -594,6 +603,7 @@ static int voice_svc_open(struct inode *inode, struct file *file)
INIT_LIST_HEAD(&prtd->response_queue);
init_waitqueue_head(&prtd->response_wait);
spin_lock_init(&prtd->response_lock);
mutex_init(&prtd->response_mutex_lock);
file->private_data = (void *)prtd;
/* Current APR implementation doesn't support session based
......@@ -644,6 +654,7 @@ static int voice_svc_release(struct inode *inode, struct file *file)
pr_err("%s: Failed to dereg MVM %d\n", __func__, ret);
}
mutex_lock(&prtd->response_mutex_lock);
spin_lock_irqsave(&prtd->response_lock, spin_flags);
while (!list_empty(&prtd->response_queue)) {
......@@ -657,6 +668,9 @@ static int voice_svc_release(struct inode *inode, struct file *file)
}
spin_unlock_irqrestore(&prtd->response_lock, spin_flags);
mutex_unlock(&prtd->response_mutex_lock);
mutex_destroy(&prtd->response_mutex_lock);
kfree(file->private_data);
file->private_data = NULL;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment