aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/irqchip.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/kernel/irqchip.c')
-rw-r--r--arch/blackfin/kernel/irqchip.c114
1 files changed, 47 insertions, 67 deletions
diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c
index 6e31e935bb31..4b5fd36187d9 100644
--- a/arch/blackfin/kernel/irqchip.c
+++ b/arch/blackfin/kernel/irqchip.c
@@ -38,38 +38,15 @@
38#include <asm/pda.h> 38#include <asm/pda.h>
39 39
40static atomic_t irq_err_count; 40static atomic_t irq_err_count;
41static spinlock_t irq_controller_lock;
42
43/*
44 * Dummy mask/unmask handler
45 */
46void dummy_mask_unmask_irq(unsigned int irq)
47{
48}
49
50void ack_bad_irq(unsigned int irq) 41void ack_bad_irq(unsigned int irq)
51{ 42{
52 atomic_inc(&irq_err_count); 43 atomic_inc(&irq_err_count);
53 printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq); 44 printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq);
54} 45}
55 46
56static struct irq_chip bad_chip = {
57 .ack = dummy_mask_unmask_irq,
58 .mask = dummy_mask_unmask_irq,
59 .unmask = dummy_mask_unmask_irq,
60};
61
62static int bad_stats;
63static struct irq_desc bad_irq_desc = { 47static struct irq_desc bad_irq_desc = {
64 .status = IRQ_DISABLED,
65 .chip = &bad_chip,
66 .handle_irq = handle_bad_irq, 48 .handle_irq = handle_bad_irq,
67 .depth = 1,
68 .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock), 49 .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock),
69 .kstat_irqs = &bad_stats,
70#ifdef CONFIG_SMP
71 .affinity = CPU_MASK_ALL
72#endif
73}; 50};
74 51
75#ifdef CONFIG_CPUMASK_OFFSTACK 52#ifdef CONFIG_CPUMASK_OFFSTACK
@@ -77,6 +54,7 @@ static struct irq_desc bad_irq_desc = {
77#error "Blackfin architecture does not support CONFIG_CPUMASK_OFFSTACK." 54#error "Blackfin architecture does not support CONFIG_CPUMASK_OFFSTACK."
78#endif 55#endif
79 56
57#ifdef CONFIG_PROC_FS
80int show_interrupts(struct seq_file *p, void *v) 58int show_interrupts(struct seq_file *p, void *v)
81{ 59{
82 int i = *(loff_t *) v, j; 60 int i = *(loff_t *) v, j;
@@ -108,50 +86,29 @@ int show_interrupts(struct seq_file *p, void *v)
108 } 86 }
109 return 0; 87 return 0;
110} 88}
111
112/*
113 * do_IRQ handles all hardware IRQs. Decoded IRQs should not
114 * come via this function. Instead, they should provide their
115 * own 'handler'
116 */
117#ifdef CONFIG_DO_IRQ_L1
118__attribute__((l1_text))
119#endif
120asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
121{
122 struct pt_regs *old_regs;
123 struct irq_desc *desc = irq_desc + irq;
124#ifndef CONFIG_IPIPE
125 unsigned short pending, other_ints;
126#endif 89#endif
127 old_regs = set_irq_regs(regs);
128 90
129 /*
130 * Some hardware gives randomly wrong interrupts. Rather
131 * than crashing, do something sensible.
132 */
133 if (irq >= NR_IRQS)
134 desc = &bad_irq_desc;
135
136 irq_enter();
137#ifdef CONFIG_DEBUG_STACKOVERFLOW 91#ifdef CONFIG_DEBUG_STACKOVERFLOW
92static void check_stack_overflow(int irq)
93{
138 /* Debugging check for stack overflow: is there less than STACK_WARN free? */ 94 /* Debugging check for stack overflow: is there less than STACK_WARN free? */
139 { 95 long sp = __get_SP() & (THREAD_SIZE - 1);
140 long sp;
141
142 sp = __get_SP() & (THREAD_SIZE-1);
143 96
144 if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) { 97 if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
145 dump_stack(); 98 dump_stack();
146 printk(KERN_EMERG "%s: possible stack overflow while handling irq %i " 99 pr_emerg("irq%i: possible stack overflow only %ld bytes free\n",
147 " only %ld bytes free\n", 100 irq, sp - sizeof(struct thread_info));
148 __func__, irq, sp - sizeof(struct thread_info));
149 }
150 } 101 }
102}
103#else
104static inline void check_stack_overflow(int irq) { }
151#endif 105#endif
152 generic_handle_irq(irq);
153 106
154#ifndef CONFIG_IPIPE 107#ifndef CONFIG_IPIPE
108static void maybe_lower_to_irq14(void)
109{
110 unsigned short pending, other_ints;
111
155 /* 112 /*
156 * If we're the only interrupt running (ignoring IRQ15 which 113 * If we're the only interrupt running (ignoring IRQ15 which
157 * is for syscalls), lower our priority to IRQ14 so that 114 * 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)
165 other_ints = pending & (pending - 1); 122 other_ints = pending & (pending - 1);
166 if (other_ints == 0) 123 if (other_ints == 0)
167 lower_to_irq14(); 124 lower_to_irq14();
168#endif /* !CONFIG_IPIPE */ 125}
126#else
127static inline void maybe_lower_to_irq14(void) { }
128#endif
129
130/*
131 * do_IRQ handles all hardware IRQs. Decoded IRQs should not
132 * come via this function. Instead, they should provide their
133 * own 'handler'
134 */
135#ifdef CONFIG_DO_IRQ_L1
136__attribute__((l1_text))
137#endif
138asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
139{
140 struct pt_regs *old_regs = set_irq_regs(regs);
141
142 irq_enter();
143
144 check_stack_overflow(irq);
145
146 /*
147 * Some hardware gives randomly wrong interrupts. Rather
148 * than crashing, do something sensible.
149 */
150 if (irq >= NR_IRQS)
151 handle_bad_irq(irq, &bad_irq_desc);
152 else
153 generic_handle_irq(irq);
154
155 maybe_lower_to_irq14();
156
169 irq_exit(); 157 irq_exit();
170 158
171 set_irq_regs(old_regs); 159 set_irq_regs(old_regs);
@@ -173,14 +161,6 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
173 161
174void __init init_IRQ(void) 162void __init init_IRQ(void)
175{ 163{
176 struct irq_desc *desc;
177 int irq;
178
179 spin_lock_init(&irq_controller_lock);
180 for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) {
181 *desc = bad_irq_desc;
182 }
183
184 init_arch_irq(); 164 init_arch_irq();
185 165
186#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND 166#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND