Merge tag 'for-v3.13/clock-fixes-a' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / drivers / usb / host / uhci-pci.c
index 0f228c4..4cd7988 100644 (file)
@@ -162,6 +162,8 @@ static void uhci_shutdown(struct pci_dev *pdev)
 
 #ifdef CONFIG_PM
 
+static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated);
+
 static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
@@ -174,12 +176,6 @@ static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
        if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead)
                goto done_okay;         /* Already suspended or dead */
 
-       if (uhci->rh_state > UHCI_RH_SUSPENDED) {
-               dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n");
-               rc = -EBUSY;
-               goto done;
-       };
-
        /* All PCI host controllers are required to disable IRQ generation
         * at the source, so we must turn off PIRQ.
         */
@@ -195,8 +191,15 @@ static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 
 done_okay:
        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-done:
        spin_unlock_irq(&uhci->lock);
+
+       synchronize_irq(hcd->irq);
+
+       /* Check for race with a wakeup request */
+       if (do_wakeup && HCD_WAKEUP_PENDING(hcd)) {
+               uhci_pci_resume(hcd, false);
+               rc = -EBUSY;
+       }
        return rc;
 }
 
@@ -299,3 +302,5 @@ static struct pci_driver uhci_pci_driver = {
        },
 #endif
 };
+
+MODULE_SOFTDEP("pre: ehci_pci");