diff options
-rw-r--r-- | drivers/usb/host/ehci-q.c | 34 |
1 files changed, 16 insertions, 18 deletions
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 64942ec584c2..315c7c14aaa8 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -242,7 +242,8 @@ __acquires(ehci->lock) | |||
242 | if (unlikely(urb->unlinked)) { | 242 | if (unlikely(urb->unlinked)) { |
243 | COUNT(ehci->stats.unlink); | 243 | COUNT(ehci->stats.unlink); |
244 | } else { | 244 | } else { |
245 | if (likely(status == -EINPROGRESS)) | 245 | /* report non-error and short read status as zero */ |
246 | if (status == -EINPROGRESS || status == -EREMOTEIO) | ||
246 | status = 0; | 247 | status = 0; |
247 | COUNT(ehci->stats.complete); | 248 | COUNT(ehci->stats.complete); |
248 | } | 249 | } |
@@ -283,7 +284,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
283 | int last_status = -EINPROGRESS; | 284 | int last_status = -EINPROGRESS; |
284 | int stopped; | 285 | int stopped; |
285 | unsigned count = 0; | 286 | unsigned count = 0; |
286 | int do_status = 0; | ||
287 | u8 state; | 287 | u8 state; |
288 | u32 halt = HALT_BIT(ehci); | 288 | u32 halt = HALT_BIT(ehci); |
289 | 289 | ||
@@ -309,7 +309,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
309 | struct ehci_qtd *qtd; | 309 | struct ehci_qtd *qtd; |
310 | struct urb *urb; | 310 | struct urb *urb; |
311 | u32 token = 0; | 311 | u32 token = 0; |
312 | int qtd_status; | ||
313 | 312 | ||
314 | qtd = list_entry (entry, struct ehci_qtd, qtd_list); | 313 | qtd = list_entry (entry, struct ehci_qtd, qtd_list); |
315 | urb = qtd->urb; | 314 | urb = qtd->urb; |
@@ -377,13 +376,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
377 | else if (last_status == -EINPROGRESS && !urb->unlinked) | 376 | else if (last_status == -EINPROGRESS && !urb->unlinked) |
378 | continue; | 377 | continue; |
379 | 378 | ||
380 | /* issue status after short control reads */ | ||
381 | if (unlikely (do_status != 0) | ||
382 | && QTD_PID (token) == 0 /* OUT */) { | ||
383 | do_status = 0; | ||
384 | continue; | ||
385 | } | ||
386 | |||
387 | /* qh unlinked; token in overlay may be most current */ | 379 | /* qh unlinked; token in overlay may be most current */ |
388 | if (state == QH_STATE_IDLE | 380 | if (state == QH_STATE_IDLE |
389 | && cpu_to_hc32(ehci, qtd->qtd_dma) | 381 | && cpu_to_hc32(ehci, qtd->qtd_dma) |
@@ -401,15 +393,21 @@ halt: | |||
401 | } | 393 | } |
402 | } | 394 | } |
403 | 395 | ||
404 | /* remove it from the queue */ | 396 | /* unless we already know the urb's status, collect qtd status |
405 | qtd_status = qtd_copy_status(ehci, urb, qtd->length, token); | 397 | * and update count of bytes transferred. in common short read |
406 | if (unlikely(qtd_status == -EREMOTEIO)) { | 398 | * cases with only one data qtd (including control transfers), |
407 | do_status = (!urb->unlinked && | 399 | * queue processing won't halt. but with two or more qtds (for |
408 | usb_pipecontrol(urb->pipe)); | 400 | * example, with a 32 KB transfer), when the first qtd gets a |
409 | qtd_status = 0; | 401 | * short read the second must be removed by hand. |
402 | */ | ||
403 | if (last_status == -EINPROGRESS) { | ||
404 | last_status = qtd_copy_status(ehci, urb, | ||
405 | qtd->length, token); | ||
406 | if (last_status == -EREMOTEIO | ||
407 | && (qtd->hw_alt_next | ||
408 | & EHCI_LIST_END(ehci))) | ||
409 | last_status = -EINPROGRESS; | ||
410 | } | 410 | } |
411 | if (likely(last_status == -EINPROGRESS)) | ||
412 | last_status = qtd_status; | ||
413 | 411 | ||
414 | /* if we're removing something not at the queue head, | 412 | /* if we're removing something not at the queue head, |
415 | * patch the hardware queue pointer. | 413 | * patch the hardware queue pointer. |