status, change, NULL);
 }
 
+static void hub_resubmit_irq_urb(struct usb_hub *hub)
+{
+       unsigned long flags;
+       int status;
+
+       spin_lock_irqsave(&hub->irq_urb_lock, flags);
+
+       if (hub->quiescing) {
+               spin_unlock_irqrestore(&hub->irq_urb_lock, flags);
+               return;
+       }
+
+       status = usb_submit_urb(hub->urb, GFP_ATOMIC);
+       if (status && status != -ENODEV && status != -EPERM &&
+           status != -ESHUTDOWN) {
+               dev_err(hub->intfdev, "resubmit --> %d\n", status);
+               mod_timer(&hub->irq_urb_retry, jiffies + HZ);
+       }
+
+       spin_unlock_irqrestore(&hub->irq_urb_lock, flags);
+}
+
+static void hub_retry_irq_urb(struct timer_list *t)
+{
+       struct usb_hub *hub = from_timer(hub, t, irq_urb_retry);
+
+       hub_resubmit_irq_urb(hub);
+}
+
+
 static void kick_hub_wq(struct usb_hub *hub)
 {
        struct usb_interface *intf;
        kick_hub_wq(hub);
 
 resubmit:
-       if (hub->quiescing)
-               return;
-
-       status = usb_submit_urb(hub->urb, GFP_ATOMIC);
-       if (status != 0 && status != -ENODEV && status != -EPERM)
-               dev_err(hub->intfdev, "resubmit --> %d\n", status);
+       hub_resubmit_irq_urb(hub);
 }
 
 /* USB 2.0 spec Section 11.24.2.3 */
 static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
 {
        struct usb_device *hdev = hub->hdev;
+       unsigned long flags;
        int i;
 
        /* hub_wq and related activity won't re-trigger */
+       spin_lock_irqsave(&hub->irq_urb_lock, flags);
        hub->quiescing = 1;
+       spin_unlock_irqrestore(&hub->irq_urb_lock, flags);
 
        if (type != HUB_SUSPEND) {
                /* Disconnect all the children */
        }
 
        /* Stop hub_wq and related activity */
+       del_timer_sync(&hub->irq_urb_retry);
        usb_kill_urb(hub->urb);
        if (hub->has_indicators)
                cancel_delayed_work_sync(&hub->leds);
        INIT_DELAYED_WORK(&hub->leds, led_work);
        INIT_DELAYED_WORK(&hub->init_work, NULL);
        INIT_WORK(&hub->events, hub_event);
+       spin_lock_init(&hub->irq_urb_lock);
+       timer_setup(&hub->irq_urb_retry, hub_retry_irq_urb, 0);
        usb_get_intf(intf);
        usb_get_dev(hdev);