Skip to content

Commit

Permalink
ASoC: SOF: sof-audio: Modify logic for enabling/disabling topology cores
Browse files Browse the repository at this point in the history
In the current code, we enable a widget core when it is set up and
disable it when it is freed. This is problematic with IPC4 because
widget free is essentially a NOP and all widgets are freed in the
firmware when the pipeline is deleted. This results in a crash during
pipeline deletion when one of it's widgets is scheduled to run on a
secondary core and is powered off when widget is freed. So, change the
logic to enable all cores needed by all the modules in a pipeline when
the pipeline widget is set up and disable them after the pipeline
widget is freed.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://lore.kernel.org/r/20231124135743.24674-3-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
ranj063 authored and broonie committed Nov 24, 2023
1 parent 0376b99 commit 31ed8da
Showing 1 changed file with 41 additions and 24 deletions.
65 changes: 41 additions & 24 deletions sound/soc/sof/sof-audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev,
struct snd_sof_widget *swidget)
{
const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
struct snd_sof_pipeline *spipe = swidget->spipe;
struct snd_sof_widget *pipe_widget;
int err = 0;
int ret;
Expand Down Expand Up @@ -87,15 +88,22 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev,
}

/*
* disable widget core. continue to route setup status and complete flag
* even if this fails and return the appropriate error
* decrement ref count for cores associated with all modules in the pipeline and clear
* the complete flag
*/
ret = snd_sof_dsp_core_put(sdev, swidget->core);
if (ret < 0) {
dev_err(sdev->dev, "error: failed to disable target core: %d for widget %s\n",
swidget->core, swidget->widget->name);
if (!err)
err = ret;
if (swidget->id == snd_soc_dapm_scheduler) {
int i;

for_each_set_bit(i, &spipe->core_mask, sdev->num_cores) {
ret = snd_sof_dsp_core_put(sdev, i);
if (ret < 0) {
dev_err(sdev->dev, "failed to disable target core: %d for pipeline %s\n",
i, swidget->widget->name);
if (!err)
err = ret;
}
}
swidget->spipe->complete = 0;
}

/*
Expand All @@ -108,10 +116,6 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev,
err = ret;
}

/* clear pipeline complete */
if (swidget->id == snd_soc_dapm_scheduler)
swidget->spipe->complete = 0;

if (!err)
dev_dbg(sdev->dev, "widget %s freed\n", swidget->widget->name);

Expand All @@ -134,8 +138,10 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev,
struct snd_sof_widget *swidget)
{
const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
struct snd_sof_pipeline *spipe = swidget->spipe;
bool use_count_decremented = false;
int ret;
int i;

/* skip if there is no private data */
if (!swidget->private)
Expand Down Expand Up @@ -166,19 +172,23 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev,
goto use_count_dec;
}

/* enable widget core */
ret = snd_sof_dsp_core_get(sdev, swidget->core);
if (ret < 0) {
dev_err(sdev->dev, "error: failed to enable target core for widget %s\n",
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) {
ret = snd_sof_dsp_core_get(sdev, i);
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;
}
}
}

/* setup widget in the DSP */
if (tplg_ops && tplg_ops->widget_setup) {
ret = tplg_ops->widget_setup(sdev, swidget);
if (ret < 0)
goto core_put;
goto pipe_widget_free;
}

/* send config for DAI components */
Expand Down Expand Up @@ -208,15 +218,22 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev,
return 0;

widget_free:
/* widget use_count and core ref_count will both be decremented by sof_widget_free() */
/* 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)
if (swidget->id != snd_soc_dapm_scheduler) {
sof_widget_free_unlocked(sdev, swidget->spipe->pipe_widget);
} else {
int j;

/* decrement ref count for all cores that were updated previously */
for_each_set_bit(j, &spipe->core_mask, sdev->num_cores) {
if (j >= i)
break;
snd_sof_dsp_core_put(sdev, j);
}
}
use_count_dec:
if (!use_count_decremented)
swidget->use_count--;
Expand Down

0 comments on commit 31ed8da

Please sign in to comment.