Source-Changes-HG archive

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

[src/netbsd-1-6]: src/sys/arch/arm/arm32 Pull up revisions 1.13-1.14 (request...



details:   https://anonhg.NetBSD.org/src/rev/26fa94136ed5
branches:  netbsd-1-6
changeset: 529657:26fa94136ed5
user:      he <he%NetBSD.org@localhost>
date:      Sat Dec 07 19:23:21 2002 +0000

description:
Pull up revisions 1.13-1.14 (requested by thorpej in ticket #568):
  Remove warning from bus_dmamap_destroy().
  Change the way 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.  Shrinks bus_dma_segment_t from 12
  to 8 bytes, and the cache flushing is also more efficient.

diffstat:

 sys/arch/arm/arm32/bus_dma.c |  218 ++++++++++++++++++++++++++++++++----------
 1 files changed, 167 insertions(+), 51 deletions(-)

diffs (truncated from 302 to 300 lines):

diff -r 298ae5574cba -r 26fa94136ed5 sys/arch/arm/arm32/bus_dma.c
--- a/sys/arch/arm/arm32/bus_dma.c      Sat Dec 07 19:15:57 2002 +0000
+++ b/sys/arch/arm/arm32/bus_dma.c      Sat Dec 07 19:23:21 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bus_dma.c,v 1.11 2002/04/10 19:35:22 thorpej Exp $     */
+/*     $NetBSD: bus_dma.c,v 1.11.4.1 2002/12/07 19:23:21 he 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;
@@ -128,10 +130,16 @@
 #ifdef DEBUG_DMA
        printf("dmamap_destroy: t=%p map=%p\n", t, map);
 #endif /* DEBUG_DMA */
-#ifdef DIAGNOSTIC
-       if (map->dm_nsegs > 0)
-               printf("bus_dmamap_destroy() called for map with valid mappings\n");
-#endif /* DIAGNOSTIC */
+
+       /*
+        * Explicit unload.
+        */
+       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);
 }
 
@@ -166,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
@@ -215,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
@@ -274,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);
@@ -309,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.
@@ -328,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",
@@ -387,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. */
@@ -686,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 &&
@@ -701,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;
                        }



Home | Main Index | Thread Index | Old Index