summaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authoreric miao <eric.y.miao@gmail.com>2010-12-13 09:42:34 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-12-24 09:47:34 +0000
commit521086412ee423fbdfc7da81f257239c43f707b4 (patch)
tree88423e6db9544002ebec1494b82a3d91bfb57363 /arch/arm/kernel
parent4a50bfe365a977f634311504484342fbfffe855c (diff)
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>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/entry-armv.S17
-rw-r--r--arch/arm/kernel/setup.c3
2 files changed, 18 insertions, 2 deletions
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 35f3f20d673..caa6c396ec7 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -30,6 +30,14 @@
* Interrupt handling. Preserves r7, r8, r9
*/
.macro irq_handler
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+ ldr r5, =handle_arch_irq
+ mov r0, sp
+ ldr r5, [r5]
+ adr lr, BSYM(9997f)
+ teq r5, #0
+ movne pc, r5
+#endif
get_irqnr_preamble r5, lr
1: get_irqnr_and_base r0, r6, r5, lr
movne r1, sp
@@ -58,9 +66,8 @@
adrne lr, BSYM(1b)
bne do_local_timer
#endif
-9997:
#endif
-
+9997:
.endm
#ifdef CONFIG_KPROBES
@@ -1245,3 +1252,9 @@ cr_alignment:
.space 4
cr_no_alignment:
.space 4
+
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+ .globl handle_arch_irq
+handle_arch_irq:
+ .space 4
+#endif
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 8075e592f90..0826f36330c 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -875,6 +875,9 @@ void __init setup_arch(char **cmdline_p)
init_arch_irq = mdesc->init_irq;
system_timer = mdesc->timer;
init_machine = mdesc->init_machine;
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+ handle_arch_irq = mdesc->handle_irq;
+#endif
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)