Commit 1c124c99 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

USB: UHCI: check for wakeup/suspend race

hcd-pci.c in usbcore contains a check for wakeup requests racing with
controller suspend.  This check is going to be moved out of usbcore
and into the individual controller drivers, where it can apply to all
platforms, not just PCI.

This patch adds the check to uhci-hcd.  Ironically, none of the
non-PCI platform drivers for uhci-hcd implement suspend/resume.
Nevertheless, this change is needed to accomodate the upcoming change
to usbcore.

The patch also removes an outdated check of the root hub state.  For
one thing, the PM layer has long been quite reliable about suspending
root hubs before controllers.  For another, virtually the same check
is also made in hcd-pci.c; there's no point in repeating it.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent b8efdafb
...@@ -162,6 +162,8 @@ static void uhci_shutdown(struct pci_dev *pdev) ...@@ -162,6 +162,8 @@ static void uhci_shutdown(struct pci_dev *pdev)
#ifdef CONFIG_PM #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) static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
{ {
struct uhci_hcd *uhci = hcd_to_uhci(hcd); struct uhci_hcd *uhci = hcd_to_uhci(hcd);
...@@ -174,12 +176,6 @@ static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) ...@@ -174,12 +176,6 @@ static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead) if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead)
goto done_okay; /* Already suspended or 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 /* All PCI host controllers are required to disable IRQ generation
* at the source, so we must turn off PIRQ. * 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) ...@@ -195,8 +191,15 @@ static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
done_okay: done_okay:
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
done:
spin_unlock_irq(&uhci->lock); 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; return rc;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment