summaryrefslogtreecommitdiff
path: root/drivers/irqchip/irq-riscv-intc.c
diff options
context:
space:
mode:
authorAnup Patel <apatel@ventanamicro.com>2023-03-28 06:52:19 +0300
committerMarc Zyngier <maz@kernel.org>2023-04-08 13:26:24 +0300
commit832f15f42646812b096bc67c0eac439291a0db1f (patch)
treeef8ad0a6a4059884420af3c093f0f182ac6aff28 /drivers/irqchip/irq-riscv-intc.c
parent0c60a31ce62ca3e93550868fd699dfc4dfc4e795 (diff)
downloadlinux-832f15f42646812b096bc67c0eac439291a0db1f.tar.xz
RISC-V: Treat IPIs as normal Linux IRQs
Currently, the RISC-V kernel provides arch specific hooks (i.e. struct riscv_ipi_ops) to register IPI handling methods. The stats gathering of IPIs is also arch specific in the RISC-V kernel. Other architectures (such as ARM, ARM64, and MIPS) have moved away from custom arch specific IPI handling methods. Currently, these architectures have Linux irqchip drivers providing a range of Linux IRQ numbers to be used as IPIs and IPI triggering is done using generic IPI APIs. This approach allows architectures to treat IPIs as normal Linux IRQs and IPI stats gathering is done by the generic Linux IRQ subsystem. We extend the RISC-V IPI handling as-per above approach so that arch specific IPI handling methods (struct riscv_ipi_ops) can be removed and the IPI handling is done through the Linux IRQ subsystem. Signed-off-by: Anup Patel <apatel@ventanamicro.com> Acked-by: Palmer Dabbelt <palmer@rivosinc.com> Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20230328035223.1480939-4-apatel@ventanamicro.com
Diffstat (limited to 'drivers/irqchip/irq-riscv-intc.c')
-rw-r--r--drivers/irqchip/irq-riscv-intc.c55
1 files changed, 24 insertions, 31 deletions
diff --git a/drivers/irqchip/irq-riscv-intc.c b/drivers/irqchip/irq-riscv-intc.c
index 9066467e99e4..784d25645704 100644
--- a/drivers/irqchip/irq-riscv-intc.c
+++ b/drivers/irqchip/irq-riscv-intc.c
@@ -26,20 +26,7 @@ static asmlinkage void riscv_intc_irq(struct pt_regs *regs)
if (unlikely(cause >= BITS_PER_LONG))
panic("unexpected interrupt cause");
- switch (cause) {
-#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
- default:
- generic_handle_domain_irq(intc_domain, cause);
- break;
- }
+ generic_handle_domain_irq(intc_domain, cause);
}
/*
@@ -59,18 +46,6 @@ static void riscv_intc_irq_unmask(struct irq_data *d)
csr_set(CSR_IE, BIT(d->hwirq));
}
-static int riscv_intc_cpu_starting(unsigned int cpu)
-{
- csr_set(CSR_IE, BIT(RV_IRQ_SOFT));
- return 0;
-}
-
-static int riscv_intc_cpu_dying(unsigned int cpu)
-{
- csr_clear(CSR_IE, BIT(RV_IRQ_SOFT));
- return 0;
-}
-
static struct irq_chip riscv_intc_chip = {
.name = "RISC-V INTC",
.irq_mask = riscv_intc_irq_mask,
@@ -87,9 +62,32 @@ static int riscv_intc_domain_map(struct irq_domain *d, unsigned int irq,
return 0;
}
+static int riscv_intc_domain_alloc(struct irq_domain *domain,
+ unsigned int virq, unsigned int nr_irqs,
+ void *arg)
+{
+ int i, ret;
+ irq_hw_number_t hwirq;
+ unsigned int type = IRQ_TYPE_NONE;
+ struct irq_fwspec *fwspec = arg;
+
+ ret = irq_domain_translate_onecell(domain, fwspec, &hwirq, &type);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < nr_irqs; i++) {
+ ret = riscv_intc_domain_map(domain, virq + i, hwirq + i);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static const struct irq_domain_ops riscv_intc_domain_ops = {
.map = riscv_intc_domain_map,
.xlate = irq_domain_xlate_onecell,
+ .alloc = riscv_intc_domain_alloc
};
static struct fwnode_handle *riscv_intc_hwnode(void)
@@ -133,11 +131,6 @@ static int __init riscv_intc_init(struct device_node *node,
riscv_set_intc_hwnode_fn(riscv_intc_hwnode);
- cpuhp_setup_state(CPUHP_AP_IRQ_RISCV_STARTING,
- "irqchip/riscv/intc:starting",
- riscv_intc_cpu_starting,
- riscv_intc_cpu_dying);
-
pr_info("%d local interrupts mapped\n", BITS_PER_LONG);
return 0;