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;
 	}

Reply via email to