Skip to content

Commit 1805a6d

Browse files
committed
ASoC: SOF: Extend the enabled DSP core handling
Merge series from Peter Ujfalusi <peter.ujfalusi@linux.intel.com>: 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.
2 parents fba2934 + 31ed8da commit 1805a6d

4 files changed

Lines changed: 54 additions & 24 deletions

File tree

sound/soc/sof/ipc3-topology.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,7 @@ static int sof_ipc3_widget_setup_comp_mixer(struct snd_sof_widget *swidget)
493493
static int sof_ipc3_widget_setup_comp_pipeline(struct snd_sof_widget *swidget)
494494
{
495495
struct snd_soc_component *scomp = swidget->scomp;
496+
struct snd_sof_pipeline *spipe = swidget->spipe;
496497
struct sof_ipc_pipe_new *pipeline;
497498
struct snd_sof_widget *comp_swidget;
498499
int ret;
@@ -545,6 +546,7 @@ static int sof_ipc3_widget_setup_comp_pipeline(struct snd_sof_widget *swidget)
545546
swidget->dynamic_pipeline_widget);
546547

547548
swidget->core = pipeline->core;
549+
spipe->core_mask |= BIT(pipeline->core);
548550

549551
return 0;
550552

sound/soc/sof/ipc4-topology.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,7 @@ static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget)
656656
{
657657
struct snd_soc_component *scomp = swidget->scomp;
658658
struct sof_ipc4_pipeline *pipeline;
659+
struct snd_sof_pipeline *spipe = swidget->spipe;
659660
int ret;
660661

661662
pipeline = kzalloc(sizeof(*pipeline), GFP_KERNEL);
@@ -670,6 +671,7 @@ static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget)
670671
}
671672

672673
swidget->core = pipeline->core_id;
674+
spipe->core_mask |= BIT(pipeline->core_id);
673675

674676
if (pipeline->use_chain_dma) {
675677
dev_dbg(scomp->dev, "Set up chain DMA for %s\n", swidget->widget->name);
@@ -797,6 +799,7 @@ static int sof_ipc4_widget_setup_comp_mixer(struct snd_sof_widget *swidget)
797799
static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget)
798800
{
799801
struct snd_soc_component *scomp = swidget->scomp;
802+
struct snd_sof_pipeline *spipe = swidget->spipe;
800803
struct sof_ipc4_src *src;
801804
int ret;
802805

@@ -819,6 +822,8 @@ static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget)
819822
goto err;
820823
}
821824

825+
spipe->core_mask |= BIT(swidget->core);
826+
822827
dev_dbg(scomp->dev, "SRC sink rate %d\n", src->sink_rate);
823828

824829
ret = sof_ipc4_widget_setup_msg(swidget, &src->msg);
@@ -864,6 +869,7 @@ static int sof_ipc4_widget_setup_comp_process(struct snd_sof_widget *swidget)
864869
{
865870
struct snd_soc_component *scomp = swidget->scomp;
866871
struct sof_ipc4_fw_module *fw_module;
872+
struct snd_sof_pipeline *spipe = swidget->spipe;
867873
struct sof_ipc4_process *process;
868874
void *cfg;
869875
int ret;
@@ -920,6 +926,9 @@ static int sof_ipc4_widget_setup_comp_process(struct snd_sof_widget *swidget)
920926

921927
sof_ipc4_widget_update_kcontrol_module_id(swidget);
922928

929+
/* set pipeline core mask to keep track of the core the module is scheduled to run on */
930+
spipe->core_mask |= BIT(swidget->core);
931+
923932
return 0;
924933
free_base_cfg_ext:
925934
kfree(process->base_config_ext);

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--;

sound/soc/sof/sof-audio.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,13 +480,15 @@ struct snd_sof_widget {
480480
* @paused_count: Count of number of PCM's that have started and have currently paused this
481481
pipeline
482482
* @complete: flag used to indicate that pipeline set up is complete.
483+
* @core_mask: Mask containing target cores for all modules in the pipeline
483484
* @list: List item in sdev pipeline_list
484485
*/
485486
struct snd_sof_pipeline {
486487
struct snd_sof_widget *pipe_widget;
487488
int started_count;
488489
int paused_count;
489490
int complete;
491+
unsigned long core_mask;
490492
struct list_head list;
491493
};
492494

0 commit comments

Comments
 (0)