Re: [PATCH v2] xhci: Fix spurious wakeups after S5 on Haswell

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



At Tue, 10 Sep 2013 08:38:50 -0700,
Sarah Sharp wrote:
> 
> On Tue, Sep 10, 2013 at 08:24:51AM +0200, Takashi Iwai wrote:
> > 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_HSW_SPURIOUS_WAKEUP, for
> > fixing the spurious wakeups at S5 by calling xhci_stop() instead of
> > its stripped version in the xhci shutdown ops, and setting the device
> > to PCI D3 at shutdown and remove ops.
> 
> Which part of xhci_stop() causes the wakeups to cease?  Is it the reset
> of the host, or the disabling of the event ring interrupts, or both?
> I'd like to understand exactly what caused the BIOS to wake up the
> system.

I'd love to understand what the heck it is, too :)

Currently we're in rush for band-aiding this problem, so had no time
for the detailed analysis.  We'll check it soon later.

> Comments below.
> 
> > The PCI D3 call is based on the initial fix patch by Oliver Neukum.
> > 
> > Cc: Oliver Neukum <oneukum@xxxxxxx>
> > Signed-off-by: Takashi Iwai <tiwai@xxxxxxx>
> > ---
> > v1->v2: forgot to refresh the patch before submission, sorry.
> > 
> >  drivers/usb/host/xhci-pci.c | 14 ++++++++++++++
> >  drivers/usb/host/xhci.c     | 18 +++++++++++++-----
> >  drivers/usb/host/xhci.h     |  1 +
> >  include/linux/pci_ids.h     |  2 ++
> >  4 files changed, 30 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
> > index c2d4950..bfed043 100644
> > --- a/drivers/usb/host/xhci-pci.c
> > +++ b/drivers/usb/host/xhci-pci.c
> > @@ -110,6 +110,15 @@ 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_HSW_SPURIOUS_WAKEUP;
> > +	}
> >  	if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
> >  			pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
> >  		xhci->quirks |= XHCI_RESET_ON_RESUME;
> > @@ -217,6 +226,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_HSW_SPURIOUS_WAKEUP)
> > +		pci_set_power_state(dev, PCI_D3cold);
> > +
> 
> As far as I know, the LPT and LPT-LP hosts don't support D3cold.  Is
> there a particular reason you set the power state to D3cold here?

It can be D3hot, too, as far as I've tested.
The only requirement is the ACPI _PS3 call, as it seems.


thanks,

Takashi

> 
> Sarah Sharp
> 
> >  	kfree(xhci);
> >  }
> >  
> > diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
> > index 49b6edb..c6027ba 100644
> > --- a/drivers/usb/host/xhci.c
> > +++ b/drivers/usb/host/xhci.c
> > @@ -728,11 +728,19 @@ void xhci_shutdown(struct usb_hcd *hcd)
> >  	if (xhci->quirks & XHCI_SPURIOUS_REBOOT)
> >  		usb_disable_xhci_ports(to_pci_dev(hcd->self.controller));
> >  
> > -	spin_lock_irq(&xhci->lock);
> > -	xhci_halt(xhci);
> > -	spin_unlock_irq(&xhci->lock);
> > -
> > -	xhci_cleanup_msix(xhci);
> > +	if (xhci->quirks & XHCI_HSW_SPURIOUS_WAKEUP) {
> > +		/* Workaround for spurious wakeups at shutdown with HSW:
> > +		 * we must call xhci_stop() for clearing all wakeups, and
> > +		 * set the device to D3.
> > +		 */
> > +		xhci_stop(hcd);
> > +		pci_set_power_state(to_pci_dev(hcd->self.controller), PCI_D3cold);
> > +	} else {
> > +		spin_lock_irq(&xhci->lock);
> > +		xhci_halt(xhci);
> > +		spin_unlock_irq(&xhci->lock);
> > +		xhci_cleanup_msix(xhci);
> > +	}
> >  
> >  	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
> >  			"xhci_shutdown completed - status = %x",
> > diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
> > index 46aa148..d71386b 100644
> > --- a/drivers/usb/host/xhci.h
> > +++ b/drivers/usb/host/xhci.h
> > @@ -1538,6 +1538,7 @@ struct xhci_hcd {
> >  #define XHCI_COMP_MODE_QUIRK	(1 << 14)
> >  #define XHCI_AVOID_BEI		(1 << 15)
> >  #define XHCI_PLAT		(1 << 16)
> > +#define XHCI_HSW_SPURIOUS_WAKEUP (1 << 17)
> >  	unsigned int		num_active_eps;
> >  	unsigned int		limit_active_eps;
> >  	/* There are two roothubs to keep track of bus suspend info for */
> > diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
> > index bc95b2b..1b3ab7d 100644
> > --- a/include/linux/pci_ids.h
> > +++ b/include/linux/pci_ids.h
> > @@ -2860,7 +2860,9 @@
> >  #define PCI_DEVICE_ID_INTEL_82454NX     0x84cb
> >  #define PCI_DEVICE_ID_INTEL_84460GX	0x84ea
> >  #define PCI_DEVICE_ID_INTEL_IXP4XX	0x8500
> > +#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI	0x8c31
> >  #define PCI_DEVICE_ID_INTEL_IXP2800	0x9004
> > +#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI	0x9c31
> >  #define PCI_DEVICE_ID_INTEL_S21152BB	0xb152
> >  
> >  #define PCI_VENDOR_ID_SCALEMP		0x8686
> > -- 
> > 1.8.4
> > 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux