Messages in this thread Patches in this message | | | Date | Sat, 22 Nov 2003 18:22:42 -0500 | From | "Neal H. Walfield" <> | Subject | maestro3.c bug using SNDCTL_DSP_SYNC ioctl in 2.4.22 |
| |
I recently acquired a Dell Latitude CPx 650 with a maestro3 chip. With the 2.4.22 verion of the linux kernel (specifically 2.4.22-1-686 as distributed by Debian), I encountered some problems with the SNDCTL_DSP_SYNC ioctl which is used, for example, by madplay [1]. On startup, madplay calls the SNDCTL_DSP_SYNC ioctl. This causes no problems until I interrupt madplay using control-C. If the next operation is the SNDCTL ioctl (e.g. by starting madplay) then the caller will hang waiting for the ioctl to return (this is easily seen using strace). As far as I can tell, the driver hangs in drain_dac()'s for loop waiting for s->dma_dac.count to drop to zero which it never does. I can use control-C to interrupt it and madplay will exit. Subsequent runs of madplay exhibit the same problem. On the other hand, if I use another audio program such as gnome-vlc (which strace indicates does not call the ioctl in question), it is able to use the audio successfully. After exiting from gnome-vlc, madplay will again work (however, hitting control-C and attempting to start madplay again will cause it to exhibit the same hang). The following work around allows me to use madplay successfully:
--- maestro3.c.orig Sat Aug 30 02:01:42 2003 +++ maestro3.c Sat Nov 22 15:52:16 2003 @@ -1291,7 +1291,7 @@ static int drain_dac(struct m3_state *s, int count; signed long tmo; - if (s->dma_dac.mapped || !s->dma_dac.ready) + if (s->dma_dac.mapped || !s->dma_dac.ready || !(s->enable & DAC_RUNNING)) return 0; set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&s->dma_dac.wait, &wait);
If drain_dac ought to work even if the card is not enabled, then maybe this patch is better:
--- maestro3.c.orig Sat Nov 22 15:52:16 2003 +++ maestro3.c Sat Nov 22 18:13:25 2003 @@ -1594,7 +1594,7 @@ static int m3_ioctl(struct inode *inode, return put_user(SOUND_VERSION, (int *)arg); case SNDCTL_DSP_SYNC: - if (file->f_mode & FMODE_WRITE) + if ((file->f_mode & FMODE_WRITE) && !(s->enable & DAC_RUNNING)) return drain_dac(s, file->f_flags & O_NONBLOCK); return 0; I have no idea if either of these are correct fix. There may, for instance, be unaccounted dma packets that need cleaning up; I haven't looked that deeply into the code to be able to tell.
Thanks.
[1] http://www.underbit.com/products/mad/ - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |