Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

irqchip/xilinx: Switch to GENERIC_IRQ_MULTI_HANDLER

Register the Xilinx driver as the root interrupt controller using
the GENERIC_IRQ_MULTI_HANDLER API, instead of the arch-specific hack.

Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Reviewed-by: Stefan Asserhall <stefan.asserhall@xilinx.com>
[maz: repainted commit message]
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/e6c6595a81f662bf839cee3109d0fa58a596ea47.1646380284.git.michal.simek@xilinx.com

authored by

Michal Simek and committed by
Marc Zyngier
1e364921 e414c25e

+19 -32
+2
arch/microblaze/Kconfig
··· 45 45 select SET_FS 46 46 select ZONE_DMA 47 47 select TRACE_IRQFLAGS_SUPPORT 48 + select GENERIC_IRQ_MULTI_HANDLER 49 + select HANDLE_DOMAIN_IRQ 48 50 49 51 # Endianness selection 50 52 choice
-3
arch/microblaze/include/asm/irq.h
··· 11 11 struct pt_regs; 12 12 extern void do_IRQ(struct pt_regs *regs); 13 13 14 - /* should be defined in each interrupt controller driver */ 15 - extern unsigned int xintc_get_irq(void); 16 - 17 14 #endif /* _ASM_MICROBLAZE_IRQ_H */
+1 -15
arch/microblaze/kernel/irq.c
··· 20 20 #include <linux/irqchip.h> 21 21 #include <linux/of_irq.h> 22 22 23 - static u32 concurrent_irq; 24 - 25 23 void __irq_entry do_IRQ(struct pt_regs *regs) 26 24 { 27 - unsigned int irq; 28 25 struct pt_regs *old_regs = set_irq_regs(regs); 29 26 trace_hardirqs_off(); 30 27 31 28 irq_enter(); 32 - irq = xintc_get_irq(); 33 - next_irq: 34 - BUG_ON(!irq); 35 - generic_handle_irq(irq); 36 - 37 - irq = xintc_get_irq(); 38 - if (irq != -1U) { 39 - pr_debug("next irq: %d\n", irq); 40 - ++concurrent_irq; 41 - goto next_irq; 42 - } 43 - 29 + handle_arch_irq(regs); 44 30 irq_exit(); 45 31 set_irq_regs(old_regs); 46 32 trace_hardirqs_on();
+16 -14
drivers/irqchip/irq-xilinx-intc.c
··· 32 32 #define MER_ME (1<<0) 33 33 #define MER_HIE (1<<1) 34 34 35 + #define SPURIOUS_IRQ (-1U) 36 + 35 37 static DEFINE_STATIC_KEY_FALSE(xintc_is_be); 36 38 37 39 struct xintc_irq_chip { ··· 112 110 .irq_mask_ack = intc_mask_ack, 113 111 }; 114 112 115 - unsigned int xintc_get_irq(void) 116 - { 117 - unsigned int irq = -1; 118 - u32 hwirq; 119 - 120 - hwirq = xintc_read(primary_intc, IVR); 121 - if (hwirq != -1U) 122 - irq = irq_find_mapping(primary_intc->root_domain, hwirq); 123 - 124 - pr_debug("irq-xilinx: hwirq=%d, irq=%d\n", hwirq, irq); 125 - 126 - return irq; 127 - } 128 - 129 113 static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) 130 114 { 131 115 struct xintc_irq_chip *irqc = d->host_data; ··· 150 162 generic_handle_domain_irq(irqc->root_domain, hwirq); 151 163 } while (true); 152 164 chained_irq_exit(chip, desc); 165 + } 166 + 167 + static void xil_intc_handle_irq(struct pt_regs *regs) 168 + { 169 + u32 hwirq; 170 + 171 + do { 172 + hwirq = xintc_read(primary_intc, IVR); 173 + if (unlikely(hwirq == SPURIOUS_IRQ)) 174 + break; 175 + 176 + generic_handle_domain_irq(primary_intc->root_domain, hwirq); 177 + } while (true); 153 178 } 154 179 155 180 static int __init xilinx_intc_of_init(struct device_node *intc, ··· 234 233 } else { 235 234 primary_intc = irqc; 236 235 irq_set_default_host(primary_intc->root_domain); 236 + set_handle_irq(xil_intc_handle_irq); 237 237 } 238 238 239 239 return 0;