]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
irqchip/crossbar: Use correct index in crossbar_domain_free()
authorBhargav Joshi <j.bhargav.u@gmail.com>
Sat, 20 Jun 2026 12:09:16 +0000 (17:39 +0530)
committerThomas Gleixner <tglx@kernel.org>
Sun, 21 Jun 2026 12:59:20 +0000 (14:59 +0200)
crossbar_domain_free() resets the domain data and then uses the nulled
out irq_data->hwirq member as index to reset the irq_map[] entry and to
write the relevant crossbar register with a safe entry. That means it
never frees the correct index and keeps the crossbar register connection
to the source interrupt active.

If it would not reset the domain data, then this would be even worse as
irq_data->hwirq holds the source interrupt number, but both the map and
register index need the corresponding GIC SPI number and not the source
interrupt number. This might even result in an out of bounds access as
the source interrupt number can be higher than the maximal index space.

Fix this by using the GIC SPI index from the parent domain's irq_data.

Fixes: 783d31863fb82 ("irqchip: crossbar: Convert dra7 crossbar to stacked domains")
Signed-off-by: Bhargav Joshi <j.bhargav.u@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260620-irq-crossbar-fix-v2-1-b8e8499f468a@gmail.com
drivers/irqchip/irq-crossbar.c

index cd1134101ace03e37e0584eab755545a46e77cc2..4e19e9d8a41d256d7c9aceef6e940cf755bab7ca 100644 (file)
@@ -158,9 +158,14 @@ static void crossbar_domain_free(struct irq_domain *domain, unsigned int virq,
        for (i = 0; i < nr_irqs; i++) {
                struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
 
+               /*
+                * irq_map[] is indexed by GIC SPI number. The parent domain's
+                * hwirq contains the GIC interrupt number (GIC SPI +
+                * GIC_IRQ_START).
+                */
+               cb->irq_map[d->parent_data->hwirq - GIC_IRQ_START] = IRQ_FREE;
+               cb->write(d->parent_data->hwirq - GIC_IRQ_START, cb->safe_map);
                irq_domain_reset_irq_data(d);
-               cb->irq_map[d->hwirq] = IRQ_FREE;
-               cb->write(d->hwirq, cb->safe_map);
        }
        raw_spin_unlock(&cb->lock);
 }