On Thu, 22 Jan 2009 Saito.Koichiro@xxxxxxxxx wrote: > I tried to one-time retrying. But it turned out that > retrying fail occasionally. Retrying with retry counter > may not have less chance of recovery. I made some changes to your patch. Most notably, I set the retry limit to 255. If there is one retry per microframe, that will last for 32 ms. When you add in the overhead of interrupt handling, it will probably last longer. I guess it will be long enough to handle most transients. When I tested it by unplugging a second device during an ongoing transfer, it worked with only one retry, just as you found. When I tested it by unplugging a flash drive during I/O, I got a rapid string of 254 debug messages at intervals of 250 us -- so the total retry period was 64 ms, which I like better than 32 ms. Of course, with debugging turned off it might go more quickly. There were a few other changes, some stylistic and some functional. We could consider merging this -- except that of course Dave has to review it. An important special case to think about: What happens if the device isn't running at high speed? Alan Stern Index: usb-2.6/drivers/usb/host/ehci-q.c =================================================================== --- usb-2.6.orig/drivers/usb/host/ehci-q.c +++ usb-2.6/drivers/usb/host/ehci-q.c @@ -333,12 +333,39 @@ qh_completions (struct ehci_hcd *ehci, s token = hc32_to_cpu(ehci, qtd->hw_token); /* always clean up qtds the hc de-activated */ + retry_xacterr: if ((token & QTD_STS_ACTIVE) == 0) { /* on STALL, error, and short reads this urb must * complete and all its qtds must be recycled. */ if ((token & QTD_STS_HALT) != 0) { + + /* retry transaction errors until we + * reach the software xacterr limit + */ + if ((token & QTD_STS_XACT) && + !QTD_CERR(token) && + --qh->xacterrs > 0) { + ehci_dbg(ehci, + "detected XactErr len %d/%d retry %d\n", + qtd->length - QTD_LENGTH(token), qtd->length, + QH_XACTERR_MAX - qh->xacterrs); + + /* reset the token in the qtd and the + * qh overlay (which still contains + * the qtd) so that we pick up from + * where we left off + */ + token &= ~QTD_STS_HALT; + token |= QTD_STS_ACTIVE | + (EHCI_TUNE_CERR << 10); + qtd->hw_token = cpu_to_hc32(ehci, + token); + wmb(); + qh->hw_token = cpu_to_hc32(ehci, token); + goto retry_xacterr; + } stopped = 1; /* magic dummy for some short reads; qh won't advance. @@ -355,6 +382,10 @@ qh_completions (struct ehci_hcd *ehci, s & EHCI_LIST_END(ehci))) { stopped = 1; goto halt; + + /* reinit the xacterr counter for the next qtd */ + } else { + qh->xacterrs = QH_XACTERR_MAX; } /* stop scanning when we reach qtds the hc is using */ Index: usb-2.6/drivers/usb/host/ehci.h =================================================================== --- usb-2.6.orig/drivers/usb/host/ehci.h +++ usb-2.6/drivers/usb/host/ehci.h @@ -370,6 +370,9 @@ struct ehci_qh { #define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */ #define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ + u8 xacterrs; /* XactErr retry counter */ +#define QH_XACTERR_MAX 255 /* XactErr retry limit */ + /* periodic schedule info */ u8 usecs; /* intr bandwidth */ u8 gap_uf; /* uframes split/csplit gap */ -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html