Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/usb PR/51202: XHCI driver sends stale TRBs from a pi...



details:   https://anonhg.NetBSD.org/src/rev/bd91636c53e4
branches:  trunk
changeset: 345709:bd91636c53e4
user:      skrll <skrll%NetBSD.org@localhost>
date:      Sun Jun 05 09:16:02 2016 +0000

description:
PR/51202: XHCI driver sends stale TRBs from a pipe previously opened

A similar patch was sent to me by t-hash and the xhci_setup_ctx is taken
from that.

diffstat:

 sys/dev/usb/xhci.c |  33 +++++++++++++++++++++++++++------
 1 files changed, 27 insertions(+), 6 deletions(-)

diffs (90 lines):

diff -r 3f6e7de872a9 -r bd91636c53e4 sys/dev/usb/xhci.c
--- a/sys/dev/usb/xhci.c        Sun Jun 05 09:13:08 2016 +0000
+++ b/sys/dev/usb/xhci.c        Sun Jun 05 09:16:02 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: xhci.c,v 1.54 2016/06/05 08:25:05 skrll Exp $  */
+/*     $NetBSD: xhci.c,v 1.55 2016/06/05 09:16:02 skrll Exp $  */
 
 /*
  * Copyright (c) 2013 Jonathan A. Kollasch
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.54 2016/06/05 08:25:05 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.55 2016/06/05 09:16:02 skrll Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -142,6 +142,7 @@
 static usbd_status xhci_reset_endpoint(struct usbd_pipe *);
 static usbd_status xhci_stop_endpoint(struct usbd_pipe *);
 
+static void xhci_host_dequeue(struct xhci_ring * const);
 static usbd_status xhci_set_dequeue(struct usbd_pipe *);
 
 static usbd_status xhci_do_command(struct xhci_softc * const,
@@ -1500,6 +1501,9 @@
        cp = xhci_slot_get_icv(sc, xs, xhci_dci_to_ici(XHCI_DCI_SLOT));
        cp[0] = htole32(XHCI_SCTX_0_CTX_NUM_SET(dci));
 
+       /* configure ep context performs an implicit dequeue */
+       xhci_host_dequeue(&xs->xs_ep[dci].xe_tr);
+
        /* sync input contexts before they are read from memory */
        usb_syncmem(&xs->xs_ic_dma, 0, sc->sc_pgsz, BUS_DMASYNC_PREWRITE);
 
@@ -1545,6 +1549,19 @@
        KASSERT(mutex_owned(&sc->sc_lock));
 }
 
+static void
+xhci_host_dequeue(struct xhci_ring * const xr)
+{
+       /* When dequeueing the controller, update our struct copy too */
+       memset(xr->xr_trb, 0, xr->xr_ntrb * XHCI_TRB_SIZE);
+       usb_syncmem(&xr->xr_dma, 0, xr->xr_ntrb * XHCI_TRB_SIZE,
+           BUS_DMASYNC_PREWRITE);
+       memset(xr->xr_cookies, 0, xr->xr_ntrb * sizeof(*xr->xr_cookies));
+
+       xr->xr_ep = 0;
+       xr->xr_cs = 1;
+}
+
 /*
  * Recover STALLed endpoint.
  * xHCI 1.1 sect 4.10.2.1
@@ -2173,11 +2190,8 @@
        xr->xr_cookies = kmem_zalloc(sizeof(*xr->xr_cookies) * ntrb, KM_SLEEP);
        xr->xr_trb = xhci_ring_trbv(xr, 0);
        xr->xr_ntrb = ntrb;
-       xr->xr_ep = 0;
-       xr->xr_cs = 1;
-       memset(xr->xr_trb, 0, size);
-       usb_syncmem(&xr->xr_dma, 0, size, BUS_DMASYNC_PREWRITE);
        xr->is_halted = false;
+       xhci_host_dequeue(xr);
 
        return USBD_NORMAL_COMPLETION;
 }
@@ -2751,6 +2765,7 @@
        DPRINTFN(4, "setting ival %u MaxBurst %#x",
            XHCI_EPCTX_0_IVAL_GET(cp[0]), XHCI_EPCTX_1_MAXB_GET(cp[1]), 0, 0);
 
+       /* rewind TR dequeue pointer in xHC */
        /* can't use xhci_ep_get_dci() yet? */
        *(uint64_t *)(&cp[2]) = htole64(
            xhci_ring_trbp(&xs->xs_ep[dci].xe_tr, 0) |
@@ -2760,6 +2775,12 @@
        cp[1] = htole32(cp[1]);
        cp[4] = htole32(cp[4]);
 
+       /* rewind TR dequeue pointer in driver */
+       struct xhci_ring *xr = &xs->xs_ep[dci].xe_tr;
+       mutex_enter(&xr->xr_lock);
+       xhci_host_dequeue(xr);
+       mutex_exit(&xr->xr_lock);
+
        /* sync input contexts before they are read from memory */
        usb_syncmem(&xs->xs_ic_dma, 0, sc->sc_pgsz, BUS_DMASYNC_PREWRITE);
 }



Home | Main Index | Thread Index | Old Index