From: sashiko-bot@kernel.org
To: "William Theesfeld" <william@theesfeld.net>
Cc: linux-watchdog@vger.kernel.org
Subject: Re: [PATCH] watchdog: starfive: use pm_runtime_resume_and_get() to fix refcount leak
Date: Fri, 05 Jun 2026 12:35:53 +0000 [thread overview]
Message-ID: <20260605123553.D2FB11F00893@smtp.kernel.org> (raw)
In-Reply-To: <20260605122336.159546-1-william@theesfeld.net>
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
Pre-existing issues:
- [Critical] System callbacks unconditionally access hardware registers while the device may be runtime-suspended, which will trigger a synchronous external abort.
- [High] starfive_wdt_pm_start() leaks the runtime PM usage counter if the hardware start operation fails, an edge case missed by the patch.
- [High] starfive_wdt_pm_stop() and starfive_wdt_probe() incorrectly handle a return value of 1 from pm_runtime_put_sync(), interpreting a success case as an error.
- [High] Multiple error paths in starfive_wdt_probe() leak the PM usage counter and fail to disable PM runtime.
- [High] starfive_wdt_shutdown() unconditionally drops the runtime PM usage counter, causing an underflow if the watchdog is not active.
- [High] Runtime PM usage counter leaks on module removal when early_enable is true and the device was never opened.
--
commit 716832af83b52aac9fc1a5fdc00be97db3d21459
Author: William Theesfeld <william@theesfeld.net>
watchdog: starfive: use pm_runtime_resume_and_get() to fix refcount leak
starfive_wdt_pm_start() calls pm_runtime_get_sync(), but
pm_runtime_get_sync() increments the runtime PM usage counter even
when it returns an error. On the error path this function just
returns the error code without a matching pm_runtime_put_noidle(),
so the usage counter is leaked on every failed resume.
Switch to pm_runtime_resume_and_get(), which decrements the usage
counter automatically on failure, leaving the caller with the simple
"check return value and propagate" pattern that the existing code
was already trying to follow.
> diff --git a/drivers/watchdog/starfive-wdt.c b/drivers/watchdog/starfive-wdt.c
> index af55adc4a3c69..5a3254c83d3bb 100644
> --- a/drivers/watchdog/starfive-wdt.c
> +++ b/drivers/watchdog/starfive-wdt.c
> @@ -371,7 +371,7 @@ static void starfive_wdt_stop(struct starfive_wdt *wdt)
> static int starfive_wdt_pm_start(struct watchdog_device *wdd)
> {
> struct starfive_wdt *wdt = watchdog_get_drvdata(wdd);
> - int ret = pm_runtime_get_sync(wdd->parent);
> + int ret = pm_runtime_resume_and_get(wdd->parent);
>
> if (ret < 0)
> return ret;
>
> return starfive_wdt_start(wdt);
[Severity: High]
This isn't a bug introduced by this patch, but does this code leak the runtime
PM usage counter if starfive_wdt_start() fails? It appears that the function
returns the error directly without calling pm_runtime_put(), keeping the
reference acquired by pm_runtime_resume_and_get().
While reviewing this file, I noticed a few other pre-existing issues.
drivers/watchdog/starfive-wdt.c:starfive_wdt_pm_stop() {
...
starfive_wdt_stop(wdt);
return pm_runtime_put_sync(wdd->parent);
}
[Severity: High]
This is a pre-existing issue, but does this break the watchdog core's
expectation of returning 0 on success?
According to Runtime PM API contracts, pm_runtime_put_sync() returns 1 if the
device is already in the RPM_SUSPENDED state, which indicates success, not an
error. By returning this raw result, it seems we force the watchdog core to
assume the stop operation failed.
drivers/watchdog/starfive-wdt.c:starfive_wdt_probe() {
...
if (!early_enable) {
if (pm_runtime_enabled(&pdev->dev)) {
ret = pm_runtime_put_sync(&pdev->dev);
if (ret)
goto err_unregister_wdt;
...
[Severity: High]
This is a pre-existing issue, but does this erroneously fail the probe if
pm_runtime_put_sync() returns 1?
drivers/watchdog/starfive-wdt.c:starfive_wdt_probe() {
...
pm_runtime_enable(&pdev->dev);
if (pm_runtime_enabled(&pdev->dev)) {
ret = pm_runtime_resume_and_get(&pdev->dev);
if (ret < 0)
return ret;
...
[Severity: High]
This is a pre-existing issue, but do these direct return paths bypass the
required pm_runtime_disable() cleanup after pm_runtime_enable() was called?
drivers/watchdog/starfive-wdt.c:starfive_wdt_probe() {
...
err_exit:
starfive_wdt_disable_clock(wdt);
pm_runtime_disable(&pdev->dev);
return ret;
}
[Severity: High]
This is a pre-existing issue, but does the err_exit label miss dropping the
runtime PM reference acquired via pm_runtime_resume_and_get() earlier in the
probe?
drivers/watchdog/starfive-wdt.c:starfive_wdt_remove() {
...
static void starfive_wdt_remove(struct platform_device *pdev)
{
struct starfive_wdt *wdt = platform_get_drvdata(pdev);
starfive_wdt_stop(wdt);
...
drivers/watchdog/starfive-wdt.c:starfive_wdt_shutdown() {
...
static void starfive_wdt_shutdown(struct platform_device *pdev)
{
struct starfive_wdt *wdt = platform_get_drvdata(pdev);
starfive_wdt_pm_stop(&wdt->wdd);
...
drivers/watchdog/starfive-wdt.c:starfive_wdt_suspend() {
...
static int starfive_wdt_suspend(struct device *dev)
{
struct starfive_wdt *wdt = dev_get_drvdata(dev);
/* Save watchdog state, and turn it off. */
wdt->reload = starfive_wdt_get_count(wdt);
/* Note that WTCNT doesn't need to be saved. */
starfive_wdt_stop(wdt);
...
drivers/watchdog/starfive-wdt.c:starfive_wdt_resume() {
...
static int starfive_wdt_resume(struct device *dev)
{
...
starfive_wdt_unlock(wdt);
/* Restore watchdog state. */
starfive_wdt_set_reload_count(wdt, wdt->reload);
starfive_wdt_lock(wdt);
...
[Severity: Critical]
These are pre-existing issues, but do these system callbacks risk triggering a
synchronous external abort by unconditionally accessing hardware registers
while the device might be runtime-suspended and unclocked?
drivers/watchdog/starfive-wdt.c:starfive_wdt_shutdown() {
...
static void starfive_wdt_shutdown(struct platform_device *pdev)
{
struct starfive_wdt *wdt = platform_get_drvdata(pdev);
starfive_wdt_pm_stop(&wdt->wdd);
}
[Severity: High]
This is a pre-existing issue, but does unconditionally calling
starfive_wdt_pm_stop() (which contains pm_runtime_put_sync()) cause a PM
usage counter underflow if the watchdog is already inactive and its counter
is 0?
drivers/watchdog/starfive-wdt.c:starfive_wdt_remove() {
...
if (pm_runtime_enabled(&pdev->dev))
pm_runtime_disable(&pdev->dev);
else
/* disable clock without PM */
starfive_wdt_disable_clock(wdt);
}
[Severity: High]
This is a pre-existing issue, but does the remove function fail to decrement
the PM usage counter if early_enable is true and the device was never opened
by userspace?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260605122336.159546-1-william@theesfeld.net?part=1
next prev parent reply other threads:[~2026-06-05 12:35 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-05 12:23 [PATCH] watchdog: starfive: use pm_runtime_resume_and_get() to fix refcount leak William Theesfeld
2026-06-05 12:35 ` sashiko-bot [this message]
2026-06-05 13:11 ` [PATCH v2 0/6] watchdog: starfive: runtime PM cleanup William Theesfeld
2026-06-05 13:11 ` [PATCH v2 1/6] watchdog: starfive: balance PM refcount when start operation fails William Theesfeld
2026-06-05 13:23 ` sashiko-bot
2026-06-05 13:11 ` [PATCH v2 2/6] watchdog: starfive: treat pm_runtime_put_sync() positive return as success William Theesfeld
2026-06-05 13:26 ` sashiko-bot
2026-06-05 13:11 ` [PATCH v2 3/6] watchdog: starfive: balance PM refcount and disable in probe error paths William Theesfeld
2026-06-05 13:24 ` sashiko-bot
2026-06-05 13:11 ` [PATCH v2 4/6] watchdog: starfive: guard system suspend/resume hardware access William Theesfeld
2026-06-05 13:27 ` sashiko-bot
2026-06-05 13:11 ` [PATCH v2 5/6] watchdog: starfive: avoid PM refcount underflow in shutdown William Theesfeld
2026-06-05 13:29 ` sashiko-bot
2026-06-05 13:11 ` [PATCH v2 6/6] watchdog: starfive: release early_enable PM refcount on remove William Theesfeld
2026-06-05 13:33 ` sashiko-bot
2026-06-05 17:19 ` [PATCH v3 0/6] watchdog: starfive: runtime PM cleanup William Theesfeld
2026-06-05 17:19 ` [PATCH v3 1/6] watchdog: starfive: balance PM refcount when start operation fails William Theesfeld
2026-06-05 17:19 ` [PATCH v3 2/6] watchdog: starfive: treat pm_runtime_put_sync() positive return as success William Theesfeld
2026-06-05 17:19 ` [PATCH v3 3/6] watchdog: starfive: balance PM refcount and disable in probe error paths William Theesfeld
2026-06-05 17:19 ` [PATCH v3 4/6] watchdog: starfive: guard system suspend/resume hardware access William Theesfeld
2026-06-05 17:19 ` [PATCH v3 5/6] watchdog: starfive: avoid PM refcount underflow in shutdown William Theesfeld
2026-06-05 17:19 ` [PATCH v3 6/6] watchdog: starfive: release early_enable PM refcount on remove William Theesfeld
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260605123553.D2FB11F00893@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-watchdog@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=william@theesfeld.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox