This is a note to let you know that I've just added the patch titled watchdog: rti_wdt: Drop runtime pm reference count when watchdog is unused to the 5.15-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: watchdog-rti_wdt-drop-runtime-pm-reference-count-whe.patch and it can be found in the queue-5.15 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit 823429dadc6322f8c969c665b8e9b7a46cc3a884 Author: Vignesh Raghavendra <vigneshr@xxxxxx> Date: Wed Dec 13 19:31:10 2023 +0530 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@xxxxxx> Tested-by: Manorit Chawdhry <m-chawdhry@xxxxxx> Reviewed-by: Guenter Roeck <linux@xxxxxxxxxxxx> Link: https://lore.kernel.org/r/20231213140110.938129-1-vigneshr@xxxxxx Signed-off-by: Guenter Roeck <linux@xxxxxxxxxxxx> Signed-off-by: Wim Van Sebroeck <wim@xxxxxxxxxxxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/drivers/watchdog/rti_wdt.c b/drivers/watchdog/rti_wdt.c index 46c2a4bd9ebe..daa00f3c5a6a 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; @@ -296,6 +301,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: @@ -310,7 +318,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;