[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20231213140110.938129-1-vigneshr@ti.com>
Date: Wed, 13 Dec 2023 19:31:10 +0530
From: Vignesh Raghavendra <vigneshr@...com>
To: Wim Van Sebroeck <wim@...ux-watchdog.org>,
Guenter Roeck <linux@...ck-us.net>
CC: Manorit Chawdhry <m-chawdhry@...com>,
<linux-watchdog@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
Vignesh Raghavendra <vigneshr@...com>,
<linux-arm-kernel@...ts.infradead.org>
Subject: [PATCH v3] watchdog: rti_wdt: Drop runtime pm reference count when watchdog is unused
Call runtime_pm_put*() if watchdog is not already started during probe and re
enable it in watchdog start as required.
On K3 SoCs, watchdogs and their corresponding CPUs are under same
power-domain, so if the reference count of unused watchdogs aren't
dropped, it will lead to CPU hotplug failures as Device Management
firmware won't allow to turn off the power-domain due to dangling
reference count.
Fixes: 2d63908bdbfb ("watchdog: Add K3 RTI watchdog support")
Signed-off-by: Vignesh Raghavendra <vigneshr@...com>
Reviewed-by: Guenter Roeck <linux@...ck-us.net>
Tested-by: Manorit Chawdhry <m-chawdhry@...com>
---
v3:
Reword commit message to expand non std acronyms
Collect Reviewed-by and Tested-by tags
No code change
v2: https://lore.kernel.org/r/20231122041642.2015936-1-vigneshr@ti.com
v2:
* Drop 1/2 (will be posted along with runtime_pm callbacks)
* Use pm_runtime_resume_and_get() instead of pm_runtime_get_sync() which
takes care of err handling
v1: https://lore.kernel.org/r/20231110100726.2930218-1-vigneshr@ti.com
drivers/watchdog/rti_wdt.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/watchdog/rti_wdt.c b/drivers/watchdog/rti_wdt.c
index 8e1be7ba0103..9215793a1c81 100644
--- a/drivers/watchdog/rti_wdt.c
+++ b/drivers/watchdog/rti_wdt.c
@@ -77,6 +77,11 @@ static int rti_wdt_start(struct watchdog_device *wdd)
{
u32 timer_margin;
struct rti_wdt_device *wdt = watchdog_get_drvdata(wdd);
+ int ret;
+
+ ret = pm_runtime_resume_and_get(wdd->parent);
+ if (ret)
+ return ret;
/* set timeout period */
timer_margin = (u64)wdd->timeout * wdt->freq;
@@ -343,6 +348,9 @@ static int rti_wdt_probe(struct platform_device *pdev)
if (last_ping)
watchdog_set_last_hw_keepalive(wdd, last_ping);
+ if (!watchdog_hw_running(wdd))
+ pm_runtime_put_sync(&pdev->dev);
+
return 0;
err_iomap:
@@ -357,7 +365,10 @@ static void rti_wdt_remove(struct platform_device *pdev)
struct rti_wdt_device *wdt = platform_get_drvdata(pdev);
watchdog_unregister_device(&wdt->wdd);
- pm_runtime_put(&pdev->dev);
+
+ if (!pm_runtime_suspended(&pdev->dev))
+ pm_runtime_put(&pdev->dev);
+
pm_runtime_disable(&pdev->dev);
}
--
2.43.0
Powered by blists - more mailing lists