[26.04_linux-nvidia-bos] NVIDIA: SAUCE: watchdog: sbsa_gwdt: park the watchdog around system sleep on MediaTek implementations - #628
Conversation
BaseOS Kernel ReviewWarning
|
PR Validation ReportPatchscan ✅ No Missing FixesAll cherry-picked commits checked — no missing upstream fixes found. PR Lint ✅ All checks passedDetailsChecking 1 commits... Cherry-pick digest: ┌──────────────┬──────────────────────────────────────────────────────────────────┬────────────┬─────────┬───────────────────────────┐ │ Local │ Referenced upstream / Patch subject │ Patch-ID │ Subject │ SoB chain │ ├──────────────┼──────────────────────────────────────────────────────────────────┼────────────┼─────────┼───────────────────────────┤ │ b86b42888d6a │ [SAUCE] watchdog: sbsa_gwdt: park the watchdog around system sle │ N/A │ N/A │ kbutala, dcemin │ └──────────────┴──────────────────────────────────────────────────────────────────┴────────────┴─────────┴───────────────────────────┘ Lint: all checks passed. |
nirmoy
left a comment
There was a problem hiding this comment.
Codex found these issues
Codex confirmed two concerns also raised by Boro—parking on unaffected implementations and timeout updates interfering with parking—and identified an additional timeout regression. Please take a look at the inline comments and let me know what you think.
Here is the requested Launchpad bug for this pair: LP #2169002.
Review covered the driver changes and watchdog-core interactions. No build or hardware tests were run.
| struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd); | ||
|
|
||
| timeout = sbsa_gwdt_program_wor(gwdt, timeout); | ||
| wdd->timeout = timeout; |
There was a problem hiding this comment.
[P1] Preserve the requested timeout
This now stores the clamped hardware timeout in wdd->timeout. Previously, that field retained the requested timeout so the watchdog core could support longer timeouts through periodic keepalives. For example, with an 8-second hardware limit, requesting 60 seconds now records 8 seconds and disables the worker that previously extended the timeout. This also affects v0 devices. Please preserve the requested value in wdd->timeout and clamp only the hardware programming.
| { | ||
| struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd); | ||
|
|
||
| timeout = sbsa_gwdt_program_wor(gwdt, timeout); |
There was a problem hiding this comment.
[P1] Keep timeout updates from undoing parking
After WDIOS_DISABLECARD, userspace can still issue WDIOC_SETTIMEOUT on the same descriptor. Stop now leaves the hardware enabled, so this unconditional WOR write replaces the parked period with a short timeout. The core has cleared WDOG_HW_RUNNING and stopped feeding the watchdog, allowing an unexpected reset. Please preserve the parked value while stopped or sleeping, save the requested timeout for the next start, and synchronize timeout programming with the parking path.
| * 4 s at 1 GHz, so parking is only useful with the 48-bit register; | ||
| * version 0 keeps the architectural disable. | ||
| */ | ||
| if (gwdt->version == 0) { |
There was a problem hiding this comment.
[P2] Limit parking to affected implementations
Checking only the version applies this workaround to every v1 watchdog, including non-MediaTek implementations. It also changes ordinary stop and magic-close behavior: hardware remains enabled while the core considers it stopped and stops supplying keepalives. The parked period is finite, so it can eventually expire and reset the system. Please gate parking on the affected implementation and retain architectural disable for unaffected hardware.
|
This applies to both #627 and #628, which carry the same commit. The points below are in addition to the Codex/Boro comments already posted. 1. Probe undoes the park, the same way 2. Implementer gating is more than P2. On a non-MediaTek v1 watchdog, the parked state is also reached from 3. Long sleeps on the affected platform. A parked watchdog stays enabled through the sleep. An s2idle longer than about 78 h asserts WS0. With 4. Upstream plan. The PR, commit and MR 28 don't mention one, and nothing has been posted to linux-watchdog. This builds on 9c77d37, which carries the v1 at https://lore.kernel.org/r/20260912182107.1156221-1-dcemin@nvidia.com. Guenter answered that posting on 2026-09-17: "this is the wrong solution". He said any fix belongs in the watchdog core and should "leave the watchdog running but ping it from the kernel while the suspend operation is going on". There has been no reply on the list since. The MediaTek property found here is a concrete implementer quirk, which makes a stronger upstream case than the generic notifier. Parking is also closer to what Guenter described. Is the plan to reply on that thread and post the park as an implementer quirk? Guenter's 2026-09-29 core series may also overlap, especially "watchdog: core: Prevent ping worker from re-arming timer on suspend" ( Commit hygiene
For the record, Boro's "WS0 workaround missed after IRQ fallback" is pre-existing. The base already calls
|
6cd3ec0 to
328f3bd
Compare
|
Thanks both, all points taken; new heads pushed to both PRs (607d5a2 / 328f3bd).
|
|
Can you check the high finding from Boro review. |
328f3bd to
c2a35f2
Compare
|
@clsotog on the Boro High: it describes the design, and there is no software alternative on this implementation. We measured that clearing WCS.EN does not stop the compare on the MediaTek block (EN cleared, one refresh, reset two periods later, no sleep involved), so the architectural disable never actually disabled anything here; what looked like a stopped watchdog was one whose last reload happened to be stale. The park replaces "fires within seconds of a stop" with "fires after about 78 hours if nothing restores it", which only a sleep longer than that can reach; the commit message states it as a known limitation, and every other implementation keeps the architectural disable (park_on_stop is MediaTek-only). If a shorter window is preferred we can restore the timeout from the resume path earlier, but no ordering of register writes removes the finite period on this hardware. The Low (start-path comment overstating when a parked period exists) is fixed in the new heads (81c08ea / c2a35f2). On the GPU/DOCA compile status on 627: both GPU driver versions (615.71.09 and 580.178.04) compiled successfully against the PR kernel; the only failure is the DOCA 3.3.0 out-of-tree build (OFED 26.01.1.0.0.1), whose configure step exits 2 against 7.0.14. That is independent of a change in drivers/watchdog. |
thanks for the explanation but looks it will not close the finding from Boro. if MediaTek cannot be truly disabled in software, then ordinary .stop() must not report success. Parking is reasonable for sleep because there is a bounded suspend/resume transition that re-arms the watchdog. It is not a valid implementation of userspace disable/magic-close because the watchdog remains able to expire. |
|
Thanks @clsotog for the thorough review, agreed, the explanation does not close it. New approach for the next heads: on the MediaTek implementation the driver will not offer a .stop op at all. The core then handles WDIOS_DISABLECARD and magic close as "hardware cannot be stopped" (WDOG_HW_RUNNING set, kernel worker keeps refreshing), which is the documented model for such hardware and the same path this driver already uses when it adopts a firmware armed watchdog at probe. No finite countdown after a userspace disable. Parking is confined to the system sleep path and to driver removal (with a warning), and other implementations keep the architectural disable on stop. Since the reboot notifier calls ops->stop directly, the MediaTek instance will not register it. We measured earlier that clearing WCS.EN with a fresh reload still resets this block, so the old stop never disabled anything here either; this change makes that explicit. Will push after board validation. |
c2a35f2 to
42f9ca3
Compare
|
New heads pushed: 8be4fe9 on 627, 42f9ca3 on 628, same driver content on both. Changes since the last round:
Validated on the reference laptop with a 10 s period (module inserted by hand, action=0): magic close and WDIOS_DISABLECARD followed by 2 and 40 minutes idle, no reset, where the old stop path reset the unit within about 10 s in the same test; four suspend cycles including two real sleeps of 1 to 2 minutes, all resumed with the period live; unbind logs "watchdog cannot be stopped, left parked" and the unit stays up, rebind restores the configured period. |
42f9ca3 to
7570293
Compare
|
On the new Boro High (version 0 MediaTek blocks still exposed as stoppable): new heads 63d7f3f on 627 and 7570293 on 628. The missing stop op is now gated on the implementer alone, so a version 0 MediaTek block gets no stop op either. Around a sleep it keeps the architectural disable, since its 32-bit WOR cannot hold a park period, and the removal warning reports it as armed rather than parked. No such part has been measured; the version 1 path is unchanged from the heads validated earlier today. |
|
I still get this finding: |
7570293 to
333499c
Compare
|
New heads: 8a322fb on 627, 333499c on 628. Three changes for this round:
Also the removal comment nit (Low on 627). Builds clean with W=1, checkpatch clean apart from the two pre-existing warnings. The restart-after-sleep sequence is unchanged apart from the commit wait; a sanity run on the reference laptop is in progress and I will report it here. |
|
thanks for the changes. I got this finding: |
…leep on MediaTek implementations BugLink: https://bugs.launchpad.net/bugs/2169002 Laptops built on the MT8901 ACPI platform reset intermittently around system suspend, both S3 and s2idle, with the SBSA generic watchdog enabled. Register-level measurements on the reference laptop show three properties of the MediaTek watchdog implementation that the driver has to work with: - the compare logic ignores WCS.EN: a watchdog that was disabled but refreshed a few seconds earlier still fires when the period elapses, while one whose last reload is long past never does; - a WOR write is only latched into the countdown while WCS.EN is set, although the register reads back the written value either way; - WCV reads back the counter value of the last reload, not the deadline. Around a system sleep the driver clears WCS.EN, but the watchdog core keeps refreshing the hardware until the CPUs go offline, so the last reload is a few seconds old when the platform enters the sleep state and the watchdog fires while nobody can refresh it. Whether the wake beats the second stage decides between a spurious wake, a reset a few seconds after resume, and a reset during the sleep, which is the intermittent pattern seen across the fleet. The platform firmware also disables the watchdog before WFI and re-enables it on the way out of the sleep, which latches whatever period the register holds onto the reload from before the sleep and produces the resume-side resets. The MediaTek implementation therefore cannot be stopped, and the driver stops pretending that it can: such an instance registers no stop op, so WDIOS_DISABLECARD and a magic close leave the watchdog running with the core refreshing it (WDOG_HW_RUNNING), the same path the driver already takes for a watchdog found armed at probe. The reboot notifier, which calls the stop op directly, is not registered for it. A running watchdog must not lose its driver either: the core already pins the module while the hardware runs, and the driver now suppresses the sysfs bind attributes, so only a probe failure can leave an armed instance behind, parked with a warning. Around a system sleep nobody can refresh the watchdog, so park it there: program WOR to the 48-bit maximum while WCS.EN is set and refresh, so the pending reload is days away, and leave WCS.EN set. A parked, enabled watchdog cannot fire for days, every later refresh (the core's keepalives until the CPUs go offline) reloads with the parked period again, and should a park ever fail the first stage wakes the system instead of the second stage resetting it. On resume, set WCS.EN, refresh so the reload moves to now while the parked period is still in effect, then restore the configured timeout (the WOR write is only taken while enabled) and refresh again. On a first start, with the block disabled, the order is enable, program, refresh instead: the period firmware left behind may be zero or expired and must not be used for a reload. Other implementations keep the architectural disable, on stop and around a sleep. A version 0 MediaTek block, should one exist, gets no stop op either, and since its 32-bit WOR cannot hold a park period the driver refuses a system sleep while such a watchdog is armed rather than let it fire unrefreshed. The block commits WOR on its own clock, tens of kHz, and a refresh issued right after the write reloads with whatever it holds at that moment. Two measures make the park robust against that: the two 32-bit halves are written high half first when parking (a mixed value is then new-high:old-low, at least 2^32 ticks) and low half first when restoring (a mixed value is the parked period again, fixed by the next keepalive), and the park waits for the commit before refreshing and refreshes twice. Without this the park failed intermittently: with the default 10 s timeout the mixed value the other way round is 8.6 s, which showed up as a reset about 17 s after any sleep entry on one unit while another unit of the same model was mostly unaffected. The timeout is not programmed into WOR while a sleep transition is in progress, so a probe that finds a firmware-armed watchdog during the transition cannot replace the parked period with a short one; the restart programs it. Every WOR write waits for the block to commit the new period before returning, so a refresh issued right after it (the core pings after WDIOC_SETTIMEOUT) reloads with the new period. wdd->timeout keeps the requested value, as the core expects; only the hardware programming is clamped. An instance joins the list the sleep notifier works on only once its timeout and mode are final, so a restart racing the probe programs the configured period. Known limitation: a parked watchdog stays enabled through the sleep with a finite period, about 78 hours at 1 GHz. A sleep longer than that asserts WS0 before the resume path restores the timeout, which panics with action=1 or resets about 78 hours later with action=0. The property that causes this is in the hardware; multi-day sleeps were not tested. Validated on two laptops of the platform, including the unit that failed every earlier variant: repeated S3 and s2idle cycles resume without a reset, WOR reads the configured value after resume and WS0 asserts at the configured period again, so the watchdog is live after the sleep rather than left parked. A magic close and WDIOS_DISABLECARD leave it running under the core, where the old stop path reset the unit about two periods later. Signed-off-by: Kaushal Rajeev Butala <kbutala@nvidia.com> Co-developed-by: David Cemin <dcemin@nvidia.com> Signed-off-by: David Cemin <dcemin@nvidia.com>
333499c to
b86b428
Compare
|
New heads: d2de08b on 627, b86b428 on 628.
Builds clean with W=1, checkpatch clean apart from the two pre-existing warnings. The restart-after-sleep sequence is unchanged from the validated heads apart from the commit wait added in the previous round; the sanity run on the reference laptop for these two rounds is still pending and I will report it here. |
|
Thanks no more findings from me. |
|
|
|
Merged, closing PR. |
Intermittent resets around system suspend (S3 and s2idle) on the MT8901 ACPI laptop platform with the SBSA generic watchdog enabled.
Root cause, measured at register level on the reference laptop: the MediaTek watchdog implementation keeps comparing against the last reload after WCS.EN is cleared, latches a WOR write into the countdown only while WCS.EN is set (the register reads back the written value either way), and commits the two WOR halves on a slow clock. The driver disables the watchdog at suspend prepare, but the core keeps refreshing it until the CPUs go offline, so the platform enters the sleep with a fresh 5 s deadline that nobody can feed; the firmware re-enable after WFI then latches the short period onto the pre-sleep reload and produces the resume-side resets.
Fix: park instead of disable. On stop, program WOR to the 48-bit maximum (high half first) while enabled, wait for the commit and refresh twice, and leave WCS.EN set; on start, enable, refresh, restore the timeout (low half first) and refresh again. Version 0 watchdogs keep the architectural disable.
Validated on two laptops of the platform, including the unit that failed every earlier variant: repeated S3 and s2idle cycles (5 + 5 on that unit) resume without a reset, WOR reads the configured value after resume and WS0 asserts at the configured period, so the watchdog is live after the sleep. Same change under review as the downstream distribution MR.
Internal tracking: NVBugs 6813557 and 6783303.
bos twin of #627.
BugLink: https://bugs.launchpad.net/bugs/2169002