svn commit: r244012 - in projects/physbio/sys: arm/arm ia64/ia64 kern mips/mips powerpc/powerpc sparc64/include sparc64/sparc64 sys x86/x86

Jeff Roberson jeff at FreeBSD.org
Sat Dec 8 02:32:37 UTC 2012


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 ***


More information about the svn-src-projects mailing list