From: Christoph Hellwig This code is the same for all architectures with the following invariants: - arm gurantees irqs are disabled when calling irq_exit so it can call __do_softirq directly instead of do_softirq - arm26 is totally broken for about half a year, I didn't care for it - some architectures use softirq_pending(smp_processor_id()) instead of local_softirq_pending, but they always evaluate to the same This patch moves the out of line irq_exit implementation from kernel/irq/handle.c which depends on CONFIG_GENERIC_HARDIRQS to kernel/softirq.c which is always compiled, tweaks it for the arm special case and moves the irq_enter/irq_exit/nmi_enter/nmi_exit bits from asm-*/hardirq.h to linux/hardirq.h Signed-off-by: Andrew Morton --- 25-akpm/arch/ia64/kernel/irq_ia64.c | 15 --------------- 25-akpm/include/asm-alpha/hardirq.h | 10 ---------- 25-akpm/include/asm-arm/hardirq.h | 12 +----------- 25-akpm/include/asm-arm26/hardirq.h | 13 ------------- 25-akpm/include/asm-cris/hardirq.h | 9 --------- 25-akpm/include/asm-h8300/hardirq.h | 9 --------- 25-akpm/include/asm-m32r/hardirq.h | 12 ------------ 25-akpm/include/asm-m68k/hardirq.h | 9 --------- 25-akpm/include/asm-m68knommu/hardirq.h | 9 --------- 25-akpm/include/asm-parisc/hardirq.h | 9 --------- 25-akpm/include/asm-s390/hardirq.h | 16 +--------------- 25-akpm/include/asm-sh/hardirq.h | 12 ------------ 25-akpm/include/asm-sparc/hardirq.h | 9 --------- 25-akpm/include/asm-sparc64/hardirq.h | 9 --------- 25-akpm/include/asm-v850/hardirq.h | 9 --------- 25-akpm/include/linux/hardirq.h | 2 -- 25-akpm/kernel/irq/handle.c | 11 ----------- 25-akpm/kernel/softirq.c | 17 +++++++++++++++++ 18 files changed, 19 insertions(+), 173 deletions(-) diff -puN arch/ia64/kernel/irq_ia64.c~move-irq_enter-and-irq_exit-to-common-code arch/ia64/kernel/irq_ia64.c --- 25/arch/ia64/kernel/irq_ia64.c~move-irq_enter-and-irq_exit-to-common-code Mon Nov 29 13:15:52 2004 +++ 25-akpm/arch/ia64/kernel/irq_ia64.c Mon Nov 29 13:15:52 2004 @@ -60,21 +60,6 @@ __u8 isa_irq_to_vector_map[16] = { }; EXPORT_SYMBOL(isa_irq_to_vector_map); -static inline void -irq_enter (void) -{ - preempt_count() += HARDIRQ_OFFSET; -} - -static inline void -irq_exit (void) -{ - preempt_count() -= IRQ_EXIT_OFFSET; - if (!in_interrupt() && local_softirq_pending()) - do_softirq(); - preempt_enable_no_resched(); -} - int assign_irq_vector (int irq) { diff -puN include/asm-alpha/hardirq.h~move-irq_enter-and-irq_exit-to-common-code include/asm-alpha/hardirq.h --- 25/include/asm-alpha/hardirq.h~move-irq_enter-and-irq_exit-to-common-code Mon Nov 29 13:15:52 2004 +++ 25-akpm/include/asm-alpha/hardirq.h Mon Nov 29 13:15:52 2004 @@ -29,14 +29,4 @@ typedef struct { #error HARDIRQ_BITS is too low! #endif -#define irq_enter() (preempt_count() += HARDIRQ_OFFSET) -#define irq_exit() \ -do { \ - preempt_count() -= IRQ_EXIT_OFFSET; \ - if (!in_interrupt() && \ - softirq_pending(smp_processor_id())) \ - do_softirq(); \ - preempt_enable_no_resched(); \ -} while (0) - #endif /* _ALPHA_HARDIRQ_H */ diff -puN include/asm-arm26/hardirq.h~move-irq_enter-and-irq_exit-to-common-code include/asm-arm26/hardirq.h --- 25/include/asm-arm26/hardirq.h~move-irq_enter-and-irq_exit-to-common-code Mon Nov 29 13:15:52 2004 +++ 25-akpm/include/asm-arm26/hardirq.h Mon Nov 29 13:15:52 2004 @@ -26,17 +26,4 @@ typedef struct { # error HARDIRQ_BITS is too low! #endif -#define irq_enter() (preempt_count() += HARDIRQ_OFFSET) - -#ifndef CONFIG_SMP -#define irq_exit() \ - do { \ - preempt_count() -= HARDIRQ_OFFSET; \ - if (!in_interrupt() && softirq_pending(smp_processor_id())) \ - __asm__("bl%? __do_softirq": : : "lr");/* out of line */\ - preempt_enable_no_resched(); \ - } while (0) - -#endif - #endif /* __ASM_HARDIRQ_H */ diff -puN include/asm-arm/hardirq.h~move-irq_enter-and-irq_exit-to-common-code include/asm-arm/hardirq.h --- 25/include/asm-arm/hardirq.h~move-irq_enter-and-irq_exit-to-common-code Mon Nov 29 13:15:52 2004 +++ 25-akpm/include/asm-arm/hardirq.h Mon Nov 29 13:15:52 2004 @@ -27,16 +27,6 @@ typedef struct { # error HARDIRQ_BITS is too low! #endif -#define irq_enter() (preempt_count() += HARDIRQ_OFFSET) - -extern asmlinkage void __do_softirq(void); - -#define irq_exit() \ - do { \ - preempt_count() -= IRQ_EXIT_OFFSET; \ - if (!in_interrupt() && local_softirq_pending()) \ - __do_softirq(); \ - preempt_enable_no_resched(); \ - } while (0) +#define __ARCH_IRQ_EXIT_IRQS_DISABLED 1 #endif /* __ASM_HARDIRQ_H */ diff -puN include/asm-cris/hardirq.h~move-irq_enter-and-irq_exit-to-common-code include/asm-cris/hardirq.h --- 25/include/asm-cris/hardirq.h~move-irq_enter-and-irq_exit-to-common-code Mon Nov 29 13:15:52 2004 +++ 25-akpm/include/asm-cris/hardirq.h Mon Nov 29 13:15:52 2004 @@ -28,13 +28,4 @@ typedef struct { # error HARDIRQ_BITS is too low! #endif -#define irq_enter() (preempt_count() += HARDIRQ_OFFSET) -#define irq_exit() \ -do { \ - preempt_count() -= IRQ_EXIT_OFFSET; \ - if (!in_interrupt() && softirq_pending(smp_processor_id())) \ - do_softirq(); \ - preempt_enable_no_resched(); \ -} while (0) - #endif /* __ASM_HARDIRQ_H */ diff -puN include/asm-h8300/hardirq.h~move-irq_enter-and-irq_exit-to-common-code include/asm-h8300/hardirq.h --- 25/include/asm-h8300/hardirq.h~move-irq_enter-and-irq_exit-to-common-code Mon Nov 29 13:15:52 2004 +++ 25-akpm/include/asm-h8300/hardirq.h Mon Nov 29 13:15:52 2004 @@ -26,13 +26,4 @@ typedef struct { # error HARDIRQ_BITS is too low! #endif -#define irq_enter() (preempt_count() += HARDIRQ_OFFSET) -#define irq_exit() \ -do { \ - preempt_count() -= IRQ_EXIT_OFFSET; \ - if (!in_interrupt() && softirq_pending(smp_processor_id())) \ - do_softirq(); \ - preempt_enable_no_resched(); \ -} while (0) - #endif diff -puN include/asm-m32r/hardirq.h~move-irq_enter-and-irq_exit-to-common-code include/asm-m32r/hardirq.h --- 25/include/asm-m32r/hardirq.h~move-irq_enter-and-irq_exit-to-common-code Mon Nov 29 13:15:52 2004 +++ 25-akpm/include/asm-m32r/hardirq.h Mon Nov 29 13:15:52 2004 @@ -28,16 +28,4 @@ typedef struct { # error HARDIRQ_BITS is too low! #endif -#define irq_enter() (preempt_count() += HARDIRQ_OFFSET) -#define nmi_enter() (irq_enter()) -#define nmi_exit() (preempt_count() -= HARDIRQ_OFFSET) - -#define irq_exit() \ -do { \ - preempt_count() -= IRQ_EXIT_OFFSET; \ - if (!in_interrupt() && softirq_pending(smp_processor_id())) \ - do_softirq(); \ - preempt_enable_no_resched(); \ -} while (0) - #endif /* __ASM_HARDIRQ_H */ diff -puN include/asm-m68k/hardirq.h~move-irq_enter-and-irq_exit-to-common-code include/asm-m68k/hardirq.h --- 25/include/asm-m68k/hardirq.h~move-irq_enter-and-irq_exit-to-common-code Mon Nov 29 13:15:52 2004 +++ 25-akpm/include/asm-m68k/hardirq.h Mon Nov 29 13:15:52 2004 @@ -23,13 +23,4 @@ typedef struct { # error HARDIRQ_BITS is too low! #endif -#define irq_enter() (preempt_count() += HARDIRQ_OFFSET) -#define irq_exit() \ -do { \ - preempt_count() -= IRQ_EXIT_OFFSET; \ - if (!in_interrupt() && softirq_pending(smp_processor_id())) \ - do_softirq(); \ - preempt_enable_no_resched(); \ -} while (0) - #endif diff -puN include/asm-m68knommu/hardirq.h~move-irq_enter-and-irq_exit-to-common-code include/asm-m68knommu/hardirq.h --- 25/include/asm-m68knommu/hardirq.h~move-irq_enter-and-irq_exit-to-common-code Mon Nov 29 13:15:52 2004 +++ 25-akpm/include/asm-m68knommu/hardirq.h Mon Nov 29 13:15:52 2004 @@ -24,13 +24,4 @@ typedef struct { # error HARDIRQ_BITS is too low! #endif -#define irq_enter() (preempt_count() += HARDIRQ_OFFSET) -#define irq_exit() \ -do { \ - preempt_count() -= IRQ_EXIT_OFFSET; \ - if (!in_interrupt() && softirq_pending(smp_processor_id())) \ - do_softirq(); \ - preempt_enable_no_resched(); \ -} while (0) - #endif /* __M68K_HARDIRQ_H */ diff -puN include/asm-parisc/hardirq.h~move-irq_enter-and-irq_exit-to-common-code include/asm-parisc/hardirq.h --- 25/include/asm-parisc/hardirq.h~move-irq_enter-and-irq_exit-to-common-code Mon Nov 29 13:15:52 2004 +++ 25-akpm/include/asm-parisc/hardirq.h Mon Nov 29 13:15:52 2004 @@ -38,13 +38,4 @@ typedef struct { # error HARDIRQ_BITS is too low! #endif -#define irq_enter() (preempt_count() += HARDIRQ_OFFSET) -#define irq_exit() \ -do { \ - preempt_count() -= IRQ_EXIT_OFFSET; \ - if (!in_interrupt() && softirq_pending(smp_processor_id())) \ - do_softirq(); \ - preempt_enable_no_resched(); \ -} while (0) - #endif /* _PARISC_HARDIRQ_H */ diff -puN include/asm-s390/hardirq.h~move-irq_enter-and-irq_exit-to-common-code include/asm-s390/hardirq.h --- 25/include/asm-s390/hardirq.h~move-irq_enter-and-irq_exit-to-common-code Mon Nov 29 13:15:52 2004 +++ 25-akpm/include/asm-s390/hardirq.h Mon Nov 29 13:15:52 2004 @@ -37,24 +37,10 @@ softirq_pending(unsigned int cpu) } #define __ARCH_IRQ_STAT +#define __ARCH_HAS_DO_SOFTIRQ #define HARDIRQ_BITS 8 extern void account_ticks(struct pt_regs *); -#define __ARCH_HAS_DO_SOFTIRQ - -#define irq_enter() \ -do { \ - (preempt_count() += HARDIRQ_OFFSET); \ -} while(0) -#define irq_exit() \ -do { \ - preempt_count() -= IRQ_EXIT_OFFSET; \ - if (!in_interrupt() && local_softirq_pending()) \ - /* Use the async. stack for softirq */ \ - do_softirq(); \ - preempt_enable_no_resched(); \ -} while (0) - #endif /* __ASM_HARDIRQ_H */ diff -puN include/asm-sh/hardirq.h~move-irq_enter-and-irq_exit-to-common-code include/asm-sh/hardirq.h --- 25/include/asm-sh/hardirq.h~move-irq_enter-and-irq_exit-to-common-code Mon Nov 29 13:15:52 2004 +++ 25-akpm/include/asm-sh/hardirq.h Mon Nov 29 13:15:52 2004 @@ -23,16 +23,4 @@ typedef struct { # error HARDIRQ_BITS is too low! #endif -#define nmi_enter() (irq_enter()) -#define nmi_exit() (preempt_count() -= HARDIRQ_OFFSET) - -#define irq_enter() (preempt_count() += HARDIRQ_OFFSET) -#define irq_exit() \ -do { \ - preempt_count() -= IRQ_EXIT_OFFSET; \ - if (!in_interrupt() && softirq_pending(smp_processor_id())) \ - do_softirq(); \ - preempt_enable_no_resched(); \ -} while (0) - #endif /* __ASM_SH_HARDIRQ_H */ diff -puN include/asm-sparc64/hardirq.h~move-irq_enter-and-irq_exit-to-common-code include/asm-sparc64/hardirq.h --- 25/include/asm-sparc64/hardirq.h~move-irq_enter-and-irq_exit-to-common-code Mon Nov 29 13:15:52 2004 +++ 25-akpm/include/asm-sparc64/hardirq.h Mon Nov 29 13:15:52 2004 @@ -20,13 +20,4 @@ typedef struct { #define HARDIRQ_BITS 8 -#define irq_enter() (preempt_count() += HARDIRQ_OFFSET) -#define irq_exit() \ -do { \ - preempt_count() -= IRQ_EXIT_OFFSET; \ - if (!in_interrupt() && softirq_pending(smp_processor_id())) \ - do_softirq(); \ - preempt_enable_no_resched(); \ -} while (0) - #endif /* !(__SPARC64_HARDIRQ_H) */ diff -puN include/asm-sparc/hardirq.h~move-irq_enter-and-irq_exit-to-common-code include/asm-sparc/hardirq.h --- 25/include/asm-sparc/hardirq.h~move-irq_enter-and-irq_exit-to-common-code Mon Nov 29 13:15:52 2004 +++ 25-akpm/include/asm-sparc/hardirq.h Mon Nov 29 13:15:52 2004 @@ -21,13 +21,4 @@ typedef struct { #define HARDIRQ_BITS 8 -#define irq_enter() (preempt_count() += HARDIRQ_OFFSET) -#define irq_exit() \ -do { \ - preempt_count() -= IRQ_EXIT_OFFSET; \ - if (!in_interrupt() && softirq_pending(smp_processor_id())) \ - do_softirq(); \ - preempt_enable_no_resched(); \ -} while (0) - #endif /* __SPARC_HARDIRQ_H */ diff -puN include/asm-v850/hardirq.h~move-irq_enter-and-irq_exit-to-common-code include/asm-v850/hardirq.h --- 25/include/asm-v850/hardirq.h~move-irq_enter-and-irq_exit-to-common-code Mon Nov 29 13:15:52 2004 +++ 25-akpm/include/asm-v850/hardirq.h Mon Nov 29 13:15:52 2004 @@ -24,13 +24,4 @@ typedef struct { # error HARDIRQ_BITS is too low! #endif -#define irq_enter() (preempt_count() += HARDIRQ_OFFSET) -#define irq_exit() \ -do { \ - preempt_count() -= IRQ_EXIT_OFFSET; \ - if (!in_interrupt() && softirq_pending(smp_processor_id())) \ - do_softirq(); \ - preempt_enable_no_resched(); \ -} while (0) - #endif /* __V850_HARDIRQ_H__ */ diff -puN include/linux/hardirq.h~move-irq_enter-and-irq_exit-to-common-code include/linux/hardirq.h --- 25/include/linux/hardirq.h~move-irq_enter-and-irq_exit-to-common-code Mon Nov 29 13:15:52 2004 +++ 25-akpm/include/linux/hardirq.h Mon Nov 29 13:15:52 2004 @@ -77,12 +77,10 @@ extern void synchronize_irq(unsigned int # define synchronize_irq(irq) barrier() #endif -#ifdef CONFIG_GENERIC_HARDIRQS #define nmi_enter() (preempt_count() += HARDIRQ_OFFSET) #define nmi_exit() (preempt_count() -= HARDIRQ_OFFSET) #define irq_enter() (preempt_count() += HARDIRQ_OFFSET) extern void irq_exit(void); -#endif #endif /* LINUX_HARDIRQ_H */ diff -puN kernel/irq/handle.c~move-irq_enter-and-irq_exit-to-common-code kernel/irq/handle.c --- 25/kernel/irq/handle.c~move-irq_enter-and-irq_exit-to-common-code Mon Nov 29 13:15:52 2004 +++ 25-akpm/kernel/irq/handle.c Mon Nov 29 13:15:52 2004 @@ -73,17 +73,6 @@ irqreturn_t no_action(int cpl, void *dev } /* - * Exit an interrupt context. Process softirqs if needed and possible: - */ -void irq_exit(void) -{ - preempt_count() -= IRQ_EXIT_OFFSET; - if (!in_interrupt() && local_softirq_pending()) - do_softirq(); - preempt_enable_no_resched(); -} - -/* * Have got an event to handle: */ fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, diff -puN kernel/softirq.c~move-irq_enter-and-irq_exit-to-common-code kernel/softirq.c --- 25/kernel/softirq.c~move-irq_enter-and-irq_exit-to-common-code Mon Nov 29 13:15:52 2004 +++ 25-akpm/kernel/softirq.c Mon Nov 29 13:15:52 2004 @@ -152,6 +152,23 @@ void local_bh_enable(void) } EXPORT_SYMBOL(local_bh_enable); +#ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED +# define invoke_softirq() __do_softirq() +#else +# define invoke_softirq() do_softirq() +#endif + +/* + * Exit an interrupt context. Process softirqs if needed and possible: + */ +void irq_exit(void) +{ + preempt_count() -= IRQ_EXIT_OFFSET; + if (!in_interrupt() && local_softirq_pending()) + invoke_softirq(); + preempt_enable_no_resched(); +} + /* * This function must run with irqs disabled! */ _