git: 26d6617f3e54 - main - watchdog: Convert to using sbintime_t format

From: Justin Hibbits <jhibbits_at_FreeBSD.org>
Date: Thu, 14 Aug 2025 19:03:09 UTC
The branch main has been updated by jhibbits:

URL: https://cgit.FreeBSD.org/src/commit/?id=26d6617f3e5406d9f92d87674f1667dd856828a3

commit 26d6617f3e5406d9f92d87674f1667dd856828a3
Author:     Justin Hibbits <jhibbits@FreeBSD.org>
AuthorDate: 2025-02-26 20:25:36 +0000
Commit:     Justin Hibbits <jhibbits@FreeBSD.org>
CommitDate: 2025-08-14 19:02:46 +0000

    watchdog: Convert to using sbintime_t format
    
    Summary:
    Some watchdogs are now based on a countdown timer instead of a bit
    check.  To deal with these, convert the watchdog framework to use
    sbintime_t instead of power-of-2-nanoseconds.  This allows more
    precision, and more variety of watchdog timeouts.  Keep the old method
    as a compatibility layer, so that drivers can be migrated slowly, as
    needed.
    
    Reviewed by:    jhb
    Sponsored by:   Juniper Networks, Inc.
    Differential Revision: https://reviews.freebsd.org/D49183
---
 sys/dev/watchdog/watchdog.c    | 202 ++++++++++++++++++++++-------------------
 sys/sys/watchdog.h             |  17 ++--
 usr.sbin/watchdogd/watchdogd.c |  99 +++++---------------
 3 files changed, 143 insertions(+), 175 deletions(-)

diff --git a/sys/dev/watchdog/watchdog.c b/sys/dev/watchdog/watchdog.c
index c0babef1b29b..e1b2e08c3f10 100644
--- a/sys/dev/watchdog/watchdog.c
+++ b/sys/dev/watchdog/watchdog.c
@@ -50,11 +50,20 @@
 
 #include <sys/syscallsubr.h> /* kern_clock_gettime() */
 
-static int wd_set_pretimeout(int newtimeout, int disableiftoolong);
+#ifdef	COMPAT_FREEBSD14
+#define WDIOCPATPAT_14	_IOW('W', 42, u_int)	/* pat the watchdog */
+#define WDIOC_SETTIMEOUT_14   _IOW('W', 43, int)	/* set/reset the timer */
+#define WDIOC_GETTIMEOUT_14    _IOR('W', 44, int)	/* get total timeout */
+#define WDIOC_GETTIMELEFT_14   _IOR('W', 45, int)	/* get time left */
+#define WDIOC_GETPRETIMEOUT_14 _IOR('W', 46, int)	/* get the pre-timeout */
+#define WDIOC_SETPRETIMEOUT_14 _IOW('W', 47, int)	/* set the pre-timeout */
+#endif
+
+static int wd_set_pretimeout(sbintime_t newtimeout, int disableiftoolong);
 static void wd_timeout_cb(void *arg);
 
 static struct callout wd_pretimeo_handle;
-static int wd_pretimeout;
+static sbintime_t wd_pretimeout;
 static int wd_pretimeout_act = WD_SOFT_LOG;
 
 static struct callout wd_softtimeo_handle;
@@ -63,6 +72,8 @@ static int wd_softtimer;	/* true = use softtimer instead of hardware
 static int wd_softtimeout_act = WD_SOFT_LOG;	/* action for the software timeout */
 
 static struct cdev *wd_dev;
+static volatile sbintime_t wd_last_sbt;	/* last timeout value (sbt) */
+static sbintime_t wd_last_sbt_sysctl;	/* last timeout value (sbt) */
 static volatile u_int wd_last_u;    /* last timeout value set by kern_do_pat */
 static u_int wd_last_u_sysctl;    /* last timeout value set by kern_do_pat */
 static u_int wd_last_u_sysctl_secs;    /* wd_last_u in seconds */
@@ -73,6 +84,8 @@ SYSCTL_UINT(_hw_watchdog, OID_AUTO, wd_last_u, CTLFLAG_RD,
     &wd_last_u_sysctl, 0, "Watchdog last update time");
 SYSCTL_UINT(_hw_watchdog, OID_AUTO, wd_last_u_secs, CTLFLAG_RD,
     &wd_last_u_sysctl_secs, 0, "Watchdog last update time");
+SYSCTL_SBINTIME_MSEC(_hw_watchdog, OID_AUTO, wd_last_msecs, CTLFLAG_RD,
+    &wd_last_sbt_sysctl, "Watchdog last update time (milliseconds)");
 
 static int wd_lastpat_valid = 0;
 static time_t wd_lastpat = 0;	/* when the watchdog was last patted */
@@ -80,41 +93,26 @@ static time_t wd_lastpat = 0;	/* when the watchdog was last patted */
 /* Hook for external software watchdog to register for use if needed */
 void (*wdog_software_attach)(void);
 
-static void
-pow2ns_to_ts(int pow2ns, struct timespec *ts)
+/* Legacy interface to watchdog. */
+int
+wdog_kern_pat(u_int utim)
 {
-	uint64_t ns;
+	sbintime_t sbt;
 
-	ns = 1ULL << pow2ns;
-	ts->tv_sec = ns / 1000000000ULL;
-	ts->tv_nsec = ns % 1000000000ULL;
-}
+	if ((utim & WD_LASTVAL) != 0 && (utim & WD_INTERVAL) > 0)
+		return (EINVAL);
 
-static int
-pow2ns_to_ticks(int pow2ns)
-{
-	struct timeval tv;
-	struct timespec ts;
+	if ((utim & WD_LASTVAL) != 0) {
+		return (wdog_control(WD_CTRL_RESET));
+	}
 
-	pow2ns_to_ts(pow2ns, &ts);
-	TIMESPEC_TO_TIMEVAL(&tv, &ts);
-	return (tvtohz(&tv));
-}
+	utim &= WD_INTERVAL;
+	if (utim == WD_TO_NEVER)
+		sbt = 0;
+	else
+		sbt = nstosbt(1 << utim);
 
-static int
-seconds_to_pow2ns(int seconds)
-{
-	uint64_t power;
-	uint64_t ns;
-	uint64_t shifted;
-
-	ns = ((uint64_t)seconds) * 1000000000ULL;
-	power = flsll(ns);
-	shifted = 1ULL << power;
-	if (shifted <= ns) {
-		power++;
-	}
-	return (power);
+	return (wdog_kern_pat_sbt(sbt));
 }
 
 int
@@ -126,76 +124,63 @@ wdog_control(int ctrl)
 	}
 
 	if ((ctrl & WD_CTRL_RESET) != 0) {
-		wdog_kern_pat(WD_ACTIVE | WD_LASTVAL);
+		wdog_kern_pat_sbt(wd_last_sbt);
 	} else if ((ctrl & WD_CTRL_ENABLE) != 0) {
-		wdog_kern_pat(WD_ACTIVE | WD_LASTVAL);
+		wdog_kern_pat_sbt(wd_last_sbt);
 	}
 
 	return (0);
 }
 
 int
-wdog_kern_pat(u_int utim)
+wdog_kern_pat_sbt(sbintime_t sbt)
 {
-	int error;
-	static int first = 1;
-
-	if ((utim & WD_LASTVAL) != 0 && (utim & WD_INTERVAL) > 0)
-		return (EINVAL);
-
-	if ((utim & WD_LASTVAL) != 0) {
-		/*
-		 * if WD_LASTVAL is set, fill in the bits for timeout
-		 * from the saved value in wd_last_u.
-		 */
-		MPASS((wd_last_u & ~WD_INTERVAL) == 0);
-		utim &= ~WD_LASTVAL;
-		utim |= wd_last_u;
-	} else {
-		/*
-		 * Otherwise save the new interval.
-		 * This can be zero (to disable the watchdog)
-		 */
-		wd_last_u = (utim & WD_INTERVAL);
+	sbintime_t error_sbt = 0;
+	int pow2ns = 0;
+	int error = 0;
+	static bool first = true;
+
+	/* legacy uses power-of-2-nanoseconds time. */
+	if (sbt != 0) {
+		pow2ns = flsl(sbttons(sbt));
+	}
+	if (wd_last_sbt != sbt) {
+		wd_last_u = pow2ns;
 		wd_last_u_sysctl = wd_last_u;
-		wd_last_u_sysctl_secs = pow2ns_to_ticks(wd_last_u) / hz;
+		wd_last_u_sysctl_secs = sbt / SBT_1S;
+
+		wd_last_sbt = sbt;
 	}
-	if ((utim & WD_INTERVAL) == WD_TO_NEVER) {
-		utim = 0;
 
-		/* Assume all is well; watchdog signals failure. */
-		error = 0;
-	} else {
-		/* Assume no watchdog available; watchdog flags success */
+	if (sbt != 0)
 		error = EOPNOTSUPP;
-	}
+
 	if (wd_softtimer) {
-		if (utim == 0) {
+		if (sbt == 0) {
 			callout_stop(&wd_softtimeo_handle);
 		} else {
-			(void) callout_reset(&wd_softtimeo_handle,
-			    pow2ns_to_ticks(utim), wd_timeout_cb, "soft");
+			(void) callout_reset_sbt(&wd_softtimeo_handle,
+			    sbt, 0, wd_timeout_cb, "soft", 0);
 		}
 		error = 0;
 	} else {
-		EVENTHANDLER_INVOKE(watchdog_list, utim, &error);
+		EVENTHANDLER_INVOKE(watchdog_sbt_list, sbt, &error_sbt, &error);
+		EVENTHANDLER_INVOKE(watchdog_list, pow2ns, &error);
 	}
 	/*
-	 * If we no hardware watchdog responded, we have not tried to
+	 * If no hardware watchdog responded, we have not tried to
 	 * attach an external software watchdog, and one is available,
 	 * attach it now and retry.
 	 */
-	if (error == EOPNOTSUPP && first && *wdog_software_attach != NULL) {
+	if (error == EOPNOTSUPP && first && wdog_software_attach != NULL) {
 		(*wdog_software_attach)();
-		EVENTHANDLER_INVOKE(watchdog_list, utim, &error);
+		EVENTHANDLER_INVOKE(watchdog_sbt_list, sbt, &error_sbt, &error);
+		EVENTHANDLER_INVOKE(watchdog_list, pow2ns, &error);
 	}
-	first = 0;
+	first = false;
 
+	/* TODO: Print a (rate limited?) warning if error_sbt is too far away */
 	wd_set_pretimeout(wd_pretimeout, true);
-	/*
-	 * If we were able to arm/strobe the watchdog, then
-	 * update the last time it was strobed for WDIOC_GETTIMELEFT
-	 */
 	if (!error) {
 		struct timespec ts;
 
@@ -206,6 +191,7 @@ wdog_kern_pat(u_int utim)
 			wd_lastpat_valid = 1;
 		}
 	}
+
 	return (error);
 }
 
@@ -282,16 +268,14 @@ wd_timeout_cb(void *arg)
  * current actual watchdog timeout.
  */
 static int
-wd_set_pretimeout(int newtimeout, int disableiftoolong)
+wd_set_pretimeout(sbintime_t newtimeout, int disableiftoolong)
 {
-	u_int utime;
-	struct timespec utime_ts;
-	int timeout_ticks;
+	sbintime_t utime;
+	sbintime_t timeout_left;
 
-	utime = wdog_kern_last_timeout();
-	pow2ns_to_ts(utime, &utime_ts);
+	utime = wdog_kern_last_timeout_sbt();
 	/* do not permit a pre-timeout >= than the timeout. */
-	if (newtimeout >= utime_ts.tv_sec) {
+	if (newtimeout >= utime) {
 		/*
 		 * If 'disableiftoolong' then just fall through
 		 * so as to disable the pre-watchdog
@@ -309,7 +293,7 @@ wd_set_pretimeout(int newtimeout, int disableiftoolong)
 		return 0;
 	}
 
-	timeout_ticks = pow2ns_to_ticks(utime) - (hz*newtimeout);
+	timeout_left = utime - newtimeout;
 #if 0
 	printf("wd_set_pretimeout: "
 	    "newtimeout: %d, "
@@ -323,8 +307,8 @@ wd_set_pretimeout(int newtimeout, int disableiftoolong)
 #endif
 
 	/* We determined the value is sane, so reset the callout */
-	(void) callout_reset(&wd_pretimeo_handle,
-	    timeout_ticks, wd_timeout_cb, "pre");
+	(void) callout_reset_sbt(&wd_pretimeo_handle,
+	    timeout_left, 0, wd_timeout_cb, "pre", 0);
 	wd_pretimeout = newtimeout;
 	return 0;
 }
@@ -333,6 +317,7 @@ static int
 wd_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
     int flags __unused, struct thread *td)
 {
+	sbintime_t sb;
 	u_int u;
 	time_t timeleft;
 	int error;
@@ -368,32 +353,55 @@ wd_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
 			error = EINVAL;
 		}
 		break;
-	case WDIOC_GETPRETIMEOUT:
-		*(int *)data = (int)wd_pretimeout;
+#ifdef	COMPAT_FREEBSD14
+	case WDIOC_GETPRETIMEOUT_14:
+		*(int *)data = (int)(wd_pretimeout / SBT_1S);
 		break;
-	case WDIOC_SETPRETIMEOUT:
-		error = wd_set_pretimeout(*(int *)data, false);
+	case WDIOC_SETPRETIMEOUT_14:
+		error = wd_set_pretimeout(*(int *)data * SBT_1S, false);
 		break;
-	case WDIOC_GETTIMELEFT:
+	case WDIOC_GETTIMELEFT_14:
 		error = wd_get_time_left(td, &timeleft);
 		if (error)
 			break;
 		*(int *)data = (int)timeleft;
 		break;
-	case WDIOC_SETTIMEOUT:
+	case WDIOC_SETTIMEOUT_14:
 		u = *(u_int *)data;
-		error = wdog_kern_pat(seconds_to_pow2ns(u));
+		error = wdog_kern_pat_sbt(mstosbt(u * 1000ULL));
 		break;
-	case WDIOC_GETTIMEOUT:
+	case WDIOC_GETTIMEOUT_14:
 		u = wdog_kern_last_timeout();
 		*(u_int *)data = u;
 		break;
-	case WDIOCPATPAT:
+	case WDIOCPATPAT_14:
 		error = wd_ioctl_patpat(data);
 		break;
+#endif
+
+	/* New API */
 	case WDIOC_CONTROL:
 		wdog_control(*(int *)data);
 		break;
+	case WDIOC_SETTIMEOUT:
+		sb = *(sbintime_t *)data;
+		error = wdog_kern_pat_sbt(sb);
+		break;
+	case WDIOC_GETTIMEOUT:
+		*(sbintime_t *)data = wdog_kern_last_timeout_sbt();
+		break;
+	case WDIOC_GETTIMELEFT:
+		error = wd_get_time_left(td, &timeleft);
+		if (error)
+			break;
+		*(sbintime_t *)data = (sbintime_t)timeleft * SBT_1S;
+		break;
+	case WDIOC_GETPRETIMEOUT:
+		*(sbintime_t *)data = wd_pretimeout;
+		break;
+	case WDIOC_SETPRETIMEOUT:
+		error = wd_set_pretimeout(*(sbintime_t *)data, false);
+		break;
 	default:
 		error = ENOIOCTL;
 		break;
@@ -412,6 +420,12 @@ wdog_kern_last_timeout(void)
 	return (wd_last_u);
 }
 
+sbintime_t
+wdog_kern_last_timeout_sbt(void)
+{
+	return (wd_last_sbt);
+}
+
 static struct cdevsw wd_cdevsw = {
 	.d_version =	D_VERSION,
 	.d_ioctl =	wd_ioctl,
diff --git a/sys/sys/watchdog.h b/sys/sys/watchdog.h
index 3c9d31eb577b..8401d343a6b7 100644
--- a/sys/sys/watchdog.h
+++ b/sys/sys/watchdog.h
@@ -32,15 +32,16 @@
 #define	_SYS_WATCHDOG_H
 
 #include <sys/ioccom.h>
+#include <sys/_types.h>
 
 #define	_PATH_WATCHDOG	"fido"
 
-#define WDIOCPATPAT	_IOW('W', 42, u_int)	/* pat the watchdog */
-#define WDIOC_SETTIMEOUT    _IOW('W', 43, int)	/* set/reset the timer */
-#define WDIOC_GETTIMEOUT    _IOR('W', 44, int)	/* get total timeout */
-#define WDIOC_GETTIMELEFT   _IOR('W', 45, int)	/* get time left */
-#define WDIOC_GETPRETIMEOUT _IOR('W', 46, int)	/* get the pre-timeout */
-#define WDIOC_SETPRETIMEOUT _IOW('W', 47, int)	/* set the pre-timeout */
+#define WDIOC_PATPAT	    _IOW('W', 52, sbintime_t)	/* pat the watchdog */
+#define WDIOC_SETTIMEOUT    _IOW('W', 53, sbintime_t)	/* set/reset the timer */
+#define WDIOC_GETTIMEOUT    _IOR('W', 54, sbintime_t)	/* get total timeout */
+#define WDIOC_GETTIMELEFT   _IOR('W', 55, sbintime_t)	/* get time left */
+#define WDIOC_GETPRETIMEOUT _IOR('W', 56, sbintime_t)	/* get the pre-timeout */
+#define WDIOC_SETPRETIMEOUT _IOW('W', 57, sbintime_t)	/* set the pre-timeout */
 /* set the action when a pre-timeout occurs see: WD_SOFT_* */
 #define WDIOC_SETPRETIMEOUTACT _IOW('W', 48, int)
 
@@ -112,11 +113,15 @@
 #include <sys/_eventhandler.h>
 
 typedef void (*watchdog_fn)(void *, u_int, int *);
+typedef void (*watchdog_sbt_fn)(void *, sbintime_t, sbintime_t *, int *);
 
 EVENTHANDLER_DECLARE(watchdog_list, watchdog_fn);
+EVENTHANDLER_DECLARE(watchdog_sbt_list, watchdog_sbt_fn);
 
 u_int	wdog_kern_last_timeout(void);
 int	wdog_kern_pat(u_int utim);
+sbintime_t	wdog_kern_last_timeout_sbt(void);
+int		wdog_kern_pat_sbt(sbintime_t utim);
 int		wdog_control(int ctrl);
 
 /*
diff --git a/usr.sbin/watchdogd/watchdogd.c b/usr.sbin/watchdogd/watchdogd.c
index 228438955006..27123f2143d0 100644
--- a/usr.sbin/watchdogd/watchdogd.c
+++ b/usr.sbin/watchdogd/watchdogd.c
@@ -63,25 +63,25 @@
 static long	fetchtimeout(int opt,
     const char *longopt, const char *myoptarg, int zero_ok);
 static void	parseargs(int, char *[]);
-static int	seconds_to_pow2ns(int);
 static void	sighandler(int);
 static void	watchdog_loop(void);
 static int	watchdog_init(void);
 static int	watchdog_onoff(int onoff);
-static int	watchdog_patpat(u_int timeout);
+static int	watchdog_patpat(sbintime_t);
 static void	usage(void);
-static int	tstotv(struct timeval *tv, struct timespec *ts);
 static int	tvtohz(struct timeval *tv);
 
 static int debugging = 0;
 static int end_program = 0;
 static const char *pidfile = _PATH_VARRUN "watchdogd.pid";
-static u_int timeout = WD_TO_128SEC;
+static sbintime_t timeout = 128 * SBT_1S;
 static u_int exit_timeout = WD_TO_NEVER;
 static u_int pretimeout = 0;
 static u_int timeout_sec;
 static u_int nap = 10;
+#ifdef notyet
 static int passive = 0;
+#endif
 static int is_daemon = 0;
 static int is_dry_run = 0;  /* do not arm the watchdog, only
 			       report on timing of the watch
@@ -174,38 +174,23 @@ main(int argc, char *argv[])
 		pidfile_remove(pfh);
 		return (EX_OK);
 	} else {
-		if (passive)
-			timeout |= WD_PASSIVE;
-		else
-			timeout |= WD_ACTIVE;
 		if (watchdog_patpat(timeout) < 0)
 			err(EX_OSERR, "patting the dog");
 		return (EX_OK);
 	}
 }
 
-static void
-pow2ns_to_ts(int pow2ns, struct timespec *ts)
-{
-	uint64_t ns;
-
-	ns = 1ULL << pow2ns;
-	ts->tv_sec = ns / 1000000000ULL;
-	ts->tv_nsec = ns % 1000000000ULL;
-}
-
 /*
  * Convert a timeout in seconds to N where 2^N nanoseconds is close to
  * "seconds".
  *
  * The kernel expects the timeouts for watchdogs in "2^N nanosecond format".
  */
-static u_int
-parse_timeout_to_pow2ns(char opt, const char *longopt, const char *myoptarg)
+static sbintime_t
+parse_timeout_to_sbt(char opt, const char *longopt, const char *myoptarg)
 {
-	double a;
-	u_int rv;
-	struct timespec ts;
+	long a;
+	sbintime_t rv;
 	struct timeval tv;
 	int ticks;
 	char shortopt[] = "- ";
@@ -216,19 +201,17 @@ parse_timeout_to_pow2ns(char opt, const char *longopt, const char *myoptarg)
 	a = fetchtimeout(opt, longopt, myoptarg, 1);
 
 	if (a == 0)
-		rv = WD_TO_NEVER;
+		rv = 0;
 	else
-		rv = seconds_to_pow2ns(a);
-	pow2ns_to_ts(rv, &ts);
-	tstotv(&tv, &ts);
+		rv = a * SBT_1S;
+	tv = sbttotv(rv);
 	ticks = tvtohz(&tv);
 	if (debugging) {
 		printf("Timeout for %s%s "
-		    "is 2^%d nanoseconds "
-		    "(in: %s sec -> out: %jd sec %ld ns -> %d ticks)\n",
+		    "is "
+		    "(in: %s sec -> out: %jd sec %ld us -> %d ticks)\n",
 		    longopt ? "-" : "", longopt ? longopt : shortopt,
-		    rv,
-		    myoptarg, (intmax_t)ts.tv_sec, ts.tv_nsec, ticks);
+		    myoptarg, (intmax_t)tv.tv_sec, tv.tv_usec, ticks);
 	}
 	if (ticks <= 0) {
 		errx(1, "Timeout for %s%s is too small, please choose a higher timeout.", longopt ? "-" : "", longopt ? longopt : shortopt);
@@ -364,7 +347,7 @@ watchdog_loop(void)
 		}
 
 		if (failed == 0)
-			watchdog_patpat(timeout|WD_ACTIVE);
+			watchdog_patpat(timeout);
 
 		waited = watchdog_check_dogfunction_time(&ts_start, &ts_end);
 		if (nap - waited > 0)
@@ -387,13 +370,13 @@ try_end:
  * to keep the watchdog from firing.
  */
 static int
-watchdog_patpat(u_int t)
+watchdog_patpat(sbintime_t sbt)
 {
 
 	if (is_dry_run)
 		return 0;
 
-	return ioctl(fd, WDIOCPATPAT, &t);
+	return ioctl(fd, WDIOC_SETTIMEOUT, &sbt);
 }
 
 static int
@@ -429,7 +412,7 @@ watchdog_onoff(int onoff)
 			warn("setting WDIOC_SETSOFT %d", softtimeout_set);
 			return (error);
 		}
-		error = watchdog_patpat((timeout|WD_ACTIVE));
+		error = watchdog_patpat(timeout);
 		if (error) {
 			warn("watchdog_patpat failed");
 			goto failsafe;
@@ -461,7 +444,7 @@ watchdog_onoff(int onoff)
 			}
 		}
 		/* pat one more time for good measure */
-		return watchdog_patpat((timeout|WD_ACTIVE));
+		return watchdog_patpat(timeout);
 	 } else {
 		return watchdog_control(WD_CTRL_DISABLE);
 	 }
@@ -576,15 +559,6 @@ timeout_act_str2int(const char *lopt, const char *acts)
 	return rv;
 }
 
-int
-tstotv(struct timeval *tv, struct timespec *ts)
-{
-
-	tv->tv_sec = ts->tv_sec;
-	tv->tv_usec = ts->tv_nsec / 1000;
-	return 0;
-}
-
 /*
  * Convert a timeval to a number of ticks.
  * Mostly copied from the kernel.
@@ -656,30 +630,6 @@ tvtohz(struct timeval *tv)
 	return ((int)ticks);
 }
 
-static int
-seconds_to_pow2ns(int seconds)
-{
-	uint64_t power;
-	uint64_t ns;
-	uint64_t shifted;
-
-	if (seconds <= 0)
-		errx(1, "seconds %d < 0", seconds);
-	ns = ((uint64_t)seconds) * 1000000000ULL;
-	power = flsll(ns);
-	shifted = 1ULL << power;
-	if (shifted <= ns) {
-		power++;
-	}
-	if (debugging) {
-		printf("shifted %lld\n", (long long)shifted);
-		printf("seconds_to_pow2ns: seconds: %d, ns %lld, power %d\n",
-		    seconds, (long long)ns, (int)power);
-	}
-	return (power);
-}
-
-
 /*
  * Handle the few command line arguments supported.
  */
@@ -692,8 +642,7 @@ parseargs(int argc, char *argv[])
 	const char *lopt;
 
 	/* Get the default value of timeout_sec from the default timeout. */
-	pow2ns_to_ts(timeout, &ts);
-	timeout_sec = ts.tv_sec;
+	timeout_sec = sbintime_getsec(timeout);
 
 	/*
 	 * if we end with a 'd' aka 'watchdogd' then we are the daemon program,
@@ -736,10 +685,10 @@ parseargs(int argc, char *argv[])
 			break;
 		case 't':
 			timeout_sec = atoi(optarg);
-			timeout = parse_timeout_to_pow2ns(c, NULL, optarg);
+			timeout = parse_timeout_to_sbt(c, NULL, optarg);
 			if (debugging)
-				printf("Timeout is 2^%d nanoseconds\n",
-				    timeout);
+				printf("Timeout is %d\n",
+				    (int)(timeout / SBT_1S));
 			break;
 		case 'T':
 			carp_thresh_seconds =
@@ -749,7 +698,7 @@ parseargs(int argc, char *argv[])
 			do_timedog = 1;
 			break;
 		case 'x':
-			exit_timeout = parse_timeout_to_pow2ns(c, NULL, optarg);
+			exit_timeout = parse_timeout_to_sbt(c, NULL, optarg);
 			if (exit_timeout != 0)
 				exit_timeout |= WD_ACTIVE;
 			break;