RISC-V: self-contained IPI handling routine
Currently, the IPI handling routine riscv_software_interrupt() does not take any argument and also does not perform irq_enter()/irq_exit(). This patch makes IPI handling routine more self-contained by: 1. Passing "pt_regs *" argument 2. Explicitly doing irq_enter()/irq_exit() 3. Explicitly save/restore "pt_regs *" using set_irq_regs() With above changes, IPI handling routine does not depend on caller function to perform irq_enter()/irq_exit() and save/restore of "pt_regs *" hence its more self-contained. This also enables us to call IPI handling routine from IRQCHIP drivers. Signed-off-by: Anup Patel <anup.patel@wdc.com> Reviewed-by: Atish Patra <atish.patra@wdc.com> Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com> Acked-by: Palmer Dabbelt <palmerdabbelt@google.com> Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
This commit is contained in:
parent
e8c7ef7d58
commit
5cf998ba8c
|
@ -13,7 +13,6 @@
|
|||
#define NR_IRQS 0
|
||||
|
||||
void riscv_timer_interrupt(void);
|
||||
void riscv_software_interrupt(void);
|
||||
|
||||
#include <asm-generic/irq.h>
|
||||
|
||||
|
|
|
@ -28,6 +28,9 @@ void show_ipi_stats(struct seq_file *p, int prec);
|
|||
/* SMP initialization hook for setup_arch */
|
||||
void __init setup_smp(void);
|
||||
|
||||
/* Called from C code, this handles an IPI. */
|
||||
void handle_IPI(struct pt_regs *regs);
|
||||
|
||||
/* Hook for the generic smp_call_function_many() routine. */
|
||||
void arch_send_call_function_ipi_mask(struct cpumask *mask);
|
||||
|
||||
|
|
|
@ -19,12 +19,15 @@ int arch_show_interrupts(struct seq_file *p, int prec)
|
|||
|
||||
asmlinkage __visible void __irq_entry do_IRQ(struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||
struct pt_regs *old_regs;
|
||||
|
||||
irq_enter();
|
||||
switch (regs->cause & ~CAUSE_IRQ_FLAG) {
|
||||
case RV_IRQ_TIMER:
|
||||
old_regs = set_irq_regs(regs);
|
||||
irq_enter();
|
||||
riscv_timer_interrupt();
|
||||
irq_exit();
|
||||
set_irq_regs(old_regs);
|
||||
break;
|
||||
#ifdef CONFIG_SMP
|
||||
case RV_IRQ_SOFT:
|
||||
|
@ -32,19 +35,20 @@ asmlinkage __visible void __irq_entry do_IRQ(struct pt_regs *regs)
|
|||
* We only use software interrupts to pass IPIs, so if a non-SMP
|
||||
* system gets one, then we don't know what to do.
|
||||
*/
|
||||
riscv_software_interrupt();
|
||||
handle_IPI(regs);
|
||||
break;
|
||||
#endif
|
||||
case RV_IRQ_EXT:
|
||||
old_regs = set_irq_regs(regs);
|
||||
irq_enter();
|
||||
handle_arch_irq(regs);
|
||||
irq_exit();
|
||||
set_irq_regs(old_regs);
|
||||
break;
|
||||
default:
|
||||
pr_alert("unexpected interrupt cause 0x%lx", regs->cause);
|
||||
BUG();
|
||||
}
|
||||
irq_exit();
|
||||
|
||||
set_irq_regs(old_regs);
|
||||
}
|
||||
|
||||
void __init init_IRQ(void)
|
||||
|
|
|
@ -123,11 +123,14 @@ static inline void clear_ipi(void)
|
|||
clint_clear_ipi(cpuid_to_hartid_map(smp_processor_id()));
|
||||
}
|
||||
|
||||
void riscv_software_interrupt(void)
|
||||
void handle_IPI(struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||
unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits;
|
||||
unsigned long *stats = ipi_data[smp_processor_id()].stats;
|
||||
|
||||
irq_enter();
|
||||
|
||||
clear_ipi();
|
||||
|
||||
while (true) {
|
||||
|
@ -138,7 +141,7 @@ void riscv_software_interrupt(void)
|
|||
|
||||
ops = xchg(pending_ipis, 0);
|
||||
if (ops == 0)
|
||||
return;
|
||||
goto done;
|
||||
|
||||
if (ops & (1 << IPI_RESCHEDULE)) {
|
||||
stats[IPI_RESCHEDULE]++;
|
||||
|
@ -160,6 +163,10 @@ void riscv_software_interrupt(void)
|
|||
/* Order data access and bit testing. */
|
||||
mb();
|
||||
}
|
||||
|
||||
done:
|
||||
irq_exit();
|
||||
set_irq_regs(old_regs);
|
||||
}
|
||||
|
||||
static const char * const ipi_names[] = {
|
||||
|
|
Loading…
Reference in New Issue