The branch main has been updated by jhibbits: URL: https://cgit.FreeBSD.org/src/commit/?id=69f7d6912a24d3caab4957a33e07529275cf4d09
commit 69f7d6912a24d3caab4957a33e07529275cf4d09 Author: Justin Hibbits <jhibb...@freebsd.org> AuthorDate: 2025-02-26 20:17:24 +0000 Commit: Justin Hibbits <jhibb...@freebsd.org> CommitDate: 2025-08-14 19:02:46 +0000 watchdog: Add a new "Control" ioctl Summary: In preparation for a new watchdog timeout interface using sbintime_t, add a new control ioctl to arm, pat, and disarm the watchdog. Reviewed by: jhb, phk Sponsored by: Juniper Networks, Inc. Differential Revision: https://reviews.freebsd.org/D49182 --- sys/dev/watchdog/watchdog.c | 20 ++++++++++++++++++++ sys/sys/watchdog.h | 8 ++++++++ usr.sbin/watchdogd/watchdogd.c | 13 +++++++++++-- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/sys/dev/watchdog/watchdog.c b/sys/dev/watchdog/watchdog.c index e6b6dc1eac70..c0babef1b29b 100644 --- a/sys/dev/watchdog/watchdog.c +++ b/sys/dev/watchdog/watchdog.c @@ -117,6 +117,23 @@ seconds_to_pow2ns(int seconds) 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); + } else if ((ctrl & WD_CTRL_ENABLE) != 0) { + wdog_kern_pat(WD_ACTIVE | WD_LASTVAL); + } + + return (0); +} + int wdog_kern_pat(u_int utim) { @@ -374,6 +391,9 @@ wd_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data, 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 index 4a16b18509f5..3c9d31eb577b 100644 --- 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 @@ EVENTHANDLER_DECLARE(watchdog_list, watchdog_fn); 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 index 88b467486da1..228438955006 100644 --- a/usr.sbin/watchdogd/watchdogd.c +++ b/usr.sbin/watchdogd/watchdogd.c @@ -396,6 +396,15 @@ watchdog_patpat(u_int t) 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 @@ watchdog_onoff(int onoff) /* 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); }