]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
realtek: watchdog: backport watchdog fix patches
authorRustam Adilov <adilov@tutamail.com>
Fri, 10 Jul 2026 13:02:25 +0000 (18:02 +0500)
committerJonas Jelonek <jelonek.jonas@gmail.com>
Wed, 22 Jul 2026 08:10:04 +0000 (10:10 +0200)
Some issues were noticed with watchdog driver while the work
on bringing regmap API was being done.
The patches have been long accepted and are already in v7.2
of linux kernel.

As a prerequisite to the regmap patch, backport them to OpenWrt.

Signed-off-by: Rustam Adilov <adilov@tutamail.com>
Link: https://github.com/openwrt/openwrt/pull/24169
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
target/linux/realtek/patches-6.18/034-01-v7.2-watchdog-realtek-otto-prevent-PHASE2-underflows.patch [new file with mode: 0644]
target/linux/realtek/patches-6.18/034-02-v7.2-watchdog-realtek-otto-enable-clock-before-using-IO.patch [new file with mode: 0644]

diff --git a/target/linux/realtek/patches-6.18/034-01-v7.2-watchdog-realtek-otto-prevent-PHASE2-underflows.patch b/target/linux/realtek/patches-6.18/034-01-v7.2-watchdog-realtek-otto-prevent-PHASE2-underflows.patch
new file mode 100644 (file)
index 0000000..733bad8
--- /dev/null
@@ -0,0 +1,58 @@
+From 05d871c5194bef01b525ca9289efb736bbfd6ece Mon Sep 17 00:00:00 2001
+From: Sander Vanheule <sander@svanheule.net>
+Date: Fri, 15 May 2026 23:23:50 +0200
+Subject: watchdog: realtek-otto: prevent PHASE2 underflows
+
+For small pretimeout values, ((timeout - pretimeout) / tick) might be
+rounded up to the same value as (timeout / tick). As a result, the
+number of PHASE2 ticks may be zero, causing an underflow when
+subtracting 1 to configure the hardware. While this results in a
+longer-than-expected time to system reset, the duration of PHASE1 and
+minimum ping interval for the watchdog would still be correct.
+
+As the watchdog core ensures pretimeout is strictly less than timeout,
+ceil(timeout / tick) is strictly greater than floor(pretimeout / tick)
+and the number of PHASE1 ticks cannot be 0. So instead of rounding up
+the number of PHASE1 ticks, we can round down the number of PHASE2
+ticks, maintaining the current behavior while avoiding underflows.
+
+The original helper function is now inlined, as it doesn't save any
+duplication anymore.
+
+Signed-off-by: Sander Vanheule <sander@svanheule.net>
+Link: https://lore.kernel.org/r/20260515212351.752054-2-sander@svanheule.net
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+---
+ drivers/watchdog/realtek_otto_wdt.c | 12 +++---------
+ 1 file changed, 3 insertions(+), 9 deletions(-)
+
+(limited to 'drivers/watchdog/realtek_otto_wdt.c')
+
+--- a/drivers/watchdog/realtek_otto_wdt.c
++++ b/drivers/watchdog/realtek_otto_wdt.c
+@@ -114,12 +114,6 @@ static int otto_wdt_tick_ms(struct otto_
+  * the value stored in those fields. This means each phase will run for at least
+  * one tick, so small values need to be clamped to correctly reflect the timeout.
+  */
+-static inline unsigned int div_round_ticks(unsigned int val, unsigned int tick_duration,
+-              unsigned int min_ticks)
+-{
+-      return max(min_ticks, DIV_ROUND_UP(val, tick_duration));
+-}
+-
+ static int otto_wdt_determine_timeouts(struct watchdog_device *wdev, unsigned int timeout,
+               unsigned int pretimeout)
+ {
+@@ -140,9 +134,9 @@ static int otto_wdt_determine_timeouts(s
+                       return -EINVAL;
+               tick_ms = otto_wdt_tick_ms(ctrl, prescale);
+-              total_ticks = div_round_ticks(timeout_ms, tick_ms, 2);
+-              phase1_ticks = div_round_ticks(timeout_ms - pretimeout_ms, tick_ms, 1);
+-              phase2_ticks = total_ticks - phase1_ticks;
++              total_ticks = max(2, DIV_ROUND_UP(timeout_ms, tick_ms));
++              phase2_ticks = max(1, pretimeout_ms / tick_ms);
++              phase1_ticks = total_ticks - phase2_ticks;
+               prescale_next++;
+       } while (phase1_ticks > OTTO_WDT_PHASE_TICKS_MAX
diff --git a/target/linux/realtek/patches-6.18/034-02-v7.2-watchdog-realtek-otto-enable-clock-before-using-IO.patch b/target/linux/realtek/patches-6.18/034-02-v7.2-watchdog-realtek-otto-enable-clock-before-using-IO.patch
new file mode 100644 (file)
index 0000000..c04cf1d
--- /dev/null
@@ -0,0 +1,41 @@
+From 1147eb0dc29bd33aa3499f9d02777d4165587575 Mon Sep 17 00:00:00 2001
+From: Sander Vanheule <sander@svanheule.net>
+Date: Fri, 15 May 2026 23:23:51 +0200
+Subject: watchdog: realtek-otto: enable clock before using I/O
+
+As the watchdog is normally on the same bus as the UART peripheral, the
+bootloader will have ensured the bus' clock is up and running before the
+watchdog driver is probed. Nevertheless, let's do things the right way
+and enable the watchdog's clock before performing I/O accesses.
+
+Signed-off-by: Sander Vanheule <sander@svanheule.net>
+Link: https://lore.kernel.org/r/20260515212351.752054-3-sander@svanheule.net
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+---
+ drivers/watchdog/realtek_otto_wdt.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+(limited to 'drivers/watchdog/realtek_otto_wdt.c')
+
+--- a/drivers/watchdog/realtek_otto_wdt.c
++++ b/drivers/watchdog/realtek_otto_wdt.c
+@@ -296,15 +296,15 @@ static int otto_wdt_probe(struct platfor
+       if (IS_ERR(ctrl->base))
+               return PTR_ERR(ctrl->base);
++      ret = otto_wdt_probe_clk(ctrl);
++      if (ret)
++              return ret;
++
+       /* Clear any old interrupts and reset initial state */
+       iowrite32(OTTO_WDT_INTR_PHASE_1 | OTTO_WDT_INTR_PHASE_2,
+                       ctrl->base + OTTO_WDT_REG_INTR);
+       iowrite32(OTTO_WDT_CTRL_DEFAULT, ctrl->base + OTTO_WDT_REG_CTRL);
+-      ret = otto_wdt_probe_clk(ctrl);
+-      if (ret)
+-              return ret;
+-
+       ctrl->irq_phase1 = platform_get_irq_byname(pdev, "phase1");
+       if (ctrl->irq_phase1 < 0)
+               return ctrl->irq_phase1;