xtensa: clean up do_interrupt/do_IRQ
authorMax Filippov <jcmvbkbc@gmail.com>
Wed, 16 Oct 2013 22:42:23 +0000 (02:42 +0400)
committerChris Zankel <chris@zankel.net>
Tue, 14 Jan 2014 18:19:57 +0000 (10:19 -0800)
- 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>
arch/xtensa/kernel/irq.c
arch/xtensa/kernel/traps.c

index ada1e4893dd6c6671121464c306c7c3169791810..3cef58e283329565b166533b66ab66385c616926 100644 (file)
@@ -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)
index 3e8a05c874cd2719951929ff348b4d24f34c773e..3dbe8648df1fe79bae79d22f100d9137a3c14dad 100644 (file)
@@ -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);
 }
 
 /*