Source-Changes-HG archive

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

[src/trunk]: src/sys/arch Change the way that DMA map syncs are done. Instea...



details:   https://anonhg.NetBSD.org/src/rev/5bd181610619
branches:  trunk
changeset: 534505:5bd181610619
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Sun Jul 28 17:54:05 2002 +0000

description:
Change the way that DMA map syncs are done.  Instead of remembering
the virtual address for each DMA segment, just cache a pointer to the
original buffer/buftype used to load the DMA map, and use that.  This
lets us shrink the bus_dma_segment_t down from 12 bytes to 8, and the
cache flushing is also more efficient.

Tested on an i80321 -- changes to others are mechanical.

diffstat:

 sys/arch/arm/arm32/bus_dma.c             |  206 +++++++++++++++++++++++-------
 sys/arch/arm/include/bus.h               |   18 +-
 sys/arch/arm/xscale/i80312_pci_dma.c     |   10 +-
 sys/arch/arm/xscale/i80321_local_dma.c   |   10 +-
 sys/arch/arm/xscale/i80321_pci_dma.c     |   10 +-
 sys/arch/evbarm/integrator/int_bus_dma.c |   10 +-
 6 files changed, 199 insertions(+), 65 deletions(-)

diffs (truncated from 544 to 300 lines):

diff -r e4108075e938 -r 5bd181610619 sys/arch/arm/arm32/bus_dma.c
--- a/sys/arch/arm/arm32/bus_dma.c      Sun Jul 28 15:41:00 2002 +0000
+++ b/sys/arch/arm/arm32/bus_dma.c      Sun Jul 28 17:54:05 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bus_dma.c,v 1.13 2002/06/28 15:21:00 briggs Exp $      */
+/*     $NetBSD: bus_dma.c,v 1.14 2002/07/28 17:54:05 thorpej Exp $     */
 
 /*-
  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@@ -106,6 +106,8 @@
        map->_dm_maxsegsz = maxsegsz;
        map->_dm_boundary = boundary;
        map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT);
+       map->_dm_origbuf = NULL;
+       map->_dm_buftype = ARM32_BUFTYPE_INVALID;
        map->_dm_proc = NULL;
        map->dm_mapsize = 0;            /* no valid mappings */
        map->dm_nsegs = 0;
@@ -134,6 +136,8 @@
         */
        map->dm_mapsize = 0;
        map->dm_nsegs = 0;
+       map->_dm_origbuf = NULL;
+       map->_dm_buftype = ARM32_BUFTYPE_INVALID;
        map->_dm_proc = NULL;
 
        free(map, M_DEVBUF);
@@ -170,6 +174,8 @@
        if (error == 0) {
                map->dm_mapsize = buflen;
                map->dm_nsegs = seg + 1;
+               map->_dm_origbuf = buf;
+               map->_dm_buftype = ARM32_BUFTYPE_LINEAR;
                map->_dm_proc = p;
        }
 #ifdef DEBUG_DMA
@@ -219,6 +225,8 @@
        if (error == 0) {
                map->dm_mapsize = m0->m_pkthdr.len;
                map->dm_nsegs = seg + 1;
+               map->_dm_origbuf = m0;
+               map->_dm_buftype = ARM32_BUFTYPE_MBUF;
                map->_dm_proc = NULL;   /* always kernel */
        }
 #ifdef DEBUG_DMA
@@ -278,6 +286,8 @@
        if (error == 0) {
                map->dm_mapsize = uio->uio_resid;
                map->dm_nsegs = seg + 1;
+               map->_dm_origbuf = uio;
+               map->_dm_buftype = ARM32_BUFTYPE_UIO;
                map->_dm_proc = p;
        }
        return (error);
@@ -313,9 +323,137 @@
         */
        map->dm_mapsize = 0;
        map->dm_nsegs = 0;
+       map->_dm_origbuf = NULL;
+       map->_dm_buftype = ARM32_BUFTYPE_INVALID;
        map->_dm_proc = NULL;
 }
 
+static void
+_bus_dmamap_sync_linear(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
+    bus_size_t len, int ops)
+{
+       vaddr_t addr = (vaddr_t) map->_dm_origbuf;
+
+       addr += offset;
+       len -= offset;
+
+       switch (ops) {
+       case BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE:
+               cpu_dcache_wbinv_range(addr, len);
+               break;
+
+       case BUS_DMASYNC_PREREAD:
+#if 1
+               cpu_dcache_wbinv_range(addr, len);
+#else
+               cpu_dcache_inv_range(addr, len);
+#endif
+               break;
+
+       case BUS_DMASYNC_PREWRITE:
+               cpu_dcache_wb_range(addr, len);
+               break;
+       }
+}
+
+static void
+_bus_dmamap_sync_mbuf(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
+    bus_size_t len, int ops)
+{
+       struct mbuf *m, *m0 = map->_dm_origbuf;
+       bus_size_t minlen, moff;
+       vaddr_t maddr;
+
+       for (moff = offset, m = m0; m != NULL && len != 0;
+            m = m->m_next) {
+               /* Find the beginning mbuf. */
+               if (moff >= m->m_len) {
+                       moff -= m->m_len;
+                       continue;
+               }
+
+               /*
+                * Now at the first mbuf to sync; nail each one until
+                * we have exhausted the length.
+                */
+               minlen = m->m_len - moff;
+               if (len < minlen)
+                       minlen = len;
+
+               maddr = mtod(m, vaddr_t);
+               maddr += moff;
+
+               switch (ops) {
+               case BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE:
+                       cpu_dcache_wbinv_range(maddr, minlen);
+                       break;
+
+               case BUS_DMASYNC_PREREAD:
+#if 1
+                       cpu_dcache_wbinv_range(maddr, minlen);
+#else
+                       cpu_dcache_inv_range(maddr, minlen);
+#endif
+                       break;
+
+               case BUS_DMASYNC_PREWRITE:
+                       cpu_dcache_wb_range(maddr, minlen);
+                       break;
+               }
+               moff = 0;
+               len -= minlen;
+       }
+}
+
+static void
+_bus_dmamap_sync_uio(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
+    bus_size_t len, int ops)
+{
+       struct uio *uio = map->_dm_origbuf;
+       struct iovec *iov;
+       bus_size_t minlen, ioff;
+       vaddr_t addr;
+
+       for (iov = uio->uio_iov, ioff = offset; len != 0; iov++) {
+               /* Find the beginning iovec. */
+               if (ioff >= iov->iov_len) {
+                       ioff -= iov->iov_len;
+                       continue;
+               }
+
+               /*
+                * Now at the first iovec to sync; nail each one until
+                * we have exhausted the length.
+                */
+               minlen = iov->iov_len - ioff;
+               if (len < minlen)
+                       minlen = len;
+
+               addr = (vaddr_t) iov->iov_base;
+               addr += ioff;
+
+               switch (ops) {
+               case BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE:
+                       cpu_dcache_wbinv_range(addr, minlen);
+                       break;
+
+               case BUS_DMASYNC_PREREAD:
+#if 1
+                       cpu_dcache_wbinv_range(addr, minlen);
+#else
+                       cpu_dcache_inv_range(addr, minlen);
+#endif
+                       break;
+
+               case BUS_DMASYNC_PREWRITE:
+                       cpu_dcache_wb_range(addr, minlen);
+                       break;
+               }
+               ioff = 0;
+               len -= minlen;
+       }
+}
+
 /*
  * Common function for DMA map synchronization.  May be called
  * by bus-specific DMA map synchronization functions.
@@ -332,9 +470,6 @@
 _bus_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
     bus_size_t len, int ops)
 {
-       bus_size_t minlen;
-       bus_addr_t addr;
-       int i;
 
 #ifdef DEBUG_DMA
        printf("dmamap_sync: t=%p map=%p offset=%lx len=%lx ops=%x\n",
@@ -391,51 +526,30 @@
        if (__predict_false(map->_dm_proc != NULL && map->_dm_proc != curproc))
                return;
 
-       for (i = 0; i < map->dm_nsegs && len != 0; i++) {
-               /* Find beginning segment. */
-               if (offset >= map->dm_segs[i].ds_len) {
-                       offset -= map->dm_segs[i].ds_len;
-                       continue;
-               }
+       switch (map->_dm_buftype) {
+       case ARM32_BUFTYPE_LINEAR:
+               _bus_dmamap_sync_linear(t, map, offset, len, ops);
+               break;
 
-               /*
-                * Now at the first segment to sync; nail
-                * each segment until we have exhausted the
-                * length.
-                */
-               minlen = len < map->dm_segs[i].ds_len - offset ?
-                   len : map->dm_segs[i].ds_len - offset;
-
-               addr = map->dm_segs[i]._ds_vaddr;
-
-#ifdef DEBUG_DMA
-               printf("bus_dmamap_sync: flushing segment %d "
-                   "(0x%lx..0x%lx) ...", i, addr + offset,
-                   addr + offset + minlen - 1);
-#endif
+       case ARM32_BUFTYPE_MBUF:
+               _bus_dmamap_sync_mbuf(t, map, offset, len, ops);
+               break;
 
-               switch (ops) {
-               case BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE:
-                       cpu_dcache_wbinv_range(addr + offset, minlen);
-                       break;
+       case ARM32_BUFTYPE_UIO:
+               _bus_dmamap_sync_uio(t, map, offset, len, ops);
+               break;
+
+       case ARM32_BUFTYPE_RAW:
+               panic("_bus_dmamap_sync: ARM32_BUFTYPE_RAW");
+               break;
 
-               case BUS_DMASYNC_PREREAD:
-#if 1
-                       cpu_dcache_wbinv_range(addr + offset, minlen);
-#else
-                       cpu_dcache_inv_range(addr + offset, minlen);
-#endif
-                       break;
+       case ARM32_BUFTYPE_INVALID:
+               panic("_bus_dmamap_sync: ARM32_BUFTYPE_INVALID");
+               break;
 
-               case BUS_DMASYNC_PREWRITE:
-                       cpu_dcache_wb_range(addr + offset, minlen);
-                       break;
-               }
-#ifdef DEBUG_DMA
-               printf("\n");
-#endif
-               offset = 0;
-               len -= minlen;
+       default:
+               printf("unknown buffer type %d\n", map->_dm_buftype);
+               panic("_bus_dmamap_sync");
        }
 
        /* Drain the write buffer. */
@@ -690,7 +804,6 @@
                if (first) {
                        map->dm_segs[seg].ds_addr = curaddr;
                        map->dm_segs[seg].ds_len = sgsize;
-                       map->dm_segs[seg]._ds_vaddr = vaddr;
                        first = 0;
                } else {
                        if (curaddr == lastaddr &&
@@ -705,7 +818,6 @@
                                        break;
                                map->dm_segs[seg].ds_addr = curaddr;
                                map->dm_segs[seg].ds_len = sgsize;
-                               map->dm_segs[seg]._ds_vaddr = vaddr;
                        }
                }
 
diff -r e4108075e938 -r 5bd181610619 sys/arch/arm/include/bus.h
--- a/sys/arch/arm/include/bus.h        Sun Jul 28 15:41:00 2002 +0000
+++ b/sys/arch/arm/include/bus.h        Sun Jul 28 17:54:05 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bus.h,v 1.4 2002/01/25 20:57:43 thorpej Exp $  */
+/*     $NetBSD: bus.h,v 1.5 2002/07/28 17:54:06 thorpej Exp $  */
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2001 The NetBSD Foundation, Inc.
@@ -661,11 +661,6 @@



Home | Main Index | Thread Index | Old Index