diff options
author | Fabio Porcedda <fabio.porcedda@gmail.com> | 2013-01-08 05:04:10 -0500 |
---|---|---|
committer | Wim Van Sebroeck <wim@iguana.be> | 2013-03-01 06:48:36 -0500 |
commit | 3048253ed957fc6cdc34599178408559aa1e0062 (patch) | |
tree | 2e8fd94c3d64899dc4a48912f7ece62721047c68 | |
parent | e3e83d0001a77cdb337be9170e58b55488835ba0 (diff) |
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>
-rw-r--r-- | Documentation/watchdog/watchdog-kernel-api.txt | 14 | ||||
-rw-r--r-- | drivers/watchdog/watchdog_core.c | 66 | ||||
-rw-r--r-- | drivers/watchdog/watchdog_dev.c | 3 | ||||
-rw-r--r-- | include/linux/watchdog.h | 9 |
4 files changed, 80 insertions, 12 deletions
diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt index 086638f6c82d..a0438f3957ca 100644 --- a/Documentation/watchdog/watchdog-kernel-api.txt +++ b/Documentation/watchdog/watchdog-kernel-api.txt | |||
@@ -1,6 +1,6 @@ | |||
1 | The Linux WatchDog Timer Driver Core kernel API. | 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 | Wim Van Sebroeck <wim@iguana.be> | 5 | Wim Van Sebroeck <wim@iguana.be> |
6 | 6 | ||
@@ -212,3 +212,15 @@ driver specific data to and a pointer to the data itself. | |||
212 | The watchdog_get_drvdata function allows you to retrieve driver specific data. | 212 | The watchdog_get_drvdata function allows you to retrieve driver specific data. |
213 | The argument of this function is the watchdog device where you want to retrieve | 213 | The argument of this function is the watchdog device where you want to retrieve |
214 | data from. The function returns the pointer to the driver specific data. | 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. | ||
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c index 3796434991fa..05d18b4c661b 100644 --- a/drivers/watchdog/watchdog_core.c +++ b/drivers/watchdog/watchdog_core.c | |||
@@ -36,12 +36,68 @@ | |||
36 | #include <linux/init.h> /* For __init/__exit/... */ | 36 | #include <linux/init.h> /* For __init/__exit/... */ |
37 | #include <linux/idr.h> /* For ida_* macros */ | 37 | #include <linux/idr.h> /* For ida_* macros */ |
38 | #include <linux/err.h> /* For IS_ERR macros */ | 38 | #include <linux/err.h> /* For IS_ERR macros */ |
39 | #include <linux/of.h> /* For of_get_timeout_sec */ | ||
39 | 40 | ||
40 | #include "watchdog_core.h" /* For watchdog_dev_register/... */ | 41 | #include "watchdog_core.h" /* For watchdog_dev_register/... */ |
41 | 42 | ||
42 | static DEFINE_IDA(watchdog_ida); | 43 | static DEFINE_IDA(watchdog_ida); |
43 | static struct class *watchdog_class; | 44 | static struct class *watchdog_class; |
44 | 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); | ||
100 | |||
45 | /** | 101 | /** |
46 | * watchdog_register_device() - register a watchdog device | 102 | * watchdog_register_device() - register a watchdog device |
47 | * @wdd: watchdog device | 103 | * @wdd: watchdog device |
@@ -63,15 +119,7 @@ int watchdog_register_device(struct watchdog_device *wdd) | |||
63 | if (wdd->ops->start == NULL || wdd->ops->stop == NULL) | 119 | if (wdd->ops->start == NULL || wdd->ops->stop == NULL) |
64 | return -EINVAL; | 120 | return -EINVAL; |
65 | 121 | ||
66 | /* | 122 | watchdog_check_min_max_timeout(wdd); |
67 | * Check that we have valid min and max timeout values, if | ||
68 | * not reset them both to 0 (=not used or unknown) | ||
69 | */ | ||
70 | if (wdd->min_timeout > wdd->max_timeout) { | ||
71 | pr_info("Invalid min and max timeout values, resetting to 0!\n"); | ||
72 | wdd->min_timeout = 0; | ||
73 | wdd->max_timeout = 0; | ||
74 | } | ||
75 | 123 | ||
76 | /* | 124 | /* |
77 | * Note: now that all watchdog_device data has been verified, we | 125 | * Note: now that all watchdog_device data has been verified, we |
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index ef8edecfc526..08b48bbf9f4b 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c | |||
@@ -200,8 +200,7 @@ static int watchdog_set_timeout(struct watchdog_device *wddev, | |||
200 | !(wddev->info->options & WDIOF_SETTIMEOUT)) | 200 | !(wddev->info->options & WDIOF_SETTIMEOUT)) |
201 | return -EOPNOTSUPP; | 201 | return -EOPNOTSUPP; |
202 | 202 | ||
203 | if ((wddev->max_timeout != 0) && | 203 | if (watchdog_timeout_invalid(wddev, timeout)) |
204 | (timeout < wddev->min_timeout || timeout > wddev->max_timeout)) | ||
205 | return -EINVAL; | 204 | return -EINVAL; |
206 | 205 | ||
207 | mutex_lock(&wddev->lock); | 206 | mutex_lock(&wddev->lock); |
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h index 3a9df2f43be6..2a3038ee17a3 100644 --- a/include/linux/watchdog.h +++ b/include/linux/watchdog.h | |||
@@ -118,6 +118,13 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway | |||
118 | set_bit(WDOG_NO_WAY_OUT, &wdd->status); | 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 | /* Use the following functions to manipulate watchdog driver specific data */ | 128 | /* Use the following functions to manipulate watchdog driver specific data */ |
122 | static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data) | 129 | static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data) |
123 | { | 130 | { |
@@ -130,6 +137,8 @@ static inline void *watchdog_get_drvdata(struct watchdog_device *wdd) | |||
130 | } | 137 | } |
131 | 138 | ||
132 | /* drivers/watchdog/watchdog_core.c */ | 139 | /* drivers/watchdog/watchdog_core.c */ |
140 | extern int watchdog_init_timeout(struct watchdog_device *wdd, | ||
141 | unsigned int timeout_parm, struct device *dev); | ||
133 | extern int watchdog_register_device(struct watchdog_device *); | 142 | extern int watchdog_register_device(struct watchdog_device *); |
134 | extern void watchdog_unregister_device(struct watchdog_device *); | 143 | extern void watchdog_unregister_device(struct watchdog_device *); |
135 | 144 | ||