watchdog: retry with larger timeout value if effective timeout is 0 staging/stintel/watchdog
authorJo-Philipp Wich <jo@mein.io>
Fri, 17 Jun 2022 07:47:51 +0000 (09:47 +0200)
committerStijn Tintel <stijn@linux-ipv6.be>
Thu, 23 Jun 2022 08:57:33 +0000 (11:57 +0300)
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>
watchdog.c

index bedb545975a0562a7377b61647482a0748970c8a..a2689a5a3cb4468e9ee31ca643d129ba751f7286 100644 (file)
@@ -87,10 +87,32 @@ static void watchdog_close(void)
 
 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)