diff options
author | Fu Wei <fu.wei@linaro.org> | 2015-06-10 18:58:34 +0800 |
---|---|---|
committer | Graeme Gregory <graeme.gregory@linaro.org> | 2015-07-20 14:22:54 +0100 |
commit | 68d341a283cec206dd313de0e2d91dc0b70e037f (patch) | |
tree | 19e450f38b4ea3abb28015979dca84fc6bde2a9f /drivers/watchdog/watchdog_core.c | |
parent | 7291ef7c1411e8b2900345534b482cdf3ebdd6b3 (diff) |
Watchdog: introdouce "pretimeout" into framework
Also update Documentation/watchdog/watchdog-kernel-api.txt to
introduce:
(1)the new elements in the watchdog_device and watchdog_ops struct;
(2)the new API "watchdog_init_timeouts"
Reasons:
(1)kernel already has two watchdog drivers are using "pretimeout":
drivers/char/ipmi/ipmi_watchdog.c
drivers/watchdog/kempld_wdt.c(but the definition is different)
(2)some other drivers are going to use this: ARM SBSA Generic Watchdog
Signed-off-by: Fu Wei <fu.wei@linaro.org>
Diffstat (limited to 'drivers/watchdog/watchdog_core.c')
-rw-r--r-- | drivers/watchdog/watchdog_core.c | 98 |
1 files changed, 70 insertions, 28 deletions
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c index 1a8059455413..280c3993f715 100644 --- a/drivers/watchdog/watchdog_core.c +++ b/drivers/watchdog/watchdog_core.c @@ -85,57 +85,99 @@ static void watchdog_deferred_registration_del(struct watchdog_device *wdd) static void watchdog_check_min_max_timeout(struct watchdog_device *wdd) { /* - * Check that we have valid min and max timeout values, if - * not reset them both to 0 (=not used or unknown) + * Check that we have valid min and max pretimeout and timeout values, + * if not, reset them all 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"); + if (wdd->min_pretimeout > wdd->max_pretimeout || + wdd->min_timeout > wdd->max_timeout || + wdd->min_timeout < wdd->min_pretimeout || + wdd->max_timeout < wdd->max_pretimeout) { + pr_info("Invalid min or max timeouts, resetting to 0\n"); + wdd->min_pretimeout = 0; + wdd->max_pretimeout = 0; wdd->min_timeout = 0; wdd->max_timeout = 0; } } /** - * watchdog_init_timeout() - initialize the timeout field + * watchdog_init_timeouts() - initialize the pretimeout and timeout field + * @pretimeout_parm: pretimeout module parameter * @timeout_parm: timeout module parameter * @dev: Device that stores the timeout-sec property * - * Initialize the timeout field of the watchdog_device struct with either the - * timeout module parameter (if it is valid value) or the timeout-sec property - * (only if it is a valid value and the timeout_parm is out of bounds). - * If none of them are valid then we keep the old value (which should normally - * be the default timeout value. + * Initialize the pretimeout and timeout field of the watchdog_device struct + * with both the pretimeout and timeout module parameters (if they are valid) or + * the timeout-sec property (only if they are valid and the pretimeout_parm or + * timeout_parm is out of bounds). If one of them is invalid, then we keep + * the old value (which should normally be the default timeout value). * * A zero is returned on success and -EINVAL for failure. */ -int watchdog_init_timeout(struct watchdog_device *wdd, - unsigned int timeout_parm, struct device *dev) +int watchdog_init_timeouts(struct watchdog_device *wdd, + unsigned int pretimeout_parm, + unsigned int timeout_parm, + struct device *dev) { - unsigned int t = 0; - int ret = 0; + int ret = 0, length = 0; + u32 timeouts[2] = {0}; + struct property *prop; watchdog_check_min_max_timeout(wdd); - /* try to get the timeout module parameter first */ - if (!watchdog_timeout_invalid(wdd, timeout_parm) && timeout_parm) { - wdd->timeout = timeout_parm; - return ret; - } - if (timeout_parm) + /* + * Try to get the pretimeout module parameter first. + * Note: zero is a valid value for pretimeout. + */ + if (watchdog_pretimeout_invalid(wdd, pretimeout_parm)) + ret = -EINVAL; + + /* + * Try to get the timeout module parameter, + * if it's valid and pretimeout is valid(ret == 0), + * assignment and return zero. Otherwise, try dtb. + */ + if (timeout_parm && !ret) { + if (!watchdog_timeout_invalid(wdd, timeout_parm)) { + wdd->timeout = timeout_parm; + wdd->pretimeout = pretimeout_parm; + return 0; + } ret = -EINVAL; + } - /* try to get the timeout_sec property */ + /* + * Either at least one of the module parameters is invalid, + * or timeout_parm is 0. Try to get the timeout_sec property. + */ if (dev == NULL || dev->of_node == NULL) return ret; - of_property_read_u32(dev->of_node, "timeout-sec", &t); - if (!watchdog_timeout_invalid(wdd, t) && t) - wdd->timeout = t; - else - ret = -EINVAL; - return ret; + prop = of_find_property(dev->of_node, "timeout-sec", &length); + if (prop && length > 0 && length <= sizeof(u32) * 2) { + of_property_read_u32_array(dev->of_node, + "timeout-sec", timeouts, + length / sizeof(u32)); + if (length == sizeof(u32) * 2) { + if (watchdog_pretimeout_invalid(wdd, timeouts[1])) + return -EINVAL; + ret = 0; + } else { + ret = -EINVAL; + } + + if (!watchdog_timeout_invalid(wdd, timeouts[0]) && + timeouts[0]) { + wdd->timeout = timeouts[0]; + if (!ret) + wdd->pretimeout = timeouts[1]; + return 0; + } + } + + return -EINVAL; } -EXPORT_SYMBOL_GPL(watchdog_init_timeout); +EXPORT_SYMBOL_GPL(watchdog_init_timeouts); static int __watchdog_register_device(struct watchdog_device *wdd) { |