summaryrefslogtreecommitdiffstats
path: root/sys/dev/watchdog/watchdog.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/watchdog/watchdog.c')
-rw-r--r--sys/dev/watchdog/watchdog.c64
1 files changed, 51 insertions, 13 deletions
diff --git a/sys/dev/watchdog/watchdog.c b/sys/dev/watchdog/watchdog.c
index 06498c9..e7edf31 100644
--- a/sys/dev/watchdog/watchdog.c
+++ b/sys/dev/watchdog/watchdog.c
@@ -40,35 +40,73 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
static struct cdev *wd_dev;
+static volatile u_int wd_last_u;
+
+static int
+kern_do_pat(u_int utim)
+{
+ int error;
+
+ if ((utim & WD_LASTVAL) != 0 && (utim & WD_INTERVAL) > 0)
+ return (EINVAL);
+
+ if ((utim & WD_LASTVAL) != 0) {
+ MPASS((wd_last_u & ~WD_INTERVAL) == 0);
+ utim &= ~WD_LASTVAL;
+ utim |= wd_last_u;
+ } else
+ wd_last_u = (utim & WD_INTERVAL);
+ 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 */
+ error = EOPNOTSUPP;
+ }
+ EVENTHANDLER_INVOKE(watchdog_list, utim, &error);
+ return (error);
+}
static int
wd_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
int flags __unused, struct thread *td)
{
- int error;
u_int u;
if (cmd != WDIOCPATPAT)
return (ENOIOCTL);
u = *(u_int *)data;
- if (u & ~(WD_ACTIVE | WD_PASSIVE | WD_INTERVAL))
+ if (u & ~(WD_ACTIVE | WD_PASSIVE | WD_LASTVAL | WD_INTERVAL))
return (EINVAL);
if ((u & (WD_ACTIVE | WD_PASSIVE)) == (WD_ACTIVE | WD_PASSIVE))
return (EINVAL);
- if ((u & (WD_ACTIVE | WD_PASSIVE)) == 0 && (u & WD_INTERVAL) > 0)
+ if ((u & (WD_ACTIVE | WD_PASSIVE)) == 0 && ((u & WD_INTERVAL) > 0 ||
+ (u & WD_LASTVAL) != 0))
return (EINVAL);
if (u & WD_PASSIVE)
return (ENOSYS); /* XXX Not implemented yet */
- if ((u & WD_INTERVAL) == WD_TO_NEVER) {
- u = 0;
- /* Assume all is well; watchdog signals failure. */
- error = 0;
- } else {
- /* Assume no watchdog available; watchdog flags success */
- error = EOPNOTSUPP;
- }
- EVENTHANDLER_INVOKE(watchdog_list, u, &error);
- return (error);
+ u &= ~(WD_ACTIVE | WD_PASSIVE);
+
+ return (kern_do_pat(u));
+}
+
+u_int
+wdog_kern_last_timeout(void)
+{
+
+ return (wd_last_u);
+}
+
+int
+wdog_kern_pat(u_int utim)
+{
+
+ if (utim & ~(WD_LASTVAL | WD_INTERVAL))
+ return (EINVAL);
+
+ return (kern_do_pat(utim));
}
static struct cdevsw wd_cdevsw = {
OpenPOWER on IntegriCloud