ASoC: SOF: sof-audio: revisit sof_pcm_stream_free() error handling and logs
authorPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Tue, 2 Apr 2024 15:18:24 +0000 (10:18 -0500)
committerMark Brown <broonie@kernel.org>
Tue, 2 Apr 2024 16:14:54 +0000 (17:14 +0100)
For some reason the existing code stops on the first error, which
potentially leaves the DMA and widgets in a weird state.

Change to free-up all resources even in case of errors.

Also add a more consistent error handling and logs, with the first
error code returned to the caller.

Reviewed-by: Rander Wang <rander.wang@intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://msgid.link/r/20240402151828.175002-14-pierre-louis.bossart@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/sof-audio.c

index e693dcb475e4d6a28273d920b36b706c21df6dd9..b5ca2861edbd5d82abf1364c5bb3c1e1d28500e0 100644 (file)
@@ -834,17 +834,21 @@ int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *subs
 {
        const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
        int ret;
+       int err = 0;
 
        if (spcm->prepared[substream->stream]) {
                /* stop DMA first if needed */
                if (pcm_ops && pcm_ops->platform_stop_during_hw_free)
                        snd_sof_pcm_platform_trigger(sdev, substream, SNDRV_PCM_TRIGGER_STOP);
 
-               /* Send PCM_FREE IPC to reset pipeline */
+               /* free PCM in the DSP */
                if (pcm_ops && pcm_ops->hw_free) {
                        ret = pcm_ops->hw_free(sdev->component, substream);
-                       if (ret < 0)
-                               return ret;
+                       if (ret < 0) {
+                               dev_err(sdev->dev, "%s: pcm_ops hw_free failed %d\n",
+                                       __func__, ret);
+                               err = ret;
+                       }
                }
 
                spcm->prepared[substream->stream] = false;
@@ -852,17 +856,25 @@ int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *subs
 
        /* reset the DMA */
        ret = snd_sof_pcm_platform_hw_free(sdev, substream);
-       if (ret < 0)
-               return ret;
+       if (ret < 0) {
+               dev_err(sdev->dev, "%s: platform hw free failed %d\n",
+                       __func__, ret);
+               if (!err)
+                       err = ret;
+       }
 
        /* free widget list */
        if (free_widget_list) {
                ret = sof_widget_list_free(sdev, spcm, dir);
-               if (ret < 0)
-                       dev_err(sdev->dev, "failed to free widgets during suspend\n");
+               if (ret < 0) {
+                       dev_err(sdev->dev, "%s: sof_widget_list_free failed %d\n",
+                               __func__, ret);
+                       if (!err)
+                               err = ret;
+               }
        }
 
-       return ret;
+       return err;
 }
 
 /*