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]

Reply via email to