aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreric miao <eric.y.miao@gmail.com>2010-12-13 03:42:34 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-12-24 04:47:34 -0500
commit521086412ee423fbdfc7da81f257239c43f707b4 (patch)
tree88423e6db9544002ebec1494b82a3d91bfb57363
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>
-rw-r--r--arch/arm/Kconfig5
-rw-r--r--arch/arm/include/asm/mach/arch.h3
-rw-r--r--arch/arm/include/asm/mach/irq.h4
-rw-r--r--arch/arm/kernel/entry-armv.S17
-rw-r--r--arch/arm/kernel/setup.c3
5 files changed, 30 insertions, 2 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index fd0e21be5e44..47694865018c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1022,6 +1022,11 @@ config CPU_HAS_PMU
1022 default y 1022 default y
1023 bool 1023 bool
1024 1024
1025config MULTI_IRQ_HANDLER
1026 bool
1027 help
1028 Allow each machine to specify it's own IRQ handler at run time.
1029
1025if !MMU 1030if !MMU
1026source "arch/arm/Kconfig-nommu" 1031source "arch/arm/Kconfig-nommu"
1027endif 1032endif
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index d97a964207fa..7d55356110d4 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -40,6 +40,9 @@ struct machine_desc {
40 void (*init_irq)(void); 40 void (*init_irq)(void);
41 struct sys_timer *timer; /* system tick timer */ 41 struct sys_timer *timer; /* system tick timer */
42 void (*init_machine)(void); 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/*
diff --git a/arch/arm/include/asm/mach/irq.h b/arch/arm/include/asm/mach/irq.h
index ce3eee9fe26c..6ecdad9a5c42 100644
--- a/arch/arm/include/asm/mach/irq.h
+++ b/arch/arm/include/asm/mach/irq.h
@@ -22,6 +22,10 @@ extern void (*init_arch_irq)(void);
22extern void init_FIQ(void); 22extern void init_FIQ(void);
23extern int show_fiq_list(struct seq_file *, void *); 23extern int show_fiq_list(struct seq_file *, void *);
24 24
25#ifdef CONFIG_MULTI_IRQ_HANDLER
26extern void (*handle_arch_irq)(struct pt_regs *);
27#endif
28
25/* 29/*
26 * This is for easy migration, but should be changed in the source 30 * This is for easy migration, but should be changed in the source
27 */ 31 */
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 35f3f20d6731..caa6c396ec78 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -30,6 +30,14 @@
30 * Interrupt handling. Preserves r7, r8, r9 30 * Interrupt handling. Preserves r7, r8, r9
31 */ 31 */
32 .macro irq_handler 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 get_irqnr_preamble r5, lr 41 get_irqnr_preamble r5, lr
341: get_irqnr_and_base r0, r6, r5, lr 421: get_irqnr_and_base r0, r6, r5, lr
35 movne r1, sp 43 movne r1, sp
@@ -58,9 +66,8 @@
58 adrne lr, BSYM(1b) 66 adrne lr, BSYM(1b)
59 bne do_local_timer 67 bne do_local_timer
60#endif 68#endif
619997:
62#endif 69#endif
63 709997:
64 .endm 71 .endm
65 72
66#ifdef CONFIG_KPROBES 73#ifdef CONFIG_KPROBES
@@ -1245,3 +1252,9 @@ cr_alignment:
1245 .space 4 1252 .space 4
1246cr_no_alignment: 1253cr_no_alignment:
1247 .space 4 1254 .space 4
1255
1256#ifdef CONFIG_MULTI_IRQ_HANDLER
1257 .globl handle_arch_irq
1258handle_arch_irq:
1259 .space 4
1260#endif
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 8075e592f902..0826f36330c4 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -875,6 +875,9 @@ void __init setup_arch(char **cmdline_p)
875 init_arch_irq = mdesc->init_irq; 875 init_arch_irq = mdesc->init_irq;
876 system_timer = mdesc->timer; 876 system_timer = mdesc->timer;
877 init_machine = mdesc->init_machine; 877 init_machine = mdesc->init_machine;
878#ifdef CONFIG_MULTI_IRQ_HANDLER
879 handle_arch_irq = mdesc->handle_irq;
880#endif
878 881
879#ifdef CONFIG_VT 882#ifdef CONFIG_VT
880#if defined(CONFIG_VGA_CONSOLE) 883#if defined(CONFIG_VGA_CONSOLE)