We extend struct riscv_ipi_ops so that the IPI providers (such as SBI, CLINT driver, ACLINT SWI driver etc) can specify: 1) Name of the IPI operations 2) Whether IPIs are suitable for doing remote FENCEs Signed-off-by: Anup Patel <anup.patel@xxxxxxx> --- arch/riscv/include/asm/smp.h | 15 +++++++++++++++ arch/riscv/kernel/sbi.c | 2 ++ arch/riscv/kernel/smp.c | 25 ++++++++++++++++++++++++- arch/riscv/mm/cacheflush.c | 2 +- drivers/clocksource/timer-clint.c | 2 ++ 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h index a7d2811f3536..4c4f0dde1164 100644 --- a/arch/riscv/include/asm/smp.h +++ b/arch/riscv/include/asm/smp.h @@ -16,11 +16,16 @@ struct seq_file; extern unsigned long boot_cpu_hartid; struct riscv_ipi_ops { + const char *name; + bool use_for_rfence; void (*ipi_inject)(const struct cpumask *target); void (*ipi_clear)(void); }; #ifdef CONFIG_SMP + +#include <linux/jump_label.h> + /* * Mapping between linux logical cpu index and hartid. */ @@ -45,6 +50,11 @@ void arch_send_call_function_single_ipi(int cpu); int riscv_hartid_to_cpuid(int hartid); void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out); +/* Check if we can use IPIs for remote FENCE */ +extern struct static_key_false riscv_ipi_for_rfence; +#define riscv_use_ipi_for_rfence() \ + static_branch_unlikely(&riscv_ipi_for_rfence) + /* Set custom IPI operations */ void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops); @@ -92,6 +102,11 @@ static inline void riscv_cpuid_to_hartid_mask(const struct cpumask *in, cpumask_set_cpu(boot_cpu_hartid, out); } +static inline bool riscv_use_ipi_for_rfence(void) +{ + return false; +} + static inline void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops) { } diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c index 8aeca26198f2..be2b7a89ce49 100644 --- a/arch/riscv/kernel/sbi.c +++ b/arch/riscv/kernel/sbi.c @@ -604,6 +604,8 @@ static void sbi_ipi_clear(void) } static const struct riscv_ipi_ops sbi_ipi_ops = { + .name = "SBI", + .use_for_rfence = false, .ipi_inject = sbi_send_cpumask_ipi, .ipi_clear = sbi_ipi_clear }; diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c index eea0c9d11d9f..cffe3247b132 100644 --- a/arch/riscv/kernel/smp.c +++ b/arch/riscv/kernel/smp.c @@ -90,9 +90,32 @@ static void ipi_stop(void) static const struct riscv_ipi_ops *ipi_ops __ro_after_init; +DEFINE_STATIC_KEY_FALSE(riscv_ipi_for_rfence); +EXPORT_SYMBOL_GPL(riscv_ipi_for_rfence); + void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops) { - ipi_ops = ops; + bool updated = true; + + if (!ops) + return; + + if (!ipi_ops) { + ipi_ops = ops; + } else { + if (!ipi_ops->use_for_rfence && ops->use_for_rfence) + ipi_ops = ops; + else + updated = false; + } + + if (updated) { + if (ipi_ops->use_for_rfence) + static_branch_enable(&riscv_ipi_for_rfence); + else + static_branch_disable(&riscv_ipi_for_rfence); + pr_info("switched IPI operations to %s\n", ipi_ops->name); + } } EXPORT_SYMBOL_GPL(riscv_set_ipi_ops); diff --git a/arch/riscv/mm/cacheflush.c b/arch/riscv/mm/cacheflush.c index 094118663285..0ffe7d560dc8 100644 --- a/arch/riscv/mm/cacheflush.c +++ b/arch/riscv/mm/cacheflush.c @@ -16,7 +16,7 @@ static void ipi_remote_fence_i(void *info) void flush_icache_all(void) { - if (IS_ENABLED(CONFIG_RISCV_SBI)) + if (!riscv_use_ipi_for_rfence()) sbi_remote_fence_i(NULL); else on_each_cpu(ipi_remote_fence_i, NULL, 1); diff --git a/drivers/clocksource/timer-clint.c b/drivers/clocksource/timer-clint.c index 6cfe2ab73eb0..dfdcd94c1fd5 100644 --- a/drivers/clocksource/timer-clint.c +++ b/drivers/clocksource/timer-clint.c @@ -55,6 +55,8 @@ static void clint_clear_ipi(void) } static struct riscv_ipi_ops clint_ipi_ops = { + .name = "CLINT", + .use_for_rfence = true, .ipi_inject = clint_send_ipi, .ipi_clear = clint_clear_ipi, }; -- 2.25.1