Skip to content

Commit

Permalink
xhci: handle no ping response error properly
Browse files Browse the repository at this point in the history
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 <stable@vger.kernel.org>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Mathias Nyman authored and Greg Kroah-Hartman committed Oct 17, 2015
1 parent e210c42 commit 3b4739b
Showing 1 changed file with 15 additions and 5 deletions.
20 changes: 15 additions & 5 deletions drivers/usb/host/xhci-ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -2284,6 +2284,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
u32 trb_comp_code;
int ret = 0;
int td_num = 0;
bool handling_skipped_tds = false;

slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
xdev = xhci->devs[slot_id];
Expand Down Expand Up @@ -2420,6 +2421,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
ep->skip = true;
xhci_dbg(xhci, "Miss service interval error, set skip flag\n");
goto cleanup;
case COMP_PING_ERR:
ep->skip = true;
xhci_dbg(xhci, "No Ping response error, Skip one Isoc TD\n");
goto cleanup;
default:
if (xhci_is_vendor_info_code(xhci, trb_comp_code)) {
status = 0;
Expand Down Expand Up @@ -2556,13 +2561,18 @@ static int handle_tx_event(struct xhci_hcd *xhci,
ep, &status);

cleanup:


handling_skipped_tds = ep->skip &&
trb_comp_code != COMP_MISSED_INT &&
trb_comp_code != COMP_PING_ERR;

/*
* Do not update event ring dequeue pointer if ep->skip is set.
* Will roll back to continue process missed tds.
* Do not update event ring dequeue pointer if we're in a loop
* processing missed tds.
*/
if (trb_comp_code == COMP_MISSED_INT || !ep->skip) {
if (!handling_skipped_tds)
inc_deq(xhci, xhci->event_ring);
}

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

return 0;
}
Expand Down

0 comments on commit 3b4739b

Please sign in to comment.