Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/powerpc/powerpc Cleanup dmamap_sync a bit and add a...



details:   https://anonhg.NetBSD.org/src/rev/fd5ec1f9c42a
branches:  trunk
changeset: 545503:fd5ec1f9c42a
user:      matt <matt%NetBSD.org@localhost>
date:      Wed Apr 09 22:28:56 2003 +0000

description:
Cleanup dmamap_sync a bit and add a few more comments.  Add support for
cached physaddr's in mbufs.

diffstat:

 sys/arch/powerpc/powerpc/bus_dma.c |  90 +++++++++++++++++++++++++++++++------
 1 files changed, 75 insertions(+), 15 deletions(-)

diffs (142 lines):

diff -r 7e2c3b3017e9 -r fd5ec1f9c42a sys/arch/powerpc/powerpc/bus_dma.c
--- a/sys/arch/powerpc/powerpc/bus_dma.c        Wed Apr 09 22:14:31 2003 +0000
+++ b/sys/arch/powerpc/powerpc/bus_dma.c        Wed Apr 09 22:28:56 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bus_dma.c,v 1.9 2003/04/02 02:47:19 thorpej Exp $      */
+/*     $NetBSD: bus_dma.c,v 1.10 2003/04/09 22:28:56 matt Exp $        */
 
 /*-
  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@@ -310,10 +310,37 @@
        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);
-               first = 0;
+       for (m = m0; m != NULL && error == 0; m = m->m_next, first = 0) {
+#ifdef POOL_VTOPHYS
+               /* 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;
+                               continue;
+                       }
+                       map->dm_segs[seg].ds_addr = lastaddr;
+                       map->dm_segs[seg].ds_len = m->m_len;
+                       lastaddr += m->m_len;
+                       continue;
+
+               case 0:
+                       lastaddr = m->m_paddr + M_BUFOFFSET(m) +
+                           (m->m_data - M_BUFADDR(m));
+                       goto have_addr;
+
+               default:
+                       break;
+               }
+#endif
+               error = _bus_dmamap_load_buffer(t, map, m->m_data,
+                   m->m_len, NULL, flags, &lastaddr, &seg, first);
        }
        if (error == 0) {
                map->dm_mapsize = m0->m_pkthdr.len;
@@ -447,12 +474,22 @@
                ds++;
        }
        __asm __volatile("eieio");
-       for (; len > 0; ds++) {
+       for (; len > 0; ds++, offset = 0) {
                bus_size_t seglen = ds->ds_len - offset;
                bus_addr_t addr = ds->ds_addr + offset;
                if (seglen > len)
                        seglen = len;
+               len -= seglen;
                KASSERT(ds < &map->dm_segs[map->dm_nsegs]);
+               /*
+                * Readjust things to start on cacheline boundarys
+                */
+               offset = (addr & (dcache_line_size-1));
+               seglen += offset;
+               addr -= offset;
+               /*
+                * Now do the appropriate thing.
+                */
                switch (ops) {
                case BUS_DMASYNC_PREWRITE:
                        /*
@@ -463,25 +500,50 @@
                case BUS_DMASYNC_PREREAD:
                        /*
                         * If the region to be invalidated doesn't fall on
-                        * cacheline boundary, store that cacheline so we
+                        * cacheline boundary, flush that cacheline so we
                         * preserve the leading content.
                         */
-                       if (addr & (dcache_line_size-1))
-                               dcbst(addr, 1, 1);
+                       if (offset) {
+                               dcbf(addr, 1, 1);
+                               /*
+                                * If we are doing <= one cache line, stop now.
+                                */
+                               if (seglen <= dcache_line_size)
+                                       break;
+                               /*
+                                * Advance one cache line since we've flushed
+                                * this one.
+                                */
+                               addr += dcache_line_size;
+                               seglen -= dcache_line_size;
+                       }
                        /*
                         * If the byte after the region to be invalidated
-                        * doesn't fall on cacheline boundary, store that
+                        * doesn't fall on cacheline boundary, flush that
                         * cacheline so we preserve the trailing content.
                         */
-                       if ((addr + seglen) & (dcache_line_size-1))
-                               dcbst(addr + seglen, 1, 1);
+                       if (seglen & (dcache_line_size-1)) {
+                               dcbf(addr + seglen, 1, 1);
+                               if (seglen <= dcache_line_size)
+                                       break;
+                               /*
+                                * Truncate the length to a multiple of a
+                                * dcache line size.  No reason to flush
+                                * the last entry again.
+                                */
+                               seglen &= ~(dcache_line_size - 1);
+                       }
                        __asm __volatile("sync; eieio"); /* is this needed? */
                        /* FALLTHROUGH */
                case BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE:
                case BUS_DMASYNC_POSTREAD:
                        /*
                         * The contents will have changed, make sure to remove
-                        * them from the cache.
+                        * them from the cache.  Note: some implementation
+                        * implement dcbi identically to dcbf.  Thus if the
+                        * cacheline has data, it will be written to memory.
+                        * If the DMA is updaing the same cacheline at the
+                        * time, bad things can happen.
                         */
                        dcbi(addr, seglen, dcache_line_size);
                        break;
@@ -497,8 +559,6 @@
                        dcbf(addr, seglen, dcache_line_size);
                        break;
                }
-               len -= seglen;
-               offset = 0;
        }
        __asm __volatile("sync");
 }



Home | Main Index | Thread Index | Old Index