Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/mips/mips When decide to coalesce segments, if the ...



details:   https://anonhg.NetBSD.org/src/rev/9c4b9a5bd59a
branches:  trunk
changeset: 789583:9c4b9a5bd59a
user:      matt <matt%NetBSD.org@localhost>
date:      Fri Aug 23 07:15:08 2013 +0000

description:
When decide to coalesce segments, if the d_cache isn't coherent also make
sure the VA is contiguous as well.

diffstat:

 sys/arch/mips/mips/bus_dma.c |  109 +++++++++++++++++++++---------------------
 1 files changed, 55 insertions(+), 54 deletions(-)

diffs (247 lines):

diff -r bda8abb7fa18 -r 9c4b9a5bd59a sys/arch/mips/mips/bus_dma.c
--- a/sys/arch/mips/mips/bus_dma.c      Fri Aug 23 06:31:49 2013 +0000
+++ b/sys/arch/mips/mips/bus_dma.c      Fri Aug 23 07:15:08 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bus_dma.c,v 1.27 2011/07/10 23:13:22 matt Exp $        */
+/*     $NetBSD: bus_dma.c,v 1.28 2013/08/23 07:15:08 matt Exp $        */
 
 /*-
  * Copyright (c) 1997, 1998, 2001 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
 
 #include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.27 2011/07/10 23:13:22 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.28 2013/08/23 07:15:08 matt Exp $");
 
 #define _MIPS_BUS_DMA_PRIVATE
 
@@ -97,26 +97,29 @@
 paddr_t kvtophys(vaddr_t);     /* XXX */
 
 /*
- * Utility function to load a linear buffer.  lastaddrp holds state
- * between invocations (for multiple-buffer loads).  segp contains
- * the starting segment on entrance, and the ending segment on exit.
- * first indicates if this is the first invocation of this function.
+ * Utility function to load a linear buffer.  segp contains the starting
+ * segment on entrance, and the ending segment on exit. first indicates
+ * if this is the first invocation of this function.
  */
 static int
 _bus_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map,
     void *buf, bus_size_t buflen, struct vmspace *vm, int flags,
-    paddr_t *lastaddrp, int *segp, int first)
+    int *segp, bool first)
 {
        bus_size_t sgsize;
-       bus_size_t bmask;
        paddr_t baddr, curaddr, lastaddr;
-       vaddr_t vaddr = (vaddr_t)buf;
-       int seg;
+       vaddr_t vaddr = (vaddr_t)buf, lastvaddr;
+       int seg = *segp;
+       bus_dma_segment_t *ds = &map->dm_segs[seg];
+       bus_dma_segment_t * const eds = &map->dm_segs[map->_dm_segcnt];
+       const bool d_cache_coherent =
+           (mips_options.mips_cpu_flags & CPU_MIPS_D_CACHE_COHERENT) != 0;
 
-       lastaddr = *lastaddrp;
-       bmask = ~(map->_dm_boundary - 1);
+       lastaddr = ds->ds_addr + ds->ds_len;
+       lastvaddr = ds->_ds_vaddr + ds->ds_len;
+       const bus_size_t bmask = ~(map->_dm_boundary - 1);
 
-       for (seg = *segp; buflen > 0 ; ) {
+       while (buflen > 0) {
                /*
                 * Get the physical address for this segment.
                 */
@@ -130,9 +133,9 @@
                 * If we're beyond the current DMA window, indicate
                 * that and try to fall back onto something else.
                 */
-               if (curaddr < t->_bounce_alloc_lo ||
-                   (t->_bounce_alloc_hi != 0
-                    && curaddr >= t->_bounce_alloc_hi))
+               if (curaddr < t->_bounce_alloc_lo
+                   || (t->_bounce_alloc_hi != 0
+                       && curaddr >= t->_bounce_alloc_hi))
                        return (EINVAL);
 #if BUS_DMA_DEBUG
                printf("dma: addr %#"PRIxPADDR" -> %#"PRIxPADDR"\n", curaddr,
@@ -144,18 +147,21 @@
                 * Compute the segment size, and adjust counts.
                 */
                sgsize = PAGE_SIZE - ((uintptr_t)vaddr & PGOFSET);
-               if (buflen < sgsize)
+               if (sgsize > buflen) {
                        sgsize = buflen;
-               if (map->dm_maxsegsz < sgsize)
+               }
+               if (sgsize > map->dm_maxsegsz) {
                        sgsize = map->dm_maxsegsz;
+               }
 
                /*
                 * Make sure we don't cross any boundaries.
                 */
                if (map->_dm_boundary > 0) {
                        baddr = (curaddr + map->_dm_boundary) & bmask;
-                       if (sgsize > (baddr - curaddr))
-                               sgsize = (baddr - curaddr);
+                       if (sgsize > baddr - curaddr) {
+                               sgsize = baddr - curaddr;
+                       }
                }
 
                /*
@@ -163,34 +169,31 @@
                 * the previous segment if possible.
                 */
                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;
+                       ds->ds_addr = curaddr;
+                       ds->ds_len = sgsize;
+                       ds->_ds_vaddr = vaddr;
+                       first = false;
+               } else if (curaddr == lastaddr
+                   && (d_cache_coherent || lastvaddr == vaddr)
+                   && ds->ds_len + sgsize <= map->dm_maxsegsz
+                   && (map->_dm_boundary == 0
+                       || ((ds->ds_addr ^ curaddr) & bmask) == 0)) {
+                       ds->ds_len += sgsize;
                } else {
-                       if (curaddr == lastaddr &&
-                           (map->dm_segs[seg].ds_len + sgsize) <=
-                            map->dm_maxsegsz &&
-                           (map->_dm_boundary == 0 ||
-                            (map->dm_segs[seg].ds_addr & bmask) ==
-                            (curaddr & bmask)))
-                               map->dm_segs[seg].ds_len += sgsize;
-                       else {
-                               if (++seg >= map->_dm_segcnt)
-                                       break;
-                               map->dm_segs[seg].ds_addr = curaddr;
-                               map->dm_segs[seg].ds_len = sgsize;
-                               map->dm_segs[seg]._ds_vaddr = vaddr;
-                       }
+                       if (++ds >= eds)
+                               break;
+                       ds->ds_addr = curaddr;
+                       ds->ds_len = sgsize;
+                       ds->_ds_vaddr = vaddr;
                }
 
                lastaddr = curaddr + sgsize;
                vaddr += sgsize;
                buflen -= sgsize;
+               lastvaddr = vaddr;
        }
 
-       *segp = seg;
-       *lastaddrp = lastaddr;
+       *segp = ds - map->dm_segs;
 
        /*
         * Did we fit?
@@ -219,7 +222,6 @@
 {
        struct mips_bus_dma_cookie * const cookie = map->_dm_cookie;
        struct vmspace * const vm = vmspace_kernel();
-       paddr_t lastaddr;
        int seg, error;
 
        KASSERT(cookie != NULL);
@@ -243,7 +245,7 @@
        cookie->id_buftype = buftype;
        seg = 0;
        error = _bus_dmamap_load_buffer(t, map, cookie->id_bouncebuf,
-           buflen, vm, flags, &lastaddr, &seg, 1);
+           buflen, vm, flags, &seg, true);
        if (error)
                return (error);
 
@@ -400,7 +402,6 @@
 _bus_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
     bus_size_t buflen, struct proc *p, int flags)
 {
-       paddr_t lastaddr;
        int seg, error;
        struct vmspace *vm;
 
@@ -435,7 +436,7 @@
 
        seg = 0;
        error = _bus_dmamap_load_buffer(t, map, buf, buflen,
-           vm, flags, &lastaddr, &seg, 1);
+           vm, flags, &seg, true);
        if (error == 0) {
                map->dm_mapsize = buflen;
                map->dm_nsegs = seg + 1;
@@ -477,10 +478,10 @@
 _bus_dmamap_load_mbuf(bus_dma_tag_t t, bus_dmamap_t map,
     struct mbuf *m0, int flags)
 {
-       paddr_t lastaddr;
-       int seg, error, first;
+       int seg, error;
        struct mbuf *m;
        struct vmspace * vm = vmspace_kernel();
+       bool first;
 
        if (map->dm_nsegs > 0) {
 #ifdef _MIPS_NEED_BUS_DMA_BOUNCE
@@ -510,15 +511,15 @@
        if (m0->m_pkthdr.len > map->_dm_size)
                return (EINVAL);
 
-       first = 1;
+       first = true;
        seg = 0;
        error = 0;
        for (m = m0; m != NULL && error == 0; m = m->m_next) {
                if (m->m_len == 0)
                        continue;
                error = _bus_dmamap_load_buffer(t, map, m->m_data, m->m_len,
-                   vm, flags, &lastaddr, &seg, first);
-               first = 0;
+                   vm, flags, &seg, first);
+               first = false;
        }
        if (error == 0) {
                map->dm_mapsize = m0->m_pkthdr.len;
@@ -548,8 +549,8 @@
 _bus_dmamap_load_uio(bus_dma_tag_t t, bus_dmamap_t map,
     struct uio *uio, int flags)
 {
-       paddr_t lastaddr;
-       int seg, i, error, first;
+       int seg, i, error;
+       bool first;
        bus_size_t minlen, resid;
        struct iovec *iov;
        void *addr;
@@ -577,7 +578,7 @@
        resid = uio->uio_resid;
        iov = uio->uio_iov;
 
-       first = 1;
+       first = true;
        seg = 0;
        error = 0;
        for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) {
@@ -589,8 +590,8 @@
                addr = (void *)iov[i].iov_base;
 
                error = _bus_dmamap_load_buffer(t, map, addr, minlen,
-                   uio->uio_vmspace, flags, &lastaddr, &seg, first);
-               first = 0;
+                   uio->uio_vmspace, flags, &seg, first);
+               first = false;
 
                resid -= minlen;
        }



Home | Main Index | Thread Index | Old Index