diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2014-03-10 21:32:16 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2014-03-10 21:32:16 +0000 |
commit | 7b166abfd4e77aaf7745980cf3bc0e8f301091bd (patch) | |
tree | 3eaccbe5a8933f222ca065cf292d0a308f842172 /sys | |
parent | 683800fdaa7922d20c840dade377b3cc138078c8 (diff) |
Support BUS_DMA_NOCACHE in bus_dma(9). Memory allocations done with
BUS_DMA_NOCACHE (or BUS_DMA_COHERENT if the platform does not have coherent
caches) will use PMAP_NOCACHE when invoking pmap_enter(), to avoid creating
cached mappings, and then evicting them from the cache.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/loongson/include/bus.h | 29 | ||||
-rw-r--r-- | sys/arch/loongson/loongson/bus_dma.c | 27 | ||||
-rw-r--r-- | sys/arch/octeon/include/bus.h | 29 | ||||
-rw-r--r-- | sys/arch/octeon/octeon/bus_dma.c | 27 | ||||
-rw-r--r-- | sys/arch/sgi/include/bus.h | 31 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/bus_dma.c | 34 |
6 files changed, 108 insertions, 69 deletions
diff --git a/sys/arch/loongson/include/bus.h b/sys/arch/loongson/include/bus.h index d9f15ef1ac3..676c5cd0d49 100644 --- a/sys/arch/loongson/include/bus.h +++ b/sys/arch/loongson/include/bus.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bus.h,v 1.3 2010/05/08 21:59:56 miod Exp $ */ +/* $OpenBSD: bus.h,v 1.4 2014/03/10 21:32:15 miod Exp $ */ /* * Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved. @@ -332,18 +332,19 @@ bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ -#define BUS_DMA_WAITOK 0x000 -#define BUS_DMA_NOWAIT 0x001 -#define BUS_DMA_ALLOCNOW 0x002 -#define BUS_DMA_COHERENT 0x008 -#define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */ -#define BUS_DMA_BUS2 0x020 -#define BUS_DMA_BUS3 0x040 -#define BUS_DMA_BUS4 0x080 -#define BUS_DMA_READ 0x100 /* mapping is device -> memory only */ -#define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */ -#define BUS_DMA_STREAMING 0x400 /* hint: sequential, unidirectional */ -#define BUS_DMA_ZERO 0x800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_WAITOK 0x0000 +#define BUS_DMA_NOWAIT 0x0001 +#define BUS_DMA_ALLOCNOW 0x0002 +#define BUS_DMA_COHERENT 0x0008 +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_BUS4 0x0080 +#define BUS_DMA_READ 0x0100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0200 /* mapping is memory -> device only */ +#define BUS_DMA_STREAMING 0x0400 /* hint: sequential, unidirectional */ +#define BUS_DMA_ZERO 0x0800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_NOCACHE 0x1000 /* Forwards needed by prototypes below. */ struct mbuf; @@ -475,7 +476,7 @@ int _dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, void _dmamem_unmap(bus_dma_tag_t, caddr_t, size_t); paddr_t _dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int); int _dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t, - bus_dma_segment_t *, int, int *, int, vaddr_t, vaddr_t); + bus_dma_segment_t *, int, int *, int, paddr_t, paddr_t); /* * bus_dmamap_t diff --git a/sys/arch/loongson/loongson/bus_dma.c b/sys/arch/loongson/loongson/bus_dma.c index ab3c742a873..b73d3a0569f 100644 --- a/sys/arch/loongson/loongson/bus_dma.c +++ b/sys/arch/loongson/loongson/bus_dma.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bus_dma.c,v 1.11 2012/10/03 21:44:51 miod Exp $ */ +/* $OpenBSD: bus_dma.c,v 1.12 2014/03/10 21:32:15 miod Exp $ */ /* * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -388,7 +388,7 @@ _dmamem_alloc(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, int flags) { return _dmamem_alloc_range(t, size, alignment, boundary, - segs, nsegs, rsegs, flags, (vaddr_t)0, (vaddr_t)-1); + segs, nsegs, rsegs, flags, (paddr_t)0, (paddr_t)-1); } /* @@ -431,11 +431,11 @@ _dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, size_t size, size_t ssize; paddr_t pa; bus_addr_t addr; - int curseg, error; + int curseg, error, pmap_flags; if (nsegs == 1) { pa = (*t->_device_to_pa)(segs[0].ds_addr); - if (flags & BUS_DMA_COHERENT) + if (flags & (BUS_DMA_COHERENT | BUS_DMA_NOCACHE)) *kvap = (caddr_t)PHYS_TO_XKPHYS(pa, CCA_NC); else *kvap = (caddr_t)PHYS_TO_XKPHYS(pa, CCA_CACHED); @@ -451,6 +451,9 @@ _dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, size_t size, sva = va; ssize = size; + pmap_flags = PMAP_WIRED | PMAP_CANFAIL; + if (flags & (BUS_DMA_COHERENT | BUS_DMA_NOCACHE)) + pmap_flags |= PMAP_NOCACHE; for (curseg = 0; curseg < nsegs; curseg++) { for (addr = segs[curseg].ds_addr; addr < (segs[curseg].ds_addr + segs[curseg].ds_len); @@ -460,14 +463,22 @@ _dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, size_t size, pa = (*t->_device_to_pa)(addr); error = pmap_enter(pmap_kernel(), va, pa, VM_PROT_READ | VM_PROT_WRITE, VM_PROT_READ | - VM_PROT_WRITE | PMAP_WIRED | PMAP_CANFAIL); + VM_PROT_WRITE | pmap_flags); if (error) { pmap_update(pmap_kernel()); uvm_km_free(kernel_map, sva, ssize); return (error); } - if (flags & BUS_DMA_COHERENT) + /* + * This is redundant with what pmap_enter() did + * above, but will take care of forcing other + * mappings of the same page (if any) to be + * uncached. + * If there are no multiple mappings of that + * page, this amounts to a noop. + */ + if (flags & (BUS_DMA_COHERENT | BUS_DMA_NOCACHE)) pmap_page_cache(PHYS_TO_VM_PAGE(pa), PV_UNCACHED); } @@ -634,9 +645,9 @@ _dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf, int _dmamem_alloc_range(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, - int flags, vaddr_t low, vaddr_t high) + int flags, paddr_t low, paddr_t high) { - vaddr_t curaddr, lastaddr; + paddr_t curaddr, lastaddr; vm_page_t m; struct pglist mlist; int curseg, error, plaflag; diff --git a/sys/arch/octeon/include/bus.h b/sys/arch/octeon/include/bus.h index 79c54f1d324..ceacab49c62 100644 --- a/sys/arch/octeon/include/bus.h +++ b/sys/arch/octeon/include/bus.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bus.h,v 1.4 2010/12/04 16:46:00 miod Exp $ */ +/* $OpenBSD: bus.h,v 1.5 2014/03/10 21:32:15 miod Exp $ */ /* * Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved. @@ -303,18 +303,19 @@ bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ -#define BUS_DMA_WAITOK 0x000 -#define BUS_DMA_NOWAIT 0x001 -#define BUS_DMA_ALLOCNOW 0x002 -#define BUS_DMA_COHERENT 0x008 -#define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */ -#define BUS_DMA_BUS2 0x020 -#define BUS_DMA_BUS3 0x040 -#define BUS_DMA_BUS4 0x080 -#define BUS_DMA_READ 0x100 /* mapping is device -> memory only */ -#define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */ -#define BUS_DMA_STREAMING 0x400 /* hint: sequential, unidirectional */ -#define BUS_DMA_ZERO 0x800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_WAITOK 0x0000 +#define BUS_DMA_NOWAIT 0x0001 +#define BUS_DMA_ALLOCNOW 0x0002 +#define BUS_DMA_COHERENT 0x0008 +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_BUS4 0x0080 +#define BUS_DMA_READ 0x0100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0200 /* mapping is memory -> device only */ +#define BUS_DMA_STREAMING 0x0400 /* hint: sequential, unidirectional */ +#define BUS_DMA_ZERO 0x0800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_NOCACHE 0x1000 /* Forwards needed by prototypes below. */ struct mbuf; @@ -446,7 +447,7 @@ int _dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, void _dmamem_unmap(bus_dma_tag_t, caddr_t, size_t); paddr_t _dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int); int _dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t, - bus_dma_segment_t *, int, int *, int, vaddr_t, vaddr_t); + bus_dma_segment_t *, int, int *, int, paddr_t, paddr_t); /* * bus_dmamap_t diff --git a/sys/arch/octeon/octeon/bus_dma.c b/sys/arch/octeon/octeon/bus_dma.c index 35d45c686cf..28728a02f92 100644 --- a/sys/arch/octeon/octeon/bus_dma.c +++ b/sys/arch/octeon/octeon/bus_dma.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bus_dma.c,v 1.7 2012/10/03 19:42:54 miod Exp $ */ +/* $OpenBSD: bus_dma.c,v 1.8 2014/03/10 21:32:15 miod Exp $ */ /* * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -381,7 +381,7 @@ _dmamem_alloc(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, int flags) { return _dmamem_alloc_range(t, size, alignment, boundary, - segs, nsegs, rsegs, flags, (vaddr_t)0, (vaddr_t)-1); + segs, nsegs, rsegs, flags, (paddr_t)0, (paddr_t)-1); } /* @@ -424,11 +424,11 @@ _dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, size_t size, size_t ssize; paddr_t pa; bus_addr_t addr; - int curseg, error; + int curseg, error, pmap_flags; if (nsegs == 1) { pa = (*t->_device_to_pa)(segs[0].ds_addr); - if (flags & BUS_DMA_COHERENT) + if (flags & (BUS_DMA_COHERENT | BUS_DMA_NOCACHE)) *kvap = (caddr_t)PHYS_TO_XKPHYS(pa, CCA_NC); else *kvap = (caddr_t)PHYS_TO_XKPHYS(pa, CCA_CACHED); @@ -444,6 +444,9 @@ _dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, size_t size, sva = va; ssize = size; + pmap_flags = PMAP_WIRED | PMAP_CANFAIL; + if (flags & (BUS_DMA_COHERENT | BUS_DMA_NOCACHE)) + pmap_flags |= PMAP_NOCACHE; for (curseg = 0; curseg < nsegs; curseg++) { for (addr = segs[curseg].ds_addr; addr < (segs[curseg].ds_addr + segs[curseg].ds_len); @@ -453,14 +456,22 @@ _dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, size_t size, pa = (*t->_device_to_pa)(addr); error = pmap_enter(pmap_kernel(), va, pa, VM_PROT_READ | VM_PROT_WRITE, VM_PROT_READ | - VM_PROT_WRITE | PMAP_WIRED | PMAP_CANFAIL); + VM_PROT_WRITE | pmap_flags); if (error) { pmap_update(pmap_kernel()); uvm_km_free(kernel_map, sva, ssize); return (error); } - if (flags & BUS_DMA_COHERENT) + /* + * This is redundant with what pmap_enter() did + * above, but will take care of forcing other + * mappings of the same page (if any) to be + * uncached. + * If there are no multiple mappings of that + * page, this amounts to a noop. + */ + if (flags & (BUS_DMA_COHERENT | BUS_DMA_NOCACHE)) pmap_page_cache(PHYS_TO_VM_PAGE(pa), PV_UNCACHED); } @@ -627,9 +638,9 @@ _dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf, int _dmamem_alloc_range(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, - int flags, vaddr_t low, vaddr_t high) + int flags, paddr_t low, paddr_t high) { - vaddr_t curaddr, lastaddr; + paddr_t curaddr, lastaddr; vm_page_t m; struct pglist mlist; int curseg, error, plaflag; diff --git a/sys/arch/sgi/include/bus.h b/sys/arch/sgi/include/bus.h index f43ef116773..7f2a067c2ab 100644 --- a/sys/arch/sgi/include/bus.h +++ b/sys/arch/sgi/include/bus.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bus.h,v 1.25 2012/03/15 18:52:55 miod Exp $ */ +/* $OpenBSD: bus.h,v 1.26 2014/03/10 21:32:15 miod Exp $ */ /* * Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved. @@ -209,7 +209,7 @@ bus_space_write_region(8,64) static __inline void \ CAT(bus_space_write_raw_region_,n)(bus_space_tag_t bst, \ bus_space_handle_t bsh, \ - bus_addr_t ba, const u_int8_t *x, size_t cnt) \ + bus_addr_t ba, const u_int8_t *x, size_t cnt) \ { \ cnt >>= ((n) >> 1); \ while (cnt--) { \ @@ -305,18 +305,19 @@ bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offs, #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ -#define BUS_DMA_WAITOK 0x000 -#define BUS_DMA_NOWAIT 0x001 -#define BUS_DMA_ALLOCNOW 0x002 -#define BUS_DMA_COHERENT 0x008 -#define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */ -#define BUS_DMA_BUS2 0x020 -#define BUS_DMA_BUS3 0x040 -#define BUS_DMA_BUS4 0x080 -#define BUS_DMA_READ 0x100 /* mapping is device -> memory only */ -#define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */ -#define BUS_DMA_STREAMING 0x400 /* hint: sequential, unidirectional */ -#define BUS_DMA_ZERO 0x800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_WAITOK 0x0000 +#define BUS_DMA_NOWAIT 0x0001 +#define BUS_DMA_ALLOCNOW 0x0002 +#define BUS_DMA_COHERENT 0x0008 +#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x0020 +#define BUS_DMA_BUS3 0x0040 +#define BUS_DMA_BUS4 0x0080 +#define BUS_DMA_READ 0x0100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x0200 /* mapping is memory -> device only */ +#define BUS_DMA_STREAMING 0x0400 /* hint: sequential, unidirectional */ +#define BUS_DMA_ZERO 0x0800 /* zero memory in dmamem_alloc */ +#define BUS_DMA_NOCACHE 0x1000 /* Forwards needed by prototypes below. */ struct mbuf; @@ -448,7 +449,7 @@ int _dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, void _dmamem_unmap(bus_dma_tag_t, caddr_t, size_t); paddr_t _dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int); int _dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t, - bus_dma_segment_t *, int, int *, int, vaddr_t, vaddr_t); + bus_dma_segment_t *, int, int *, int, paddr_t, paddr_t); /* * bus_dmamap_t diff --git a/sys/arch/sgi/sgi/bus_dma.c b/sys/arch/sgi/sgi/bus_dma.c index 7419d278b1f..2565e2c7067 100644 --- a/sys/arch/sgi/sgi/bus_dma.c +++ b/sys/arch/sgi/sgi/bus_dma.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bus_dma.c,v 1.30 2012/10/03 22:46:09 miod Exp $ */ +/* $OpenBSD: bus_dma.c,v 1.31 2014/03/10 21:32:15 miod Exp $ */ /* * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -345,10 +345,12 @@ _dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t addr, if (ssize > size) ssize = size; +#ifndef TGT_COHERENT if (IS_XKPHYS(vaddr) && XKPHYS_TO_CCA(vaddr) == CCA_NC) { size -= ssize; ssize = 0; } +#endif if (ssize != 0) { #ifdef TGT_COHERENT @@ -440,7 +442,7 @@ _dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, size_t size, size_t ssize; paddr_t pa; bus_addr_t addr; - int curseg, error; + int curseg, error, pmap_flags; #if defined(TGT_INDIGO2) /* @@ -454,13 +456,16 @@ _dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, size_t size, return EINVAL; #endif +#ifdef TGT_COHERENT + /* coherent mappings do not need to be uncached on these platforms */ + flags &= ~BUS_DMA_COHERENT; +#endif + if (nsegs == 1) { pa = (*t->_device_to_pa)(segs[0].ds_addr); -#ifndef TGT_COHERENT - if (flags & BUS_DMA_COHERENT) + if (flags & (BUS_DMA_COHERENT | BUS_DMA_NOCACHE)) *kvap = (caddr_t)PHYS_TO_XKPHYS(pa, CCA_NC); else -#endif *kvap = (caddr_t)PHYS_TO_XKPHYS(pa, CCA_CACHED); return (0); } @@ -474,6 +479,9 @@ _dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, size_t size, sva = va; ssize = size; + pmap_flags = PMAP_WIRED | PMAP_CANFAIL; + if (flags & (BUS_DMA_COHERENT | BUS_DMA_NOCACHE)) + pmap_flags |= PMAP_NOCACHE; for (curseg = 0; curseg < nsegs; curseg++) { for (addr = segs[curseg].ds_addr; addr < (segs[curseg].ds_addr + segs[curseg].ds_len); @@ -485,18 +493,24 @@ _dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, size_t size, pa = (*t->_device_to_pa)(addr); error = pmap_enter(pmap_kernel(), va, pa, VM_PROT_READ | VM_PROT_WRITE, VM_PROT_READ | - VM_PROT_WRITE | PMAP_WIRED | PMAP_CANFAIL); + VM_PROT_WRITE | pmap_flags); if (error) { pmap_update(pmap_kernel()); uvm_km_free(kernel_map, sva, ssize); return (error); } -#ifndef TGT_COHERENT - if (flags & BUS_DMA_COHERENT) + /* + * This is redundant with what pmap_enter() did + * above, but will take care of forcing other + * mappings of the same page (if any) to be + * uncached. + * If there are no multiple mappings of that + * page, this amounts to a noop. + */ + if (flags & (BUS_DMA_COHERENT | BUS_DMA_NOCACHE)) pmap_page_cache(PHYS_TO_VM_PAGE(pa), PV_UNCACHED); -#endif } pmap_update(pmap_kernel()); } @@ -670,7 +684,7 @@ _dmamem_alloc_range(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags, paddr_t low, paddr_t high) { - vaddr_t curaddr, lastaddr; + paddr_t curaddr, lastaddr; vm_page_t m; struct pglist mlist; int curseg, error, plaflag; |