diff -upN reference/arch/i386/Kconfig current/arch/i386/Kconfig --- reference/arch/i386/Kconfig 2004-04-29 10:39:06.000000000 -0700 +++ current/arch/i386/Kconfig 2004-04-29 10:39:07.000000000 -0700 @@ -1497,6 +1497,9 @@ config MAGIC_SYSRQ depends on KGDB_SYSRQ default y +config 4KSTACKS + def_bool y + config X86_FIND_SMP_CONFIG bool depends on X86_LOCAL_APIC || X86_VOYAGER diff -upN reference/arch/i386/Makefile current/arch/i386/Makefile --- reference/arch/i386/Makefile 2004-04-29 10:39:02.000000000 -0700 +++ current/arch/i386/Makefile 2004-04-29 10:39:07.000000000 -0700 @@ -56,9 +56,9 @@ cflags-$(CONFIG_X86_ELAN) += -march=i486 GCC_VERSION := $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC)) cflags-$(CONFIG_REGPARM) += $(shell if [ $(GCC_VERSION) -ge 0300 ] ; then echo "-mregparm=3"; fi ;) -# Enable unit-at-a-time mode when possible. It shrinks the -# kernel considerably. -CFLAGS += $(call check_gcc,-funit-at-a-time,) +# Disable unit-at-a-time mode, it makes gcc use a lot more stack +# due to the lack of sharing of stacklots. +CFLAGS += $(call check_gcc,-fno-unit-at-a-time,) CFLAGS += $(cflags-y) diff -upN reference/arch/i386/kernel/i8259.c current/arch/i386/kernel/i8259.c --- reference/arch/i386/kernel/i8259.c 2004-03-11 14:33:36.000000000 -0800 +++ current/arch/i386/kernel/i8259.c 2004-04-29 10:39:07.000000000 -0700 @@ -444,4 +444,7 @@ void __init init_IRQ(void) */ if (boot_cpu_data.hard_math && !cpu_has_fpu) setup_irq(FPU_IRQ, &fpu_irq); + + current_thread_info()->cpu = 0; + irq_ctx_init(0); } diff -upN reference/arch/i386/kernel/irq.c current/arch/i386/kernel/irq.c --- reference/arch/i386/kernel/irq.c 2004-04-29 10:39:04.000000000 -0700 +++ current/arch/i386/kernel/irq.c 2004-04-29 10:39:07.000000000 -0700 @@ -75,6 +75,14 @@ irq_desc_t irq_desc[NR_IRQS] __cacheline static void register_irq_proc (unsigned int irq); /* + * per-CPU IRQ handling stacks + */ +#ifdef CONFIG_4KSTACKS +union irq_ctx *hardirq_ctx[NR_CPUS]; +union irq_ctx *softirq_ctx[NR_CPUS]; +#endif + +/* * Special irq handlers. */ @@ -213,7 +221,7 @@ inline void synchronize_irq(unsigned int * waste of time and is not what some drivers would * prefer. */ -int handle_IRQ_event(unsigned int irq, +asmlinkage int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, struct irqaction *action) { int status = 1; /* Force the "do bottom halves" bit */ @@ -436,7 +444,7 @@ asmlinkage unsigned int do_IRQ(struct pt __asm__ __volatile__("andl %%esp,%0" : "=r" (esp) : "0" (THREAD_SIZE - 1)); - if (unlikely(esp < (sizeof(struct thread_info) + 1024))) { + if (unlikely(esp < (sizeof(struct thread_info) + STACK_WARN))) { printk("do_IRQ: stack overflow: %ld\n", esp - sizeof(struct thread_info)); dump_stack(); @@ -484,11 +492,68 @@ asmlinkage unsigned int do_IRQ(struct pt * useful for irq hardware that does not mask cleanly in an * SMP environment. */ +#ifdef CONFIG_4KSTACKS + + for (;;) { + irqreturn_t action_ret; + u32 *isp; + union irq_ctx * curctx; + union irq_ctx * irqctx; + + curctx = (union irq_ctx *) current_thread_info(); + irqctx = hardirq_ctx[smp_processor_id()]; + + spin_unlock(&desc->lock); + + /* + * this is where we switch to the IRQ stack. However, if we are already using + * the IRQ stack (because we interrupted a hardirq handler) we can't do that + * and just have to keep using the current stack (which is the irq stack already + * after all) + */ + + if (curctx == irqctx) + action_ret = handle_IRQ_event(irq, ®s, action); + else { + /* build the stack frame on the IRQ stack */ + isp = (u32*) ((char*)irqctx + sizeof(*irqctx)); + irqctx->tinfo.task = curctx->tinfo.task; + irqctx->tinfo.previous_esp = current_stack_pointer(); + + *--isp = (u32) action; + *--isp = (u32) ®s; + *--isp = (u32) irq; + + asm volatile( + " xchgl %%ebx,%%esp \n" + " call handle_IRQ_event \n" + " xchgl %%ebx,%%esp \n" + : "=a"(action_ret) + : "b"(isp) + : "memory", "cc", "edx", "ecx" + ); + + + } + spin_lock(&desc->lock); + if (!noirqdebug) + note_interrupt(irq, desc, action_ret); + if (curctx != irqctx) + irqctx->tinfo.task = NULL; + if (likely(!(desc->status & IRQ_PENDING))) + break; + desc->status &= ~IRQ_PENDING; + } + +#else + for (;;) { irqreturn_t action_ret; spin_unlock(&desc->lock); + action_ret = handle_IRQ_event(irq, ®s, action); + spin_lock(&desc->lock); if (!noirqdebug) note_interrupt(irq, desc, action_ret); @@ -496,6 +561,7 @@ asmlinkage unsigned int do_IRQ(struct pt break; desc->status &= ~IRQ_PENDING; } +#endif desc->status &= ~IRQ_INPROGRESS; out: @@ -1055,3 +1121,79 @@ void init_irq_proc (void) register_irq_proc(i); } + +#ifdef CONFIG_4KSTACKS +static char softirq_stack[NR_CPUS * THREAD_SIZE] __attribute__((__aligned__(THREAD_SIZE))); +static char hardirq_stack[NR_CPUS * THREAD_SIZE] __attribute__((__aligned__(THREAD_SIZE))); + +/* + * allocate per-cpu stacks for hardirq and for softirq processing + */ +void irq_ctx_init(int cpu) +{ + union irq_ctx *irqctx; + + if (hardirq_ctx[cpu]) + return; + + irqctx = (union irq_ctx*) &hardirq_stack[cpu*THREAD_SIZE]; + irqctx->tinfo.task = NULL; + irqctx->tinfo.exec_domain = NULL; + irqctx->tinfo.cpu = cpu; + irqctx->tinfo.preempt_count = HARDIRQ_OFFSET; + irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); + + hardirq_ctx[cpu] = irqctx; + + irqctx = (union irq_ctx*) &softirq_stack[cpu*THREAD_SIZE]; + irqctx->tinfo.task = NULL; + irqctx->tinfo.exec_domain = NULL; + irqctx->tinfo.cpu = cpu; + irqctx->tinfo.preempt_count = SOFTIRQ_OFFSET; + irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); + + softirq_ctx[cpu] = irqctx; + + printk("CPU %u irqstacks, hard=%p soft=%p\n", + cpu,hardirq_ctx[cpu],softirq_ctx[cpu]); +} + +extern asmlinkage void __do_softirq(void); + +asmlinkage void do_softirq(void) +{ + unsigned long flags; + struct thread_info *curctx; + union irq_ctx *irqctx; + u32 *isp; + + if (in_interrupt()) + return; + + local_irq_save(flags); + + if (local_softirq_pending()) { + curctx = current_thread_info(); + irqctx = softirq_ctx[smp_processor_id()]; + irqctx->tinfo.task = curctx->task; + irqctx->tinfo.previous_esp = current_stack_pointer(); + + /* build the stack frame on the softirq stack */ + isp = (u32*) ((char*)irqctx + sizeof(*irqctx)); + + + asm volatile( + " xchgl %%ebx,%%esp \n" + " call __do_softirq \n" + " movl %%ebx,%%esp \n" + : "=b"(isp) + : "0"(isp) + : "memory", "cc", "edx", "ecx", "eax" + ); + } + + local_irq_restore(flags); +} + +EXPORT_SYMBOL(do_softirq); +#endif diff -upN reference/arch/i386/kernel/smpboot.c current/arch/i386/kernel/smpboot.c --- reference/arch/i386/kernel/smpboot.c 2004-04-29 10:39:06.000000000 -0700 +++ current/arch/i386/kernel/smpboot.c 2004-04-29 10:39:07.000000000 -0700 @@ -816,6 +816,8 @@ static int __init do_boot_cpu(int apicid /* Stack for startup_32 can be just as for start_secondary onwards */ stack_start.esp = (void *) idle->thread.esp; + irq_ctx_init(cpu); + /* * This grunge runs the startup process for * the targeted processor. diff -upN reference/arch/i386/kernel/traps.c current/arch/i386/kernel/traps.c --- reference/arch/i386/kernel/traps.c 2004-04-29 10:39:06.000000000 -0700 +++ current/arch/i386/kernel/traps.c 2004-04-29 10:39:07.000000000 -0700 @@ -141,12 +141,20 @@ void show_trace(struct task_struct *task #ifdef CONFIG_KALLSYMS printk("\n"); #endif - while (!kstack_end(stack)) { - addr = *stack++; - if (kernel_text_address(addr)) { - printk(" [<%08lx>] ", addr); - print_symbol("%s\n", addr); + while (1) { + struct thread_info *context; + context = (struct thread_info*) ((unsigned long)stack & (~(THREAD_SIZE - 1))); + while (!kstack_end(stack)) { + addr = *stack++; + if (kernel_text_address(addr)) { + printk(" [<%08lx>] ", addr); + print_symbol("%s\n", addr); + } } + stack = (unsigned long*)context->previous_esp; + if (!stack) + break; + printk(" =======================\n"); } printk("\n"); } diff -upN reference/include/asm-alpha/irq.h current/include/asm-alpha/irq.h --- reference/include/asm-alpha/irq.h 2003-10-01 11:35:30.000000000 -0700 +++ current/include/asm-alpha/irq.h 2004-04-29 10:39:07.000000000 -0700 @@ -93,5 +93,8 @@ extern void enable_irq(unsigned int); struct pt_regs; extern void (*perf_irq)(unsigned long, struct pt_regs *); +struct irqaction; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _ALPHA_IRQ_H */ diff -upN reference/include/asm-arm/irq.h current/include/asm-arm/irq.h --- reference/include/asm-arm/irq.h 2003-06-05 14:39:14.000000000 -0700 +++ current/include/asm-arm/irq.h 2004-04-29 10:39:07.000000000 -0700 @@ -44,5 +44,9 @@ void disable_irq_wake(unsigned int irq); void enable_irq_wake(unsigned int irq); int setup_irq(unsigned int, struct irqaction *); +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif diff -upN reference/include/asm-arm26/irq.h current/include/asm-arm26/irq.h --- reference/include/asm-arm26/irq.h 2003-06-19 14:41:50.000000000 -0700 +++ current/include/asm-arm26/irq.h 2004-04-29 10:39:07.000000000 -0700 @@ -45,6 +45,8 @@ extern void enable_irq(unsigned int); int set_irq_type(unsigned int irq, unsigned int type); int setup_irq(unsigned int, struct irqaction *); +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); #endif diff -upN reference/include/asm-cris/irq.h current/include/asm-cris/irq.h --- reference/include/asm-cris/irq.h 2003-07-28 15:31:10.000000000 -0700 +++ current/include/asm-cris/irq.h 2004-04-29 10:39:07.000000000 -0700 @@ -14,6 +14,10 @@ extern void enable_irq(unsigned int); #define disable_irq_nosync disable_irq #define enable_irq_nosync enable_irq +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _ASM_IRQ_H */ diff -upN reference/include/asm-h8300/irq.h current/include/asm-h8300/irq.h --- reference/include/asm-h8300/irq.h 2004-04-07 14:54:32.000000000 -0700 +++ current/include/asm-h8300/irq.h 2004-04-29 10:39:07.000000000 -0700 @@ -68,4 +68,8 @@ extern void disable_irq(unsigned int); #define enable_irq_nosync(x) enable_irq(x) #define disable_irq_nosync(x) disable_irq(x) +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _H8300_IRQ_H_ */ diff -upN reference/include/asm-i386/irq.h current/include/asm-i386/irq.h --- reference/include/asm-i386/irq.h 2004-01-15 10:41:17.000000000 -0800 +++ current/include/asm-i386/irq.h 2004-04-29 10:39:07.000000000 -0700 @@ -14,6 +14,7 @@ #include /* include comes from machine specific directory */ #include "irq_vectors.h" +#include static __inline__ int irq_canonicalize(int irq) { @@ -30,4 +31,28 @@ extern int can_request_irq(unsigned int, #define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */ #endif +#ifdef CONFIG_4KSTACKS +/* + * per-CPU IRQ handling contexts (thread information and stack) + */ +union irq_ctx { + struct thread_info tinfo; + u32 stack[THREAD_SIZE/sizeof(u32)]; +}; + +extern union irq_ctx *hardirq_ctx[NR_CPUS]; +extern union irq_ctx *softirq_ctx[NR_CPUS]; + +extern void irq_ctx_init(int cpu); + +#define __ARCH_HAS_DO_SOFTIRQ +#else +#define irq_ctx_init(cpu) do { ; } while (0) +#endif + +struct irqaction; +struct pt_regs; +asmlinkage int handle_IRQ_event(unsigned int, struct pt_regs *, + struct irqaction *); + #endif /* _ASM_IRQ_H */ diff -upN reference/include/asm-i386/module.h current/include/asm-i386/module.h --- reference/include/asm-i386/module.h 2004-04-07 14:54:32.000000000 -0700 +++ current/include/asm-i386/module.h 2004-04-29 10:39:07.000000000 -0700 @@ -60,6 +60,12 @@ struct mod_arch_specific #define MODULE_REGPARM "" #endif -#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_REGPARM +#ifdef CONFIG_4KSTACKS +#define MODULE_STACKSIZE "4KSTACKS " +#else +#define MODULE_STACKSIZE "" +#endif + +#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_REGPARM MODULE_STACKSIZE #endif /* _ASM_I386_MODULE_H */ diff -upN reference/include/asm-i386/thread_info.h current/include/asm-i386/thread_info.h --- reference/include/asm-i386/thread_info.h 2004-03-11 14:35:15.000000000 -0800 +++ current/include/asm-i386/thread_info.h 2004-04-29 10:39:07.000000000 -0700 @@ -9,6 +9,9 @@ #ifdef __KERNEL__ +#include +#include + #ifndef __ASSEMBLY__ #include #endif @@ -29,12 +32,16 @@ struct thread_info { __u32 cpu; /* current CPU */ __s32 preempt_count; /* 0 => preemptable, <0 => BUG */ + mm_segment_t addr_limit; /* thread address space: 0-0xBFFFFFFF for user-thead 0-0xFFFFFFFF for kernel-thread */ struct restart_block restart_block; + unsigned long previous_esp; /* ESP of the previous stack in case + of nested (IRQ) stacks + */ __u8 supervisor_stack[0]; }; @@ -53,7 +60,13 @@ struct thread_info { #endif #define PREEMPT_ACTIVE 0x4000000 +#ifdef CONFIG_4KSTACKS +#define THREAD_SIZE (4096) +#else +#define THREAD_SIZE (8192) +#endif +#define STACK_WARN (THREAD_SIZE/8) /* * macros/functions for gaining access to the thread information structure * @@ -77,7 +90,6 @@ struct thread_info { #define init_thread_info (init_thread_union.thread_info) #define init_stack (init_thread_union.stack) -#define THREAD_SIZE (2*PAGE_SIZE) /* how to get the thread information struct from C */ static inline struct thread_info *current_thread_info(void) @@ -87,6 +99,14 @@ static inline struct thread_info *curren return ti; } +/* how to get the current stack pointer from C */ +static inline unsigned long current_stack_pointer(void) +{ + unsigned long ti; + __asm__("movl %%esp,%0; ":"=r" (ti) : ); + return ti; +} + /* thread information allocation */ #ifdef CONFIG_DEBUG_STACK_USAGE #define alloc_thread_info(tsk) \ @@ -108,8 +128,6 @@ static inline struct thread_info *curren #else /* !__ASSEMBLY__ */ -#define THREAD_SIZE 8192 - /* how to get the thread information struct from ASM */ #define GET_THREAD_INFO(reg) \ movl $-THREAD_SIZE, reg; \ diff -upN reference/include/asm-ia64/irq.h current/include/asm-ia64/irq.h --- reference/include/asm-ia64/irq.h 2003-06-05 14:39:17.000000000 -0700 +++ current/include/asm-ia64/irq.h 2004-04-29 10:39:07.000000000 -0700 @@ -29,4 +29,8 @@ extern void disable_irq_nosync (unsigned extern void enable_irq (unsigned int); extern void set_irq_affinity_info (unsigned int irq, int dest, int redir); +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _ASM_IA64_IRQ_H */ diff -upN reference/include/asm-m68k/irq.h current/include/asm-m68k/irq.h --- reference/include/asm-m68k/irq.h 2004-04-07 14:54:33.000000000 -0700 +++ current/include/asm-m68k/irq.h 2004-04-29 10:39:07.000000000 -0700 @@ -124,4 +124,8 @@ extern volatile unsigned int num_spuriou */ extern irq_node_t *new_irq_node(void); +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _M68K_IRQ_H_ */ diff -upN reference/include/asm-m68knommu/irq.h current/include/asm-m68knommu/irq.h --- reference/include/asm-m68knommu/irq.h 2004-03-11 14:35:16.000000000 -0800 +++ current/include/asm-m68knommu/irq.h 2004-04-29 10:39:07.000000000 -0700 @@ -121,4 +121,8 @@ extern irq_node_t *new_irq_node(void); #define enable_irq_nosync(x) enable_irq(x) #define disable_irq_nosync(x) disable_irq(x) +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _M68K_IRQ_H_ */ diff -upN reference/include/asm-mips/irq.h current/include/asm-mips/irq.h --- reference/include/asm-mips/irq.h 2004-03-11 14:35:18.000000000 -0800 +++ current/include/asm-mips/irq.h 2004-04-29 10:39:07.000000000 -0700 @@ -31,4 +31,7 @@ extern asmlinkage unsigned int do_IRQ(in extern void init_generic_irq(void); +struct irqaction; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _ASM_IRQ_H */ diff -upN reference/include/asm-parisc/irq.h current/include/asm-parisc/irq.h --- reference/include/asm-parisc/irq.h 2003-10-14 15:50:33.000000000 -0700 +++ current/include/asm-parisc/irq.h 2004-04-29 10:39:07.000000000 -0700 @@ -96,4 +96,7 @@ extern unsigned long txn_alloc_addr(int) /* soft power switch support (power.c) */ extern struct tasklet_struct power_tasklet; +struct irqaction; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _ASM_PARISC_IRQ_H */ diff -upN reference/include/asm-ppc/irq.h current/include/asm-ppc/irq.h --- reference/include/asm-ppc/irq.h 2003-10-01 11:48:23.000000000 -0700 +++ current/include/asm-ppc/irq.h 2004-04-29 10:39:07.000000000 -0700 @@ -211,5 +211,9 @@ extern unsigned long ppc_cached_irq_mask extern unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; extern atomic_t ppc_n_lost_interrupts; +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _ASM_IRQ_H */ #endif /* __KERNEL__ */ diff -upN reference/include/asm-ppc64/irq.h current/include/asm-ppc64/irq.h --- reference/include/asm-ppc64/irq.h 2004-03-11 14:35:23.000000000 -0800 +++ current/include/asm-ppc64/irq.h 2004-04-29 10:39:08.000000000 -0700 @@ -48,5 +48,9 @@ static __inline__ int irq_canonicalize(i #define NR_MASK_WORDS ((NR_IRQS + 63) / 64) +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _ASM_IRQ_H */ #endif /* __KERNEL__ */ diff -upN reference/include/asm-s390/irq.h current/include/asm-s390/irq.h --- reference/include/asm-s390/irq.h 2003-07-28 15:33:24.000000000 -0700 +++ current/include/asm-s390/irq.h 2004-04-29 10:39:08.000000000 -0700 @@ -21,6 +21,10 @@ enum interruption_class { #define touch_nmi_watchdog() do { } while(0) +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* __KERNEL__ */ #endif diff -upN reference/include/asm-sh/irq.h current/include/asm-sh/irq.h --- reference/include/asm-sh/irq.h 2004-04-07 14:54:34.000000000 -0700 +++ current/include/asm-sh/irq.h 2004-04-29 10:39:08.000000000 -0700 @@ -329,4 +329,8 @@ static inline int generic_irq_demux(int #define irq_canonicalize(irq) (irq) #define irq_demux(irq) __irq_demux(sh_mv.mv_irq_demux(irq)) +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* __ASM_SH_IRQ_H */ diff -upN reference/include/asm-sparc/irq.h current/include/asm-sparc/irq.h --- reference/include/asm-sparc/irq.h 2003-10-21 11:16:12.000000000 -0700 +++ current/include/asm-sparc/irq.h 2004-04-29 10:39:08.000000000 -0700 @@ -184,4 +184,8 @@ extern struct sun4m_intregs *sun4m_inter #define SUN4M_INT_SBUS(x) (1 << (x+7)) #define SUN4M_INT_VME(x) (1 << (x)) +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif diff -upN reference/include/asm-sparc64/irq.h current/include/asm-sparc64/irq.h --- reference/include/asm-sparc64/irq.h 2003-10-01 11:41:16.000000000 -0700 +++ current/include/asm-sparc64/irq.h 2004-04-29 10:39:08.000000000 -0700 @@ -150,4 +150,8 @@ static __inline__ unsigned long get_soft return retval; } +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif diff -upN reference/include/asm-um/irq.h current/include/asm-um/irq.h --- reference/include/asm-um/irq.h 2002-12-09 18:46:25.000000000 -0800 +++ current/include/asm-um/irq.h 2004-04-29 10:39:08.000000000 -0700 @@ -32,4 +32,9 @@ extern int um_request_irq(unsigned int i void (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id); + +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif diff -upN reference/include/asm-v850/irq.h current/include/asm-v850/irq.h --- reference/include/asm-v850/irq.h 2003-06-05 14:39:21.000000000 -0700 +++ current/include/asm-v850/irq.h 2004-04-29 10:39:08.000000000 -0700 @@ -65,4 +65,8 @@ extern void disable_irq_nosync (unsigned #endif /* !__ASSEMBLY__ */ +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* __V850_IRQ_H__ */ diff -upN reference/include/asm-x86_64/irq.h current/include/asm-x86_64/irq.h --- reference/include/asm-x86_64/irq.h 2004-01-15 10:41:18.000000000 -0800 +++ current/include/asm-x86_64/irq.h 2004-04-29 10:39:08.000000000 -0700 @@ -53,4 +53,8 @@ extern int can_request_irq(unsigned int, #define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */ #endif +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _ASM_IRQ_H */ diff -upN reference/include/linux/compiler-gcc3.h current/include/linux/compiler-gcc3.h --- reference/include/linux/compiler-gcc3.h 2004-03-11 14:35:28.000000000 -0800 +++ current/include/linux/compiler-gcc3.h 2004-04-29 10:39:08.000000000 -0700 @@ -3,7 +3,7 @@ /* These definitions are for GCC v3.x. */ #include -#if __GNUC_MINOR__ >= 1 +#if __GNUC_MINOR__ >= 1 && __GNUC_MINOR__ < 4 # define inline __inline__ __attribute__((always_inline)) # define __inline__ __inline__ __attribute__((always_inline)) # define __inline __inline__ __attribute__((always_inline)) diff -upN reference/include/linux/irq.h current/include/linux/irq.h --- reference/include/linux/irq.h 2003-10-01 11:41:17.000000000 -0700 +++ current/include/linux/irq.h 2004-04-29 10:39:08.000000000 -0700 @@ -71,7 +71,6 @@ extern irq_desc_t irq_desc [NR_IRQS]; #include /* the arch dependent stuff */ -extern int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); extern int setup_irq(unsigned int , struct irqaction * ); extern hw_irq_controller no_irq_type; /* needed in every arch ? */ diff -upN reference/kernel/softirq.c current/kernel/softirq.c --- reference/kernel/softirq.c 2004-04-07 14:54:37.000000000 -0700 +++ current/kernel/softirq.c 2004-04-29 10:39:08.000000000 -0700 @@ -16,6 +16,7 @@ #include #include +#include /* - No shared variables, all the data are CPU local. - If a softirq needs serialization, let it serialize itself @@ -69,53 +70,66 @@ static inline void wakeup_softirqd(void) */ #define MAX_SOFTIRQ_RESTART 10 -asmlinkage void do_softirq(void) +asmlinkage void __do_softirq(void) { - int max_restart = MAX_SOFTIRQ_RESTART; + struct softirq_action *h; __u32 pending; - unsigned long flags; + int max_restart = MAX_SOFTIRQ_RESTART; - if (in_interrupt()) - return; + pending = local_softirq_pending(); - local_irq_save(flags); + local_bh_disable(); +restart: + /* Reset the pending bitmask before enabling irqs */ + local_softirq_pending() = 0; + + local_irq_enable(); + + h = softirq_vec; + + do { + if (pending & 1) + h->action(h); + h++; + pending >>= 1; + } while (pending); + + local_irq_disable(); pending = local_softirq_pending(); + if (pending && --max_restart) + goto restart; - if (pending) { - struct softirq_action *h; + if (pending) + wakeup_softirqd(); - local_bh_disable(); -restart: - /* Reset the pending bitmask before enabling irqs */ - local_softirq_pending() = 0; + __local_bh_enable(); +} - local_irq_enable(); +#ifndef __ARCH_HAS_DO_SOFTIRQ + +asmlinkage void do_softirq(void) +{ + __u32 pending; + unsigned long flags; - h = softirq_vec; + if (in_interrupt()) + return; - do { - if (pending & 1) - h->action(h); - h++; - pending >>= 1; - } while (pending); + local_irq_save(flags); - local_irq_disable(); + pending = local_softirq_pending(); - pending = local_softirq_pending(); - if (pending && --max_restart) - goto restart; - if (pending) - wakeup_softirqd(); - __local_bh_enable(); - } + if (pending) + __do_softirq(); local_irq_restore(flags); } EXPORT_SYMBOL(do_softirq); +#endif + void local_bh_enable(void) { __local_bh_enable();