Get the number of seconds before reboot
=======================================
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index 8e8304607a8c..0e70f510a491 100644
--- a/drivers/watchdog/watchdog_dev.c
+++ b/drivers/watchdog/watchdog_dev.c
@@ -423,6 +423,48 @@ static int watchdog_set_pretimeout(struct watchdog_device *wdd,
return err;
}
+/*
+ * watchdog_set_action: set the action the watchdog performs.
+ * @wdd: the watchdog device to set the timeout for
+ * @action: The action, one of WDIOA_xxx
+ *
+ * The caller must hold wd_data->lock.
+ */
+
+static int watchdog_set_action(struct watchdog_device *wdd,
+ unsigned int action)
+{
+ int err = 0;
+
+ if (wdd->ops->set_action)
+ err = wdd->ops->set_action(wdd, action);
+ else if (action != WDIOA_RESET)
+ err = -EINVAL;
+
+ return err;
+}
+
+/*
+ * watchdog_set_preaction: set the action the watchdog pretimeout performs.
+ * @wdd: the watchdog device to set the timeout for
+ * @action: The action, one of WDIOP_xxx
+ *
+ * The caller must hold wd_data->lock.
+ */
+
+static int watchdog_set_preaction(struct watchdog_device *wdd,
+ unsigned int action)
+{
+ int err;
+
+ if (wdd->ops->set_preaction)
+ err = wdd->ops->set_preaction(wdd, action);
+ else
+ err = -EOPNOTSUPP;
+
+ return err;
+}
+
/*
* watchdog_get_timeleft: wrapper to get the time left before a reboot
* @wdd: the watchdog device to get the remaining time from
@@ -516,6 +558,24 @@ static ssize_t pretimeout_show(struct device *dev,
}
static DEVICE_ATTR_RO(pretimeout);
+static ssize_t action_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct watchdog_device *wdd = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", wdd->action);
+}
+static DEVICE_ATTR_RO(action);
+
+static ssize_t preaction_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct watchdog_device *wdd = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", wdd->preaction);
+}
+static DEVICE_ATTR_RO(preaction);
+
static ssize_t identity_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -592,6 +652,8 @@ static struct attribute *wdt_attrs[] = {
&dev_attr_identity.attr,
&dev_attr_timeout.attr,
&dev_attr_pretimeout.attr,
+ &dev_attr_action.attr,
+ &dev_attr_preaction.attr,
&dev_attr_timeleft.attr,
&dev_attr_bootstatus.attr,
&dev_attr_status.attr,
@@ -784,6 +846,26 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
case WDIOC_GETPRETIMEOUT:
err = put_user(wdd->pretimeout, p);
break;
+ case WDIOC_SETACTION:
+ if (get_user(val, p)) {
+ err = -EFAULT;
+ break;
+ }
+ err = watchdog_set_action(wdd, val);
+ break;
+ case WDIOC_GETACTION:
+ err = put_user(wdd->action, p);
+ break;
+ case WDIOC_SETPREACTION:
+ if (get_user(val, p)) {
+ err = -EFAULT;
+ break;
+ }
+ err = watchdog_set_preaction(wdd, val);
+ break;
+ case WDIOC_GETPREACTION:
+ err = put_user(wdd->preaction, p);
+ break;
default:
err = -ENOTTY;
break;
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
index e34501a822f0..d4644994106e 100644
--- a/include/linux/watchdog.h
+++ b/include/linux/watchdog.h
@@ -53,6 +53,8 @@ struct watchdog_ops {
unsigned int (*get_timeleft)(struct watchdog_device *);
int (*restart)(struct watchdog_device *, unsigned long, void *);
long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long);
+ int (*set_action)(struct watchdog_device *wdd, unsigned int val);
+ int (*set_preaction)(struct watchdog_device *wdd, unsigned int val);
};
/** struct watchdog_device - The structure that defines a watchdog device
@@ -101,6 +103,8 @@ struct watchdog_device {
unsigned int bootstatus;
unsigned int timeout;
unsigned int pretimeout;
+ unsigned int action;
+ unsigned int preaction;
unsigned int min_timeout;
unsigned int max_timeout;
unsigned int min_hw_heartbeat_ms;
diff --git a/include/uapi/linux/watchdog.h b/include/uapi/linux/watchdog.h
index b15cde5c9054..bf13cf25f9e0 100644
--- a/include/uapi/linux/watchdog.h
+++ b/include/uapi/linux/watchdog.h
@@ -32,6 +32,10 @@ struct watchdog_info {
#define WDIOC_SETPRETIMEOUT _IOWR(WATCHDOG_IOCTL_BASE, 8, int)
#define WDIOC_GETPRETIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 9, int)
#define WDIOC_GETTIMELEFT _IOR(WATCHDOG_IOCTL_BASE, 10, int)
+#define WDIOC_SETACTION _IOWR(WATCHDOG_IOCTL_BASE, 11, int)
+#define WDIOC_GETACTION _IOR(WATCHDOG_IOCTL_BASE, 12, int)
+#define WDIOC_SETPREACTION _IOWR(WATCHDOG_IOCTL_BASE, 13, int)
+#define WDIOC_GETPREACTION _IOR(WATCHDOG_IOCTL_BASE, 14, int)
#define WDIOF_UNKNOWN -1 /* Unknown flag error */
#define WDIOS_UNKNOWN -1 /* Unknown status error */
@@ -54,5 +58,15 @@ struct watchdog_info {
#define WDIOS_ENABLECARD 0x0002 /* Turn on the watchdog timer */
#define WDIOS_TEMPPANIC 0x0004 /* Kernel panic on temperature trip */
+/* Actions for WDIOC_xxxACTION ioctls. */
+#define WDIOA_RESET 0 /* Reset the system. */
+#define WDIOA_POWER_OFF 1 /* Power off the system. */
+#define WDIOA_POWER_CYCLE 2 /* Power cycle the system. */
+
+/* Actions for WDIOC_xxxPREACTION ioctls. */
+#define WDIOP_NONE 0 /* Do nothing. */
+#define WDIOP_NMI 1 /* Issue an NMI. */
+#define WDIOP_SMI 2 /* Issue a system management irq. */
+#define WDIOP_INTERRUPT 3 /* Issue a normal irq. */
#endif /* _UAPI_LINUX_WATCHDOG_H */
--
2.17.1