Skip to content

Commit e63a9a1

Browse files
committed
ASoC: SOF: Intel: hda: reset dma_sata during suspend
When the stream is cleared during the suspend trigger, the dma_data must be set to NULL and snd_hdac_ext_stream_release() must be called to release the link dev. Without this, some platforms run into issues with triggering the host DMA during system resume. Add the missing sequences to both hda_link_pcm_trigger() to handle all streams that get suspended and to hda_dsp_set_hw_params_upon_resume() to handle paused streams that are reset during system suspend. Also, because the dma_data is set to NULL during suspend, add the checks to ensure link_dev is not NULL during hw_params and hw_free to prevent NULL pointer dereferences. BugLink: thesofproject/sof#4779 Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
1 parent 78a8ed4 commit e63a9a1

File tree

2 files changed

+18
-9
lines changed

2 files changed

+18
-9
lines changed

sound/soc/sof/intel/hda-dai.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ static int hda_link_pcm_prepare(struct snd_pcm_substream *substream,
279279
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
280280
int stream = substream->stream;
281281

282-
if (link_dev->link_prepared)
282+
if (link_dev && link_dev->link_prepared)
283283
return 0;
284284

285285
dev_dbg(sdev->dev, "hda: prepare stream dir %d\n", substream->stream);
@@ -306,6 +306,10 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream,
306306
bus = hstream->bus;
307307
rtd = asoc_substream_to_rtd(substream);
308308

309+
/* when paused streams are never released after system resume, link_dev would be NULL. */
310+
if (!link_dev)
311+
return 0;
312+
309313
link = snd_hdac_ext_bus_get_link(bus, asoc_rtd_to_codec(rtd, 0)->component->name);
310314
if (!link)
311315
return -EINVAL;
@@ -347,7 +351,10 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream,
347351
snd_hdac_ext_link_clear_stream_id(link, stream_tag);
348352
}
349353

354+
snd_soc_dai_set_dma_data(dai, substream, NULL);
355+
snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK);
350356
link_dev->link_prepared = 0;
357+
hda_stream->host_reserved = 0;
351358

352359
fallthrough;
353360
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -377,11 +384,8 @@ static int hda_link_hw_free(struct snd_pcm_substream *substream,
377384
rtd = asoc_substream_to_rtd(substream);
378385
link_dev = snd_soc_dai_get_dma_data(dai, substream);
379386

380-
if (!link_dev) {
381-
dev_dbg(dai->dev,
382-
"%s: link_dev is not assigned\n", __func__);
383-
return -EINVAL;
384-
}
387+
if (!link_dev)
388+
return 0;
385389

386390
hda_stream = hstream_to_sof_hda_stream(link_dev);
387391

sound/soc/sof/intel/hda-dsp.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -922,16 +922,21 @@ int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev)
922922
* explicitly during suspend.
923923
*/
924924
if (stream->link_substream) {
925+
struct snd_soc_dai *cpu_dai;
926+
925927
rtd = asoc_substream_to_rtd(stream->link_substream);
928+
cpu_dai = asoc_rtd_to_cpu(rtd, 0);
926929
name = asoc_rtd_to_codec(rtd, 0)->component->name;
927930
link = snd_hdac_ext_bus_get_link(bus, name);
928931
if (!link)
929932
return -EINVAL;
930933

931-
stream->link_prepared = 0;
934+
snd_soc_dai_set_dma_data(cpu_dai, stream->link_substream, NULL);
935+
snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK);
936+
link_dev->link_prepared = 0;
937+
hda_stream->host_reserved = 0;
932938

933-
if (hdac_stream(stream)->direction ==
934-
SNDRV_PCM_STREAM_CAPTURE)
939+
if (hdac_stream(stream)->direction == SNDRV_PCM_STREAM_CAPTURE)
935940
continue;
936941

937942
stream_tag = hdac_stream(stream)->stream_tag;

0 commit comments

Comments
 (0)