aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/uhci-hcd.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2010-01-08 11:18:20 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-01-20 18:24:34 -0500
commitcec3a53c7fe794237b582e8e77fc0e48465e65ee (patch)
treebc73dbdef0688d6c656d04f288e736cb9b60d9b9 /drivers/usb/host/uhci-hcd.c
parent1b9a38bfa6e664ff02511314f5586d711c83cc91 (diff)
USB: EHCI & UHCI: fix race between root-hub suspend and port resume
This patch (as1321) fixes a problem with EHCI and UHCI root-hub suspends: If the suspend occurs while a port is trying to resume, the resume doesn't finish and simply gets lost. When remote wakeup is enabled, this is undesirable behavior. The patch checks first to see if any port resumes are in progress, and if they are then it fails the root-hub suspend with -EBUSY. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/uhci-hcd.c')
-rw-r--r--drivers/usb/host/uhci-hcd.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 5cd0e48f67fb..99cd00fd3514 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -749,7 +749,20 @@ static int uhci_rh_suspend(struct usb_hcd *hcd)
749 spin_lock_irq(&uhci->lock); 749 spin_lock_irq(&uhci->lock);
750 if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) 750 if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
751 rc = -ESHUTDOWN; 751 rc = -ESHUTDOWN;
752 else if (!uhci->dead) 752 else if (uhci->dead)
753 ; /* Dead controllers tell no tales */
754
755 /* Once the controller is stopped, port resumes that are already
756 * in progress won't complete. Hence if remote wakeup is enabled
757 * for the root hub and any ports are in the middle of a resume or
758 * remote wakeup, we must fail the suspend.
759 */
760 else if (hcd->self.root_hub->do_remote_wakeup &&
761 uhci->resuming_ports) {
762 dev_dbg(uhci_dev(uhci), "suspend failed because a port "
763 "is resuming\n");
764 rc = -EBUSY;
765 } else
753 suspend_rh(uhci, UHCI_RH_SUSPENDED); 766 suspend_rh(uhci, UHCI_RH_SUSPENDED);
754 spin_unlock_irq(&uhci->lock); 767 spin_unlock_irq(&uhci->lock);
755 return rc; 768 return rc;