summaryrefslogtreecommitdiff
path: root/sound/soc
diff options
context:
space:
mode:
authorBhalchandra Gajare <gajare@codeaurora.org>2016-02-04 15:14:57 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 21:20:37 -0700
commit72f0f4b937bd8a4ae15a6dd3b8a7a92b39ec6567 (patch)
treee8107e30b7dd1dfa5dbfd0ddd89d093d7ba902fd /sound/soc
parent90c2030c5bdc3013b2b02eda8bdc7cf93c5eb141 (diff)
ASoC: wcd_cpe_services: Make the worker thread standalone
The worker thread can either be stopped through kthread_stop or could return from the function on some conditions. Since thread has two exit points, this is causing a race condition where kthread_stop indefinitely waits for the thread to exit. Make the thread standalone and always call do_exit itself to exit instead of stopping it through kthread_stop. CRs-fixed: 972943 Change-Id: If95cbd6ee895d566887453e98421d1514147441b Signed-off-by: Bhalchandra Gajare <gajare@codeaurora.org>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/codecs/wcd_cpe_services.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/sound/soc/codecs/wcd_cpe_services.c b/sound/soc/codecs/wcd_cpe_services.c
index d4dbf02d15d1..5a82c8e5382b 100644
--- a/sound/soc/codecs/wcd_cpe_services.c
+++ b/sound/soc/codecs/wcd_cpe_services.c
@@ -161,6 +161,7 @@ struct cpe_command_node {
struct cpe_info {
struct list_head main_queue;
struct completion cmd_complete;
+ struct completion thread_comp;
void *thread_handler;
bool stop_thread;
struct mutex msg_lock;
@@ -392,31 +393,34 @@ static int cpe_worker_thread(void *context)
{
struct cpe_info *t_info = (struct cpe_info *)context;
- while (!kthread_should_stop()) {
+ /*
+ * Thread will run until requested to stop explicitly
+ * by setting the t_info->stop_thread flag
+ */
+ while (1) {
+ /* Wait for command to be processed */
wait_for_completion(&t_info->cmd_complete);
CPE_SVC_GRAB_LOCK(&t_info->msg_lock, "msg_lock");
cpe_cmd_received(t_info);
reinit_completion(&t_info->cmd_complete);
+ /* Check if thread needs to be stopped */
if (t_info->stop_thread)
goto unlock_and_exit;
CPE_SVC_REL_LOCK(&t_info->msg_lock, "msg_lock");
};
- pr_debug("%s: thread exited\n", __func__);
- return 0;
-
unlock_and_exit:
pr_debug("%s: thread stopped\n", __func__);
CPE_SVC_REL_LOCK(&t_info->msg_lock, "msg_lock");
-
- return 0;
+ complete_and_exit(&t_info->thread_comp, 0);
}
static void cpe_create_worker_thread(struct cpe_info *t_info)
{
INIT_LIST_HEAD(&t_info->main_queue);
init_completion(&t_info->cmd_complete);
+ init_completion(&t_info->thread_comp);
t_info->stop_thread = false;
t_info->thread_handler = kthread_run(cpe_worker_thread,
(void *)t_info, "cpe-worker-thread");
@@ -440,9 +444,12 @@ static void cpe_cleanup_worker_thread(struct cpe_info *t_info)
complete(&t_info->cmd_complete);
CPE_SVC_REL_LOCK(&t_info->msg_lock, "msg_lock");
- kthread_stop(t_info->thread_handler);
-
+ /* Wait for the thread to exit */
+ wait_for_completion(&t_info->thread_comp);
t_info->thread_handler = NULL;
+
+ pr_debug("%s: Thread cleaned up successfully\n",
+ __func__);
}
static enum cpe_svc_result