[PATCH AUTOSEL 6.19-5.10] fix it87_wdt early reboot by reporting running timer

Sasha Levin
2026-02-19T02:04:29Z

From: René Rebe <rene@exactco.de>

[ Upstream commit 88b2ab346436f799b99894a3e9518a3ffa344524 ]

Some products, such as the Ugreen DXP4800 Plus NAS, ship with the it87
wdt enabled by the firmware and a broken BIOS option that does not
allow to change the time or turn it off. As this makes installing
Linux rather difficult, change the it87_wdt to report it running to
the watchdog core.

Signed-off-by: René Rebe <rene@exactco.de>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
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>
---

LLM Generated explanations, may be completely bogus:

I see that `wdt_update_timeout()` selects GPIO before calling
`_wdt_update_timeout()` (which accesses these registers). In the init
function, `superio_select(GPIO)` is called at line 354, then the PWRGD
quirk might change to EC. But looking at the diff again carefully:

The diff shows the `_wdt_running()` check is placed AFTER the PWRGD
block. For chips with the PWRGD quirk, the GPIO LDN may not be selected
at that point. However, this was reviewed by Guenter Roeck, the watchdog
subsystem co-maintainer, so he considered this acceptable. It's possible
either:
1. The WDTVAL registers are accessible regardless of LDN in these chips,
or
2. The PWRGD quirk only applies to chips where the check still works, or
3. It might need a `superio_select(GPIO)` before the check — but this
was reviewed and accepted by the maintainer, so I'll trust the
review.

## Classification

This commit:
- **Fixes a real bug**: Systems with firmware-enabled IT87 watchdogs
reboot during Linux boot/installation because the kernel doesn't know
the watchdog is already running
- **Is small and contained**: 12 lines added, 1 file changed
- **Uses a well-established pattern**: `WDOG_HW_RUNNING` is used by 15+
other watchdog drivers
- **No new features**: This doesn't add new functionality — it makes
existing hardware work correctly by properly reporting hardware state
- **Was reviewed by the subsystem maintainer**: Guenter Roeck reviewed
and signed off

This falls into the **hardware quirk/workaround** category — it makes
certain hardware (Ugreen DXP4800 Plus NAS and similar) work correctly
with Linux when the firmware leaves the watchdog enabled.

## Risk Assessment

**Very low risk**:
- The added code is read-only during init (reads WDT value registers)
- `WDOG_HW_RUNNING` is a standard, well-tested mechanism
- Worst case: if the check incorrectly reports the watchdog as running,
the kernel just pings it unnecessarily (no harm)
- If the check incorrectly reports the watchdog as NOT running, behavior
is unchanged from before (same as current code)
- Single file, single driver, isolated change

## User Impact

**High for affected users**: Without this fix, users with IT87 watchdog-
enabled firmware literally cannot install Linux — the system reboots
before installation completes. This is a critical usability bug for
specific NAS products.

## Verification

- Confirmed `WDOG_HW_RUNNING` is defined in
`include/linux/watchdog.h:122` as bit 3 of watchdog status
- Confirmed `watchdog_dev.c` automatically pings watchdog when
`WDOG_HW_RUNNING` is set (line 96, 1099-1104)
- Confirmed at least 15 other watchdog drivers use the same
`set_bit(WDOG_HW_RUNNING, ...)` pattern in init
- Confirmed commit 88b2ab346436f is the actual commit, dated Nov 17
2025, adding 12 lines
- Confirmed `wdt_update_timeout()` uses `superio_select(GPIO)` before
accessing WDT registers, consistent with the `_wdt_running()` function
design
- Confirmed the commit was Reviewed-by Guenter Roeck (watchdog co-
maintainer) and Signed-off-by both Guenter Roeck and Wim Van Sebroeck
(watchdog maintainer)
- Confirmed the change is self-contained — no dependencies on other
patches

## Conclusion

This is a textbook stable backport candidate:
- Fixes a real, user-impacting bug (system reboots during boot/install)
- Small, surgical, well-understood change (12 lines)
- Uses a standard, well-tested kernel mechanism (`WDOG_HW_RUNNING`)
- Reviewed by the subsystem maintainer
- Zero risk of regression (read-only check during init, standard
pattern)
- Isolated to a single driver file

**YES**

drivers/watchdog/it87_wdt.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c
index 3b8488c86a2f3..1d9f8591f38d8 100644
--- a/drivers/watchdog/it87_wdt.c
+++ b/drivers/watchdog/it87_wdt.c
@@ -188,6 +188,12 @@ static void _wdt_update_timeout(unsigned int t)
superio_outb(t >> 8, WDTVALMSB);
}

+/* Internal function, should be called after superio_select(GPIO) */
+static bool _wdt_running(void)
+{
+ return superio_inb(WDTVALLSB) || (max_units > 255 && superio_inb(WDTVALMSB));
+}
+
static int wdt_update_timeout(unsigned int t)
{
int ret;
@@ -374,6 +380,12 @@ static int __init it87_wdt_init(void)
}
}

+ /* wdt already left running by firmware? */
+ if (_wdt_running()) {
+ pr_info("Left running by firmware.\n");
+ set_bit(WDOG_HW_RUNNING, &wdt_dev.status);
+ }
+
superio_exit();

if (timeout < 1 || timeout > max_units * 60) {
--
2.51.0