From bbe41586cdfa9aeb95d24b5682ce3a0f528e9648 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 19 Oct 2026 15:58:20 +0900 Subject: [PATCH] ASoC: imx-pcm-rpmsg: Flush pending work in hw_free imx_rpmsg_terminate_all() queues the TERMINATE message to the workqueue and returns, while the DAI hw_free() synchronously gates the audio clock. The two can then run concurrently, and this concurrent access to the shared audio clock path can cause a stop failure or even hang the system. Flush the workqueue in a new component hw_free(), which runs before the DAI hw_free(), so TERMINATE is fully handled before the clock is gated. CLOSE stays the last message. Signed-off-by: Chancel Liu Reviewed-by: Frank Li Reviewed-by: Shengjiu Wang Link: https://patch.msgid.link/20261019-b4-imx-pcm-rpmsg-concurrent-v1-1-c1fb8c33f4db@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-pcm-rpmsg.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c index 85b7c929a28a..6a0174d6c78d 100644 --- a/sound/soc/fsl/imx-pcm-rpmsg.c +++ b/sound/soc/fsl/imx-pcm-rpmsg.c @@ -178,6 +178,16 @@ static int imx_rpmsg_pcm_hw_params(struct snd_soc_component *component, return 0; } +static int imx_rpmsg_pcm_hw_free(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct rpmsg_info *info = dev_get_drvdata(component->dev); + + flush_workqueue(info->rpmsg_wq); + + return 0; +} + static snd_pcm_uframes_t imx_rpmsg_pcm_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream) { @@ -285,9 +295,6 @@ static int imx_rpmsg_pcm_close(struct snd_soc_component *component, struct rpmsg_info *info = dev_get_drvdata(component->dev); struct rpmsg_msg *msg; - /* Flush work in workqueue to make TX_CLOSE is the last message */ - flush_workqueue(info->rpmsg_wq); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { msg = &info->msg[TX_CLOSE]; msg->s_msg.header.cmd = TX_CLOSE; @@ -624,6 +631,7 @@ static const struct snd_soc_component_driver imx_rpmsg_soc_component = { .open = imx_rpmsg_pcm_open, .close = imx_rpmsg_pcm_close, .hw_params = imx_rpmsg_pcm_hw_params, + .hw_free = imx_rpmsg_pcm_hw_free, .trigger = imx_rpmsg_pcm_trigger, .pointer = imx_rpmsg_pcm_pointer, .ack = imx_rpmsg_pcm_ack,