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

ARM: 6532/1: Allow machine to specify it's own IRQ handlers at run-time

Normally different ARM platform has different way to decode the IRQ
hardware status and demultiplex to the corresponding IRQ handler.
This is highly optimized by macro irq_handler in entry-armv.S, and
each machine defines their own macro to decode the IRQ number.
However, this prevents multiple machine classes to be built into a
single kernel.

By allowing each machine to specify thier own handler, and making
function pointer 'handle_arch_irq' to point to it at run time, this
can be solved. And introduce CONFIG_MULTI_IRQ_HANDLER to allow both
solutions to work.

Comparing with the highly optimized macro of irq_handler, the new
function must be written with care not to lose too much performance.
And the IPI stuff on SMP is expected to move to the provided arch
IRQ handler as well.

The assembly code to invoke handle_arch_irq is optimized by Russell
King.

Signed-off-by: Eric Miao <eric.miao@canonical.com>
Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by

eric miao and committed by
Russell King
52108641 4a50bfe3

+30 -2
+5
arch/arm/Kconfig
··· 1022 1022 default y 1023 1023 bool 1024 1024 1025 + config MULTI_IRQ_HANDLER 1026 + bool 1027 + help 1028 + Allow each machine to specify it's own IRQ handler at run time. 1029 + 1025 1030 if !MMU 1026 1031 source "arch/arm/Kconfig-nommu" 1027 1032 endif
+3
arch/arm/include/asm/mach/arch.h
··· 40 40 void (*init_irq)(void); 41 41 struct sys_timer *timer; /* system tick timer */ 42 42 void (*init_machine)(void); 43 + #ifdef CONFIG_MULTI_IRQ_HANDLER 44 + void (*handle_irq)(struct pt_regs *); 45 + #endif 43 46 }; 44 47 45 48 /*
+4
arch/arm/include/asm/mach/irq.h
··· 22 22 extern void init_FIQ(void); 23 23 extern int show_fiq_list(struct seq_file *, void *); 24 24 25 + #ifdef CONFIG_MULTI_IRQ_HANDLER 26 + extern void (*handle_arch_irq)(struct pt_regs *); 27 + #endif 28 + 25 29 /* 26 30 * This is for easy migration, but should be changed in the source 27 31 */
+15 -2
arch/arm/kernel/entry-armv.S
··· 30 30 * Interrupt handling. Preserves r7, r8, r9 31 31 */ 32 32 .macro irq_handler 33 + #ifdef CONFIG_MULTI_IRQ_HANDLER 34 + ldr r5, =handle_arch_irq 35 + mov r0, sp 36 + ldr r5, [r5] 37 + adr lr, BSYM(9997f) 38 + teq r5, #0 39 + movne pc, r5 40 + #endif 33 41 get_irqnr_preamble r5, lr 34 42 1: get_irqnr_and_base r0, r6, r5, lr 35 43 movne r1, sp ··· 66 58 adrne lr, BSYM(1b) 67 59 bne do_local_timer 68 60 #endif 69 - 9997: 70 61 #endif 71 - 62 + 9997: 72 63 .endm 73 64 74 65 #ifdef CONFIG_KPROBES ··· 1252 1245 .space 4 1253 1246 cr_no_alignment: 1254 1247 .space 4 1248 + 1249 + #ifdef CONFIG_MULTI_IRQ_HANDLER 1250 + .globl handle_arch_irq 1251 + handle_arch_irq: 1252 + .space 4 1253 + #endif
+3
arch/arm/kernel/setup.c
··· 875 875 init_arch_irq = mdesc->init_irq; 876 876 system_timer = mdesc->timer; 877 877 init_machine = mdesc->init_machine; 878 + #ifdef CONFIG_MULTI_IRQ_HANDLER 879 + handle_arch_irq = mdesc->handle_irq; 880 + #endif 878 881 879 882 #ifdef CONFIG_VT 880 883 #if defined(CONFIG_VGA_CONSOLE)