Date: Sat, 8 Dec 2012 02:32:36 +0000 (UTC) From: Jeff Roberson <jeff@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r244012 - in projects/physbio/sys: arm/arm ia64/ia64 kern mips/mips powerpc/powerpc sparc64/include sparc64/sparc64 sys x86/x86 Message-ID: <201212080232.qB82WaJl041966@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jeff Date: Sat Dec 8 02:32:35 2012 New Revision: 244012 URL: http://svnweb.freebsd.org/changeset/base/244012 Log: - Make a MI/MD busdma interface for loading virtual addresses. Re-implement load_mbuf, load_uio, load_buf, and a new load of a virtual segment list using these primitives. This eliminates code duplicated in 8 places and allows for future expansion of the busdma types without changing each architecture. Sponsored by: EMC / Isilon Storage Division Modified: projects/physbio/sys/arm/arm/busdma_machdep-v6.c projects/physbio/sys/arm/arm/busdma_machdep.c projects/physbio/sys/ia64/ia64/busdma_machdep.c projects/physbio/sys/kern/subr_busdma.c projects/physbio/sys/mips/mips/busdma_machdep.c projects/physbio/sys/powerpc/powerpc/busdma_machdep.c projects/physbio/sys/sparc64/include/bus_dma.h projects/physbio/sys/sparc64/sparc64/bus_machdep.c projects/physbio/sys/sparc64/sparc64/iommu.c projects/physbio/sys/sys/bus_dma.h projects/physbio/sys/x86/x86/busdma_machdep.c Modified: projects/physbio/sys/arm/arm/busdma_machdep-v6.c ============================================================================== --- projects/physbio/sys/arm/arm/busdma_machdep-v6.c Sat Dec 8 01:16:54 2012 (r244011) +++ projects/physbio/sys/arm/arm/busdma_machdep-v6.c Sat Dec 8 02:32:35 2012 (r244012) @@ -46,8 +46,6 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/proc.h> #include <sys/mutex.h> -#include <sys/mbuf.h> -#include <sys/uio.h> #include <sys/sysctl.h> #include <vm/vm.h> @@ -837,168 +835,46 @@ cleanup: return (0); } -/* - * Map the buffer buf into bus space using the dmamap map. - */ -int -bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, - bus_size_t buflen, bus_dmamap_callback_t *callback, - void *callback_arg, int flags) + +void +__bus_dmamap_mayblock(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dmamap_callback_t *callback, void *callback_arg, + int *flags) { - int error, nsegs = -1; - flags |= BUS_DMA_WAITOK; + (*flags) |= BUS_DMA_WAITOK; map->callback = callback; map->callback_arg = callback_arg; +} - error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, kernel_pmap, - flags, NULL, &nsegs); - - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, nsegs + 1); - - if (error == EINPROGRESS) { - return (error); - } +void +_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dmamap_callback_t *callback, void *callback_arg, + int nsegs, int error) +{ if (error) (*callback)(callback_arg, dmat->segments, 0, error); else - (*callback)(callback_arg, dmat->segments, nsegs + 1, 0); - - /* - * Return ENOMEM to the caller so that it can pass it up the stack. - * This error only happens when NOWAIT is set, so deferal is disabled. - */ - if (error == ENOMEM) - return (error); - - return (0); + (*callback)(callback_arg, dmat->segments, nsegs, 0); } - -/* - * Like _bus_dmamap_load(), but for mbufs. - */ -static __inline int -_bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, - struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, - int flags) -{ - int error; - - M_ASSERTPKTHDR(m0); - - flags |= BUS_DMA_NOWAIT; - *nsegs = -1; - error = 0; - if (m0->m_pkthdr.len <= dmat->maxsize) { - struct mbuf *m; - - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = _bus_dmamap_load_buffer(dmat, map, - m->m_data, m->m_len, - kernel_pmap, flags, segs, - nsegs); - } - } - } else { - error = EINVAL; - } - - /* XXX FIXME: Having to increment nsegs is really annoying */ - ++*nsegs; - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, *nsegs); - return (error); -} - -int -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) +void +_bus_dmamap_complete2(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dmamap_callback2_t *callback, + void *callback_arg, int nsegs, bus_size_t len, int error) { - int nsegs, error; - error = _bus_dmamap_load_mbuf_sg(dmat, map, m0, NULL, &nsegs, flags); - - if (error) { - /* force "no valid mappings" in callback */ + if (error) (*callback)(callback_arg, dmat->segments, 0, 0, error); - } else { - (*callback)(callback_arg, dmat->segments, - nsegs, m0->m_pkthdr.len, error); - } - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, nsegs); - - return (error); + else + (*callback)(callback_arg, dmat->segments, nsegs, len, error); } -int -bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, - struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, - int flags) +void +_bus_dmamap_directseg(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dma_segment_t *segs, int nsegs, int error) { - return (_bus_dmamap_load_mbuf_sg(dmat, map, m0, segs, nsegs, flags)); -} - -/* - * Like _bus_dmamap_load(), but for uios. - */ -int -bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, - struct uio *uio, - bus_dmamap_callback2_t *callback, void *callback_arg, - int flags) -{ - int nsegs, error, i; - bus_size_t resid; - struct iovec *iov; - pmap_t pmap; - - flags |= BUS_DMA_NOWAIT; - resid = uio->uio_resid; - iov = uio->uio_iov; - - if (uio->uio_segflg == UIO_USERSPACE) { - KASSERT(uio->uio_td != NULL, - ("bus_dmamap_load_uio: USERSPACE but no proc")); - pmap = vmspace_pmap(uio->uio_td->td_proc->p_vmspace); - } else - pmap = kernel_pmap; - - nsegs = -1; - error = 0; - for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) { - /* - * Now at the first iovec to load. Load each iovec - * until we have exhausted the residual count. - */ - bus_size_t minlen = - resid < iov[i].iov_len ? resid : iov[i].iov_len; - caddr_t addr = (caddr_t) iov[i].iov_base; - - if (minlen > 0) { - error = _bus_dmamap_load_buffer(dmat, map, - addr, minlen, pmap, flags, - NULL, &nsegs); - resid -= minlen; - } - } - - if (error) { - /* force "no valid mappings" in callback */ - (*callback)(callback_arg, dmat->segments, 0, 0, error); - } else { - (*callback)(callback_arg, dmat->segments, - nsegs+1, uio->uio_resid, error); - } - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, nsegs + 1); - return (error); } /* Modified: projects/physbio/sys/arm/arm/busdma_machdep.c ============================================================================== --- projects/physbio/sys/arm/arm/busdma_machdep.c Sat Dec 8 01:16:54 2012 (r244011) +++ projects/physbio/sys/arm/arm/busdma_machdep.c Sat Dec 8 02:32:35 2012 (r244012) @@ -44,8 +44,6 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/proc.h> #include <sys/mutex.h> -#include <sys/mbuf.h> -#include <sys/uio.h> #include <sys/ktr.h> #include <sys/kernel.h> #include <sys/sysctl.h> @@ -916,164 +914,47 @@ cleanup: return (error); } -/* - * Map the buffer buf into bus space using the dmamap map. - */ -int -bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, - bus_size_t buflen, bus_dmamap_callback_t *callback, - void *callback_arg, int flags) +void +__bus_dmamap_mayblock(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dmamap_callback_t *callback, void *callback_arg, + int *flags) { - int error, nsegs = -1; KASSERT(dmat != NULL, ("dmatag is NULL")); KASSERT(map != NULL, ("dmamap is NULL")); + (*flags) |= BUS_DMA_WAITOK; map->callback = callback; map->callback_arg = callback_arg; - error = _bus_dmamap_load_buffer(dmat, - map, buf, buflen, kernel_pmap, - flags, NULL, &nsegs); - if (error == EINPROGRESS) - return (error); - if (error) - (*callback)(callback_arg, NULL, 0, error); - else - (*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); - - return (error); -} - -/* - * Like bus_dmamap_load(), but for mbufs. - */ -int -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) -{ - int nsegs = -1, error = 0; - - M_ASSERTPKTHDR(m0); - - if (m0->m_pkthdr.len <= dmat->maxsize) { - struct mbuf *m; - - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = _bus_dmamap_load_buffer(dmat, - map, m->m_data, m->m_len, - kernel_pmap, flags, NULL, &nsegs); - } - } - } else { - error = EINVAL; - } - - if (error) { - /* - * force "no valid mappings" on error in callback. - */ - (*callback)(callback_arg, dmat->segments, 0, 0, error); - } else { - (*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", - __func__, dmat, dmat->flags, error, nsegs + 1); - - return (error); } -int -bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, - struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, - int flags) +void +_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dmamap_callback_t *callback, void *callback_arg, + int nsegs, int error) { - int error = 0; - M_ASSERTPKTHDR(m0); - - flags |= BUS_DMA_NOWAIT; - *nsegs = -1; - if (m0->m_pkthdr.len <= dmat->maxsize) { - struct mbuf *m; - - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = _bus_dmamap_load_buffer(dmat, map, - m->m_data, m->m_len, - kernel_pmap, flags, - segs, nsegs); - } - } - } else { - error = EINVAL; - } - /* XXX FIXME: Having to increment nsegs is really annoying */ - ++*nsegs; - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, *nsegs); - return (error); + if (error) + (*callback)(callback_arg, dmat->segments, 0, error); + else + (*callback)(callback_arg, dmat->segments, nsegs, 0); } -/* - * Like bus_dmamap_load(), but for uios. - */ -int -bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, - bus_dmamap_callback2_t *callback, void *callback_arg, - int flags) -{ - int nsegs, i, error; - bus_size_t resid; - struct iovec *iov; - struct pmap *pmap; - - resid = uio->uio_resid; - iov = uio->uio_iov; - - if (uio->uio_segflg == UIO_USERSPACE) { - KASSERT(uio->uio_td != NULL, - ("bus_dmamap_load_uio: USERSPACE but no proc")); - pmap = vmspace_pmap(uio->uio_td->td_proc->p_vmspace); - } else - pmap = kernel_pmap; - - error = 0; - nsegs = -1; - for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) { - /* - * Now at the first iovec to load. Load each iovec - * until we have exhausted the residual count. - */ - bus_size_t minlen = - resid < iov[i].iov_len ? resid : iov[i].iov_len; - caddr_t addr = (caddr_t) iov[i].iov_base; - - if (minlen > 0) { - error = _bus_dmamap_load_buffer(dmat, - map, addr, minlen, pmap, flags, NULL, &nsegs); - - resid -= minlen; - } - } +void +_bus_dmamap_complete2(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dmamap_callback2_t *callback, + void *callback_arg, int nsegs, bus_size_t len, int error) +{ - if (error) { - /* - * force "no valid mappings" on error in callback. - */ + if (error) (*callback)(callback_arg, dmat->segments, 0, 0, error); - } else { - (*callback)(callback_arg, dmat->segments, nsegs+1, - uio->uio_resid, error); - } + else + (*callback)(callback_arg, dmat->segments, nsegs, len, error); +} - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, nsegs + 1); - return (error); +void +_bus_dmamap_directseg(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dma_segment_t *segs, int nsegs, int error) +{ } /* Modified: projects/physbio/sys/ia64/ia64/busdma_machdep.c ============================================================================== --- projects/physbio/sys/ia64/ia64/busdma_machdep.c Sat Dec 8 01:16:54 2012 (r244011) +++ projects/physbio/sys/ia64/ia64/busdma_machdep.c Sat Dec 8 02:32:35 2012 (r244012) @@ -31,13 +31,11 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> -#include <sys/mbuf.h> #include <sys/lock.h> #include <sys/mutex.h> #include <sys/bus.h> #include <sys/interrupt.h> #include <sys/proc.h> -#include <sys/uio.h> #include <sys/sysctl.h> #include <vm/vm.h> @@ -615,152 +613,45 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dm return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */ } -/* - * Map the buffer buf into bus space using the dmamap map. - */ -int -bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, - bus_size_t buflen, bus_dmamap_callback_t *callback, void *callback_arg, - int flags) -{ - int error, nsegs = -1; +void +__bus_dmamap_mayblock(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dmamap_callback_t *callback, void *callback_arg, int *flags) +{ if (map != NULL) { - flags |= BUS_DMA_WAITOK; + (*flags) |= BUS_DMA_WAITOK; map->callback = callback; map->callback_arg = callback_arg; } +} - error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, kernel_pmap, - flags, NULL, &nsegs); - - if (error == EINPROGRESS) - return (error); +void +_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dmamap_callback_t *callback, void *callback_arg, int nsegs, int error) +{ if (error) (*callback)(callback_arg, dmat->segments, 0, error); else - (*callback)(callback_arg, dmat->segments, nsegs + 1, 0); - - return (0); + (*callback)(callback_arg, dmat->segments, nsegs, 0); } -/* - * Like _bus_dmamap_load(), but for mbufs. - */ -int -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) +void +_bus_dmamap_complete2(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dmamap_callback2_t *callback, + void *callback_arg, int nsegs, bus_size_t len, int error) { - int nsegs, error; - - M_ASSERTPKTHDR(m0); - - flags |= BUS_DMA_NOWAIT; - nsegs = -1; - error = 0; - if (m0->m_pkthdr.len <= dmat->maxsize) { - struct mbuf *m; - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = _bus_dmamap_load_buffer(dmat, map, - m->m_data, m->m_len, kernel_pmap, flags, - NULL, &nsegs); - } - } - } else { - error = EINVAL; - } - - if (error) { - /* force "no valid mappings" in callback */ + if (error) (*callback)(callback_arg, dmat->segments, 0, 0, error); - } else { - (*callback)(callback_arg, dmat->segments, nsegs + 1, - m0->m_pkthdr.len, error); - } - return (error); -} - -int -bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, - bus_dma_segment_t *segs, int *nsegs, int flags) -{ - int error; - - M_ASSERTPKTHDR(m0); - - flags |= BUS_DMA_NOWAIT; - *nsegs = -1; - error = 0; - if (m0->m_pkthdr.len <= dmat->maxsize) { - struct mbuf *m; - - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = _bus_dmamap_load_buffer(dmat, map, - m->m_data, m->m_len, kernel_pmap, flags, - segs, nsegs); - } - } - ++*nsegs; - } else { - error = EINVAL; - } - - return (error); + else + (*callback)(callback_arg, dmat->segments, nsegs, len, error); } -/* - * Like _bus_dmamap_load(), but for uios. - */ -int -bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, - bus_dmamap_callback2_t *callback, void *callback_arg, int flags) +void +_bus_dmamap_directseg(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dma_segment_t *segs, int nsegs, int error) { - int nsegs, error, i; - bus_size_t resid; - struct iovec *iov; - pmap_t pmap; - - flags |= BUS_DMA_NOWAIT; - resid = uio->uio_resid; - iov = uio->uio_iov; - - if (uio->uio_segflg == UIO_USERSPACE) { - pmap = vmspace_pmap(uio->uio_td->td_proc->p_vmspace); - KASSERT(td != NULL, - ("bus_dmamap_load_uio: USERSPACE but no proc")); - } else - pmap = kernel_pmap; - - nsegs = -1; - error = 0; - for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) { - /* - * Now at the first iovec to load. Load each iovec - * until we have exhausted the residual count. - */ - bus_size_t minlen = - resid < iov[i].iov_len ? resid : iov[i].iov_len; - caddr_t addr = (caddr_t) iov[i].iov_base; - - if (minlen > 0) { - error = _bus_dmamap_load_buffer(dmat, map, addr, - minlen, td, flags, NULL, &nsegs); - resid -= minlen; - } - } - - if (error) { - /* force "no valid mappings" in callback */ - (*callback)(callback_arg, dmat->segments, 0, 0, error); - } else { - (*callback)(callback_arg, dmat->segments, nsegs + 1, - uio->uio_resid, error); - } - return (error); } /* Modified: projects/physbio/sys/kern/subr_busdma.c ============================================================================== --- projects/physbio/sys/kern/subr_busdma.c Sat Dec 8 01:16:54 2012 (r244011) +++ projects/physbio/sys/kern/subr_busdma.c Sat Dec 8 02:32:35 2012 (r244012) @@ -2,6 +2,9 @@ * Copyright (c) 2012 EMC Corp. * All rights reserved. * + * Copyright (c) 1997, 1998 Justin T. Gibbs. + * All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,13 +38,162 @@ __FBSDID("$FreeBSD$"); #include <sys/bio.h> #include <sys/bus.h> #include <sys/callout.h> +#include <sys/mbuf.h> +#include <sys/proc.h> #include <sys/uio.h> +#include <vm/vm.h> +#include <vm/vm_page.h> +#include <vm/vm_map.h> +#include <vm/pmap.h> + #include <cam/cam.h> #include <cam/cam_ccb.h> #include <machine/bus.h> +/* + * Map the buffer buf into bus space using the dmamap map. + */ +int +bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, + bus_size_t buflen, bus_dmamap_callback_t *callback, + void *callback_arg, int flags) +{ + int error; + int nsegs; + + _bus_dmamap_mayblock(dmat, map, callback, callback_arg, &flags); + + nsegs = -1; + error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, kernel_pmap, + flags, NULL, &nsegs); + nsegs++; + + CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", + __func__, dmat, flags, error, nsegs + 1); + + if (error == EINPROGRESS) + return (error); + + _bus_dmamap_complete(dmat, map, callback, callback_arg, nsegs, error); + + /* + * Return ENOMEM to the caller so that it can pass it up the stack. + * This error only happens when NOWAIT is set, so deferal is disabled. + */ + if (error == ENOMEM) + return (error); + + return (0); +} + +/* + * Like _bus_dmamap_load(), but for mbufs. + */ +static __inline int +_bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, + struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, int flags) +{ + struct mbuf *m; + int error; + + M_ASSERTPKTHDR(m0); + + flags |= BUS_DMA_NOWAIT; + *nsegs = -1; + error = 0; + + for (m = m0; m != NULL && error == 0; m = m->m_next) { + if (m->m_len > 0) { + error = _bus_dmamap_load_buffer(dmat, map, m->m_data, + m->m_len, kernel_pmap, flags, segs, nsegs); + } + } + + ++*nsegs; + CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", + __func__, dmat, flags, error, *nsegs); + return (error); +} + +int +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) +{ + int nsegs, error; + + error = _bus_dmamap_load_mbuf_sg(dmat, map, m0, NULL, &nsegs, flags); + + _bus_dmamap_complete2(dmat, map, callback, callback_arg, nsegs, + m0->m_pkthdr.len, error); + + CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", + __func__, dmat, flags, error, nsegs); + return (error); +} + +int +bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, + bus_dma_segment_t *segs, int *nsegs, int flags) +{ + int error; + + error = _bus_dmamap_load_mbuf_sg(dmat, map, m0, segs, nsegs, flags); + _bus_dmamap_directseg(dmat, map, segs, *nsegs, error); + return (error); +} + +/* + * Like _bus_dmamap_load(), but for uios. + */ +int +bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, + bus_dmamap_callback2_t *callback, void *callback_arg, int flags) +{ + int nsegs, error, i; + bus_size_t resid; + bus_size_t minlen; + struct iovec *iov; + caddr_t addr; + pmap_t pmap; + + flags |= BUS_DMA_NOWAIT; + resid = uio->uio_resid; + iov = uio->uio_iov; + + if (uio->uio_segflg == UIO_USERSPACE) { + KASSERT(uio->uio_td != NULL, + ("bus_dmamap_load_uio: USERSPACE but no proc")); + pmap = vmspace_pmap(uio->uio_td->td_proc->p_vmspace); + } else + pmap = kernel_pmap; + + nsegs = -1; + error = 0; + for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) { + /* + * Now at the first iovec to load. Load each iovec + * until we have exhausted the residual count. + */ + + addr = (caddr_t) iov[i].iov_base; + minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len; + if (minlen > 0) { + error = _bus_dmamap_load_buffer(dmat, map, addr, + minlen, pmap, flags, NULL, &nsegs); + resid -= minlen; + } + } + + _bus_dmamap_complete2(dmat, map, callback, callback_arg, nsegs, + uio->uio_resid, error); + + CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", + __func__, dmat, dmat, error, nsegs + 1); + return (error); +} + int bus_dmamap_load_ccb(bus_dma_tag_t dmat, bus_dmamap_t map, union ccb *ccb, bus_dmamap_callback_t *callback, void *callback_arg, @@ -96,22 +248,26 @@ bus_dmamap_load_ccb(bus_dma_tag_t dmat, break; } case CAM_DATA_SG: { -#if 0 - struct uio sguio; - KASSERT((sizeof (sguio.uio_iov) == sizeof (data_ptr) && - sizeof (sguio.uio_iovcnt) >= sizeof (sglist_cnt) && - sizeof (sguio.uio_resid) >= sizeof (dxfer_len)), - ("uio won't fit csio data")); - sguio.uio_iov = (struct iovec *)data_ptr; - sguio.uio_iovcnt = csio->sglist_cnt; - sguio.uio_resid = csio->dxfer_len; - sguio.uio_segflg = UIO_SYSSPACE; - return bus_dmamap_load_uio(dmat, map, &sguio, callback, - callback_arg, 0); -#else - panic("bus_dmamap_load_ccb: flags 0x%X unimplemented", - ccb_h->flags); -#endif + struct bus_dma_segment *segs; + int nsegs; + int error; + int i; + + flags |= BUS_DMA_NOWAIT; + segs = (struct bus_dma_segment *)data_ptr; + nsegs = -1; + error = 0; + for (i = 0; i < csio->sglist_cnt && error == 0; i++) { + error = _bus_dmamap_load_buffer(dmat, map, + (void *)segs[i].ds_addr, segs[i].ds_len, + kernel_pmap, flags, NULL, &nsegs); + } + nsegs++; + _bus_dmamap_complete(dmat, map, callback, callback_arg, nsegs, + error); + if (error == ENOMEM) + return (error); + break; } case CAM_DATA_SG_PADDR: { struct bus_dma_segment *segs; Modified: projects/physbio/sys/mips/mips/busdma_machdep.c ============================================================================== --- projects/physbio/sys/mips/mips/busdma_machdep.c Sat Dec 8 01:16:54 2012 (r244011) +++ projects/physbio/sys/mips/mips/busdma_machdep.c Sat Dec 8 02:32:35 2012 (r244012) @@ -41,8 +41,6 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/proc.h> #include <sys/mutex.h> -#include <sys/mbuf.h> -#include <sys/uio.h> #include <sys/ktr.h> #include <sys/kernel.h> #include <sys/sysctl.h> @@ -858,164 +856,47 @@ cleanup: return (error); } -/* - * Map the buffer buf into bus space using the dmamap map. - */ -int -bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, - bus_size_t buflen, bus_dmamap_callback_t *callback, - void *callback_arg, int flags) +void +__bus_dmamap_mayblock(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dmamap_callback_t *callback, void *callback_arg, + int *flags) { - int error, nsegs = -1; KASSERT(dmat != NULL, ("dmatag is NULL")); KASSERT(map != NULL, ("dmamap is NULL")); + (*flags) |= BUS_DMA_WAITOK; map->callback = callback; map->callback_arg = callback_arg; - error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, kernel_pmap, - flags, NULL, &nsegs); - if (error == EINPROGRESS) - return (error); - if (error) - (*callback)(callback_arg, NULL, 0, error); - else - (*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); - - return (error); -} - -/* - * Like bus_dmamap_load(), but for mbufs. - */ -int -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) -{ - int nsegs = -1, error = 0; - - M_ASSERTPKTHDR(m0); - - if (m0->m_pkthdr.len <= dmat->maxsize) { - struct mbuf *m; - - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = _bus_dmamap_load_buffer(dmat, - map, m->m_data, m->m_len, - kernel_pmap, flags, NULL, &nsegs); - } - } - } else { - error = EINVAL; - } - - if (error) { - /* - * force "no valid mappings" on error in callback. - */ - (*callback)(callback_arg, dmat->segments, 0, 0, error); - } else { - (*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", - __func__, dmat, dmat->flags, error, nsegs + 1); - - return (error); } -int -bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, - struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, - int flags) +void +_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dmamap_callback_t *callback, void *callback_arg, + int nsegs, int error) { - int error = 0; - M_ASSERTPKTHDR(m0); - flags |= BUS_DMA_NOWAIT; - *nsegs = -1; - if (m0->m_pkthdr.len <= dmat->maxsize) { - struct mbuf *m; - - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = _bus_dmamap_load_buffer(dmat, map, - m->m_data, m->m_len, - kernel_pmap, flags, - segs, nsegs); - } - } - } else { - error = EINVAL; - } - - /* XXX FIXME: Having to increment nsegs is really annoying */ - ++*nsegs; - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, *nsegs); - return (error); + if (error) + (*callback)(callback_arg, dmat->segments, 0, error); + else + (*callback)(callback_arg, dmat->segments, nsegs, 0); } -/* - * Like bus_dmamap_load(), but for uios. - */ -int -bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, - bus_dmamap_callback2_t *callback, void *callback_arg, - int flags) -{ - int nsegs, i, error; - bus_size_t resid; - struct iovec *iov; - struct pmap *pmap; - - resid = uio->uio_resid; - iov = uio->uio_iov; - - if (uio->uio_segflg == UIO_USERSPACE) { - KASSERT(uio->uio_td != NULL, - ("bus_dmamap_load_uio: USERSPACE but no proc")); - /* XXX: pmap = vmspace_pmap(uio->uio_td->td_proc->p_vmspace); */ - panic("can't do it yet"); - } else - pmap = kernel_pmap; - - error = 0; - nsegs = -1; - for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) { - /* - * Now at the first iovec to load. Load each iovec - * until we have exhausted the residual count. - */ - bus_size_t minlen = - resid < iov[i].iov_len ? resid : iov[i].iov_len; - caddr_t addr = (caddr_t) iov[i].iov_base; - - if (minlen > 0) { - error = _bus_dmamap_load_buffer(dmat, map, addr, - minlen, pmap, flags, NULL, &nsegs); - - resid -= minlen; - } - } +void +_bus_dmamap_complete2(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dmamap_callback2_t *callback, + void *callback_arg, int nsegs, bus_size_t len, int error) +{ - if (error) { - /* - * force "no valid mappings" on error in callback. - */ + if (error) (*callback)(callback_arg, dmat->segments, 0, 0, error); - } else { - (*callback)(callback_arg, dmat->segments, nsegs+1, - uio->uio_resid, error); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201212080232.qB82WaJl041966>