Source-Changes-HG archive

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

[src/trunk]: src/sys/arch Use cached physical addresses for mbufs and cluster...



details:   https://anonhg.NetBSD.org/src/rev/923823cc6096
branches:  trunk
changeset: 545491:923823cc6096
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Wed Apr 09 18:51:35 2003 +0000

description:
Use cached physical addresses for mbufs and clusters to save having
to extract the physical address from the virtual.

On the ARM, also use the "read-only at MMU" indication to avoid a
redundant cache clean operation.

Other platforms should use these two as examples of how to use these
new pool/mbuf features to improve network performance.  Note this requires
a platform to provide a working POOL_VTOPHYS().

Part 3 in a series of simple patches contributed by Wasabi Systems
to improve network performance.

diffstat:

 sys/arch/arm/arm32/bus_dma.c |  88 ++++++++++++++++++++++++++++++++++++++++----
 sys/arch/x86/x86/bus_dma.c   |  36 ++++++++++++++++--
 2 files changed, 112 insertions(+), 12 deletions(-)

diffs (187 lines):

diff -r 50152660decd -r 923823cc6096 sys/arch/arm/arm32/bus_dma.c
--- a/sys/arch/arm/arm32/bus_dma.c      Wed Apr 09 18:46:47 2003 +0000
+++ b/sys/arch/arm/arm32/bus_dma.c      Wed Apr 09 18:51:35 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bus_dma.c,v 1.27 2003/04/01 23:21:12 thorpej Exp $     */
+/*     $NetBSD: bus_dma.c,v 1.28 2003/04/09 18:51:35 thorpej Exp $     */
 
 /*-
  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@@ -213,6 +213,7 @@
 _bus_dmamap_load_mbuf(bus_dma_tag_t t, bus_dmamap_t map, struct mbuf *m0,
     int flags)
 {
+       struct arm32_dma_range *dr;
        paddr_t lastaddr;
        int seg, error, first;
        struct mbuf *m;
@@ -236,15 +237,66 @@
        if (m0->m_pkthdr.len > map->_dm_size)
                return (EINVAL);
 
-       /* _bus_dmamap_load_buffer() clears this if we're not... */
-       map->_dm_flags |= ARM32_DMAMAP_COHERENT;
+       /*
+        * Mbuf chains should almost never have coherent (i.e.
+        * un-cached) mappings, so clear that flag now.
+        */
+       map->_dm_flags &= ~ARM32_DMAMAP_COHERENT;
 
        first = 1;
        seg = 0;
        error = 0;
        for (m = m0; m != NULL && error == 0; m = m->m_next) {
-               error = _bus_dmamap_load_buffer(t, map, m->m_data, m->m_len,
-                   NULL, flags, &lastaddr, &seg, first);
+               if (m->m_len == 0)
+                       continue;
+               /* XXX Could be better about coalescing. */
+               /* XXX Doesn't check boundaries. */
+               switch (m->m_flags & (M_EXT|M_CLUSTER)) {
+               case M_EXT|M_CLUSTER:
+                       /* XXX KDASSERT */
+                       KASSERT(m->m_ext.ext_paddr != M_PADDR_INVALID);
+                       lastaddr = m->m_ext.ext_paddr +
+                           (m->m_data - m->m_ext.ext_buf);
+ have_addr:
+                       if (first == 0 &&
+                           ++seg >= map->_dm_segcnt) {
+                               error = EFBIG;
+                               break;
+                       }
+                       /*
+                        * Make sure we're in an allowed DMA range.
+                        */
+                       if (t->_ranges != NULL) {
+                               /* XXX cache last result? */
+                               dr = _bus_dma_inrange(t->_ranges, t->_nranges,
+                                   lastaddr);
+                               if (dr == NULL) {
+                                       error = EINVAL;
+                                       break;
+                               }
+                       
+                               /*
+                                * In a valid DMA range.  Translate the
+                                * physical memory address to an address
+                                * in the DMA window.
+                                */
+                               lastaddr = (lastaddr - dr->dr_sysbase) +
+                                   dr->dr_busbase;
+                       }
+                       map->dm_segs[seg].ds_addr = lastaddr;
+                       map->dm_segs[seg].ds_len = m->m_len;
+                       lastaddr += m->m_len;
+                       break;
+
+               case 0:
+                       lastaddr = m->m_paddr + M_BUFOFFSET(m) +
+                           (m->m_data - M_BUFADDR(m));
+                       goto have_addr;
+
+               default:
+                       error = _bus_dmamap_load_buffer(t, map, m->m_data,
+                           m->m_len, NULL, flags, &lastaddr, &seg, first);
+               }
                first = 0;
        }
        if (error == 0) {
@@ -409,10 +461,29 @@
                maddr = mtod(m, vaddr_t);
                maddr += moff;
 
+               /*
+                * We can save a lot of work here if we know the mapping
+                * is read-only at the MMU:
+                *
+                * If a mapping is read-only, no dirty cache blocks will
+                * exist for it.  If a writable mapping was made read-only,
+                * we know any dirty cache lines for the range will have
+                * been cleaned for us already.  Therefore, if the upper
+                * layer can tell us we have a read-only mapping, we can
+                * skip all cache cleaning.
+                *
+                * NOTE: This only works if we know the pmap cleans pages
+                * before making a read-write -> read-only transition.  If
+                * this ever becomes non-true (e.g. Physically Indexed
+                * cache), this will have to be revisited.
+                */
                switch (ops) {
                case BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE:
-                       cpu_dcache_wbinv_range(maddr, minlen);
-                       break;
+                       if (! M_ROMAP(m)) {
+                               cpu_dcache_wbinv_range(maddr, minlen);
+                               break;
+                       }
+                       /* else FALLTHROUGH */
 
                case BUS_DMASYNC_PREREAD:
                        if (((maddr | minlen) & arm_dcache_align_mask) == 0)
@@ -422,7 +493,8 @@
                        break;
 
                case BUS_DMASYNC_PREWRITE:
-                       cpu_dcache_wb_range(maddr, minlen);
+                       if (! M_ROMAP(m))
+                               cpu_dcache_wb_range(maddr, minlen);
                        break;
                }
                moff = 0;
diff -r 50152660decd -r 923823cc6096 sys/arch/x86/x86/bus_dma.c
--- a/sys/arch/x86/x86/bus_dma.c        Wed Apr 09 18:46:47 2003 +0000
+++ b/sys/arch/x86/x86/bus_dma.c        Wed Apr 09 18:51:35 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bus_dma.c,v 1.1 2003/03/12 00:09:52 thorpej Exp $      */
+/*     $NetBSD: bus_dma.c,v 1.2 2003/04/09 18:51:36 thorpej Exp $      */
 
 /*-
  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.1 2003/03/12 00:09:52 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.2 2003/04/09 18:51:36 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -185,8 +185,36 @@
        seg = 0;
        error = 0;
        for (m = m0; m != NULL && error == 0; m = m->m_next) {
-               error = _bus_dmamap_load_buffer(t, map, m->m_data, m->m_len,
-                   NULL, flags, &lastaddr, &seg, first);
+               if (m->m_len == 0)
+                       continue;
+               /* XXX Could be better about coalescing. */
+               /* XXX Doesn't check boundaries. */
+               switch (m->m_flags & (M_EXT|M_EXT_CLUSTER)) {
+               case M_EXT|M_EXT_CLUSTER:
+                       /* XXX KDASSERT */
+                       KASSERT(m->m_ext.ext_paddr != M_PADDR_INVALID);
+                       lastaddr = m->m_ext.ext_paddr +
+                           (m->m_data - m->m_ext.ext_buf);
+ have_addr:
+                       if (first == 0 &&
+                           ++seg >= map->_dm_segcnt) {
+                               error = EFBIG;
+                               break;
+                       }
+                       map->dm_segs[seg].ds_addr = lastaddr;
+                       map->dm_segs[seg].ds_len = m->m_len;
+                       lastaddr += m->m_len;
+                       break;
+
+               case 0:
+                       lastaddr = m->m_paddr + M_BUFOFFSET(m) +
+                           (m->m_data - M_BUFADDR(m));
+                       goto have_addr;
+
+               default:
+                       error = _bus_dmamap_load_buffer(t, map, m->m_data,
+                           m->m_len, NULL, flags, &lastaddr, &seg, first);
+               }
                first = 0;
        }
        if (error == 0) {



Home | Main Index | Thread Index | Old Index