diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt index 829955bd245e..4f7c894244d2 100644 --- a/Documentation/watchdog/watchdog-kernel-api.txt +++ b/Documentation/watchdog/watchdog-kernel-api.txt @@ -43,6 +43,8 @@ struct watchdog_device { const struct watchdog_ops *ops; unsigned int bootstatus; unsigned int timeout; + unsigned int min_timeout; + unsigned int max_timeout; void *driver_data; unsigned long status; }; @@ -52,6 +54,8 @@ It contains following fields: additional information about the watchdog timer itself. (Like it's unique name) * ops: a pointer to the list of watchdog operations that the watchdog supports. * timeout: the watchdog timer's timeout value (in seconds). +* min_timeout: the watchdog timer's minimum timeout value (in seconds). +* max_timeout: the watchdog timer's maximum timeout value (in seconds). * bootstatus: status of the device after booting (reported with watchdog WDIOF_* status bits). * driver_data: a pointer to the drivers private data of a watchdog device. diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c index 47fc1267ad4e..cfa1a1518aad 100644 --- a/drivers/watchdog/watchdog_core.c +++ b/drivers/watchdog/watchdog_core.c @@ -58,6 +58,16 @@ int watchdog_register_device(struct watchdog_device *wdd) if (wdd->ops->start == NULL || wdd->ops->stop == NULL) return -EINVAL; + /* + * Check that we have valid min and max timeout values, if + * not reset them both to 0 (=not used or unknown) + */ + if (wdd->min_timeout > wdd->max_timeout) { + pr_info("Invalid min and max timeout values, resetting to 0!\n"); + wdd->min_timeout = 0; + wdd->max_timeout = 0; + } + /* * Note: now that all watchdog_device data has been verified, we * will not check this anymore in other functions. If data gets diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index e7134a5979c6..d33520d0b4c9 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -220,6 +220,9 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd, return -EOPNOTSUPP; if (get_user(val, p)) return -EFAULT; + if ((wdd->max_timeout != 0) && + (val < wdd->min_timeout || val > wdd->max_timeout)) + return -EINVAL; err = wdd->ops->set_timeout(wdd, val); if (err < 0) return err; diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h index 325d90b6641b..111843f88b2a 100644 --- a/include/linux/watchdog.h +++ b/include/linux/watchdog.h @@ -95,6 +95,8 @@ struct watchdog_ops { * @ops: Pointer to the list of watchdog operations. * @bootstatus: Status of the watchdog device at boot. * @timeout: The watchdog devices timeout value. + * @min_timeout:The watchdog devices minimum timeout value. + * @max_timeout:The watchdog devices maximum timeout value. * @driver-data:Pointer to the drivers private data. * @status: Field that contains the devices internal status bits. * @@ -109,6 +111,8 @@ struct watchdog_device { const struct watchdog_ops *ops; unsigned int bootstatus; unsigned int timeout; + unsigned int min_timeout; + unsigned int max_timeout; void *driver_data; unsigned long status; /* Bit numbers for status flags */