aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/xtensa/kernel/traps.c')
-rw-r--r--arch/xtensa/kernel/traps.c55
1 files changed, 38 insertions, 17 deletions
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 01e0111bf787..9b5c345d2b4f 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -193,28 +193,49 @@ void do_multihit(struct pt_regs *regs, unsigned long exccause)
193} 193}
194 194
195/* 195/*
196 * Level-1 interrupt. 196 * IRQ handler.
197 * We currently have no priority encoding. 197 * PS.INTLEVEL is the current IRQ priority level.
198 */ 198 */
199 199
200unsigned long ignored_level1_interrupts;
201extern void do_IRQ(int, struct pt_regs *); 200extern void do_IRQ(int, struct pt_regs *);
202 201
203void do_interrupt (struct pt_regs *regs) 202void do_interrupt(struct pt_regs *regs)
204{ 203{
205 unsigned long intread = get_sr (interrupt); 204 static const unsigned int_level_mask[] = {
206 unsigned long intenable = get_sr (intenable); 205 0,
207 int i, mask; 206 XCHAL_INTLEVEL1_MASK,
208 207 XCHAL_INTLEVEL2_MASK,
209 /* Handle all interrupts (no priorities). 208 XCHAL_INTLEVEL3_MASK,
210 * (Clear the interrupt before processing, in case it's 209 XCHAL_INTLEVEL4_MASK,
211 * edge-triggered or software-generated) 210 XCHAL_INTLEVEL5_MASK,
212 */ 211 XCHAL_INTLEVEL6_MASK,
212 XCHAL_INTLEVEL7_MASK,
213 };
214 unsigned level = get_sr(ps) & PS_INTLEVEL_MASK;
215
216 if (WARN_ON_ONCE(level >= ARRAY_SIZE(int_level_mask)))
217 return;
213 218
214 for (i=0, mask = 1; i < XCHAL_NUM_INTERRUPTS; i++, mask <<= 1) { 219 for (;;) {
215 if (mask & (intread & intenable)) { 220 unsigned intread = get_sr(interrupt);
216 set_sr (mask, intclear); 221 unsigned intenable = get_sr(intenable);
217 do_IRQ (i,regs); 222 unsigned int_at_level = intread & intenable &
223 int_level_mask[level];
224
225 if (!int_at_level)
226 return;
227
228 /*
229 * Clear the interrupt before processing, in case it's
230 * edge-triggered or software-generated
231 */
232 while (int_at_level) {
233 unsigned i = __ffs(int_at_level);
234 unsigned mask = 1 << i;
235
236 int_at_level ^= mask;
237 set_sr(mask, intclear);
238 do_IRQ(i, regs);
218 } 239 }
219 } 240 }
220} 241}
@@ -397,7 +418,7 @@ static inline void spill_registers(void)
397 unsigned int a0, ps; 418 unsigned int a0, ps;
398 419
399 __asm__ __volatile__ ( 420 __asm__ __volatile__ (
400 "movi a14, " __stringify(PS_EXCM_BIT | 1) "\n\t" 421 "movi a14, " __stringify(PS_EXCM_BIT | LOCKLEVEL) "\n\t"
401 "mov a12, a0\n\t" 422 "mov a12, a0\n\t"
402 "rsr a13, sar\n\t" 423 "rsr a13, sar\n\t"
403 "xsr a14, ps\n\t" 424 "xsr a14, ps\n\t"