diff mbox series

[18/21] ASoC: SOF: Intel: hda: fix link DMA config

Message ID 20190722141402.7194-19-pierre-louis.bossart@linux.intel.com (mailing list archive)
State Accepted
Commit 934bf82203d679a8f2ff22817e341bc059f5f7fc
Headers show
Series ASoC: SOF: updates for 5.4 | expand

Commit Message

Pierre-Louis Bossart July 22, 2019, 2:13 p.m. UTC
From: Rander Wang <rander.wang@linux.intel.com>

For this bug, there are two capture pcm streams active, with one
stream and its related stream tag released before suspend. Later
when system suspend is done, the stream tag for the remaining
active stream is released by SOF driver. After system resume, hda
codec driver restores the stream tag for the active pcm stream,
but SOF goes to assign a new one, which now doesn't match with the
stream tag used by codec driver, and this causes DMA to fail
receiving data, leading to unrecoverable XRUN condition in FW.

For stream tag is stored in both hda codec and SOF driver, it
shouldn't be released only in SOF driver. This patch just keeps the
stream information in dma data and checks whether there is a stored
DMA data for stream resuming from S3 and restores it. And it also
removes DMA data when the stream is released.

Tested on Whiskey Lake platform.

GitHub issue: https://github.com/thesofproject/sof/issues/1594
Signed-off-by: Rander Wang <rander.wang@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 sound/soc/sof/intel/hda-dai.c | 15 +++++++++------
 sound/soc/sof/intel/hda-dsp.c | 10 ++++------
 2 files changed, 13 insertions(+), 12 deletions(-)

Comments

Mark Brown July 23, 2019, 11:15 a.m. UTC | #1
On Mon, Jul 22, 2019 at 09:13:59AM -0500, Pierre-Louis Bossart wrote:
> From: Rander Wang <rander.wang@linux.intel.com>
> 
> For this bug, there are two capture pcm streams active, with one
> stream and its related stream tag released before suspend. Later
> when system suspend is done, the stream tag for the remaining

In general fixes should come at the start of a series so that they can
be applied as such and sent to Linus without getting caught up with
dependencies on development work.
Pierre-Louis Bossart July 23, 2019, 2:37 p.m. UTC | #2
On 7/23/19 6:15 AM, Mark Brown wrote:
> On Mon, Jul 22, 2019 at 09:13:59AM -0500, Pierre-Louis Bossart wrote:
>> From: Rander Wang <rander.wang@linux.intel.com>
>>
>> For this bug, there are two capture pcm streams active, with one
>> stream and its related stream tag released before suspend. Later
>> when system suspend is done, the stream tag for the remaining
> 
> In general fixes should come at the start of a series so that they can
> be applied as such and sent to Linus without getting caught up with
> dependencies on development work.

Yes, but in this case we had two developers that changed the code and I 
couldn't really move code around too much.
You have a good point though, we should ask for the 'fix' subject to be 
used really for true fixes that should have a more direct integration 
path or go to linux-stable.
Thanks for the merges.
Mark Brown July 23, 2019, 4:30 p.m. UTC | #3
On Tue, Jul 23, 2019 at 09:37:47AM -0500, Pierre-Louis Bossart wrote:
> On 7/23/19 6:15 AM, Mark Brown wrote:

> > In general fixes should come at the start of a series so that they can
> > be applied as such and sent to Linus without getting caught up with
> > dependencies on development work.

> Yes, but in this case we had two developers that changed the code and I
> couldn't really move code around too much.

Might be worth pushing back on them to pick a better base for their
fixes (and possibly work out a way to get that stuff sent out separately
rather than stuck with a big queue of other stuff).
diff mbox series

Patch

diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c
index a448be60f6dd..2b5e2b8c69c2 100644
--- a/sound/soc/sof/intel/hda-dai.c
+++ b/sound/soc/sof/intel/hda-dai.c
@@ -210,9 +210,13 @@  static int hda_link_hw_params(struct snd_pcm_substream *substream,
 	int stream_tag;
 	int ret;
 
-	link_dev = hda_link_stream_assign(bus, substream);
-	if (!link_dev)
-		return -EBUSY;
+	/* get stored dma data if resuming from system suspend */
+	link_dev = snd_soc_dai_get_dma_data(dai, substream);
+	if (!link_dev) {
+		link_dev = hda_link_stream_assign(bus, substream);
+		if (!link_dev)
+			return -EBUSY;
+	}
 
 	stream_tag = hdac_stream(link_dev)->stream_tag;
 
@@ -316,7 +320,7 @@  static int hda_link_pcm_trigger(struct snd_pcm_substream *substream,
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_STOP:
 		/*
-		 * clear and release link DMA channel. It will be assigned when
+		 * clear link DMA channel. It will be assigned when
 		 * hw_params is set up again after resume.
 		 */
 		ret = hda_link_config_ipc(hda_stream, dai->name,
@@ -325,8 +329,6 @@  static int hda_link_pcm_trigger(struct snd_pcm_substream *substream,
 			return ret;
 		stream_tag = hdac_stream(link_dev)->stream_tag;
 		snd_hdac_ext_link_clear_stream_id(link, stream_tag);
-		snd_hdac_ext_stream_release(link_dev,
-					    HDAC_EXT_STREAM_TYPE_LINK);
 		link_dev->link_prepared = 0;
 
 		/* fallthrough */
@@ -369,6 +371,7 @@  static int hda_link_hw_free(struct snd_pcm_substream *substream,
 
 	stream_tag = hdac_stream(link_dev)->stream_tag;
 	snd_hdac_ext_link_clear_stream_id(link, stream_tag);
+	snd_soc_dai_set_dma_data(dai, substream, NULL);
 	snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK);
 	link_dev->link_prepared = 0;
 
diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c
index e82ecaad1763..e38008194574 100644
--- a/sound/soc/sof/intel/hda-dsp.c
+++ b/sound/soc/sof/intel/hda-dsp.c
@@ -439,10 +439,10 @@  int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev)
 		stream = stream_to_hdac_ext_stream(s);
 
 		/*
-		 * clear and release stream. This should already be taken care
-		 * for running streams when the SUSPEND trigger is called.
-		 * But paused streams do not get suspended, so this needs to be
-		 * done explicitly during suspend.
+		 * clear stream. This should already be taken care for running
+		 * streams when the SUSPEND trigger is called. But paused
+		 * streams do not get suspended, so this needs to be done
+		 * explicitly during suspend.
 		 */
 		if (stream->link_substream) {
 			rtd = snd_pcm_substream_chip(stream->link_substream);
@@ -452,8 +452,6 @@  int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev)
 				return -EINVAL;
 			stream_tag = hdac_stream(stream)->stream_tag;
 			snd_hdac_ext_link_clear_stream_id(link, stream_tag);
-			snd_hdac_ext_stream_release(stream,
-						    HDAC_EXT_STREAM_TYPE_LINK);
 			stream->link_prepared = 0;
 		}
 	}