diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2013-10-17 02:42:23 +0400 |
---|---|---|
committer | Chris Zankel <chris@zankel.net> | 2014-01-14 10:19:57 -0800 |
commit | 996232393bcdfff49de31e1bc1c431fd8bce9ccb (patch) | |
tree | 96cb815dfb70ff3a9c8b07afdbc5f0b3a71fdb95 /arch/xtensa | |
parent | cbd1de2e8e46207cead11034f92ea8a018b11189 (diff) |
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>
Diffstat (limited to 'arch/xtensa')
-rw-r--r-- | arch/xtensa/kernel/irq.c | 6 | ||||
-rw-r--r-- | arch/xtensa/kernel/traps.c | 23 |
2 files changed, 9 insertions, 20 deletions
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c index ada1e4893dd..3cef58e2833 100644 --- a/arch/xtensa/kernel/irq.c +++ b/arch/xtensa/kernel/irq.c @@ -30,7 +30,6 @@ atomic_t irq_err_count; 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 @@ asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs) __func__, hwirq); } - irq_enter(); - #ifdef CONFIG_DEBUG_STACKOVERFLOW /* Debugging check for stack overflow: is there less than 1KB free? */ { @@ -54,9 +51,6 @@ asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs) } #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 3e8a05c874c..3dbe8648df1 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -212,6 +212,9 @@ void do_interrupt(struct pt_regs *regs) 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 @@ void do_interrupt(struct pt_regs *regs) } if (level == 0) - return; - - /* - * 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); - } + break; + + do_IRQ(__ffs(int_at_level), regs); } + + irq_exit(); + set_irq_regs(old_regs); } /* |