Skip to content

Commit 638298d

Browse files
tiwaiSarah Sharp
authored andcommitted
xhci: Fix spurious wakeups after S5 on Haswell
Haswell LynxPoint and LynxPoint-LP with the recent Intel BIOS show mysterious wakeups after shutdown occasionally. After discussing with BIOS engineers, they explained that the new BIOS expects that the wakeup sources are cleared and set to D3 for all wakeup devices when the system is going to sleep or power off, but the current xhci driver doesn't do this properly (partly intentionally). This patch introduces a new quirk, XHCI_SPURIOUS_WAKEUP, for fixing the spurious wakeups at S5 by calling xhci_reset() in the xhci shutdown ops as done in xhci_stop(), and setting the device to PCI D3 at shutdown and remove ops. The PCI D3 call is based on the initial fix patch by Oliver Neukum. [Note: Sarah changed the quirk name from XHCI_HSW_SPURIOUS_WAKEUP to XHCI_SPURIOUS_WAKEUP, since none of the other quirks have system names in them. Sarah also fixed a collision with a quirk submitted around the same time, by changing the xhci->quirks bit from 17 to 18.] This patch should be backported to kernels as old as 3.0, that contain the commit 1c12443 "xhci: Add Lynx Point to list of Intel switchable hosts." Cc: Oliver Neukum <[email protected]> Signed-off-by: Takashi Iwai <[email protected]> Signed-off-by: Sarah Sharp <[email protected]> Cc: [email protected]
1 parent e459933 commit 638298d

File tree

3 files changed

+25
-0
lines changed

3 files changed

+25
-0
lines changed

drivers/usb/host/xhci-pci.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
#define PCI_VENDOR_ID_ETRON 0x1b6f
3636
#define PCI_DEVICE_ID_ASROCK_P67 0x7023
3737

38+
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31
39+
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
40+
3841
static const char hcd_name[] = "xhci_hcd";
3942

4043
/* called after powerup, by probe or system-pm "wakeup" */
@@ -118,6 +121,15 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
118121
xhci->quirks |= XHCI_SPURIOUS_REBOOT;
119122
xhci->quirks |= XHCI_AVOID_BEI;
120123
}
124+
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
125+
(pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI ||
126+
pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI)) {
127+
/* Workaround for occasional spurious wakeups from S5 (or
128+
* any other sleep) on Haswell machines with LPT and LPT-LP
129+
* with the new Intel BIOS
130+
*/
131+
xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
132+
}
121133
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
122134
pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
123135
xhci->quirks |= XHCI_RESET_ON_RESUME;
@@ -225,6 +237,11 @@ static void xhci_pci_remove(struct pci_dev *dev)
225237
usb_put_hcd(xhci->shared_hcd);
226238
}
227239
usb_hcd_pci_remove(dev);
240+
241+
/* Workaround for spurious wakeups at shutdown with HSW */
242+
if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
243+
pci_set_power_state(dev, PCI_D3hot);
244+
228245
kfree(xhci);
229246
}
230247

drivers/usb/host/xhci.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,13 +730,20 @@ void xhci_shutdown(struct usb_hcd *hcd)
730730

731731
spin_lock_irq(&xhci->lock);
732732
xhci_halt(xhci);
733+
/* Workaround for spurious wakeups at shutdown with HSW */
734+
if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
735+
xhci_reset(xhci);
733736
spin_unlock_irq(&xhci->lock);
734737

735738
xhci_cleanup_msix(xhci);
736739

737740
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
738741
"xhci_shutdown completed - status = %x",
739742
xhci_readl(xhci, &xhci->op_regs->status));
743+
744+
/* Yet another workaround for spurious wakeups at shutdown with HSW */
745+
if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
746+
pci_set_power_state(to_pci_dev(hcd->self.controller), PCI_D3hot);
740747
}
741748

742749
#ifdef CONFIG_PM

drivers/usb/host/xhci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1549,6 +1549,7 @@ struct xhci_hcd {
15491549
#define XHCI_AVOID_BEI (1 << 15)
15501550
#define XHCI_PLAT (1 << 16)
15511551
#define XHCI_SLOW_SUSPEND (1 << 17)
1552+
#define XHCI_SPURIOUS_WAKEUP (1 << 18)
15521553
unsigned int num_active_eps;
15531554
unsigned int limit_active_eps;
15541555
/* There are two roothubs to keep track of bus suspend info for */

0 commit comments

Comments
 (0)