]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
watchdog: core: dt: add support for the timeout-sec dt property
authorFabio Porcedda <fabio.porcedda@gmail.com>
Tue, 8 Jan 2013 10:04:10 +0000 (11:04 +0100)
committerWim Van Sebroeck <wim@iguana.be>
Thu, 14 Feb 2013 21:01:54 +0000 (22:01 +0100)
Add support for watchdog drivers to initialize/set the timeout field
of the watchdog_device structure. The timeout field is initialised
either with the module timeout parameter value (if valid) or with the
timeout-sec dt property (if valid). If both are invalid the initial
value is unchanged.

Signed-off-by: Fabio Porcedda <fabio.porcedda@gmail.com>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Documentation/watchdog/watchdog-kernel-api.txt
drivers/watchdog/watchdog_core.c
drivers/watchdog/watchdog_dev.c
include/linux/watchdog.h

index 086638f6c82d2e37d92e2aefa94243c5b1b74b13..a0438f3957cad82a29ee8f90753709e9d673056c 100644 (file)
@@ -1,6 +1,6 @@
 The Linux WatchDog Timer Driver Core kernel API.
 ===============================================
-Last reviewed: 22-May-2012
+Last reviewed: 12-Feb-2013
 
 Wim Van Sebroeck <wim@iguana.be>
 
@@ -212,3 +212,15 @@ driver specific data to and a pointer to the data itself.
 The watchdog_get_drvdata function allows you to retrieve driver specific data.
 The argument of this function is the watchdog device where you want to retrieve
 data from. The function returns the pointer to the driver specific data.
+
+To initialize the timeout field, the following function can be used:
+
+extern int watchdog_init_timeout(struct watchdog_device *wdd,
+                                  unsigned int timeout_parm, struct device *dev);
+
+The watchdog_init_timeout function allows you to initialize the timeout field
+using the module timeout parameter or by retrieving the timeout-sec property from
+the device tree (if the module timeout parameter is invalid). Best practice is
+to set the default timeout value as timeout value in the watchdog_device and
+then use this function to set the user "preferred" timeout value.
+This routine returns zero on success and a negative errno code for failure.
index 3796434991faa83466c85c8779a072db1278ef33..05d18b4c661b2c15904982e6385944b1ca5515d1 100644 (file)
 #include <linux/init.h>                /* For __init/__exit/... */
 #include <linux/idr.h>         /* For ida_* macros */
 #include <linux/err.h>         /* For IS_ERR macros */
+#include <linux/of.h>          /* For of_get_timeout_sec */
 
 #include "watchdog_core.h"     /* For watchdog_dev_register/... */
 
 static DEFINE_IDA(watchdog_ida);
 static struct class *watchdog_class;
 
+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)
+        */
+       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;
+       }
+}
+
+/**
+ * watchdog_init_timeout() - initialize the timeout field
+ * @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.
+ *
+ * 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)
+{
+       unsigned int t = 0;
+       int ret = 0;
+
+       watchdog_check_min_max_timeout(wdd);
+
+       /* try to get the tiemout module parameter first */
+       if (!watchdog_timeout_invalid(wdd, timeout_parm)) {
+               wdd->timeout = timeout_parm;
+               return ret;
+       }
+       if (timeout_parm)
+               ret = -EINVAL;
+
+       /* 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))
+               wdd->timeout = t;
+       else
+               ret = -EINVAL;
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(watchdog_init_timeout);
+
 /**
  * watchdog_register_device() - register a watchdog device
  * @wdd: watchdog device
@@ -63,15 +119,7 @@ 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;
-       }
+       watchdog_check_min_max_timeout(wdd);
 
        /*
         * Note: now that all watchdog_device data has been verified, we
index ef8edecfc526cedaa27bb22b23a2729289221f1b..08b48bbf9f4b2d3c65cf18045ff90c1465c9787f 100644 (file)
@@ -200,8 +200,7 @@ static int watchdog_set_timeout(struct watchdog_device *wddev,
            !(wddev->info->options & WDIOF_SETTIMEOUT))
                return -EOPNOTSUPP;
 
-       if ((wddev->max_timeout != 0) &&
-           (timeout < wddev->min_timeout || timeout > wddev->max_timeout))
+       if (watchdog_timeout_invalid(wddev, timeout))
                return -EINVAL;
 
        mutex_lock(&wddev->lock);
index 3a9df2f43be642a7cbad15f678ef29c7f85f27e5..2a3038ee17a33a3f6b4b4bee7b25dc6f0f633b04 100644 (file)
@@ -118,6 +118,13 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway
                set_bit(WDOG_NO_WAY_OUT, &wdd->status);
 }
 
+/* Use the following function to check if a timeout value is invalid */
+static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
+{
+       return ((wdd->max_timeout != 0) &&
+               (t < wdd->min_timeout || t > wdd->max_timeout));
+}
+
 /* Use the following functions to manipulate watchdog driver specific data */
 static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data)
 {
@@ -130,6 +137,8 @@ static inline void *watchdog_get_drvdata(struct watchdog_device *wdd)
 }
 
 /* drivers/watchdog/watchdog_core.c */
+extern int watchdog_init_timeout(struct watchdog_device *wdd,
+                                 unsigned int timeout_parm, struct device *dev);
 extern int watchdog_register_device(struct watchdog_device *);
 extern void watchdog_unregister_device(struct watchdog_device *);