summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2022-12-29 11:35:02 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2022-12-29 11:35:02 +0000
commitee90c601aaa241e50187c2be95213e4f4ec0a40e (patch)
tree330057ad28bae36ecc30dd2bc3ec94c5ad1666bf
parent5a0d6275947e329e587c2a43e5aa6fc00006eb6b (diff)
Avoid doing cache flush/invalidate operations for DMA memory allocated with
the BUS_DMA_COHERENT flag. ok miod@
-rw-r--r--sys/arch/riscv64/include/bus.h3
-rw-r--r--sys/arch/riscv64/riscv64/bus_dma.c15
2 files changed, 14 insertions, 4 deletions
diff --git a/sys/arch/riscv64/include/bus.h b/sys/arch/riscv64/include/bus.h
index 2e7c71d5716..14a324c04d3 100644
--- a/sys/arch/riscv64/include/bus.h
+++ b/sys/arch/riscv64/include/bus.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bus.h,v 1.4 2021/05/12 01:20:52 jsg Exp $ */
+/* $OpenBSD: bus.h,v 1.5 2022/12/29 11:35:01 kettenis Exp $ */
/*
* Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved.
@@ -361,6 +361,7 @@ struct machine_bus_dma_segment {
paddr_t _ds_paddr; /* CPU address */
vaddr_t _ds_vaddr; /* CPU address */
+ int _ds_coherent; /* Coherently mapped */
};
typedef struct machine_bus_dma_segment bus_dma_segment_t;
diff --git a/sys/arch/riscv64/riscv64/bus_dma.c b/sys/arch/riscv64/riscv64/bus_dma.c
index 7659eb5be28..3cd6db63ec6 100644
--- a/sys/arch/riscv64/riscv64/bus_dma.c
+++ b/sys/arch/riscv64/riscv64/bus_dma.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bus_dma.c,v 1.6 2022/12/29 11:30:58 kettenis Exp $ */
+/* $OpenBSD: bus_dma.c,v 1.7 2022/12/29 11:35:01 kettenis Exp $ */
/*
* Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -101,7 +101,6 @@ _dmamap_create(bus_dma_tag_t t, bus_size_t size, int nsegments,
map->_dm_segcnt = nsegments;
map->_dm_maxsegsz = maxsegsz;
map->_dm_boundary = boundary;
- map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT);
*dmamp = map;
return (0);
@@ -275,11 +274,20 @@ _dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t map, bus_dma_segment_t *segs,
mapsize = size;
bmask = ~(map->_dm_boundary - 1);
+ /*
+ * Assume the mapping is coherent until we run into a segment
+ * that isn't.
+ */
+ map->_dm_flags = BUS_DMA_COHERENT;
+
for (i = 0; i < nsegs && size > 0; i++) {
paddr = segs[i].ds_addr;
vaddr = segs[i]._ds_vaddr;
plen = MIN(segs[i].ds_len, size);
+ if (!segs[i]._ds_coherent)
+ map->_dm_flags &= ~BUS_DMA_COHERENT;
+
while (plen > 0) {
/*
* Compute the segment size, and adjust counts.
@@ -400,7 +408,7 @@ _dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t addr,
* with is coherent, make sure the write buffer is synced
* and return.
*/
- if (t->_flags & BUS_DMA_COHERENT) {
+ if (t->_flags & BUS_DMA_COHERENT || map->_dm_flags & BUS_DMA_COHERENT) {
__asm volatile ("fence iorw,iorw" ::: "memory");
return;
}
@@ -514,6 +522,7 @@ _dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, size_t size,
cache = PMAP_CACHE_CI;
for (curseg = 0; curseg < nsegs; curseg++) {
segs[curseg]._ds_vaddr = va;
+ segs[curseg]._ds_coherent = !!(flags & BUS_DMA_COHERENT);
for (addr = segs[curseg].ds_addr;
addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
addr += NBPG, va += NBPG, size -= NBPG) {