mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 14:04:27 -04:00
irqchip/gic-v5: Release IRS iomem region on driver init failure
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:5cb1b6dab2("irqchip/gic-v5: Add GICv5 IRS/SPI support") Fixes:35866efa52("irqchip/gic-v5: Add ACPI IRS probing") Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org> Signed-off-by: Thomas Gleixner <tglx@kernel.org> Link: https://sashiko.dev/#/message/20260810104747.E5CE71F000E9%40smtp.kernel.org Link: https://patch.msgid.link/20260812-gicv5-7-2-fixes-v1-5-3743e82c69a4@kernel.org
This commit is contained in:
committed by
Thomas Gleixner
parent
183750b276
commit
dc2eae1620
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user