irq-bcm6345-l1: Do not assume a fixed block to cpu mapping

The irq to block mapping is fixed, and interrupts from the first block
will always be routed to the first parent IRQ. But the parent interrupts
themselves can be routed to any available CPU.

This is used by the bootloader to map the first parent interrupt to the
boot CPU, regardless wether the boot CPU is the first one or the second
one.

When booting from the second CPU, the assumption that the first block's
IRQ is mapped to the first CPU breaks, and the system hangs because
interrupts do not get routed correctly.

Fix this by passing the appropriate bcm6434_l1_cpu to the interrupt
handler instead of the chip itself, so the handler always has the right
block.

Fixes: c7c42ec2ba ("irqchips/bmips: Add bcm6345-l1 interrupt controller")
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20230629072620.62527-1-jonas.gorski@gmail.com
This commit is contained in:
Jonas Gorski 2023-06-29 09:26:20 +02:00 committed by Marc Zyngier
parent a82f3119d5
commit 55ad248573
1 changed files with 5 additions and 9 deletions

View File

@ -82,6 +82,7 @@ struct bcm6345_l1_chip {
}; };
struct bcm6345_l1_cpu { struct bcm6345_l1_cpu {
struct bcm6345_l1_chip *intc;
void __iomem *map_base; void __iomem *map_base;
unsigned int parent_irq; unsigned int parent_irq;
u32 enable_cache[]; u32 enable_cache[];
@ -115,17 +116,11 @@ static inline unsigned int cpu_for_irq(struct bcm6345_l1_chip *intc,
static void bcm6345_l1_irq_handle(struct irq_desc *desc) static void bcm6345_l1_irq_handle(struct irq_desc *desc)
{ {
struct bcm6345_l1_chip *intc = irq_desc_get_handler_data(desc); struct bcm6345_l1_cpu *cpu = irq_desc_get_handler_data(desc);
struct bcm6345_l1_cpu *cpu; struct bcm6345_l1_chip *intc = cpu->intc;
struct irq_chip *chip = irq_desc_get_chip(desc); struct irq_chip *chip = irq_desc_get_chip(desc);
unsigned int idx; unsigned int idx;
#ifdef CONFIG_SMP
cpu = intc->cpus[cpu_logical_map(smp_processor_id())];
#else
cpu = intc->cpus[0];
#endif
chained_irq_enter(chip, desc); chained_irq_enter(chip, desc);
for (idx = 0; idx < intc->n_words; idx++) { for (idx = 0; idx < intc->n_words; idx++) {
@ -253,6 +248,7 @@ static int __init bcm6345_l1_init_one(struct device_node *dn,
if (!cpu) if (!cpu)
return -ENOMEM; return -ENOMEM;
cpu->intc = intc;
cpu->map_base = ioremap(res.start, sz); cpu->map_base = ioremap(res.start, sz);
if (!cpu->map_base) if (!cpu->map_base)
return -ENOMEM; return -ENOMEM;
@ -271,7 +267,7 @@ static int __init bcm6345_l1_init_one(struct device_node *dn,
return -EINVAL; return -EINVAL;
} }
irq_set_chained_handler_and_data(cpu->parent_irq, irq_set_chained_handler_and_data(cpu->parent_irq,
bcm6345_l1_irq_handle, intc); bcm6345_l1_irq_handle, cpu);
return 0; return 0;
} }