Skip to content

Commit 5568147

Browse files
tiwaigregkh
authored andcommitted
ALSA: msnd: Optimize / harden DSP and MIDI loops
commit 20e2b791796bd68816fa115f12be5320de2b8021 upstream. 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> Signed-off-by: grygorii tertychnyi <gtertych@cisco.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 1086360 commit 5568147

2 files changed

Lines changed: 27 additions & 26 deletions

File tree

sound/isa/msnd/msnd_midi.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -120,24 +120,24 @@ void snd_msndmidi_input_read(void *mpuv)
120120
unsigned long flags;
121121
struct snd_msndmidi *mpu = mpuv;
122122
void *pwMIDQData = mpu->dev->mappedbase + MIDQ_DATA_BUFF;
123+
u16 head, tail, size;
123124

124125
spin_lock_irqsave(&mpu->input_lock, flags);
125-
while (readw(mpu->dev->MIDQ + JQS_wTail) !=
126-
readw(mpu->dev->MIDQ + JQS_wHead)) {
127-
u16 wTmp, val;
128-
val = readw(pwMIDQData + 2 * readw(mpu->dev->MIDQ + JQS_wHead));
129-
130-
if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER,
131-
&mpu->mode))
132-
snd_rawmidi_receive(mpu->substream_input,
133-
(unsigned char *)&val, 1);
134-
135-
wTmp = readw(mpu->dev->MIDQ + JQS_wHead) + 1;
136-
if (wTmp > readw(mpu->dev->MIDQ + JQS_wSize))
137-
writew(0, mpu->dev->MIDQ + JQS_wHead);
138-
else
139-
writew(wTmp, mpu->dev->MIDQ + JQS_wHead);
126+
head = readw(mpu->dev->MIDQ + JQS_wHead);
127+
tail = readw(mpu->dev->MIDQ + JQS_wTail);
128+
size = readw(mpu->dev->MIDQ + JQS_wSize);
129+
if (head > size || tail > size)
130+
goto out;
131+
while (head != tail) {
132+
unsigned char val = readw(pwMIDQData + 2 * head);
133+
134+
if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, &mpu->mode))
135+
snd_rawmidi_receive(mpu->substream_input, &val, 1);
136+
if (++head > size)
137+
head = 0;
138+
writew(head, mpu->dev->MIDQ + JQS_wHead);
140139
}
140+
out:
141141
spin_unlock_irqrestore(&mpu->input_lock, flags);
142142
}
143143
EXPORT_SYMBOL(snd_msndmidi_input_read);

sound/isa/msnd/msnd_pinnacle.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -170,23 +170,24 @@ static irqreturn_t snd_msnd_interrupt(int irq, void *dev_id)
170170
{
171171
struct snd_msnd *chip = dev_id;
172172
void *pwDSPQData = chip->mappedbase + DSPQ_DATA_BUFF;
173+
u16 head, tail, size;
173174

174175
/* Send ack to DSP */
175176
/* inb(chip->io + HP_RXL); */
176177

177178
/* Evaluate queued DSP messages */
178-
while (readw(chip->DSPQ + JQS_wTail) != readw(chip->DSPQ + JQS_wHead)) {
179-
u16 wTmp;
180-
181-
snd_msnd_eval_dsp_msg(chip,
182-
readw(pwDSPQData + 2 * readw(chip->DSPQ + JQS_wHead)));
183-
184-
wTmp = readw(chip->DSPQ + JQS_wHead) + 1;
185-
if (wTmp > readw(chip->DSPQ + JQS_wSize))
186-
writew(0, chip->DSPQ + JQS_wHead);
187-
else
188-
writew(wTmp, chip->DSPQ + JQS_wHead);
179+
head = readw(chip->DSPQ + JQS_wHead);
180+
tail = readw(chip->DSPQ + JQS_wTail);
181+
size = readw(chip->DSPQ + JQS_wSize);
182+
if (head > size || tail > size)
183+
goto out;
184+
while (head != tail) {
185+
snd_msnd_eval_dsp_msg(chip, readw(pwDSPQData + 2 * head));
186+
if (++head > size)
187+
head = 0;
188+
writew(head, chip->DSPQ + JQS_wHead);
189189
}
190+
out:
190191
/* Send ack to DSP */
191192
inb(chip->io + HP_RXL);
192193
return IRQ_HANDLED;

0 commit comments

Comments
 (0)