Commit 8e84b6a4 authored by Ranjani Sridharan's avatar Ranjani Sridharan Committed by Mark Brown

ASoC: SOF: remove incorrect clearing of prepared flag

When the system is suspended while a PCM is paused, it doesn't receive
the SUSPEND trigger. So, the SOF driver has to ensure that the PCM and
the widgets associated with the paused PCM are freed in the firmware
during suspend. This is handled in the
sof_tear_down_left_over_pipelines() call. But since the state of this
PCM is SUSPENDED, we end up clearing the prepared flag for the PCM
before freeing it. This results in IPC errors while freeing the widgets.
But because the widget use_counts are reset to 0 even though the IPC
fails, releasing the paused stream after resuming from suspend proceeds
normally.

Fix the IPC errors by removing the clearing of the prepared flag in
sof_set_hw_params_upon_resume(). In fact, we can remove the
sof_set_hw_params_upon_resume() and call
snd_sof_dsp_hw_params_upon_resume() directly. This will ensure that the
PCM is freed in the firmware before the IPC's for freeing the widgets
are sent.

BugLink: https://github.com/thesofproject/linux/issues/3543Reviewed-by: default avatarBard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: default avatarPéter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20220421203201.1550328-2-pierre-louis.bossart@linux.intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 57ebd5d5
...@@ -194,7 +194,7 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) ...@@ -194,7 +194,7 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
/* prepare for streams to be resumed properly upon resume */ /* prepare for streams to be resumed properly upon resume */
if (!runtime_suspend) { if (!runtime_suspend) {
ret = sof_set_hw_params_upon_resume(sdev->dev); ret = snd_sof_dsp_hw_params_upon_resume(sdev);
if (ret < 0) { if (ret < 0) {
dev_err(sdev->dev, dev_err(sdev->dev,
"error: setting hw_params flag during suspend %d\n", "error: setting hw_params flag during suspend %d\n",
......
...@@ -413,42 +413,6 @@ bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev) ...@@ -413,42 +413,6 @@ bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev)
return false; return false;
} }
int sof_set_hw_params_upon_resume(struct device *dev)
{
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
struct snd_pcm_substream *substream;
struct snd_sof_pcm *spcm;
snd_pcm_state_t state;
int dir;
/*
* SOF requires hw_params to be set-up internally upon resume.
* So, set the flag to indicate this for those streams that
* have been suspended.
*/
list_for_each_entry(spcm, &sdev->pcm_list, list) {
for_each_pcm_streams(dir) {
/*
* do not reset hw_params upon resume for streams that
* were kept running during suspend
*/
if (spcm->stream[dir].suspend_ignored)
continue;
substream = spcm->stream[dir].substream;
if (!substream || !substream->runtime)
continue;
state = substream->runtime->status->state;
if (state == SNDRV_PCM_STATE_SUSPENDED)
spcm->prepared[dir] = false;
}
}
/* set internal flag for BE */
return snd_sof_dsp_hw_params_upon_resume(sdev);
}
int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream,
struct snd_sof_pcm *spcm, int dir, bool free_widget_list) struct snd_sof_pcm *spcm, int dir, bool free_widget_list)
{ {
......
...@@ -434,7 +434,6 @@ static inline void snd_sof_compr_init_elapsed_work(struct work_struct *work) { } ...@@ -434,7 +434,6 @@ static inline void snd_sof_compr_init_elapsed_work(struct work_struct *work) { }
int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params); int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params);
/* PM */ /* PM */
int sof_set_hw_params_upon_resume(struct device *dev);
bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev); bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev);
bool snd_sof_dsp_only_d0i3_compatible_stream_active(struct snd_sof_dev *sdev); bool snd_sof_dsp_only_d0i3_compatible_stream_active(struct snd_sof_dev *sdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment