usbcore: make hcd_endpoint_disable wait for queue to drain
authorAlan Stern <stern@rowland.harvard.edu>
Fri, 11 Aug 2006 20:01:45 +0000 (16:01 -0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 27 Sep 2006 18:58:54 +0000 (11:58 -0700)
commit455b25fb209c8241e2163b491228b28667d82c1c
treec7155eb33fa8b2916d52472fb517165b3b32813c
parentde06a3b842b31b31220637c869f112cfbc1a5ef6
usbcore: make hcd_endpoint_disable wait for queue to drain

The inconsistent lock state problem in usbcore (the one that shows up
when an HCD is unloaded) comes down to two inter-related problems:

usb_rh_urb_dequeue() isn't set up to be called with interrupts
disabled.

hcd_endpoint_disable() doesn't wait for all URBs on the
endpoint's queue to complete.

The two problems are related because the one type of URB that isn't
likely to be complete when hcd_endpoint_disable() returns is a root-hub
URB.  Right now usb_rh_urb_dequeue() waits for them to complete, and it
assumes interrupts are enabled so it can wait.  But
hcd_endpoint_disable() calls it with interrupts disabled.

Now, it should be legal to unlink root-hub URBs with interrupts
disabled.  The solution is to move the waiting into
hcd_endpoint_disable(), where it belongs.  This patch (as754) does that.

It turns out to be completely safe to replace the del_timer_sync() with
a simple del_timer().  It doesn't matter if the timer routine is
running; hcd_root_hub_lock will synchronize the two threads and the
status URB will complete with an unlink error, as it should.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/core/hcd.c