[PATCH 11/16] irqchip/loongson-eiointc: preserve live state on cascade failure
Haofeng Li <[email protected]> Tue, 14 Jul 2026 21:24:47 +0800
| Newsgroups | org.kernel.vger.linux-mips,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
From: Haofeng Li <[email protected]> eiointc_init() publishes priv through the IRQ domain, chained handlers, eiointc_priv[], syscore operations, and CPU hotplug state. If subsequent cascade initialization fails, jumping to out_free_handle frees priv and its fwnode while all of those users remain live. Cascade initialization may also have created PCH PIC, MSI, or LPC child domains before reporting an error, so removing the EIOINTC parent at that point is not a safe rollback. After eiointc_init() succeeds, keep the published controller alive and propagate the cascade error without freeing it. Before ownership is transferred, validate the parent mapping and dispose it if eiointc_init() fails. Preserve the actual error code on all cleanup paths. Fixes: a3f1132c4c6b ("irqchip/loongson-eiointc: Add DT init support") Signed-off-by: Haofeng Li <[email protected]> --- drivers/irqchip/irq-loongson-eiointc.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index a9e8b481d31d..d2310a1ebbd6 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -580,7 +580,7 @@ static int __init eiointc_init(struct eiointc_priv *priv, int parent_irq, int __init eiointc_acpi_init(struct irq_domain *parent, struct acpi_madt_eio_pic *acpi_eiointc) { - int parent_irq, ret; + int parent_irq, ret = -ENOMEM; struct eiointc_priv *priv; int node; @@ -599,10 +599,12 @@ int __init eiointc_acpi_init(struct irq_domain *parent, priv->node = acpi_eiointc->node; priv->parent_hwirq = acpi_eiointc->cascade; parent_irq = irq_create_mapping(parent, acpi_eiointc->cascade); + if (!parent_irq) + goto out_free_handle; ret = eiointc_init(priv, parent_irq, acpi_eiointc->node_map); if (ret < 0) - goto out_free_handle; + goto out_dispose_mapping; if (cpu_has_flatmode) node = early_cpu_to_node(acpi_eiointc->node * CORES_PER_EIO_NODE); @@ -612,18 +614,17 @@ int __init eiointc_acpi_init(struct irq_domain *parent, acpi_set_vec_parent(node, priv->eiointc_domain, msi_group); ret = acpi_cascade_irqdomain_init(); - if (ret < 0) - goto out_free_handle; - return ret; +out_dispose_mapping: + irq_dispose_mapping(parent_irq); out_free_handle: irq_domain_free_fwnode(priv->domain_handle); priv->domain_handle = NULL; out_free_priv: kfree(priv); - return -ENOMEM; + return ret; } static int __init eiointc_of_init(struct device_node *of_node, -- 2.25.1