summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2005-01-15 09:20:47 +0000
committerscottl <scottl@FreeBSD.org>2005-01-15 09:20:47 +0000
commitc1d168f9a450be99fc5b9c2de536f93f01049276 (patch)
treee22e3ce5d9a4a3aa8f706dad2502620c4b7c0391 /sys
parentf4c183f0bacf6ff6016a7255beb1692cf302b883 (diff)
downloadFreeBSD-src-c1d168f9a450be99fc5b9c2de536f93f01049276.zip
FreeBSD-src-c1d168f9a450be99fc5b9c2de536f93f01049276.tar.gz
Add the bus_dmamap_load_mbuf_sg() function to sparc64.
Diffstat (limited to 'sys')
-rw-r--r--sys/sparc64/include/bus.h4
-rw-r--r--sys/sparc64/sparc64/bus_machdep.c45
-rw-r--r--sys/sparc64/sparc64/iommu.c65
3 files changed, 99 insertions, 15 deletions
diff --git a/sys/sparc64/include/bus.h b/sys/sparc64/include/bus.h
index 4aa0a7b..1a90e24 100644
--- a/sys/sparc64/include/bus.h
+++ b/sys/sparc64/include/bus.h
@@ -988,6 +988,8 @@ struct bus_dma_methods {
bus_size_t, bus_dmamap_callback_t *, void *, int);
int (*dm_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t,
struct mbuf *, bus_dmamap_callback2_t *, void *, int);
+ int (*dm_dmamap_load_mbuf_sg)(bus_dma_tag_t, bus_dmamap_t,
+ struct mbuf *, bus_dma_segment_t *segs, int *nsegs, int);
int (*dm_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t, struct uio *,
bus_dmamap_callback2_t *, void *, int);
void (*dm_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t);
@@ -1039,6 +1041,8 @@ int bus_dma_tag_destroy(bus_dma_tag_t);
((t)->dt_mt->dm_dmamap_load((t), (m), (p), (s), (cb), (cba), (f)))
#define bus_dmamap_load_mbuf(t, m, mb, cb, cba, f) \
((t)->dt_mt->dm_dmamap_load_mbuf((t), (m), (mb), (cb), (cba), (f)))
+#define bus_dmamap_load_mbuf_sg(t, m, mb, segs, nsegs, f) \
+ ((t)->dt_mt->dm_dmamap_load_mbuf_sg((t), (m), (mb), (segs), (nsegs), (f)))
#define bus_dmamap_load_uio(t, m, ui, cb, cba, f) \
((t)->dt_mt->dm_dmamap_load_uio((t), (m), (ui), (cb), (cba), (f)))
#define bus_dmamap_unload(t, p) \
diff --git a/sys/sparc64/sparc64/bus_machdep.c b/sys/sparc64/sparc64/bus_machdep.c
index e93ba9d..7a9bdf3 100644
--- a/sys/sparc64/sparc64/bus_machdep.c
+++ b/sys/sparc64/sparc64/bus_machdep.c
@@ -351,17 +351,15 @@ nexus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)
*/
static int
_nexus_dmamap_load_buffer(bus_dma_tag_t dmat, void *buf, bus_size_t buflen,
- struct thread *td, int flags, bus_addr_t *lastaddrp, int *segp, int first)
+ struct thread *td, int flags, bus_addr_t *lastaddrp,
+ bus_dma_segment_t *segs, int *segp, int first)
{
- bus_dma_segment_t *segs;
bus_size_t sgsize;
bus_addr_t curaddr, lastaddr, baddr, bmask;
vm_offset_t vaddr = (vm_offset_t)buf;
int seg;
pmap_t pmap;
- segs = dmat->dt_segments;
-
if (td != NULL)
pmap = vmspace_pmap(td->td_proc->p_vmspace);
else
@@ -450,7 +448,7 @@ nexus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
int error, nsegs;
error = _nexus_dmamap_load_buffer(dmat, buf, buflen, NULL, flags,
- &lastaddr, &nsegs, 1);
+ &lastaddr, dmat->dt_segments, &nsegs, 1);
if (error == 0) {
(*callback)(callback_arg, dmat->dt_segments, nsegs + 1, 0);
@@ -483,7 +481,7 @@ nexus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0,
if (m->m_len > 0) {
error = _nexus_dmamap_load_buffer(dmat,
m->m_data, m->m_len,NULL, flags, &lastaddr,
- &nsegs, first);
+ dmat->dt_segments, &nsegs, first);
first = 0;
}
}
@@ -502,6 +500,37 @@ nexus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0,
return (error);
}
+static int
+nexus_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);
+
+ *nsegs = 0;
+ error = 0;
+ if (m0->m_pkthdr.len <= dmat->dt_maxsize) {
+ int first = 1;
+ bus_addr_t lastaddr = 0;
+ struct mbuf *m;
+
+ for (m = m0; m != NULL && error == 0; m = m->m_next) {
+ if (m->m_len > 0) {
+ error = _nexus_dmamap_load_buffer(dmat,
+ m->m_data, m->m_len,NULL, flags, &lastaddr,
+ segs, nsegs, first);
+ first = 0;
+ }
+ }
+ } else {
+ error = EINVAL;
+ }
+
+ ++*nsegs;
+ return (error);
+}
+
/*
* Like nexus_dmamap_load(), but for uios.
*/
@@ -538,7 +567,8 @@ nexus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio,
if (minlen > 0) {
error = _nexus_dmamap_load_buffer(dmat, addr, minlen,
- td, flags, &lastaddr, &nsegs, first);
+ td, flags, &lastaddr, dmat->dt_segments, &nsegs,
+ first);
first = 0;
resid -= minlen;
@@ -654,6 +684,7 @@ struct bus_dma_methods nexus_dma_methods = {
nexus_dmamap_destroy,
nexus_dmamap_load,
nexus_dmamap_load_mbuf,
+ nexus_dmamap_load_mbuf_sg,
nexus_dmamap_load_uio,
nexus_dmamap_unload,
nexus_dmamap_sync,
diff --git a/sys/sparc64/sparc64/iommu.c b/sys/sparc64/sparc64/iommu.c
index 42a98c7..b7522cc 100644
--- a/sys/sparc64/sparc64/iommu.c
+++ b/sys/sparc64/sparc64/iommu.c
@@ -891,7 +891,7 @@ iommu_dvmamap_destroy(bus_dma_tag_t dt, bus_dmamap_t map)
static int
iommu_dvmamap_load_buffer(bus_dma_tag_t dt, struct iommu_state *is,
bus_dmamap_t map, void *buf, bus_size_t buflen, struct thread *td,
- int flags, int *segp, int align)
+ int flags, bus_dma_segment_t *segs, int *segp, int align)
{
bus_addr_t amask, dvmaddr;
bus_size_t sgsize, esize;
@@ -948,8 +948,8 @@ iommu_dvmamap_load_buffer(bus_dma_tag_t dt, struct iommu_state *is,
*/
if (!firstpg) {
esize = ulmin(sgsize,
- dt->dt_maxsegsz - dt->dt_segments[sgcnt].ds_len);
- dt->dt_segments[sgcnt].ds_len += esize;
+ dt->dt_maxsegsz - segs[sgcnt].ds_len);
+ segs[sgcnt].ds_len += esize;
sgsize -= esize;
dvmaddr += esize;
}
@@ -965,8 +965,8 @@ iommu_dvmamap_load_buffer(bus_dma_tag_t dt, struct iommu_state *is,
* that such tags have maxsegsize >= maxsize.
*/
esize = ulmin(sgsize, dt->dt_maxsegsz);
- dt->dt_segments[sgcnt].ds_addr = dvmaddr;
- dt->dt_segments[sgcnt].ds_len = esize;
+ segs[sgcnt].ds_addr = dvmaddr;
+ segs[sgcnt].ds_len = esize;
sgsize -= esize;
dvmaddr += esize;
}
@@ -1002,7 +1002,7 @@ iommu_dvmamap_load(bus_dma_tag_t dt, bus_dmamap_t map, void *buf,
IS_UNLOCK(is);
error = iommu_dvmamap_load_buffer(dt, is, map, buf, buflen, NULL,
- flags, &seg, 1);
+ flags, dt->dt_segments, &seg, 1);
IS_LOCK(is);
iommu_map_insq(is, map);
@@ -1045,7 +1045,8 @@ iommu_dvmamap_load_mbuf(bus_dma_tag_t dt, bus_dmamap_t map, struct mbuf *m0,
if (m->m_len == 0)
continue;
error = iommu_dvmamap_load_buffer(dt, is, map,
- m->m_data, m->m_len, NULL, flags, &nsegs, first);
+ m->m_data, m->m_len, NULL, flags, dt->dt_segments,
+ &nsegs, first);
first = 0;
}
} else
@@ -1067,6 +1068,52 @@ iommu_dvmamap_load_mbuf(bus_dma_tag_t dt, bus_dmamap_t map, struct mbuf *m0,
}
static int
+iommu_dvamamp_load_mbuf_sg(bus_dma_tag_t dt, bus_dmamap_t map, struct mbuf *m0,
+ bus_dma_segment_t *segs, int *nsegs, int flags)
+{
+ struct iommu_state *is = dt->dt_cookie;
+ struct mbuf *m;
+ int error = 0, first = 1;
+
+ M_ASSERTPKTHDR(m0);
+
+ *nsegs = -1;
+ if ((map->dm_flags & DMF_LOADED) != 0) {
+#ifdef DIAGNOSTIC
+ printf("iommu_dvmamap_load_mbuf: map still in use\n");
+#endif
+ bus_dmamap_unload(dt, map);
+ }
+
+ IS_LOCK(is);
+ iommu_map_remq(is, map);
+ IS_UNLOCK(is);
+
+ if (m0->m_pkthdr.len <= dt->dt_maxsize) {
+ for (m = m0; m != NULL && error == 0; m = m->m_next) {
+ if (m->m_len == 0)
+ continue;
+ error = iommu_dvmamap_load_buffer(dt, is, map,
+ m->m_data, m->m_len, NULL, flags, segs,
+ nsegs, first);
+ first = 0;
+ }
+ } else
+ error = EINVAL;
+
+ IS_LOCK(is);
+ iommu_map_insq(is, map);
+ if (error != 0) {
+ iommu_dvmamap_vunload(is, map);
+ } else {
+ map->dm_flags |= DMF_LOADED;
+ ++*nsegs;
+ }
+ IS_UNLOCK(is);
+ return (error);
+}
+
+static int
iommu_dvmamap_load_uio(bus_dma_tag_t dt, bus_dmamap_t map, struct uio *uio,
bus_dmamap_callback2_t *cb, void *cba, int flags)
{
@@ -1106,7 +1153,8 @@ iommu_dvmamap_load_uio(bus_dma_tag_t dt, bus_dmamap_t map, struct uio *uio,
continue;
error = iommu_dvmamap_load_buffer(dt, is, map,
- iov[i].iov_base, minlen, td, flags, &nsegs, first);
+ iov[i].iov_base, minlen, td, flags, dt->dt_segments,
+ &nsegs, first);
first = 0;
resid -= minlen;
@@ -1219,6 +1267,7 @@ struct bus_dma_methods iommu_dma_methods = {
iommu_dvmamap_destroy,
iommu_dvmamap_load,
iommu_dvmamap_load_mbuf,
+ iommu_dvamamp_load_mbuf_sg,
iommu_dvmamap_load_uio,
iommu_dvmamap_unload,
iommu_dvmamap_sync,
OpenPOWER on IntegriCloud