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