aboutsummaryrefslogtreecommitdiff
path: root/drivers/watchdog/watchdog_core.c
diff options
context:
space:
mode:
authorFu Wei <fu.wei@linaro.org>2015-06-10 18:58:34 +0800
committerGraeme Gregory <graeme.gregory@linaro.org>2015-07-20 14:22:54 +0100
commit68d341a283cec206dd313de0e2d91dc0b70e037f (patch)
tree19e450f38b4ea3abb28015979dca84fc6bde2a9f /drivers/watchdog/watchdog_core.c
parent7291ef7c1411e8b2900345534b482cdf3ebdd6b3 (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.c98
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)
{