The patch
ASoC: SOF: pcm: harden PCM STOP sequence
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.4
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 0a1b08345bc5d9214dc701f8ec5d67c473fab735 Mon Sep 17 00:00:00 2001
From: Pan Xiuli xiuli.pan@linux.intel.com Date: Fri, 27 Sep 2019 15:05:31 -0500 Subject: [PATCH] ASoC: SOF: pcm: harden PCM STOP sequence
The old STOP sequence is: 1. stop DMA 2. send STOP ipc If delay happen before the steps 1 and 2, the DMA buffer will be empty in short time and cause pipeline xrun then stop the pipeline. Then the step 2 ipc stop will return error as pipeline is already stopped.
Suggested change to avoid the issue is to switch the order of steps 1 and 2 for the stop sequence.
Signed-off-by: Pan Xiuli xiuli.pan@linux.intel.com Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Link: https://lore.kernel.org/r/20190927200538.660-7-pierre-louis.bossart@linux.in... Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/sof/pcm.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index fa7769dd825c..2b876d497447 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -323,6 +323,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct sof_ipc_stream stream; struct sof_ipc_reply reply; bool reset_hw_params = false; + bool ipc_first = false; int ret;
/* nothing to do for BE */ @@ -343,6 +344,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) switch (cmd) { case SNDRV_PCM_TRIGGER_PAUSE_PUSH: stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_PAUSE; + ipc_first = true; break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_RELEASE; @@ -363,6 +365,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP; + ipc_first = true; reset_hw_params = true; break; default: @@ -370,12 +373,22 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) return -EINVAL; }
- snd_sof_pcm_platform_trigger(sdev, substream, cmd); + /* + * DMA and IPC sequence is different for start and stop. Need to send + * STOP IPC before stop DMA + */ + if (!ipc_first) + snd_sof_pcm_platform_trigger(sdev, substream, cmd);
/* send IPC to the DSP */ ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, sizeof(stream), &reply, sizeof(reply));
+ /* need to STOP DMA even if STOP IPC failed */ + if (ipc_first) + snd_sof_pcm_platform_trigger(sdev, substream, cmd); + + /* free PCM if reset_hw_params is set and the STOP IPC is successful */ if (!ret && reset_hw_params) ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);