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]>


 drivers/usb/core/hcd.c |   32 +++++++++++++++++++++++++++++---
 drivers/usb/core/hcd.h |    2 ++
 drivers/usb/core/hub.c |   17 ++++++++++++++++-
 drivers/usb/core/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 13:36:20 -08:00
+++ b/drivers/usb/core/hcd.c    2005-03-30 13:36:20 -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 13:36:20 -08:00
+++ b/drivers/usb/core/hcd.h    2005-03-30 13:36:20 -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 13:36:20 -08:00
+++ b/drivers/usb/core/hub.c    2005-03-30 13:36:20 -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 13:36:20 -08:00
+++ b/drivers/usb/core/usb.h    2005-03-30 13:36:20 -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;
 



-------------------------------------------------------
This SF.net email is sponsored by Demarc:
A global provider of Threat Management Solutions.
Download our HomeAdmin security software for free today!
http://www.demarc.com/info/Sentarus/hamr30
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to