return rc;
 }
 
+static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev)
+{
+       return pdev->class == PCI_CLASS_SERIAL_USB_EHCI &&
+               pdev->vendor == PCI_VENDOR_ID_INTEL &&
+               pdev->device == 0x1E26;
+}
+
+static void ehci_enable_xhci_companion(void)
+{
+       struct pci_dev          *companion = NULL;
+
+       /* The xHCI and EHCI controllers are not on the same PCI slot */
+       for_each_pci_dev(companion) {
+               if (!usb_is_intel_switchable_xhci(companion))
+                       continue;
+               usb_enable_xhci_ports(companion);
+               return;
+       }
+}
+
 static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
        struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
 
+       /* The BIOS on systems with the Intel Panther Point chipset may or may
+        * not support xHCI natively.  That means that during system resume, it
+        * may switch the ports back to EHCI so that users can use their
+        * keyboard to select a kernel from GRUB after resume from hibernate.
+        *
+        * The BIOS is supposed to remember whether the OS had xHCI ports
+        * enabled before resume, and switch the ports back to xHCI when the
+        * BIOS/OS semaphore is written, but we all know we can't trust BIOS
+        * writers.
+        *
+        * Unconditionally switch the ports back to xHCI after a system resume.
+        * We can't tell whether the EHCI or xHCI controller will be resumed
+        * first, so we have to do the port switchover in both drivers.  Writing
+        * a '1' to the port switchover registers should have no effect if the
+        * port was already switched over.
+        */
+       if (usb_is_intel_switchable_ehci(pdev))
+               ehci_enable_xhci_companion();
+
        // maybe restore FLADJ
 
        if (time_before(jiffies, ehci->next_statechange))
 
 #define        NB_PIF0_PWRDOWN_0       0x01100012
 #define        NB_PIF0_PWRDOWN_1       0x01100013
 
+#define USB_INTEL_XUSB2PR      0xD0
+#define USB_INTEL_USB3_PSSEN   0xD8
+
 static struct amd_chipset_info {
        struct pci_dev  *nb_dev;
        struct pci_dev  *smbus_dev;
        return -ETIMEDOUT;
 }
 
+bool usb_is_intel_switchable_xhci(struct pci_dev *pdev)
+{
+       return pdev->class == PCI_CLASS_SERIAL_USB_XHCI &&
+               pdev->vendor == PCI_VENDOR_ID_INTEL &&
+               pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI;
+}
+EXPORT_SYMBOL_GPL(usb_is_intel_switchable_xhci);
+
+/*
+ * Intel's Panther Point chipset has two host controllers (EHCI and xHCI) that
+ * share some number of ports.  These ports can be switched between either
+ * controller.  Not all of the ports under the EHCI host controller may be
+ * switchable.
+ *
+ * The ports should be switched over to xHCI before PCI probes for any device
+ * start.  This avoids active devices under EHCI being disconnected during the
+ * port switchover, which could cause loss of data on USB storage devices, or
+ * failed boot when the root file system is on a USB mass storage device and is
+ * enumerated under EHCI first.
+ *
+ * We write into the xHC's PCI configuration space in some Intel-specific
+ * registers to switch the ports over.  The USB 3.0 terminations and the USB
+ * 2.0 data wires are switched separately.  We want to enable the SuperSpeed
+ * terminations before switching the USB 2.0 wires over, so that USB 3.0
+ * devices connect at SuperSpeed, rather than at USB 2.0 speeds.
+ */
+void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
+{
+       u32             ports_available;
+
+       ports_available = 0xffffffff;
+       /* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable
+        * Register, to turn on SuperSpeed terminations for all
+        * available ports.
+        */
+       pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,
+                       cpu_to_le32(ports_available));
+
+       pci_read_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,
+                       &ports_available);
+       dev_dbg(&xhci_pdev->dev, "USB 3.0 ports that are now enabled "
+                       "under xHCI: 0x%x\n", ports_available);
+
+       ports_available = 0xffffffff;
+       /* Write XUSB2PR, the xHC USB 2.0 Port Routing Register, to
+        * switch the USB 2.0 power and data lines over to the xHCI
+        * host.
+        */
+       pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
+                       cpu_to_le32(ports_available));
+
+       pci_read_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
+                       &ports_available);
+       dev_dbg(&xhci_pdev->dev, "USB 2.0 ports that are now switched over "
+                       "to xHCI: 0x%x\n", ports_available);
+}
+EXPORT_SYMBOL_GPL(usb_enable_xhci_ports);
+
 /**
  * PCI Quirks for xHCI.
  *
        writel(XHCI_LEGACY_DISABLE_SMI,
                        base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
 
+       if (usb_is_intel_switchable_xhci(pdev))
+               usb_enable_xhci_ports(pdev);
 hc_init:
        op_reg_base = base + XHCI_HC_LENGTH(readl(base));
 
 
 void usb_amd_dev_put(void);
 void usb_amd_quirk_pll_disable(void);
 void usb_amd_quirk_pll_enable(void);
+bool usb_is_intel_switchable_xhci(struct pci_dev *pdev);
+void usb_enable_xhci_ports(struct pci_dev *xhci_pdev);
 #else
 static inline void usb_amd_quirk_pll_disable(void) {}
 static inline void usb_amd_quirk_pll_enable(void) {}
 
 static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
 {
        struct xhci_hcd         *xhci = hcd_to_xhci(hcd);
+       struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
        int                     retval = 0;
 
+       /* The BIOS on systems with the Intel Panther Point chipset may or may
+        * not support xHCI natively.  That means that during system resume, it
+        * may switch the ports back to EHCI so that users can use their
+        * keyboard to select a kernel from GRUB after resume from hibernate.
+        *
+        * The BIOS is supposed to remember whether the OS had xHCI ports
+        * enabled before resume, and switch the ports back to xHCI when the
+        * BIOS/OS semaphore is written, but we all know we can't trust BIOS
+        * writers.
+        *
+        * Unconditionally switch the ports back to xHCI after a system resume.
+        * We can't tell whether the EHCI or xHCI controller will be resumed
+        * first, so we have to do the port switchover in both drivers.  Writing
+        * a '1' to the port switchover registers should have no effect if the
+        * port was already switched over.
+        */
+       if (usb_is_intel_switchable_xhci(pdev))
+               usb_enable_xhci_ports(pdev);
+
        retval = xhci_resume(xhci, hibernated);
        return retval;
 }