Module Name: src Committed By: skrll Date: Fri Jun 14 09:09:12 UTC 2019
Modified Files: src/sys/arch/arm/arm32: bus_dma.c Log Message: Simplify the _ARM32_NEED_BUS_DMA_BOUNCE #ifdefs and rely on compiler optimisation of the bouncing = false case. Drain the write buf (aka DSB) in more cases Catch all CPUs that support speculation. (thunderx isn't CPU_CORTEX) To generate a diff of this commit: cvs rdiff -u -r1.114 -r1.115 src/sys/arch/arm/arm32/bus_dma.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/arm32/bus_dma.c diff -u src/sys/arch/arm/arm32/bus_dma.c:1.114 src/sys/arch/arm/arm32/bus_dma.c:1.115 --- src/sys/arch/arm/arm32/bus_dma.c:1.114 Sat Jun 8 11:57:27 2019 +++ src/sys/arch/arm/arm32/bus_dma.c Fri Jun 14 09:09:12 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: bus_dma.c,v 1.114 2019/06/08 11:57:27 skrll Exp $ */ +/* $NetBSD: bus_dma.c,v 1.115 2019/06/14 09:09:12 skrll Exp $ */ /*- * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. @@ -36,7 +36,7 @@ #include "opt_cputypes.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.114 2019/06/08 11:57:27 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.115 2019/06/14 09:09:12 skrll Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -254,12 +254,13 @@ _bus_dmamap_load_paddr(bus_dma_tag_t t, return 0; } +static int _bus_dma_uiomove(void *buf, struct uio *uio, size_t n, + int direction); + #ifdef _ARM32_NEED_BUS_DMA_BOUNCE static int _bus_dma_alloc_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map, bus_size_t size, int flags); static void _bus_dma_free_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map); -static int _bus_dma_uiomove(void *buf, struct uio *uio, size_t n, - int direction); static int _bus_dma_load_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map, void *buf, @@ -796,7 +797,7 @@ _bus_dmamap_sync_segment(vaddr_t va, pad bool readonly_p) { -#if defined(ARM_MMU_EXTENDED) || defined(CPU_CORTEX) +#if defined(ARM_MMU_EXTENDED) /* * No optimisations are available for readonly mbufs on armv6+, so * assume it's not readonly from here on. @@ -863,7 +864,8 @@ _bus_dmamap_sync_segment(vaddr_t va, pad cpu_sdcache_wb_range(va, pa, len); break; -#ifdef CPU_CORTEX +#if defined(CPU_CORTEX) || defined(CPU_ARMV8) + /* * Cortex CPUs can do speculative loads so we need to clean the cache * after a DMA read to deal with any speculatively loaded cache lines. @@ -1074,22 +1076,23 @@ _bus_dmamap_sync(bus_dma_tag_t t, bus_dm #endif const int pre_ops = ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); -#ifdef CPU_CORTEX +#if defined(CPU_CORTEX) || defined(CPU_ARMV8) const int post_ops = ops & (BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); #else const int post_ops = 0; #endif - if (!bouncing) { - if (pre_ops == 0 && post_ops == BUS_DMASYNC_POSTWRITE) { - STAT_INCR(sync_postwrite); - return; - } else if (pre_ops == 0 && post_ops == 0) { - return; - } + if (pre_ops == 0 && post_ops == 0) + return; + + if (post_ops == BUS_DMASYNC_POSTWRITE) { + KASSERT(pre_ops == 0); + STAT_INCR(sync_postwrite); + return; } + KASSERTMSG(bouncing || pre_ops != 0 || (post_ops & BUS_DMASYNC_POSTREAD), "pre_ops %#x post_ops %#x", pre_ops, post_ops); -#ifdef _ARM32_NEED_BUS_DMA_BOUNCE + if (bouncing && (ops & BUS_DMASYNC_PREWRITE)) { struct arm32_bus_dma_cookie * const cookie = map->_dm_cookie; STAT_INCR(write_bounces); @@ -1123,23 +1126,28 @@ _bus_dmamap_sync(bus_dma_tag_t t, bus_dm #endif /* DIAGNOSTIC */ } } -#endif /* _ARM32_NEED_BUS_DMA_BOUNCE */ - /* Skip cache frobbing if mapping was COHERENT. */ - if (!bouncing && (map->_dm_flags & _BUS_DMAMAP_COHERENT)) { - /* Drain the write buffer. */ - if (pre_ops & BUS_DMASYNC_PREWRITE) + /* Skip cache frobbing if mapping was COHERENT */ + if ((map->_dm_flags & _BUS_DMAMAP_COHERENT)) { + /* + * Drain the write buffer of DMA operators. + * 1) when cpu->device (prewrite) + * 2) when device->cpu (postread) + */ + if ((pre_ops & BUS_DMASYNC_PREWRITE) || (post_ops & BUS_DMASYNC_POSTREAD)) cpu_drain_writebuf(); - return; - } -#ifdef _ARM32_NEED_BUS_DMA_BOUNCE - if (bouncing && ((map->_dm_flags & _BUS_DMAMAP_COHERENT) || pre_ops == 0)) { - goto bounce_it; + /* + * Only thing left to do for COHERENT mapping is copy from bounce + * in the POSTREAD case. + */ + if (bouncing && (post_ops & BUS_DMASYNC_POSTREAD)) + goto bounce_it; + + return; } -#endif /* _ARM32_NEED_BUS_DMA_BOUNCE */ -#ifndef ARM_MMU_EXTENDED +#if !defined( ARM_MMU_EXTENDED) /* * If the mapping belongs to a non-kernel vmspace, and the * vmspace has not been active since the last time a full @@ -1151,11 +1159,9 @@ _bus_dmamap_sync(bus_dma_tag_t t, bus_dm #endif int buftype = map->_dm_buftype; -#ifdef _ARM32_NEED_BUS_DMA_BOUNCE if (bouncing) { buftype = _BUS_DMA_BUFTYPE_LINEAR; } -#endif switch (buftype) { case _BUS_DMA_BUFTYPE_LINEAR: @@ -1186,14 +1192,14 @@ _bus_dmamap_sync(bus_dma_tag_t t, bus_dm /* Drain the write buffer. */ cpu_drain_writebuf(); -#ifdef _ARM32_NEED_BUS_DMA_BOUNCE - bounce_it: if (!bouncing || (ops & BUS_DMASYNC_POSTREAD) == 0) return; + bounce_it: + STAT_INCR(read_bounces); + struct arm32_bus_dma_cookie * const cookie = map->_dm_cookie; char * const dataptr = (char *)cookie->id_bouncebuf + offset; - STAT_INCR(read_bounces); /* * Copy the bounce buffer to the caller's buffer. */ @@ -1224,7 +1230,6 @@ _bus_dmamap_sync(bus_dma_tag_t t, bus_dm break; #endif } -#endif /* _ARM32_NEED_BUS_DMA_BOUNCE */ } /* @@ -1749,6 +1754,7 @@ _bus_dma_free_bouncebuf(bus_dma_tag_t t, cookie->id_nbouncesegs = 0; cookie->id_flags &= ~_BUS_DMA_HAS_BOUNCE; } +#endif /* _ARM32_NEED_BUS_DMA_BOUNCE */ /* * This function does the same as uiomove, but takes an explicit @@ -1792,7 +1798,6 @@ _bus_dma_uiomove(void *buf, struct uio * } return 0; } -#endif /* _ARM32_NEED_BUS_DMA_BOUNCE */ int _bus_dmatag_subregion(bus_dma_tag_t tag, bus_addr_t min_addr,