aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2011-05-25 13:43:56 -0400
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2011-05-27 15:08:13 -0400
commitad808333d8201d53075a11bc8dd83b81f3d68f0b (patch)
tree40f3a11f028175f61cce14088a0f93ebd68c4b60 /drivers/usb/host
parent69e848c2090aebba5698a1620604c7dccb448684 (diff)
Intel xhci: Ignore spurious successful event.
The xHCI host controller in the Panther Point chipset sometimes produces spurious events on the event ring. If it receives a short packet, it first puts a Transfer Event with a short transfer completion code on the event ring. Then it puts a Transfer Event with a successful completion code on the ring for the same TD. The xHCI driver correctly processes the short transfer completion code, gives the URB back to the driver, and then prints a warning in dmesg about the spurious event. These warning messages really fill up dmesg when an HD webcam is plugged into xHCI. This spurious successful event behavior isn't technically disallowed by the xHCI specification, so make the xHCI driver just ignore the spurious completion event. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/xhci-pci.c4
-rw-r--r--drivers/usb/host/xhci-ring.c14
-rw-r--r--drivers/usb/host/xhci.h2
3 files changed, 20 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index faf039ac6573..eafd17fae949 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -118,6 +118,10 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
118 /* AMD PLL quirk */ 118 /* AMD PLL quirk */
119 if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info()) 119 if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info())
120 xhci->quirks |= XHCI_AMD_PLL_FIX; 120 xhci->quirks |= XHCI_AMD_PLL_FIX;
121 if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
122 pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI) {
123 xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
124 }
121 125
122 /* Make sure the HC is halted. */ 126 /* Make sure the HC is halted. */
123 retval = xhci_halt(xhci); 127 retval = xhci_halt(xhci);
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index d1498c03c4cb..56f6c584c651 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2061,6 +2061,16 @@ static int handle_tx_event(struct xhci_hcd *xhci,
2061 if (!event_seg) { 2061 if (!event_seg) {
2062 if (!ep->skip || 2062 if (!ep->skip ||
2063 !usb_endpoint_xfer_isoc(&td->urb->ep->desc)) { 2063 !usb_endpoint_xfer_isoc(&td->urb->ep->desc)) {
2064 /* Some host controllers give a spurious
2065 * successful event after a short transfer.
2066 * Ignore it.
2067 */
2068 if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) &&
2069 ep_ring->last_td_was_short) {
2070 ep_ring->last_td_was_short = false;
2071 ret = 0;
2072 goto cleanup;
2073 }
2064 /* HC is busted, give up! */ 2074 /* HC is busted, give up! */
2065 xhci_err(xhci, 2075 xhci_err(xhci,
2066 "ERROR Transfer event TRB DMA ptr not " 2076 "ERROR Transfer event TRB DMA ptr not "
@@ -2071,6 +2081,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
2071 ret = skip_isoc_td(xhci, td, event, ep, &status); 2081 ret = skip_isoc_td(xhci, td, event, ep, &status);
2072 goto cleanup; 2082 goto cleanup;
2073 } 2083 }
2084 if (trb_comp_code == COMP_SHORT_TX)
2085 ep_ring->last_td_was_short = true;
2086 else
2087 ep_ring->last_td_was_short = false;
2074 2088
2075 if (ep->skip) { 2089 if (ep->skip) {
2076 xhci_dbg(xhci, "Found td. Clear skip flag.\n"); 2090 xhci_dbg(xhci, "Found td. Clear skip flag.\n");
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 0772a8cfea23..5cfeb8614b87 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1123,6 +1123,7 @@ struct xhci_ring {
1123 */ 1123 */
1124 u32 cycle_state; 1124 u32 cycle_state;
1125 unsigned int stream_id; 1125 unsigned int stream_id;
1126 bool last_td_was_short;
1126}; 1127};
1127 1128
1128struct xhci_erst_entry { 1129struct xhci_erst_entry {
@@ -1290,6 +1291,7 @@ struct xhci_hcd {
1290#define XHCI_RESET_EP_QUIRK (1 << 1) 1291#define XHCI_RESET_EP_QUIRK (1 << 1)
1291#define XHCI_NEC_HOST (1 << 2) 1292#define XHCI_NEC_HOST (1 << 2)
1292#define XHCI_AMD_PLL_FIX (1 << 3) 1293#define XHCI_AMD_PLL_FIX (1 << 3)
1294#define XHCI_SPURIOUS_SUCCESS (1 << 4)
1293 /* There are two roothubs to keep track of bus suspend info for */ 1295 /* There are two roothubs to keep track of bus suspend info for */
1294 struct xhci_bus_state bus_state[2]; 1296 struct xhci_bus_state bus_state[2];
1295 /* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */ 1297 /* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */