[PATCH 1/1] usb: xhci: apply XHCI_AVOID_BEI quirk to Intel ValleyView and LynxPoint LP

From: Lu Baolu
Date: Wed Mar 11 2015 - 21:39:15 EST


When a device with an isochronous endpoint is plugged into the Intel
xHCI host controller, and the driver submits multiple frames per URB,
the xHCI driver will set the Block Event Interrupt (BEI) flag on all
but the last TD for the URB. This causes the host controller to place
an event on the event ring, but not send an interrupt. When the last
TD for the URB completes, BEI is cleared, and we get an interrupt for
the whole URB.

However, under some Intel xHCI host controllers like ValleyView and
Lynx Point LP, if the event ring is full of events from transfers with
BEI set, a "Event Ring is Full" event will be posted to the last entry
of the event ring, but no interrupt is generated. Host will cease all
transfer and command executions and wait until software completes
handling the pending events in event ring. That means xHC stops but
event of "event ring is full" is not notified. As the result, the xHC
looks like dead to user.

The patch is to apply XHCI_AVOID_BEI to Intel VallyView and Lynx Point
LP devices. And it should be backported to kernels as old as 3.0, that
contains the commit 69e848c2090a ("Intel xhci: Support EHCI/xHCI port
switching.")

Signed-off-by: Lu Baolu <baolu.lu@xxxxxxxxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx
---
drivers/usb/host/xhci-pci.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index fd53c9e..5aa4893 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -40,6 +40,7 @@
#define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI 0x22b5
#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI 0xa12f
#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI 0x9d2f
+#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_XHCI 0x0f35

static const char hcd_name[] = "xhci_hcd";

@@ -135,6 +136,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) {
xhci->quirks |= XHCI_SPURIOUS_REBOOT;
+ xhci->quirks |= XHCI_AVOID_BEI;
}
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
(pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
@@ -142,6 +144,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI)) {
xhci->quirks |= XHCI_PME_STUCK_QUIRK;
}
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+ pdev->device == PCI_DEVICE_ID_INTEL_VALLEYVIEW_XHCI)
+ xhci->quirks |= XHCI_AVOID_BEI;
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
pdev->device == PCI_DEVICE_ID_EJ168) {
xhci->quirks |= XHCI_RESET_ON_RESUME;
--
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/