All of lore.kernel.org
 help / color / mirror / Atom feed
* Handling HDA FIFO error
@ 2013-05-14 17:00 Daniel Drake
  2013-05-15  9:08 ` Clemens Ladisch
  0 siblings, 1 reply; 4+ messages in thread
From: Daniel Drake @ 2013-05-14 17:00 UTC (permalink / raw)
  To: alsa-devel

Hi,

On the OLPC XO-1.5 (VIA VX855 SoC with HDA) we sometimes see a problem
where audio playback fails. Easy to reproduce by playing a short wav
file in a loop, it will fail after a minute or two.

The playback app gets confused here: snd_pcm_wait() returns success,
but snd_pcm_writei() returns EAGAIN.

Digging into the HDA code, I can see that normally, when the stream
gets started, we get interrupts with SD_STS as 0x24. In the failure
case, as soon as we start the stream, we get a flood of interrupts
with SD_STS 0x8 - which indicates FIFO error.

Disabling interrupt generation upon FIFO error does not help much - it
avoids the flood of interrupts, but doesn't change the fact that audio
playing apps hang or loop infinitely.

I have tried the various position_fix options with no luck.

Are there any things I could check that would explain why a FIFO error
might be occurring? After a quick read of the HDA spec I don't really
understand what this FIFO actually is and what it does, how does it
relate to the BDL, CORB and RIRB?

Failing that... any suggestions for how to improve the hda_intel
driver to handle FIFO error gracefully? Right now there is no code to
handle that.

Thanks
Daniel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Handling HDA FIFO error
  2013-05-14 17:00 Handling HDA FIFO error Daniel Drake
@ 2013-05-15  9:08 ` Clemens Ladisch
  2013-05-15 10:08   ` Takashi Iwai
  0 siblings, 1 reply; 4+ messages in thread
From: Clemens Ladisch @ 2013-05-15  9:08 UTC (permalink / raw)
  To: Daniel Drake; +Cc: alsa-devel

Daniel Drake wrote:
> Digging into the HDA code, I can see that normally, when the stream
> gets started, we get interrupts with SD_STS as 0x24. In the failure
> case, as soon as we start the stream, we get a flood of interrupts
> with SD_STS 0x8 - which indicates FIFO error.
>
> Disabling interrupt generation upon FIFO error does not help much - it
> avoids the flood of interrupts, but doesn't change the fact that audio
> playing apps hang or loop infinitely.
>
> Are there any things I could check that would explain why a FIFO error
> might be occurring?

Probably a buffer underrun, i.e., the controller did not manage to
read samples from memory fast enough.

> any suggestions for how to improve the hda_intel driver to handle
> FIFO error gracefully? Right now there is no code to handle that.

It should stop the stream, i.e., go into the xrun state.

In theory, the application restarting the stream should reset the DMA
engine enough to make it work again.  But you say this happens also
when starting the stream, so I guess more resetting is needed.


Regards,
Clemens

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Handling HDA FIFO error
  2013-05-15  9:08 ` Clemens Ladisch
@ 2013-05-15 10:08   ` Takashi Iwai
  2013-05-25 14:08     ` Daniel Drake
  0 siblings, 1 reply; 4+ messages in thread
From: Takashi Iwai @ 2013-05-15 10:08 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: alsa-devel, Daniel Drake

At Wed, 15 May 2013 11:08:55 +0200,
Clemens Ladisch wrote:
> 
> Daniel Drake wrote:
> > Digging into the HDA code, I can see that normally, when the stream
> > gets started, we get interrupts with SD_STS as 0x24. In the failure
> > case, as soon as we start the stream, we get a flood of interrupts
> > with SD_STS 0x8 - which indicates FIFO error.
> >
> > Disabling interrupt generation upon FIFO error does not help much - it
> > avoids the flood of interrupts, but doesn't change the fact that audio
> > playing apps hang or loop infinitely.
> >
> > Are there any things I could check that would explain why a FIFO error
> > might be occurring?
> 
> Probably a buffer underrun, i.e., the controller did not manage to
> read samples from memory fast enough.
> 
> > any suggestions for how to improve the hda_intel driver to handle
> > FIFO error gracefully? Right now there is no code to handle that.
> 
> It should stop the stream, i.e., go into the xrun state.
> 
> In theory, the application restarting the stream should reset the DMA
> engine enough to make it work again.  But you say this happens also
> when starting the stream, so I guess more resetting is needed.

Or possibly the coherency issue.  Try to disable snoop option.


Takashi

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Handling HDA FIFO error
  2013-05-15 10:08   ` Takashi Iwai
@ 2013-05-25 14:08     ` Daniel Drake
  0 siblings, 0 replies; 4+ messages in thread
From: Daniel Drake @ 2013-05-25 14:08 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Clemens Ladisch

[-- Attachment #1: Type: text/plain, Size: 1875 bytes --]

On Wed, May 15, 2013 at 4:08 AM, Takashi Iwai <tiwai@suse.de> wrote:
> At Wed, 15 May 2013 11:08:55 +0200,
> Clemens Ladisch wrote:
>> Daniel Drake wrote:
>> > Digging into the HDA code, I can see that normally, when the stream
>> > gets started, we get interrupts with SD_STS as 0x24. In the failure
>> > case, as soon as we start the stream, we get a flood of interrupts
>> > with SD_STS 0x8 - which indicates FIFO error.
>> >
>> > Disabling interrupt generation upon FIFO error does not help much - it
>> > avoids the flood of interrupts, but doesn't change the fact that audio
>> > playing apps hang or loop infinitely.
>> >
>> > Are there any things I could check that would explain why a FIFO error
>> > might be occurring?
>>
>> Probably a buffer underrun, i.e., the controller did not manage to
>> read samples from memory fast enough.

That would seem logical, but I don't think this can be happening here.
In this case the audio buffer is filled up with data before playback
is started, and it only auto-starts right at the point when the buffer
becomes full. Then immediately, the first interrupt that comes in says
"FIFO error". The buffer was full at this point.

However I was unable to reproduce this FIFO error interrupt when
revisiting the problem. Every time I go back to it with my test case
of calling gst-launch in a loop, a different audio-related problem
seems to pop up.

Digging further, I found some oddness with the device being powered up
and down at the wrong times. I'm on Linux-3.3 here, so I threw in a
load of the newer commits that fix the CONFIG_SND_HDA_POWER_SAVE
functionality and now things seem to be working perfectly. Sorry for
the noise and thanks for already having fixed this :)

Here is a patch anyway which could be used to handle the FIFO error
interrupt. It hasn't reappeared so I haven't been able to test it.

Thanks,
Daniel

[-- Attachment #2: 0001-ALSA-HDA-handle-FIFO-errors.txt --]
[-- Type: text/plain, Size: 1663 bytes --]

From ba057abe909df7e2b9fba57e0db989e7ea47951b Mon Sep 17 00:00:00 2001
From: Daniel Drake <dsd@laptop.org>
Date: Tue, 21 May 2013 13:02:39 -0600
Subject: [PATCH] ALSA: HDA: handle FIFO errors

The HDA code was listening for the FIFO error interrupt but not handling
it. Such condition would tend to indicate an xrun.

On OLPC XO-1.75 (VIA VX855) this interrupt seems to be erroneously raised
on occasion, resulting in a halt of sound playback and the application
hanging as no sound buffer space becomes available.

Signed-off-by: Daniel Drake <dsd@laptop.org>
---
 sound/pci/hda/hda_intel.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index de65fa8..c3ef376 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1237,8 +1237,20 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
 		if (status & azx_dev->sd_int_sta_mask) {
 			sd_status = azx_sd_readb(azx_dev, SD_STS);
 			azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
-			if (!azx_dev->substream || !azx_dev->running ||
-			    !(sd_status & SD_INT_COMPLETE))
+			if (!azx_dev->substream || !azx_dev->running)
+				continue;
+
+			if (sd_status & SD_INT_FIFO_ERR) {
+				snd_pcm_stream_lock(azx_dev->substream);
+				spin_unlock(&chip->reg_lock);
+				snd_pcm_stop(azx_dev->substream,
+					     SNDRV_PCM_STATE_XRUN);
+				spin_lock(&chip->reg_lock);
+				snd_pcm_stream_unlock(azx_dev->substream);
+				continue;
+			}
+
+			if (!(sd_status & SD_INT_COMPLETE))
 				continue;
 			/* check whether this IRQ is really acceptable */
 			ok = azx_position_ok(chip, azx_dev);
-- 
1.8.1.4


[-- Attachment #3: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-05-25 14:08 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-05-14 17:00 Handling HDA FIFO error Daniel Drake
2013-05-15  9:08 ` Clemens Ladisch
2013-05-15 10:08   ` Takashi Iwai
2013-05-25 14:08     ` Daniel Drake

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.