tech-kern archive

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

[patch] xhci patch 20160809



Hello,

I'll post xhci patches for HEAD.


x-addrendian.diff
	+ Fix endian issue of device address.
x-linktrb2.diff
	+ Put Link TRB always at the end of ring.
	  Should fix ctrl xfer problem on Intel xHC.


Thanks,
--
t-hash
--- sys/dev/usb/xhci.c.orig	2016-07-18 07:07:53.000000000 +0900
+++ sys/dev/usb/xhci.c	2016-08-07 14:17:46.000000000 +0900
@@ -2229,7 +2246,7 @@ xhci_new_device(device_t parent, struct 
 
 		cp = xhci_slot_get_dcv(sc, xs, XHCI_DCI_SLOT);
 		//hexdump("slot context", cp, sc->sc_ctxsz);
-		uint8_t addr = XHCI_SCTX_3_DEV_ADDR_GET(cp[3]);
+		uint8_t addr = XHCI_SCTX_3_DEV_ADDR_GET(le32toh(cp[3]));
 		DPRINTFN(4, "device address %u", addr, 0, 0, 0);
 		/* XXX ensure we know when the hardware does something
 		   we can't yet cope with */
--- sys/dev/usb/xhci.c.orig	2016-07-18 07:07:53.000000000 +0900
+++ sys/dev/usb/xhci.c	2016-08-09 17:37:40.000000000 +0900
@@ -2374,58 +2397,63 @@ 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++;
-
-	/* 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;
+	u_int firstep = xr->xr_ep;
+	u_int firstcs = xr->xr_cs;
 
-		if (cs) {
-			control |= XHCI_TRB_3_CYCLE_BIT;
+	for (i = 0; i < ntrbs; ) {
+		u_int oldri = ri;
+		u_int oldcs = cs;
+
+		if (ri >= (xr->xr_ntrb - 1)) {
+			/* Put Link TD at the end of ring */
+			parameter = xhci_ring_trbp(xr, 0);
+			status = 0;
+			control = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) |
+			    XHCI_TRB_3_TC_BIT;
+			xr->xr_cookies[ri] = NULL;
+			xr->xr_ep = 0;
+			xr->xr_cs ^= 1;
+			ri = xr->xr_ep;
+			cs = xr->xr_cs;
 		} else {
-			control &= ~XHCI_TRB_3_CYCLE_BIT;
+			parameter = trbs[i].trb_0;
+			status = trbs[i].trb_2;
+			control = trbs[i].trb_3;
+
+			xr->xr_cookies[ri] = cookie;
+			ri++;
+			i++;
 		}
-
-		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] = cookie;
-		ri++;
+		/*
+		 * If this is a first TRB, mark it invalid to prevent
+		 * xHC from running it immediately.
+		 */
+		if (oldri == firstep) {
+			if (oldcs) {
+				control &= ~XHCI_TRB_3_CYCLE_BIT;
+			} else {
+				control |= XHCI_TRB_3_CYCLE_BIT;
+			}
+		} else {
+			if (oldcs) {
+				control |= XHCI_TRB_3_CYCLE_BIT;
+			} else {
+				control &= ~XHCI_TRB_3_CYCLE_BIT;
+			}
+		}
+		xhci_trb_put(&xr->xr_trb[oldri], parameter, status, control);
+		usb_syncmem(&xr->xr_dma, XHCI_TRB_SIZE * oldri,
+		    XHCI_TRB_SIZE * 1, BUS_DMASYNC_PREWRITE);
 	}
 
-	/* 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;
+	/* Now invert cycle bit of first TRB */
+	if (firstcs) {
+		xr->xr_trb[firstep].trb_3 |= htole32(XHCI_TRB_3_CYCLE_BIT);
 	} else {
-		control &= ~XHCI_TRB_3_CYCLE_BIT;
+		xr->xr_trb[firstep].trb_3 &= ~htole32(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;
+	usb_syncmem(&xr->xr_dma, XHCI_TRB_SIZE * firstep,
+	    XHCI_TRB_SIZE * 1, BUS_DMASYNC_PREWRITE);
 
 	xr->xr_ep = ri;
 	xr->xr_cs = cs;


Home | Main Index | Thread Index | Old Index