This patchlet fixes a BUG() when using async unlink on OHCI. Basically, an
error in refcounting led to a schedule()-hungry sohci_free_dev call, even
when in_interrupt().

It's been against 2.4.0-test1-ac7, which includes Roman's last
visible patch (22/5).

        -- Cyrille

------------------------------------------------------------------------------
Grumpf.

--- drivers/usb/usb-ohci.romans.c       Thu Jun  1 22:12:35 2000
+++ drivers/usb/usb-ohci.c      Thu Jun  1 22:19:18 2000
@@ -527,12 +527,12 @@
 #ifdef DEBUG
        urb_print (urb, "UNLINK", 1);
 #endif           
-
-       usb_dec_dev_use (urb->dev);     
        
-       if (usb_pipedevice (urb->pipe) == ohci->rh.devnum) 
+       if (usb_pipedevice (urb->pipe) == ohci->rh.devnum) {
+               usb_dec_dev_use(urb->dev);
                return rh_unlink_urb (urb); /* a request to the virtual root hub */
-       
+       }
+
        if (urb->hcpriv) { 
                /* URB active? */
                if (urb->status == USB_ST_URB_PENDING && !ohci->disabled) {
@@ -548,15 +548,19 @@
                        urb_priv->ed->state |= ED_URB_DEL;
                        spin_unlock_irqrestore (&usb_ed_lock, flags);
                        if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) {
+                               usb_dec_dev_use (urb->dev);     
                                add_wait_queue (&op_wakeup, &wait);
                                current->state = TASK_UNINTERRUPTIBLE;
                                if (!schedule_timeout (HZ / 10)) /* wait until all TDs 
are deleted */
                                        err("unlink URB timeout!");
                                remove_wait_queue (&op_wakeup, &wait); 
                                urb->status = -ENOENT;
-                       } else
+                       } else {
+                               /* usb_dec_dev_use done in dl_del_list() */
                                urb->status = -EINPROGRESS;
+                       }
                } else {
+                       usb_dec_dev_use (urb->dev);     
                        urb_rm_priv (urb);
                        if (urb->complete && (urb->transfer_flags & USB_ASYNC_UNLINK)) 
{
                                urb->complete (urb); 
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to