From 4d7e825ff097bebb2b64957d1bd38f0aa454f7e8 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 6 Feb 2024 16:52:33 +0200 Subject: [PATCH] ASoC: SOF: sof-audio: Manage core refcount per widget as well Increment and decrement the core use count per widget alongside of the pipeline used core refcounting to avoid cases when the pipeline widget is not the last one to be freed, causing cores to power off and IPCs failing Fixes: 31ed8da1c8e5 ("ASoC: SOF: sof-audio: Modify logic for enabling/disabling topology cores") Signed-off-by: Peter Ujfalusi --- sound/soc/sof/sof-audio.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 9163975c9c3f..07ba125d730b 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -86,6 +86,16 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev, err = ret; } + /* decrement ref count for core associated with the widget */ + ret = snd_sof_dsp_core_put(sdev, swidget->core); + if (ret < 0) { + dev_err(sdev->dev, + "failed to disable target core: %d for widget %s\n", + swidget->core, swidget->widget->name); + if (!err) + err = ret; + } + /* * decrement ref count for cores associated with all modules in the pipeline and clear * the complete flag @@ -109,8 +119,9 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev, * free the scheduler widget (same as pipe_widget) associated with the current swidget. * skip for static pipelines */ - if (swidget->dynamic_pipeline_widget && swidget->id != snd_soc_dapm_scheduler) { - ret = sof_widget_free_unlocked(sdev, pipe_widget); + if (swidget->spipe && swidget->dynamic_pipeline_widget && + swidget->id != snd_soc_dapm_scheduler) { + ret = sof_widget_free_unlocked(sdev, swidget->spipe->pipe_widget); if (ret < 0 && !err) err = ret; } @@ -171,6 +182,14 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev, goto use_count_dec; } + /* update ref count for core associated with the widget */ + ret = snd_sof_dsp_core_get(sdev, swidget->core); + if (ret < 0) { + dev_err(sdev->dev, "failed to enable target core %d for pipeline %s\n", + swidget->core, swidget->widget->name); + goto pipe_widget_free; + } + /* update ref count for cores associated with all modules in the pipeline */ if (swidget->id == snd_soc_dapm_scheduler) { for_each_set_bit(i, &spipe->core_mask, sdev->num_cores) { @@ -178,7 +197,7 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev, if (ret < 0) { dev_err(sdev->dev, "failed to enable target core %d for pipeline %s\n", i, swidget->widget->name); - goto pipe_widget_free; + goto core_put; } } } @@ -187,7 +206,7 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev, if (tplg_ops && tplg_ops->widget_setup) { ret = tplg_ops->widget_setup(sdev, swidget); if (ret < 0) - goto pipe_widget_free; + goto core_put; } /* send config for DAI components */ @@ -220,6 +239,9 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev, /* widget use_count will be decremented by sof_widget_free() */ sof_widget_free_unlocked(sdev, swidget); use_count_decremented = true; +core_put: + if (!use_count_decremented) + snd_sof_dsp_core_put(sdev, swidget->core); pipe_widget_free: if (swidget->id != snd_soc_dapm_scheduler) { sof_widget_free_unlocked(sdev, swidget->spipe->pipe_widget); -- 2.43.0