aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/watchdog
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /Documentation/watchdog
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'Documentation/watchdog')
-rw-r--r--Documentation/watchdog/convert_drivers_to_kernel_api.txt218
-rw-r--r--Documentation/watchdog/src/watchdog-test.c20
-rw-r--r--Documentation/watchdog/watchdog-kernel-api.txt64
-rw-r--r--Documentation/watchdog/watchdog-parameters.txt5
4 files changed, 9 insertions, 298 deletions
diff --git a/Documentation/watchdog/convert_drivers_to_kernel_api.txt b/Documentation/watchdog/convert_drivers_to_kernel_api.txt
deleted file mode 100644
index 271b8850dde..00000000000
--- a/Documentation/watchdog/convert_drivers_to_kernel_api.txt
+++ /dev/null
@@ -1,218 +0,0 @@
1Converting old watchdog drivers to the watchdog framework
2by Wolfram Sang <w.sang@pengutronix.de>
3=========================================================
4
5Before the watchdog framework came into the kernel, every driver had to
6implement the API on its own. Now, as the framework factored out the common
7components, those drivers can be lightened making it a user of the framework.
8This document shall guide you for this task. The necessary steps are described
9as well as things to look out for.
10
11
12Remove the file_operations struct
13---------------------------------
14
15Old drivers define their own file_operations for actions like open(), write(),
16etc... These are now handled by the framework and just call the driver when
17needed. So, in general, the 'file_operations' struct and assorted functions can
18go. Only very few driver-specific details have to be moved to other functions.
19Here is a overview of the functions and probably needed actions:
20
21- open: Everything dealing with resource management (file-open checks, magic
22 close preparations) can simply go. Device specific stuff needs to go to the
23 driver specific start-function. Note that for some drivers, the start-function
24 also serves as the ping-function. If that is the case and you need start/stop
25 to be balanced (clocks!), you are better off refactoring a separate start-function.
26
27- close: Same hints as for open apply.
28
29- write: Can simply go, all defined behaviour is taken care of by the framework,
30 i.e. ping on write and magic char ('V') handling.
31
32- ioctl: While the driver is allowed to have extensions to the IOCTL interface,
33 the most common ones are handled by the framework, supported by some assistance
34 from the driver:
35
36 WDIOC_GETSUPPORT:
37 Returns the mandatory watchdog_info struct from the driver
38
39 WDIOC_GETSTATUS:
40 Needs the status-callback defined, otherwise returns 0
41
42 WDIOC_GETBOOTSTATUS:
43 Needs the bootstatus member properly set. Make sure it is 0 if you
44 don't have further support!
45
46 WDIOC_SETOPTIONS:
47 No preparations needed
48
49 WDIOC_KEEPALIVE:
50 If wanted, options in watchdog_info need to have WDIOF_KEEPALIVEPING
51 set
52
53 WDIOC_SETTIMEOUT:
54 Options in watchdog_info need to have WDIOF_SETTIMEOUT set
55 and a set_timeout-callback has to be defined. The core will also
56 do limit-checking, if min_timeout and max_timeout in the watchdog
57 device are set. All is optional.
58
59 WDIOC_GETTIMEOUT:
60 No preparations needed
61
62 WDIOC_GETTIMELEFT:
63 It needs get_timeleft() callback to be defined. Otherwise it
64 will return EOPNOTSUPP
65
66 Other IOCTLs can be served using the ioctl-callback. Note that this is mainly
67 intended for porting old drivers; new drivers should not invent private IOCTLs.
68 Private IOCTLs are processed first. When the callback returns with
69 -ENOIOCTLCMD, the IOCTLs of the framework will be tried, too. Any other error
70 is directly given to the user.
71
72Example conversion:
73
74-static const struct file_operations s3c2410wdt_fops = {
75- .owner = THIS_MODULE,
76- .llseek = no_llseek,
77- .write = s3c2410wdt_write,
78- .unlocked_ioctl = s3c2410wdt_ioctl,
79- .open = s3c2410wdt_open,
80- .release = s3c2410wdt_release,
81-};
82
83Check the functions for device-specific stuff and keep it for later
84refactoring. The rest can go.
85
86
87Remove the miscdevice
88---------------------
89
90Since the file_operations are gone now, you can also remove the 'struct
91miscdevice'. The framework will create it on watchdog_dev_register() called by
92watchdog_register_device().
93
94-static struct miscdevice s3c2410wdt_miscdev = {
95- .minor = WATCHDOG_MINOR,
96- .name = "watchdog",
97- .fops = &s3c2410wdt_fops,
98-};
99
100
101Remove obsolete includes and defines
102------------------------------------
103
104Because of the simplifications, a few defines are probably unused now. Remove
105them. Includes can be removed, too. For example:
106
107- #include <linux/fs.h>
108- #include <linux/miscdevice.h> (if MODULE_ALIAS_MISCDEV is not used)
109- #include <linux/uaccess.h> (if no custom IOCTLs are used)
110
111
112Add the watchdog operations
113---------------------------
114
115All possible callbacks are defined in 'struct watchdog_ops'. You can find it
116explained in 'watchdog-kernel-api.txt' in this directory. start(), stop() and
117owner must be set, the rest are optional. You will easily find corresponding
118functions in the old driver. Note that you will now get a pointer to the
119watchdog_device as a parameter to these functions, so you probably have to
120change the function header. Other changes are most likely not needed, because
121here simply happens the direct hardware access. If you have device-specific
122code left from the above steps, it should be refactored into these callbacks.
123
124Here is a simple example:
125
126+static struct watchdog_ops s3c2410wdt_ops = {
127+ .owner = THIS_MODULE,
128+ .start = s3c2410wdt_start,
129+ .stop = s3c2410wdt_stop,
130+ .ping = s3c2410wdt_keepalive,
131+ .set_timeout = s3c2410wdt_set_heartbeat,
132+};
133
134A typical function-header change looks like:
135
136-static void s3c2410wdt_keepalive(void)
137+static int s3c2410wdt_keepalive(struct watchdog_device *wdd)
138 {
139...
140+
141+ return 0;
142 }
143
144...
145
146- s3c2410wdt_keepalive();
147+ s3c2410wdt_keepalive(&s3c2410_wdd);
148
149
150Add the watchdog device
151-----------------------
152
153Now we need to create a 'struct watchdog_device' and populate it with the
154necessary information for the framework. The struct is also explained in detail
155in 'watchdog-kernel-api.txt' in this directory. We pass it the mandatory
156watchdog_info struct and the newly created watchdog_ops. Often, old drivers
157have their own record-keeping for things like bootstatus and timeout using
158static variables. Those have to be converted to use the members in
159watchdog_device. Note that the timeout values are unsigned int. Some drivers
160use signed int, so this has to be converted, too.
161
162Here is a simple example for a watchdog device:
163
164+static struct watchdog_device s3c2410_wdd = {
165+ .info = &s3c2410_wdt_ident,
166+ .ops = &s3c2410wdt_ops,
167+};
168
169
170Handle the 'nowayout' feature
171-----------------------------
172
173A few drivers use nowayout statically, i.e. there is no module parameter for it
174and only CONFIG_WATCHDOG_NOWAYOUT determines if the feature is going to be
175used. This needs to be converted by initializing the status variable of the
176watchdog_device like this:
177
178 .status = WATCHDOG_NOWAYOUT_INIT_STATUS,
179
180Most drivers, however, also allow runtime configuration of nowayout, usually
181by adding a module parameter. The conversion for this would be something like:
182
183 watchdog_set_nowayout(&s3c2410_wdd, nowayout);
184
185The module parameter itself needs to stay, everything else related to nowayout
186can go, though. This will likely be some code in open(), close() or write().
187
188
189Register the watchdog device
190----------------------------
191
192Replace misc_register(&miscdev) with watchdog_register_device(&watchdog_dev).
193Make sure the return value gets checked and the error message, if present,
194still fits. Also convert the unregister case.
195
196- ret = misc_register(&s3c2410wdt_miscdev);
197+ ret = watchdog_register_device(&s3c2410_wdd);
198
199...
200
201- misc_deregister(&s3c2410wdt_miscdev);
202+ watchdog_unregister_device(&s3c2410_wdd);
203
204
205Update the Kconfig-entry
206------------------------
207
208The entry for the driver now needs to select WATCHDOG_CORE:
209
210+ select WATCHDOG_CORE
211
212
213Create a patch and send it to upstream
214--------------------------------------
215
216Make sure you understood Documentation/SubmittingPatches and send your patch to
217linux-watchdog@vger.kernel.org. We are looking forward to it :)
218
diff --git a/Documentation/watchdog/src/watchdog-test.c b/Documentation/watchdog/src/watchdog-test.c
index 3da822967ee..63fdc34ceb9 100644
--- a/Documentation/watchdog/src/watchdog-test.c
+++ b/Documentation/watchdog/src/watchdog-test.c
@@ -7,7 +7,6 @@
7#include <string.h> 7#include <string.h>
8#include <unistd.h> 8#include <unistd.h>
9#include <fcntl.h> 9#include <fcntl.h>
10#include <signal.h>
11#include <sys/ioctl.h> 10#include <sys/ioctl.h>
12#include <linux/types.h> 11#include <linux/types.h>
13#include <linux/watchdog.h> 12#include <linux/watchdog.h>
@@ -30,14 +29,6 @@ static void keep_alive(void)
30 * The main program. Run the program with "-d" to disable the card, 29 * The main program. Run the program with "-d" to disable the card,
31 * or "-e" to enable the card. 30 * or "-e" to enable the card.
32 */ 31 */
33
34static void term(int sig)
35{
36 close(fd);
37 fprintf(stderr, "Stopping watchdog ticks...\n");
38 exit(0);
39}
40
41int main(int argc, char *argv[]) 32int main(int argc, char *argv[])
42{ 33{
43 int flags; 34 int flags;
@@ -56,31 +47,26 @@ int main(int argc, char *argv[])
56 ioctl(fd, WDIOC_SETOPTIONS, &flags); 47 ioctl(fd, WDIOC_SETOPTIONS, &flags);
57 fprintf(stderr, "Watchdog card disabled.\n"); 48 fprintf(stderr, "Watchdog card disabled.\n");
58 fflush(stderr); 49 fflush(stderr);
59 goto end; 50 exit(0);
60 } else if (!strncasecmp(argv[1], "-e", 2)) { 51 } else if (!strncasecmp(argv[1], "-e", 2)) {
61 flags = WDIOS_ENABLECARD; 52 flags = WDIOS_ENABLECARD;
62 ioctl(fd, WDIOC_SETOPTIONS, &flags); 53 ioctl(fd, WDIOC_SETOPTIONS, &flags);
63 fprintf(stderr, "Watchdog card enabled.\n"); 54 fprintf(stderr, "Watchdog card enabled.\n");
64 fflush(stderr); 55 fflush(stderr);
65 goto end; 56 exit(0);
66 } else { 57 } else {
67 fprintf(stderr, "-d to disable, -e to enable.\n"); 58 fprintf(stderr, "-d to disable, -e to enable.\n");
68 fprintf(stderr, "run by itself to tick the card.\n"); 59 fprintf(stderr, "run by itself to tick the card.\n");
69 fflush(stderr); 60 fflush(stderr);
70 goto end; 61 exit(0);
71 } 62 }
72 } else { 63 } else {
73 fprintf(stderr, "Watchdog Ticking Away!\n"); 64 fprintf(stderr, "Watchdog Ticking Away!\n");
74 fflush(stderr); 65 fflush(stderr);
75 } 66 }
76 67
77 signal(SIGINT, term);
78
79 while(1) { 68 while(1) {
80 keep_alive(); 69 keep_alive();
81 sleep(1); 70 sleep(1);
82 } 71 }
83end:
84 close(fd);
85 return 0;
86} 72}
diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
index 086638f6c82..4f7c894244d 100644
--- a/Documentation/watchdog/watchdog-kernel-api.txt
+++ b/Documentation/watchdog/watchdog-kernel-api.txt
@@ -1,6 +1,6 @@
1The Linux WatchDog Timer Driver Core kernel API. 1The Linux WatchDog Timer Driver Core kernel API.
2=============================================== 2===============================================
3Last reviewed: 22-May-2012 3Last reviewed: 22-Jul-2011
4 4
5Wim Van Sebroeck <wim@iguana.be> 5Wim Van Sebroeck <wim@iguana.be>
6 6
@@ -39,10 +39,6 @@ watchdog_device structure.
39The watchdog device structure looks like this: 39The watchdog device structure looks like this:
40 40
41struct watchdog_device { 41struct watchdog_device {
42 int id;
43 struct cdev cdev;
44 struct device *dev;
45 struct device *parent;
46 const struct watchdog_info *info; 42 const struct watchdog_info *info;
47 const struct watchdog_ops *ops; 43 const struct watchdog_ops *ops;
48 unsigned int bootstatus; 44 unsigned int bootstatus;
@@ -50,20 +46,10 @@ struct watchdog_device {
50 unsigned int min_timeout; 46 unsigned int min_timeout;
51 unsigned int max_timeout; 47 unsigned int max_timeout;
52 void *driver_data; 48 void *driver_data;
53 struct mutex lock;
54 unsigned long status; 49 unsigned long status;
55}; 50};
56 51
57It contains following fields: 52It contains following fields:
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.
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.
67* info: a pointer to a watchdog_info structure. This structure gives some 53* 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) 54 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. 55* ops: a pointer to the list of watchdog operations that the watchdog supports.
@@ -73,9 +59,8 @@ It contains following fields:
73* bootstatus: status of the device after booting (reported with watchdog 59* bootstatus: status of the device after booting (reported with watchdog
74 WDIOF_* status bits). 60 WDIOF_* status bits).
75* driver_data: a pointer to the drivers private data of a watchdog device. 61* driver_data: a pointer to the drivers private data of a watchdog device.
76 This data should only be accessed via the watchdog_set_drvdata and 62 This data should only be accessed via the watchdog_set_drvadata and
77 watchdog_get_drvdata routines. 63 watchdog_get_drvdata routines.
78* lock: Mutex for WatchDog Timer Driver Core internal use only.
79* status: this field contains a number of status bits that give extra 64* status: this field contains a number of status bits that give extra
80 information about the status of the device (Like: is the watchdog timer 65 information about the status of the device (Like: is the watchdog timer
81 running/active, is the nowayout bit set, is the device opened via 66 running/active, is the nowayout bit set, is the device opened via
@@ -92,9 +77,6 @@ struct watchdog_ops {
92 int (*ping)(struct watchdog_device *); 77 int (*ping)(struct watchdog_device *);
93 unsigned int (*status)(struct watchdog_device *); 78 unsigned int (*status)(struct watchdog_device *);
94 int (*set_timeout)(struct watchdog_device *, unsigned int); 79 int (*set_timeout)(struct watchdog_device *, unsigned int);
95 unsigned int (*get_timeleft)(struct watchdog_device *);
96 void (*ref)(struct watchdog_device *);
97 void (*unref)(struct watchdog_device *);
98 long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long); 80 long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long);
99}; 81};
100 82
@@ -102,21 +84,6 @@ It is important that you first define the module owner of the watchdog timer
102driver's operations. This module owner will be used to lock the module when 84driver's operations. This module owner will be used to lock the module when
103the watchdog is active. (This to avoid a system crash when you unload the 85the watchdog is active. (This to avoid a system crash when you unload the
104module and /dev/watchdog is still open). 86module and /dev/watchdog is still open).
105
106If the watchdog_device struct is dynamically allocated, just locking the module
107is not enough and a driver also needs to define the ref and unref operations to
108ensure the structure holding the watchdog_device does not go away.
109
110The simplest (and usually sufficient) implementation of this is to:
1111) Add a kref struct to the same structure which is holding the watchdog_device
1122) Define a release callback for the kref which frees the struct holding both
1133) Call kref_init on this kref *before* calling watchdog_register_device()
1144) Define a ref operation calling kref_get on this kref
1155) Define a unref operation calling kref_put on this kref
1166) 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
120Some operations are mandatory and some are optional. The mandatory operations 87Some operations are mandatory and some are optional. The mandatory operations
121are: 88are:
122* start: this is a pointer to the routine that starts the watchdog timer 89* start: this is a pointer to the routine that starts the watchdog timer
@@ -150,17 +117,11 @@ they are supported. These optional routines/operations are:
150 status of the device is reported with watchdog WDIOF_* status flags/bits. 117 status of the device is reported with watchdog WDIOF_* status flags/bits.
151* set_timeout: this routine checks and changes the timeout of the watchdog 118* 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" 119 timer device. It returns 0 on success, -EINVAL for "parameter out of range"
153 and -EIO for "could not write value to the watchdog". On success this 120 and -EIO for "could not write value to the watchdog". On success the timeout
154 routine should set the timeout value of the watchdog_device to the 121 value of the watchdog_device will be changed to the value that was just used
155 achieved timeout value (which may be different from the requested one 122 to re-program the watchdog timer device.
156 because the watchdog does not necessarily has a 1 second resolution).
157 (Note: the WDIOF_SETTIMEOUT needs to be set in the options field of the 123 (Note: the WDIOF_SETTIMEOUT needs to be set in the options field of the
158 watchdog's info structure). 124 watchdog's info structure).
159* get_timeleft: this routines returns the time that's left before a reset.
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.
164* ioctl: if this routine is present then it will be called first before we do 125* 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 126 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 127 if a command is not supported. The parameters that are passed to the ioctl
@@ -180,19 +141,6 @@ bit-operations. The status bits that are defined are:
180 (This bit should only be used by the WatchDog Timer Driver Core). 141 (This bit should only be used by the WatchDog Timer Driver Core).
181* WDOG_NO_WAY_OUT: this bit stores the nowayout setting for the watchdog. 142* 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. 143 If this bit is set then the watchdog timer will not be able to stop.
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
188
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 144
197Note: The WatchDog Timer Driver Core supports the magic close feature and 145Note: The WatchDog Timer Driver Core supports the magic close feature and
198the nowayout feature. To use the magic close feature you must set the 146the nowayout feature. To use the magic close feature you must set the
@@ -211,4 +159,4 @@ driver specific data to and a pointer to the data itself.
211 159
212The watchdog_get_drvdata function allows you to retrieve driver specific data. 160The watchdog_get_drvdata function allows you to retrieve driver specific data.
213The argument of this function is the watchdog device where you want to retrieve 161The argument of this function is the watchdog device where you want to retrieve
214data from. The function returns the pointer to the driver specific data. 162data from. The function retruns the pointer to the driver specific data.
diff --git a/Documentation/watchdog/watchdog-parameters.txt b/Documentation/watchdog/watchdog-parameters.txt
index 04fddbacdbd..17ddd822b45 100644
--- a/Documentation/watchdog/watchdog-parameters.txt
+++ b/Documentation/watchdog/watchdog-parameters.txt
@@ -78,11 +78,6 @@ wd0_timeout: Default watchdog0 timeout in 1/10secs
78wd1_timeout: Default watchdog1 timeout in 1/10secs 78wd1_timeout: Default watchdog1 timeout in 1/10secs
79wd2_timeout: Default watchdog2 timeout in 1/10secs 79wd2_timeout: Default watchdog2 timeout in 1/10secs
80------------------------------------------------- 80-------------------------------------------------
81da9052wdt:
82timeout: Watchdog timeout in seconds. 2<= timeout <=131, default=2.048s
83nowayout: Watchdog cannot be stopped once started
84 (default=kernel config parameter)
85-------------------------------------------------
86davinci_wdt: 81davinci_wdt:
87heartbeat: Watchdog heartbeat period in seconds from 1 to 600, default 60 82heartbeat: Watchdog heartbeat period in seconds from 1 to 600, default 60
88------------------------------------------------- 83-------------------------------------------------