summaryrefslogtreecommitdiff
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorVignesh Raghavendra <vigneshr@ti.com>2023-12-13 17:01:10 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-01-26 02:27:36 +0300
commit24961a5dc7590fd2ee0b41167996a229c172d44b (patch)
treea41521a673bdce410db92144ce7cb7b23086f29a /drivers/watchdog
parent6317445623a2b7ce194806424ef7f48a28db0d72 (diff)
downloadlinux-24961a5dc7590fd2ee0b41167996a229c172d44b.tar.xz
watchdog: rti_wdt: Drop runtime pm reference count when watchdog is unused
[ Upstream commit c1a6edf3b541e44e78f10bc6024df779715723f1 ] 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@ti.com> Tested-by: Manorit Chawdhry <m-chawdhry@ti.com> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Link: https://lore.kernel.org/r/20231213140110.938129-1-vigneshr@ti.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/rti_wdt.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/drivers/watchdog/rti_wdt.c b/drivers/watchdog/rti_wdt.c
index 6e9253761fc1..ea617c0f9747 100644
--- a/drivers/watchdog/rti_wdt.c
+++ b/drivers/watchdog/rti_wdt.c
@@ -70,6 +70,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;
@@ -295,6 +300,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:
@@ -309,7 +317,10 @@ static int 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);
return 0;