diff --git a/sys/dev/watchdog/watchdog.c b/sys/dev/watchdog/watchdog.c --- a/sys/dev/watchdog/watchdog.c +++ b/sys/dev/watchdog/watchdog.c @@ -117,6 +117,25 @@ return (power); } +int +wdog_control(int ctrl) +{ + /* Disable takes precedence */ + if (ctrl == WD_CTRL_DISABLE) { + wdog_kern_pat(0); + } + + if ((ctrl & WD_CTRL_RESET) != 0) { + wdog_kern_pat(WD_ACTIVE | WD_LASTVAL); + } + + if ((ctrl & WD_CTRL_ENABLE) != 0) { + wdog_kern_pat(WD_ACTIVE | WD_LASTVAL); + } + + return (0); +} + int wdog_kern_pat(u_int utim) { @@ -374,6 +393,9 @@ case WDIOCPATPAT: error = wd_ioctl_patpat(data); break; + case WDIOC_CONTROL: + wdog_control(*(int *)data); + break; default: error = ENOIOCTL; break; diff --git a/sys/sys/watchdog.h b/sys/sys/watchdog.h --- a/sys/sys/watchdog.h +++ b/sys/sys/watchdog.h @@ -48,6 +48,8 @@ #define WDIOC_SETSOFT _IOW('W', 49, int) #define WDIOC_SETSOFTTIMEOUTACT _IOW('W', 50, int) +#define WDIOC_CONTROL _IOW('W', 51, int) /* configure watchdog */ + #define WD_ACTIVE 0x8000000 /* * Watchdog reset, timeout set to value in WD_INTERVAL field. @@ -93,6 +95,11 @@ #define WD_TO_64SEC 36 #define WD_TO_128SEC 37 +/* Control options for WDIOC_CONTROL */ +#define WD_CTRL_DISABLE 0x00000000 +#define WD_CTRL_ENABLE 0x00000001 +#define WD_CTRL_RESET 0x00000002 + /* action on pre-timeout trigger */ #define WD_SOFT_PANIC 0x01 /* panic */ #define WD_SOFT_DDB 0x02 /* enter debugger */ @@ -110,6 +117,7 @@ u_int wdog_kern_last_timeout(void); int wdog_kern_pat(u_int utim); +int wdog_control(int ctrl); /* * The following function pointer is used to attach a software watchdog diff --git a/usr.sbin/watchdogd/watchdogd.c b/usr.sbin/watchdogd/watchdogd.c --- a/usr.sbin/watchdogd/watchdogd.c +++ b/usr.sbin/watchdogd/watchdogd.c @@ -396,6 +396,15 @@ return ioctl(fd, WDIOCPATPAT, &t); } +static int +watchdog_control(u_int control) +{ + if (is_dry_run) + return (0); + + return ioctl(fd, WDIOC_CONTROL, &control); +} + /* * Toggle the kernel's watchdog. This routine is used to enable and * disable the watchdog. @@ -454,10 +463,10 @@ /* pat one more time for good measure */ return watchdog_patpat((timeout|WD_ACTIVE)); } else { - return watchdog_patpat(exit_timeout); + return watchdog_control(WD_CTRL_DISABLE); } failsafe: - watchdog_patpat(exit_timeout); + watchdog_control(WD_CTRL_DISABLE); return (error); }