mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-10-01 01:35:54 -04:00
131 lines
4.1 KiB
Diff
131 lines
4.1 KiB
Diff
|
From d3237316314c3d6f75a58192971f66e3822cd250 Mon Sep 17 00:00:00 2001
|
||
|
From: Siena Richard <sienar@codeaurora.org>
|
||
|
Date: Thu, 26 Jan 2017 15:02:42 -0800
|
||
|
Subject: 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.
|
||
|
|
||
|
CRs-Fixed: 1116015
|
||
|
Change-Id: Id2ef32edb939f8af2850b54bd6f6f447939c0732
|
||
|
Signed-off-by: Siena Richard <sienar@codeaurora.org>
|
||
|
---
|
||
|
drivers/soc/qcom/qdsp6v2/voice_svc.c | 26 ++++++++++++++++++++------
|
||
|
1 file changed, 20 insertions(+), 6 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c
|
||
|
index 50dd925..10f71b8 100644
|
||
|
--- a/drivers/soc/qcom/qdsp6v2/voice_svc.c
|
||
|
+++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c
|
||
|
@@ -1,4 +1,4 @@
|
||
|
-/* 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;
|
||
|
--
|
||
|
cgit v1.1
|
||
|
|