linux/arch/riscv/kernel/irq.c
Anup Patel 5cf998ba8c
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>
2020-06-09 19:11:19 -07:00

57 lines
1.1 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2012 Regents of the University of California
* Copyright (C) 2017 SiFive
* Copyright (C) 2018 Christoph Hellwig
*/
#include <linux/interrupt.h>
#include <linux/irqchip.h>
#include <linux/irqdomain.h>
#include <linux/seq_file.h>
#include <asm/smp.h>
int arch_show_interrupts(struct seq_file *p, int prec)
{
show_ipi_stats(p, prec);
return 0;
}
asmlinkage __visible void __irq_entry do_IRQ(struct pt_regs *regs)
{
struct pt_regs *old_regs;
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:
/*
* We only use software interrupts to pass IPIs, so if a non-SMP
* system gets one, then we don't know what to do.
*/
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();
}
}
void __init init_IRQ(void)
{
irqchip_init();
}