diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2010-05-25 09:03:40 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-05-25 20:23:15 +0200 |
commit | 9ef04066b3e7c51ed7edc6010ac039f18f9f3617 (patch) | |
tree | 7581d83c1f06f56f47f461e85ef181e3d3878921 /sound/pci/hda/hda_intel.c | |
parent | 66668b6fb6861fad7f6bfef6646ac84693474c9a (diff) |
ALSA: hda_intel: fix handling of non-completion stream interrupts
Check that the interrupt raised for a stream is actually a buffer
completion interrupt before handling it as one. Otherwise, memory
errors or FIFO xruns would be interpreted as a pointer update and could
break the stream timing.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_intel.c')
-rw-r--r-- | sound/pci/hda/hda_intel.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 14d895bcf3fe..77e22c2a8caa 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1097,6 +1097,7 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) struct azx *chip = dev_id; struct azx_dev *azx_dev; u32 status; + u8 sd_status; int i, ok; spin_lock(&chip->reg_lock); @@ -1110,8 +1111,10 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) for (i = 0; i < chip->num_streams; i++) { azx_dev = &chip->azx_dev[i]; 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) + if (!azx_dev->substream || !azx_dev->running || + !(sd_status & SD_INT_COMPLETE)) continue; /* check whether this IRQ is really acceptable */ ok = azx_position_ok(chip, azx_dev); |