summaryrefslogtreecommitdiffstats
path: root/Documentation/watchdog/watchdog-kernel-api.txt
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2015-12-25 19:01:42 -0500
committerWim Van Sebroeck <wim@iguana.be>2015-12-29 14:36:03 -0500
commitb4ffb1909843b28f3b1b60197d517b123b7a9b66 (patch)
tree1fbbf01c383b8cba232bd312737b26fe91830c77 /Documentation/watchdog/watchdog-kernel-api.txt
parente7d162faa6d067777548cb98d55206cf7cd3438e (diff)
watchdog: Separate and maintain variables based on variable lifetime
All variables required by the watchdog core to manage a watchdog are currently stored in struct watchdog_device. The lifetime of those variables is determined by the watchdog driver. However, the lifetime of variables used by the watchdog core differs from the lifetime of struct watchdog_device. To remedy this situation, watchdog drivers can implement ref and unref callbacks, to be used by the watchdog core to lock struct watchdog_device in memory. While this solves the immediate problem, it depends on watchdog drivers to actually implement the ref/unref callbacks. This is error prone, often not implemented in the first place, or not implemented correctly. To solve the problem without requiring driver support, split the variables in struct watchdog_device into two data structures - one for variables associated with the watchdog driver, one for variables associated with the watchdog core. With this approach, the watchdog core can keep track of its variable lifetime and no longer depends on ref/unref callbacks in the driver. As a side effect, some of the variables originally in struct watchdog_driver are now private to the watchdog core and no longer visible in watchdog drivers. As a side effect of the changes made, an ioctl will now always fail with -ENODEV after a watchdog device was unregistered with the character device still open. Previously, it would only fail with -ENODEV in some situations. Also, ioctl operations are now atomic from driver perspective. With this change, it is now guaranteed that the driver will not unregister a watchdog between a timeout change and the subsequent ping. The 'ref' and 'unref' callbacks in struct watchdog_driver are no longer used and marked as deprecated. Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Diffstat (limited to 'Documentation/watchdog/watchdog-kernel-api.txt')
-rw-r--r--Documentation/watchdog/watchdog-kernel-api.txt45
1 files changed, 7 insertions, 38 deletions
diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
index 0a37da76acef..72a009478b15 100644
--- a/Documentation/watchdog/watchdog-kernel-api.txt
+++ b/Documentation/watchdog/watchdog-kernel-api.txt
@@ -44,7 +44,6 @@ The watchdog device structure looks like this:
44 44
45struct watchdog_device { 45struct watchdog_device {
46 int id; 46 int id;
47 struct cdev cdev;
48 struct device *dev; 47 struct device *dev;
49 struct device *parent; 48 struct device *parent;
50 const struct watchdog_info *info; 49 const struct watchdog_info *info;
@@ -56,7 +55,7 @@ struct watchdog_device {
56 struct notifier_block reboot_nb; 55 struct notifier_block reboot_nb;
57 struct notifier_block restart_nb; 56 struct notifier_block restart_nb;
58 void *driver_data; 57 void *driver_data;
59 struct mutex lock; 58 struct watchdog_core_data *wd_data;
60 unsigned long status; 59 unsigned long status;
61 struct list_head deferred; 60 struct list_head deferred;
62}; 61};
@@ -66,8 +65,6 @@ It contains following fields:
66 /dev/watchdog0 cdev (dynamic major, minor 0) as well as the old 65 /dev/watchdog0 cdev (dynamic major, minor 0) as well as the old
67 /dev/watchdog miscdev. The id is set automatically when calling 66 /dev/watchdog miscdev. The id is set automatically when calling
68 watchdog_register_device. 67 watchdog_register_device.
69* cdev: cdev for the dynamic /dev/watchdog<id> device nodes. This
70 field is also populated by watchdog_register_device.
71* dev: device under the watchdog class (created by watchdog_register_device). 68* dev: device under the watchdog class (created by watchdog_register_device).
72* parent: set this to the parent device (or NULL) before calling 69* parent: set this to the parent device (or NULL) before calling
73 watchdog_register_device. 70 watchdog_register_device.
@@ -89,11 +86,10 @@ It contains following fields:
89* driver_data: a pointer to the drivers private data of a watchdog device. 86* driver_data: a pointer to the drivers private data of a watchdog device.
90 This data should only be accessed via the watchdog_set_drvdata and 87 This data should only be accessed via the watchdog_set_drvdata and
91 watchdog_get_drvdata routines. 88 watchdog_get_drvdata routines.
92* lock: Mutex for WatchDog Timer Driver Core internal use only. 89* wd_data: a pointer to watchdog core internal data.
93* status: this field contains a number of status bits that give extra 90* status: this field contains a number of status bits that give extra
94 information about the status of the device (Like: is the watchdog timer 91 information about the status of the device (Like: is the watchdog timer
95 running/active, is the nowayout bit set, is the device opened via 92 running/active, or is the nowayout bit set).
96 the /dev/watchdog interface or not, ...).
97* deferred: entry in wtd_deferred_reg_list which is used to 93* deferred: entry in wtd_deferred_reg_list which is used to
98 register early initialized watchdogs. 94 register early initialized watchdogs.
99 95
@@ -110,8 +106,8 @@ struct watchdog_ops {
110 int (*set_timeout)(struct watchdog_device *, unsigned int); 106 int (*set_timeout)(struct watchdog_device *, unsigned int);
111 unsigned int (*get_timeleft)(struct watchdog_device *); 107 unsigned int (*get_timeleft)(struct watchdog_device *);
112 int (*restart)(struct watchdog_device *); 108 int (*restart)(struct watchdog_device *);
113 void (*ref)(struct watchdog_device *); 109 void (*ref)(struct watchdog_device *) __deprecated;
114 void (*unref)(struct watchdog_device *); 110 void (*unref)(struct watchdog_device *) __deprecated;
115 long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long); 111 long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long);
116}; 112};
117 113
@@ -120,20 +116,6 @@ driver's operations. This module owner will be used to lock the module when
120the watchdog is active. (This to avoid a system crash when you unload the 116the watchdog is active. (This to avoid a system crash when you unload the
121module and /dev/watchdog is still open). 117module and /dev/watchdog is still open).
122 118
123If the watchdog_device struct is dynamically allocated, just locking the module
124is not enough and a driver also needs to define the ref and unref operations to
125ensure the structure holding the watchdog_device does not go away.
126
127The simplest (and usually sufficient) implementation of this is to:
1281) Add a kref struct to the same structure which is holding the watchdog_device
1292) Define a release callback for the kref which frees the struct holding both
1303) Call kref_init on this kref *before* calling watchdog_register_device()
1314) Define a ref operation calling kref_get on this kref
1325) Define a unref operation calling kref_put on this kref
1336) When it is time to cleanup:
134 * Do not kfree() the struct holding both, the last kref_put will do this!
135 * *After* calling watchdog_unregister_device() call kref_put on the kref
136
137Some operations are mandatory and some are optional. The mandatory operations 119Some operations are mandatory and some are optional. The mandatory operations
138are: 120are:
139* start: this is a pointer to the routine that starts the watchdog timer 121* start: this is a pointer to the routine that starts the watchdog timer
@@ -176,34 +158,21 @@ they are supported. These optional routines/operations are:
176* get_timeleft: this routines returns the time that's left before a reset. 158* get_timeleft: this routines returns the time that's left before a reset.
177* restart: this routine restarts the machine. It returns 0 on success or a 159* restart: this routine restarts the machine. It returns 0 on success or a
178 negative errno code for failure. 160 negative errno code for failure.
179* ref: the operation that calls kref_get on the kref of a dynamically
180 allocated watchdog_device struct.
181* unref: the operation that calls kref_put on the kref of a dynamically
182 allocated watchdog_device struct.
183* ioctl: if this routine is present then it will be called first before we do 161* ioctl: if this routine is present then it will be called first before we do
184 our own internal ioctl call handling. This routine should return -ENOIOCTLCMD 162 our own internal ioctl call handling. This routine should return -ENOIOCTLCMD
185 if a command is not supported. The parameters that are passed to the ioctl 163 if a command is not supported. The parameters that are passed to the ioctl
186 call are: watchdog_device, cmd and arg. 164 call are: watchdog_device, cmd and arg.
187 165
166The 'ref' and 'unref' operations are no longer used and deprecated.
167
188The status bits should (preferably) be set with the set_bit and clear_bit alike 168The status bits should (preferably) be set with the set_bit and clear_bit alike
189bit-operations. The status bits that are defined are: 169bit-operations. The status bits that are defined are:
190* WDOG_ACTIVE: this status bit indicates whether or not a watchdog timer device 170* WDOG_ACTIVE: this status bit indicates whether or not a watchdog timer device
191 is active or not. When the watchdog is active after booting, then you should 171 is active or not. When the watchdog is active after booting, then you should
192 set this status bit (Note: when you register the watchdog timer device with 172 set this status bit (Note: when you register the watchdog timer device with
193 this bit set, then opening /dev/watchdog will skip the start operation) 173 this bit set, then opening /dev/watchdog will skip the start operation)
194* WDOG_DEV_OPEN: this status bit shows whether or not the watchdog device
195 was opened via /dev/watchdog.
196 (This bit should only be used by the WatchDog Timer Driver Core).
197* WDOG_ALLOW_RELEASE: this bit stores whether or not the magic close character
198 has been sent (so that we can support the magic close feature).
199 (This bit should only be used by the WatchDog Timer Driver Core).
200* WDOG_NO_WAY_OUT: this bit stores the nowayout setting for the watchdog. 174* WDOG_NO_WAY_OUT: this bit stores the nowayout setting for the watchdog.
201 If this bit is set then the watchdog timer will not be able to stop. 175 If this bit is set then the watchdog timer will not be able to stop.
202* WDOG_UNREGISTERED: this bit gets set by the WatchDog Timer Driver Core
203 after calling watchdog_unregister_device, and then checked before calling
204 any watchdog_ops, so that you can be sure that no operations (other then
205 unref) will get called after unregister, even if userspace still holds a
206 reference to /dev/watchdog
207 176
208 To set the WDOG_NO_WAY_OUT status bit (before registering your watchdog 177 To set the WDOG_NO_WAY_OUT status bit (before registering your watchdog
209 timer device) you can either: 178 timer device) you can either: