diff options
Diffstat (limited to 'drivers/usb/host/xhci-ring.c')
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 4142c04b5adf..b4fab00105d4 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -1092,7 +1092,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
1092 | td->urb->actual_length = | 1092 | td->urb->actual_length = |
1093 | td->urb->transfer_buffer_length - | 1093 | td->urb->transfer_buffer_length - |
1094 | TRB_LEN(event->transfer_len); | 1094 | TRB_LEN(event->transfer_len); |
1095 | if (td->urb->actual_length < 0) { | 1095 | if (td->urb->transfer_buffer_length < |
1096 | td->urb->actual_length) { | ||
1096 | xhci_warn(xhci, "HC gave bad length " | 1097 | xhci_warn(xhci, "HC gave bad length " |
1097 | "of %d bytes left\n", | 1098 | "of %d bytes left\n", |
1098 | TRB_LEN(event->transfer_len)); | 1099 | TRB_LEN(event->transfer_len)); |
@@ -1167,6 +1168,20 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
1167 | td_cleanup: | 1168 | td_cleanup: |
1168 | /* Clean up the endpoint's TD list */ | 1169 | /* Clean up the endpoint's TD list */ |
1169 | urb = td->urb; | 1170 | urb = td->urb; |
1171 | /* Do one last check of the actual transfer length. | ||
1172 | * If the host controller said we transferred more data than | ||
1173 | * the buffer length, urb->actual_length will be a very big | ||
1174 | * number (since it's unsigned). Play it safe and say we didn't | ||
1175 | * transfer anything. | ||
1176 | */ | ||
1177 | if (urb->actual_length > urb->transfer_buffer_length) { | ||
1178 | xhci_warn(xhci, "URB transfer length is wrong, " | ||
1179 | "xHC issue? req. len = %u, " | ||
1180 | "act. len = %u\n", | ||
1181 | urb->transfer_buffer_length, | ||
1182 | urb->actual_length); | ||
1183 | urb->actual_length = 0; | ||
1184 | } | ||
1170 | list_del(&td->td_list); | 1185 | list_del(&td->td_list); |
1171 | /* Was this TD slated to be cancelled but completed anyway? */ | 1186 | /* Was this TD slated to be cancelled but completed anyway? */ |
1172 | if (!list_empty(&td->cancelled_td_list)) { | 1187 | if (!list_empty(&td->cancelled_td_list)) { |