aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/watchdog
diff options
context:
space:
mode:
authorWolfram Sang <w.sang@pengutronix.de>2011-09-26 09:40:13 -0400
committerWim Van Sebroeck <wim@iguana.be>2011-11-05 16:25:16 -0400
commit74cd4c67392c1cee0499ba0977ec843252c7af28 (patch)
tree1248b9020720ea88c8e24a675ffe75bd317bc272 /Documentation/watchdog
parentdeb9197b7031b8f4ed311dc47a14363da4458544 (diff)
Documentation: watchdog: add guide how to convert drivers to new framework
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de> Cc: Randy Dunlap <rdunlap@xenotime.net> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Diffstat (limited to 'Documentation/watchdog')
-rw-r--r--Documentation/watchdog/convert_drivers_to_kernel_api.txt195
1 files changed, 195 insertions, 0 deletions
diff --git a/Documentation/watchdog/convert_drivers_to_kernel_api.txt b/Documentation/watchdog/convert_drivers_to_kernel_api.txt
new file mode 100644
index 000000000000..ae1e90036d06
--- /dev/null
+++ b/Documentation/watchdog/convert_drivers_to_kernel_api.txt
@@ -0,0 +1,195 @@
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 Other IOCTLs can be served using the ioctl-callback. Note that this is mainly
63 intended for porting old drivers; new drivers should not invent private IOCTLs.
64 Private IOCTLs are processed first. When the callback returns with
65 -ENOIOCTLCMD, the IOCTLs of the framework will be tried, too. Any other error
66 is directly given to the user.
67
68Example conversion:
69
70-static const struct file_operations s3c2410wdt_fops = {
71- .owner = THIS_MODULE,
72- .llseek = no_llseek,
73- .write = s3c2410wdt_write,
74- .unlocked_ioctl = s3c2410wdt_ioctl,
75- .open = s3c2410wdt_open,
76- .release = s3c2410wdt_release,
77-};
78
79Check the functions for device-specific stuff and keep it for later
80refactoring. The rest can go.
81
82
83Remove the miscdevice
84---------------------
85
86Since the file_operations are gone now, you can also remove the 'struct
87miscdevice'. The framework will create it on watchdog_dev_register() called by
88watchdog_register_device().
89
90-static struct miscdevice s3c2410wdt_miscdev = {
91- .minor = WATCHDOG_MINOR,
92- .name = "watchdog",
93- .fops = &s3c2410wdt_fops,
94-};
95
96
97Remove obsolete includes and defines
98------------------------------------
99
100Because of the simplifications, a few defines are probably unused now. Remove
101them. Includes can be removed, too. For example:
102
103- #include <linux/fs.h>
104- #include <linux/miscdevice.h> (if MODULE_ALIAS_MISCDEV is not used)
105- #include <linux/uaccess.h> (if no custom IOCTLs are used)
106
107
108Add the watchdog operations
109---------------------------
110
111All possible callbacks are defined in 'struct watchdog_ops'. You can find it
112explained in 'watchdog-kernel-api.txt' in this directory. start(), stop() and
113owner must be set, the rest are optional. You will easily find corresponding
114functions in the old driver. Note that you will now get a pointer to the
115watchdog_device as a parameter to these functions, so you probably have to
116change the function header. Other changes are most likely not needed, because
117here simply happens the direct hardware access. If you have device-specific
118code left from the above steps, it should be refactored into these callbacks.
119
120Here is a simple example:
121
122+static struct watchdog_ops s3c2410wdt_ops = {
123+ .owner = THIS_MODULE,
124+ .start = s3c2410wdt_start,
125+ .stop = s3c2410wdt_stop,
126+ .ping = s3c2410wdt_keepalive,
127+ .set_timeout = s3c2410wdt_set_heartbeat,
128+};
129
130A typical function-header change looks like:
131
132-static void s3c2410wdt_keepalive(void)
133+static int s3c2410wdt_keepalive(struct watchdog_device *wdd)
134 {
135...
136+
137+ return 0;
138 }
139
140...
141
142- s3c2410wdt_keepalive();
143+ s3c2410wdt_keepalive(&s3c2410_wdd);
144
145
146Add the watchdog device
147-----------------------
148
149Now we need to create a 'struct watchdog_device' and populate it with the
150necessary information for the framework. The struct is also explained in detail
151in 'watchdog-kernel-api.txt' in this directory. We pass it the mandatory
152watchdog_info struct and the newly created watchdog_ops. Often, old drivers
153have their own record-keeping for things like bootstatus and timeout using
154static variables. Those have to be converted to use the members in
155watchdog_device. Note that the timeout values are unsigned int. Some drivers
156use signed int, so this has to be converted, too.
157
158Here is a simple example for a watchdog device:
159
160+static struct watchdog_device s3c2410_wdd = {
161+ .info = &s3c2410_wdt_ident,
162+ .ops = &s3c2410wdt_ops,
163+};
164
165
166Register the watchdog device
167----------------------------
168
169Replace misc_register(&miscdev) with watchdog_register_device(&watchdog_dev).
170Make sure the return value gets checked and the error message, if present,
171still fits. Also convert the unregister case.
172
173- ret = misc_register(&s3c2410wdt_miscdev);
174+ ret = watchdog_register_device(&s3c2410_wdd);
175
176...
177
178- misc_deregister(&s3c2410wdt_miscdev);
179+ watchdog_unregister_device(&s3c2410_wdd);
180
181
182Update the Kconfig-entry
183------------------------
184
185The entry for the driver now needs to select WATCHDOG_CORE:
186
187+ select WATCHDOG_CORE
188
189
190Create a patch and send it to upstream
191--------------------------------------
192
193Make sure you understood Documentation/SubmittingPatches and send your patch to
194linux-watchdog@vger.kernel.org. We are looking forward to it :)
195