diff mbox series

ASoC: SOF: ipc4-topology: Implement tear_down_all_pipelines callback

Message ID 20221107084158.26629-1-peter.ujfalusi@linux.intel.com
State Accepted
Commit 18cd1f3227768f4a76c4f7aa95c1256f07ce8647
Headers show
Series ASoC: SOF: ipc4-topology: Implement tear_down_all_pipelines callback | expand

Commit Message

Peter Ujfalusi Nov. 7, 2022, 8:41 a.m. UTC
During system suspend there is a chance that the running stream undergo
an xrun and instead of the expected SNDRV_PCM_TRIGGER_SUSPEND trigger
we will receive SNDRV_PCM_TRIGGER_STOP.

The handling of SUSPEND and STOP triggers differ that case of the later
the sof_pcm_stream_free() will be called with free_widget_list = false.
But we must make sure that all active widgets and streams are free before
entering suspend in order to be able to resume without error.

We can utilize the tear_down_all_pipelines to put the system to an expected
state and to fix the suspend/resume error.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
---
 sound/soc/sof/ipc4-topology.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

Comments

Mark Brown Nov. 10, 2022, 5:55 p.m. UTC | #1
On Mon, 7 Nov 2022 10:41:58 +0200, Peter Ujfalusi wrote:
> During system suspend there is a chance that the running stream undergo
> an xrun and instead of the expected SNDRV_PCM_TRIGGER_SUSPEND trigger
> we will receive SNDRV_PCM_TRIGGER_STOP.
> 
> The handling of SUSPEND and STOP triggers differ that case of the later
> the sof_pcm_stream_free() will be called with free_widget_list = false.
> But we must make sure that all active widgets and streams are free before
> entering suspend in order to be able to resume without error.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/1] ASoC: SOF: ipc4-topology: Implement tear_down_all_pipelines callback
      commit: 18cd1f3227768f4a76c4f7aa95c1256f07ce8647

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
diff mbox series

Patch

diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c
index ab85dde4303b..c31b7f065c1d 100644
--- a/sound/soc/sof/ipc4-topology.c
+++ b/sound/soc/sof/ipc4-topology.c
@@ -1813,6 +1813,39 @@  static int sof_ipc4_dai_get_clk(struct snd_sof_dev *sdev, struct snd_sof_dai *da
 	return -EINVAL;
 }
 
+static int sof_ipc4_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verify)
+{
+	struct snd_sof_pcm *spcm;
+	int dir, ret;
+
+	/*
+	 * This function is called during system suspend, we need to make sure
+	 * that all streams have been freed up.
+	 * Freeing might have been skipped when xrun happened just at the start
+	 * of the suspend and it sent a SNDRV_PCM_TRIGGER_STOP to the active
+	 * stream. This will call sof_pcm_stream_free() with
+	 * free_widget_list = false which will leave the kernel and firmware out
+	 * of sync during suspend/resume.
+	 *
+	 * This will also make sure that paused streams handled correctly.
+	 */
+	list_for_each_entry(spcm, &sdev->pcm_list, list) {
+		for_each_pcm_streams(dir) {
+			struct snd_pcm_substream *substream = spcm->stream[dir].substream;
+
+			if (!substream || !substream->runtime)
+				continue;
+
+			if (spcm->stream[dir].list) {
+				ret = sof_pcm_stream_free(sdev, substream, spcm, dir, true);
+				if (ret < 0)
+					return ret;
+			}
+		}
+	}
+	return 0;
+}
+
 static enum sof_tokens host_token_list[] = {
 	SOF_COMP_TOKENS,
 	SOF_AUDIO_FMT_NUM_TOKENS,
@@ -1913,4 +1946,5 @@  const struct sof_ipc_tplg_ops ipc4_tplg_ops = {
 	.dai_config = sof_ipc4_dai_config,
 	.parse_manifest = sof_ipc4_parse_manifest,
 	.dai_get_clk = sof_ipc4_dai_get_clk,
+	.tear_down_all_pipelines = sof_ipc4_tear_down_all_pipelines,
 };