diff options
| author | David S. Miller <davem@davemloft.net> | 2009-03-27 20:19:16 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2009-03-27 20:19:16 -0400 |
| commit | a83398570e17af6bb81eb94f4f5dd356bd2828d8 (patch) | |
| tree | 5b5c7c3a56898485479291b7c964a1f3887d469c /drivers/usb/host/ehci-q.c | |
| parent | f9384d41c02408dd404aa64d66d0ef38adcf6479 (diff) | |
| parent | 0b4d569de222452bcb55a4a536ade6cf4d8d1e30 (diff) | |
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Diffstat (limited to 'drivers/usb/host/ehci-q.c')
| -rw-r--r-- | drivers/usb/host/ehci-q.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index ecc9b66c03cd..1976b1b3778c 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
| @@ -333,12 +333,40 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
| 333 | token = hc32_to_cpu(ehci, qtd->hw_token); | 333 | token = hc32_to_cpu(ehci, qtd->hw_token); |
| 334 | 334 | ||
| 335 | /* always clean up qtds the hc de-activated */ | 335 | /* always clean up qtds the hc de-activated */ |
| 336 | retry_xacterr: | ||
| 336 | if ((token & QTD_STS_ACTIVE) == 0) { | 337 | if ((token & QTD_STS_ACTIVE) == 0) { |
| 337 | 338 | ||
| 338 | /* on STALL, error, and short reads this urb must | 339 | /* on STALL, error, and short reads this urb must |
| 339 | * complete and all its qtds must be recycled. | 340 | * complete and all its qtds must be recycled. |
| 340 | */ | 341 | */ |
| 341 | if ((token & QTD_STS_HALT) != 0) { | 342 | if ((token & QTD_STS_HALT) != 0) { |
| 343 | |||
| 344 | /* retry transaction errors until we | ||
| 345 | * reach the software xacterr limit | ||
| 346 | */ | ||
| 347 | if ((token & QTD_STS_XACT) && | ||
| 348 | QTD_CERR(token) == 0 && | ||
| 349 | --qh->xacterrs > 0 && | ||
| 350 | !urb->unlinked) { | ||
| 351 | ehci_dbg(ehci, | ||
| 352 | "detected XactErr len %zu/%zu retry %d\n", | ||
| 353 | qtd->length - QTD_LENGTH(token), qtd->length, | ||
| 354 | QH_XACTERR_MAX - qh->xacterrs); | ||
| 355 | |||
| 356 | /* reset the token in the qtd and the | ||
| 357 | * qh overlay (which still contains | ||
| 358 | * the qtd) so that we pick up from | ||
| 359 | * where we left off | ||
| 360 | */ | ||
| 361 | token &= ~QTD_STS_HALT; | ||
| 362 | token |= QTD_STS_ACTIVE | | ||
| 363 | (EHCI_TUNE_CERR << 10); | ||
| 364 | qtd->hw_token = cpu_to_hc32(ehci, | ||
| 365 | token); | ||
| 366 | wmb(); | ||
| 367 | qh->hw_token = cpu_to_hc32(ehci, token); | ||
| 368 | goto retry_xacterr; | ||
| 369 | } | ||
| 342 | stopped = 1; | 370 | stopped = 1; |
| 343 | 371 | ||
| 344 | /* magic dummy for some short reads; qh won't advance. | 372 | /* magic dummy for some short reads; qh won't advance. |
| @@ -421,6 +449,9 @@ halt: | |||
| 421 | /* remove qtd; it's recycled after possible urb completion */ | 449 | /* remove qtd; it's recycled after possible urb completion */ |
| 422 | list_del (&qtd->qtd_list); | 450 | list_del (&qtd->qtd_list); |
| 423 | last = qtd; | 451 | last = qtd; |
| 452 | |||
| 453 | /* reinit the xacterr counter for the next qtd */ | ||
| 454 | qh->xacterrs = QH_XACTERR_MAX; | ||
| 424 | } | 455 | } |
| 425 | 456 | ||
| 426 | /* last urb's completion might still need calling */ | 457 | /* last urb's completion might still need calling */ |
| @@ -862,6 +893,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
| 862 | head->qh_next.qh = qh; | 893 | head->qh_next.qh = qh; |
| 863 | head->hw_next = dma; | 894 | head->hw_next = dma; |
| 864 | 895 | ||
| 896 | qh->xacterrs = QH_XACTERR_MAX; | ||
| 865 | qh->qh_state = QH_STATE_LINKED; | 897 | qh->qh_state = QH_STATE_LINKED; |
| 866 | /* qtd completions reported later by interrupt */ | 898 | /* qtd completions reported later by interrupt */ |
| 867 | } | 899 | } |
