Linux Watchdog driver development
 help / color / mirror / Atom feed
* [PATCH v2 0/8] watchdog: starfive-wdt: Fix runtime PM and unclocked register access bugs
@ 2026-11-05 19:05 Guenter Roeck
  2026-11-05 19:05 ` [PATCH v2 1/8] watchdog: starfive-wdt: Drop runtime PM reference if starting watchdog fails Guenter Roeck
                   ` (7 more replies)
  0 siblings, 8 replies; 15+ messages in thread
From: Guenter Roeck @ 2026-11-05 19:05 UTC (permalink / raw)
  To: linux-watchdog; +Cc: Tzung-Bi Shih, Guenter Roeck, Xingyu Wu, Ziv Xu

The StarFive watchdog driver (drivers/watchdog/starfive-wdt.c) gates its
APB and core clocks via runtime PM callbacks, but has several runtime PM
reference-counting, ordering, and unclocked MMIO access bugs across
probe, remove, start/stop, shutdown, ioctl/sysfs, and system sleep paths:

1. In starfive_wdt_pm_start(), if starfive_wdt_start() fails after
   pm_runtime_resume_and_get() succeeds, the acquired runtime PM
   reference is leaked because the watchdog core does not call the stop
   callback when start fails.
2. In starfive_wdt_probe(), early returns on pm_runtime_resume_and_get()
   or starfive_wdt_enable_clock() failure bypass pm_runtime_disable(),
   leaving the runtime PM disable_depth counter unbalanced.
3. When runtime PM has suspended an idle watchdog and gated its clocks,
   starfive_wdt_remove(), starfive_wdt_shutdown(), starfive_wdt_suspend(),
   and starfive_wdt_resume() unconditionally read and write hardware
   registers, causing unclocked MMIO bus faults. In addition,
   starfive_wdt_shutdown() duplicates watchdog_stop_on_reboot() (causing
   unbalanced runtime PM puts when not runtime-suspended and ignoring
   watchdog.stop_on_reboot=0), and starfive_wdt_pm_stop() propagates
   non-zero idle return codes from pm_runtime_put_sync() as errors to
   watchdog_stop().
4. Probe error paths after pm_runtime_resume_and_get() disable clocks
   manually without releasing the runtime PM reference (and without
   stopping an early_enable watchdog if registration fails), and
   starfive_wdt_remove() never drops the active runtime PM reference
   retained when watchdog_hw_running() is still set (e.g. early_enable).
5. In starfive_wdt_probe(), watchdog_register_device() is called before
   pm_runtime_put_sync() drops the probe-time reference, and non-zero
   idle return values such as -EAGAIN (triggered if userspace opens
   /dev/watchdog immediately upon registration) are treated as fatal
   probe errors.
6. In starfive_wdt_get_timeleft(), reading the sysfs timeleft attribute
   or issuing ioctl(WDIOC_GETTIMELEFT) while the watchdog is inactive
   reads hardware registers while clocks are gated off.
7. In starfive_wdt_probe(), omitting watchdog_stop_ping_on_suspend()
   leaves the non-freezable watchdog ping worker active across system
   suspend when early_enable=1 is used, risking unclocked MMIO in
   starfive_wdt_keepalive() after starfive_wdt_suspend() gates clocks.
8. In starfive_wdt_set_timeout(), issuing ioctl(WDIOC_SETTIMEOUT) after
   stopping the watchdog via WDIOS_DISABLECARD accesses unclocked MMIO
   registers (when runtime-suspended) or unexpectedly re-enables the
   hardware counter while inactive (when runtime PM is disabled).

This 8-patch series fixes each of these issues in sequence.

Changes in v2:
- Patch 1, 2, 4, and 5: Added Reviewed-by: tags
- Patch 3: Remove the redundant starfive_wdt_shutdown() callback instead
  of guarding it with !pm_runtime_suspended(), avoiding unbalanced
  pm_runtime_put_sync() calls when runtime suspend is forbidden or after
  watchdog_reboot_notifier() already stopped the watchdog, avoiding
  unclocked MMIO during hibernation shutdown, and respecting the
  watchdog.stop_on_reboot module parameter.
- Patch 6 (new): Return 0 in starfive_wdt_get_timeleft() when
  !watchdog_hw_running() to avoid unclocked MMIO reads.
- Patch 7 (new): Call watchdog_stop_ping_on_suspend() in
  starfive_wdt_probe() so the ping worker does not call
  starfive_wdt_keepalive() while clocks are gated during suspend.
- Patch 8 (new): Only program hardware registers in
  starfive_wdt_set_timeout() when watchdog_hw_running() is set, and
  reload the preset counter in starfive_wdt_start() when starting from
  probe or after WDIOS_DISABLECARD.

Note on tooling and testing:
This series was generated with an AI coding assistant (Jetski / Gemini)
following analysis of reported runtime PM and lifecycle bugs in
starfive-wdt.c. All patches were build-tested with make allmodconfig and
make W=1 with zero warnings, verified with scripts/checkpatch.pl
--strict, and validated against a state-machine simulation harness
covering runtime PM, clock gating, ioctl/sysfs, suspend/shutdown, and
concurrent open paths; they were not tested on physical StarFive
JH7100/JH7110 hardware.

Cc: Xingyu Wu <xingyu.wu@starfivetech.com>
Cc: Ziv Xu <ziv.xu@starfivetech.com>

Guenter Roeck (8):
  watchdog: starfive-wdt: Drop runtime PM reference if starting watchdog
    fails
  watchdog: starfive-wdt: Balance pm_runtime_enable() on probe error
    paths
  watchdog: starfive-wdt: Avoid unclocked register access in remove and
    PM paths
  watchdog: starfive-wdt: Fix runtime PM usage count leaks in probe and
    remove
  watchdog: starfive-wdt: Drop runtime PM reference before registering
    watchdog
  watchdog: starfive-wdt: Avoid unclocked MMIO read in
    starfive_wdt_get_timeleft()
  watchdog: starfive-wdt: Stop ping worker on system suspend
  watchdog: starfive-wdt: Avoid unclocked MMIO access in
    starfive_wdt_set_timeout()

 drivers/watchdog/starfive-wdt.c | 102 ++++++++++++++++++--------------
 1 file changed, 58 insertions(+), 44 deletions(-)

-- 
2.56.0

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2026-11-06 15:51 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-05 19:05 [PATCH v2 0/8] watchdog: starfive-wdt: Fix runtime PM and unclocked register access bugs Guenter Roeck
2026-11-05 19:05 ` [PATCH v2 1/8] watchdog: starfive-wdt: Drop runtime PM reference if starting watchdog fails Guenter Roeck
2026-11-05 19:05 ` [PATCH v2 2/8] watchdog: starfive-wdt: Balance pm_runtime_enable() on probe error paths Guenter Roeck
2026-11-05 19:05 ` [PATCH v2 3/8] watchdog: starfive-wdt: Avoid unclocked register access in remove and PM paths Guenter Roeck
2026-11-06 14:21   ` Tzung-Bi Shih
2026-11-05 19:05 ` [PATCH v2 4/8] watchdog: starfive-wdt: Fix runtime PM usage count leaks in probe and remove Guenter Roeck
2026-11-05 19:05 ` [PATCH v2 5/8] watchdog: starfive-wdt: Drop runtime PM reference before registering watchdog Guenter Roeck
2026-11-05 19:05 ` [PATCH v2 6/8] watchdog: starfive-wdt: Avoid unclocked MMIO read in starfive_wdt_get_timeleft() Guenter Roeck
2026-11-06 14:22   ` Tzung-Bi Shih
2026-11-05 19:05 ` [PATCH v2 7/8] watchdog: starfive-wdt: Stop ping worker on system suspend Guenter Roeck
2026-11-06 14:22   ` Tzung-Bi Shih
2026-11-05 19:05 ` [PATCH v2 8/8] watchdog: starfive-wdt: Avoid unclocked MMIO access in starfive_wdt_set_timeout() Guenter Roeck
2026-11-06 14:21   ` Tzung-Bi Shih
2026-11-06 15:20     ` Guenter Roeck
2026-11-06 15:51       ` Tzung-Bi Shih

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox