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 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 | ||
40 | static atomic_t irq_err_count; | 40 | static atomic_t irq_err_count; |
41 | static spinlock_t irq_controller_lock; | ||
42 | |||
43 | /* | ||
44 | * Dummy mask/unmask handler | ||
45 | */ | ||
46 | void dummy_mask_unmask_irq(unsigned int irq) | ||
47 | { | ||
48 | } | ||
49 | |||
50 | void ack_bad_irq(unsigned int irq) | 41 | void 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 | ||
56 | static 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 | |||
62 | static int bad_stats; | ||
63 | static struct irq_desc bad_irq_desc = { | 47 | static 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 | ||
80 | int show_interrupts(struct seq_file *p, void *v) | 58 | int 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 | ||
120 | asmlinkage 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 |
92 | static 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 | ||
104 | static 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 |
108 | static 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 | ||
127 | static 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 | ||
138 | asmlinkage 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 | ||
174 | void __init init_IRQ(void) | 162 | void __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 |