Re: ehci: qh->xacterrs not initialized (Was: Kernel lockup when unplugging device from hub)

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

 



On Thu, 30 Jul 2009, Matthijs Kooijman wrote:

> Hi Alan,
> 
> I've tried a clean kernel (without your patch), which shows the same problem.
> So it seems it's not caused by your patch. I also added some debug statements
> to see what is happening. It seems that the xacterrs value is never initalized
> for this particular qh, which voids my theory about rapidly decreasing
> xacterrs without any messages printed.
> 
> I've made a log of just inserting the hub, using 2.6.31-rc4 with your patch
> and [1] applied. The resulting kernel output is at [2].
> 
> I had a look at the kernel sources, but I really don't know enough about USB
> and the ehci driver to follow the code paths (or rather, know how they should
> be). So I hope you can make a decent guess from this log.

Good work; I figured it out.  Although it's easy to forget, there are 
_two_ routines which can add a QH to the schedule, and they both need 
to initialize qh->xacterrs.

I decided to simplify the transaction error counting at the same time.  
The resulting patch below should fix the problem.  It is independent of
the other patch, although it touches some adjacent lines.

Alan Stern



Index: 2.6.31-rc4/drivers/usb/host/ehci-q.c
===================================================================
--- 2.6.31-rc4.orig/drivers/usb/host/ehci-q.c
+++ 2.6.31-rc4/drivers/usb/host/ehci-q.c
@@ -375,12 +375,11 @@ qh_completions (struct ehci_hcd *ehci, s
 				 */
 				if ((token & QTD_STS_XACT) &&
 						QTD_CERR(token) == 0 &&
-						--qh->xacterrs > 0 &&
+						++qh->xacterrs < QH_XACTERR_MAX &&
 						!urb->unlinked) {
 					ehci_dbg(ehci,
 	"detected XactErr len %zu/%zu retry %d\n",
-	qtd->length - QTD_LENGTH(token), qtd->length,
-	QH_XACTERR_MAX - qh->xacterrs);
+	qtd->length - QTD_LENGTH(token), qtd->length, qh->xacterrs);
 
 					/* reset the token in the qtd and the
 					 * qh overlay (which still contains
@@ -494,7 +493,7 @@ halt:
 		last = qtd;
 
 		/* reinit the xacterr counter for the next qtd */
-		qh->xacterrs = QH_XACTERR_MAX;
+		qh->xacterrs = 0;
 	}
 
 	/* last urb's completion might still need calling */
@@ -941,7 +940,7 @@ static void qh_link_async (struct ehci_h
 	head->hw_next = dma;
 
 	qh_get(qh);
-	qh->xacterrs = QH_XACTERR_MAX;
+	qh->xacterrs = 0;
 	qh->qh_state = QH_STATE_LINKED;
 	/* qtd completions reported later by interrupt */
 }
Index: 2.6.31-rc4/drivers/usb/host/ehci-sched.c
===================================================================
--- 2.6.31-rc4.orig/drivers/usb/host/ehci-sched.c
+++ 2.6.31-rc4/drivers/usb/host/ehci-sched.c
@@ -542,6 +542,7 @@ static int qh_link_periodic (struct ehci
 		}
 	}
 	qh->qh_state = QH_STATE_LINKED;
+	qh->xacterrs = 0;
 	qh_get (qh);
 
 	/* update per-qh bandwidth for usbfs */

--
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