Commit a6835090 authored by Mathias Nyman's avatar Mathias Nyman Committed by Greg Kroah-Hartman

Revert "xhci: don't finish a TD if we get a short-transfer event mid TD"

This reverts commit e210c422 ("xhci: don't finish a TD if we get a
short transfer event mid TD")

Turns out that most host controllers do not follow the xHCI specs and never
send the second event for the last TRB in the TD if there was a short event
mid-TD.

Returning the URB directly after the first short-transfer event is far
better than never returning the URB. (class drivers usually timeout
after 30sec). For the hosts that do send the second event we will go
back to treating it as misplaced event and print an error message for it.

The origial patch was sent to stable kernels and needs to be reverted from
there as well

Cc: stable@vger.kernel.org
Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 36f90b0a
...@@ -2193,10 +2193,6 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, ...@@ -2193,10 +2193,6 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
} }
/* Fast path - was this the last TRB in the TD for this URB? */ /* Fast path - was this the last TRB in the TD for this URB? */
} else if (event_trb == td->last_trb) { } else if (event_trb == td->last_trb) {
if (td->urb_length_set && trb_comp_code == COMP_SHORT_TX)
return finish_td(xhci, td, event_trb, event, ep,
status, false);
if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
td->urb->actual_length = td->urb->actual_length =
td->urb->transfer_buffer_length - td->urb->transfer_buffer_length -
...@@ -2248,12 +2244,6 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, ...@@ -2248,12 +2244,6 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
td->urb->actual_length += td->urb->actual_length +=
TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
if (trb_comp_code == COMP_SHORT_TX) {
xhci_dbg(xhci, "mid bulk/intr SP, wait for last TRB event\n");
td->urb_length_set = true;
return 0;
}
} }
return finish_td(xhci, td, event_trb, event, ep, status, false); return finish_td(xhci, td, event_trb, event, ep, status, false);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment