diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2007-03-13 11:10:52 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-04-27 13:28:34 -0700 |
commit | 1b42ae6d4355328dc4406b6f0188adcf8c566435 (patch) | |
tree | 054e44f46fd7c2c4b25e4a7d40313879c5a4bffd | |
parent | 949be0f7be8de0c5a6a46626bd983f7a03a4b26e (diff) |
USB: fix race in HCD removal
This patch (as865) fixes a race in the HCD removal code discovered by
Milan Plzik. Arrival of an interrupt after the root hub was
unregistered could cause the root-hub status timer to start up, even
after it was supposed to have been shut down. The problem is fixed by
moving the del_timer_sync() call to after the HCD's stop() method, at
which time IRQ generation should be disabled.
Cc: Milan Plzik <milan.plzik@gmail.com>
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/core/hcd.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index b26c19e8d19..af7aed11398 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -544,6 +544,8 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) unsigned long flags; char buffer[4]; /* Any root hubs with > 31 ports? */ + if (unlikely(!hcd->rh_registered)) + return; if (!hcd->uses_new_polling && !hcd->status_urb) return; @@ -1670,12 +1672,12 @@ void usb_remove_hcd(struct usb_hcd *hcd) usb_disconnect(&hcd->self.root_hub); mutex_unlock(&usb_bus_list_lock); - hcd->poll_rh = 0; - del_timer_sync(&hcd->rh_timer); - hcd->driver->stop(hcd); hcd->state = HC_STATE_HALT; + hcd->poll_rh = 0; + del_timer_sync(&hcd->rh_timer); + if (hcd->irq >= 0) free_irq(hcd->irq, hcd); usb_deregister_bus(&hcd->self); |