[PATCH v4 1/2] irqchip/imx-irqsteer: Convert to devm_pm_runtime_enable()

From: Fabio Estevam

Date: Mon Aug 17 2026 - 15:06:52 EST


From: Fabio Estevam <festevam@xxxxxxxxxxxx>

imx_irqsteer_probe() enables runtime PM, but imx_irqsteer_remove() does
not disable it. Consequently, runtime PM remains enabled after unbinding
the device, and rebinding it triggers:

Unbalanced pm_runtime_enable!

Use devm_pm_runtime_enable() to automatically disable runtime PM when
the device is removed.

The driver core may runtime suspend the device before calling remove.
In that case, the runtime suspend callback has already disabled the IPG
clock, so only disable it in remove when the device is still active.

Set up runtime PM before creating the IRQ domain and registering chained
handlers so that a failure cannot leave either resource pointing at
freed driver data.

Fixes: 4730d2233311 ("irqchip/imx-irqsteer: Add runtime PM support")
Signed-off-by: Fabio Estevam <festevam@xxxxxxxxxxxx>
---
Changes since v3:
- Do not disable the IPG clock in remove when runtime PM has already
suspended the device, preventing a clock reference-count underflow. (Radu)

drivers/irqchip/irq-imx-irqsteer.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
index 87b07f517be3..f4df5ae73e9a 100644
--- a/drivers/irqchip/irq-imx-irqsteer.c
+++ b/drivers/irqchip/irq-imx-irqsteer.c
@@ -236,6 +236,11 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
if (irqsteer_has_chanctrl(data->devtype_data))
writel_relaxed(BIT(data->channel), data->regs + CHANCTRL);

+ pm_runtime_set_active(&pdev->dev);
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret)
+ goto out;
+
data->domain = irq_domain_create_linear(dev_fwnode(&pdev->dev), data->reg_num * 32,
&imx_irqsteer_domain_ops, data);
if (!data->domain) {
@@ -262,9 +267,6 @@ static int imx_irqsteer_probe(struct platform_device *pdev)

platform_set_drvdata(pdev, data);

- pm_runtime_set_active(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
-
return 0;
out:
clk_disable_unprepare(data->ipg_clk);
@@ -286,7 +288,8 @@ static void imx_irqsteer_remove(struct platform_device *pdev)

irq_domain_remove(irqsteer_data->domain);

- clk_disable_unprepare(irqsteer_data->ipg_clk);
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ clk_disable_unprepare(irqsteer_data->ipg_clk);
}

#ifdef CONFIG_PM
--
2.43.0