Skip to content

Commit 5d6aa89

Browse files
dvhartWim Van Sebroeck
authored andcommitted
sbsa_gwdt: Calculate timeout with 64-bit math
Commit abd3ac7 ("watchdog: sbsa: Support architecture version 1") introduced new timer math for watchdog revision 1 with the 48 bit offset register. The gwdt->clk and timeout are u32, but the argument being calculated is u64. Without a cast, the compiler performs u32 operations, truncating intermediate steps, resulting in incorrect values. A watchdog revision 1 implementation with a gwdt->clk of 1GHz and a timeout of 600s writes 3647256576 to the one shot watchdog instead of 300000000000, resulting in the watchdog firing in 3.6s instead of 600s. Force u64 math by casting the first argument (gwdt->clk) as a u64. Make the order of operations explicit with parenthesis. Fixes: abd3ac7 ("watchdog: sbsa: Support architecture version 1") Reported-by: Vanshidhar Konda <vanshikonda@os.amperecomputing.com> Signed-off-by: Darren Hart <darren@os.amperecomputing.com> Cc: Wim Van Sebroeck <wim@linux-watchdog.org> Cc: Guenter Roeck <linux@roeck-us.net> Cc: linux-watchdog@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: <stable@vger.kernel.org> # 5.14.x Reviewed-by: Guenter Roeck <linux@roeck-us.net> Link: https://lore.kernel.org/r/7d1713c5ffab19b0f3de796d82df19e8b1f340de.1695286124.git.darren@os.amperecomputing.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
1 parent b4075ec commit 5d6aa89

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

drivers/watchdog/sbsa_gwdt.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,14 +152,14 @@ static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
152152
timeout = clamp_t(unsigned int, timeout, 1, wdd->max_hw_heartbeat_ms / 1000);
153153

154154
if (action)
155-
sbsa_gwdt_reg_write(gwdt->clk * timeout, gwdt);
155+
sbsa_gwdt_reg_write((u64)gwdt->clk * timeout, gwdt);
156156
else
157157
/*
158158
* In the single stage mode, The first signal (WS0) is ignored,
159159
* the timeout is (WOR * 2), so the WOR should be configured
160160
* to half value of timeout.
161161
*/
162-
sbsa_gwdt_reg_write(gwdt->clk / 2 * timeout, gwdt);
162+
sbsa_gwdt_reg_write(((u64)gwdt->clk / 2) * timeout, gwdt);
163163

164164
return 0;
165165
}

0 commit comments

Comments
 (0)