diff options
author | jhb <jhb@FreeBSD.org> | 2012-09-06 20:16:59 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2012-09-06 20:16:59 +0000 |
commit | 0bc0a2586ce9caa8fbee0c1f134bff3f6dec4f15 (patch) | |
tree | 01bf8e21104992b8d6a4b8388ad9b756dfcfa433 | |
parent | b483b4ba3d82feaef71fa09be9ad987686bd4204 (diff) | |
download | FreeBSD-src-0bc0a2586ce9caa8fbee0c1f134bff3f6dec4f15.zip FreeBSD-src-0bc0a2586ce9caa8fbee0c1f134bff3f6dec4f15.tar.gz |
Dynamically allocate the S/G lists passed to callback routines rather than
allocating them on the stack of various bus_dmamap_load*() functions. The
S/G lists are stored in the DMA tags. This matches the implementation on
all other platforms.
Discussed with: scottl, gibbs
Tested by: stas (arm@)
-rw-r--r-- | sys/arm/arm/busdma_machdep.c | 60 | ||||
-rw-r--r-- | sys/mips/mips/busdma_machdep.c | 61 |
2 files changed, 71 insertions, 50 deletions
diff --git a/sys/arm/arm/busdma_machdep.c b/sys/arm/arm/busdma_machdep.c index 7deffed..ecda7f9 100644 --- a/sys/arm/arm/busdma_machdep.c +++ b/sys/arm/arm/busdma_machdep.c @@ -81,6 +81,7 @@ struct bus_dma_tag { int map_count; bus_dma_lock_t *lockfunc; void *lockfuncarg; + bus_dma_segment_t *segments; /* * DMA range for this tag. If the page doesn't fall within * one of these ranges, an error is returned. The caller @@ -374,6 +375,8 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, newtag->lockfunc = dflt_lock; newtag->lockfuncarg = NULL; } + newtag->segments = NULL; + /* * Take into account any restrictions imposed by our parent tag */ @@ -447,7 +450,6 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat) #endif if (dmat != NULL) { - if (dmat->map_count != 0) return (EBUSY); @@ -457,6 +459,8 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat) parent = dmat->parent; atomic_subtract_int(&dmat->ref_count, 1); if (dmat->ref_count == 0) { + if (dmat->segments != NULL) + free(dmat->segments, M_DEVBUF); free(dmat, M_DEVBUF); /* * Last reference count, so @@ -484,6 +488,17 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) bus_dmamap_t newmap; int error = 0; + if (dmat->segments == NULL) { + dmat->segments = (bus_dma_segment_t *)malloc( + sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF, + M_NOWAIT); + if (dmat->segments == NULL) { + CTR3(KTR_BUSDMA, "%s: tag %p error %d", + __func__, dmat, ENOMEM); + return (ENOMEM); + } + } + newmap = _busdma_alloc_dmamap(); if (newmap == NULL) { CTR3(KTR_BUSDMA, "%s: tag %p error %d", __func__, dmat, ENOMEM); @@ -585,6 +600,16 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, mflags = M_NOWAIT; else mflags = M_WAITOK; + if (dmat->segments == NULL) { + dmat->segments = (bus_dma_segment_t *)malloc( + sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF, + mflags); + if (dmat->segments == NULL) { + CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", + __func__, dmat, dmat->flags, ENOMEM); + return (ENOMEM); + } + } if (flags & BUS_DMA_ZERO) mflags |= M_ZERO; @@ -883,11 +908,6 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, { vm_offset_t lastaddr = 0; int error, nsegs = -1; -#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT - bus_dma_segment_t dm_segments[dmat->nsegments]; -#else - bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS]; -#endif KASSERT(dmat != NULL, ("dmatag is NULL")); KASSERT(map != NULL, ("dmamap is NULL")); @@ -898,14 +918,14 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, map->buffer = buf; map->len = buflen; error = bus_dmamap_load_buffer(dmat, - dm_segments, map, buf, buflen, kernel_pmap, + dmat->segments, map, buf, buflen, kernel_pmap, flags, &lastaddr, &nsegs); if (error == EINPROGRESS) return (error); if (error) (*callback)(callback_arg, NULL, 0, error); else - (*callback)(callback_arg, dm_segments, nsegs + 1, error); + (*callback)(callback_arg, dmat->segments, nsegs + 1, error); CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", __func__, dmat, dmat->flags, nsegs + 1, error); @@ -921,11 +941,6 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, bus_dmamap_callback2_t *callback, void *callback_arg, int flags) { -#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT - bus_dma_segment_t dm_segments[dmat->nsegments]; -#else - bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS]; -#endif int nsegs = -1, error = 0; M_ASSERTPKTHDR(m0); @@ -941,7 +956,7 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, for (m = m0; m != NULL && error == 0; m = m->m_next) { if (m->m_len > 0) { error = bus_dmamap_load_buffer(dmat, - dm_segments, map, m->m_data, m->m_len, + dmat->segments, map, m->m_data, m->m_len, pmap_kernel(), flags, &lastaddr, &nsegs); map->len += m->m_len; } @@ -954,9 +969,9 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, /* * force "no valid mappings" on error in callback. */ - (*callback)(callback_arg, dm_segments, 0, 0, error); + (*callback)(callback_arg, dmat->segments, 0, 0, error); } else { - (*callback)(callback_arg, dm_segments, nsegs + 1, + (*callback)(callback_arg, dmat->segments, nsegs + 1, m0->m_pkthdr.len, error); } CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", @@ -1012,11 +1027,6 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, int flags) { vm_offset_t lastaddr = 0; -#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT - bus_dma_segment_t dm_segments[dmat->nsegments]; -#else - bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS]; -#endif int nsegs, i, error; bus_size_t resid; struct iovec *iov; @@ -1048,8 +1058,8 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, caddr_t addr = (caddr_t) iov[i].iov_base; if (minlen > 0) { - error = bus_dmamap_load_buffer(dmat, dm_segments, map, - addr, minlen, pmap, flags, &lastaddr, &nsegs); + error = bus_dmamap_load_buffer(dmat, dmat->segments, + map, addr, minlen, pmap, flags, &lastaddr, &nsegs); map->len += minlen; resid -= minlen; @@ -1060,9 +1070,9 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, /* * force "no valid mappings" on error in callback. */ - (*callback)(callback_arg, dm_segments, 0, 0, error); + (*callback)(callback_arg, dmat->segments, 0, 0, error); } else { - (*callback)(callback_arg, dm_segments, nsegs+1, + (*callback)(callback_arg, dmat->segments, nsegs+1, uio->uio_resid, error); } diff --git a/sys/mips/mips/busdma_machdep.c b/sys/mips/mips/busdma_machdep.c index 8e0317d..62e5efd 100644 --- a/sys/mips/mips/busdma_machdep.c +++ b/sys/mips/mips/busdma_machdep.c @@ -80,6 +80,7 @@ struct bus_dma_tag { int map_count; bus_dma_lock_t *lockfunc; void *lockfuncarg; + bus_dma_segment_t *segments; struct bounce_zone *bounce_zone; }; @@ -352,6 +353,8 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, newtag->lockfunc = dflt_lock; newtag->lockfuncarg = NULL; } + newtag->segments = NULL; + /* * Take into account any restrictions imposed by our parent tag */ @@ -434,6 +437,8 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat) parent = dmat->parent; atomic_subtract_int(&dmat->ref_count, 1); if (dmat->ref_count == 0) { + if (dmat->segments != NULL) + free(dmat->segments, M_DEVBUF); free(dmat, M_DEVBUF); /* * Last reference count, so @@ -442,7 +447,7 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat) */ dmat = parent; } else - dmat = NULL; + dmat = NULL; } } CTR2(KTR_BUSDMA, "%s tag %p", __func__, dmat_copy); @@ -461,6 +466,17 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) bus_dmamap_t newmap; int error = 0; + if (dmat->segments == NULL) { + dmat->segments = (bus_dma_segment_t *)malloc( + sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF, + M_NOWAIT); + if (dmat->segments == NULL) { + CTR3(KTR_BUSDMA, "%s: tag %p error %d", + __func__, dmat, ENOMEM); + return (ENOMEM); + } + } + newmap = _busdma_alloc_dmamap(); if (newmap == NULL) { CTR3(KTR_BUSDMA, "%s: tag %p error %d", __func__, dmat, ENOMEM); @@ -563,6 +579,16 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, mflags = M_NOWAIT; else mflags = M_WAITOK; + if (dmat->segments == NULL) { + dmat->segments = (bus_dma_segment_t *)malloc( + sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF, + mflags); + if (dmat->segments == NULL) { + CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", + __func__, dmat, dmat->flags, ENOMEM); + return (ENOMEM); + } + } if (flags & BUS_DMA_ZERO) mflags |= M_ZERO; @@ -824,11 +850,6 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, { vm_offset_t lastaddr = 0; int error, nsegs = -1; -#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT - bus_dma_segment_t dm_segments[dmat->nsegments]; -#else - bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS]; -#endif KASSERT(dmat != NULL, ("dmatag is NULL")); KASSERT(map != NULL, ("dmamap is NULL")); @@ -839,14 +860,14 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, map->buffer = buf; map->len = buflen; error = bus_dmamap_load_buffer(dmat, - dm_segments, map, buf, buflen, kernel_pmap, + dmat->segments, map, buf, buflen, kernel_pmap, flags, &lastaddr, &nsegs); if (error == EINPROGRESS) return (error); if (error) (*callback)(callback_arg, NULL, 0, error); else - (*callback)(callback_arg, dm_segments, nsegs + 1, error); + (*callback)(callback_arg, dmat->segments, nsegs + 1, error); CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", __func__, dmat, dmat->flags, nsegs + 1, error); @@ -862,11 +883,6 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, bus_dmamap_callback2_t *callback, void *callback_arg, int flags) { -#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT - bus_dma_segment_t dm_segments[dmat->nsegments]; -#else - bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS]; -#endif int nsegs = -1, error = 0; M_ASSERTPKTHDR(m0); @@ -882,7 +898,7 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, for (m = m0; m != NULL && error == 0; m = m->m_next) { if (m->m_len > 0) { error = bus_dmamap_load_buffer(dmat, - dm_segments, map, m->m_data, m->m_len, + dmat->segments, map, m->m_data, m->m_len, kernel_pmap, flags, &lastaddr, &nsegs); map->len += m->m_len; } @@ -895,9 +911,9 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, /* * force "no valid mappings" on error in callback. */ - (*callback)(callback_arg, dm_segments, 0, 0, error); + (*callback)(callback_arg, dmat->segments, 0, 0, error); } else { - (*callback)(callback_arg, dm_segments, nsegs + 1, + (*callback)(callback_arg, dmat->segments, nsegs + 1, m0->m_pkthdr.len, error); } CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", @@ -953,11 +969,6 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, int flags) { vm_offset_t lastaddr = 0; -#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT - bus_dma_segment_t dm_segments[dmat->nsegments]; -#else - bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS]; -#endif int nsegs, i, error; bus_size_t resid; struct iovec *iov; @@ -990,8 +1001,8 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, caddr_t addr = (caddr_t) iov[i].iov_base; if (minlen > 0) { - error = bus_dmamap_load_buffer(dmat, dm_segments, map, - addr, minlen, pmap, flags, &lastaddr, &nsegs); + error = bus_dmamap_load_buffer(dmat, dmat->segments, + map, addr, minlen, pmap, flags, &lastaddr, &nsegs); map->len += minlen; resid -= minlen; @@ -1002,9 +1013,9 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, /* * force "no valid mappings" on error in callback. */ - (*callback)(callback_arg, dm_segments, 0, 0, error); + (*callback)(callback_arg, dmat->segments, 0, 0, error); } else { - (*callback)(callback_arg, dm_segments, nsegs+1, + (*callback)(callback_arg, dmat->segments, nsegs+1, uio->uio_resid, error); } |