Some watchdog drivers, such as w83793, have a very low timeout granularity
of only one minute. The procd default timeout of 30s will yield an effective
timeout of 0 with this driver, leading to an almost instant reset once
activated.
In order to gracefully deal with watchdogs having no sub-30s resolution,
check that the effectively calculated timeout returned by the ioctl() call
is zero and retry with a duplicated timeout value in this case.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
static int watchdog_set_drv_timeout(void)
{
+ int timeout = wdt_drv_timeout;
+ int rv;
+
if (wdt_fd < 0)
return -1;
- return ioctl(wdt_fd, WDIOC_SETTIMEOUT, &wdt_drv_timeout);
+ while (1) {
+ rv = ioctl(wdt_fd, WDIOC_SETTIMEOUT, &timeout);
+
+ if (rv != 0)
+ break;
+
+ if (timeout == 0 && wdt_drv_timeout != 0) {
+ DEBUG(2, "Watchdog timeout %d too low, retrying with %d\n", wdt_drv_timeout, wdt_drv_timeout * 2);
+
+ wdt_drv_timeout *= 2;
+ timeout = wdt_drv_timeout;
+
+ continue;
+ }
+
+ wdt_drv_timeout = timeout;
+ break;
+ }
+
+ return rv;
}
static void watchdog_print_status(void)