tech-kern archive

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

Re: bus_dmamap_sync() for uhci(4)



On Tue, Jun 10, 2008 at 11:15:29AM -0400, Michael Lorenz wrote:
> Currently BUS_DMAMAP_COHERENT translates to 'access via kseg1' on  
> sgimips. Yes, should be completely uncached.

OK, thanks.
Here's an updated patch, which fixes some cut-n-paste and adds some
usb_syncmem() based on Izumi's comments.
But again I can't see how it would change anything on a BUS_DMAMAP_COHERENT
memory ... it's just some more wmb() calls, which should now be redundant.

-- 
Manuel Bouyer <bouyer%antioche.eu.org@localhost>
     NetBSD: 26 ans d'experience feront toujours la difference
--
Index: ehci.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/ehci.c,v
retrieving revision 1.136
diff -u -r1.136 ehci.c
--- ehci.c      21 May 2008 17:19:44 -0000      1.136
+++ ehci.c      10 Jun 2008 20:38:47 -0000
@@ -437,6 +437,8 @@
                sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
                sqh->qh.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED);
                sqh->sqtd = NULL;
+               usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
        }
        /* Point the frame list at the last level (128ms). */
        for (i = 0; i < sc->sc_flsize; i++) {
@@ -448,6 +450,8 @@
                    sc->sc_islots[EHCI_IQHIDX(EHCI_IPOLLRATES - 1,
                    i)].sqh->physaddr);
        }
+       usb_syncmem(&sc->sc_fldma, 0, sc->sc_flsize * sizeof(ehci_link_t),
+           BUS_DMASYNC_PREWRITE);
 
        /* Allocate dummy QH that starts the async list. */
        sqh = ehci_alloc_sqh(sc);
@@ -467,6 +471,8 @@
        sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
        sqh->qh.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED);
        sqh->sqtd = NULL;
+       usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 #ifdef EHCI_DEBUG
        if (ehcidebug) {
                ehci_dump_sqh(sqh);
@@ -699,10 +705,21 @@
         * is a an error somewhere in the middle, or whether there was a
         * short packet (SPD and not ACTIVE).
         */
+       usb_syncmem(&lsqtd->dma,
+           lsqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+           sizeof(lsqtd->qtd.qtd_status),
+           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
        if (le32toh(lsqtd->qtd.qtd_status) & EHCI_QTD_ACTIVE) {
                DPRINTFN(12, ("ehci_check_intr: active ex=%p\n", ex));
                for (sqtd = ex->sqtdstart; sqtd != lsqtd; sqtd=sqtd->nextqtd) {
+                       usb_syncmem(&sqtd->dma,
+                           sqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+                           sizeof(sqtd->qtd.qtd_status),
+                           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
                        status = le32toh(sqtd->qtd.qtd_status);
+                       usb_syncmem(&sqtd->dma,
+                           sqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+                           sizeof(sqtd->qtd.qtd_status), BUS_DMASYNC_PREREAD);
                        /* If there's an active QTD the xfer isn't done. */
                        if (status & EHCI_QTD_ACTIVE)
                                break;
@@ -715,6 +732,9 @@
                }
                DPRINTFN(12, ("ehci_check_intr: ex=%p std=%p still active\n",
                              ex, ex->sqtdstart));
+               usb_syncmem(&lsqtd->dma,
+                   lsqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+                   sizeof(lsqtd->qtd.qtd_status), BUS_DMASYNC_PREREAD);
                return;
        }
  done:
@@ -767,6 +787,8 @@
        lsqtd = ex->sqtdend;
        actlen = 0;
        for (sqtd = ex->sqtdstart; sqtd != lsqtd->nextqtd; sqtd=sqtd->nextqtd) {
+               usb_syncmem(&sqtd->dma, sqtd->offs, sizeof(sqtd->qtd),
+                   BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
                nstatus = le32toh(sqtd->qtd.qtd_status);
                if (nstatus & EHCI_QTD_ACTIVE)
                        break;
@@ -1232,7 +1254,14 @@
        stop = 0;
        for (i = 0; sqtd && i < 20 && !stop; sqtd = sqtd->nextqtd, i++) {
                ehci_dump_sqtd(sqtd);
+               usb_syncmem(&sqtd->dma,
+                   sqtd->offs + offsetof(ehci_qtd_t, qtd_next), 
+                   sizeof(sqtd->qtd),
+                   BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
                stop = sqtd->qtd.qtd_next & htole32(EHCI_LINK_TERMINATE);
+               usb_syncmem(&sqtd->dma,
+                   sqtd->offs + offsetof(ehci_qtd_t, qtd_next), 
+                   sizeof(sqtd->qtd), BUS_DMASYNC_PREREAD);
        }
        if (sqtd)
                printf("dump aborted, too many TDs\n");
@@ -1241,8 +1270,12 @@
 void
 ehci_dump_sqtd(ehci_soft_qtd_t *sqtd)
 {
+       usb_syncmem(&sqtd->dma, sqtd->offs, 
+           sizeof(sqtd->qtd), BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
        printf("QTD(%p) at 0x%08x:\n", sqtd, sqtd->physaddr);
        ehci_dump_qtd(&sqtd->qtd);
+       usb_syncmem(&sqtd->dma, sqtd->offs, 
+           sizeof(sqtd->qtd), BUS_DMASYNC_PREREAD);
 }
 
 void
@@ -1273,6 +1306,8 @@
        ehci_qh_t *qh = &sqh->qh;
        u_int32_t endp, endphub;
 
+       usb_syncmem(&sqh->dma, sqh->offs, 
+           sizeof(sqh->qh), BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
        printf("QH(%p) at 0x%08x:\n", sqh, sqh->physaddr);
        printf("  link="); ehci_dump_link(qh->qh_link, 1); printf("\n");
        endp = le32toh(qh->qh_endp);
@@ -1293,6 +1328,8 @@
        printf("  curqtd="); ehci_dump_link(qh->qh_curqtd, 0); printf("\n");
        printf("Overlay qTD:\n");
        ehci_dump_qtd(&qh->qh_qtd);
+       usb_syncmem(&sqh->dma, sqh->offs, 
+           sizeof(sqh->qh), BUS_DMASYNC_PREREAD);
 }
 
 #ifdef DIAGNOSTIC
@@ -1393,6 +1430,8 @@
        sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
        sqh->qh.qh_qtd.qtd_status = htole32(0);
 
+       usb_syncmem(&sqh->dma, sqh->offs, 
+           sizeof(sqh->qh), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
        epipe->sqh = sqh;
 
        switch (xfertype) {
@@ -1459,10 +1498,16 @@
 {
        SPLUSBCHECK;
 
+       usb_syncmem(&head->dma, head->offs + offsetof(ehci_qh_t, qh_link),
+           sizeof(head->qh.qh_link), BUS_DMASYNC_POSTWRITE);
        sqh->next = head->next;
        sqh->qh.qh_link = head->qh.qh_link;
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(ehci_qh_t, qh_link),
+           sizeof(sqh->qh.qh_link), BUS_DMASYNC_PREWRITE);
        head->next = sqh;
        head->qh.qh_link = htole32(sqh->physaddr | EHCI_LINK_QH);
+       usb_syncmem(&head->dma, head->offs + offsetof(ehci_qh_t, qh_link),
+           sizeof(head->qh.qh_link), BUS_DMASYNC_PREWRITE);
 
 #ifdef EHCI_DEBUG
        if (ehcidebug > 5) {
@@ -1486,8 +1531,12 @@
                ;
        if (p == NULL)
                panic("ehci_rem_qh: ED not found");
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(ehci_qh_t, qh_link),
+           sizeof(sqh->qh.qh_link), BUS_DMASYNC_POSTWRITE);
        p->next = sqh->next;
        p->qh.qh_link = sqh->qh.qh_link;
+       usb_syncmem(&p->dma, p->offs + offsetof(ehci_qh_t, qh_link),
+           sizeof(p->qh.qh_link), BUS_DMASYNC_PREWRITE);
 
        ehci_sync_hc(sc);
 }
@@ -1499,20 +1548,32 @@
        u_int32_t status;
 
        /* Save toggle bit and ping status. */
+       usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
        status = sqh->qh.qh_qtd.qtd_status &
            htole32(EHCI_QTD_TOGGLE_MASK |
                    EHCI_QTD_SET_STATUS(EHCI_QTD_PINGSTATE));
        /* Set HALTED to make hw leave it alone. */
        sqh->qh.qh_qtd.qtd_status =
            htole32(EHCI_QTD_SET_STATUS(EHCI_QTD_HALTED));
+       usb_syncmem(&sqh->dma,
+           sqh->offs + offsetof(ehci_qh_t, qh_qtd.qtd_status),
+           sizeof(sqh->qh.qh_qtd.qtd_status),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
        sqh->qh.qh_curqtd = 0;
        sqh->qh.qh_qtd.qtd_next = htole32(sqtd->physaddr);
        sqh->qh.qh_qtd.qtd_altnext = 0;
        for (i = 0; i < EHCI_QTD_NBUFFERS; i++)
                sqh->qh.qh_qtd.qtd_buffer[i] = 0;
        sqh->sqtd = sqtd;
+       usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
        /* Set !HALTED && !ACTIVE to start execution, preserve some fields */
        sqh->qh.qh_qtd.qtd_status = status;
+       usb_syncmem(&sqh->dma,
+           sqh->offs + offsetof(ehci_qh_t, qh_qtd.qtd_status),
+           sizeof(sqh->qh.qh_qtd.qtd_status),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 }
 
 /*
@@ -2171,6 +2232,8 @@
                        offs = i * EHCI_SQH_SIZE;
                        sqh = KERNADDR(&dma, offs);
                        sqh->physaddr = DMAADDR(&dma, offs);
+                       sqh->dma = dma;
+                       sqh->offs = offs;
                        sqh->next = sc->sc_freeqhs;
                        sc->sc_freeqhs = sqh;
                }
@@ -2213,6 +2276,8 @@
                        offs = i * EHCI_SQTD_SIZE;
                        sqtd = KERNADDR(&dma, offs);
                        sqtd->physaddr = DMAADDR(&dma, offs);
+                       sqtd->dma = dma;
+                       sqtd->offs = offs;
                        sqtd->nextqtd = sc->sc_freeqtds;
                        sc->sc_freeqtds = sqtd;
                }
@@ -2273,6 +2338,9 @@
        *sp = cur;
        if (cur == NULL)
                goto nomem;
+
+       usb_syncmem(dma, 0, alen,
+           rd ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
        for (;;) {
                dataphyspage = EHCI_PAGE(dataphys);
                /* The EHCI hardware can handle at most 5 pages. */
@@ -2347,6 +2415,7 @@
                    htole32(qtdstatus | EHCI_QTD_SET_BYTES(curlen));
                cur->xfer = xfer;
                cur->len = curlen;
+
                DPRINTFN(10,("ehci_alloc_sqtd_chain: cbp=0x%08x end=0x%08x\n",
                            dataphys, dataphys + curlen));
                /* adjust the toggle based on the number of packets in this
@@ -2357,11 +2426,15 @@
                }
                if (next == NULL)
                        break;
+               usb_syncmem(&cur->dma, cur->offs, sizeof(cur->qtd),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
                DPRINTFN(10,("ehci_alloc_sqtd_chain: extend chain\n"));
                dataphys += curlen;
                cur = next;
        }
        cur->qtd.qtd_status |= htole32(EHCI_QTD_IOC);
+       usb_syncmem(&cur->dma, cur->offs, sizeof(cur->qtd),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
        *ep = cur;
        epipe->nexttoggle = tog;
 
@@ -2478,10 +2551,27 @@
        s = splusb();
        xfer->status = status;  /* make software ignore it */
        usb_uncallout(xfer->timeout_handle, ehci_timeout, xfer);
+
+       usb_syncmem(&sqh->dma,
+           sqh->offs + offsetof(ehci_qh_t, qh_qtd.qtd_status),
+           sizeof(sqh->qh.qh_qtd.qtd_status),
+           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
        qhstatus = sqh->qh.qh_qtd.qtd_status;
        sqh->qh.qh_qtd.qtd_status = qhstatus | htole32(EHCI_QTD_HALTED);
+       usb_syncmem(&sqh->dma,
+           sqh->offs + offsetof(ehci_qh_t, qh_qtd.qtd_status),
+           sizeof(sqh->qh.qh_qtd.qtd_status),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
        for (sqtd = exfer->sqtdstart; ; sqtd = sqtd->nextqtd) {
+               usb_syncmem(&sqtd->dma,
+                   sqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+                   sizeof(sqtd->qtd.qtd_status),
+                   BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
                sqtd->qtd.qtd_status |= htole32(EHCI_QTD_HALTED);
+               usb_syncmem(&sqtd->dma,
+                   sqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+                   sizeof(sqtd->qtd.qtd_status),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
                if (sqtd == exfer->sqtdend)
                        break;
        }
@@ -2511,6 +2601,11 @@
         * any of them.
         */
        s = splusb();           /* XXX why? */
+
+       usb_syncmem(&sqh->dma,
+           sqh->offs + offsetof(ehci_qh_t, qh_curqtd),
+           sizeof(sqh->qh.qh_curqtd),
+           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
        cur = EHCI_LINK_ADDR(le32toh(sqh->qh.qh_curqtd));
        hit = 0;
        for (sqtd = exfer->sqtdstart; ; sqtd = sqtd->nextqtd) {
@@ -2523,7 +2618,15 @@
        if (hit && sqtd != NULL) {
                DPRINTFN(1,("ehci_abort_xfer: cur=0x%08x\n", sqtd->physaddr));
                sqh->qh.qh_curqtd = htole32(sqtd->physaddr); /* unlink qTDs */
+               usb_syncmem(&sqh->dma,
+                   sqh->offs + offsetof(ehci_qh_t, qh_curqtd),
+                   sizeof(sqh->qh.qh_curqtd),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
                sqh->qh.qh_qtd.qtd_status = qhstatus;
+               usb_syncmem(&sqh->dma,
+                   sqh->offs + offsetof(ehci_qh_t, qh_qtd.qtd_status),
+                   sizeof(sqh->qh.qh_qtd.qtd_status),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
        } else {
                DPRINTFN(1,("ehci_abort_xfer: no hit\n"));
        }
@@ -2628,7 +2731,10 @@
 {
        struct ehci_xfer *ex = EXFER(xfer);
        ehci_softc_t *sc = xfer->pipe->device->bus->hci_private;
-       /*struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;*/
+       struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
+       usb_device_request_t *req = &xfer->request;
+       int len = UGETW(req->wLength);
+       int rd = req->bmRequestType & UT_READ;
 
        DPRINTFN(10,("ehci_ctrl_done: xfer=%p\n", xfer));
 
@@ -2641,6 +2747,11 @@
        if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) {
                ehci_del_intr_list(ex); /* remove from active list */
                ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL);
+               usb_syncmem(&epipe->u.ctl.reqdma, 0, sizeof *req,
+                   BUS_DMASYNC_POSTWRITE);
+               if (len)
+                       usb_syncmem(&xfer->dmabuf, 0, len,
+                           rd ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
        }
 
        DPRINTFN(5, ("ehci_ctrl_done: length=%d\n", xfer->actlen));
@@ -2729,11 +2840,14 @@
                end->nextqtd = stat;
                end->qtd.qtd_next =
                end->qtd.qtd_altnext = htole32(stat->physaddr);
+               usb_syncmem(&end->dma, end->offs, sizeof(end->qtd),
+                  BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
        } else {
                next = stat;
        }
 
        memcpy(KERNADDR(&epipe->u.ctl.reqdma, 0), req, sizeof *req);
+       usb_syncmem(&epipe->u.ctl.reqdma, 0, sizeof *req, BUS_DMASYNC_PREWRITE);
 
        /* Clear toggle */
        setup->qtd.qtd_status = htole32(
@@ -2749,6 +2863,8 @@
        setup->qtd.qtd_next = setup->qtd.qtd_altnext = htole32(next->physaddr);
        setup->xfer = xfer;
        setup->len = sizeof *req;
+       usb_syncmem(&setup->dma, setup->offs, sizeof(setup->qtd),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
        stat->qtd.qtd_status = htole32(
            EHCI_QTD_ACTIVE |
@@ -2763,6 +2879,8 @@
        stat->qtd.qtd_next = stat->qtd.qtd_altnext = EHCI_NULL;
        stat->xfer = xfer;
        stat->len = 0;
+       usb_syncmem(&stat->dma, stat->offs, sizeof(stat->qtd),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 #ifdef EHCI_DEBUG
        if (ehcidebug > 5) {
@@ -2783,7 +2901,7 @@
 
        /* Insert qTD in QH list. */
        s = splusb();
-       ehci_set_qh_qtd(sqh, setup);
+       ehci_set_qh_qtd(sqh, setup); /* also does usb_syncmem(sqh) */
        if (xfer->timeout && !sc->sc_bus.use_polling) {
                 usb_callout(xfer->timeout_handle, mstohz(xfer->timeout),
                            ehci_timeout, xfer);
@@ -2916,7 +3034,7 @@
 #endif
 
        s = splusb();
-       ehci_set_qh_qtd(sqh, data);
+       ehci_set_qh_qtd(sqh, data); /* also does usb_syncmem(sqh) */
        if (xfer->timeout && !sc->sc_bus.use_polling) {
                usb_callout(xfer->timeout_handle, mstohz(xfer->timeout),
                            ehci_timeout, xfer);
@@ -2972,7 +3090,9 @@
 {
        struct ehci_xfer *ex = EXFER(xfer);
        ehci_softc_t *sc = xfer->pipe->device->bus->hci_private;
-       /*struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;*/
+       struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
+       int endpt = epipe->pipe.endpoint->edesc->bEndpointAddress;
+       int rd = UE_GET_DIR(endpt) == UE_DIR_IN;
 
        DPRINTFN(10,("ehci_bulk_done: xfer=%p, actlen=%d\n",
                     xfer, xfer->actlen));
@@ -2980,6 +3100,8 @@
        if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) {
                ehci_del_intr_list(ex); /* remove from active list */
                ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL);
+               usb_syncmem(&xfer->dmabuf, 0, xfer->length,
+                   rd ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
        }
 
        DPRINTFN(5, ("ehci_bulk_done: length=%d\n", xfer->actlen));
@@ -3086,7 +3208,7 @@
 #endif
 
        s = splusb();
-       ehci_set_qh_qtd(sqh, data);
+       ehci_set_qh_qtd(sqh, data); /* also does usb_syncmem(sqh) */
        if (xfer->timeout && !sc->sc_bus.use_polling) {
                usb_callout(xfer->timeout_handle, mstohz(xfer->timeout),
                    ehci_timeout, xfer);
@@ -3158,6 +3280,8 @@
                xfer->length = len;
                endpt = epipe->pipe.endpoint->edesc->bEndpointAddress;
                isread = UE_GET_DIR(endpt) == UE_DIR_IN;
+               usb_syncmem(&xfer->dmabuf, 0, len,
+                   isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
                sqh = epipe->sqh;
 
                err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer,
@@ -3180,7 +3304,7 @@
 #endif
 
                s = splusb();
-               ehci_set_qh_qtd(sqh, data);
+               ehci_set_qh_qtd(sqh, data); /* also does usb_syncmem(sqh) */
                if (xfer->timeout && !sc->sc_bus.use_polling) {
                        usb_callout(xfer->timeout_handle,
                            mstohz(xfer->timeout), ehci_timeout, xfer);
@@ -3191,6 +3315,10 @@
        } else if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) {
                ehci_del_intr_list(ex); /* remove from active list */
                ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL);
+               endpt = epipe->pipe.endpoint->edesc->bEndpointAddress;
+               isread = UE_GET_DIR(endpt) == UE_DIR_IN;
+               usb_syncmem(&xfer->dmabuf, 0, xfer->length,
+                   isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
        }
 #undef exfer
 }
Index: ehcivar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/ehcivar.h,v
retrieving revision 1.30
diff -u -r1.30 ehcivar.h
--- ehcivar.h   28 Apr 2008 20:23:58 -0000      1.30
+++ ehcivar.h   10 Jun 2008 20:38:47 -0000
@@ -33,6 +33,8 @@
        ehci_qtd_t qtd;
        struct ehci_soft_qtd *nextqtd; /* mirrors nextqtd in TD */
        ehci_physaddr_t physaddr;
+       usb_dma_t dma;                  /* qTD's DMA infos */
+       int offs;                       /* qTD's offset in usb_dma_t */
        usbd_xfer_handle xfer;
        LIST_ENTRY(ehci_soft_qtd) hnext;
        u_int16_t len;
@@ -45,6 +47,8 @@
        struct ehci_soft_qh *next;
        struct ehci_soft_qtd *sqtd;
        ehci_physaddr_t physaddr;
+       usb_dma_t dma;                  /* QH's DMA infos */
+       int offs;                       /* QH's offset in usb_dma_t */
        int islot;
 } ehci_soft_qh_t;
 #define EHCI_SQH_SIZE ((sizeof (struct ehci_soft_qh) + EHCI_QH_ALIGN - 1) / 
EHCI_QH_ALIGN * EHCI_QH_ALIGN)
Index: uhci.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/uhci.c,v
retrieving revision 1.221
diff -u -r1.221 uhci.c
--- uhci.c      6 Jun 2008 11:21:16 -0000       1.221
+++ uhci.c      10 Jun 2008 20:38:47 -0000
@@ -390,6 +392,10 @@
 
        for (; pqh->hlink != sqh; pqh = pqh->hlink) {
 #if defined(DIAGNOSTIC) || defined(UHCI_DEBUG)
+               usb_syncmem(&pqh->dma,
+                   pqh->offs + offsetof(uhci_qh_t, qh_hlink),
+                   sizeof(pqh->qh.qh_hlink),
+                   BUS_DMASYNC_POSTWRITE);
                if (le32toh(pqh->qh.qh_hlink) & UHCI_PTR_T) {
                        printf("uhci_find_prev_qh: QH not found\n");
                        return (NULL);
@@ -458,6 +464,8 @@
        std->td.td_status = htole32(0); /* inactive */
        std->td.td_token = htole32(0);
        std->td.td_buffer = htole32(0);
+       usb_syncmem(&std->dma, std->offs, sizeof(std->td),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
        /* Allocate the dummy QH marking the end and used for looping the QHs.*/
        lsqh = uhci_alloc_sqh(sc);
@@ -468,6 +476,8 @@
        lsqh->elink = std;
        lsqh->qh.qh_elink = htole32(std->physaddr | UHCI_PTR_TD);
        sc->sc_last_qh = lsqh;
+       usb_syncmem(&lsqh->dma, lsqh->offs, sizeof(lsqh->qh),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
        /* Allocate the dummy QH where bulk traffic will be queued. */
        bsqh = uhci_alloc_sqh(sc);
@@ -478,6 +488,8 @@
        bsqh->elink = NULL;
        bsqh->qh.qh_elink = htole32(UHCI_PTR_T);
        sc->sc_bulk_start = sc->sc_bulk_end = bsqh;
+       usb_syncmem(&bsqh->dma, bsqh->offs, sizeof(bsqh->qh),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
        /* Allocate dummy QH where high speed control traffic will be queued. */
        chsqh = uhci_alloc_sqh(sc);
@@ -488,6 +500,8 @@
        chsqh->elink = NULL;
        chsqh->qh.qh_elink = htole32(UHCI_PTR_T);
        sc->sc_hctl_start = sc->sc_hctl_end = chsqh;
+       usb_syncmem(&chsqh->dma, chsqh->offs, sizeof(chsqh->qh),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
        /* Allocate dummy QH where control traffic will be queued. */
        clsqh = uhci_alloc_sqh(sc);
@@ -498,6 +512,8 @@
        clsqh->elink = NULL;
        clsqh->qh.qh_elink = htole32(UHCI_PTR_T);
        sc->sc_lctl_start = sc->sc_lctl_end = clsqh;
+       usb_syncmem(&clsqh->dma, clsqh->offs, sizeof(clsqh->qh),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
        /*
         * Make all (virtual) frame list pointers point to the interrupt
@@ -514,10 +530,14 @@
                std->td.td_status = htole32(UHCI_TD_IOS); /* iso, inactive */
                std->td.td_token = htole32(0);
                std->td.td_buffer = htole32(0);
+               usb_syncmem(&std->dma, std->offs, sizeof(std->td),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
                sqh->hlink = clsqh;
                sqh->qh.qh_hlink = htole32(clsqh->physaddr | UHCI_PTR_QH);
                sqh->elink = NULL;
                sqh->qh.qh_elink = htole32(UHCI_PTR_T);
+               usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
                sc->sc_vframes[i].htd = std;
                sc->sc_vframes[i].etd = std;
                sc->sc_vframes[i].hqh = sqh;
@@ -527,6 +547,10 @@
                     j += UHCI_VFRAMELIST_COUNT)
                        sc->sc_pframes[j] = htole32(std->physaddr);
        }
+       usb_syncmem(&sc->sc_dma, 0,
+           UHCI_FRAMELIST_COUNT * sizeof(uhci_physaddr_t),
+           BUS_DMASYNC_PREWRITE);
+
 
        LIST_INIT(&sc->sc_intrhead);
 
@@ -814,6 +838,9 @@
 {
        char sbuf[128], sbuf2[128];
 
+       
+       usb_syncmem(&p->dma, p->offs, sizeof(p->td),
+           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
        DPRINTFN(-1,("TD(%p) at %08lx = link=0x%08lx status=0x%08lx "
                     "token=0x%08lx buffer=0x%08lx\n",
                     p, (long)p->physaddr,
@@ -838,14 +865,19 @@
                     UHCI_TD_GET_ENDPT(le32toh(p->td.td_token)),
                     UHCI_TD_GET_DT(le32toh(p->td.td_token)),
                     UHCI_TD_GET_MAXLEN(le32toh(p->td.td_token))));
+       usb_syncmem(&p->dma, p->offs, sizeof(p->td),
+           BUS_DMASYNC_PREREAD);
 }
 
 void
 uhci_dump_qh(uhci_soft_qh_t *sqh)
 {
+       usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
        DPRINTFN(-1,("QH(%p) at %08x: hlink=%08x elink=%08x\n", sqh,
            (int)sqh->physaddr, le32toh(sqh->qh.qh_hlink),
            le32toh(sqh->qh.qh_elink)));
+       usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh), BUS_DMASYNC_PREREAD);
 }
 
 
@@ -887,10 +919,13 @@
         */
 
 
+       usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
        if (sqh->hlink != NULL && !(le32toh(sqh->qh.qh_hlink) & UHCI_PTR_T))
                uhci_dump_qhs(sqh->hlink);
        else
                DPRINTF(("No QH\n"));
+       usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh), BUS_DMASYNC_PREREAD);
 
        if (sqh->elink != NULL && !(le32toh(sqh->qh.qh_elink) & UHCI_PTR_T))
                uhci_dump_tds(sqh->elink);
@@ -902,6 +937,7 @@
 uhci_dump_tds(uhci_soft_td_t *std)
 {
        uhci_soft_td_t *td;
+       int stop;
 
        for(td = std; td != NULL; td = td->link.std) {
                uhci_dump_td(td);
@@ -911,8 +947,14 @@
                 * printing the free list in case the queue/TD has
                 * already been moved there (seatbelt).
                 */
-               if (le32toh(td->td.td_link) & UHCI_PTR_T ||
-                   le32toh(td->td.td_link) == 0)
+               usb_syncmem(&td->dma, td->offs + offsetof(uhci_td_t, td_link),
+                   sizeof(td->td.td_link),
+                   BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
+               stop = (le32toh(td->td.td_link) & UHCI_PTR_T ||
+                       le32toh(td->td.td_link) == 0);
+               usb_syncmem(&td->dma, td->offs + offsetof(uhci_td_t, td_link),
+                   sizeof(td->td.td_link), BUS_DMASYNC_PREREAD);
+               if (stop)
                        break;
        }
 }
@@ -1044,6 +1086,10 @@
                /* Note, we don't loop back the soft pointer. */
                sc->sc_last_qh->qh.qh_hlink =
                    htole32(sc->sc_hctl_start->physaddr | UHCI_PTR_QH);
+               usb_syncmem(&sc->sc_last_qh->dma,
+                   sc->sc_last_qh->offs + offsetof(uhci_qh_t, qh_hlink),
+                   sizeof(sc->sc_last_qh->qh.qh_hlink),
+                   BUS_DMASYNC_PREWRITE);
        }
 }
 
@@ -1056,6 +1102,10 @@
        if (--sc->sc_loops == 0) {
                DPRINTFN(5,("uhci_end_loop: remove\n"));
                sc->sc_last_qh->qh.qh_hlink = htole32(UHCI_PTR_T);
+               usb_syncmem(&sc->sc_last_qh->dma,
+                   sc->sc_last_qh->offs + offsetof(uhci_qh_t, qh_hlink),
+                   sizeof(sc->sc_last_qh->qh.qh_hlink),
+                   BUS_DMASYNC_PREWRITE);
        }
 }
 
@@ -1069,11 +1119,20 @@
 
        DPRINTFN(10, ("uhci_add_ctrl: sqh=%p\n", sqh));
        eqh = sc->sc_hctl_end;
+       usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(eqh->qh.qh_hlink),
+           BUS_DMASYNC_POSTWRITE);
        sqh->hlink       = eqh->hlink;
        sqh->qh.qh_hlink = eqh->qh.qh_hlink;
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(sqh->qh.qh_hlink),
+           BUS_DMASYNC_PREWRITE);
        eqh->hlink       = sqh;
        eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH);
        sc->sc_hctl_end = sqh;
+       usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(eqh->qh.qh_hlink),
+           BUS_DMASYNC_PREWRITE);
 #ifdef UHCI_CTL_LOOP
        uhci_add_loop(sc);
 #endif
@@ -1099,14 +1158,26 @@
         * In this case we set the T bit and wait a little for the HC
         * to stop looking at the TD.
         */
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink),
+           sizeof(sqh->qh.qh_elink),
+           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
        if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) {
                sqh->qh.qh_elink = htole32(UHCI_PTR_T);
+               usb_syncmem(&sqh->dma,
+                   sqh->offs + offsetof(uhci_qh_t, qh_elink),
+                   sizeof(sqh->qh.qh_elink),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
                delay(UHCI_QH_REMOVE_DELAY);
        }
 
        pqh = uhci_find_prev_qh(sc->sc_hctl_start, sqh);
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(sqh->qh.qh_hlink), BUS_DMASYNC_POSTWRITE);
        pqh->hlink = sqh->hlink;
        pqh->qh.qh_hlink = sqh->qh.qh_hlink;
+       usb_syncmem(&pqh->dma, pqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(pqh->qh.qh_hlink),
+           BUS_DMASYNC_PREWRITE);
        delay(UHCI_QH_REMOVE_DELAY);
        if (sc->sc_hctl_end == sqh)
                sc->sc_hctl_end = pqh;
@@ -1122,10 +1193,19 @@
 
        DPRINTFN(10, ("uhci_add_ls_ctrl: sqh=%p\n", sqh));
        eqh = sc->sc_lctl_end;
+       usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(eqh->qh.qh_hlink),
+           BUS_DMASYNC_POSTWRITE);
        sqh->hlink = eqh->hlink;
        sqh->qh.qh_hlink = eqh->qh.qh_hlink;
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(sqh->qh.qh_hlink),
+           BUS_DMASYNC_PREWRITE);
        eqh->hlink = sqh;
        eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH);
+       usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(eqh->qh.qh_hlink),
+           BUS_DMASYNC_PREWRITE);
        sc->sc_lctl_end = sqh;
 }
 
@@ -1139,13 +1219,25 @@
 
        DPRINTFN(10, ("uhci_remove_ls_ctrl: sqh=%p\n", sqh));
        /* See comment in uhci_remove_hs_ctrl() */
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink),
+           sizeof(sqh->qh.qh_elink),
+           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
        if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) {
                sqh->qh.qh_elink = htole32(UHCI_PTR_T);
+               usb_syncmem(&sqh->dma,
+                   sqh->offs + offsetof(uhci_qh_t, qh_elink),
+                   sizeof(sqh->qh.qh_elink),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
                delay(UHCI_QH_REMOVE_DELAY);
        }
        pqh = uhci_find_prev_qh(sc->sc_lctl_start, sqh);
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(sqh->qh.qh_hlink), BUS_DMASYNC_POSTWRITE);
        pqh->hlink = sqh->hlink;
        pqh->qh.qh_hlink = sqh->qh.qh_hlink;
+       usb_syncmem(&pqh->dma, pqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(pqh->qh.qh_hlink),
+           BUS_DMASYNC_PREWRITE);
        delay(UHCI_QH_REMOVE_DELAY);
        if (sc->sc_lctl_end == sqh)
                sc->sc_lctl_end = pqh;
@@ -1161,10 +1253,19 @@
 
        DPRINTFN(10, ("uhci_add_bulk: sqh=%p\n", sqh));
        eqh = sc->sc_bulk_end;
+       usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(eqh->qh.qh_hlink),
+           BUS_DMASYNC_POSTWRITE);
        sqh->hlink = eqh->hlink;
        sqh->qh.qh_hlink = eqh->qh.qh_hlink;
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(sqh->qh.qh_hlink),
+           BUS_DMASYNC_PREWRITE);
        eqh->hlink = sqh;
        eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH);
+       usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(eqh->qh.qh_hlink),
+           BUS_DMASYNC_PREWRITE);
        sc->sc_bulk_end = sqh;
        uhci_add_loop(sc);
 }
@@ -1180,13 +1281,24 @@
        DPRINTFN(10, ("uhci_remove_bulk: sqh=%p\n", sqh));
        uhci_rem_loop(sc);
        /* See comment in uhci_remove_hs_ctrl() */
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink),
+           sizeof(sqh->qh.qh_elink),
+           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
        if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) {
                sqh->qh.qh_elink = htole32(UHCI_PTR_T);
+               usb_syncmem(&sqh->dma,
+                   sqh->offs + offsetof(uhci_qh_t, qh_elink),
+                   sizeof(sqh->qh.qh_elink),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
                delay(UHCI_QH_REMOVE_DELAY);
        }
        pqh = uhci_find_prev_qh(sc->sc_bulk_start, sqh);
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(sqh->qh.qh_hlink), BUS_DMASYNC_POSTWRITE);
        pqh->hlink       = sqh->hlink;
        pqh->qh.qh_hlink = sqh->qh.qh_hlink;
+       usb_syncmem(&pqh->dma, pqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(pqh->qh.qh_hlink), BUS_DMASYNC_PREWRITE);
        delay(UHCI_QH_REMOVE_DELAY);
        if (sc->sc_bulk_end == sqh)
                sc->sc_bulk_end = pqh;
@@ -1354,10 +1485,21 @@
         * is an error somewhere in the middle, or whether there was a
         * short packet (SPD and not ACTIVE).
         */
+       usb_syncmem(&lstd->dma,
+           lstd->offs + offsetof(uhci_td_t, td_status),
+           sizeof(lstd->td.td_status),
+           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
        if (le32toh(lstd->td.td_status) & UHCI_TD_ACTIVE) {
                DPRINTFN(12, ("uhci_check_intr: active ii=%p\n", ii));
                for (std = ii->stdstart; std != lstd; std = std->link.std) {
+                       usb_syncmem(&std->dma,
+                           std->offs + offsetof(uhci_td_t, td_status),
+                           sizeof(std->td.td_status),
+                           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
                        status = le32toh(std->td.td_status);
+                       usb_syncmem(&std->dma,
+                           std->offs + offsetof(uhci_td_t, td_status),
+                           sizeof(std->td.td_status), BUS_DMASYNC_PREREAD);
                        /* If there's an active TD the xfer isn't done. */
                        if (status & UHCI_TD_ACTIVE)
                                break;
@@ -1365,6 +1507,10 @@
                        if (status & UHCI_TD_STALLED)
                                goto done;
                        /* We want short packets, and it is short: it's done */
+                       usb_syncmem(&std->dma,
+                           std->offs + offsetof(uhci_td_t, td_token),
+                           sizeof(std->td.td_token),
+                           BUS_DMASYNC_POSTWRITE);
                        if ((status & UHCI_TD_SPD) &&
                              UHCI_TD_GET_ACTLEN(status) <
                              UHCI_TD_GET_MAXLEN(le32toh(std->td.td_token)))
@@ -1372,6 +1518,10 @@
                }
                DPRINTFN(12, ("uhci_check_intr: ii=%p std=%p still active\n",
                              ii, ii->stdstart));
+               usb_syncmem(&lstd->dma,
+                   lstd->offs + offsetof(uhci_td_t, td_status),
+                   sizeof(lstd->td.td_status),
+                   BUS_DMASYNC_PREREAD);
                return;
        }
  done:
@@ -1429,6 +1579,10 @@
 #endif
                        if (++n >= UHCI_VFRAMELIST_COUNT)
                                n = 0;
+                       usb_syncmem(&std->dma,
+                           std->offs + offsetof(uhci_td_t, td_status),
+                           sizeof(std->td.td_status),
+                           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
                        status = le32toh(std->td.td_status);
                        len = UHCI_TD_GET_ACTLEN(status);
                        xfer->frlengths[i] = len;
@@ -1450,6 +1604,8 @@
        /* The transfer is done, compute actual length and status. */
        actlen = 0;
        for (std = ii->stdstart; std != NULL; std = std->link.std) {
+               usb_syncmem(&std->dma, std->offs, sizeof(std->td),
+                   BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
                nstatus = le32toh(std->td.td_status);
                if (nstatus & UHCI_TD_ACTIVE)
                        break;
@@ -1665,6 +1821,8 @@
                        offs = i * UHCI_STD_SIZE;
                        std = KERNADDR(&dma, offs);
                        std->physaddr = DMAADDR(&dma, offs);
+                       std->dma = dma;
+                       std->offs = offs;
                        std->link.std = sc->sc_freetds;
                        sc->sc_freetds = std;
                }
@@ -1708,6 +1866,8 @@
                        offs = i * UHCI_SQH_SIZE;
                        sqh = KERNADDR(&dma, offs);
                        sqh->physaddr = DMAADDR(&dma, offs);
+                       sqh->dma = dma;
+                       sqh->offs = offs;
                        sqh->hlink = sc->sc_freeqhs;
                        sc->sc_freeqhs = sqh;
                }
@@ -1778,6 +1938,8 @@
                status |= UHCI_TD_LS;
        if (flags & USBD_SHORT_XFER_OK)
                status |= UHCI_TD_SPD;
+       usb_syncmem(dma, 0, len,
+           rd ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
        for (i = ntd; i >= 0; i--) {
                p = uhci_alloc_std(sc);
                if (p == NULL) {
@@ -1802,6 +1964,8 @@
                    htole32(rd ? UHCI_TD_IN (l, endpt, addr, tog) :
                                 UHCI_TD_OUT(l, endpt, addr, tog));
                p->td.td_buffer = htole32(DMAADDR(dma, i * maxp));
+               usb_syncmem(&p->dma, p->offs, sizeof(p->td),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
                tog ^= 1;
        }
        *sp = lastp;
@@ -1876,6 +2040,11 @@
        if (err)
                return (err);
        dataend->td.td_status |= htole32(UHCI_TD_IOC);
+       usb_syncmem(&dataend->dma,
+           dataend->offs + offsetof(uhci_td_t, td_status),
+           sizeof(dataend->td.td_status),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+
 
 #ifdef UHCI_DEBUG
        if (uhcidebug > 8) {
@@ -1897,6 +2066,9 @@
 
        sqh->elink = data;
        sqh->qh.qh_elink = htole32(data->physaddr | UHCI_PTR_TD);
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink),
+           sizeof(sqh->qh.qh_elink),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
        s = splusb();
        uhci_add_bulk(sc, sqh);
@@ -1992,8 +2164,17 @@
        xfer->status = status;  /* make software ignore it */
        usb_uncallout(xfer->timeout_handle, uhci_timeout, ii);
        DPRINTFN(1,("uhci_abort_xfer: stop ii=%p\n", ii));
-       for (std = ii->stdstart; std != NULL; std = std->link.std)
+       for (std = ii->stdstart; std != NULL; std = std->link.std) {
+               usb_syncmem(&std->dma,
+                   std->offs + offsetof(uhci_td_t, td_status),
+                   sizeof(std->td.td_status),
+                   BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
                std->td.td_status &= htole32(~(UHCI_TD_ACTIVE | UHCI_TD_IOC));
+               usb_syncmem(&std->dma,
+                   std->offs + offsetof(uhci_td_t, td_status),
+                   sizeof(std->td.td_status),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+       }
        splx(s);
 
        /*
@@ -2132,6 +2313,10 @@
        if (err)
                return (err);
        dataend->td.td_status |= htole32(UHCI_TD_IOC);
+       usb_syncmem(&dataend->dma,
+           dataend->offs + offsetof(uhci_td_t, td_status),
+           sizeof(dataend->td.td_status),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 #ifdef UHCI_DEBUG
        if (uhcidebug > 10) {
@@ -2159,6 +2344,10 @@
                sqh = upipe->u.intr.qhs[i];
                sqh->elink = data;
                sqh->qh.qh_elink = htole32(data->physaddr | UHCI_PTR_TD);
+               usb_syncmem(&sqh->dma,
+                   sqh->offs + offsetof(uhci_qh_t, qh_elink),
+                   sizeof(sqh->qh.qh_elink),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
        }
        uhci_add_intr_info(sc, ii);
        xfer->status = USBD_IN_PROGRESS;
@@ -2272,12 +2461,17 @@
                next = data;
                dataend->link.std = stat;
                dataend->td.td_link = htole32(stat->physaddr | UHCI_PTR_VF | 
UHCI_PTR_TD);
+               usb_syncmem(&dataend->dma,
+                   dataend->offs + offsetof(uhci_td_t, td_link),
+                   sizeof(dataend->td.td_link),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
        } else {
                next = stat;
        }
        upipe->u.ctl.length = len;
 
        memcpy(KERNADDR(&upipe->u.ctl.reqdma, 0), req, sizeof *req);
+       usb_syncmem(&upipe->u.ctl.reqdma, 0, sizeof *req, BUS_DMASYNC_PREREAD);
 
        setup->link.std = next;
        setup->td.td_link = htole32(next->physaddr | UHCI_PTR_VF | UHCI_PTR_TD);
@@ -2285,6 +2479,8 @@
                UHCI_TD_ACTIVE);
        setup->td.td_token = htole32(UHCI_TD_SETUP(sizeof *req, endpt, addr));
        setup->td.td_buffer = htole32(DMAADDR(&upipe->u.ctl.reqdma, 0));
+       usb_syncmem(&setup->dma, setup->offs, sizeof(setup->td),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
        stat->link.std = NULL;
        stat->td.td_link = htole32(UHCI_PTR_T);
@@ -2294,6 +2490,8 @@
                htole32(isread ? UHCI_TD_OUT(0, endpt, addr, 1) :
                                 UHCI_TD_IN (0, endpt, addr, 1));
        stat->td.td_buffer = htole32(0);
+       usb_syncmem(&stat->dma, stat->offs, sizeof(stat->td),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 #ifdef UHCI_DEBUG
        if (uhcidebug > 10) {
@@ -2315,6 +2513,9 @@
 
        sqh->elink = setup;
        sqh->qh.qh_elink = htole32(setup->physaddr | UHCI_PTR_TD);
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink),
+           sizeof(sqh->qh.qh_elink),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
        s = splusb();
        if (dev->speed == USB_SPEED_LOW)
@@ -2393,8 +2594,9 @@
        uhci_softc_t *sc = dev->bus->hci_private;
        struct iso *iso = &upipe->u.iso;
        uhci_soft_td_t *std;
-       u_int32_t buf, len, status;
+       u_int32_t buf, len, status, offs;
        int s, i, next, nframes;
+       int rd = UE_GET_DIR(upipe->pipe.endpoint->edesc->bEndpointAddress) == 
UE_DIR_IN;
 
        DPRINTFN(5,("uhci_device_isoc_enter: used=%d next=%d xfer=%p "
                    "nframes=%d\n",
@@ -2425,6 +2627,7 @@
        UXFER(xfer)->curframe = next;
 
        buf = DMAADDR(&xfer->dmabuf, 0);
+       offs = 0;
        status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(0) |
                                     UHCI_TD_ACTIVE |
                                     UHCI_TD_IOS);
@@ -2436,11 +2639,15 @@
                        next = 0;
                len = xfer->frlengths[i];
                std->td.td_buffer = htole32(buf);
+               usb_syncmem(&xfer->dmabuf, offs, len, 
+                   rd ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
                if (i == nframes - 1)
                        status |= UHCI_TD_IOC;
                std->td.td_status = htole32(status);
                std->td.td_token &= htole32(~UHCI_TD_MAXLEN_MASK);
                std->td.td_token |= htole32(UHCI_TD_SET_MAXLEN(len));
+               usb_syncmem(&std->dma, std->offs, sizeof(std->td),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 #ifdef UHCI_DEBUG
                if (uhcidebug > 5) {
                        DPRINTFN(5,("uhci_device_isoc_enter: TD %d\n", i));
@@ -2448,6 +2655,7 @@
                }
 #endif
                buf += len;
+               offs += len;
        }
        iso->next = next;
        iso->inuse += xfer->nframes;
@@ -2531,7 +2739,19 @@
        maxlen = 0;
        for (i = 0; i < nframes; i++) {
                std = stds[n];
+               usb_syncmem(&std->dma,
+                   std->offs + offsetof(uhci_td_t, td_status),
+                   sizeof(std->td.td_status),
+                   BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
                std->td.td_status &= htole32(~(UHCI_TD_ACTIVE | UHCI_TD_IOC));
+               usb_syncmem(&std->dma,
+                   std->offs + offsetof(uhci_td_t, td_status),
+                   sizeof(std->td.td_status),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+               usb_syncmem(&std->dma,
+                   std->offs + offsetof(uhci_td_t, td_token),
+                   sizeof(std->td.td_token),
+                   BUS_DMASYNC_POSTWRITE);
                len = UHCI_TD_GET_MAXLEN(le32toh(std->td.td_token));
                if (len > maxlen)
                        maxlen = len;
@@ -2569,8 +2789,18 @@
         */
        iso = &upipe->u.iso;
 
-       for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++)
-               iso->stds[i]->td.td_status &= htole32(~UHCI_TD_ACTIVE);
+       for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) {
+               std = iso->stds[i];
+               usb_syncmem(&std->dma,
+                   std->offs + offsetof(uhci_td_t, td_status),
+                   sizeof(std->td.td_status),
+                   BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
+               std->td.td_status &= htole32(~UHCI_TD_ACTIVE);
+               usb_syncmem(&std->dma,
+                   std->offs + offsetof(uhci_td_t, td_status),
+                   sizeof(std->td.td_status),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+       }
        usb_delay_ms(&sc->sc_bus, 2); /* wait for completion */
 
        s = splusb();
@@ -2587,7 +2817,15 @@
                        return;
                }
                vstd->link = std->link;
+               usb_syncmem(&std->dma,
+                   std->offs + offsetof(uhci_td_t, td_link),
+                   sizeof(std->td.td_link),
+                   BUS_DMASYNC_POSTWRITE);
                vstd->td.td_link = std->td.td_link;
+               usb_syncmem(&vstd->dma,
+                   vstd->offs + offsetof(uhci_td_t, td_link),
+                   sizeof(vstd->td.td_link),
+                   BUS_DMASYNC_PREWRITE);
                uhci_free_std(sc, std);
        }
        splx(s);
@@ -2623,6 +2861,8 @@
                        goto bad;
                std->td.td_status = htole32(UHCI_TD_IOS); /* iso, inactive */
                std->td.td_token = htole32(token);
+               usb_syncmem(&std->dma, std->offs, sizeof(std->td),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
                iso->stds[i] = std;
        }
 
@@ -2631,10 +2871,22 @@
        for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) {
                std = iso->stds[i];
                vstd = sc->sc_vframes[i].htd;
+               usb_syncmem(&vstd->dma,
+                   vstd->offs + offsetof(uhci_td_t, td_link),
+                   sizeof(vstd->td.td_link),
+                   BUS_DMASYNC_POSTWRITE);
                std->link = vstd->link;
                std->td.td_link = vstd->td.td_link;
+               usb_syncmem(&std->dma,
+                   std->offs + offsetof(uhci_td_t, td_link),
+                   sizeof(std->td.td_link),
+                   BUS_DMASYNC_PREWRITE);
                vstd->link.std = std;
                vstd->td.td_link = htole32(std->physaddr | UHCI_PTR_TD);
+               usb_syncmem(&vstd->dma,
+                   vstd->offs + offsetof(uhci_td_t, td_link),
+                   sizeof(vstd->td.td_link),
+                   BUS_DMASYNC_PREWRITE);
        }
        splx(s);
 
@@ -2654,6 +2906,10 @@
 uhci_device_isoc_done(usbd_xfer_handle xfer)
 {
        uhci_intr_info_t *ii = &UXFER(xfer)->iinfo;
+       struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
+       int i, offs;
+       int rd = UE_GET_DIR(upipe->pipe.endpoint->edesc->bEndpointAddress) == 
UE_DIR_IN;
+
 
        DPRINTFN(4, ("uhci_isoc_done: length=%d, busy_free=0x%08x\n",
                        xfer->actlen, xfer->busy_free));
@@ -2676,9 +2932,24 @@
 #endif
 
        /* Turn off the interrupt since it is active even if the TD is not. */
+       usb_syncmem(&ii->stdend->dma,
+           ii->stdend->offs + offsetof(uhci_td_t, td_status),
+           sizeof(ii->stdend->td.td_status),
+           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
        ii->stdend->td.td_status &= htole32(~UHCI_TD_IOC);
+       usb_syncmem(&ii->stdend->dma,
+           ii->stdend->offs + offsetof(uhci_td_t, td_status),
+           sizeof(ii->stdend->td.td_status),
+           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
        uhci_del_intr_info(ii); /* remove from active list */
+
+       offs = 0;
+       for (i = 0; i < xfer->nframes; i++) {
+               usb_syncmem(&xfer->dmabuf, offs, xfer->frlengths[i],
+                   rd ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
+               offs += xfer->frlengths[i];
+       }
 }
 
 void
@@ -2688,7 +2959,7 @@
        uhci_softc_t *sc = ii->sc;
        struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
        uhci_soft_qh_t *sqh;
-       int i, npoll;
+       int i, npoll, isread;
 
        DPRINTFN(5, ("uhci_device_intr_done: length=%d\n", xfer->actlen));
 
@@ -2697,6 +2968,10 @@
                sqh = upipe->u.intr.qhs[i];
                sqh->elink = NULL;
                sqh->qh.qh_elink = htole32(UHCI_PTR_T);
+               usb_syncmem(&sqh->dma,
+                   sqh->offs + offsetof(uhci_qh_t, qh_elink),
+                   sizeof(sqh->qh.qh_elink),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
        }
        uhci_free_std_chain(sc, ii->stdstart, NULL);
 
@@ -2710,7 +2985,15 @@
                uhci_alloc_std_chain(upipe, sc, xfer->length,
                                     upipe->u.intr.isread, xfer->flags,
                                     &xfer->dmabuf, &data, &dataend);
+               usb_syncmem(&dataend->dma,
+                   dataend->offs + offsetof(uhci_td_t, td_status),
+                   sizeof(dataend->td.td_status),
+                   BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
                dataend->td.td_status |= htole32(UHCI_TD_IOC);
+               usb_syncmem(&dataend->dma,
+                   dataend->offs + offsetof(uhci_td_t, td_status),
+                   sizeof(dataend->td.td_status),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 #ifdef UHCI_DEBUG
                if (uhcidebug > 10) {
@@ -2732,6 +3015,10 @@
                        sqh = upipe->u.intr.qhs[i];
                        sqh->elink = data;
                        sqh->qh.qh_elink = htole32(data->physaddr | 
UHCI_PTR_TD);
+                       usb_syncmem(&sqh->dma,
+                           sqh->offs + offsetof(uhci_qh_t, qh_elink),
+                           sizeof(sqh->qh.qh_elink),
+                           BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
                }
                xfer->status = USBD_IN_PROGRESS;
                /* The ii is already on the examined list, just leave it. */
@@ -2740,6 +3027,10 @@
                if (uhci_active_intr_info(ii))
                        uhci_del_intr_info(ii);
        }
+
+       isread = UE_GET_DIR(upipe->pipe.endpoint->edesc->bEndpointAddress) == 
UE_DIR_IN;
+       usb_syncmem(&xfer->dmabuf, 0, xfer->length, 
+           isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
 }
 
 /* Deallocate request data structures */
@@ -2749,6 +3040,8 @@
        uhci_intr_info_t *ii = &UXFER(xfer)->iinfo;
        uhci_softc_t *sc = ii->sc;
        struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
+       int len = UGETW(xfer->request.wLength);
+       int isread = (xfer->request.bmRequestType & UT_READ);
 
 #ifdef DIAGNOSTIC
        if (!(xfer->rqflags & URQ_REQUEST))
@@ -2768,6 +3061,13 @@
        if (upipe->u.ctl.length != 0)
                uhci_free_std_chain(sc, ii->stdstart->link.std, ii->stdend);
 
+       if (len) {
+               usb_syncmem(&xfer->dmabuf, 0, len, 
+                   isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
+       }
+       usb_syncmem(&upipe->u.ctl.reqdma, 0,
+           sizeof(usb_device_request_t),  BUS_DMASYNC_POSTREAD);
+
        DPRINTFN(5, ("uhci_device_ctrl_done: length=%d\n", xfer->actlen));
 }
 
@@ -2804,10 +3104,19 @@
        DPRINTFN(4, ("uhci_add_intr: n=%d sqh=%p\n", sqh->pos, sqh));
 
        eqh = vf->eqh;
+       usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(eqh->qh.qh_hlink),
+           BUS_DMASYNC_POSTWRITE);
        sqh->hlink       = eqh->hlink;
        sqh->qh.qh_hlink = eqh->qh.qh_hlink;
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(sqh->qh.qh_hlink),
+           BUS_DMASYNC_PREWRITE);
        eqh->hlink       = sqh;
        eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH);
+       usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(eqh->qh.qh_hlink),
+           BUS_DMASYNC_PREWRITE);
        vf->eqh = sqh;
        vf->bandwidth++;
 }
@@ -2822,14 +3131,28 @@
        DPRINTFN(4, ("uhci_remove_intr: n=%d sqh=%p\n", sqh->pos, sqh));
 
        /* See comment in uhci_remove_ctrl() */
+
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink),
+           sizeof(sqh->qh.qh_elink),
+           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
        if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) {
                sqh->qh.qh_elink = htole32(UHCI_PTR_T);
+               usb_syncmem(&sqh->dma,
+                   sqh->offs + offsetof(uhci_qh_t, qh_elink),
+                   sizeof(sqh->qh.qh_elink),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
                delay(UHCI_QH_REMOVE_DELAY);
        }
 
        pqh = uhci_find_prev_qh(vf->hqh, sqh);
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(sqh->qh.qh_hlink),
+           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
        pqh->hlink       = sqh->hlink;
        pqh->qh.qh_hlink = sqh->qh.qh_hlink;
+       usb_syncmem(&pqh->dma, pqh->offs + offsetof(uhci_qh_t, qh_hlink),
+           sizeof(pqh->qh.qh_hlink),
+           BUS_DMASYNC_PREWRITE);
        delay(UHCI_QH_REMOVE_DELAY);
        if (vf->eqh == sqh)
                vf->eqh = pqh;
@@ -2877,6 +3200,10 @@
                upipe->u.intr.qhs[i] = sqh = uhci_alloc_sqh(sc);
                sqh->elink = NULL;
                sqh->qh.qh_elink = htole32(UHCI_PTR_T);
+               usb_syncmem(&sqh->dma,
+                   sqh->offs + offsetof(uhci_qh_t, qh_elink),
+                   sizeof(sqh->qh.qh_elink),
+                   BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
                sqh->pos = MOD(i * ival + bestoffs);
        }
 #undef MOD
Index: uhcivar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/uhcivar.h,v
retrieving revision 1.44
diff -u -r1.44 uhcivar.h
--- uhcivar.h   28 Apr 2008 20:23:59 -0000      1.44
+++ uhcivar.h   10 Jun 2008 20:38:47 -0000
@@ -87,6 +87,8 @@
        uhci_td_t td;                   /* The real TD, must be first */
        uhci_soft_td_qh_t link;         /* soft version of the td_link field */
        uhci_physaddr_t physaddr;       /* TD's physical address. */
+       usb_dma_t dma;                  /* TD's DMA infos */
+       int offs;                       /* TD's offset in usb_dma_t */
 };
 /*
  * Make the size such that it is a multiple of UHCI_TD_ALIGN.  This way
@@ -106,6 +108,8 @@
        uhci_soft_td_t *elink;          /* soft version of qh_elink */
        uhci_physaddr_t physaddr;       /* QH's physical address. */
        int pos;                        /* Timeslot position */
+       usb_dma_t dma;                  /* QH's DMA infos */
+       int offs;                       /* QH's offset in usb_dma_t */
 };
 /* See comment about UHCI_STD_SIZE. */
 #define UHCI_SQH_SIZE ((sizeof (struct uhci_soft_qh) + UHCI_QH_ALIGN - 1) / 
UHCI_QH_ALIGN * UHCI_QH_ALIGN)
Index: usb_mem.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/usb_mem.c,v
retrieving revision 1.36
diff -u -r1.36 usb_mem.c
--- usb_mem.c   21 May 2008 17:19:44 -0000      1.36
+++ usb_mem.c   10 Jun 2008 20:38:47 -0000
@@ -287,6 +287,13 @@
        DPRINTFN(5, ("usb_freemem: frag=%p\n", f));
 }
 
+void
+usb_syncmem(usb_dma_t *p, bus_addr_t offset, bus_size_t len, int ops)
+{
+       bus_dmamap_sync(p->block->tag, p->block->map, p->offs + offset,
+           len, ops);
+}
+
 
 #ifdef __NetBSD__
 usbd_status
Index: usb_mem.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/usb_mem.h,v
retrieving revision 1.26
diff -u -r1.26 usb_mem.h
--- usb_mem.h   21 May 2008 17:19:44 -0000      1.26
+++ usb_mem.h   10 Jun 2008 20:38:47 -0000
@@ -52,6 +52,7 @@
 
 usbd_status    usb_allocmem(usbd_bus_handle,size_t,size_t, usb_dma_t *);
 void           usb_freemem(usbd_bus_handle, usb_dma_t *);
+void           usb_syncmem(usb_dma_t *, bus_addr_t, bus_size_t, int ops);
 
 #ifdef __NetBSD__
 struct extent;


Home | Main Index | Thread Index | Old Index