Commit | Line | Data |
---|---|---|
43316044 WVS |
1 | The Linux WatchDog Timer Driver Core kernel API. |
2 | =============================================== | |
3 | Last reviewed: 22-Jul-2011 | |
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 { | |
42 | const struct watchdog_info *info; | |
43 | const struct watchdog_ops *ops; | |
2fa03560 | 44 | unsigned int bootstatus; |
43316044 WVS |
45 | void *driver_data; |
46 | unsigned long status; | |
47 | }; | |
48 | ||
49 | It contains following fields: | |
50 | * info: a pointer to a watchdog_info structure. This structure gives some | |
51 | additional information about the watchdog timer itself. (Like it's unique name) | |
52 | * ops: a pointer to the list of watchdog operations that the watchdog supports. | |
2fa03560 WVS |
53 | * bootstatus: status of the device after booting (reported with watchdog |
54 | WDIOF_* status bits). | |
43316044 WVS |
55 | * driver_data: a pointer to the drivers private data of a watchdog device. |
56 | This data should only be accessed via the watchdog_set_drvadata and | |
57 | watchdog_get_drvdata routines. | |
58 | * status: this field contains a number of status bits that give extra | |
234445b4 WVS |
59 | information about the status of the device (Like: is the watchdog timer |
60 | running/active, is the device opened via the /dev/watchdog interface or not, | |
61 | ...). | |
43316044 WVS |
62 | |
63 | The list of watchdog operations is defined as: | |
64 | ||
65 | struct watchdog_ops { | |
66 | struct module *owner; | |
67 | /* mandatory operations */ | |
68 | int (*start)(struct watchdog_device *); | |
69 | int (*stop)(struct watchdog_device *); | |
70 | /* optional operations */ | |
71 | int (*ping)(struct watchdog_device *); | |
2fa03560 | 72 | unsigned int (*status)(struct watchdog_device *); |
43316044 WVS |
73 | }; |
74 | ||
75 | It is important that you first define the module owner of the watchdog timer | |
76 | driver's operations. This module owner will be used to lock the module when | |
77 | the watchdog is active. (This to avoid a system crash when you unload the | |
78 | module and /dev/watchdog is still open). | |
79 | Some operations are mandatory and some are optional. The mandatory operations | |
80 | are: | |
81 | * start: this is a pointer to the routine that starts the watchdog timer | |
82 | device. | |
83 | The routine needs a pointer to the watchdog timer device structure as a | |
84 | parameter. It returns zero on success or a negative errno code for failure. | |
85 | * stop: with this routine the watchdog timer device is being stopped. | |
86 | The routine needs a pointer to the watchdog timer device structure as a | |
87 | parameter. It returns zero on success or a negative errno code for failure. | |
88 | Some watchdog timer hardware can only be started and not be stopped. The | |
89 | driver supporting this hardware needs to make sure that a start and stop | |
90 | routine is being provided. This can be done by using a timer in the driver | |
91 | that regularly sends a keepalive ping to the watchdog timer hardware. | |
92 | ||
93 | Not all watchdog timer hardware supports the same functionality. That's why | |
94 | all other routines/operations are optional. They only need to be provided if | |
95 | they are supported. These optional routines/operations are: | |
96 | * ping: this is the routine that sends a keepalive ping to the watchdog timer | |
97 | hardware. | |
98 | The routine needs a pointer to the watchdog timer device structure as a | |
99 | parameter. It returns zero on success or a negative errno code for failure. | |
100 | Most hardware that does not support this as a separate function uses the | |
101 | start function to restart the watchdog timer hardware. And that's also what | |
102 | the watchdog timer driver core does: to send a keepalive ping to the watchdog | |
103 | timer hardware it will either use the ping operation (when available) or the | |
104 | start operation (when the ping operation is not available). | |
c2dc00e4 WVS |
105 | (Note: the WDIOC_KEEPALIVE ioctl call will only be active when the |
106 | WDIOF_KEEPALIVEPING bit has been set in the option field on the watchdog's | |
107 | info structure). | |
2fa03560 WVS |
108 | * status: this routine checks the status of the watchdog timer device. The |
109 | status of the device is reported with watchdog WDIOF_* status flags/bits. | |
43316044 WVS |
110 | |
111 | The status bits should (preferably) be set with the set_bit and clear_bit alike | |
112 | bit-operations. The status bits that are defined are: | |
234445b4 WVS |
113 | * WDOG_ACTIVE: this status bit indicates whether or not a watchdog timer device |
114 | is active or not. When the watchdog is active after booting, then you should | |
115 | set this status bit (Note: when you register the watchdog timer device with | |
116 | this bit set, then opening /dev/watchdog will skip the start operation) | |
43316044 WVS |
117 | * WDOG_DEV_OPEN: this status bit shows whether or not the watchdog device |
118 | was opened via /dev/watchdog. | |
119 | (This bit should only be used by the WatchDog Timer Driver Core). | |
120 | ||
121 | To get or set driver specific data the following two helper functions should be | |
122 | used: | |
123 | ||
124 | static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data) | |
125 | static inline void *watchdog_get_drvdata(struct watchdog_device *wdd) | |
126 | ||
127 | The watchdog_set_drvdata function allows you to add driver specific data. The | |
128 | arguments of this function are the watchdog device where you want to add the | |
129 | driver specific data to and a pointer to the data itself. | |
130 | ||
131 | The watchdog_get_drvdata function allows you to retrieve driver specific data. | |
132 | The argument of this function is the watchdog device where you want to retrieve | |
133 | data from. The function retruns the pointer to the driver specific data. |