uhci_remove_qh() calls uhci_free_qh() which may call usb_free_dev() and
consequently uhci_free_dev().  The last call causes a dead lock if
urb_list_lock is held which is the case when uhci_remove_qh is called
from uhci_transfer_result() through uhci_unlink_generic().

The following patch removes the dead lock by delaying the removal as
in the normal case.
-- 
Debian GNU/Linux 2.2 is out! ( http://www.debian.org/ )
Email:  Herbert Xu ~{PmV>HI~} <[EMAIL PROTECTED]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Index: drivers/usb/uhci.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.4/drivers/usb/uhci.c,v
retrieving revision 1.1.1.8
diff -u -r1.1.1.8 uhci.c
--- drivers/usb/uhci.c  2001/05/21 22:02:06     1.1.1.8
+++ drivers/usb/uhci.c  2001/06/05 09:43:11
@@ -425,8 +425,7 @@
 
        /* Only go through the hoops if it's actually linked in */
        if (list_empty(&qh->list)) {
-               uhci_free_qh(uhci, qh);
-               return;
+               goto list;
        }
 
        qh->urbp = NULL;
@@ -444,6 +443,7 @@
 
        spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
 
+list:
        spin_lock_irqsave(&uhci->qh_remove_list_lock, flags);
 
        /* Check to see if the remove list is empty. Set the IOC bit */

Reply via email to