Commit | Line | Data |
---|---|---|
43316044 WVS |
1 | The Linux WatchDog Timer Driver Core kernel API. |
2 | =============================================== | |
3048253e | 3 | Last reviewed: 12-Feb-2013 |
43316044 WVS |
4 | |
5 | Wim Van Sebroeck <wim@iguana.be> | |
6 | ||
7 | Introduction | |
8 | ------------ | |
9 | This document does not describe what a WatchDog Timer (WDT) Driver or Device is. | |
10 | It also does not describe the API which can be used by user space to communicate | |
11 | with a WatchDog Timer. If you want to know this then please read the following | |
12 | file: Documentation/watchdog/watchdog-api.txt . | |
13 | ||
14 | So what does this document describe? It describes the API that can be used by | |
15 | WatchDog Timer Drivers that want to use the WatchDog Timer Driver Core | |
16 | Framework. This framework provides all interfacing towards user space so that | |
17 | the same code does not have to be reproduced each time. This also means that | |
18 | a watchdog timer driver then only needs to provide the different routines | |
19 | (operations) that control the watchdog timer (WDT). | |
20 | ||
21 | The API | |
22 | ------- | |
23 | Each watchdog timer driver that wants to use the WatchDog Timer Driver Core | |
24 | must #include <linux/watchdog.h> (you would have to do this anyway when | |
25 | writing a watchdog device driver). This include file contains following | |
26 | register/unregister routines: | |
27 | ||
28 | extern int watchdog_register_device(struct watchdog_device *); | |
29 | extern void watchdog_unregister_device(struct watchdog_device *); | |
30 | ||
31 | The watchdog_register_device routine registers a watchdog timer device. | |
32 | The parameter of this routine is a pointer to a watchdog_device structure. | |
33 | This routine returns zero on success and a negative errno code for failure. | |
34 | ||
35 | The watchdog_unregister_device routine deregisters a registered watchdog timer | |
36 | device. The parameter of this routine is the pointer to the registered | |
37 | watchdog_device structure. | |
38 | ||
39 | The watchdog device structure looks like this: | |
40 | ||
41 | struct watchdog_device { | |
45f5fed3 AC |
42 | int id; |
43 | struct cdev cdev; | |
d6b469d9 AC |
44 | struct device *dev; |
45 | struct device *parent; | |
43316044 WVS |
46 | const struct watchdog_info *info; |
47 | const struct watchdog_ops *ops; | |
2fa03560 | 48 | unsigned int bootstatus; |
014d694e | 49 | unsigned int timeout; |
3f43f68e WVS |
50 | unsigned int min_timeout; |
51 | unsigned int max_timeout; | |
43316044 | 52 | void *driver_data; |
f4e9c82f | 53 | struct mutex lock; |
43316044 WVS |
54 | unsigned long status; |
55 | }; | |
56 | ||
57 | It contains following fields: | |
45f5fed3 AC |
58 | * id: set by watchdog_register_device, id 0 is special. It has both a |
59 | /dev/watchdog0 cdev (dynamic major, minor 0) as well as the old | |
60 | /dev/watchdog miscdev. The id is set automatically when calling | |
61 | watchdog_register_device. | |
62 | * cdev: cdev for the dynamic /dev/watchdog<id> device nodes. This | |
63 | field is also populated by watchdog_register_device. | |
d6b469d9 AC |
64 | * dev: device under the watchdog class (created by watchdog_register_device). |
65 | * parent: set this to the parent device (or NULL) before calling | |
66 | watchdog_register_device. | |
43316044 WVS |
67 | * info: a pointer to a watchdog_info structure. This structure gives some |
68 | additional information about the watchdog timer itself. (Like it's unique name) | |
69 | * ops: a pointer to the list of watchdog operations that the watchdog supports. | |
014d694e | 70 | * timeout: the watchdog timer's timeout value (in seconds). |
3f43f68e WVS |
71 | * min_timeout: the watchdog timer's minimum timeout value (in seconds). |
72 | * max_timeout: the watchdog timer's maximum timeout value (in seconds). | |
2fa03560 WVS |
73 | * bootstatus: status of the device after booting (reported with watchdog |
74 | WDIOF_* status bits). | |
43316044 | 75 | * driver_data: a pointer to the drivers private data of a watchdog device. |
2deca736 | 76 | This data should only be accessed via the watchdog_set_drvdata and |
43316044 | 77 | watchdog_get_drvdata routines. |
f4e9c82f | 78 | * lock: Mutex for WatchDog Timer Driver Core internal use only. |
43316044 | 79 | * status: this field contains a number of status bits that give extra |
234445b4 | 80 | information about the status of the device (Like: is the watchdog timer |
7e192b9c WVS |
81 | running/active, is the nowayout bit set, is the device opened via |
82 | the /dev/watchdog interface or not, ...). | |
43316044 WVS |
83 | |
84 | The list of watchdog operations is defined as: | |
85 | ||
86 | struct watchdog_ops { | |
87 | struct module *owner; | |
88 | /* mandatory operations */ | |
89 | int (*start)(struct watchdog_device *); | |
90 | int (*stop)(struct watchdog_device *); | |
91 | /* optional operations */ | |
92 | int (*ping)(struct watchdog_device *); | |
2fa03560 | 93 | unsigned int (*status)(struct watchdog_device *); |
014d694e | 94 | int (*set_timeout)(struct watchdog_device *, unsigned int); |
fd7b673c | 95 | unsigned int (*get_timeleft)(struct watchdog_device *); |
e907df32 HG |
96 | void (*ref)(struct watchdog_device *); |
97 | void (*unref)(struct watchdog_device *); | |
78d88fc0 | 98 | long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long); |
43316044 WVS |
99 | }; |
100 | ||
101 | It is important that you first define the module owner of the watchdog timer | |
102 | driver's operations. This module owner will be used to lock the module when | |
103 | the watchdog is active. (This to avoid a system crash when you unload the | |
104 | module and /dev/watchdog is still open). | |
e907df32 HG |
105 | |
106 | If the watchdog_device struct is dynamically allocated, just locking the module | |
107 | is not enough and a driver also needs to define the ref and unref operations to | |
108 | ensure the structure holding the watchdog_device does not go away. | |
109 | ||
110 | The simplest (and usually sufficient) implementation of this is to: | |
111 | 1) Add a kref struct to the same structure which is holding the watchdog_device | |
112 | 2) Define a release callback for the kref which frees the struct holding both | |
113 | 3) Call kref_init on this kref *before* calling watchdog_register_device() | |
114 | 4) Define a ref operation calling kref_get on this kref | |
115 | 5) Define a unref operation calling kref_put on this kref | |
116 | 6) When it is time to cleanup: | |
117 | * Do not kfree() the struct holding both, the last kref_put will do this! | |
118 | * *After* calling watchdog_unregister_device() call kref_put on the kref | |
119 | ||
43316044 WVS |
120 | Some operations are mandatory and some are optional. The mandatory operations |
121 | are: | |
122 | * start: this is a pointer to the routine that starts the watchdog timer | |
123 | device. | |
124 | The routine needs a pointer to the watchdog timer device structure as a | |
125 | parameter. It returns zero on success or a negative errno code for failure. | |
126 | * stop: with this routine the watchdog timer device is being stopped. | |
127 | The routine needs a pointer to the watchdog timer device structure as a | |
128 | parameter. It returns zero on success or a negative errno code for failure. | |
129 | Some watchdog timer hardware can only be started and not be stopped. The | |
130 | driver supporting this hardware needs to make sure that a start and stop | |
131 | routine is being provided. This can be done by using a timer in the driver | |
132 | that regularly sends a keepalive ping to the watchdog timer hardware. | |
133 | ||
134 | Not all watchdog timer hardware supports the same functionality. That's why | |
135 | all other routines/operations are optional. They only need to be provided if | |
136 | they are supported. These optional routines/operations are: | |
137 | * ping: this is the routine that sends a keepalive ping to the watchdog timer | |
138 | hardware. | |
139 | The routine needs a pointer to the watchdog timer device structure as a | |
140 | parameter. It returns zero on success or a negative errno code for failure. | |
141 | Most hardware that does not support this as a separate function uses the | |
142 | start function to restart the watchdog timer hardware. And that's also what | |
143 | the watchdog timer driver core does: to send a keepalive ping to the watchdog | |
144 | timer hardware it will either use the ping operation (when available) or the | |
145 | start operation (when the ping operation is not available). | |
c2dc00e4 WVS |
146 | (Note: the WDIOC_KEEPALIVE ioctl call will only be active when the |
147 | WDIOF_KEEPALIVEPING bit has been set in the option field on the watchdog's | |
148 | info structure). | |
2fa03560 WVS |
149 | * status: this routine checks the status of the watchdog timer device. The |
150 | status of the device is reported with watchdog WDIOF_* status flags/bits. | |
014d694e WVS |
151 | * set_timeout: this routine checks and changes the timeout of the watchdog |
152 | timer device. It returns 0 on success, -EINVAL for "parameter out of range" | |
b10f7c12 HG |
153 | and -EIO for "could not write value to the watchdog". On success this |
154 | routine should set the timeout value of the watchdog_device to the | |
155 | achieved timeout value (which may be different from the requested one | |
156 | because the watchdog does not necessarily has a 1 second resolution). | |
014d694e WVS |
157 | (Note: the WDIOF_SETTIMEOUT needs to be set in the options field of the |
158 | watchdog's info structure). | |
fd7b673c | 159 | * get_timeleft: this routines returns the time that's left before a reset. |
e907df32 HG |
160 | * ref: the operation that calls kref_get on the kref of a dynamically |
161 | allocated watchdog_device struct. | |
162 | * unref: the operation that calls kref_put on the kref of a dynamically | |
163 | allocated watchdog_device struct. | |
78d88fc0 WVS |
164 | * ioctl: if this routine is present then it will be called first before we do |
165 | our own internal ioctl call handling. This routine should return -ENOIOCTLCMD | |
166 | if a command is not supported. The parameters that are passed to the ioctl | |
167 | call are: watchdog_device, cmd and arg. | |
43316044 WVS |
168 | |
169 | The status bits should (preferably) be set with the set_bit and clear_bit alike | |
170 | bit-operations. The status bits that are defined are: | |
234445b4 WVS |
171 | * WDOG_ACTIVE: this status bit indicates whether or not a watchdog timer device |
172 | is active or not. When the watchdog is active after booting, then you should | |
173 | set this status bit (Note: when you register the watchdog timer device with | |
174 | this bit set, then opening /dev/watchdog will skip the start operation) | |
43316044 WVS |
175 | * WDOG_DEV_OPEN: this status bit shows whether or not the watchdog device |
176 | was opened via /dev/watchdog. | |
177 | (This bit should only be used by the WatchDog Timer Driver Core). | |
017cf080 WVS |
178 | * WDOG_ALLOW_RELEASE: this bit stores whether or not the magic close character |
179 | has been sent (so that we can support the magic close feature). | |
180 | (This bit should only be used by the WatchDog Timer Driver Core). | |
7e192b9c WVS |
181 | * WDOG_NO_WAY_OUT: this bit stores the nowayout setting for the watchdog. |
182 | If this bit is set then the watchdog timer will not be able to stop. | |
e907df32 HG |
183 | * WDOG_UNREGISTERED: this bit gets set by the WatchDog Timer Driver Core |
184 | after calling watchdog_unregister_device, and then checked before calling | |
185 | any watchdog_ops, so that you can be sure that no operations (other then | |
186 | unref) will get called after unregister, even if userspace still holds a | |
187 | reference to /dev/watchdog | |
017cf080 | 188 | |
ff0b3cd4 WVS |
189 | To set the WDOG_NO_WAY_OUT status bit (before registering your watchdog |
190 | timer device) you can either: | |
191 | * set it statically in your watchdog_device struct with | |
192 | .status = WATCHDOG_NOWAYOUT_INIT_STATUS, | |
193 | (this will set the value the same as CONFIG_WATCHDOG_NOWAYOUT) or | |
194 | * use the following helper function: | |
195 | static inline void watchdog_set_nowayout(struct watchdog_device *wdd, int nowayout) | |
196 | ||
7e192b9c WVS |
197 | Note: The WatchDog Timer Driver Core supports the magic close feature and |
198 | the nowayout feature. To use the magic close feature you must set the | |
199 | WDIOF_MAGICCLOSE bit in the options field of the watchdog's info structure. | |
200 | The nowayout feature will overrule the magic close feature. | |
43316044 WVS |
201 | |
202 | To get or set driver specific data the following two helper functions should be | |
203 | used: | |
204 | ||
205 | static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data) | |
206 | static inline void *watchdog_get_drvdata(struct watchdog_device *wdd) | |
207 | ||
208 | The watchdog_set_drvdata function allows you to add driver specific data. The | |
209 | arguments of this function are the watchdog device where you want to add the | |
210 | driver specific data to and a pointer to the data itself. | |
211 | ||
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 | |
e1986521 | 214 | data from. The function returns the pointer to the driver specific data. |
3048253e FP |
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. |