Skip to content

Commit

Permalink
ASoC: SOF: ipc3-topology: Fix pipeline tear down logic
Browse files Browse the repository at this point in the history
[ Upstream commit d7332c4 ]

With the change in the widget free logic to power down the cores only
when the scheduler widgets are freed, we need to ensure that the
scheduler widget is freed only after all the widgets associated with the
scheduler are freed. This is to ensure that the secondary core that the
scheduler is scheduled to run on is kept powered on until all widgets
that need them are in use. While this works well for dynamic pipelines,
in the case of static pipelines the current logic does not take this into
account and frees all widgets in the order they occur in the
widget_list. So, modify this to ensure that the scheduler widgets are freed
only after all other types of widgets in the widget_list are freed.

Link: thesofproject/linux#4807
Fixes: 31ed8da ("ASoC: SOF: sof-audio: Modify logic for enabling/disabling topology cores")
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/20240208133432.1688-1-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
ranj063 authored and Sasha Levin committed Feb 20, 2024
1 parent 06f90eb commit bbbfcb9
Showing 1 changed file with 41 additions and 14 deletions.
55 changes: 41 additions & 14 deletions sound/soc/sof/ipc3-topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -2309,27 +2309,16 @@ static int sof_tear_down_left_over_pipelines(struct snd_sof_dev *sdev)
return 0;
}

/*
* For older firmware, this function doesn't free widgets for static pipelines during suspend.
* It only resets use_count for all widgets.
*/
static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verify)
static int sof_ipc3_free_widgets_in_list(struct snd_sof_dev *sdev, bool include_scheduler,
bool *dyn_widgets, bool verify)
{
struct sof_ipc_fw_version *v = &sdev->fw_ready.version;
struct snd_sof_widget *swidget;
struct snd_sof_route *sroute;
bool dyn_widgets = false;
int ret;

/*
* This function is called during suspend and for one-time topology verification during
* first boot. In both cases, there is no need to protect swidget->use_count and
* sroute->setup because during suspend all running streams are suspended and during
* topology loading the sound card unavailable to open PCMs.
*/
list_for_each_entry(swidget, &sdev->widget_list, list) {
if (swidget->dynamic_pipeline_widget) {
dyn_widgets = true;
*dyn_widgets = true;
continue;
}

Expand All @@ -2344,11 +2333,49 @@ static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verif
continue;
}

if (include_scheduler && swidget->id != snd_soc_dapm_scheduler)
continue;

if (!include_scheduler && swidget->id == snd_soc_dapm_scheduler)
continue;

ret = sof_widget_free(sdev, swidget);
if (ret < 0)
return ret;
}

return 0;
}

/*
* For older firmware, this function doesn't free widgets for static pipelines during suspend.
* It only resets use_count for all widgets.
*/
static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verify)
{
struct sof_ipc_fw_version *v = &sdev->fw_ready.version;
struct snd_sof_widget *swidget;
struct snd_sof_route *sroute;
bool dyn_widgets = false;
int ret;

/*
* This function is called during suspend and for one-time topology verification during
* first boot. In both cases, there is no need to protect swidget->use_count and
* sroute->setup because during suspend all running streams are suspended and during
* topology loading the sound card unavailable to open PCMs. Do not free the scheduler
* widgets yet so that the secondary cores do not get powered down before all the widgets
* associated with the scheduler are freed.
*/
ret = sof_ipc3_free_widgets_in_list(sdev, false, &dyn_widgets, verify);
if (ret < 0)
return ret;

/* free all the scheduler widgets now */
ret = sof_ipc3_free_widgets_in_list(sdev, true, &dyn_widgets, verify);
if (ret < 0)
return ret;

/*
* Tear down all pipelines associated with PCMs that did not get suspended
* and unset the prepare flag so that they can be set up again during resume.
Expand Down

0 comments on commit bbbfcb9

Please sign in to comment.