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>
This commit is contained in:
Родитель
4147200d25
Коммит
ee0b9be829
|
@ -166,6 +166,10 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
|
||||||
ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg);
|
ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Does the root hub have a port wakeup pending? */
|
||||||
|
if (!suspending && (ehci_readl(ehci, &ehci->regs->status) & STS_PCD))
|
||||||
|
usb_hcd_resume_root_hub(ehci_to_hcd(ehci));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ehci_bus_suspend (struct usb_hcd *hcd)
|
static int ehci_bus_suspend (struct usb_hcd *hcd)
|
||||||
|
|
|
@ -355,6 +355,11 @@ static void ohci_finish_controller_resume(struct usb_hcd *hcd)
|
||||||
ohci_readl(ohci, &ohci->regs->intrenable);
|
ohci_readl(ohci, &ohci->regs->intrenable);
|
||||||
msleep(20);
|
msleep(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Does the root hub have a port wakeup pending? */
|
||||||
|
if (ohci_readl(ohci, &ohci->regs->intrstatus) &
|
||||||
|
(OHCI_INTR_RD | OHCI_INTR_RHSC))
|
||||||
|
usb_hcd_resume_root_hub(hcd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Carry out polling-, autostop-, and autoresume-related state changes */
|
/* 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,
|
||||||
int poll_rh = 1;
|
int poll_rh = 1;
|
||||||
int rhsc_enable;
|
int rhsc_enable;
|
||||||
|
|
||||||
/* Some broken controllers never turn off RHCS in the interrupt
|
/* Some broken controllers never turn off RHSC in the interrupt
|
||||||
* status register. For their sake we won't re-enable RHSC
|
* status register. For their sake we won't re-enable RHSC
|
||||||
* interrupts if the interrupt bit is already active.
|
* interrupts if the interrupt bit is already active.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -862,10 +862,11 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
|
||||||
/* If interrupts don't work and remote wakeup is enabled then
|
/* If interrupts don't work and remote wakeup is enabled then
|
||||||
* the suspended root hub needs to be polled.
|
* the suspended root hub needs to be polled.
|
||||||
*/
|
*/
|
||||||
if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup) {
|
if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup)
|
||||||
set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
|
set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
|
||||||
usb_hcd_poll_rh_status(hcd);
|
|
||||||
}
|
/* Does the root hub have a port wakeup pending? */
|
||||||
|
usb_hcd_poll_rh_status(hcd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -200,7 +200,7 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
|
||||||
case UHCI_RH_SUSPENDING:
|
case UHCI_RH_SUSPENDING:
|
||||||
case UHCI_RH_SUSPENDED:
|
case UHCI_RH_SUSPENDED:
|
||||||
/* if port change, ask to be resumed */
|
/* if port change, ask to be resumed */
|
||||||
if (status)
|
if (status || uhci->resuming_ports)
|
||||||
usb_hcd_resume_root_hub(hcd);
|
usb_hcd_resume_root_hub(hcd);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче