aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2010-06-25 14:02:24 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-10 17:35:37 -0400
commitee0b9be829803e3ff5adec7456bd59a08425ffa1 (patch)
treebab8946024f7c93428a383b813a7cfc94e71a409 /drivers/usb
parent4147200d25c423e627ab4487530b3d9f2ef829c8 (diff)
USB: controller resume should check the root hub
This patch (as1394) adds code to ehci-hcd, ohci-hcd, and uhci-hcd for automatically resuming the root hub when the controller is resumed, if the root hub has a wakeup request pending on some port. During resume from system sleep this doesn't matter, because the root hubs will naturally be resumed along with every other device in the system. However it _will_ matter for runtime PM: If the controller is suspended and a remote wakeup request is received then the controller will autoresume, but we need to ensure that the root hub also autoresumes. Otherwise the wakeup request would be ignored, the controller would go back to sleep, and the cycle would repeat a large number of times (I saw this happen before the patch was written). Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/ehci-hub.c4
-rw-r--r--drivers/usb/host/ohci-hub.c7
-rw-r--r--drivers/usb/host/uhci-hcd.c7
-rw-r--r--drivers/usb/host/uhci-hub.c2
4 files changed, 15 insertions, 5 deletions
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 1292a5b2197a..796ea0c8900f 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -166,6 +166,10 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
166 ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg); 166 ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg);
167 } 167 }
168 } 168 }
169
170 /* Does the root hub have a port wakeup pending? */
171 if (!suspending && (ehci_readl(ehci, &ehci->regs->status) & STS_PCD))
172 usb_hcd_resume_root_hub(ehci_to_hcd(ehci));
169} 173}
170 174
171static int ehci_bus_suspend (struct usb_hcd *hcd) 175static int ehci_bus_suspend (struct usb_hcd *hcd)
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 4dd39022c388..cddcda95b579 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -355,6 +355,11 @@ static void ohci_finish_controller_resume(struct usb_hcd *hcd)
355 ohci_readl(ohci, &ohci->regs->intrenable); 355 ohci_readl(ohci, &ohci->regs->intrenable);
356 msleep(20); 356 msleep(20);
357 } 357 }
358
359 /* Does the root hub have a port wakeup pending? */
360 if (ohci_readl(ohci, &ohci->regs->intrstatus) &
361 (OHCI_INTR_RD | OHCI_INTR_RHSC))
362 usb_hcd_resume_root_hub(hcd);
358} 363}
359 364
360/* Carry out polling-, autostop-, and autoresume-related state changes */ 365/* Carry out polling-, autostop-, and autoresume-related state changes */
@@ -364,7 +369,7 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
364 int poll_rh = 1; 369 int poll_rh = 1;
365 int rhsc_enable; 370 int rhsc_enable;
366 371
367 /* Some broken controllers never turn off RHCS in the interrupt 372 /* Some broken controllers never turn off RHSC in the interrupt
368 * status register. For their sake we won't re-enable RHSC 373 * status register. For their sake we won't re-enable RHSC
369 * interrupts if the interrupt bit is already active. 374 * interrupts if the interrupt bit is already active.
370 */ 375 */
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index a7850f51fdc5..9d4d81248f96 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -862,10 +862,11 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
862 /* If interrupts don't work and remote wakeup is enabled then 862 /* If interrupts don't work and remote wakeup is enabled then
863 * the suspended root hub needs to be polled. 863 * the suspended root hub needs to be polled.
864 */ 864 */
865 if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup) { 865 if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup)
866 set_bit(HCD_FLAG_POLL_RH, &hcd->flags); 866 set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
867 usb_hcd_poll_rh_status(hcd); 867
868 } 868 /* Does the root hub have a port wakeup pending? */
869 usb_hcd_poll_rh_status(hcd);
869 return 0; 870 return 0;
870} 871}
871#endif 872#endif
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index f0c58116c0ad..6d59c0f77f25 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -200,7 +200,7 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
200 case UHCI_RH_SUSPENDING: 200 case UHCI_RH_SUSPENDING:
201 case UHCI_RH_SUSPENDED: 201 case UHCI_RH_SUSPENDED:
202 /* if port change, ask to be resumed */ 202 /* if port change, ask to be resumed */
203 if (status) 203 if (status || uhci->resuming_ports)
204 usb_hcd_resume_root_hub(hcd); 204 usb_hcd_resume_root_hub(hcd);
205 break; 205 break;
206 206