xtensa: clean up do_interrupt/do_IRQ
- set up irq registers and call irq_enter/irq_exit once for each kernel
entry due to interrupt;
- don't attempt to clear current IRQ in the do_interrupt, IRQ handler
will take care of it;
- find pending interrupt with highest priority before every ISR
invocation.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Chris Zankel <chris@zankel.net>
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c
index ada1e48..3cef58e 100644
--- a/arch/xtensa/kernel/irq.c
+++ b/arch/xtensa/kernel/irq.c
@@ -30,7 +30,6 @@
asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs)
{
- struct pt_regs *old_regs = set_irq_regs(regs);
int irq = irq_find_mapping(NULL, hwirq);
if (hwirq >= NR_IRQS) {
@@ -38,8 +37,6 @@
__func__, hwirq);
}
- irq_enter();
-
#ifdef CONFIG_DEBUG_STACKOVERFLOW
/* Debugging check for stack overflow: is there less than 1KB free? */
{
@@ -54,9 +51,6 @@
}
#endif
generic_handle_irq(irq);
-
- irq_exit();
- set_irq_regs(old_regs);
}
int arch_show_interrupts(struct seq_file *p, int prec)
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 3e8a05c..3dbe864 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -212,6 +212,9 @@
XCHAL_INTLEVEL6_MASK,
XCHAL_INTLEVEL7_MASK,
};
+ struct pt_regs *old_regs = set_irq_regs(regs);
+
+ irq_enter();
for (;;) {
unsigned intread = get_sr(interrupt);
@@ -227,21 +230,13 @@
}
if (level == 0)
- return;
+ break;
- /*
- * Clear the interrupt before processing, in case it's
- * edge-triggered or software-generated
- */
- while (int_at_level) {
- unsigned i = __ffs(int_at_level);
- unsigned mask = 1 << i;
-
- int_at_level ^= mask;
- set_sr(mask, intclear);
- do_IRQ(i, regs);
- }
+ do_IRQ(__ffs(int_at_level), regs);
}
+
+ irq_exit();
+ set_irq_regs(old_regs);
}
/*