aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/usb
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2010-06-09 17:34:17 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-10 17:35:33 -0400
commit6d88e6792574497bfac9a81403cc47712040636f (patch)
treeecd65e7b2c3c0f90f7a5e39313a3fb2850b2fdb8 /include/linux/usb
parent96e077ae347912dfce0e93f5958efc3ed6f311f4 (diff)
USB: don't stop root-hub status polls too soon
This patch (as1390) fixes a problem that crops up when a UHCI host controller is unbound from uhci-hcd while there are still some active URBs. The URBs have to be unlinked when the root hub is unregistered, and uhci-hcd relies upon root-hub status polls as part of its unlinking procedure. But usb_hcd_poll_rh_status() won't make those status calls if hcd->rh_registered is clear, and the flag is cleared _before_ the unregistration takes place. Since hcd->rh_registered is used for other things and needs to be cleared early, the solution is to add a new flag (rh_pollable) and use it instead. It gets cleared _after_ the root hub is unregistered. Now that the status polls don't end too soon, we have to make sure they also don't occur too late -- after the root hub's usb_device structure or the HCD's private structures are deallocated. Therefore the patch adds usb_get_device() and usb_put_device() calls to protect the root hub structure, and it adds an extra del_timer_sync() to prevent the root-hub timer from causing an unexpected status poll. This additional complexity would not be needed if the HCD framework had provided separate stop() and release() callbacks instead of just stop(). This lack could be fixed at some future time (although it would require changes to every host controller driver); when that happens this patch won't be needed any more. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'include/linux/usb')
-rw-r--r--include/linux/usb/hcd.h1
1 files changed, 1 insertions, 0 deletions
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 2e3a4ea1a3da..11b638195901 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -95,6 +95,7 @@ struct usb_hcd {
95#define HCD_FLAG_SAW_IRQ 0x00000002 95#define HCD_FLAG_SAW_IRQ 0x00000002
96 96
97 unsigned rh_registered:1;/* is root hub registered? */ 97 unsigned rh_registered:1;/* is root hub registered? */
98 unsigned rh_pollable:1; /* may we poll the root hub? */
98 99
99 /* The next flag is a stopgap, to be removed when all the HCDs 100 /* The next flag is a stopgap, to be removed when all the HCDs
100 * support the new root-hub polling mechanism. */ 101 * support the new root-hub polling mechanism. */