Module Name:    src
Committed By:   matt
Date:           Wed Feb 26 01:05:52 UTC 2014

Modified Files:
        src/sys/arch/arm/arm32: bus_dma.c

Log Message:
Use kmem instead of malloc.
Fix various corner cases with bounce buffers.
Use PMAP_NOCACHE instead of manipulating PTEs directly.


To generate a diff of this commit:
cvs rdiff -u -r1.80 -r1.81 src/sys/arch/arm/arm32/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/arm/arm32/bus_dma.c
diff -u src/sys/arch/arm/arm32/bus_dma.c:1.80 src/sys/arch/arm/arm32/bus_dma.c:1.81
--- src/sys/arch/arm/arm32/bus_dma.c:1.80	Mon Feb 18 16:03:25 2013
+++ src/sys/arch/arm/arm32/bus_dma.c	Wed Feb 26 01:05:52 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: bus_dma.c,v 1.80 2013/02/18 16:03:25 matt Exp $	*/
+/*	$NetBSD: bus_dma.c,v 1.81 2014/02/26 01:05:52 matt Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@@ -32,8 +32,10 @@
 
 #define _ARM32_BUS_DMA_PRIVATE
 
+#include "opt_arm_bus_space.h"
+
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.80 2013/02/18 16:03:25 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.81 2014/02/26 01:05:52 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -43,7 +45,7 @@ __KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 
 #include <sys/reboot.h>
 #include <sys/conf.h>
 #include <sys/file.h>
-#include <sys/malloc.h>
+#include <sys/kmem.h>
 #include <sys/mbuf.h>
 #include <sys/vnode.h>
 #include <sys/device.h>
@@ -64,6 +66,8 @@ static struct evcnt bus_dma_loads =
 	EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "loads");
 static struct evcnt bus_dma_bounced_loads =
 	EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "bounced loads");
+static struct evcnt bus_dma_coherent_loads =
+	EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "coherent loads");
 static struct evcnt bus_dma_read_bounces =
 	EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "read bounces");
 static struct evcnt bus_dma_write_bounces =
@@ -97,6 +101,7 @@ EVCNT_ATTACH_STATIC(bus_dma_creates);
 EVCNT_ATTACH_STATIC(bus_dma_bounced_creates);
 EVCNT_ATTACH_STATIC(bus_dma_loads);
 EVCNT_ATTACH_STATIC(bus_dma_bounced_loads);
+EVCNT_ATTACH_STATIC(bus_dma_coherent_loads);
 EVCNT_ATTACH_STATIC(bus_dma_read_bounces);
 EVCNT_ATTACH_STATIC(bus_dma_write_bounces);
 EVCNT_ATTACH_STATIC(bus_dma_unloads);
@@ -315,7 +320,6 @@ _bus_dmamap_create(bus_dma_tag_t t, bus_
 {
 	struct arm32_bus_dmamap *map;
 	void *mapstore;
-	size_t mapsize;
 
 #ifdef DEBUG_DMA
 	printf("dmamap_create: t=%p size=%lx nseg=%x msegsz=%lx boundary=%lx flags=%x\n",
@@ -334,10 +338,10 @@ _bus_dmamap_create(bus_dma_tag_t t, bus_
 	 * The bus_dmamap_t includes one bus_dma_segment_t, hence
 	 * the (nsegments - 1).
 	 */
-	mapsize = sizeof(struct arm32_bus_dmamap) +
+	const size_t mapsize = sizeof(struct arm32_bus_dmamap) +
 	    (sizeof(bus_dma_segment_t) * (nsegments - 1));
-	const int mallocflags = M_ZERO|(flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK;
-	if ((mapstore = malloc(mapsize, M_DMAMAP, mallocflags)) == NULL)
+	const int zallocflags = (flags & BUS_DMA_NOWAIT) ? KM_NOSLEEP : KM_SLEEP;
+	if ((mapstore = kmem_intr_zalloc(mapsize, zallocflags)) == NULL)
 		return (ENOMEM);
 
 	map = (struct arm32_bus_dmamap *)mapstore;
@@ -360,7 +364,6 @@ _bus_dmamap_create(bus_dma_tag_t t, bus_
 	struct arm32_bus_dma_cookie *cookie;
 	int cookieflags;
 	void *cookiestore;
-	size_t cookiesize;
 	int error;
 
 	cookieflags = 0;
@@ -379,13 +382,13 @@ _bus_dmamap_create(bus_dma_tag_t t, bus_
 		return 0;
 	}
 
-	cookiesize = sizeof(struct arm32_bus_dma_cookie) +
+	const size_t cookiesize = sizeof(struct arm32_bus_dma_cookie) +
 	    (sizeof(bus_dma_segment_t) * map->_dm_segcnt);
 
 	/*
 	 * Allocate our cookie.
 	 */
-	if ((cookiestore = malloc(cookiesize, M_DMAMAP, mallocflags)) == NULL) {
+	if ((cookiestore = kmem_intr_zalloc(cookiesize, zallocflags)) == NULL) {
 		error = ENOMEM;
 		goto out;
 	}
@@ -426,13 +429,16 @@ _bus_dmamap_destroy(bus_dma_tag_t t, bus
 	 * Free any bounce pages this map might hold.
 	 */
 	if (cookie != NULL) {
+		const size_t cookiesize = sizeof(struct arm32_bus_dma_cookie) +
+		    (sizeof(bus_dma_segment_t) * map->_dm_segcnt);
+
 		if (cookie->id_flags & _BUS_DMA_IS_BOUNCING)
 			STAT_INCR(bounced_unloads);
 		map->dm_nsegs = 0;
 		if (cookie->id_flags & _BUS_DMA_HAS_BOUNCE)
 			_bus_dma_free_bouncebuf(t, map);
 		STAT_INCR(bounced_destroys);
-		free(cookie, M_DMAMAP);
+		kmem_intr_free(cookie, cookiesize);
 	} else
 #endif
 	STAT_INCR(destroys);
@@ -440,7 +446,9 @@ _bus_dmamap_destroy(bus_dma_tag_t t, bus
 	if (map->dm_nsegs > 0)
 		STAT_INCR(unloads);
 
-	free(map, M_DMAMAP);
+	const size_t mapsize = sizeof(struct arm32_bus_dmamap) +
+	    (sizeof(bus_dma_segment_t) * (map->_dm_segcnt - 1));
+	kmem_intr_free(map, mapsize);
 }
 
 /*
@@ -501,6 +509,11 @@ _bus_dmamap_load(bus_dma_tag_t t, bus_dm
 		map->_dm_vmspace = vm;
 		map->_dm_origbuf = buf;
 		map->_dm_buftype = _BUS_DMA_BUFTYPE_LINEAR;
+		if (map->_dm_flags & _BUS_DMAMAP_COHERENT) {
+			STAT_INCR(coherent_loads);
+		} else {
+			STAT_INCR(loads);
+		}
 		return 0;
 	}
 #ifdef _ARM32_NEED_BUS_DMA_BOUNCE
@@ -640,6 +653,11 @@ _bus_dmamap_load_mbuf(bus_dma_tag_t t, b
 		map->_dm_origbuf = m0;
 		map->_dm_buftype = _BUS_DMA_BUFTYPE_MBUF;
 		map->_dm_vmspace = vmspace_kernel();	/* always kernel */
+		if (map->_dm_flags & _BUS_DMAMAP_COHERENT) {
+			STAT_INCR(coherent_loads);
+		} else {
+			STAT_INCR(loads);
+		}
 		return 0;
 	}
 #ifdef _ARM32_NEED_BUS_DMA_BOUNCE
@@ -698,6 +716,11 @@ _bus_dmamap_load_uio(bus_dma_tag_t t, bu
 		map->_dm_origbuf = uio;
 		map->_dm_buftype = _BUS_DMA_BUFTYPE_UIO;
 		map->_dm_vmspace = uio->uio_vmspace;
+		if (map->_dm_flags & _BUS_DMAMAP_COHERENT) {
+			STAT_INCR(coherent_loads);
+		} else {
+			STAT_INCR(loads);
+		}
 	}
 	return (error);
 }
@@ -1242,7 +1265,6 @@ _bus_dmamem_map(bus_dma_tag_t t, bus_dma
 	vaddr_t va;
 	paddr_t pa;
 	int curseg;
-	pt_entry_t *ptep;
 	const uvm_flag_t kmflags = UVM_KMF_VAONLY
 	    | ((flags & BUS_DMA_NOWAIT) != 0 ? UVM_KMF_NOWAIT : 0);
 	vsize_t align = 0;
@@ -1299,7 +1321,7 @@ _bus_dmamem_map(bus_dma_tag_t t, bus_dma
 		if (size >= L1_S_SIZE)
 			align = L1_S_SIZE;
 		else
-			align = L2_S_SIZE;
+			align = L2_L_SIZE;
 	}
 
 	va = uvm_km_alloc(kernel_map, size, align, kmflags);
@@ -1335,8 +1357,8 @@ _bus_dmamem_map(bus_dma_tag_t t, bus_dma
 				uncached = false;
 			}
 
-			pmap_kenter_pa(va, pa,
-			    VM_PROT_READ | VM_PROT_WRITE, PMAP_WIRED);
+			pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE,
+			    PMAP_WIRED | (uncached ? PMAP_NOCACHE : 0));
 
 			/*
 			 * If the memory must remain coherent with the
@@ -1346,19 +1368,6 @@ _bus_dmamem_map(bus_dma_tag_t t, bus_dma
 			 * contain the virtal addresses we are making
 			 * uncacheable.
 			 */
-			if (uncached) {
-				cpu_dcache_wbinv_range(va, PAGE_SIZE);
-				cpu_sdcache_wbinv_range(va, pa, PAGE_SIZE);
-				cpu_drain_writebuf();
-				ptep = vtopte(va);
-				*ptep &= ~L2_S_CACHE_MASK;
-				PTE_SYNC(ptep);
-				tlb_flush();
-			}
-#ifdef DEBUG_DMA
-			ptep = vtopte(va);
-			printf(" pte=v%p *pte=%x\n", ptep, *ptep);
-#endif	/* DEBUG_DMA */
 		}
 	}
 	pmap_update(pmap_kernel());
@@ -1766,9 +1775,9 @@ _bus_dmatag_subregion(bus_dma_tag_t tag,
 		nranges = 1;
 	}
 
-	size_t mallocsize = sizeof(*tag) + nranges * sizeof(*dr);
-	if ((*newtag = malloc(mallocsize, M_DMAMAP,
-	    (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL)
+	const size_t tagsize = sizeof(*tag) + nranges * sizeof(*dr);
+	if ((*newtag = kmem_intr_zalloc(tagsize,
+	    (flags & BUS_DMA_NOWAIT) ? KM_NOSLEEP : KM_SLEEP)) == NULL)
 		return ENOMEM;
 
 	dr = (void *)(*newtag + 1);
@@ -1813,10 +1822,13 @@ _bus_dmatag_destroy(bus_dma_tag_t tag)
 #ifdef _ARM32_NEED_BUS_DMA_BOUNCE
 	switch (tag->_tag_needs_free) {
 	case 0:
-		break;				/* not allocated with malloc */
-	case 1:
-		free(tag, M_DMAMAP);		/* last reference to tag */
+		break;				/* not allocated with kmem */
+	case 1: {
+		const size_t tagsize = sizeof(*tag)
+		    + tag->_nranges * sizeof(*tag->_ranges);
+		kmem_intr_free(tag, tagsize);	/* last reference to tag */
 		break;
+	}
 	default:
 		(tag->_tag_needs_free)--;	/* one less reference */
 	}

Reply via email to