diff options
author | jhb <jhb@FreeBSD.org> | 2012-08-03 13:50:29 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2012-08-03 13:50:29 +0000 |
commit | f9289f9fa2c7c57477d2badf22ce93fa88d40980 (patch) | |
tree | 0def93a0647d8081690c1b834995b33f80c45d5e /sys/powerpc | |
parent | 10741a6f2e055da1e3257fa5200824b2204cca4d (diff) | |
download | FreeBSD-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.c | 39 |
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); } |