Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/usb Put Link TRB always at the end of ring. Should ...



details:   https://anonhg.NetBSD.org/src/rev/6d5aba0b075e
branches:  trunk
changeset: 817345:6d5aba0b075e
user:      skrll <skrll%NetBSD.org@localhost>
date:      Thu Aug 18 07:18:52 2016 +0000

description:
Put Link TRB always at the end of ring.  Should fix ctrl xfer problem on
Intel xHC.

>From t-hash.

diffstat:

 sys/dev/usb/xhci.c |  101 +++++++++++++++++++++++++++-------------------------
 1 files changed, 53 insertions(+), 48 deletions(-)

diffs (128 lines):

diff -r b0506e49fa93 -r 6d5aba0b075e sys/dev/usb/xhci.c
--- a/sys/dev/usb/xhci.c        Thu Aug 18 07:08:32 2016 +0000
+++ b/sys/dev/usb/xhci.c        Thu Aug 18 07:18:52 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: xhci.c,v 1.64 2016/08/18 07:08:32 skrll Exp $  */
+/*     $NetBSD: xhci.c,v 1.65 2016/08/18 07:18:52 skrll Exp $  */
 
 /*
  * Copyright (c) 2013 Jonathan A. Kollasch
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.64 2016/08/18 07:08:32 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.65 2016/08/18 07:18:52 skrll Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -2374,58 +2374,63 @@
         * 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;
-
-               if (cs) {
-                       control |= XHCI_TRB_3_CYCLE_BIT;
+       u_int firstep = xr->xr_ep;
+       u_int firstcs = xr->xr_cs;
+
+       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