|
@@ -1787,8 +1787,12 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|
|
/* handle completion code */
|
|
|
switch (trb_comp_code) {
|
|
|
case COMP_SUCCESS:
|
|
|
- frame->status = 0;
|
|
|
- break;
|
|
|
+ if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
|
|
|
+ frame->status = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if ((xhci->quirks & XHCI_TRUST_TX_LENGTH))
|
|
|
+ trb_comp_code = COMP_SHORT_TX;
|
|
|
case COMP_SHORT_TX:
|
|
|
frame->status = td->urb->transfer_flags & URB_SHORT_NOT_OK ?
|
|
|
-EREMOTEIO : 0;
|
|
@@ -1885,13 +1889,16 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|
|
switch (trb_comp_code) {
|
|
|
case COMP_SUCCESS:
|
|
|
/* Double check that the HW transferred everything. */
|
|
|
- if (event_trb != td->last_trb) {
|
|
|
+ if (event_trb != td->last_trb ||
|
|
|
+ TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
|
|
|
xhci_warn(xhci, "WARN Successful completion "
|
|
|
"on short TX\n");
|
|
|
if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
|
|
|
*status = -EREMOTEIO;
|
|
|
else
|
|
|
*status = 0;
|
|
|
+ if ((xhci->quirks & XHCI_TRUST_TX_LENGTH))
|
|
|
+ trb_comp_code = COMP_SHORT_TX;
|
|
|
} else {
|
|
|
*status = 0;
|
|
|
}
|
|
@@ -2050,6 +2057,13 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
|
|
* transfer type
|
|
|
*/
|
|
|
case COMP_SUCCESS:
|
|
|
+ if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
|
|
|
+ break;
|
|
|
+ if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
|
|
|
+ trb_comp_code = COMP_SHORT_TX;
|
|
|
+ else
|
|
|
+ xhci_warn(xhci, "WARN Successful completion on short TX: "
|
|
|
+ "needs XHCI_TRUST_TX_LENGTH quirk?\n");
|
|
|
case COMP_SHORT_TX:
|
|
|
break;
|
|
|
case COMP_STOP:
|