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