6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter dan.carpenter@linaro.org
[ Upstream commit a186120c780e21e4cfd186a925e34f718e30de88 ]
Code in gicv5_its_irq_domain_alloc() has two issues:
- it checks the wrong return value/variable when calling gicv5_alloc_lpi()
- The cleanup code does not take previous loop iterations into account
Fix both issues at once by adding the right gicv5_alloc_lpi() variable check and by reworking the function cleanup code to take into account current and previous iterations.
[ lpieralisi: Reworded commit message ]
Fixes: 57d72196dfc8 ("irqchip/gic-v5: Add GICv5 ITS support") Signed-off-by: Dan Carpenter dan.carpenter@linaro.org Signed-off-by: Lorenzo Pieralisi lpieralisi@kernel.org Signed-off-by: Thomas Gleixner tglx@linutronix.de Reviewed-by: Zenghui Yu yuzenghui@huawei.com Link: https://lore.kernel.org/all/20250908082745.113718-4-lpieralisi@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/irqchip/irq-gic-v5-its.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v5-its.c b/drivers/irqchip/irq-gic-v5-its.c index 4701ef62b8b27..2fb58d76f5214 100644 --- a/drivers/irqchip/irq-gic-v5-its.c +++ b/drivers/irqchip/irq-gic-v5-its.c @@ -949,15 +949,18 @@ static int gicv5_its_irq_domain_alloc(struct irq_domain *domain, unsigned int vi device_id = its_dev->device_id;
for (i = 0; i < nr_irqs; i++) { - lpi = gicv5_alloc_lpi(); + ret = gicv5_alloc_lpi(); if (ret < 0) { pr_debug("Failed to find free LPI!\n"); - goto out_eventid; + goto out_free_irqs; } + lpi = ret;
ret = irq_domain_alloc_irqs_parent(domain, virq + i, 1, &lpi); - if (ret) - goto out_free_lpi; + if (ret) { + gicv5_free_lpi(lpi); + goto out_free_irqs; + }
/* * Store eventid and deviceid into the hwirq for later use. @@ -977,8 +980,13 @@ static int gicv5_its_irq_domain_alloc(struct irq_domain *domain, unsigned int vi
return 0;
-out_free_lpi: - gicv5_free_lpi(lpi); +out_free_irqs: + while (--i >= 0) { + irqd = irq_domain_get_irq_data(domain, virq + i); + gicv5_free_lpi(irqd->parent_data->hwirq); + irq_domain_reset_irq_data(irqd); + irq_domain_free_irqs_parent(domain, virq + i, 1); + } out_eventid: gicv5_its_free_eventid(its_dev, event_id_base, nr_irqs); return ret;