Avoid doing cache flush/invalidate operations for DMA memory allocated with
authorkettenis <kettenis@openbsd.org>
Thu, 29 Dec 2022 11:35:01 +0000 (11:35 +0000)
committerkettenis <kettenis@openbsd.org>
Thu, 29 Dec 2022 11:35:01 +0000 (11:35 +0000)
the BUS_DMA_COHERENT flag.

ok miod@

sys/arch/riscv64/include/bus.h
sys/arch/riscv64/riscv64/bus_dma.c

index 2e7c71d..14a324c 100644 (file)
@@ -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;
 
index 7659eb5..3cd6db6 100644 (file)
@@ -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) {