aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-10-23 18:52:59 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-10-23 18:52:59 -0400
commit018155365dccecd9ea9f26e1b26fb0f960c1ee32 (patch)
tree6fbfd8f2fe22966118823845a45b8cc26076def8
parentdd5ae6818ccd4ab0aa6f7d84e88f60a48af0fb52 (diff)
parentfd7cd061adcf5f7503515ba52b6a724642a839c8 (diff)
Merge tag 'usb-4.3-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB fixes from Greg KH: "Here are three xhci driver fixes for reported issues for 4.3-rc7 All have been in linux-next for a while with no problems" * tag 'usb-4.3-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: xhci: Add spurious wakeup quirk for LynxPoint-LP controllers xhci: handle no ping response error properly xhci: don't finish a TD if we get a short transfer event mid TD
-rw-r--r--drivers/usb/host/xhci-pci.c1
-rw-r--r--drivers/usb/host/xhci-ring.c30
2 files changed, 26 insertions, 5 deletions
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index c79d33676672..c47d3e480586 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -147,6 +147,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
147 if (pdev->vendor == PCI_VENDOR_ID_INTEL && 147 if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
148 pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) { 148 pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) {
149 xhci->quirks |= XHCI_SPURIOUS_REBOOT; 149 xhci->quirks |= XHCI_SPURIOUS_REBOOT;
150 xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
150 } 151 }
151 if (pdev->vendor == PCI_VENDOR_ID_INTEL && 152 if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
152 (pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI || 153 (pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 43291f93afeb..97ffe3997273 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2191,6 +2191,10 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
2191 } 2191 }
2192 /* Fast path - was this the last TRB in the TD for this URB? */ 2192 /* Fast path - was this the last TRB in the TD for this URB? */
2193 } else if (event_trb == td->last_trb) { 2193 } else if (event_trb == td->last_trb) {
2194 if (td->urb_length_set && trb_comp_code == COMP_SHORT_TX)
2195 return finish_td(xhci, td, event_trb, event, ep,
2196 status, false);
2197
2194 if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { 2198 if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
2195 td->urb->actual_length = 2199 td->urb->actual_length =
2196 td->urb->transfer_buffer_length - 2200 td->urb->transfer_buffer_length -
@@ -2242,6 +2246,12 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
2242 td->urb->actual_length += 2246 td->urb->actual_length +=
2243 TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - 2247 TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
2244 EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); 2248 EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
2249
2250 if (trb_comp_code == COMP_SHORT_TX) {
2251 xhci_dbg(xhci, "mid bulk/intr SP, wait for last TRB event\n");
2252 td->urb_length_set = true;
2253 return 0;
2254 }
2245 } 2255 }
2246 2256
2247 return finish_td(xhci, td, event_trb, event, ep, status, false); 2257 return finish_td(xhci, td, event_trb, event, ep, status, false);
@@ -2274,6 +2284,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
2274 u32 trb_comp_code; 2284 u32 trb_comp_code;
2275 int ret = 0; 2285 int ret = 0;
2276 int td_num = 0; 2286 int td_num = 0;
2287 bool handling_skipped_tds = false;
2277 2288
2278 slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); 2289 slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
2279 xdev = xhci->devs[slot_id]; 2290 xdev = xhci->devs[slot_id];
@@ -2410,6 +2421,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
2410 ep->skip = true; 2421 ep->skip = true;
2411 xhci_dbg(xhci, "Miss service interval error, set skip flag\n"); 2422 xhci_dbg(xhci, "Miss service interval error, set skip flag\n");
2412 goto cleanup; 2423 goto cleanup;
2424 case COMP_PING_ERR:
2425 ep->skip = true;
2426 xhci_dbg(xhci, "No Ping response error, Skip one Isoc TD\n");
2427 goto cleanup;
2413 default: 2428 default:
2414 if (xhci_is_vendor_info_code(xhci, trb_comp_code)) { 2429 if (xhci_is_vendor_info_code(xhci, trb_comp_code)) {
2415 status = 0; 2430 status = 0;
@@ -2546,13 +2561,18 @@ static int handle_tx_event(struct xhci_hcd *xhci,
2546 ep, &status); 2561 ep, &status);
2547 2562
2548cleanup: 2563cleanup:
2564
2565
2566 handling_skipped_tds = ep->skip &&
2567 trb_comp_code != COMP_MISSED_INT &&
2568 trb_comp_code != COMP_PING_ERR;
2569
2549 /* 2570 /*
2550 * Do not update event ring dequeue pointer if ep->skip is set. 2571 * Do not update event ring dequeue pointer if we're in a loop
2551 * Will roll back to continue process missed tds. 2572 * processing missed tds.
2552 */ 2573 */
2553 if (trb_comp_code == COMP_MISSED_INT || !ep->skip) { 2574 if (!handling_skipped_tds)
2554 inc_deq(xhci, xhci->event_ring); 2575 inc_deq(xhci, xhci->event_ring);
2555 }
2556 2576
2557 if (ret) { 2577 if (ret) {
2558 urb = td->urb; 2578 urb = td->urb;
@@ -2587,7 +2607,7 @@ cleanup:
2587 * Process them as short transfer until reach the td pointed by 2607 * Process them as short transfer until reach the td pointed by
2588 * the event. 2608 * the event.
2589 */ 2609 */
2590 } while (ep->skip && trb_comp_code != COMP_MISSED_INT); 2610 } while (handling_skipped_tds);
2591 2611
2592 return 0; 2612 return 0;
2593} 2613}