diff options
author | Rabin Vincent <rabin.vincent@axis.com> | 2015-06-12 04:01:56 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2015-06-13 05:33:00 -0400 |
commit | 1b3ed367ce11fb39a345d807ef4168f727236083 (patch) | |
tree | be2d9178cc1b9503d664e099de37fd87134ecbaf /drivers/irqchip/irq-mips-gic.c | |
parent | 9cc719ab3f4f639d629ac8ff09e9b998bc006f68 (diff) |
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: Rabin Vincent <rabin.vincent@axis.com>
Reviewed-by: Andrew Bresticker <abrestic@chromium.org>
Acked-by: Thomas 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: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers/irqchip/irq-mips-gic.c')
-rw-r--r-- | drivers/irqchip/irq-mips-gic.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 57f09cb54464..269c2354c431 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c | |||
@@ -271,7 +271,7 @@ int gic_get_c0_fdc_int(void) | |||
271 | GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_FDC)); | 271 | GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_FDC)); |
272 | } | 272 | } |
273 | 273 | ||
274 | static void gic_handle_shared_int(void) | 274 | static void gic_handle_shared_int(bool chained) |
275 | { | 275 | { |
276 | unsigned int i, intr, virq; | 276 | unsigned int i, intr, virq; |
277 | unsigned long *pcpu_mask; | 277 | unsigned long *pcpu_mask; |
@@ -299,7 +299,10 @@ static void gic_handle_shared_int(void) | |||
299 | while (intr != gic_shared_intrs) { | 299 | while (intr != gic_shared_intrs) { |
300 | virq = irq_linear_revmap(gic_irq_domain, | 300 | virq = irq_linear_revmap(gic_irq_domain, |
301 | GIC_SHARED_TO_HWIRQ(intr)); | 301 | GIC_SHARED_TO_HWIRQ(intr)); |
302 | do_IRQ(virq); | 302 | if (chained) |
303 | generic_handle_irq(virq); | ||
304 | else | ||
305 | do_IRQ(virq); | ||
303 | 306 | ||
304 | /* go to next pending bit */ | 307 | /* go to next pending bit */ |
305 | bitmap_clear(pending, intr, 1); | 308 | bitmap_clear(pending, intr, 1); |
@@ -431,7 +434,7 @@ static struct irq_chip gic_edge_irq_controller = { | |||
431 | #endif | 434 | #endif |
432 | }; | 435 | }; |
433 | 436 | ||
434 | static void gic_handle_local_int(void) | 437 | static void gic_handle_local_int(bool chained) |
435 | { | 438 | { |
436 | unsigned long pending, masked; | 439 | unsigned long pending, masked; |
437 | unsigned int intr, virq; | 440 | unsigned int intr, virq; |
@@ -445,7 +448,10 @@ static void gic_handle_local_int(void) | |||
445 | while (intr != GIC_NUM_LOCAL_INTRS) { | 448 | while (intr != GIC_NUM_LOCAL_INTRS) { |
446 | virq = irq_linear_revmap(gic_irq_domain, | 449 | virq = irq_linear_revmap(gic_irq_domain, |
447 | GIC_LOCAL_TO_HWIRQ(intr)); | 450 | GIC_LOCAL_TO_HWIRQ(intr)); |
448 | do_IRQ(virq); | 451 | if (chained) |
452 | generic_handle_irq(virq); | ||
453 | else | ||
454 | do_IRQ(virq); | ||
449 | 455 | ||
450 | /* go to next pending bit */ | 456 | /* go to next pending bit */ |
451 | bitmap_clear(&pending, intr, 1); | 457 | bitmap_clear(&pending, intr, 1); |
@@ -509,13 +515,14 @@ static struct irq_chip gic_all_vpes_local_irq_controller = { | |||
509 | 515 | ||
510 | static void __gic_irq_dispatch(void) | 516 | static void __gic_irq_dispatch(void) |
511 | { | 517 | { |
512 | gic_handle_local_int(); | 518 | gic_handle_local_int(false); |
513 | gic_handle_shared_int(); | 519 | gic_handle_shared_int(false); |
514 | } | 520 | } |
515 | 521 | ||
516 | static void gic_irq_dispatch(unsigned int irq, struct irq_desc *desc) | 522 | static void gic_irq_dispatch(unsigned int irq, struct irq_desc *desc) |
517 | { | 523 | { |
518 | __gic_irq_dispatch(); | 524 | gic_handle_local_int(true); |
525 | gic_handle_shared_int(true); | ||
519 | } | 526 | } |
520 | 527 | ||
521 | #ifdef CONFIG_MIPS_GIC_IPI | 528 | #ifdef CONFIG_MIPS_GIC_IPI |