[PATCH v4 1/2] irqchip/imx-irqsteer: Convert to devm_pm_runtime_enable()
Fabio Estevam <[email protected]>
| Newsgroups | gmane.linux.kernel |
|---|---|
| Message-ID | <[email protected]> |
From: Fabio Estevam <[email protected]> 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 <[email protected]> --- 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