diff options
Diffstat (limited to 'arch/blackfin/kernel/irqchip.c')
-rw-r--r-- | arch/blackfin/kernel/irqchip.c | 114 |
1 files changed, 47 insertions, 67 deletions
diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index 6e31e935bb3..4b5fd36187d 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c @@ -38,38 +38,15 @@ #include <asm/pda.h> static atomic_t irq_err_count; -static spinlock_t irq_controller_lock; - -/* - * Dummy mask/unmask handler - */ -void dummy_mask_unmask_irq(unsigned int irq) -{ -} - void ack_bad_irq(unsigned int irq) { atomic_inc(&irq_err_count); printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq); } -static struct irq_chip bad_chip = { - .ack = dummy_mask_unmask_irq, - .mask = dummy_mask_unmask_irq, - .unmask = dummy_mask_unmask_irq, -}; - -static int bad_stats; static struct irq_desc bad_irq_desc = { - .status = IRQ_DISABLED, - .chip = &bad_chip, .handle_irq = handle_bad_irq, - .depth = 1, .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock), - .kstat_irqs = &bad_stats, -#ifdef CONFIG_SMP - .affinity = CPU_MASK_ALL -#endif }; #ifdef CONFIG_CPUMASK_OFFSTACK @@ -77,6 +54,7 @@ static struct irq_desc bad_irq_desc = { #error "Blackfin architecture does not support CONFIG_CPUMASK_OFFSTACK." #endif +#ifdef CONFIG_PROC_FS int show_interrupts(struct seq_file *p, void *v) { int i = *(loff_t *) v, j; @@ -108,50 +86,29 @@ int show_interrupts(struct seq_file *p, void *v) } return 0; } - -/* - * do_IRQ handles all hardware IRQs. Decoded IRQs should not - * come via this function. Instead, they should provide their - * own 'handler' - */ -#ifdef CONFIG_DO_IRQ_L1 -__attribute__((l1_text)) -#endif -asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) -{ - struct pt_regs *old_regs; - struct irq_desc *desc = irq_desc + irq; -#ifndef CONFIG_IPIPE - unsigned short pending, other_ints; #endif - old_regs = set_irq_regs(regs); - /* - * Some hardware gives randomly wrong interrupts. Rather - * than crashing, do something sensible. - */ - if (irq >= NR_IRQS) - desc = &bad_irq_desc; - - irq_enter(); #ifdef CONFIG_DEBUG_STACKOVERFLOW +static void check_stack_overflow(int irq) +{ /* Debugging check for stack overflow: is there less than STACK_WARN free? */ - { - long sp; - - sp = __get_SP() & (THREAD_SIZE-1); + long sp = __get_SP() & (THREAD_SIZE - 1); - if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) { - dump_stack(); - printk(KERN_EMERG "%s: possible stack overflow while handling irq %i " - " only %ld bytes free\n", - __func__, irq, sp - sizeof(struct thread_info)); - } + if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) { + dump_stack(); + pr_emerg("irq%i: possible stack overflow only %ld bytes free\n", + irq, sp - sizeof(struct thread_info)); } +} +#else +static inline void check_stack_overflow(int irq) { } #endif - generic_handle_irq(irq); #ifndef CONFIG_IPIPE +static void maybe_lower_to_irq14(void) +{ + unsigned short pending, other_ints; + /* * If we're the only interrupt running (ignoring IRQ15 which * is for syscalls), lower our priority to IRQ14 so that @@ -165,7 +122,38 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) other_ints = pending & (pending - 1); if (other_ints == 0) lower_to_irq14(); -#endif /* !CONFIG_IPIPE */ +} +#else +static inline void maybe_lower_to_irq14(void) { } +#endif + +/* + * do_IRQ handles all hardware IRQs. Decoded IRQs should not + * come via this function. Instead, they should provide their + * own 'handler' + */ +#ifdef CONFIG_DO_IRQ_L1 +__attribute__((l1_text)) +#endif +asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) +{ + struct pt_regs *old_regs = set_irq_regs(regs); + + irq_enter(); + + check_stack_overflow(irq); + + /* + * Some hardware gives randomly wrong interrupts. Rather + * than crashing, do something sensible. + */ + if (irq >= NR_IRQS) + handle_bad_irq(irq, &bad_irq_desc); + else + generic_handle_irq(irq); + + maybe_lower_to_irq14(); + irq_exit(); set_irq_regs(old_regs); @@ -173,14 +161,6 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) void __init init_IRQ(void) { - struct irq_desc *desc; - int irq; - - spin_lock_init(&irq_controller_lock); - for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) { - *desc = bad_irq_desc; - } - init_arch_irq(); #ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND |