Module Name: src Committed By: bouyer Date: Wed May 21 20:36:11 UTC 2014
Modified Files: src/sys/arch/mips/mips [netbsd-6]: bus_dma.c Log Message: Pull up following revision(s) (requested by skrll in ticket #1055): sys/arch/mips/mips/bus_dma.c: revision 1.28 When decide to coalesce segments, if the d_cache isn't coherent also make sure the VA is contiguous as well. To generate a diff of this commit: cvs rdiff -u -r1.27 -r1.27.8.1 src/sys/arch/mips/mips/bus_dma.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/mips/mips/bus_dma.c diff -u src/sys/arch/mips/mips/bus_dma.c:1.27 src/sys/arch/mips/mips/bus_dma.c:1.27.8.1 --- src/sys/arch/mips/mips/bus_dma.c:1.27 Sun Jul 10 23:13:22 2011 +++ src/sys/arch/mips/mips/bus_dma.c Wed May 21 20:36:11 2014 @@ -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.27.8.1 2014/05/21 20:36:11 bouyer 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.27.8.1 2014/05/21 20:36:11 bouyer Exp $"); #define _MIPS_BUS_DMA_PRIVATE @@ -97,26 +97,29 @@ EVCNT_ATTACH_STATIC(bus_dma_bounced_dest 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 = ds->ds_addr + ds->ds_len; + lastvaddr = ds->_ds_vaddr + ds->ds_len; + const bus_size_t bmask = ~(map->_dm_boundary - 1); - lastaddr = *lastaddrp; - bmask = ~(map->_dm_boundary - 1); - - for (seg = *segp; buflen > 0 ; ) { + while (buflen > 0) { /* * Get the physical address for this segment. */ @@ -130,9 +133,9 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t, * 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 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t, * 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 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t, * 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 @@ _bus_dma_load_bouncebuf(bus_dma_tag_t t, { 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 @@ _bus_dma_load_bouncebuf(bus_dma_tag_t t, 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 @@ int _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 @@ _bus_dmamap_load(bus_dma_tag_t t, bus_dm 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 @@ int _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 @@ _bus_dmamap_load_mbuf(bus_dma_tag_t t, b 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 @@ int _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 @@ _bus_dmamap_load_uio(bus_dma_tag_t t, bu 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 @@ _bus_dmamap_load_uio(bus_dma_tag_t t, bu 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; }