Commit 1b3ed367 authored by Rabin Vincent's avatar Rabin Vincent Committed by Ralf Baechle

IRQCHIP: mips-gic: Don't nest calls to do_IRQ()

The GIC chained handlers use do_IRQ() to call the subhandlers.  This
means that irq_enter() calls get nested, which leads to preempt count
looking like we're in nested interrupts, which in turn leads to all
system time being accounted as IRQ time in account_system_time().

Fix it by using generic_handle_irq().  Since these same functions are
used in some systems (if cpu_has_veic) from a low-level vectored
interrupt handler which does not go throught do_IRQ(), we need to do it
conditionally.
Signed-off-by: default avatarRabin Vincent <rabin.vincent@axis.com>
Reviewed-by: default avatarAndrew Bresticker <abrestic@chromium.org>
Acked-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: linux-mips@linux-mips.org
Cc: tglx@linutronix.de
Cc: jason@lakedaemon.net
Patchwork: https://patchwork.linux-mips.org/patch/10545/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 9cc719ab
...@@ -271,7 +271,7 @@ int gic_get_c0_fdc_int(void) ...@@ -271,7 +271,7 @@ int gic_get_c0_fdc_int(void)
GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_FDC)); GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_FDC));
} }
static void gic_handle_shared_int(void) static void gic_handle_shared_int(bool chained)
{ {
unsigned int i, intr, virq; unsigned int i, intr, virq;
unsigned long *pcpu_mask; unsigned long *pcpu_mask;
...@@ -299,6 +299,9 @@ static void gic_handle_shared_int(void) ...@@ -299,6 +299,9 @@ static void gic_handle_shared_int(void)
while (intr != gic_shared_intrs) { while (intr != gic_shared_intrs) {
virq = irq_linear_revmap(gic_irq_domain, virq = irq_linear_revmap(gic_irq_domain,
GIC_SHARED_TO_HWIRQ(intr)); GIC_SHARED_TO_HWIRQ(intr));
if (chained)
generic_handle_irq(virq);
else
do_IRQ(virq); do_IRQ(virq);
/* go to next pending bit */ /* go to next pending bit */
...@@ -431,7 +434,7 @@ static struct irq_chip gic_edge_irq_controller = { ...@@ -431,7 +434,7 @@ static struct irq_chip gic_edge_irq_controller = {
#endif #endif
}; };
static void gic_handle_local_int(void) static void gic_handle_local_int(bool chained)
{ {
unsigned long pending, masked; unsigned long pending, masked;
unsigned int intr, virq; unsigned int intr, virq;
...@@ -445,6 +448,9 @@ static void gic_handle_local_int(void) ...@@ -445,6 +448,9 @@ static void gic_handle_local_int(void)
while (intr != GIC_NUM_LOCAL_INTRS) { while (intr != GIC_NUM_LOCAL_INTRS) {
virq = irq_linear_revmap(gic_irq_domain, virq = irq_linear_revmap(gic_irq_domain,
GIC_LOCAL_TO_HWIRQ(intr)); GIC_LOCAL_TO_HWIRQ(intr));
if (chained)
generic_handle_irq(virq);
else
do_IRQ(virq); do_IRQ(virq);
/* go to next pending bit */ /* go to next pending bit */
...@@ -509,13 +515,14 @@ static struct irq_chip gic_all_vpes_local_irq_controller = { ...@@ -509,13 +515,14 @@ static struct irq_chip gic_all_vpes_local_irq_controller = {
static void __gic_irq_dispatch(void) static void __gic_irq_dispatch(void)
{ {
gic_handle_local_int(); gic_handle_local_int(false);
gic_handle_shared_int(); gic_handle_shared_int(false);
} }
static void gic_irq_dispatch(unsigned int irq, struct irq_desc *desc) static void gic_irq_dispatch(unsigned int irq, struct irq_desc *desc)
{ {
__gic_irq_dispatch(); gic_handle_local_int(true);
gic_handle_shared_int(true);
} }
#ifdef CONFIG_MIPS_GIC_IPI #ifdef CONFIG_MIPS_GIC_IPI
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment