Jean Delvare d609cb
From: Jean Delvare <jdelvare@suse.de>
Jean Delvare d609cb
Subject: watchdog: wdat_wdt: Set the min and max timeout values properly
Jean Delvare d609cb
References: bsc#1194023
Jean Delvare d609cb
Patch-mainline: submitted, 2022-08-23 https://lore.kernel.org/linux-watchdog/20220823154713.023ee771@endymion.delvare/
Jean Delvare d609cb
Jean Delvare d609cb
The wdat_wdt driver is misusing the min_hw_heartbeat_ms field. This
Jean Delvare d609cb
field should only be used when the hardware watchdog device should not
Jean Delvare d609cb
be pinged more frequently than a specific period. The ACPI WDAT
Jean Delvare d609cb
"Minimum Count" field, on the other hand, specifies the minimum
Jean Delvare d609cb
timeout value that can be set. This corresponds to the min_timeout
Jean Delvare d609cb
field in Linux's watchdog infrastructure.
Jean Delvare d609cb
Jean Delvare d609cb
Setting min_hw_heartbeat_ms instead can cause pings to the hardware
Jean Delvare d609cb
to be delayed when there is no reason for that, eventually leading to
Jean Delvare d609cb
unexpected firing of the watchdog timer (and thus unexpected reboot).
Jean Delvare d609cb
Jean Delvare d609cb
Since commit 6d72c7ac9fbe ("watchdog: wdat_wdt: Using the existing
Jean Delvare d609cb
function to check parameter timeout"), min_timeout is being set too,
Jean Delvare d609cb
but to the arbitrary value of 1 second, which doesn't make sense and
Jean Delvare d609cb
allows setting timeout values lower that the ACPI WDAT "Minimum
Jean Delvare d609cb
Count" field.
Jean Delvare d609cb
Jean Delvare d609cb
I'm also changing max_hw_heartbeat_ms to max_timeout for symmetry,
Jean Delvare d609cb
although the use of this one isn't fundamentally wrong, but there is
Jean Delvare d609cb
also no reason to enable the software-driven ping mechanism for the
Jean Delvare d609cb
wdat_wdt driver.
Jean Delvare d609cb
Jean Delvare d609cb
Signed-off-by: Jean Delvare <jdelvare@suse.de>
Jean Delvare d609cb
Fixes: 058dfc767008 ("ACPI / watchdog: Add support for WDAT hardware watchdog")
Jean Delvare d609cb
Fixes: 6d72c7ac9fbe ("watchdog: wdat_wdt: Using the existing function to check parameter timeout")
Jean Delvare d609cb
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Jean Delvare d609cb
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Jean Delvare d609cb
Cc: Wim Van Sebroeck <wim@linux-watchdog.org>
Jean Delvare d609cb
Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Jean Delvare d609cb
Cc: Liu Xinpeng <liuxp11@chinatelecom.cn>
Jean Delvare d609cb
---
Jean Delvare d609cb
 drivers/watchdog/wdat_wdt.c |    8 ++++----
Jean Delvare d609cb
 1 file changed, 4 insertions(+), 4 deletions(-)
Jean Delvare d609cb
Jean Delvare d609cb
--- a/drivers/watchdog/wdat_wdt.c
Jean Delvare d609cb
+++ b/drivers/watchdog/wdat_wdt.c
Jean Delvare d609cb
@@ -342,8 +342,8 @@ static int wdat_wdt_probe(struct platfor
Jean Delvare d609cb
 		return -EINVAL;
Jean Delvare d609cb
 
Jean Delvare d609cb
 	wdat->period = tbl->timer_period;
Jean Delvare d609cb
-	wdat->wdd.min_hw_heartbeat_ms = wdat->period * tbl->min_count;
Jean Delvare d609cb
-	wdat->wdd.max_hw_heartbeat_ms = wdat->period * tbl->max_count;
Jean Delvare d609cb
+	wdat->wdd.min_timeout = DIV_ROUND_UP(wdat->period * tbl->min_count, 1000);
Jean Delvare d609cb
+	wdat->wdd.max_timeout = wdat->period * tbl->max_count / 1000;
Jean Delvare d609cb
 	wdat->stopped_in_sleep = tbl->flags & ACPI_WDAT_STOPPED;
Jean Delvare d609cb
 	wdat->wdd.info = &wdat_wdt_info;
Jean Delvare d609cb
 	wdat->wdd.ops = &wdat_wdt_ops;
Jean Delvare d609cb
@@ -450,8 +450,8 @@ static int wdat_wdt_probe(struct platfor
Jean Delvare d609cb
 	 * watchdog properly after it has opened the device. In some cases
Jean Delvare d609cb
 	 * the BIOS default is too short and causes immediate reboot.
Jean Delvare d609cb
 	 */
Jean Delvare d609cb
-	if (timeout * 1000 < wdat->wdd.min_hw_heartbeat_ms ||
Jean Delvare d609cb
-	    timeout * 1000 > wdat->wdd.max_hw_heartbeat_ms) {
Jean Delvare d609cb
+	if (timeout < wdat->wdd.min_timeout ||
Jean Delvare d609cb
+	    timeout > wdat->wdd.max_timeout) {
Jean Delvare d609cb
 		dev_warn(dev, "Invalid timeout %d given, using %d\n",
Jean Delvare d609cb
 			 timeout, WDAT_DEFAULT_TIMEOUT);
Jean Delvare d609cb
 		timeout = WDAT_DEFAULT_TIMEOUT;