Skip to content

Commit

Permalink
riscv: mm: dma-noncoherent: nonstandard cache operations support
Browse files Browse the repository at this point in the history
Introduce support for nonstandard noncoherent systems in the RISC-V
architecture. It enables function pointer support to handle cache
management in such systems.

This patch adds a new configuration option called
"RISCV_NONSTANDARD_CACHE_OPS." This option is a boolean flag that
depends on "RISCV_DMA_NONCOHERENT" and enables the function pointer
support for cache management in nonstandard noncoherent systems.

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Tested-by: Conor Dooley <conor.dooley@microchip.com> # tyre-kicking on a d1
Reviewed-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
Tested-by: Emil Renner Berthing <emil.renner.berthing@canonical.com> #
Link: https://lore.kernel.org/r/20230818135723.80612-4-prabhakar.mahadev-lad.rj@bp.renesas.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
  • Loading branch information
prabhakarlad authored and palmer-dabbelt committed Sep 1, 2023
1 parent e021ae7 commit b79f300
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 0 deletions.
7 changes: 7 additions & 0 deletions arch/riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,13 @@ config RISCV_DMA_NONCOHERENT
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
select DMA_DIRECT_REMAP

config RISCV_NONSTANDARD_CACHE_OPS
bool
depends on RISCV_DMA_NONCOHERENT
help
This enables function pointer support for non-standard noncoherent
systems to handle cache management.

config AS_HAS_INSN
def_bool $(as-instr,.insn r 51$(comma) 0$(comma) 0$(comma) t0$(comma) t0$(comma) zero)

Expand Down
28 changes: 28 additions & 0 deletions arch/riscv/include/asm/dma-noncoherent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2023 Renesas Electronics Corp.
*/

#ifndef __ASM_DMA_NONCOHERENT_H
#define __ASM_DMA_NONCOHERENT_H

#include <linux/dma-direct.h>

/*
* struct riscv_nonstd_cache_ops - Structure for non-standard CMO function pointers
*
* @wback: Function pointer for cache writeback
* @inv: Function pointer for invalidating cache
* @wback_inv: Function pointer for flushing the cache (writeback + invalidating)
*/
struct riscv_nonstd_cache_ops {
void (*wback)(phys_addr_t paddr, size_t size);
void (*inv)(phys_addr_t paddr, size_t size);
void (*wback_inv)(phys_addr_t paddr, size_t size);
};

extern struct riscv_nonstd_cache_ops noncoherent_cache_ops;

void riscv_noncoherent_register_cache_ops(const struct riscv_nonstd_cache_ops *ops);

#endif /* __ASM_DMA_NONCOHERENT_H */
43 changes: 43 additions & 0 deletions arch/riscv/mm/dma-noncoherent.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,54 @@
#include <linux/dma-map-ops.h>
#include <linux/mm.h>
#include <asm/cacheflush.h>
#include <asm/dma-noncoherent.h>

static bool noncoherent_supported __ro_after_init;

struct riscv_nonstd_cache_ops noncoherent_cache_ops __ro_after_init = {
.wback = NULL,
.inv = NULL,
.wback_inv = NULL,
};

static inline void arch_dma_cache_wback(phys_addr_t paddr, size_t size)
{
void *vaddr = phys_to_virt(paddr);

#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
if (unlikely(noncoherent_cache_ops.wback)) {
noncoherent_cache_ops.wback(paddr, size);
return;
}
#endif
ALT_CMO_OP(clean, vaddr, size, riscv_cbom_block_size);
}

static inline void arch_dma_cache_inv(phys_addr_t paddr, size_t size)
{
void *vaddr = phys_to_virt(paddr);

#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
if (unlikely(noncoherent_cache_ops.inv)) {
noncoherent_cache_ops.inv(paddr, size);
return;
}
#endif

ALT_CMO_OP(inval, vaddr, size, riscv_cbom_block_size);
}

static inline void arch_dma_cache_wback_inv(phys_addr_t paddr, size_t size)
{
void *vaddr = phys_to_virt(paddr);

#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
if (unlikely(noncoherent_cache_ops.wback_inv)) {
noncoherent_cache_ops.wback_inv(paddr, size);
return;
}
#endif

ALT_CMO_OP(flush, vaddr, size, riscv_cbom_block_size);
}

Expand Down Expand Up @@ -95,6 +122,13 @@ void arch_dma_prep_coherent(struct page *page, size_t size)
{
void *flush_addr = page_address(page);

#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
if (unlikely(noncoherent_cache_ops.wback_inv)) {
noncoherent_cache_ops.wback_inv(page_to_phys(page), size);
return;
}
#endif

ALT_CMO_OP(flush, flush_addr, size, riscv_cbom_block_size);
}

Expand All @@ -120,3 +154,12 @@ void riscv_noncoherent_supported(void)
"Non-coherent DMA support enabled without a block size\n");
noncoherent_supported = true;
}

void riscv_noncoherent_register_cache_ops(const struct riscv_nonstd_cache_ops *ops)
{
if (!ops)
return;

noncoherent_cache_ops = *ops;
}
EXPORT_SYMBOL_GPL(riscv_noncoherent_register_cache_ops);
13 changes: 13 additions & 0 deletions arch/riscv/mm/pmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,28 @@
#include <linux/libnvdimm.h>

#include <asm/cacheflush.h>
#include <asm/dma-noncoherent.h>

void arch_wb_cache_pmem(void *addr, size_t size)
{
#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
if (unlikely(noncoherent_cache_ops.wback)) {
noncoherent_cache_ops.wback(virt_to_phys(addr), size);
return;
}
#endif
ALT_CMO_OP(clean, addr, size, riscv_cbom_block_size);
}
EXPORT_SYMBOL_GPL(arch_wb_cache_pmem);

void arch_invalidate_pmem(void *addr, size_t size)
{
#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
if (unlikely(noncoherent_cache_ops.inv)) {
noncoherent_cache_ops.inv(virt_to_phys(addr), size);
return;
}
#endif
ALT_CMO_OP(inval, addr, size, riscv_cbom_block_size);
}
EXPORT_SYMBOL_GPL(arch_invalidate_pmem);

0 comments on commit b79f300

Please sign in to comment.