Skip to content

Commit ee0b9be

Browse files
AlanSterngregkh
authored andcommitted
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 <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 4147200 commit ee0b9be

File tree

4 files changed

+15
-5
lines changed

4 files changed

+15
-5
lines changed

drivers/usb/host/ehci-hub.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
166166
ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg);
167167
}
168168
}
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));
169173
}
170174

171175
static int ehci_bus_suspend (struct usb_hcd *hcd)

drivers/usb/host/ohci-hub.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,11 @@ static void ohci_finish_controller_resume(struct usb_hcd *hcd)
355355
ohci_readl(ohci, &ohci->regs->intrenable);
356356
msleep(20);
357357
}
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);
358363
}
359364

360365
/* 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,
364369
int poll_rh = 1;
365370
int rhsc_enable;
366371

367-
/* Some broken controllers never turn off RHCS in the interrupt
372+
/* Some broken controllers never turn off RHSC in the interrupt
368373
* status register. For their sake we won't re-enable RHSC
369374
* interrupts if the interrupt bit is already active.
370375
*/

drivers/usb/host/uhci-hcd.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -862,10 +862,11 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
862862
/* If interrupts don't work and remote wakeup is enabled then
863863
* the suspended root hub needs to be polled.
864864
*/
865-
if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup) {
865+
if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup)
866866
set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
867-
usb_hcd_poll_rh_status(hcd);
868-
}
867+
868+
/* Does the root hub have a port wakeup pending? */
869+
usb_hcd_poll_rh_status(hcd);
869870
return 0;
870871
}
871872
#endif

drivers/usb/host/uhci-hub.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
200200
case UHCI_RH_SUSPENDING:
201201
case UHCI_RH_SUSPENDED:
202202
/* if port change, ask to be resumed */
203-
if (status)
203+
if (status || uhci->resuming_ports)
204204
usb_hcd_resume_root_hub(hcd);
205205
break;
206206

0 commit comments

Comments
 (0)