Hi Randy & list
Here's another patch for audio against 2.3.99-pre10-pre3.
It fixes a poll_wait related possibly random corrupting bug Alan reminded me to fix.
It also fixes SELECTOR support.
Please apply.
Tom
--- /usr/ife/t3/sailer/tmp4/linux/drivers/usb/audio.c Thu May 25 15:31:22 2000
+++ audio.c Thu May 25 14:54:26 2000
@@ -89,6 +89,8 @@
* Somewhat peculiar due to OSS interface limitations. Only works
* for channels where a "slider" is already in front of it (i.e.
* a MIXER unit or a FEATURE unit with volume capability).
+ * 2000-05-25: Switch to one waitqueue per Input/Output channel pair
+ * to avoid corruption on poll (calling poll_wait twice is forbidden).
*
*/
@@ -254,7 +256,6 @@
unsigned total_bytes;
int count;
unsigned error; /* over/underrun */
- wait_queue_head_t wait;
/* redundant, but makes calculations easier */
unsigned fragsize;
unsigned dmasize;
@@ -296,6 +297,7 @@
/* wave stuff */
mode_t open_mode;
spinlock_t lock; /* DMA buffer access spinlock */
+ wait_queue_head_t iowait;
struct usbin {
int interface; /* Interface number, -1 means not used */
@@ -799,8 +801,9 @@
}
}
-static int usbin_prepare_desc(struct usbin *u, purb_t urb)
+static int usbin_prepare_desc(struct usb_audiodev *as, purb_t urb)
{
+ struct usbin *u = &as->usbin;
unsigned int i, maxsize, offs;
maxsize = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format));
@@ -816,8 +819,9 @@
* return value: 0 if descriptor should be restarted, -1 otherwise
* convert sample format on the fly if necessary
*/
-static int usbin_retire_desc(struct usbin *u, purb_t urb)
+static int usbin_retire_desc(struct usb_audiodev *as, purb_t urb)
{
+ struct usbin *u = &as->usbin;
unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, dmafree;
unsigned char *cp;
@@ -853,7 +857,7 @@
if (err)
u->dma.error++;
if (u->dma.count >= (signed)u->dma.fragsize)
- wake_up(&u->dma.wait);
+ wake_up(&as->iowait);
return err ? -1 : 0;
}
@@ -877,14 +881,14 @@
printk(KERN_ERR "usbin_completed: panic: unknown URB\n");
}
spin_lock_irqsave(&as->lock, flags);
- if (!usbin_retire_desc(u, urb) &&
+ if (!usbin_retire_desc(as, urb) &&
u->flags & FLG_RUNNING &&
- !usbin_prepare_desc(u, urb) &&
+ !usbin_prepare_desc(as, urb) &&
(suret = usb_submit_urb(urb)) == USB_ST_NOERROR) {
u->flags |= mask;
} else {
u->flags &= ~(mask | FLG_RUNNING);
- wake_up(&u->dma.wait);
+ wake_up(&as->iowait);
printk(KERN_DEBUG "usbin_completed: descriptor not restarted
(usb_submit_urb: %d)\n", suret);
}
spin_unlock_irqrestore(&as->lock, flags);
@@ -893,8 +897,9 @@
/*
* we output sync data
*/
-static int usbin_sync_prepare_desc(struct usbin *u, purb_t urb)
+static int usbin_sync_prepare_desc(struct usb_audiodev *as, purb_t urb)
{
+ struct usbin *u = &as->usbin;
unsigned char *cp = urb->transfer_buffer;
unsigned int i, offs;
@@ -911,7 +916,7 @@
/*
* return value: 0 if descriptor should be restarted, -1 otherwise
*/
-static int usbin_sync_retire_desc(struct usbin *u, purb_t urb)
+static int usbin_sync_retire_desc(struct usb_audiodev *as, purb_t urb)
{
unsigned int i;
@@ -941,14 +946,14 @@
printk(KERN_ERR "usbin_sync_completed: panic: unknown URB\n");
}
spin_lock_irqsave(&as->lock, flags);
- if (!usbin_sync_retire_desc(u, urb) &&
+ if (!usbin_sync_retire_desc(as, urb) &&
u->flags & FLG_RUNNING &&
- !usbin_sync_prepare_desc(u, urb) &&
+ !usbin_sync_prepare_desc(as, urb) &&
(suret = usb_submit_urb(urb)) == USB_ST_NOERROR) {
u->flags |= mask;
} else {
u->flags &= ~(mask | FLG_RUNNING);
- wake_up(&u->dma.wait);
+ wake_up(&as->iowait);
printk(KERN_DEBUG "usbin_sync_completed: descriptor not restarted
(usb_submit_urb: %d)\n", suret);
}
spin_unlock_irqrestore(&as->lock, flags);
@@ -1015,7 +1020,7 @@
urb->number_of_packets = DESCFRAMES;
urb->context = as;
urb->complete = usbin_completed;
- if (!usbin_prepare_desc(u, urb) && !usb_submit_urb(urb))
+ if (!usbin_prepare_desc(as, urb) && !usb_submit_urb(urb))
u->flags |= FLG_URB0RUNNING;
else
u->flags &= ~FLG_RUNNING;
@@ -1028,7 +1033,7 @@
urb->number_of_packets = DESCFRAMES;
urb->context = as;
urb->complete = usbin_completed;
- if (!usbin_prepare_desc(u, urb) && !usb_submit_urb(urb))
+ if (!usbin_prepare_desc(as, urb) && !usb_submit_urb(urb))
u->flags |= FLG_URB1RUNNING;
else
u->flags &= ~FLG_RUNNING;
@@ -1043,7 +1048,7 @@
urb->context = as;
urb->complete = usbin_sync_completed;
/* stride: u->syncinterval */
- if (!usbin_sync_prepare_desc(u, urb) && !usb_submit_urb(urb))
+ if (!usbin_sync_prepare_desc(as, urb) && !usb_submit_urb(urb))
u->flags |= FLG_SYNC0RUNNING;
else
u->flags &= ~FLG_RUNNING;
@@ -1057,7 +1062,7 @@
urb->context = as;
urb->complete = usbin_sync_completed;
/* stride: u->syncinterval */
- if (!usbin_sync_prepare_desc(u, urb) && !usb_submit_urb(urb))
+ if (!usbin_sync_prepare_desc(as, urb) && !usb_submit_urb(urb))
u->flags |= FLG_SYNC1RUNNING;
else
u->flags &= ~FLG_RUNNING;
@@ -1146,8 +1151,9 @@
}
}
-static int usbout_prepare_desc(struct usbout *u, purb_t urb)
+static int usbout_prepare_desc(struct usb_audiodev *as, purb_t urb)
{
+ struct usbout *u = &as->usbout;
unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, offs;
unsigned char *cp = urb->transfer_buffer;
@@ -1187,10 +1193,10 @@
u->dma.error++;
if (u->dma.mapped) {
if (u->dma.count >= (signed)u->dma.fragsize)
- wake_up(&u->dma.wait);
+ wake_up(&as->iowait);
} else {
if ((signed)u->dma.dmasize >= u->dma.count + (signed)u->dma.fragsize)
- wake_up(&u->dma.wait);
+ wake_up(&as->iowait);
}
return err ? -1 : 0;
}
@@ -1198,7 +1204,7 @@
/*
* return value: 0 if descriptor should be restarted, -1 otherwise
*/
-static int usbout_retire_desc(struct usbout *u, purb_t urb)
+static int usbout_retire_desc(struct usb_audiodev *as, purb_t urb)
{
unsigned int i;
@@ -1231,20 +1237,20 @@
printk(KERN_ERR "usbout_completed: panic: unknown URB\n");
}
spin_lock_irqsave(&as->lock, flags);
- if (!usbout_retire_desc(u, urb) &&
+ if (!usbout_retire_desc(as, urb) &&
u->flags & FLG_RUNNING &&
- !usbout_prepare_desc(u, urb) &&
+ !usbout_prepare_desc(as, urb) &&
(suret = usb_submit_urb(urb)) == USB_ST_NOERROR) {
u->flags |= mask;
} else {
u->flags &= ~(mask | FLG_RUNNING);
- wake_up(&u->dma.wait);
+ wake_up(&as->iowait);
printk(KERN_DEBUG "usbout_completed: descriptor not restarted
(usb_submit_urb: %d)\n", suret);
}
spin_unlock_irqrestore(&as->lock, flags);
}
-static int usbout_sync_prepare_desc(struct usbout *u, purb_t urb)
+static int usbout_sync_prepare_desc(struct usb_audiodev *as, purb_t urb)
{
unsigned int i, offs;
@@ -1258,8 +1264,9 @@
/*
* return value: 0 if descriptor should be restarted, -1 otherwise
*/
-static int usbout_sync_retire_desc(struct usbout *u, purb_t urb)
+static int usbout_sync_retire_desc(struct usb_audiodev *as, purb_t urb)
{
+ struct usbout *u = &as->usbout;
unsigned char *cp = urb->transfer_buffer;
unsigned int f, i;
@@ -1302,14 +1309,14 @@
printk(KERN_ERR "usbout_sync_completed: panic: unknown URB\n");
}
spin_lock_irqsave(&as->lock, flags);
- if (!usbout_sync_retire_desc(u, urb) &&
+ if (!usbout_sync_retire_desc(as, urb) &&
u->flags & FLG_RUNNING &&
- !usbout_sync_prepare_desc(u, urb) &&
+ !usbout_sync_prepare_desc(as, urb) &&
(suret = usb_submit_urb(urb)) == USB_ST_NOERROR) {
u->flags |= mask;
} else {
u->flags &= ~(mask | FLG_RUNNING);
- wake_up(&u->dma.wait);
+ wake_up(&as->iowait);
printk(KERN_DEBUG "usbout_sync_completed: descriptor not restarted
(usb_submit_urb: %d)\n", suret);
}
spin_unlock_irqrestore(&as->lock, flags);
@@ -1376,7 +1383,7 @@
urb->number_of_packets = DESCFRAMES;
urb->context = as;
urb->complete = usbout_completed;
- if (!usbout_prepare_desc(u, urb) && !usb_submit_urb(urb))
+ if (!usbout_prepare_desc(as, urb) && !usb_submit_urb(urb))
u->flags |= FLG_URB0RUNNING;
else
u->flags &= ~FLG_RUNNING;
@@ -1389,7 +1396,7 @@
urb->number_of_packets = DESCFRAMES;
urb->context = as;
urb->complete = usbout_completed;
- if (!usbout_prepare_desc(u, urb) && !usb_submit_urb(urb))
+ if (!usbout_prepare_desc(as, urb) && !usb_submit_urb(urb))
u->flags |= FLG_URB1RUNNING;
else
u->flags &= ~FLG_RUNNING;
@@ -1404,7 +1411,7 @@
urb->context = as;
urb->complete = usbout_sync_completed;
/* stride: u->syncinterval */
- if (!usbout_sync_prepare_desc(u, urb) && !usb_submit_urb(urb))
+ if (!usbout_sync_prepare_desc(as, urb) && !usb_submit_urb(urb))
u->flags |= FLG_SYNC0RUNNING;
else
u->flags &= ~FLG_RUNNING;
@@ -1418,7 +1425,7 @@
urb->context = as;
urb->complete = usbout_sync_completed;
/* stride: u->syncinterval */
- if (!usbout_sync_prepare_desc(u, urb) && !usb_submit_urb(urb))
+ if (!usbout_sync_prepare_desc(as, urb) && !usb_submit_urb(urb))
u->flags |= FLG_SYNC1RUNNING;
else
u->flags &= ~FLG_RUNNING;
@@ -1788,7 +1795,7 @@
dev->devnum, ms->iface, ms->ch[i].slctunitid & 0xff);
continue;
}
- for (j = i; j < ms->numch; i++) {
+ for (j = i; j < ms->numch; j++) {
if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff)
continue;
mask |= 1 << j;
@@ -1821,7 +1828,7 @@
}
/* first generate smask */
smask = bmask = 0;
- for (j = i; j < ms->numch; i++) {
+ for (j = i; j < ms->numch; j++) {
if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff)
continue;
smask |= 1 << ms->ch[j].osschannel;
@@ -1835,7 +1842,7 @@
continue;
if (j > 1)
srcmask &= ~bmask;
- for (j = i; j < ms->numch; i++) {
+ for (j = i; j < ms->numch; j++) {
if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff)
continue;
if (!(srcmask & (1 << ms->ch[j].osschannel)))
@@ -2062,7 +2069,7 @@
if (as->usbout.dma.mapped || !as->usbout.dma.ready)
return 0;
usbout_start(as);
- add_wait_queue(&as->usbout.dma.wait, &wait);
+ add_wait_queue(&as->iowait, &wait);
for (;;) {
__set_current_state(TASK_INTERRUPTIBLE);
spin_lock_irqsave(&as->lock, flags);
@@ -2073,7 +2080,7 @@
if (signal_pending(current))
break;
if (nonblock) {
- remove_wait_queue(&as->usbout.dma.wait, &wait);
+ remove_wait_queue(&as->iowait, &wait);
set_current_state(TASK_RUNNING);
return -EBUSY;
}
@@ -2084,7 +2091,7 @@
break;
}
}
- remove_wait_queue(&as->usbout.dma.wait, &wait);
+ remove_wait_queue(&as->iowait, &wait);
set_current_state(TASK_RUNNING);
if (signal_pending(current))
return -ERESTARTSYS;
@@ -2110,7 +2117,7 @@
return ret;
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
- add_wait_queue(&as->usbin.dma.wait, &wait);
+ add_wait_queue(&as->iowait, &wait);
while (count > 0) {
spin_lock_irqsave(&as->lock, flags);
ptr = as->usbin.dma.rdptr;
@@ -2157,7 +2164,7 @@
ret += cnt;
}
__set_current_state(TASK_RUNNING);
- remove_wait_queue(&as->usbin.dma.wait, &wait);
+ remove_wait_queue(&as->iowait, &wait);
return ret;
}
@@ -2180,7 +2187,7 @@
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
start_thr = (as->usbout.dma.srate << AFMT_BYTESSHIFT(as->usbout.dma.format)) /
(1000 / (3 * DESCFRAMES));
- add_wait_queue(&as->usbout.dma.wait, &wait);
+ add_wait_queue(&as->iowait, &wait);
while (count > 0) {
#if 0
printk(KERN_DEBUG "usb_audio_write: count %u dma: count %u rdptr %u
wrptr %u dmasize %u fragsize %u flags 0x%02x taskst 0x%lx\n",
@@ -2241,7 +2248,7 @@
}
}
__set_current_state(TASK_RUNNING);
- remove_wait_queue(&as->usbout.dma.wait, &wait);
+ remove_wait_queue(&as->iowait, &wait);
return ret;
}
@@ -2252,16 +2259,13 @@
unsigned long flags;
unsigned int mask = 0;
- if (file->f_mode & FMODE_WRITE) {
- if (!as->usbout.dma.ready)
- prog_dmabuf_out(as);
- poll_wait(file, &as->usbout.dma.wait, wait);
- }
- if (file->f_mode & FMODE_READ) {
- if (!as->usbin.dma.ready)
- prog_dmabuf_in(as);
- poll_wait(file, &as->usbin.dma.wait, wait);
- }
+ if (!(file->f_mode & (FMODE_WRITE|FMODE_READ)))
+ return 0;
+ if (file->f_mode & FMODE_WRITE && !as->usbout.dma.ready)
+ prog_dmabuf_out(as);
+ if (file->f_mode & FMODE_READ && !as->usbin.dma.ready)
+ prog_dmabuf_in(as);
+ poll_wait(file, &as->iowait, wait);
spin_lock_irqsave(&as->lock, flags);
if (file->f_mode & FMODE_READ) {
if (as->usbin.dma.count >= (signed)as->usbin.dma.fragsize)
@@ -2744,8 +2748,7 @@
if (!(as = kmalloc(sizeof(struct usb_audiodev), GFP_KERNEL)))
return;
memset(as, 0, sizeof(struct usb_audiodev));
- init_waitqueue_head(&as->usbin.dma.wait);
- init_waitqueue_head(&as->usbout.dma.wait);
+ init_waitqueue_head(&as->iowait);
spin_lock_init(&as->lock);
as->state = s;
as->usbin.interface = asifin;
@@ -3193,6 +3196,16 @@
state->termtype = 0;
}
+static struct mixerchannel *slctsrc_findunit(struct consmixstate *state, __u8 unitid)
+{
+ unsigned int i;
+
+ for (i = 0; i < state->nrmixch; i++)
+ if (state->mixch[i].unitid == unitid)
+ return &state->mixch[i];
+ return NULL;
+}
+
static void usb_audio_selectorunit(struct consmixstate *state, unsigned char
*selector)
{
unsigned int chnum, i, mixch;
@@ -3206,7 +3219,9 @@
usb_audio_recurseunit(state, selector[5]);
if (state->nrmixch != mixch) {
mch = &state->mixch[state->nrmixch-1];
- mch->slctunitid = selector[5] | (1 << 8);
+ mch->slctunitid = selector[3] | (1 << 8);
+ } else if ((mch = slctsrc_findunit(state, selector[5]))) {
+ mch->slctunitid = selector[3] | (1 << 8);
} else {
printk(KERN_INFO "usbaudio: selector unit %u: ignoring channel 1\n",
selector[3]);
}
@@ -3223,7 +3238,9 @@
}
if (state->nrmixch != mixch) {
mch = &state->mixch[state->nrmixch-1];
- mch->slctunitid = selector[5] | ((i + 1) << 8);
+ mch->slctunitid = selector[3] | ((i + 1) << 8);
+ } else if ((mch = slctsrc_findunit(state, selector[5+i]))) {
+ mch->slctunitid = selector[3] | ((i + 1) << 8);
} else {
printk(KERN_INFO "usbaudio: selector unit %u: ignoring channel
%u\n", selector[3], i+1);
}
@@ -3672,8 +3689,7 @@
as = list_entry(list, struct usb_audiodev, list);
usbin_disc(as);
usbout_disc(as);
- wake_up(&as->usbin.dma.wait);
- wake_up(&as->usbout.dma.wait);
+ wake_up(&as->iowait);
if (as->dev_audio >= 0)
unregister_sound_dsp(as->dev_audio);
as->dev_audio = -1;
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]