Kernel Sound Driver

James Pharaoh (james@pharaoh0.demon.co.uk)
Sun, 29 Jun 1997 09:35:35 +0100 (BST)


Hi,

I have noticed a problem in the kernel sound driver, in at least version
2.0.29 and 2.0.30 of the kernel. I believe that previously the sound
driver has worked without a problem. It seems to occur when the device is
being shut down or closed. I have looked through the code (and I really
don't know much about this), and a few things occured to me as looking
wrong... (BTW the problem is a complete lock-up, and occurs using the dsp
device, at least)

drivers/sound/uart401.c, line 227
for (timeout = 30000; timeout < 0 && !output_ready (devc); timeout--);
Surely this should be timeout > 0? And again, line 354. uart6850.c line
284.

drivers/sound/sb_audio.c, sb_audio_open
save_flags (flags);
cli ();
if (devc->opened)
{
restore_flags (flags);
return -(EBUSY);
}

if (devc->dma16 != -1 && devc->dma16 != devc->dma8)
{
if (sound_open_dma (devc->dma16, "Sound Blaster 16 bit"))
{
return -(EBUSY);
}
}
devc->opened = mode;
restore_flags (flags);
The second return -(EBUSY) is not prefixed by restore_flags - surely
potentially leaving interrupts disabled (unless restored by some higher
function...)?

drivers/sound/pas2_midi.c, pas_midi_open
save_flags (flags);
cli ();

if ((err = pas_set_intr (0x10)) < 0)
return err;
Again, we are returning without calling restore_flags.

drivers/sound/gus_wave.c, gus_voice_fade
save_flags (flags);
cli ();
gus_select_voice (voice);

if (instr_no < 0 || instr_no > MAX_SAMPLE)
{
gus_write8 (0x00, 0x03); /* Hard stop */
voice_alloc->map[voice] = 0;
restore_flags (flags);
return;
}

is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0; /* 8 or 16bits */

if (voices[voice].mode & WAVE_ENVELOPES)
{
start_release (voice, flags);
return;
}
Once more, restore_flags is not called.

drivers/sound/gus_wave.c, do_volume_irq
save_flags (flags);
cli ();

gus_select_voice (voice);

tmp = gus_read8 (0x0d);
tmp &= ~0x20; /*
* Disable volume ramp IRQ
*/
gus_write8 (0x0d, tmp);

mode = voices[voice].volume_irq_mode;
voices[voice].volume_irq_mode = 0;
parm = voices[voice].volume_irq_parm;

switch (mode)
{
case VMODE_HALT: /*
* Decay phase finished
*/
restore_flags (flags);
gus_voice_init (voice);
break;

case VMODE_ENVELOPE:
gus_rampoff ();
restore_flags (flags);
step_envelope (voice);
break;

case VMODE_START_NOTE:
restore_flags (flags);
guswave_start_note2 (voices[voice].dev_pending, voice,
voices[voice].note_pending,voices[voice].volume_pending);
if (voices[voice].kill_pending)
guswave_kill_note (voices[voice].dev_pending, voice,
voices[voice].note_pending, 0);

if (voices[voice].sample_pending >= 0)
{
guswave_set_instr (voices[voice].dev_pending, voice,
voices[voice].sample_pending);
voices[voice].sample_pending = -1;
}
break;

default:;
}
}
Apparently the default action here is to not restore_flags.

drivers/sound/dmabuf.c, line 947 onwards
cli ();
changed = audio_devs[dev]->enable_bits ^ bits;

if ((changed & bits) & PCM_ENABLE_INPUT && audio_devs[dev]->go)
{
int err;

if (!(dmap_in->flags & DMA_ALLOC_DONE))
{
reorganize_buffers (dev, dmap_in, 1);
}

if ((err = audio_devs[dev]->d->prepare_for_input (dev,
dmap_in->fragment_size, dmap_in->nbufs)) <0)
return -(err);

audio_devs[dev]->enable_bits = bits;
activate_recording (dev, dmap_in);
}

if ((changed & bits) & PCM_ENABLE_OUTPUT &&
dmap_out->mapping_flags & DMA_MAP_MAPPED &&
audio_devs[dev]->go)
{
int err;

if (!(dmap_out->flags & DMA_ALLOC_DONE))
{
reorganize_buffers (dev, dmap_out, 0);
}

if ((err = audio_devs[dev]->d->prepare_for_output (dev,
dmap_out->fragment_size, dmap_out->nbufs)) <0)
return -(err);

dmap_out->counts[dmap_out->qhead] = dmap_out->fragment_size;
DMAbuf_start_output (dev, 0, dmap_out->fragment_size);
}

audio_devs[dev]->enable_bits = bits;
if (changed && audio_devs[dev]->d->trigger)
{
audio_devs[dev]->d->trigger (dev, bits * audio_devs[dev]->go);
}
restore_flags (flags);
A few times here we are yet again returning without calls to
restore_flags.

drivers/sound/dev_table.c, line 170 onwards
save_flags (flags);
cli ();

restore_flags (flags);
What?

*Phew* there's some 627 calls to cli() in that directory I just checked
through :). I apologise in advance if I'm wrong and have wasted anybodies
time...

BTW, I tried correcting these and the sound driver still crashes, so...

Thanks,

James.

-----------------------. ,--.
simeon900@bigfoot.com \ / \ http://www.pharaoh0.demon.co.uk
`--' `---------------------------------