diff options
author | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2010-12-17 15:35:05 -0500 |
---|---|---|
committer | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2011-03-13 21:23:45 -0400 |
commit | 65b22f93fde320b34d43e4a3978e1b52b1bcc279 (patch) | |
tree | 087312018a0076866f28e056f1481db76cfe2b78 /drivers/usb/host/xhci.c | |
parent | f9de8151877b4f01cc8e124b0e213a6c6c78d970 (diff) |
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/usb/host/xhci.c')
-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) | |||
730 | { | 730 | { |
731 | u32 command, temp = 0; | 731 | u32 command, temp = 0; |
732 | struct usb_hcd *hcd = xhci_to_hcd(xhci); | 732 | struct usb_hcd *hcd = xhci_to_hcd(xhci); |
733 | struct usb_hcd *secondary_hcd; | ||
733 | int retval; | 734 | int retval; |
734 | 735 | ||
735 | /* Wait a bit if either of the roothubs need to settle from the | 736 | /* 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) | |||
790 | xhci_dbg(xhci, "xhci_stop completed - status = %x\n", | 791 | xhci_dbg(xhci, "xhci_stop completed - status = %x\n", |
791 | xhci_readl(xhci, &xhci->op_regs->status)); | 792 | xhci_readl(xhci, &xhci->op_regs->status)); |
792 | 793 | ||
793 | xhci_dbg(xhci, "Initialize the HCD\n"); | 794 | /* USB core calls the PCI reinit and start functions twice: |
794 | retval = xhci_init(hcd); | 795 | * first with the primary HCD, and then with the secondary HCD. |
796 | * If we don't do the same, the host will never be started. | ||
797 | */ | ||
798 | if (!usb_hcd_is_primary_hcd(hcd)) | ||
799 | secondary_hcd = hcd; | ||
800 | else | ||
801 | secondary_hcd = xhci->shared_hcd; | ||
802 | |||
803 | xhci_dbg(xhci, "Initialize the xhci_hcd\n"); | ||
804 | retval = xhci_init(hcd->primary_hcd); | ||
795 | if (retval) | 805 | if (retval) |
796 | return retval; | 806 | return retval; |
807 | xhci_dbg(xhci, "Start the primary HCD\n"); | ||
808 | retval = xhci_run(hcd->primary_hcd); | ||
809 | if (retval) | ||
810 | goto failed_restart; | ||
797 | 811 | ||
798 | xhci_dbg(xhci, "Start the HCD\n"); | 812 | xhci_dbg(xhci, "Start the secondary HCD\n"); |
799 | retval = xhci_run(hcd); | 813 | retval = xhci_run(secondary_hcd); |
800 | if (!retval) | 814 | if (!retval) |
801 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | 815 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
816 | failed_restart: | ||
802 | hcd->state = HC_STATE_SUSPENDED; | 817 | hcd->state = HC_STATE_SUSPENDED; |
803 | return retval; | 818 | return retval; |
804 | } | 819 | } |