Re: When unplug USB device, another USB device access failed

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux