diff options
author | Jeffrey Deans <jeffrey.deans@imgtec.com> | 2014-07-17 04:20:58 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-08-01 18:06:41 -0400 |
commit | 1c772b5664d9efa8d8d25b69b4ea8ae8996d6153 (patch) | |
tree | 9ff73849a38884773d291383298263d5e0b7d624 /arch/mips/mti-malta | |
parent | 31521a7a64bc5df5202e479ee7ba8133993ab32a (diff) |
MIPS: Malta: Fix dispatching of GIC interrupts
The Malta malta_ipi_irqdispatch() routine now checks only IPI interrupts
when handling IPIs. It could previously call do_IRQ() for non-IPIs, and
also call do_IRQ() with an invalid IRQ number if there were no pending
GIC interrupts when gic_get_int() was called.
Signed-off-by: Jeffrey Deans <jeffrey.deans@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/7377/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/mti-malta')
-rw-r--r-- | arch/mips/mti-malta/malta-int.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index 4ab919141737..e4f43baa8f67 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c | |||
@@ -42,6 +42,10 @@ static unsigned int ipi_map[NR_CPUS]; | |||
42 | 42 | ||
43 | static DEFINE_RAW_SPINLOCK(mips_irq_lock); | 43 | static DEFINE_RAW_SPINLOCK(mips_irq_lock); |
44 | 44 | ||
45 | #ifdef CONFIG_MIPS_GIC_IPI | ||
46 | DECLARE_BITMAP(ipi_ints, GIC_NUM_INTRS); | ||
47 | #endif | ||
48 | |||
45 | static inline int mips_pcibios_iack(void) | 49 | static inline int mips_pcibios_iack(void) |
46 | { | 50 | { |
47 | int irq; | 51 | int irq; |
@@ -125,16 +129,22 @@ static void malta_hw0_irqdispatch(void) | |||
125 | 129 | ||
126 | static void malta_ipi_irqdispatch(void) | 130 | static void malta_ipi_irqdispatch(void) |
127 | { | 131 | { |
128 | int irq; | 132 | #ifdef CONFIG_MIPS_GIC_IPI |
133 | unsigned long irq; | ||
134 | DECLARE_BITMAP(pending, GIC_NUM_INTRS); | ||
129 | 135 | ||
130 | if (gic_compare_int()) | 136 | gic_get_int_mask(pending, ipi_ints); |
131 | do_IRQ(MIPS_GIC_IRQ_BASE); | 137 | |
138 | irq = find_first_bit(pending, GIC_NUM_INTRS); | ||
132 | 139 | ||
133 | irq = gic_get_int(); | 140 | while (irq < GIC_NUM_INTRS) { |
134 | if (irq < 0) | 141 | do_IRQ(MIPS_GIC_IRQ_BASE + irq); |
135 | return; /* interrupt has already been cleared */ | ||
136 | 142 | ||
137 | do_IRQ(MIPS_GIC_IRQ_BASE + irq); | 143 | irq = find_next_bit(pending, GIC_NUM_INTRS, irq + 1); |
144 | } | ||
145 | #endif | ||
146 | if (gic_compare_int()) | ||
147 | do_IRQ(MIPS_GIC_IRQ_BASE); | ||
138 | } | 148 | } |
139 | 149 | ||
140 | static void corehi_irqdispatch(void) | 150 | static void corehi_irqdispatch(void) |
@@ -429,6 +439,7 @@ static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin) | |||
429 | gic_intr_map[intr].trigtype = GIC_TRIG_EDGE; | 439 | gic_intr_map[intr].trigtype = GIC_TRIG_EDGE; |
430 | gic_intr_map[intr].flags = 0; | 440 | gic_intr_map[intr].flags = 0; |
431 | ipi_map[cpu] |= (1 << (cpupin + 2)); | 441 | ipi_map[cpu] |= (1 << (cpupin + 2)); |
442 | bitmap_set(ipi_ints, intr, 1); | ||
432 | } | 443 | } |
433 | 444 | ||
434 | static void __init fill_ipi_map(void) | 445 | static void __init fill_ipi_map(void) |