Skip to content

Commit 758e836

Browse files
jaszczyk-grzegorzJason Cooper
authored andcommitted
irqchip: armada-370-xp: Fix MPIC interrupt handling
In both Armada-375 and Armada-38x MPIC interrupts should be identified by reading cause register multiplied by the interrupt mask. A lack of above mentioned multiplication resulted in a bug, caused by the fact that in Armada-375 and Armada-38x some of the interrupts (e.g. network interrupts) can be handled either as a GIC or MPIC interrupts. Therefore during MPIC interrupts handling, cause register shows hits from interrupts even if they are masked for MPIC but unmasked for a GIC. This resulted in 'bad IRQ' error, because masked MPIC interrupt without registered interrupt handler, was trying to be handled during interrupt handling procedure of some other unmasked MPIC interrupt (e.g. local timer irq). This commit fixes that by ensuring that during MPIC interrupt handling only interrupts that are unmasked for MPIC are processed. Signed-off-by: Grzegorz Jaszczyk <[email protected]> Reviewed-by: Gregory CLEMENT <[email protected]> Fixes: bc69b8a ("irqchip: armada-370-xp: Setup a chained handler for the MPIC") Cc: <[email protected]> # v3.15+ Acked-by: Ezequiel Garcia <[email protected]> Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Jason Cooper <[email protected]>
1 parent 298dcb2 commit 758e836

File tree

1 file changed

+17
-6
lines changed

1 file changed

+17
-6
lines changed

drivers/irqchip/irq-armada-370-xp.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS (0x34)
4444
#define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4)
4545
#define ARMADA_370_XP_INT_SOURCE_CPU_MASK 0xF
46+
#define ARMADA_370_XP_INT_IRQ_FIQ_MASK(cpuid) ((BIT(0) | BIT(8)) << cpuid)
4647

4748
#define ARMADA_370_XP_CPU_INTACK_OFFS (0x44)
4849
#define ARMADA_375_PPI_CAUSE (0x10)
@@ -406,19 +407,29 @@ static void armada_370_xp_mpic_handle_cascade_irq(unsigned int irq,
406407
struct irq_desc *desc)
407408
{
408409
struct irq_chip *chip = irq_get_chip(irq);
409-
unsigned long irqmap, irqn;
410+
unsigned long irqmap, irqn, irqsrc, cpuid;
410411
unsigned int cascade_irq;
411412

412413
chained_irq_enter(chip, desc);
413414

414415
irqmap = readl_relaxed(per_cpu_int_base + ARMADA_375_PPI_CAUSE);
415-
416-
if (irqmap & BIT(1)) {
417-
armada_370_xp_handle_msi_irq(NULL, true);
418-
irqmap &= ~BIT(1);
419-
}
416+
cpuid = cpu_logical_map(smp_processor_id());
420417

421418
for_each_set_bit(irqn, &irqmap, BITS_PER_LONG) {
419+
irqsrc = readl_relaxed(main_int_base +
420+
ARMADA_370_XP_INT_SOURCE_CTL(irqn));
421+
422+
/* Check if the interrupt is not masked on current CPU.
423+
* Test IRQ (0-1) and FIQ (8-9) mask bits.
424+
*/
425+
if (!(irqsrc & ARMADA_370_XP_INT_IRQ_FIQ_MASK(cpuid)))
426+
continue;
427+
428+
if (irqn == 1) {
429+
armada_370_xp_handle_msi_irq(NULL, true);
430+
continue;
431+
}
432+
422433
cascade_irq = irq_find_mapping(armada_370_xp_mpic_domain, irqn);
423434
generic_handle_irq(cascade_irq);
424435
}

0 commit comments

Comments
 (0)