summaryrefslogtreecommitdiffstats
path: root/sys/powerpc
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2012-08-03 13:50:29 +0000
committerjhb <jhb@FreeBSD.org>2012-08-03 13:50:29 +0000
commitf9289f9fa2c7c57477d2badf22ce93fa88d40980 (patch)
tree0def93a0647d8081690c1b834995b33f80c45d5e /sys/powerpc
parent10741a6f2e055da1e3257fa5200824b2204cca4d (diff)
downloadFreeBSD-src-f9289f9fa2c7c57477d2badf22ce93fa88d40980.zip
FreeBSD-src-f9289f9fa2c7c57477d2badf22ce93fa88d40980.tar.gz
Improve the handling of static DMA buffers that use non-default memory
attributes (currently just BUS_DMA_NOCACHE): - Don't call pmap_change_attr() on the returned address, instead use kmem_alloc_contig() to ask the VM system for memory with the requested attribute. - As a result, always use kmem_alloc_contig() for non-default memory attributes, even for sub-page allocations. This requires adjusting bus_dmamem_free()'s logic for determining which free routine to use. - For x86, add a new dummy bus_dmamap that is used for static DMA buffers allocated via kmem_alloc_contig(). bus_dmamem_free() can then use the map pointer to determine which free routine to use. - For powerpc, add a new flag to the allocated map (bus_dmamem_alloc() always creates a real map on powerpc) to indicate which free routine should be used. Note that the BUS_DMA_NOCACHE handling in powerpc is currently #ifdef'd out. I have left it disabled but updated it to match x86. Reviewed by: scottl MFC after: 1 month
Diffstat (limited to 'sys/powerpc')
-rw-r--r--sys/powerpc/powerpc/busdma_machdep.c39
1 files changed, 20 insertions, 19 deletions
diff --git a/sys/powerpc/powerpc/busdma_machdep.c b/sys/powerpc/powerpc/busdma_machdep.c
index 2063b1d..7953f91 100644
--- a/sys/powerpc/powerpc/busdma_machdep.c
+++ b/sys/powerpc/powerpc/busdma_machdep.c
@@ -46,6 +46,8 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
#include <vm/vm_page.h>
#include <vm/vm_map.h>
@@ -130,6 +132,7 @@ struct bus_dmamap {
bus_dmamap_callback_t *callback;
void *callback_arg;
STAILQ_ENTRY(bus_dmamap) links;
+ int contigalloc;
};
static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist;
@@ -489,6 +492,7 @@ int
bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
bus_dmamap_t *mapp)
{
+ vm_memattr_t attr;
int mflags;
if (flags & BUS_DMA_NOWAIT)
@@ -500,6 +504,12 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
if (flags & BUS_DMA_ZERO)
mflags |= M_ZERO;
+#ifdef NOTYET
+ if (flags & BUS_DMA_NOCACHE)
+ attr = VM_MEMATTR_UNCACHEABLE;
+ else
+#endif
+ attr = VM_MEMATTR_DEFAULT;
/*
* XXX:
@@ -511,7 +521,8 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
*/
if ((dmat->maxsize <= PAGE_SIZE) &&
(dmat->alignment < dmat->maxsize) &&
- dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) {
+ dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem) &&
+ attr == VM_MEMATTR_DEFAULT) {
*vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags);
} else {
/*
@@ -520,9 +531,10 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
* multi-seg allocations yet though.
* XXX Certain AGP hardware does.
*/
- *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags,
- 0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul,
- dmat->boundary);
+ *vaddr = (void *)kmem_alloc_contig(kernel_map, dmat->maxsize,
+ mflags, 0ul, dmat->lowaddr, dmat->alignment ?
+ dmat->alignment : 1ul, dmat->boundary, attr);
+ (*mapp)->contigalloc = 1;
}
if (*vaddr == NULL) {
CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
@@ -531,11 +543,6 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
} else if (vtophys(*vaddr) & (dmat->alignment - 1)) {
printf("bus_dmamem_alloc failed to align memory properly.\n");
}
-#ifdef NOTYET
- if (flags & BUS_DMA_NOCACHE)
- pmap_change_attr((vm_offset_t)*vaddr, dmat->maxsize,
- VM_MEMATTR_UNCACHEABLE);
-#endif
CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
__func__, dmat, dmat->flags, 0);
return (0);
@@ -548,18 +555,12 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
void
bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)
{
- bus_dmamap_destroy(dmat, map);
-#ifdef NOTYET
- pmap_change_attr((vm_offset_t)vaddr, dmat->maxsize, VM_MEMATTR_DEFAULT);
-#endif
- if ((dmat->maxsize <= PAGE_SIZE) &&
- (dmat->alignment < dmat->maxsize) &&
- dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem))
+ if (!map->contigalloc)
free(vaddr, M_DEVBUF);
- else {
- contigfree(vaddr, dmat->maxsize, M_DEVBUF);
- }
+ else
+ kmem_free(kernel_map, (vm_offset_t)vaddr, dmat->maxsize);
+ bus_dmamap_destroy(dmat, map);
CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags);
}
OpenPOWER on IntegriCloud