[02/21] xtensa: dma-mapping: use normal cache invalidation rules
Commit Message
From: Arnd Bergmann <arnd@arndb.de>
xtensa is one of the platforms that has both write-back and write-through
caches, and needs to account for both in its DMA mapping operations.
It does this through a set of operations that is different from any
architecture. This is not a problem by itself, but it makes it rather
hard to figure out whether this is correct or not, and to unify this
implementation with the others.
Change the semantics to the usual ones for non-speculating CPUs:
- On DMA_TO_DEVICE, call __flush_dcache_range() to perform the
writeback even on writethrough caches, where this is a nop.
- On DMA_FROM_DEVICE, invalidate the mapping before the DMA rather
than afterwards.
- On DMA_BIDIRECTIONAL, combine the pre-writeback with the
post-invalidate into a call to __flush_invalidate_dcache_range()
that turns into a simple invalidate on writeback caches.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/xtensa/Kconfig | 1 -
arch/xtensa/include/asm/cacheflush.h | 6 +++---
arch/xtensa/kernel/pci-dma.c | 29 +++++-----------------------
3 files changed, 8 insertions(+), 28 deletions(-)
Comments
On Mon, Mar 27, 2023 at 5:14 AM Arnd Bergmann <arnd@kernel.org> wrote:
>
> From: Arnd Bergmann <arnd@arndb.de>
>
> xtensa is one of the platforms that has both write-back and write-through
> caches, and needs to account for both in its DMA mapping operations.
>
> It does this through a set of operations that is different from any
> architecture. This is not a problem by itself, but it makes it rather
> hard to figure out whether this is correct or not, and to unify this
> implementation with the others.
>
> Change the semantics to the usual ones for non-speculating CPUs:
>
> - On DMA_TO_DEVICE, call __flush_dcache_range() to perform the
> writeback even on writethrough caches, where this is a nop.
>
> - On DMA_FROM_DEVICE, invalidate the mapping before the DMA rather
> than afterwards.
>
> - On DMA_BIDIRECTIONAL, combine the pre-writeback with the
> post-invalidate into a call to __flush_invalidate_dcache_range()
> that turns into a simple invalidate on writeback caches.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> arch/xtensa/Kconfig | 1 -
> arch/xtensa/include/asm/cacheflush.h | 6 +++---
> arch/xtensa/kernel/pci-dma.c | 29 +++++-----------------------
> 3 files changed, 8 insertions(+), 28 deletions(-)
Reviewed-by: Max Filippov <jcmvbkbc@gmail.com>
@@ -8,7 +8,6 @@ config XTENSA
select ARCH_HAS_DMA_PREP_COHERENT if MMU
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_KCOV
- select ARCH_HAS_SYNC_DMA_FOR_CPU if MMU
select ARCH_HAS_SYNC_DMA_FOR_DEVICE if MMU
select ARCH_HAS_DMA_SET_UNCACHED if MMU
select ARCH_HAS_STRNCPY_FROM_USER if !KASAN
@@ -61,9 +61,9 @@ static inline void __flush_dcache_page(unsigned long va)
static inline void __flush_dcache_range(unsigned long va, unsigned long sz)
{
}
-# define __flush_invalidate_dcache_all() __invalidate_dcache_all()
-# define __flush_invalidate_dcache_page(p) __invalidate_dcache_page(p)
-# define __flush_invalidate_dcache_range(p,s) __invalidate_dcache_range(p,s)
+# define __flush_invalidate_dcache_all __invalidate_dcache_all
+# define __flush_invalidate_dcache_page __invalidate_dcache_page
+# define __flush_invalidate_dcache_range __invalidate_dcache_range
#endif
#if defined(CONFIG_MMU) && (DCACHE_WAY_SIZE > PAGE_SIZE)
@@ -43,38 +43,19 @@ static void do_cache_op(phys_addr_t paddr, size_t size,
}
}
-void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
enum dma_data_direction dir)
{
switch (dir) {
- case DMA_BIDIRECTIONAL:
+ case DMA_TO_DEVICE:
+ do_cache_op(paddr, size, __flush_dcache_range);
+ break;
case DMA_FROM_DEVICE:
do_cache_op(paddr, size, __invalidate_dcache_range);
break;
-
- case DMA_NONE:
- BUG();
- break;
-
- default:
- break;
- }
-}
-
-void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
- enum dma_data_direction dir)
-{
- switch (dir) {
case DMA_BIDIRECTIONAL:
- case DMA_TO_DEVICE:
- if (XCHAL_DCACHE_IS_WRITEBACK)
- do_cache_op(paddr, size, __flush_dcache_range);
+ do_cache_op(paddr, size, __flush_invalidate_dcache_range);
break;
-
- case DMA_NONE:
- BUG();
- break;
-
default:
break;
}