Commit a0789993 authored by Michal Simek's avatar Michal Simek Committed by Marc Zyngier

irqchip/xilinx: Enable generic irq multi handler

Register default arch handler via driver instead of directly pointing to
xilinx intc controller. This patch makes architecture code more generic.

Driver calls generic domain specific irq handler which does the most of
things self. Also get rid of concurrent_irq counting which hasn't been
exported anywhere.
Based on this loop was also optimized by using do/while loop instead of
goto loop.
Signed-off-by: default avatarMichal Simek <michal.simek@xilinx.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Reviewed-by: default avatarStefan Asserhall <stefan.asserhall@xilinx.com>
Link: https://lore.kernel.org/r/20200317125600.15913-4-mubin.usman.sayyed@xilinx.com
parent c74038ba
......@@ -47,6 +47,8 @@ config MICROBLAZE
select CPU_NO_EFFICIENT_FFS
select MMU_GATHER_NO_RANGE if MMU
select SPARSE_IRQ
select GENERIC_IRQ_MULTI_HANDLER
select HANDLE_DOMAIN_IRQ
# Endianness selection
choice
......
......@@ -14,7 +14,4 @@
struct pt_regs;
extern void do_IRQ(struct pt_regs *regs);
/* should be defined in each interrupt controller driver */
extern unsigned int xintc_get_irq(void);
#endif /* _ASM_MICROBLAZE_IRQ_H */
......@@ -20,29 +20,10 @@
#include <linux/irqchip.h>
#include <linux/of_irq.h>
static u32 concurrent_irq;
void __irq_entry do_IRQ(struct pt_regs *regs)
{
unsigned int irq;
struct pt_regs *old_regs = set_irq_regs(regs);
trace_hardirqs_off();
irq_enter();
irq = xintc_get_irq();
next_irq:
BUG_ON(!irq);
generic_handle_irq(irq);
irq = xintc_get_irq();
if (irq != -1U) {
pr_debug("next irq: %d\n", irq);
++concurrent_irq;
goto next_irq;
}
irq_exit();
set_irq_regs(old_regs);
handle_arch_irq(regs);
trace_hardirqs_on();
}
......
......@@ -124,20 +124,6 @@ static unsigned int xintc_get_irq_local(struct xintc_irq_chip *irqc)
return irq;
}
unsigned int xintc_get_irq(void)
{
unsigned int irq = -1;
u32 hwirq;
hwirq = xintc_read(primary_intc, IVR);
if (hwirq != -1U)
irq = irq_find_mapping(primary_intc->root_domain, hwirq);
pr_debug("irq-xilinx: hwirq=%d, irq=%d\n", hwirq, irq);
return irq;
}
static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
{
struct xintc_irq_chip *irqc = d->host_data;
......@@ -177,6 +163,25 @@ static void xil_intc_irq_handler(struct irq_desc *desc)
chained_irq_exit(chip, desc);
}
static void xil_intc_handle_irq(struct pt_regs *regs)
{
u32 hwirq;
struct xintc_irq_chip *irqc = primary_intc;
do {
hwirq = xintc_read(irqc, IVR);
if (likely(hwirq != -1U)) {
int ret;
ret = handle_domain_irq(irqc->root_domain, hwirq, regs);
WARN_ONCE(ret, "Unhandled HWIRQ %d\n", hwirq);
continue;
}
break;
} while (1);
}
static int __init xilinx_intc_of_init(struct device_node *intc,
struct device_node *parent)
{
......@@ -246,6 +251,7 @@ static int __init xilinx_intc_of_init(struct device_node *intc,
} else {
primary_intc = irqc;
irq_set_default_host(primary_intc->root_domain);
set_handle_irq(xil_intc_handle_irq);
}
return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment