Skip to content

Commit 3b4739b

Browse files
matnymangregkh
authored andcommitted
xhci: handle no ping response error properly
If a host fails to wake up a isochronous SuperSpeed device from U1/U2 in time for a isoch transfer it will generate a "No ping response error" Host will then move to the next transfer descriptor. Handle this case in the same way as missed service errors, tag the current TD as skipped and handle it on the next transfer event. Cc: stable <[email protected]> Signed-off-by: Mathias Nyman <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent e210c42 commit 3b4739b

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

drivers/usb/host/xhci-ring.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2284,6 +2284,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
22842284
u32 trb_comp_code;
22852285
int ret = 0;
22862286
int td_num = 0;
2287+
bool handling_skipped_tds = false;
22872288

22882289
slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
22892290
xdev = xhci->devs[slot_id];
@@ -2420,6 +2421,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
24202421
ep->skip = true;
24212422
xhci_dbg(xhci, "Miss service interval error, set skip flag\n");
24222423
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;
24232428
default:
24242429
if (xhci_is_vendor_info_code(xhci, trb_comp_code)) {
24252430
status = 0;
@@ -2556,13 +2561,18 @@ static int handle_tx_event(struct xhci_hcd *xhci,
25562561
ep, &status);
25572562

25582563
cleanup:
2564+
2565+
2566+
handling_skipped_tds = ep->skip &&
2567+
trb_comp_code != COMP_MISSED_INT &&
2568+
trb_comp_code != COMP_PING_ERR;
2569+
25592570
/*
2560-
* Do not update event ring dequeue pointer if ep->skip is set.
2561-
* Will roll back to continue process missed tds.
2571+
* Do not update event ring dequeue pointer if we're in a loop
2572+
* processing missed tds.
25622573
*/
2563-
if (trb_comp_code == COMP_MISSED_INT || !ep->skip) {
2574+
if (!handling_skipped_tds)
25642575
inc_deq(xhci, xhci->event_ring);
2565-
}
25662576

25672577
if (ret) {
25682578
urb = td->urb;
@@ -2597,7 +2607,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
25972607
* Process them as short transfer until reach the td pointed by
25982608
* the event.
25992609
*/
2600-
} while (ep->skip && trb_comp_code != COMP_MISSED_INT);
2610+
} while (handling_skipped_tds);
26012611

26022612
return 0;
26032613
}

0 commit comments

Comments
 (0)