| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: bus_dma.c,v 1.100 2017/12/29 08:56:49 skrll Exp $ */ | | 1 | /* $NetBSD: bus_dma.c,v 1.101 2017/12/29 08:58:57 skrll Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | | 8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, |
9 | * NASA Ames Research Center. | | 9 | * NASA Ames Research Center. |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
| @@ -25,27 +25,27 @@ | | | @@ -25,27 +25,27 @@ |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
30 | * POSSIBILITY OF SUCH DAMAGE. | | 30 | * POSSIBILITY OF SUCH DAMAGE. |
31 | */ | | 31 | */ |
32 | | | 32 | |
33 | #define _ARM32_BUS_DMA_PRIVATE | | 33 | #define _ARM32_BUS_DMA_PRIVATE |
34 | | | 34 | |
35 | #include "opt_arm_bus_space.h" | | 35 | #include "opt_arm_bus_space.h" |
36 | | | 36 | |
37 | #include <sys/cdefs.h> | | 37 | #include <sys/cdefs.h> |
38 | __KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.100 2017/12/29 08:56:49 skrll Exp $"); | | 38 | __KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.101 2017/12/29 08:58:57 skrll Exp $"); |
39 | | | 39 | |
40 | #include <sys/param.h> | | 40 | #include <sys/param.h> |
41 | #include <sys/systm.h> | | 41 | #include <sys/systm.h> |
42 | #include <sys/kernel.h> | | 42 | #include <sys/kernel.h> |
43 | #include <sys/proc.h> | | 43 | #include <sys/proc.h> |
44 | #include <sys/buf.h> | | 44 | #include <sys/buf.h> |
45 | #include <sys/bus.h> | | 45 | #include <sys/bus.h> |
46 | #include <sys/cpu.h> | | 46 | #include <sys/cpu.h> |
47 | #include <sys/reboot.h> | | 47 | #include <sys/reboot.h> |
48 | #include <sys/conf.h> | | 48 | #include <sys/conf.h> |
49 | #include <sys/file.h> | | 49 | #include <sys/file.h> |
50 | #include <sys/kmem.h> | | 50 | #include <sys/kmem.h> |
51 | #include <sys/mbuf.h> | | 51 | #include <sys/mbuf.h> |
| @@ -176,27 +176,27 @@ _bus_dma_busaddr_to_paddr(bus_dma_tag_t | | | @@ -176,27 +176,27 @@ _bus_dma_busaddr_to_paddr(bus_dma_tag_t |
176 | static int | | 176 | static int |
177 | _bus_dmamap_load_paddr(bus_dma_tag_t t, bus_dmamap_t map, | | 177 | _bus_dmamap_load_paddr(bus_dma_tag_t t, bus_dmamap_t map, |
178 | bus_addr_t paddr, bus_size_t size, bool coherent) | | 178 | bus_addr_t paddr, bus_size_t size, bool coherent) |
179 | { | | 179 | { |
180 | bus_dma_segment_t * const segs = map->dm_segs; | | 180 | bus_dma_segment_t * const segs = map->dm_segs; |
181 | int nseg = map->dm_nsegs; | | 181 | int nseg = map->dm_nsegs; |
182 | bus_addr_t lastaddr; | | 182 | bus_addr_t lastaddr; |
183 | bus_addr_t bmask = ~(map->_dm_boundary - 1); | | 183 | bus_addr_t bmask = ~(map->_dm_boundary - 1); |
184 | bus_addr_t curaddr; | | 184 | bus_addr_t curaddr; |
185 | bus_size_t sgsize; | | 185 | bus_size_t sgsize; |
186 | uint32_t _ds_flags = coherent ? _BUS_DMAMAP_COHERENT : 0; | | 186 | uint32_t _ds_flags = coherent ? _BUS_DMAMAP_COHERENT : 0; |
187 | | | 187 | |
188 | if (nseg > 0) | | 188 | if (nseg > 0) |
189 | lastaddr = segs[nseg-1].ds_addr + segs[nseg-1].ds_len; | | 189 | lastaddr = segs[nseg - 1].ds_addr + segs[nseg - 1].ds_len; |
190 | else | | 190 | else |
191 | lastaddr = 0xdead; | | 191 | lastaddr = 0xdead; |
192 | | | 192 | |
193 | again: | | 193 | again: |
194 | sgsize = size; | | 194 | sgsize = size; |
195 | | | 195 | |
196 | /* Make sure we're in an allowed DMA range. */ | | 196 | /* Make sure we're in an allowed DMA range. */ |
197 | if (t->_ranges != NULL) { | | 197 | if (t->_ranges != NULL) { |
198 | /* XXX cache last result? */ | | 198 | /* XXX cache last result? */ |
199 | const struct arm32_dma_range * const dr = | | 199 | const struct arm32_dma_range * const dr = |
200 | _bus_dma_paddr_inrange(t->_ranges, t->_nranges, paddr); | | 200 | _bus_dma_paddr_inrange(t->_ranges, t->_nranges, paddr); |
201 | if (dr == NULL) | | 201 | if (dr == NULL) |
202 | return EINVAL; | | 202 | return EINVAL; |
| @@ -225,32 +225,32 @@ _bus_dmamap_load_paddr(bus_dma_tag_t t, | | | @@ -225,32 +225,32 @@ _bus_dmamap_load_paddr(bus_dma_tag_t t, |
225 | if (map->_dm_boundary > 0) { | | 225 | if (map->_dm_boundary > 0) { |
226 | bus_addr_t baddr; /* next boundary address */ | | 226 | bus_addr_t baddr; /* next boundary address */ |
227 | | | 227 | |
228 | baddr = (curaddr + map->_dm_boundary) & bmask; | | 228 | baddr = (curaddr + map->_dm_boundary) & bmask; |
229 | if (sgsize > (baddr - curaddr)) | | 229 | if (sgsize > (baddr - curaddr)) |
230 | sgsize = (baddr - curaddr); | | 230 | sgsize = (baddr - curaddr); |
231 | } | | 231 | } |
232 | | | 232 | |
233 | /* | | 233 | /* |
234 | * Insert chunk into a segment, coalescing with the | | 234 | * Insert chunk into a segment, coalescing with the |
235 | * previous segment if possible. | | 235 | * previous segment if possible. |
236 | */ | | 236 | */ |
237 | if (nseg > 0 && curaddr == lastaddr && | | 237 | if (nseg > 0 && curaddr == lastaddr && |
238 | segs[nseg-1].ds_len + sgsize <= map->dm_maxsegsz && | | 238 | segs[nseg - 1].ds_len + sgsize <= map->dm_maxsegsz && |
239 | ((segs[nseg-1]._ds_flags ^ _ds_flags) & _BUS_DMAMAP_COHERENT) == 0 && | | 239 | ((segs[nseg - 1]._ds_flags ^ _ds_flags) & _BUS_DMAMAP_COHERENT) == 0 && |
240 | (map->_dm_boundary == 0 || | | 240 | (map->_dm_boundary == 0 || |
241 | (segs[nseg-1].ds_addr & bmask) == (curaddr & bmask))) { | | 241 | (segs[nseg - 1].ds_addr & bmask) == (curaddr & bmask))) { |
242 | /* coalesce */ | | 242 | /* coalesce */ |
243 | segs[nseg-1].ds_len += sgsize; | | 243 | segs[nseg - 1].ds_len += sgsize; |
244 | } else if (nseg >= map->_dm_segcnt) { | | 244 | } else if (nseg >= map->_dm_segcnt) { |
245 | return EFBIG; | | 245 | return EFBIG; |
246 | } else { | | 246 | } else { |
247 | /* new segment */ | | 247 | /* new segment */ |
248 | segs[nseg].ds_addr = curaddr; | | 248 | segs[nseg].ds_addr = curaddr; |
249 | segs[nseg].ds_len = sgsize; | | 249 | segs[nseg].ds_len = sgsize; |
250 | segs[nseg]._ds_flags = _ds_flags; | | 250 | segs[nseg]._ds_flags = _ds_flags; |
251 | nseg++; | | 251 | nseg++; |
252 | } | | 252 | } |
253 | | | 253 | |
254 | lastaddr = curaddr + sgsize; | | 254 | lastaddr = curaddr + sgsize; |
255 | | | 255 | |
256 | paddr += sgsize; | | 256 | paddr += sgsize; |
| @@ -1607,27 +1607,27 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t, | | | @@ -1607,27 +1607,27 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t, |
1607 | * Allocate physical memory from the given physical address range. | | 1607 | * Allocate physical memory from the given physical address range. |
1608 | * Called by DMA-safe memory allocation methods. | | 1608 | * Called by DMA-safe memory allocation methods. |
1609 | */ | | 1609 | */ |
1610 | int | | 1610 | int |
1611 | _bus_dmamem_alloc_range(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, | | 1611 | _bus_dmamem_alloc_range(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, |
1612 | bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, | | 1612 | bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, |
1613 | int flags, paddr_t low, paddr_t high) | | 1613 | int flags, paddr_t low, paddr_t high) |
1614 | { | | 1614 | { |
1615 | paddr_t curaddr, lastaddr; | | 1615 | paddr_t curaddr, lastaddr; |
1616 | struct vm_page *m; | | 1616 | struct vm_page *m; |
1617 | struct pglist mlist; | | 1617 | struct pglist mlist; |
1618 | int curseg, error; | | 1618 | int curseg, error; |
1619 | | | 1619 | |
1620 | KASSERTMSG(boundary == 0 || (boundary & (boundary-1)) == 0, | | 1620 | KASSERTMSG(boundary == 0 || (boundary & (boundary - 1)) == 0, |
1621 | "invalid boundary %#lx", boundary); | | 1621 | "invalid boundary %#lx", boundary); |
1622 | | | 1622 | |
1623 | #ifdef DEBUG_DMA | | 1623 | #ifdef DEBUG_DMA |
1624 | printf("alloc_range: t=%p size=%lx align=%lx boundary=%lx segs=%p nsegs=%x rsegs=%p flags=%x lo=%lx hi=%lx\n", | | 1624 | printf("alloc_range: t=%p size=%lx align=%lx boundary=%lx segs=%p nsegs=%x rsegs=%p flags=%x lo=%lx hi=%lx\n", |
1625 | t, size, alignment, boundary, segs, nsegs, rsegs, flags, low, high); | | 1625 | t, size, alignment, boundary, segs, nsegs, rsegs, flags, low, high); |
1626 | #endif /* DEBUG_DMA */ | | 1626 | #endif /* DEBUG_DMA */ |
1627 | | | 1627 | |
1628 | /* Always round the size. */ | | 1628 | /* Always round the size. */ |
1629 | size = round_page(size); | | 1629 | size = round_page(size); |
1630 | | | 1630 | |
1631 | /* | | 1631 | /* |
1632 | * We accept boundaries < size, splitting in multiple segments | | 1632 | * We accept boundaries < size, splitting in multiple segments |
1633 | * if needed. uvm_pglistalloc does not, so compute an appropriate | | 1633 | * if needed. uvm_pglistalloc does not, so compute an appropriate |