Skip to content

Commit 20e2b79

Browse files
committed
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>
1 parent f33f79f commit 20e2b79

File tree

2 files changed

+27
-26
lines changed

2 files changed

+27
-26
lines changed

Diff for: sound/isa/msnd/msnd_midi.c

+15-15
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);

Diff for: sound/isa/msnd/msnd_pinnacle.c

+12-11
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)