diff options
author | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2010-12-17 21:35:05 +0100 |
---|---|---|
committer | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2011-03-14 02:23:45 +0100 |
commit | 65b22f93fde320b34d43e4a3978e1b52b1bcc279 (patch) | |
tree | 087312018a0076866f28e056f1481db76cfe2b78 /drivers | |
parent | xhci: Make roothub functions deal with device removal. (diff) | |
download | linux-65b22f93fde320b34d43e4a3978e1b52b1bcc279.tar.xz linux-65b22f93fde320b34d43e4a3978e1b52b1bcc279.zip |
xhci: Fix re-init on power loss after resume.
When a host controller has lost power during a suspend, we must
reinitialize it. Now that the xHCI host has two roothubs, xhci_run() and
xhci_stop() expect to be called with both usb_hcd structures. Be sure
that the re-initialization code in xhci_resume() mirrors the process the
USB PCI probe function uses.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/host/xhci.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 4549068758f5..ce024dc7116f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -730,6 +730,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) { u32 command, temp = 0; struct usb_hcd *hcd = xhci_to_hcd(xhci); + struct usb_hcd *secondary_hcd; int retval; /* Wait a bit if either of the roothubs need to settle from the @@ -790,15 +791,29 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) xhci_dbg(xhci, "xhci_stop completed - status = %x\n", xhci_readl(xhci, &xhci->op_regs->status)); - xhci_dbg(xhci, "Initialize the HCD\n"); - retval = xhci_init(hcd); + /* USB core calls the PCI reinit and start functions twice: + * first with the primary HCD, and then with the secondary HCD. + * If we don't do the same, the host will never be started. + */ + if (!usb_hcd_is_primary_hcd(hcd)) + secondary_hcd = hcd; + else + secondary_hcd = xhci->shared_hcd; + + xhci_dbg(xhci, "Initialize the xhci_hcd\n"); + retval = xhci_init(hcd->primary_hcd); if (retval) return retval; + xhci_dbg(xhci, "Start the primary HCD\n"); + retval = xhci_run(hcd->primary_hcd); + if (retval) + goto failed_restart; - xhci_dbg(xhci, "Start the HCD\n"); - retval = xhci_run(hcd); + xhci_dbg(xhci, "Start the secondary HCD\n"); + retval = xhci_run(secondary_hcd); if (!retval) set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); +failed_restart: hcd->state = HC_STATE_SUSPENDED; return retval; } |