in kernel/traps.c [260:307]
void do_interrupt(struct pt_regs *regs)
{
static const unsigned int_level_mask[] = {
0,
XCHAL_INTLEVEL1_MASK,
XCHAL_INTLEVEL2_MASK,
XCHAL_INTLEVEL3_MASK,
XCHAL_INTLEVEL4_MASK,
XCHAL_INTLEVEL5_MASK,
XCHAL_INTLEVEL6_MASK,
XCHAL_INTLEVEL7_MASK,
};
struct pt_regs *old_regs;
unsigned unhandled = ~0u;
trace_hardirqs_off();
old_regs = set_irq_regs(regs);
irq_enter();
for (;;) {
unsigned intread = xtensa_get_sr(interrupt);
unsigned intenable = xtensa_get_sr(intenable);
unsigned int_at_level = intread & intenable;
unsigned level;
for (level = LOCKLEVEL; level > 0; --level) {
if (int_at_level & int_level_mask[level]) {
int_at_level &= int_level_mask[level];
if (int_at_level & unhandled)
int_at_level &= unhandled;
else
unhandled |= int_level_mask[level];
break;
}
}
if (level == 0)
break;
/* clear lowest pending irq in the unhandled mask */
unhandled ^= (int_at_level & -int_at_level);
do_IRQ(__ffs(int_at_level), regs);
}
irq_exit();
set_irq_regs(old_regs);
}