Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/usb Add a few comments about some perversities of th...



details:   https://anonhg.NetBSD.org/src/rev/ce7f635198f5
branches:  trunk
changeset: 325188:ce7f635198f5
user:      dsl <dsl%NetBSD.org@localhost>
date:      Tue Dec 10 19:39:42 2013 +0000

description:
Add a few comments about some perversities of the xhci specification.
XXX: I can't see any code that ensures there is space in the rings.
XXX: Nothing stops buffer fragments crossing 64kB boundaries.

diffstat:

 sys/dev/usb/xhci.c |  26 ++++++++++++++++++++++++--
 1 files changed, 24 insertions(+), 2 deletions(-)

diffs (68 lines):

diff -r 2d0146f50cb5 -r ce7f635198f5 sys/dev/usb/xhci.c
--- a/sys/dev/usb/xhci.c        Tue Dec 10 18:20:32 2013 +0000
+++ b/sys/dev/usb/xhci.c        Tue Dec 10 19:39:42 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: xhci.c,v 1.10 2013/11/17 16:11:35 skrll Exp $  */
+/*     $NetBSD: xhci.c,v 1.11 2013/12/10 19:39:42 dsl Exp $    */
 
 /*
  * Copyright (c) 2013 Jonathan A. Kollasch
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.10 2013/11/17 16:11:35 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.11 2013/12/10 19:39:42 dsl Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1621,6 +1621,15 @@
        ri = xr->xr_ep;
        cs = xr->xr_cs;
 
+       /*
+        * Although the xhci hardware can do scatter/gather dma from
+        * arbitrary sized buffers, there is a non-obvious restriction
+        * that a LINK trb is only allowed at the end of a burst of
+        * transfers - which might be 16kB.
+        * Arbitrary aligned LINK trb definitely fail on Ivy bridge.
+        * The simple solution is not to allow a LINK trb in the middle
+        * of anything - as here.
+        */
        if (ri + ntrbs >= (xr->xr_ntrb - 1)) {
                parameter = xhci_ring_trbp(xr, 0);
                status = 0;
@@ -1639,6 +1648,7 @@
 
        ri++;
 
+       /* Write any subsequent TRB first */
        for (i = 1; i < ntrbs; i++) {
                parameter = trbs[i].trb_0;
                status = trbs[i].trb_2;
@@ -1658,6 +1668,7 @@
                ri++;
        }
 
+       /* Write the first TRB last */
        i = 0;
        {
                parameter = trbs[i].trb_0;
@@ -2659,6 +2670,17 @@
        KASSERT((xfer->rqflags & URQ_REQUEST) == 0);
 
        parameter = DMAADDR(dma, 0);
+       /*
+        * XXX: The physical buffer must not cross a 64k boundary.
+        * If the user supplied buffer crosses such a boundary then 2
+        * (or more) TRB should be used.
+        * If multiple TRB are used the td_size field must be set correctly.
+        * For v1.0 devices (like ivy bridge) this is the number of usb data
+        * blocks needed to complete the transfer.
+        * Setting it to 1 in the last TRB causes an extra zero-length
+        * data block be sent.
+        * The earlier documentation differs, I don't know how it behaves.
+        */
        KASSERT(len <= 0x10000);
        status = XHCI_TRB_2_IRQ_SET(0) |
            XHCI_TRB_2_TDSZ_SET(1) |



Home | Main Index | Thread Index | Old Index