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 */