summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/arm/arm/busdma_machdep-v6.c10
-rw-r--r--sys/arm/arm/busdma_machdep.c11
-rw-r--r--sys/ia64/ia64/busdma_machdep.c11
-rw-r--r--sys/kern/subr_bus_dma.c25
-rw-r--r--sys/mips/mips/busdma_machdep.c10
-rw-r--r--sys/powerpc/powerpc/busdma_machdep.c10
-rw-r--r--sys/sparc64/include/bus_dma.h2
-rw-r--r--sys/sys/bus_dma.h13
-rw-r--r--sys/x86/x86/busdma_machdep.c10
9 files changed, 94 insertions, 8 deletions
diff --git a/sys/arm/arm/busdma_machdep-v6.c b/sys/arm/arm/busdma_machdep-v6.c
index 31ebfe4..e7f01c4 100644
--- a/sys/arm/arm/busdma_machdep-v6.c
+++ b/sys/arm/arm/busdma_machdep-v6.c
@@ -975,6 +975,16 @@ _bus_dmamap_load_phys(bus_dma_tag_t dmat,
return (0);
}
+int
+_bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map,
+ struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags,
+ bus_dma_segment_t *segs, int *segp)
+{
+
+ return (bus_dmamap_load_ma_triv(dmat, map, ma, tlen, ma_offs, flags,
+ segs, segp));
+}
+
/*
* Utility function to load a linear buffer. segp contains
* the starting segment on entrace, and the ending segment on exit.
diff --git a/sys/arm/arm/busdma_machdep.c b/sys/arm/arm/busdma_machdep.c
index 1fca1e8..8ef8e03 100644
--- a/sys/arm/arm/busdma_machdep.c
+++ b/sys/arm/arm/busdma_machdep.c
@@ -992,6 +992,17 @@ _bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf,
}
return (0);
}
+
+int
+_bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map,
+ struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags,
+ bus_dma_segment_t *segs, int *segp)
+{
+
+ return (bus_dmamap_load_ma_triv(dmat, map, ma, tlen, ma_offs, flags,
+ segs, segp));
+}
+
/*
* Utility function to load a linear buffer. segp contains
* the starting segment on entrance, and the ending segment on exit.
diff --git a/sys/ia64/ia64/busdma_machdep.c b/sys/ia64/ia64/busdma_machdep.c
index 770f29f..206fc6e 100644
--- a/sys/ia64/ia64/busdma_machdep.c
+++ b/sys/ia64/ia64/busdma_machdep.c
@@ -658,6 +658,17 @@ _bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map,
*/
return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */
}
+
+int
+_bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map,
+ struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags,
+ bus_dma_segment_t *segs, int *segp)
+{
+
+ return (bus_dmamap_load_ma_triv(dmat, map, ma, tlen, ma_offs, flags,
+ segs, segp));
+}
+
/*
* Utility function to load a linear buffer. segp contains
* the starting segment on entrace, and the ending segment on exit.
diff --git a/sys/kern/subr_bus_dma.c b/sys/kern/subr_bus_dma.c
index 999de3f..a16d8c8 100644
--- a/sys/kern/subr_bus_dma.c
+++ b/sys/kern/subr_bus_dma.c
@@ -124,24 +124,33 @@ static int
_bus_dmamap_load_bio(bus_dma_tag_t dmat, bus_dmamap_t map, struct bio *bio,
int *nsegs, int flags)
{
- vm_paddr_t paddr;
- bus_size_t len, tlen;
- int error, i, ma_offs;
+ int error;
if ((bio->bio_flags & BIO_UNMAPPED) == 0) {
error = _bus_dmamap_load_buffer(dmat, map, bio->bio_data,
bio->bio_bcount, kernel_pmap, flags, NULL, nsegs);
- return (error);
+ } else {
+ error = _bus_dmamap_load_ma(dmat, map, bio->bio_ma,
+ bio->bio_bcount, bio->bio_ma_offset, flags, NULL, nsegs);
}
+ return (error);
+}
+
+int
+bus_dmamap_load_ma_triv(bus_dma_tag_t dmat, bus_dmamap_t map,
+ struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags,
+ bus_dma_segment_t *segs, int *segp)
+{
+ vm_paddr_t paddr;
+ bus_size_t len;
+ int error, i;
error = 0;
- tlen = bio->bio_bcount;
- ma_offs = bio->bio_ma_offset;
for (i = 0; tlen > 0; i++, tlen -= len) {
len = min(PAGE_SIZE - ma_offs, tlen);
- paddr = VM_PAGE_TO_PHYS(bio->bio_ma[i]) + ma_offs;
+ paddr = VM_PAGE_TO_PHYS(ma[i]) + ma_offs;
error = _bus_dmamap_load_phys(dmat, map, paddr, len,
- flags, NULL, nsegs);
+ flags, segs, segp);
if (error != 0)
break;
ma_offs = 0;
diff --git a/sys/mips/mips/busdma_machdep.c b/sys/mips/mips/busdma_machdep.c
index f3275e6..823ae9c 100644
--- a/sys/mips/mips/busdma_machdep.c
+++ b/sys/mips/mips/busdma_machdep.c
@@ -878,6 +878,16 @@ _bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map,
return (0);
}
+int
+_bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map,
+ struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags,
+ bus_dma_segment_t *segs, int *segp)
+{
+
+ return (bus_dmamap_load_ma_triv(dmat, map, ma, tlen, ma_offs, flags,
+ segs, segp));
+}
+
/*
* Utility function to load a linear buffer. segp contains
* the starting segment on entrance, and the ending segment on exit.
diff --git a/sys/powerpc/powerpc/busdma_machdep.c b/sys/powerpc/powerpc/busdma_machdep.c
index 144b7f9..e35ecec 100644
--- a/sys/powerpc/powerpc/busdma_machdep.c
+++ b/sys/powerpc/powerpc/busdma_machdep.c
@@ -754,6 +754,16 @@ _bus_dmamap_load_phys(bus_dma_tag_t dmat,
return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */
}
+int
+_bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map,
+ struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags,
+ bus_dma_segment_t *segs, int *segp)
+{
+
+ return (bus_dmamap_load_ma_triv(dmat, map, ma, tlen, ma_offs, flags,
+ segs, segp));
+}
+
/*
* Utility function to load a linear buffer. segp contains
* the starting segment on entrance, and the ending segment on exit.
diff --git a/sys/sparc64/include/bus_dma.h b/sys/sparc64/include/bus_dma.h
index 7395794..7d74419 100644
--- a/sys/sparc64/include/bus_dma.h
+++ b/sys/sparc64/include/bus_dma.h
@@ -146,5 +146,7 @@ struct bus_dma_tag {
((t)->dt_mt->dm_dmamem_alloc((t), (v), (f), (m)))
#define bus_dmamem_free(t, v, m) \
((t)->dt_mt->dm_dmamem_free((t), (v), (m)))
+#define _bus_dmamap_load_ma(t, m, a, tt, o, f, s, p) \
+ bus_dmamap_load_ma_triv((t), (m), (a), (tt), (o), (f), (s), (p))
#endif /* !_SPARC64_BUS_DMA_H_ */
diff --git a/sys/sys/bus_dma.h b/sys/sys/bus_dma.h
index c3ac56e..5f096f8 100644
--- a/sys/sys/bus_dma.h
+++ b/sys/sys/bus_dma.h
@@ -247,6 +247,15 @@ int bus_dmamap_load_mem(bus_dma_tag_t dmat, bus_dmamap_t map,
void *callback_arg, int flags);
/*
+ * Placeholder for use by busdma implementations which do not benefit
+ * from optimized procedure to load an array of vm_page_t. Falls back
+ * to do _bus_dmamap_load_phys() in loop.
+ */
+int bus_dmamap_load_ma_triv(bus_dma_tag_t dmat, bus_dmamap_t map,
+ struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags,
+ bus_dma_segment_t *segs, int *segp);
+
+/*
* XXX sparc64 uses the same interface, but a much different implementation.
* <machine/bus_dma.h> for the sparc64 arch contains the equivalent
* declarations.
@@ -324,6 +333,10 @@ 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);
+int _bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map,
+ struct vm_page **ma, bus_size_t tlen, int ma_offs, 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,
diff --git a/sys/x86/x86/busdma_machdep.c b/sys/x86/x86/busdma_machdep.c
index 0b59616..7223354 100644
--- a/sys/x86/x86/busdma_machdep.c
+++ b/sys/x86/x86/busdma_machdep.c
@@ -849,6 +849,16 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat,
return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */
}
+int
+_bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map,
+ struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags,
+ bus_dma_segment_t *segs, int *segp)
+{
+
+ return (bus_dmamap_load_ma_triv(dmat, map, ma, tlen, ma_offs, flags,
+ segs, segp));
+}
+
void
__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map,
struct memdesc *mem, bus_dmamap_callback_t *callback,
OpenPOWER on IntegriCloud