diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/host/xhci-pci.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 14 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 2 |
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 | ||
1128 | struct xhci_erst_entry { | 1129 | struct 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? */ |