Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-1-6]: src/sys/arch/arm/arm32 Pull up revisions 1.13-1.14 (request...
details: https://anonhg.NetBSD.org/src/rev/26fa94136ed5
branches: netbsd-1-6
changeset: 529657:26fa94136ed5
user: he <he%NetBSD.org@localhost>
date: Sat Dec 07 19:23:21 2002 +0000
description:
Pull up revisions 1.13-1.14 (requested by thorpej in ticket #568):
Remove warning from bus_dmamap_destroy().
Change the way DMA map syncs are done. Instead of remembering
the virtual address for each DMA segment, just cache a
pointer to the original buffer/buftype used to load the
DMA map, and use that. Shrinks bus_dma_segment_t from 12
to 8 bytes, and the cache flushing is also more efficient.
diffstat:
sys/arch/arm/arm32/bus_dma.c | 218 ++++++++++++++++++++++++++++++++----------
1 files changed, 167 insertions(+), 51 deletions(-)
diffs (truncated from 302 to 300 lines):
diff -r 298ae5574cba -r 26fa94136ed5 sys/arch/arm/arm32/bus_dma.c
--- a/sys/arch/arm/arm32/bus_dma.c Sat Dec 07 19:15:57 2002 +0000
+++ b/sys/arch/arm/arm32/bus_dma.c Sat Dec 07 19:23:21 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: bus_dma.c,v 1.11 2002/04/10 19:35:22 thorpej Exp $ */
+/* $NetBSD: bus_dma.c,v 1.11.4.1 2002/12/07 19:23:21 he Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@@ -106,6 +106,8 @@
map->_dm_maxsegsz = maxsegsz;
map->_dm_boundary = boundary;
map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT);
+ map->_dm_origbuf = NULL;
+ map->_dm_buftype = ARM32_BUFTYPE_INVALID;
map->_dm_proc = NULL;
map->dm_mapsize = 0; /* no valid mappings */
map->dm_nsegs = 0;
@@ -128,10 +130,16 @@
#ifdef DEBUG_DMA
printf("dmamap_destroy: t=%p map=%p\n", t, map);
#endif /* DEBUG_DMA */
-#ifdef DIAGNOSTIC
- if (map->dm_nsegs > 0)
- printf("bus_dmamap_destroy() called for map with valid mappings\n");
-#endif /* DIAGNOSTIC */
+
+ /*
+ * Explicit unload.
+ */
+ map->dm_mapsize = 0;
+ map->dm_nsegs = 0;
+ map->_dm_origbuf = NULL;
+ map->_dm_buftype = ARM32_BUFTYPE_INVALID;
+ map->_dm_proc = NULL;
+
free(map, M_DEVBUF);
}
@@ -166,6 +174,8 @@
if (error == 0) {
map->dm_mapsize = buflen;
map->dm_nsegs = seg + 1;
+ map->_dm_origbuf = buf;
+ map->_dm_buftype = ARM32_BUFTYPE_LINEAR;
map->_dm_proc = p;
}
#ifdef DEBUG_DMA
@@ -215,6 +225,8 @@
if (error == 0) {
map->dm_mapsize = m0->m_pkthdr.len;
map->dm_nsegs = seg + 1;
+ map->_dm_origbuf = m0;
+ map->_dm_buftype = ARM32_BUFTYPE_MBUF;
map->_dm_proc = NULL; /* always kernel */
}
#ifdef DEBUG_DMA
@@ -274,6 +286,8 @@
if (error == 0) {
map->dm_mapsize = uio->uio_resid;
map->dm_nsegs = seg + 1;
+ map->_dm_origbuf = uio;
+ map->_dm_buftype = ARM32_BUFTYPE_UIO;
map->_dm_proc = p;
}
return (error);
@@ -309,9 +323,137 @@
*/
map->dm_mapsize = 0;
map->dm_nsegs = 0;
+ map->_dm_origbuf = NULL;
+ map->_dm_buftype = ARM32_BUFTYPE_INVALID;
map->_dm_proc = NULL;
}
+static void
+_bus_dmamap_sync_linear(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
+ bus_size_t len, int ops)
+{
+ vaddr_t addr = (vaddr_t) map->_dm_origbuf;
+
+ addr += offset;
+ len -= offset;
+
+ switch (ops) {
+ case BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE:
+ cpu_dcache_wbinv_range(addr, len);
+ break;
+
+ case BUS_DMASYNC_PREREAD:
+#if 1
+ cpu_dcache_wbinv_range(addr, len);
+#else
+ cpu_dcache_inv_range(addr, len);
+#endif
+ break;
+
+ case BUS_DMASYNC_PREWRITE:
+ cpu_dcache_wb_range(addr, len);
+ break;
+ }
+}
+
+static void
+_bus_dmamap_sync_mbuf(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
+ bus_size_t len, int ops)
+{
+ struct mbuf *m, *m0 = map->_dm_origbuf;
+ bus_size_t minlen, moff;
+ vaddr_t maddr;
+
+ for (moff = offset, m = m0; m != NULL && len != 0;
+ m = m->m_next) {
+ /* Find the beginning mbuf. */
+ if (moff >= m->m_len) {
+ moff -= m->m_len;
+ continue;
+ }
+
+ /*
+ * Now at the first mbuf to sync; nail each one until
+ * we have exhausted the length.
+ */
+ minlen = m->m_len - moff;
+ if (len < minlen)
+ minlen = len;
+
+ maddr = mtod(m, vaddr_t);
+ maddr += moff;
+
+ switch (ops) {
+ case BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE:
+ cpu_dcache_wbinv_range(maddr, minlen);
+ break;
+
+ case BUS_DMASYNC_PREREAD:
+#if 1
+ cpu_dcache_wbinv_range(maddr, minlen);
+#else
+ cpu_dcache_inv_range(maddr, minlen);
+#endif
+ break;
+
+ case BUS_DMASYNC_PREWRITE:
+ cpu_dcache_wb_range(maddr, minlen);
+ break;
+ }
+ moff = 0;
+ len -= minlen;
+ }
+}
+
+static void
+_bus_dmamap_sync_uio(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
+ bus_size_t len, int ops)
+{
+ struct uio *uio = map->_dm_origbuf;
+ struct iovec *iov;
+ bus_size_t minlen, ioff;
+ vaddr_t addr;
+
+ for (iov = uio->uio_iov, ioff = offset; len != 0; iov++) {
+ /* Find the beginning iovec. */
+ if (ioff >= iov->iov_len) {
+ ioff -= iov->iov_len;
+ continue;
+ }
+
+ /*
+ * Now at the first iovec to sync; nail each one until
+ * we have exhausted the length.
+ */
+ minlen = iov->iov_len - ioff;
+ if (len < minlen)
+ minlen = len;
+
+ addr = (vaddr_t) iov->iov_base;
+ addr += ioff;
+
+ switch (ops) {
+ case BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE:
+ cpu_dcache_wbinv_range(addr, minlen);
+ break;
+
+ case BUS_DMASYNC_PREREAD:
+#if 1
+ cpu_dcache_wbinv_range(addr, minlen);
+#else
+ cpu_dcache_inv_range(addr, minlen);
+#endif
+ break;
+
+ case BUS_DMASYNC_PREWRITE:
+ cpu_dcache_wb_range(addr, minlen);
+ break;
+ }
+ ioff = 0;
+ len -= minlen;
+ }
+}
+
/*
* Common function for DMA map synchronization. May be called
* by bus-specific DMA map synchronization functions.
@@ -328,9 +470,6 @@
_bus_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
bus_size_t len, int ops)
{
- bus_size_t minlen;
- bus_addr_t addr;
- int i;
#ifdef DEBUG_DMA
printf("dmamap_sync: t=%p map=%p offset=%lx len=%lx ops=%x\n",
@@ -387,51 +526,30 @@
if (__predict_false(map->_dm_proc != NULL && map->_dm_proc != curproc))
return;
- for (i = 0; i < map->dm_nsegs && len != 0; i++) {
- /* Find beginning segment. */
- if (offset >= map->dm_segs[i].ds_len) {
- offset -= map->dm_segs[i].ds_len;
- continue;
- }
+ switch (map->_dm_buftype) {
+ case ARM32_BUFTYPE_LINEAR:
+ _bus_dmamap_sync_linear(t, map, offset, len, ops);
+ break;
- /*
- * Now at the first segment to sync; nail
- * each segment until we have exhausted the
- * length.
- */
- minlen = len < map->dm_segs[i].ds_len - offset ?
- len : map->dm_segs[i].ds_len - offset;
-
- addr = map->dm_segs[i]._ds_vaddr;
-
-#ifdef DEBUG_DMA
- printf("bus_dmamap_sync: flushing segment %d "
- "(0x%lx..0x%lx) ...", i, addr + offset,
- addr + offset + minlen - 1);
-#endif
+ case ARM32_BUFTYPE_MBUF:
+ _bus_dmamap_sync_mbuf(t, map, offset, len, ops);
+ break;
- switch (ops) {
- case BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE:
- cpu_dcache_wbinv_range(addr + offset, minlen);
- break;
+ case ARM32_BUFTYPE_UIO:
+ _bus_dmamap_sync_uio(t, map, offset, len, ops);
+ break;
+
+ case ARM32_BUFTYPE_RAW:
+ panic("_bus_dmamap_sync: ARM32_BUFTYPE_RAW");
+ break;
- case BUS_DMASYNC_PREREAD:
-#if 1
- cpu_dcache_wbinv_range(addr + offset, minlen);
-#else
- cpu_dcache_inv_range(addr + offset, minlen);
-#endif
- break;
+ case ARM32_BUFTYPE_INVALID:
+ panic("_bus_dmamap_sync: ARM32_BUFTYPE_INVALID");
+ break;
- case BUS_DMASYNC_PREWRITE:
- cpu_dcache_wb_range(addr + offset, minlen);
- break;
- }
-#ifdef DEBUG_DMA
- printf("\n");
-#endif
- offset = 0;
- len -= minlen;
+ default:
+ printf("unknown buffer type %d\n", map->_dm_buftype);
+ panic("_bus_dmamap_sync");
}
/* Drain the write buffer. */
@@ -686,7 +804,6 @@
if (first) {
map->dm_segs[seg].ds_addr = curaddr;
map->dm_segs[seg].ds_len = sgsize;
- map->dm_segs[seg]._ds_vaddr = vaddr;
first = 0;
} else {
if (curaddr == lastaddr &&
@@ -701,7 +818,6 @@
break;
map->dm_segs[seg].ds_addr = curaddr;
map->dm_segs[seg].ds_len = sgsize;
- map->dm_segs[seg]._ds_vaddr = vaddr;
}
Home |
Main Index |
Thread Index |
Old Index