[PATCH 5/7] irqchip/gic-v5: Release IRS iomem region on driver init failure
Lorenzo Pieralisi
lpieralisi at kernel.org
Wed Aug 12 02:10:33 PDT 2026
In gicv5_irs_of_init(), an IRS is set-up using of_io_request_and_map() to
request its memory region (corresponding to the configuration frame) and
map the IRS configuration frame.
On gicv5_irs_of_init() failure, the driver unmaps the IRS iomem region but
does not release the requested memory region leaving it allocated in the
iomem resource tree.
Fix it by releasing the iomem region on gicv5_irs_of_init() probe failure.
Likewise, on both OF and ACPI driver init failure, IRS iomem regions are
requested but never released in gicv5_irs_remove().
Stash a copy of the IRS iomem region in a struct resource in
struct gicv5_irs_chip_data and use it to release the requested region in
gicv5_irs_remove() if the driver probe fails.
Fixes: 5cb1b6dab2de ("irqchip/gic-v5: Add GICv5 IRS/SPI support")
Fixes: 35866efa52fe ("irqchip/gic-v5: Add ACPI IRS probing")
Signed-off-by: Lorenzo Pieralisi <lpieralisi at kernel.org>
Cc: Thomas Gleixner <tglx at kernel.org>
Cc: Marc Zyngier <maz at kernel.org>
Link: https://sashiko.dev/#/message/20260810104747.E5CE71F000E9%40smtp.kernel.org
---
drivers/irqchip/irq-gic-v5-irs.c | 10 ++++++++++
include/linux/irqchip/arm-gic-v5.h | 2 ++
2 files changed, 12 insertions(+)
diff --git a/drivers/irqchip/irq-gic-v5-irs.c b/drivers/irqchip/irq-gic-v5-irs.c
index 9d25ce8bfd8c..86da9f82a7b0 100644
--- a/drivers/irqchip/irq-gic-v5-irs.c
+++ b/drivers/irqchip/irq-gic-v5-irs.c
@@ -740,6 +740,7 @@ static int __init gicv5_irs_init(struct gicv5_irs_chip_data *irs_data)
static int __init gicv5_irs_of_init(struct device_node *node)
{
struct gicv5_irs_chip_data *irs_data;
+ struct resource res;
void __iomem *irs_base;
u8 iaffid_bits;
u32 idr;
@@ -757,6 +758,11 @@ static int __init gicv5_irs_of_init(struct device_node *node)
goto out_err;
}
+ if (of_address_to_resource(node, ret, &res)) {
+ ret = -EINVAL;
+ goto out_err;
+ }
+
irs_base = of_io_request_and_map(node, ret, of_node_full_name(node));
if (IS_ERR(irs_base)) {
pr_err("%pOF: unable to map GICv5 IRS registers\n", node);
@@ -765,6 +771,7 @@ static int __init gicv5_irs_of_init(struct device_node *node)
}
irs_data->fwnode = of_fwnode_handle(node);
+ irs_data->res = res;
gicv5_irs_init_bases(irs_data, irs_base, of_property_read_bool(node, "dma-noncoherent"));
idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR1);
@@ -794,6 +801,7 @@ static int __init gicv5_irs_of_init(struct device_node *node)
gicv5_irs_clear_affinity(irs_data);
gicv5_irs_disable(irs_data);
iounmap(irs_base);
+ release_mem_region(res.start, resource_size(&res));
out_err:
kfree(irs_data);
return ret;
@@ -810,6 +818,7 @@ void __init gicv5_irs_remove(void)
gicv5_irs_clear_affinity(irs_data);
gicv5_irs_disable(irs_data);
iounmap(irs_data->irs_base);
+ release_mem_region(irs_data->res.start, resource_size(&irs_data->res));
list_del(&irs_data->entry);
kfree(irs_data);
}
@@ -958,6 +967,7 @@ static int __init gic_acpi_parse_madt_irs(union acpi_subtable_headers *header,
}
gicv5_irs_init_bases(irs_data, irs_base, irs->flags & ACPI_MADT_IRS_NON_COHERENT);
+ irs_data->res = *r;
gicv5_irs_acpi_init_affinity(irs->irs_id, irs_data);
diff --git a/include/linux/irqchip/arm-gic-v5.h b/include/linux/irqchip/arm-gic-v5.h
index f78787e654f4..2c2fb39f049c 100644
--- a/include/linux/irqchip/arm-gic-v5.h
+++ b/include/linux/irqchip/arm-gic-v5.h
@@ -6,6 +6,7 @@
#define __LINUX_IRQCHIP_ARM_GIC_V5_H
#include <linux/iopoll.h>
+#include <linux/ioport.h>
#include <asm/cacheflush.h>
#include <asm/smp.h>
@@ -324,6 +325,7 @@ struct gicv5_irs_chip_data {
struct list_head entry;
struct fwnode_handle *fwnode;
void __iomem *irs_base;
+ struct resource res;
u32 flags;
u32 spi_min;
u32 spi_range;
--
2.53.0
More information about the linux-arm-kernel
mailing list