diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 588686fca471..5dd3b1fd71c0 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -892,15 +892,23 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
892 | if (event_trb != ep_ring->dequeue) { | 892 | if (event_trb != ep_ring->dequeue) { |
893 | /* The event was for the status stage */ | 893 | /* The event was for the status stage */ |
894 | if (event_trb == td->last_trb) { | 894 | if (event_trb == td->last_trb) { |
895 | td->urb->actual_length = | 895 | /* Did we already see a short data stage? */ |
896 | td->urb->transfer_buffer_length; | 896 | if (td->urb->actual_length != 0) |
897 | status = -EREMOTEIO; | ||
898 | else | ||
899 | td->urb->actual_length = | ||
900 | td->urb->transfer_buffer_length; | ||
897 | } else { | 901 | } else { |
898 | /* Maybe the event was for the data stage? */ | 902 | /* Maybe the event was for the data stage? */ |
899 | if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL) | 903 | if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL) { |
900 | /* We didn't stop on a link TRB in the middle */ | 904 | /* We didn't stop on a link TRB in the middle */ |
901 | td->urb->actual_length = | 905 | td->urb->actual_length = |
902 | td->urb->transfer_buffer_length - | 906 | td->urb->transfer_buffer_length - |
903 | TRB_LEN(event->transfer_len); | 907 | TRB_LEN(event->transfer_len); |
908 | xhci_dbg(xhci, "Waiting for status stage event\n"); | ||
909 | urb = NULL; | ||
910 | goto cleanup; | ||
911 | } | ||
904 | } | 912 | } |
905 | } | 913 | } |
906 | } else { | 914 | } else { |