ChangeSet 1.2181.4.40, 2005/03/21 14:58:02-08:00, [EMAIL PROTECTED]
[PATCH] USBcore updates
This is the third of five updates to usbcore:
Adjust the usb_hc_died routine to eliminate races with root-hub
registration/deregistration and have it tell khubd to remove
all devices below the root hub.
Signed-off-by: Alan Stern <[EMAIL PROTECTED]>
Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
hcd.c | 32 +++++++++++++++++++++++++++++---
hcd.h | 2 ++
hub.c | 17 ++++++++++++++++-
usb.h | 2 ++
4 files changed, 49 insertions(+), 4 deletions(-)
diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
--- a/drivers/usb/core/hcd.c 2005-03-30 15:12:37 -08:00
+++ b/drivers/usb/core/hcd.c 2005-03-30 15:12:37 -08:00
@@ -101,6 +101,9 @@
DECLARE_MUTEX (usb_bus_list_lock); /* exported only for usbfs */
EXPORT_SYMBOL_GPL (usb_bus_list_lock);
+/* used for controlling access to virtual root hubs */
+static DEFINE_SPINLOCK(hcd_root_hub_lock);
+
/* used when updating hcd data */
static DEFINE_SPINLOCK(hcd_data_lock);
@@ -874,6 +877,17 @@
usb_dev->dev.bus_id, retval);
}
up (&usb_bus_list_lock);
+
+ if (retval == 0) {
+ spin_lock_irq (&hcd_root_hub_lock);
+ hcd->rh_registered = 1;
+ spin_unlock_irq (&hcd_root_hub_lock);
+
+ /* Did the HC die before the root hub was registered? */
+ if (hcd->state == HC_STATE_HALT)
+ usb_hc_died (hcd); /* This time clean up */
+ }
+
return retval;
}
EXPORT_SYMBOL_GPL(usb_hcd_register_root_hub);
@@ -1575,12 +1589,21 @@
*/
void usb_hc_died (struct usb_hcd *hcd)
{
+ unsigned long flags;
+
dev_err (hcd->self.controller, "HC died; cleaning up\n");
- /* make khubd clean up old urbs and devices */
- usb_set_device_state(hcd->self.root_hub, USB_STATE_NOTATTACHED);
- mod_timer(&hcd->rh_timer, jiffies);
+ spin_lock_irqsave (&hcd_root_hub_lock, flags);
+ if (hcd->rh_registered) {
+
+ /* make khubd clean up old urbs and devices */
+ usb_set_device_state (hcd->self.root_hub,
+ USB_STATE_NOTATTACHED);
+ usb_kick_khubd (hcd->self.root_hub);
+ }
+ spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
}
+EXPORT_SYMBOL_GPL (usb_hc_died);
/*-------------------------------------------------------------------------*/
@@ -1737,6 +1760,9 @@
hcd->state = HC_STATE_QUIESCING;
dev_dbg(hcd->self.controller, "roothub graceful disconnect\n");
+ spin_lock_irq (&hcd_root_hub_lock);
+ hcd->rh_registered = 0;
+ spin_unlock_irq (&hcd_root_hub_lock);
usb_disconnect(&hcd->self.root_hub);
hcd->driver->stop(hcd);
diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
--- a/drivers/usb/core/hcd.h 2005-03-30 15:12:37 -08:00
+++ b/drivers/usb/core/hcd.h 2005-03-30 15:12:37 -08:00
@@ -74,6 +74,8 @@
unsigned saw_irq : 1;
unsigned can_wakeup:1; /* hw supports wakeup? */
unsigned remote_wakeup:1;/* sw should use wakeup? */
+ unsigned rh_registered:1;/* is root hub registered? */
+
int irq; /* irq allocated */
void __iomem *regs; /* device memory/io */
u64 rsrc_start; /* memory/io resource start */
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c 2005-03-30 15:12:37 -08:00
+++ b/drivers/usb/core/hub.c 2005-03-30 15:12:37 -08:00
@@ -289,6 +289,11 @@
spin_unlock_irqrestore(&hub_event_lock, flags);
}
+void usb_kick_khubd(struct usb_device *hdev)
+{
+ kick_khubd(hdev_to_hub(hdev));
+}
+
/* completion function, fires on port status changes and various faults */
static void hub_irq(struct urb *urb, struct pt_regs *regs)
@@ -2624,7 +2629,17 @@
usb_put_intf(intf);
continue;
}
- if (hub != usb_get_intfdata(intf) || hub->quiescing)
+ if (hub != usb_get_intfdata(intf))
+ goto loop;
+
+ /* If the hub has died, clean up after it */
+ if (hdev->state == USB_STATE_NOTATTACHED) {
+ hub_pre_reset(hub);
+ goto loop;
+ }
+
+ /* If this is an inactive or suspended hub, do nothing */
+ if (hub->quiescing)
goto loop;
if (hub->error) {
diff -Nru a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
--- a/drivers/usb/core/usb.h 2005-03-30 15:12:37 -08:00
+++ b/drivers/usb/core/usb.h 2005-03-30 15:12:37 -08:00
@@ -18,6 +18,8 @@
extern void usb_lock_all_devices(void);
extern void usb_unlock_all_devices(void);
+extern void usb_kick_khubd(struct usb_device *dev);
+
/* for labeling diagnostics */
extern const char *usbcore_name;
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html