[PATCH] ARM: Allow machine to specify it's own IRQ handlers at run-time

Eric Miao eric.y.miao at gmail.com
Sun Dec 12 09:33:01 EST 2010


On Wed, Dec 8, 2010 at 9:41 PM, Russell King - ARM Linux
<linux at arm.linux.org.uk> wrote:
> On Tue, Dec 07, 2010 at 09:31:11PM +0800, Eric Miao wrote:
>> Ah silly me, the patch below fixed this, and tested on Marvell Dove:
> ...
>> diff --git a/arch/arm/include/asm/mach/irq.h b/arch/arm/include/asm/mach/irq.h
>> index ce3eee9..6ecdad9 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);
>>  extern void init_FIQ(void);
>>  extern int show_fiq_list(struct seq_file *, void *);
>>
>> +#ifdef CONFIG_MULTI_IRQ_HANDLER
>> +extern void (*handle_arch_irq)(struct pt_regs *);
>> +#endif
>> +
>>  /*
>>   * This is for easy migration, but should be changed in the source
>>   */
>> diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
>> index c09e357..d29e31b 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     r1, =handle_arch_irq
>> +     ldr     r0, [r1]
>> +     cmp     r0, #0
>> +     movne   r0, sp
>> +     adrne   lr, BSYM(9997f)
>> +     ldrne   pc, [r1]
>> +#endif
>
> You might as well do this:
>
>        ldr     r5, =handle_arch_irq
>        mov     r0, sp
>        ldr     r5, [r5]
>        adr     lr, BSYM(9997f)
>        teq     r5, #0
>        movne   pc, r5
>
> which also helps to fill the load delay slots with useful work.
>
>>       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:
>> +     .long   0
>
>        .space 4
>
> as above please
>

Updated the patch following your suggestions, verified on Marvell Dove
platform and it worked all right. Do you want me to submit this to the
patch tracking system?

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index db524e7..0cecffb 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1017,6 +1017,11 @@ config CPU_HAS_PMU
 	default y
 	bool

+config MULTI_IRQ_HANDLER
+	bool
+	help
+	  Allow each machine to specify it's own IRQ handler at run time.
+
 if !MMU
 source "arch/arm/Kconfig-nommu"
 endif
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index d97a964..7d55356 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -40,6 +40,9 @@ struct machine_desc {
 	void			(*init_irq)(void);
 	struct sys_timer	*timer;		/* system tick timer	*/
 	void			(*init_machine)(void);
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+	void			(*handle_irq)(struct pt_regs *);
+#endif
 };

 /*
diff --git a/arch/arm/include/asm/mach/irq.h b/arch/arm/include/asm/mach/irq.h
index ce3eee9..6ecdad9 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);
 extern void init_FIQ(void);
 extern int show_fiq_list(struct seq_file *, void *);

+#ifdef CONFIG_MULTI_IRQ_HANDLER
+extern void (*handle_arch_irq)(struct pt_regs *);
+#endif
+
 /*
  * This is for easy migration, but should be changed in the source
  */
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index c09e357..d29e31b 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	r1, =handle_arch_irq
+	ldr	r0, [r1]
+	cmp	r0, #0
+	movne	r0, sp
+	adrne	lr, BSYM(9997f)
+	ldrne	pc, [r1]
+#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:
+	.long	0
+#endif
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 336f14e..b809521 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)



More information about the linux-arm-kernel mailing list