Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

watchdog: core: dt: add support for the timeout-sec dt property

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>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>

authored by

Fabio Porcedda and committed by
Wim Van Sebroeck
3048253e e3e83d00

+80 -12
+13 -1
Documentation/watchdog/watchdog-kernel-api.txt
··· 1 1 The Linux WatchDog Timer Driver Core kernel API. 2 2 =============================================== 3 - Last reviewed: 22-May-2012 3 + Last reviewed: 12-Feb-2013 4 4 5 5 Wim Van Sebroeck <wim@iguana.be> 6 6 ··· 212 212 The watchdog_get_drvdata function allows you to retrieve driver specific data. 213 213 The argument of this function is the watchdog device where you want to retrieve 214 214 data from. The function returns the pointer to the driver specific data. 215 + 216 + To initialize the timeout field, the following function can be used: 217 + 218 + extern int watchdog_init_timeout(struct watchdog_device *wdd, 219 + unsigned int timeout_parm, struct device *dev); 220 + 221 + The watchdog_init_timeout function allows you to initialize the timeout field 222 + using the module timeout parameter or by retrieving the timeout-sec property from 223 + the device tree (if the module timeout parameter is invalid). Best practice is 224 + to set the default timeout value as timeout value in the watchdog_device and 225 + then use this function to set the user "preferred" timeout value. 226 + This routine returns zero on success and a negative errno code for failure.
+57 -9
drivers/watchdog/watchdog_core.c
··· 36 36 #include <linux/init.h> /* For __init/__exit/... */ 37 37 #include <linux/idr.h> /* For ida_* macros */ 38 38 #include <linux/err.h> /* For IS_ERR macros */ 39 + #include <linux/of.h> /* For of_get_timeout_sec */ 39 40 40 41 #include "watchdog_core.h" /* For watchdog_dev_register/... */ 41 42 42 43 static DEFINE_IDA(watchdog_ida); 43 44 static struct class *watchdog_class; 45 + 46 + static void watchdog_check_min_max_timeout(struct watchdog_device *wdd) 47 + { 48 + /* 49 + * Check that we have valid min and max timeout values, if 50 + * not reset them both to 0 (=not used or unknown) 51 + */ 52 + if (wdd->min_timeout > wdd->max_timeout) { 53 + pr_info("Invalid min and max timeout values, resetting to 0!\n"); 54 + wdd->min_timeout = 0; 55 + wdd->max_timeout = 0; 56 + } 57 + } 58 + 59 + /** 60 + * watchdog_init_timeout() - initialize the timeout field 61 + * @timeout_parm: timeout module parameter 62 + * @dev: Device that stores the timeout-sec property 63 + * 64 + * Initialize the timeout field of the watchdog_device struct with either the 65 + * timeout module parameter (if it is valid value) or the timeout-sec property 66 + * (only if it is a valid value and the timeout_parm is out of bounds). 67 + * If none of them are valid then we keep the old value (which should normally 68 + * be the default timeout value. 69 + * 70 + * A zero is returned on success and -EINVAL for failure. 71 + */ 72 + int watchdog_init_timeout(struct watchdog_device *wdd, 73 + unsigned int timeout_parm, struct device *dev) 74 + { 75 + unsigned int t = 0; 76 + int ret = 0; 77 + 78 + watchdog_check_min_max_timeout(wdd); 79 + 80 + /* try to get the tiemout module parameter first */ 81 + if (!watchdog_timeout_invalid(wdd, timeout_parm)) { 82 + wdd->timeout = timeout_parm; 83 + return ret; 84 + } 85 + if (timeout_parm) 86 + ret = -EINVAL; 87 + 88 + /* try to get the timeout_sec property */ 89 + if (dev == NULL || dev->of_node == NULL) 90 + return ret; 91 + of_property_read_u32(dev->of_node, "timeout-sec", &t); 92 + if (!watchdog_timeout_invalid(wdd, t)) 93 + wdd->timeout = t; 94 + else 95 + ret = -EINVAL; 96 + 97 + return ret; 98 + } 99 + EXPORT_SYMBOL_GPL(watchdog_init_timeout); 44 100 45 101 /** 46 102 * watchdog_register_device() - register a watchdog device ··· 119 63 if (wdd->ops->start == NULL || wdd->ops->stop == NULL) 120 64 return -EINVAL; 121 65 122 - /* 123 - * Check that we have valid min and max timeout values, if 124 - * not reset them both to 0 (=not used or unknown) 125 - */ 126 - if (wdd->min_timeout > wdd->max_timeout) { 127 - pr_info("Invalid min and max timeout values, resetting to 0!\n"); 128 - wdd->min_timeout = 0; 129 - wdd->max_timeout = 0; 130 - } 66 + watchdog_check_min_max_timeout(wdd); 131 67 132 68 /* 133 69 * Note: now that all watchdog_device data has been verified, we
+1 -2
drivers/watchdog/watchdog_dev.c
··· 200 200 !(wddev->info->options & WDIOF_SETTIMEOUT)) 201 201 return -EOPNOTSUPP; 202 202 203 - if ((wddev->max_timeout != 0) && 204 - (timeout < wddev->min_timeout || timeout > wddev->max_timeout)) 203 + if (watchdog_timeout_invalid(wddev, timeout)) 205 204 return -EINVAL; 206 205 207 206 mutex_lock(&wddev->lock);
+9
include/linux/watchdog.h
··· 118 118 set_bit(WDOG_NO_WAY_OUT, &wdd->status); 119 119 } 120 120 121 + /* Use the following function to check if a timeout value is invalid */ 122 + static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t) 123 + { 124 + return ((wdd->max_timeout != 0) && 125 + (t < wdd->min_timeout || t > wdd->max_timeout)); 126 + } 127 + 121 128 /* Use the following functions to manipulate watchdog driver specific data */ 122 129 static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data) 123 130 { ··· 137 130 } 138 131 139 132 /* drivers/watchdog/watchdog_core.c */ 133 + extern int watchdog_init_timeout(struct watchdog_device *wdd, 134 + unsigned int timeout_parm, struct device *dev); 140 135 extern int watchdog_register_device(struct watchdog_device *); 141 136 extern void watchdog_unregister_device(struct watchdog_device *); 142 137