svn commit: r244726 - 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
Thu Dec 27 04:29:17 UTC 2012
Author: jeff
Date: Thu Dec 27 04:29:14 2012
New Revision: 244726
URL: http://svnweb.freebsd.org/changeset/base/244726
Log:
- Implement a bus_dma_memory_t type that is used to encapsulate objects
and types for various structures that describe memory regions we want
to dma to.
- Rename bus_dma_mayblock to _nowait to be more consistent. Add a memory_t
parameter so that EINPROGRESS operations will work with any type.
- Change all mayblock implementations to restart any arbitrary type.
- Redefine the load routines splitting the parsers from the API policy.
- Add a physical address loading routine to the backend API. Currently
it is empty.
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 Thu Dec 27 02:02:23 2012 (r244725)
+++ projects/physbio/sys/arm/arm/busdma_machdep-v6.c Thu Dec 27 04:29:14 2012 (r244726)
@@ -142,8 +142,7 @@ struct bus_dmamap {
int pagesneeded;
int pagesreserved;
bus_dma_tag_t dmat;
- void *buf; /* unmapped buffer pointer */
- bus_size_t buflen; /* unmapped buffer length */
+ bus_dma_memory_t mem;
pmap_t pmap;
bus_dmamap_callback_t *callback;
void *callback_arg;
@@ -694,9 +693,6 @@ _bus_dmamap_count_pages(bus_dma_tag_t dm
} else {
if (reserve_bounce_pages(dmat, map, 1) != 0) {
/* Queue us for resources */
- map->dmat = dmat;
- map->buf = buf;
- map->buflen = buflen;
STAILQ_INSERT_TAIL(&bounce_map_waitinglist,
map, links);
mtx_unlock(&bounce_lock);
@@ -842,10 +838,13 @@ cleanup:
void
-__bus_dmamap_mayblock(bus_dma_tag_t dmat, bus_dmamap_t map,
- bus_dmamap_callback_t *callback, void *callback_arg)
+__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map,
+ bus_dma_memory_t mem, bus_dmamap_callback_t *callback,
+ void *callback_arg)
{
+ map->mem = mem;
+ map->dmat = dmat;
map->callback = callback;
map->callback_arg = callback_arg;
}
@@ -1379,8 +1378,8 @@ busdma_swi(void)
mtx_unlock(&bounce_lock);
dmat = map->dmat;
(dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_LOCK);
- bus_dmamap_load(map->dmat, map, map->buf, map->buflen,
- map->callback, map->callback_arg, /*flags*/0);
+ bus_dmamap_load_mem(map->dmat, map, &map->mem, map->callback,
+ map->callback_arg, BUS_DMA_WAITOK);
(dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_UNLOCK);
mtx_lock(&bounce_lock);
}
Modified: projects/physbio/sys/arm/arm/busdma_machdep.c
==============================================================================
--- projects/physbio/sys/arm/arm/busdma_machdep.c Thu Dec 27 02:02:23 2012 (r244725)
+++ projects/physbio/sys/arm/arm/busdma_machdep.c Thu Dec 27 04:29:14 2012 (r244726)
@@ -142,12 +142,11 @@ struct bus_dmamap {
int pagesneeded;
int pagesreserved;
bus_dma_tag_t dmat;
+ bus_dma_memory_t mem;
int flags;
- void *buffer;
void *origbuffer;
void *allocbuffer;
TAILQ_ENTRY(bus_dmamap) freelist;
- int len;
STAILQ_ENTRY(bus_dmamap) links;
bus_dmamap_callback_t *callback;
void *callback_arg;
@@ -740,8 +739,6 @@ _bus_dmamap_count_pages(bus_dma_tag_t dm
} else {
if (reserve_bounce_pages(dmat, map, 1) != 0) {
/* Queue us for resources */
- map->buffer = buf;
- map->len = buflen;
STAILQ_INSERT_TAIL(&bounce_map_waitinglist,
map, links);
mtx_unlock(&bounce_lock);
@@ -923,12 +920,14 @@ cleanup:
}
void
-__bus_dmamap_mayblock(bus_dma_tag_t dmat, bus_dmamap_t map,
- bus_dmamap_callback_t *callback, void *callback_arg)
+__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map,
+ bus_dma_memory_t mem, bus_dmamap_callback_t *callback,
+ void *callback_arg)
{
KASSERT(dmat != NULL, ("dmatag is NULL"));
KASSERT(map != NULL, ("dmamap is NULL"));
+ map->mem = mem;
map->callback = callback;
map->callback_arg = callback_arg;
}
@@ -1308,8 +1307,8 @@ busdma_swi(void)
mtx_unlock(&bounce_lock);
dmat = map->dmat;
(dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_LOCK);
- bus_dmamap_load(map->dmat, map, map->buffer, map->len,
- map->callback, map->callback_arg, /*flags*/0);
+ bus_dmamap_load_mem(map->dmat, map, &map->mem,
+ map->callback, map->callback_arg, BUS_DMA_WAITOK);
(dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_UNLOCK);
mtx_lock(&bounce_lock);
}
Modified: projects/physbio/sys/ia64/ia64/busdma_machdep.c
==============================================================================
--- projects/physbio/sys/ia64/ia64/busdma_machdep.c Thu Dec 27 02:02:23 2012 (r244725)
+++ projects/physbio/sys/ia64/ia64/busdma_machdep.c Thu Dec 27 04:29:14 2012 (r244726)
@@ -105,8 +105,7 @@ struct bus_dmamap {
int pagesneeded;
int pagesreserved;
bus_dma_tag_t dmat;
- void *buf; /* unmapped buffer pointer */
- bus_size_t buflen; /* unmapped buffer length */
+ bus_dma_memory_t mem;
bus_dmamap_callback_t *callback;
void *callback_arg;
STAILQ_ENTRY(bus_dmamap) links;
@@ -535,9 +534,6 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dm
} else {
if (reserve_bounce_pages(dmat, map, 1) != 0) {
/* Queue us for resources */
- map->dmat = dmat;
- map->buf = buf;
- map->buflen = buflen;
STAILQ_INSERT_TAIL(&bounce_map_waitinglist,
map, links);
mtx_unlock(&bounce_lock);
@@ -615,10 +611,12 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dm
void
-__bus_dmamap_mayblock(bus_dma_tag_t dmat, bus_dmamap_t map,
- bus_dmamap_callback_t *callback, void *callback_arg)
+__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map,
+ bus_dma_memory_t mem, bus_dmamap_callback_t *callback, void *callback_arg)
{
if (map != NULL) {
+ map->dmat = dmat;
+ map->mem = mem;
map->callback = callback;
map->callback_arg = callback_arg;
}
@@ -827,8 +825,8 @@ busdma_swi(void)
mtx_unlock(&bounce_lock);
dmat = map->dmat;
(dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_LOCK);
- bus_dmamap_load(map->dmat, map, map->buf, map->buflen,
- map->callback, map->callback_arg, /*flags*/0);
+ bus_dmamap_load_mem(map->dmat, map, &map->mem, map->callback,
+ map->callback_arg, BUS_DMA_WAITOK);
(dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_UNLOCK);
mtx_lock(&bounce_lock);
}
Modified: projects/physbio/sys/kern/subr_busdma.c
==============================================================================
--- projects/physbio/sys/kern/subr_busdma.c Thu Dec 27 02:02:23 2012 (r244725)
+++ projects/physbio/sys/kern/subr_busdma.c Thu Dec 27 04:29:14 2012 (r244726)
@@ -53,6 +53,185 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
/*
+ * Load a list of virtual addresses.
+ */
+static int
+_bus_dmamap_load_vlist(bus_dma_tag_t dmat, bus_dmamap_t map,
+ bus_dma_segment_t *list, int sglist_cnt, struct pmap *pmap, int *nsegs,
+ int flags)
+{
+ int error;
+
+ error = 0;
+ for (; sglist_cnt > 0; sglist_cnt--, list++) {
+ error = _bus_dmamap_load_buffer(dmat, map,
+ (void *)list->ds_addr, list->ds_len, pmap, flags, NULL,
+ nsegs);
+ if (error)
+ break;
+ }
+ return (error);
+}
+
+/*
+ * Load a list of physical addresses.
+ */
+static int
+_bus_dmamap_load_plist(bus_dma_tag_t dmat, bus_dmamap_t map,
+ bus_dma_segment_t *list, int sglist_cnt, int *nsegs, int flags)
+{
+ int error;
+
+ error = 0;
+ for (; sglist_cnt > 0; sglist_cnt--, list++) {
+ error = _bus_dmamap_load_phys(dmat, map,
+ (vm_paddr_t)list->ds_addr, list->ds_len, flags, NULL,
+ nsegs);
+ if (error)
+ break;
+ }
+ return (error);
+}
+
+/*
+ * Load an mbuf chain.
+ */
+static 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);
+
+ 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);
+ }
+ }
+ CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
+ __func__, dmat, flags, error, *nsegs);
+ return (error);
+}
+
+/*
+ * Load from block io.
+ */
+static int
+_bus_dmamap_load_bio(bus_dma_tag_t dmat, bus_dmamap_t map, struct bio *bio,
+ int *nsegs, int flags)
+{
+ int error;
+
+ error = _bus_dmamap_load_buffer(dmat, map, bio->bio_data,
+ bio->bio_bcount, kernel_pmap, flags, NULL, nsegs);
+
+ return (error);
+}
+
+/*
+ * Load a cam control block.
+ */
+static int
+_bus_dmamap_load_ccb(bus_dma_tag_t dmat, bus_dmamap_t map, union ccb *ccb,
+ int *nsegs, int flags)
+{
+ struct ccb_ataio *ataio;
+ struct ccb_scsiio *csio;
+ struct ccb_hdr *ccb_h;
+ void *data_ptr;
+ int error;
+ uint32_t dxfer_len;
+ uint16_t sglist_cnt;
+
+ error = 0;
+ ccb_h = &ccb->ccb_h;
+ switch (ccb_h->func_code) {
+ case XPT_SCSI_IO:
+ csio = &ccb->csio;
+ data_ptr = csio->data_ptr;
+ dxfer_len = csio->dxfer_len;
+ sglist_cnt = csio->sglist_cnt;
+ break;
+ case XPT_ATA_IO:
+ ataio = &ccb->ataio;
+ data_ptr = ataio->data_ptr;
+ dxfer_len = ataio->dxfer_len;
+ sglist_cnt = 0;
+ break;
+ default:
+ panic("_bus_dmamap_load_ccb: Unsupported func code %d",
+ ccb_h->func_code);
+ }
+
+ switch ((ccb_h->flags & CAM_DATA_MASK)) {
+ case CAM_DATA_VADDR:
+ error = _bus_dmamap_load_buffer(dmat, map, data_ptr, dxfer_len,
+ kernel_pmap, flags, NULL, nsegs);
+ break;
+ case CAM_DATA_PADDR:
+ error = _bus_dmamap_load_phys(dmat, map, (vm_paddr_t)data_ptr,
+ dxfer_len, flags, NULL, nsegs);
+ break;
+ case CAM_DATA_SG:
+ error = _bus_dmamap_load_vlist(dmat, map,
+ (bus_dma_segment_t *)data_ptr, sglist_cnt, kernel_pmap,
+ nsegs, flags);
+ break;
+ case CAM_DATA_SG_PADDR:
+ error = _bus_dmamap_load_plist(dmat, map,
+ (bus_dma_segment_t *)data_ptr, sglist_cnt, nsegs, flags);
+ break;
+ case CAM_DATA_BIO:
+ error = _bus_dmamap_load_bio(dmat, map, (struct bio *)data_ptr,
+ nsegs, flags);
+ break;
+ default:
+ panic("_bus_dmamap_load_ccb: flags 0x%X unimplemented",
+ ccb_h->flags);
+ }
+ return (error);
+}
+
+/*
+ * Load a uio.
+ */
+static int
+_bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio,
+ pmap_t pmap, int *nsegs, int flags)
+{
+ bus_size_t resid;
+ bus_size_t minlen;
+ struct iovec *iov;
+ caddr_t addr;
+ int error, i;
+
+ resid = uio->uio_resid;
+ iov = uio->uio_iov;
+ 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;
+ }
+ }
+
+ return (error);
+}
+
+/*
* Map the buffer buf into bus space using the dmamap map.
*/
int
@@ -65,7 +244,8 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_
int nsegs;
if ((flags & BUS_DMA_NOWAIT) == 0)
- _bus_dmamap_mayblock(dmat, map, callback, callback_arg);
+ _bus_dmamap_waitok(dmat, map, dma_mem_vaddr(buf, buflen),
+ callback, callback_arg);
nsegs = -1;
error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, kernel_pmap,
@@ -94,35 +274,6 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_
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)
@@ -130,7 +281,10 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat,
bus_dma_segment_t *segs;
int nsegs, error;
+ flags |= BUS_DMA_NOWAIT;
+ nsegs = -1;
error = _bus_dmamap_load_mbuf_sg(dmat, map, m0, NULL, &nsegs, flags);
+ ++nsegs;
segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error);
if (error)
@@ -149,30 +303,23 @@ bus_dmamap_load_mbuf_sg(bus_dma_tag_t dm
{
int error;
+ flags |= BUS_DMA_NOWAIT;
+ *nsegs = -1;
error = _bus_dmamap_load_mbuf_sg(dmat, map, m0, segs, nsegs, flags);
+ ++*nsegs;
_bus_dmamap_complete(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)
{
bus_dma_segment_t *segs;
- int nsegs, error, i;
- bus_size_t resid;
- bus_size_t minlen;
- struct iovec *iov;
- caddr_t addr;
+ int nsegs, error;
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"));
@@ -181,23 +328,9 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat,
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;
- }
- }
-
+ error = _bus_dmamap_load_uio(dmat, map, uio, pmap, &nsegs, flags);
nsegs++;
+
segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error);
if (error)
(*callback)(callback_arg, segs, 0, 0, error);
@@ -214,91 +347,107 @@ bus_dmamap_load_ccb(bus_dma_tag_t dmat,
bus_dmamap_callback_t *callback, void *callback_arg,
int flags)
{
- struct ccb_ataio *ataio;
- struct ccb_scsiio *csio;
+ bus_dma_segment_t *segs;
struct ccb_hdr *ccb_h;
- void *data_ptr;
- uint32_t dxfer_len;
- uint16_t sglist_cnt;
+ int error;
+ int nsegs;
ccb_h = &ccb->ccb_h;
if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_NONE) {
callback(callback_arg, NULL, 0, 0);
return (0);
}
+ if ((flags & BUS_DMA_NOWAIT) == 0)
+ _bus_dmamap_waitok(dmat, map, dma_mem_ccb(ccb), callback,
+ callback_arg);
+ nsegs = -1;
+ error = _bus_dmamap_load_ccb(dmat, map, ccb, &nsegs, flags);
+ nsegs++;
+ if (error == EINPROGRESS)
+ return (error);
- switch (ccb_h->func_code) {
- case XPT_SCSI_IO:
- csio = &ccb->csio;
- data_ptr = csio->data_ptr;
- dxfer_len = csio->dxfer_len;
- sglist_cnt = csio->sglist_cnt;
+ segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error);
+ if (error)
+ (*callback)(callback_arg, segs, 0, error);
+ else
+ (*callback)(callback_arg, segs, 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);
+}
+
+int
+bus_dmamap_load_mem(bus_dma_tag_t dmat, bus_dmamap_t map,
+ bus_dma_memory_t *mem, bus_dmamap_callback_t *callback,
+ void *callback_arg, int flags)
+{
+ bus_dma_segment_t *segs;
+ int error;
+ int nsegs;
+
+ if ((flags & BUS_DMA_NOWAIT) == 0)
+ _bus_dmamap_waitok(dmat, map, *mem, callback, callback_arg);
+
+ nsegs = -1;
+ switch (mem->dm_type) {
+ case BUS_DMAMEM_VADDR:
+ error = _bus_dmamap_load_buffer(dmat, map, mem->dm_vaddr,
+ mem->dm_opaque, kernel_pmap, flags, NULL, &nsegs);
break;
- case XPT_ATA_IO:
- ataio = &ccb->ataio;
- data_ptr = ataio->data_ptr;
- dxfer_len = ataio->dxfer_len;
- sglist_cnt = 0;
+ case BUS_DMAMEM_PADDR:
+ error = _bus_dmamap_load_phys(dmat, map, mem->dm_paddr,
+ mem->dm_opaque, flags, NULL, &nsegs);
break;
- default:
- panic("bus_dmamap_load_ccb: Unsupported func code %d",
- ccb_h->func_code);
- }
-
- switch ((ccb_h->flags & CAM_DATA_MASK)) {
- case CAM_DATA_VADDR:
- return bus_dmamap_load(dmat,
- map,
- data_ptr,
- dxfer_len,
- callback,
- callback_arg,
- /*flags*/0);
- case CAM_DATA_PADDR: {
- bus_dma_segment_t seg;
-
- seg.ds_addr = (bus_addr_t)(vm_offset_t)data_ptr;
- seg.ds_len = dxfer_len;
- callback(callback_arg, &seg, 1, 0);
- break;
- }
- case CAM_DATA_SG: {
- bus_dma_segment_t *segs;
- int nsegs;
- int error;
- int i;
-
- flags |= BUS_DMA_NOWAIT;
- segs = (bus_dma_segment_t *)data_ptr;
- nsegs = -1;
- error = 0;
- for (i = 0; i < 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++;
- segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error);
- if (error)
- (*callback)(callback_arg, segs, 0, error);
- else
- (*callback)(callback_arg, segs, nsegs, error);
-
- if (error == ENOMEM)
- return (error);
+ case BUS_DMAMEM_VLIST:
+ error = _bus_dmamap_load_vlist(dmat, map, mem->dm_list,
+ mem->dm_opaque, kernel_pmap, &nsegs, flags);
break;
- }
- case CAM_DATA_SG_PADDR: {
- bus_dma_segment_t *segs;
- /* Just use the segments provided */
- segs = (bus_dma_segment_t *)data_ptr;
- callback(callback_arg, segs, sglist_cnt, 0);
+ case BUS_DMAMEM_PLIST:
+ error = _bus_dmamap_load_plist(dmat, map, mem->dm_list,
+ mem->dm_opaque, &nsegs, flags);
+ break;
+ case BUS_DMAMEM_BIO:
+ error = _bus_dmamap_load_bio(dmat, map, mem->dm_bio,
+ &nsegs, flags);
+ break;
+ case BUS_DMAMEM_UIO:
+ error = _bus_dmamap_load_uio(dmat, map, mem->dm_uio,
+ /*XXX*/kernel_pmap, &nsegs, flags);
+ break;
+ case BUS_DMAMEM_MBUF:
+ error = _bus_dmamap_load_mbuf_sg(dmat, map, mem->dm_mbuf, NULL,
+ &nsegs, flags);
+ break;
+ case BUS_DMAMEM_CCB:
+ error = _bus_dmamap_load_ccb(dmat, map, mem->dm_ccb, &nsegs,
+ flags);
break;
}
- case CAM_DATA_BIO:
- default:
- panic("bus_dmamap_load_ccb: flags 0x%X unimplemented",
- ccb_h->flags);
- }
+ 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);
+
+ segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error);
+ if (error)
+ (*callback)(callback_arg, segs, 0, error);
+ else
+ (*callback)(callback_arg, segs, nsegs, 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);
}
Modified: projects/physbio/sys/mips/mips/busdma_machdep.c
==============================================================================
--- projects/physbio/sys/mips/mips/busdma_machdep.c Thu Dec 27 02:02:23 2012 (r244725)
+++ projects/physbio/sys/mips/mips/busdma_machdep.c Thu Dec 27 04:29:14 2012 (r244726)
@@ -135,12 +135,11 @@ struct bus_dmamap {
int pagesneeded;
int pagesreserved;
bus_dma_tag_t dmat;
+ bus_dma_memory_t mem;
int flags;
- void *buffer;
void *origbuffer;
void *allocbuffer;
TAILQ_ENTRY(bus_dmamap) freelist;
- int len;
STAILQ_ENTRY(bus_dmamap) links;
bus_dmamap_callback_t *callback;
void *callback_arg;
@@ -738,8 +737,6 @@ _bus_dmamap_count_pages(bus_dma_tag_t dm
} else {
if (reserve_bounce_pages(dmat, map, 1) != 0) {
/* Queue us for resources */
- map->buffer = buf;
- map->len = buflen;
STAILQ_INSERT_TAIL(&bounce_map_waitinglist,
map, links);
mtx_unlock(&bounce_lock);
@@ -865,12 +862,13 @@ cleanup:
}
void
-__bus_dmamap_mayblock(bus_dma_tag_t dmat, bus_dmamap_t map,
- bus_dmamap_callback_t *callback, void *callback_arg)
+__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map,
+ bus_dma_memory_t mem, bus_dmamap_callback_t *callback, void *callback_arg)
{
KASSERT(dmat != NULL, ("dmatag is NULL"));
KASSERT(map != NULL, ("dmamap is NULL"));
+ map->mem = mem;
map->callback = callback;
map->callback_arg = callback_arg;
}
@@ -1292,8 +1290,8 @@ busdma_swi(void)
mtx_unlock(&bounce_lock);
dmat = map->dmat;
(dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_LOCK);
- bus_dmamap_load(map->dmat, map, map->buffer, map->len,
- map->callback, map->callback_arg, /*flags*/0);
+ bus_dmamap_load_mem(map->dmat, map, &map->mem, map->callback,
+ map->callback_arg, BUS_DMA_WAITOK);
(dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_UNLOCK);
mtx_lock(&bounce_lock);
}
Modified: projects/physbio/sys/powerpc/powerpc/busdma_machdep.c
==============================================================================
--- projects/physbio/sys/powerpc/powerpc/busdma_machdep.c Thu Dec 27 02:02:23 2012 (r244725)
+++ projects/physbio/sys/powerpc/powerpc/busdma_machdep.c Thu Dec 27 04:29:14 2012 (r244726)
@@ -626,9 +626,6 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dm
} else {
if (reserve_bounce_pages(dmat, map, 1) != 0) {
/* Queue us for resources */
- map->dmat = dmat;
- map->buf = buf;
- map->buflen = buflen;
STAILQ_INSERT_TAIL(&bounce_map_waitinglist,
map, links);
mtx_unlock(&bounce_lock);
@@ -709,11 +706,14 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dm
}
void
-__bus_dmamap_mayblock(bus_dma_tag_t dmat, bus_dmamap_t map,
- bus_dmamap_callback_t *callback, void *callback_arg)
+__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map,
+ bus_dma_memory_t mem, bus_dmamap_callback_t *callback,
+ void *callback_arg)
{
if (dmat->flags & BUS_DMA_COULD_BOUNCE) {
+ map->dmat = dmat;
+ map->mem = mem;
map->callback = callback;
map->callback_arg = callback_arg;
}
@@ -1036,8 +1036,9 @@ busdma_swi(void)
mtx_unlock(&bounce_lock);
dmat = map->dmat;
(dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_LOCK);
- bus_dmamap_load(map->dmat, map, map->buf, map->buflen,
- map->callback, map->callback_arg, /*flags*/0);
+ bus_dmamap_load_mem(map->dmat, map, &map->mem,
+ map->callback, map->callback_arg,
+ BUS_DMA_WAITOK);
(dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_UNLOCK);
mtx_lock(&bounce_lock);
}
Modified: projects/physbio/sys/sparc64/include/bus_dma.h
==============================================================================
--- projects/physbio/sys/sparc64/include/bus_dma.h Thu Dec 27 02:02:23 2012 (r244725)
+++ projects/physbio/sys/sparc64/include/bus_dma.h Thu Dec 27 04:29:14 2012 (r244726)
@@ -81,7 +81,7 @@ struct bus_dma_methods {
int (*dm_dmamap_load_buffer)(bus_dma_tag_t dmat, bus_dmamap_t map,
void *buf, bus_size_t buflen, struct pmap *pmap, int flags,
bus_dma_segment_t *segs, int *segp);
- void (*dm_dmamap_mayblock)(bus_dma_tag_t dmat, bus_dmamap_t map,
+ void (*dm_dmamap_waitok)(bus_dma_tag_t dmat, bus_dmamap_t map,
bus_dmamap_callback_t *callback, void *callback_arg);
bus_dma_segment_t *(*dm_dmamap_complete)(bus_dma_tag_t dmat,
bus_dmamap_t map, bus_dma_segment_t *segs, int nsegs, int error);
@@ -127,8 +127,8 @@ struct bus_dma_tag {
#define _bus_dmamap_load_buffer(t, m, b, l, p, f, s, sp) \
((t)->dt_mt->dm_dmamap_load_buffer((t), (m), (b), (l), (p), \
(f), (s), (sp)))
-#define _bus_dmamap_mayblock(t, m, c, ca) \
- ((t)->dt_mt->dm_dmamap_mayblock((t), (m), (c), (ca)))
+#define _bus_dmamap_waitok(t, m, mem, c, ca) \
+ ((t)->dt_mt->dm_dmamap_waitok((t), (m), (mem), (c), (ca)))
#define _bus_dmamap_complete(t, m, s, n, e) \
((t)->dt_mt->dm_dmamap_complete((t), (m), (s), (n), (e)))
#define bus_dmamap_unload(t, p) \
Modified: projects/physbio/sys/sparc64/sparc64/bus_machdep.c
==============================================================================
--- projects/physbio/sys/sparc64/sparc64/bus_machdep.c Thu Dec 27 02:02:23 2012 (r244725)
+++ projects/physbio/sys/sparc64/sparc64/bus_machdep.c Thu Dec 27 04:29:14 2012 (r244726)
@@ -404,8 +404,8 @@ nexus_dmamap_load_buffer(bus_dma_tag_t d
}
static void
-nexus_dmamap_mayblock(bus_dma_tag_t dmat, bus_dmamap_t map,
- bus_dmamap_callback_t *callback, void *callback_arg)
+nexus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map,
+ bus_dma_memory_t mem, bus_dmamap_callback_t *callback, void *callback_arg)
{
}
@@ -521,7 +521,7 @@ static struct bus_dma_methods nexus_dma_
nexus_dmamap_create,
nexus_dmamap_destroy,
nexus_dmamap_load_buffer,
- nexus_dmamap_mayblock,
+ nexus_dmamap_waitok,
nexus_dmamap_complete,
nexus_dmamap_unload,
nexus_dmamap_sync,
Modified: projects/physbio/sys/sparc64/sparc64/iommu.c
==============================================================================
--- projects/physbio/sys/sparc64/sparc64/iommu.c Thu Dec 27 02:02:23 2012 (r244725)
+++ projects/physbio/sys/sparc64/sparc64/iommu.c Thu Dec 27 04:29:14 2012 (r244726)
@@ -970,8 +970,8 @@ iommu_dvmamap_load_buffer(bus_dma_tag_t
}
static void
-iommu_dvmamap_mayblock(bus_dma_tag_t dmat, bus_dmamap_t map,
- bus_dmamap_callback_t *callback, void *callback_arg)
+iommu_dvmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map,
+ bus_dma_memory_t mem, bus_dmamap_callback_t *callback, void *callback_arg)
{
}
@@ -1089,7 +1089,7 @@ struct bus_dma_methods iommu_dma_methods
iommu_dvmamap_create,
iommu_dvmamap_destroy,
iommu_dvmamap_load_buffer,
- iommu_dvmamap_mayblock,
+ iommu_dvmamap_waitok,
iommu_dvmamap_complete,
iommu_dvmamap_unload,
iommu_dvmamap_sync,
Modified: projects/physbio/sys/sys/bus_dma.h
==============================================================================
--- projects/physbio/sys/sys/bus_dma.h Thu Dec 27 02:02:23 2012 (r244725)
+++ projects/physbio/sys/sys/bus_dma.h Thu Dec 27 04:29:14 2012 (r244726)
@@ -113,6 +113,7 @@
struct pmap;
struct mbuf;
struct uio;
+struct bio;
union ccb;
/*
@@ -135,6 +136,128 @@ typedef struct bus_dma_segment {
} bus_dma_segment_t;
/*
+ * bus_dma_memory_t
+ *
+ * Encapsulates various memory descriptors that devices may DMA
+ * to or from.
+ */
+
+typedef struct bus_dma_memory {
+ union {
+ void *dm_vaddr;
+ vm_paddr_t dm_paddr;
+ bus_dma_segment_t *dm_list;
+ struct bio *dm_bio;
+ struct uio *dm_uio;
+ struct mbuf *dm_mbuf;
+ union ccb *dm_ccb;
+ };
+ bus_size_t dm_opaque; /* type specific data. */
+ uint32_t dm_type; /* Type of memory. */
+} bus_dma_memory_t;
+
+#define BUS_DMAMEM_VADDR 1 /* Contiguous virtual address. */
+#define BUS_DMAMEM_PADDR 2 /* Contiguous physical address. */
+#define BUS_DMAMEM_VLIST 3 /* sglist of kva. */
+#define BUS_DMAMEM_PLIST 4 /* sglist of physical addresses. */
+#define BUS_DMAMEM_BIO 5 /* Pointer to a bio (block io). */
+#define BUS_DMAMEM_UIO 6 /* Pointer to a uio (any io). */
+#define BUS_DMAMEM_MBUF 7 /* Pointer to a mbuf (network io). */
+#define BUS_DMAMEM_CCB 8 /* Cam control block. (scsi/ata io). */
+
+static inline bus_dma_memory_t
+dma_mem_vaddr(void *vaddr, bus_size_t len)
+{
+ bus_dma_memory_t mem;
+
+ mem.dm_vaddr = vaddr;
+ mem.dm_opaque = len;
+ mem.dm_type = BUS_DMAMEM_VADDR;
+
+ return (mem);
+}
+
+static inline bus_dma_memory_t
+dma_mem_paddr(vm_paddr_t paddr, bus_size_t len)
+{
+ bus_dma_memory_t mem;
+
+ mem.dm_paddr = paddr;
+ mem.dm_opaque = len;
+ mem.dm_type = BUS_DMAMEM_PADDR;
+
+ return (mem);
+}
+
+static inline bus_dma_memory_t
+dma_mem_vlist(bus_dma_segment_t *vlist, int sglist_cnt)
+{
+ bus_dma_memory_t mem;
+
+ mem.dm_list = vlist;
+ mem.dm_opaque = sglist_cnt;
+ mem.dm_type = BUS_DMAMEM_VLIST;
+
+ return (mem);
+}
+
+static inline bus_dma_memory_t
+dma_mem_plist(bus_dma_segment_t *plist, int sglist_cnt)
+{
+ bus_dma_memory_t mem;
+
+ mem.dm_list = plist;
+ mem.dm_opaque = sglist_cnt;
+ mem.dm_type = BUS_DMAMEM_PLIST;
+
+ return (mem);
+}
+
+static inline bus_dma_memory_t
+dma_mem_bio(struct bio *bio)
+{
+ bus_dma_memory_t mem;
+
+ mem.dm_bio = bio;
+ mem.dm_type = BUS_DMAMEM_BIO;
+
+ return (mem);
+}
+
+static inline bus_dma_memory_t
+dma_mem_uio(struct uio *uio)
+{
+ bus_dma_memory_t mem;
+
+ mem.dm_uio = uio;
+ mem.dm_type = BUS_DMAMEM_UIO;
+
+ return (mem);
+}
+
+static inline bus_dma_memory_t
+dma_mem_mbuf(struct mbuf *mbuf)
+{
+ bus_dma_memory_t mem;
+
+ mem.dm_mbuf = mbuf;
+ mem.dm_type = BUS_DMAMEM_MBUF;
+
+ return (mem);
+}
+
+static inline bus_dma_memory_t
+dma_mem_ccb(union ccb *ccb)
+{
+ bus_dma_memory_t mem;
+
+ mem.dm_ccb = ccb;
+ mem.dm_type = BUS_DMAMEM_CCB;
+
+ return (mem);
+}
+
+/*
* A function that returns 1 if the address cannot be accessed by
* a device and 0 if it can be.
*/
@@ -229,6 +352,13 @@ int bus_dmamap_load_ccb(bus_dma_tag_t dm
int flags);
/*
+ * Loads any memory descriptor.
+ */
+int bus_dmamap_load_mem(bus_dma_tag_t dmat, bus_dmamap_t map,
+ bus_dma_memory_t *mem, bus_dmamap_callback_t *callback,
+ void *callback_arg, int flags);
+
+/*
* XXX sparc64 uses the same interface, but a much different implementation.
* <machine/bus_dma.h> for the sparc64 arch contains the equivalent
* declarations.
@@ -286,13 +416,15 @@ void _bus_dmamap_unload(bus_dma_tag_t dm
* busdma layers. These are not intended for consumption by driver
* software.
*/
-void __bus_dmamap_mayblock(bus_dma_tag_t dmat, bus_dmamap_t map,
- bus_dmamap_callback_t *callback, void *callback_arg);
+void __bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map,
+ bus_dma_memory_t mem,
+ bus_dmamap_callback_t *callback,
+ void *callback_arg);
-#define _bus_dmamap_mayblock(dmat, map, callback, callback_arg) \
+#define _bus_dmamap_waitok(dmat, map, mem, callback, callback_arg) \
do { \
if ((map) != NULL) \
- __bus_dmamap_mayblock(dmat, map, callback, \
+ __bus_dmamap_waitok(dmat, map, mem, callback, \
callback_arg); \
} while (0);
@@ -300,6 +432,10 @@ int _bus_dmamap_load_buffer(bus_dma_tag_
void *buf, bus_size_t buflen, struct pmap *pmap,
int flags, bus_dma_segment_t *segs, int *segp);
+int _bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map,
+ vm_paddr_t paddr, bus_size_t buflen,
+ int flags, bus_dma_segment_t *segs, int *segp);
+
bus_dma_segment_t *_bus_dmamap_complete(bus_dma_tag_t dmat,
bus_dmamap_t map,
bus_dma_segment_t *segs,
Modified: projects/physbio/sys/x86/x86/busdma_machdep.c
==============================================================================
--- projects/physbio/sys/x86/x86/busdma_machdep.c Thu Dec 27 02:02:23 2012 (r244725)
+++ projects/physbio/sys/x86/x86/busdma_machdep.c Thu Dec 27 04:29:14 2012 (r244726)
@@ -122,8 +122,7 @@ struct bus_dmamap {
int pagesneeded;
int pagesreserved;
bus_dma_tag_t dmat;
- void *buf; /* unmapped buffer pointer */
- bus_size_t buflen; /* unmapped buffer length */
+ bus_dma_memory_t mem;
bus_dmamap_callback_t *callback;
void *callback_arg;
STAILQ_ENTRY(bus_dmamap) links;
@@ -627,9 +626,6 @@ _bus_dmamap_count_pages(bus_dma_tag_t dm
} else {
if (reserve_bounce_pages(dmat, map, 1) != 0) {
/* Queue us for resources */
- map->dmat = dmat;
- map->buf = buf;
- map->buflen = buflen;
STAILQ_INSERT_TAIL(&bounce_map_waitinglist,
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-projects
mailing list