• Alan Stern's avatar
    usbcore: make hcd_endpoint_disable wait for queue to drain · 455b25fb
    Alan Stern authored
    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: default avatarAlan Stern <stern@rowland.harvard.edu>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
    455b25fb
hcd.c 55.8 KB