diff options
author | Takashi Iwai <tiwai@suse.de> | 2017-07-06 12:34:40 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2017-07-07 15:34:57 +0200 |
commit | 20e2b791796bd68816fa115f12be5320de2b8021 (patch) | |
tree | 3380b79080ccb2942cd976ddb16f54728e6b1b0f /sound/isa/msnd/msnd_pinnacle.c | |
parent | ALSA: hda/realtek - change the location for one of two front microphones (diff) | |
download | linux-20e2b791796bd68816fa115f12be5320de2b8021.tar.xz linux-20e2b791796bd68816fa115f12be5320de2b8021.zip |
ALSA: msnd: Optimize / harden DSP and MIDI loops
The ISA msnd drivers have loops fetching the ring-buffer head, tail
and size values inside the loops. Such codes are inefficient and
fragile.
This patch optimizes it, and also adds the sanity check to avoid the
endless loops.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=196131
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=196133
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to '')
-rw-r--r-- | sound/isa/msnd/msnd_pinnacle.c | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index ad4897337df5..fc4fb1904aef 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -170,23 +170,24 @@ static irqreturn_t snd_msnd_interrupt(int irq, void *dev_id) { struct snd_msnd *chip = dev_id; void *pwDSPQData = chip->mappedbase + DSPQ_DATA_BUFF; + u16 head, tail, size; /* Send ack to DSP */ /* inb(chip->io + HP_RXL); */ /* Evaluate queued DSP messages */ - while (readw(chip->DSPQ + JQS_wTail) != readw(chip->DSPQ + JQS_wHead)) { - u16 wTmp; - - snd_msnd_eval_dsp_msg(chip, - readw(pwDSPQData + 2 * readw(chip->DSPQ + JQS_wHead))); - - wTmp = readw(chip->DSPQ + JQS_wHead) + 1; - if (wTmp > readw(chip->DSPQ + JQS_wSize)) - writew(0, chip->DSPQ + JQS_wHead); - else - writew(wTmp, chip->DSPQ + JQS_wHead); + head = readw(chip->DSPQ + JQS_wHead); + tail = readw(chip->DSPQ + JQS_wTail); + size = readw(chip->DSPQ + JQS_wSize); + if (head > size || tail > size) + goto out; + while (head != tail) { + snd_msnd_eval_dsp_msg(chip, readw(pwDSPQData + 2 * head)); + if (++head > size) + head = 0; + writew(head, chip->DSPQ + JQS_wHead); } + out: /* Send ack to DSP */ inb(chip->io + HP_RXL); return IRQ_HANDLED; |