summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/arm/arm/busdma_machdep.c51
1 files changed, 47 insertions, 4 deletions
diff --git a/sys/arm/arm/busdma_machdep.c b/sys/arm/arm/busdma_machdep.c
index bab00ad..0ee2d9f 100644
--- a/sys/arm/arm/busdma_machdep.c
+++ b/sys/arm/arm/busdma_machdep.c
@@ -189,7 +189,8 @@ _busdma_alloc_dmamap(void)
mtx_lock(&busdma_mtx);
map = TAILQ_FIRST(&dmamap_freelist);
- TAILQ_REMOVE(&dmamap_freelist, map, freelist);
+ if (map)
+ TAILQ_REMOVE(&dmamap_freelist, map, freelist);
mtx_unlock(&busdma_mtx);
if (!map) {
map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT);
@@ -493,10 +494,14 @@ bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dma_segment_t *segs,
} else {
curaddr = (pte & L2_S_FRAME) |
(vaddr & L2_S_OFFSET);
+ pmap_uncache(ptep);
+ map->flags |= DMAMAP_UNCACHED;
+#if 0
if (pte & L2_S_CACHE_MASK) {
map->flags &=
~DMAMAP_COHERENT;
}
+#endif
}
}
} else {
@@ -769,7 +774,43 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio,
*/
void
_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
-{
+{
+ struct mbuf *m;
+ struct uio *uio;
+ int resid;
+ struct iovec *iov;
+
+ if (map->flags & DMAMAP_UNCACHED) {
+ switch(map->flags & DMAMAP_TYPE_MASK) {
+ case DMAMAP_LINEAR:
+ pmap_recache(map->buffer, len);
+ break;
+ case DMAMAP_MBUF:
+ m = map->buffer;
+ while (m) {
+ if (m->m_len > 0)
+ pmap_recache(m->m_data, len);
+ m = m->m_next;
+ }
+ break;
+ case DMAMAP_UIO:
+ uio = map->buffer;
+ iov = uio->uio_iov;
+ resid = uio->uio_resid;
+ for (int i = 0; i < uio->uio_iovcnt && resid != 0; i++) {
+ bus_size_t minlen = resid < iov[i].iov_len ? resid :
+ iov[i].iov_len;
+ if (minlen > 0) {
+ pmap_recache(iov[i].iov_base, minlen);
+ resid -= minlen;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ }
map->flags &= ~DMAMAP_TYPE_MASK;
return;
}
@@ -799,9 +840,11 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
if (!(op & (BUS_DMASYNC_PREWRITE | BUS_DMASYNC_POSTREAD)))
return;
- if (map->flags & DMAMAP_COHERENT)
+ if (map->flags & DMAMAP_COHERENT) {
+ printf("COHERENT\n");
return;
- if ((op && BUS_DMASYNC_POSTREAD) && (map->len > PAGE_SIZE)) {
+ }
+ if ((op && BUS_DMASYNC_POSTREAD) && (map->len >= 2 * PAGE_SIZE)) {
cpu_dcache_wbinv_all();
return;
}
OpenPOWER on IntegriCloud