Skip to content

Commit 31ed8da

Browse files
ranj063broonie
authored andcommitted
ASoC: SOF: sof-audio: Modify logic for enabling/disabling topology cores
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>
1 parent 0376b99 commit 31ed8da

1 file changed

Lines changed: 41 additions & 24 deletions

File tree

sound/soc/sof/sof-audio.c

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev,
4646
struct snd_sof_widget *swidget)
4747
{
4848
const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
49+
struct snd_sof_pipeline *spipe = swidget->spipe;
4950
struct snd_sof_widget *pipe_widget;
5051
int err = 0;
5152
int ret;
@@ -87,15 +88,22 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev,
8788
}
8889

8990
/*
90-
* disable widget core. continue to route setup status and complete flag
91-
* even if this fails and return the appropriate error
91+
* decrement ref count for cores associated with all modules in the pipeline and clear
92+
* the complete flag
9293
*/
93-
ret = snd_sof_dsp_core_put(sdev, swidget->core);
94-
if (ret < 0) {
95-
dev_err(sdev->dev, "error: failed to disable target core: %d for widget %s\n",
96-
swidget->core, swidget->widget->name);
97-
if (!err)
98-
err = ret;
94+
if (swidget->id == snd_soc_dapm_scheduler) {
95+
int i;
96+
97+
for_each_set_bit(i, &spipe->core_mask, sdev->num_cores) {
98+
ret = snd_sof_dsp_core_put(sdev, i);
99+
if (ret < 0) {
100+
dev_err(sdev->dev, "failed to disable target core: %d for pipeline %s\n",
101+
i, swidget->widget->name);
102+
if (!err)
103+
err = ret;
104+
}
105+
}
106+
swidget->spipe->complete = 0;
99107
}
100108

101109
/*
@@ -108,10 +116,6 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev,
108116
err = ret;
109117
}
110118

111-
/* clear pipeline complete */
112-
if (swidget->id == snd_soc_dapm_scheduler)
113-
swidget->spipe->complete = 0;
114-
115119
if (!err)
116120
dev_dbg(sdev->dev, "widget %s freed\n", swidget->widget->name);
117121

@@ -134,8 +138,10 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev,
134138
struct snd_sof_widget *swidget)
135139
{
136140
const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
141+
struct snd_sof_pipeline *spipe = swidget->spipe;
137142
bool use_count_decremented = false;
138143
int ret;
144+
int i;
139145

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

169-
/* enable widget core */
170-
ret = snd_sof_dsp_core_get(sdev, swidget->core);
171-
if (ret < 0) {
172-
dev_err(sdev->dev, "error: failed to enable target core for widget %s\n",
173-
swidget->widget->name);
174-
goto pipe_widget_free;
175+
/* update ref count for cores associated with all modules in the pipeline */
176+
if (swidget->id == snd_soc_dapm_scheduler) {
177+
for_each_set_bit(i, &spipe->core_mask, sdev->num_cores) {
178+
ret = snd_sof_dsp_core_get(sdev, i);
179+
if (ret < 0) {
180+
dev_err(sdev->dev, "failed to enable target core %d for pipeline %s\n",
181+
i, swidget->widget->name);
182+
goto pipe_widget_free;
183+
}
184+
}
175185
}
176186

177187
/* setup widget in the DSP */
178188
if (tplg_ops && tplg_ops->widget_setup) {
179189
ret = tplg_ops->widget_setup(sdev, swidget);
180190
if (ret < 0)
181-
goto core_put;
191+
goto pipe_widget_free;
182192
}
183193

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

210220
widget_free:
211-
/* widget use_count and core ref_count will both be decremented by sof_widget_free() */
221+
/* widget use_count will be decremented by sof_widget_free() */
212222
sof_widget_free_unlocked(sdev, swidget);
213223
use_count_decremented = true;
214-
core_put:
215-
if (!use_count_decremented)
216-
snd_sof_dsp_core_put(sdev, swidget->core);
217224
pipe_widget_free:
218-
if (swidget->id != snd_soc_dapm_scheduler)
225+
if (swidget->id != snd_soc_dapm_scheduler) {
219226
sof_widget_free_unlocked(sdev, swidget->spipe->pipe_widget);
227+
} else {
228+
int j;
229+
230+
/* decrement ref count for all cores that were updated previously */
231+
for_each_set_bit(j, &spipe->core_mask, sdev->num_cores) {
232+
if (j >= i)
233+
break;
234+
snd_sof_dsp_core_put(sdev, j);
235+
}
236+
}
220237
use_count_dec:
221238
if (!use_count_decremented)
222239
swidget->use_count--;

0 commit comments

Comments
 (0)