NetBSD-Bugs archive

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

Re: kern/51395: USB Ethernet makes xhci hang



I've found that the previous fix was imcomplete.

Can you try attached patch?
This patch tries to put Link TRB at the last of ring.
This lacks handling that first TRB should be written at last.

Thank you for reporting this problem.


--
t-hash
--- sys/dev/usb/xhci.c.orig	2016-07-18 07:07:53.000000000 +0900
+++ sys/dev/usb/xhci.c	2016-08-08 22:06:19.000000000 +0900
@@ -2374,25 +2397,24 @@ xhci_ring_put(struct xhci_softc * const 
 	 * The code should write the 'cycle' bit on the link trb AFTER
 	 * adding the other trb.
 	 */
-	if (ri + ntrbs >= (xr->xr_ntrb - 1)) {
-		parameter = xhci_ring_trbp(xr, 0);
-		status = 0;
-		control = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) |
-		    XHCI_TRB_3_TC_BIT | (cs ? XHCI_TRB_3_CYCLE_BIT : 0);
-		xhci_trb_put(&xr->xr_trb[ri], parameter, status, control);
-		usb_syncmem(&xr->xr_dma, XHCI_TRB_SIZE * ri, XHCI_TRB_SIZE * 1,
-		    BUS_DMASYNC_PREWRITE);
-		xr->xr_cookies[ri] = NULL;
-		xr->xr_ep = 0;
-		xr->xr_cs ^= 1;
-		ri = xr->xr_ep;
-		cs = xr->xr_cs;
-	}
-
-	ri++;
+	for (i = 0; i < ntrbs; ) {
+		if (ri >= (xr->xr_ntrb - 1)) {
+			parameter = xhci_ring_trbp(xr, 0);
+			status = 0;
+			control = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) |
+			    XHCI_TRB_3_TC_BIT | (cs ? XHCI_TRB_3_CYCLE_BIT : 0);
+			xhci_trb_put(&xr->xr_trb[ri], parameter, status,
+			    control);
+			usb_syncmem(&xr->xr_dma, XHCI_TRB_SIZE * ri,
+			    XHCI_TRB_SIZE * 1, BUS_DMASYNC_PREWRITE);
+			xr->xr_cookies[ri] = NULL;
+			xr->xr_ep = 0;
+			xr->xr_cs ^= 1;
+			ri = xr->xr_ep;
+			cs = xr->xr_cs;
+			continue;
+		}
 
-	/* Write any subsequent TRB first */
-	for (i = 1; i < ntrbs; i++) {
 		parameter = trbs[i].trb_0;
 		status = trbs[i].trb_2;
 		control = trbs[i].trb_3;
@@ -2408,25 +2430,9 @@ xhci_ring_put(struct xhci_softc * const 
 		    BUS_DMASYNC_PREWRITE);
 		xr->xr_cookies[ri] = cookie;
 		ri++;
+		i++;
 	}
 
-	/* Write the first TRB last */
-	i = 0;
-	parameter = trbs[i].trb_0;
-	status = trbs[i].trb_2;
-	control = trbs[i].trb_3;
-
-	if (xr->xr_cs) {
-		control |= XHCI_TRB_3_CYCLE_BIT;
-	} else {
-		control &= ~XHCI_TRB_3_CYCLE_BIT;
-	}
-
-	xhci_trb_put(&xr->xr_trb[xr->xr_ep], parameter, status, control);
-	usb_syncmem(&xr->xr_dma, XHCI_TRB_SIZE * xr->xr_ep, XHCI_TRB_SIZE * 1,
-	    BUS_DMASYNC_PREWRITE);
-	xr->xr_cookies[xr->xr_ep] = cookie;
-
 	xr->xr_ep = ri;
 	xr->xr_cs = cs;
 


Home | Main Index | Thread Index | Old Index