summaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/xhci-pci.c')
-rw-r--r--drivers/usb/host/xhci-pci.c55
1 files changed, 43 insertions, 12 deletions
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index f00cb203fae..b8dffd59eb2 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -25,6 +25,7 @@
#include <linux/module.h>
#include "xhci.h"
+#include "xhci-trace.h"
/* Device for a quirk */
#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
@@ -34,6 +35,9 @@
#define PCI_VENDOR_ID_ETRON 0x1b6f
#define PCI_DEVICE_ID_ASROCK_P67 0x7023
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
+
static const char hcd_name[] = "xhci_hcd";
/* called after powerup, by probe or system-pm "wakeup" */
@@ -64,16 +68,26 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
pdev->revision == 0x0) {
xhci->quirks |= XHCI_RESET_EP_QUIRK;
- xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure"
- " endpoint cmd after reset endpoint\n");
+ xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
+ "QUIRK: Fresco Logic xHC needs configure"
+ " endpoint cmd after reset endpoint");
+ }
+ if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
+ pdev->revision == 0x4) {
+ xhci->quirks |= XHCI_SLOW_SUSPEND;
+ xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
+ "QUIRK: Fresco Logic xHC revision %u"
+ "must be suspended extra slowly",
+ pdev->revision);
}
/* Fresco Logic confirms: all revisions of this chip do not
* support MSI, even though some of them claim to in their PCI
* capabilities.
*/
xhci->quirks |= XHCI_BROKEN_MSI;
- xhci_dbg(xhci, "QUIRK: Fresco Logic revision %u "
- "has broken MSI implementation\n",
+ xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
+ "QUIRK: Fresco Logic revision %u "
+ "has broken MSI implementation",
pdev->revision);
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
}
@@ -107,10 +121,20 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
xhci->quirks |= XHCI_SPURIOUS_REBOOT;
xhci->quirks |= XHCI_AVOID_BEI;
}
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+ (pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI ||
+ pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI)) {
+ /* Workaround for occasional spurious wakeups from S5 (or
+ * any other sleep) on Haswell machines with LPT and LPT-LP
+ * with the new Intel BIOS
+ */
+ xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
+ }
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
xhci->quirks |= XHCI_RESET_ON_RESUME;
- xhci_dbg(xhci, "QUIRK: Resetting on resume\n");
+ xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
+ "QUIRK: Resetting on resume");
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
}
if (pdev->vendor == PCI_VENDOR_ID_VIA)
@@ -213,6 +237,11 @@ static void xhci_pci_remove(struct pci_dev *dev)
usb_put_hcd(xhci->shared_hcd);
}
usb_hcd_pci_remove(dev);
+
+ /* Workaround for spurious wakeups at shutdown with HSW */
+ if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
+ pci_set_power_state(dev, PCI_D3hot);
+
kfree(xhci);
}
@@ -249,13 +278,15 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
* 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.
+ * It should not matter whether the EHCI or xHCI controller is
+ * resumed first. It's enough to do the switchover in xHCI because
+ * USB core won't notice anything as the hub driver doesn't start
+ * running again until after all the devices (including both EHCI and
+ * xHCI host controllers) have been resumed.
*/
- if (usb_is_intel_switchable_xhci(pdev))
- usb_enable_xhci_ports(pdev);
+
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL)
+ usb_enable_intel_xhci_ports(pdev);
retval = xhci_resume(xhci, hibernated);
return retval;
@@ -345,7 +376,7 @@ static struct pci_driver xhci_pci_driver = {
/* suspend and resume implemented later */
.shutdown = usb_hcd_pci_shutdown,
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
.driver = {
.pm = &usb_hcd_pci_pm_ops
},