diff options
Diffstat (limited to 'Documentation/watchdog/watchdog-kernel-api.txt')
| -rw-r--r-- | Documentation/watchdog/watchdog-kernel-api.txt | 226 |
1 files changed, 0 insertions, 226 deletions
diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt deleted file mode 100644 index a0438f3957ca..000000000000 --- a/Documentation/watchdog/watchdog-kernel-api.txt +++ /dev/null @@ -1,226 +0,0 @@ -The Linux WatchDog Timer Driver Core kernel API. -=============================================== -Last reviewed: 12-Feb-2013 - -Wim Van Sebroeck <wim@iguana.be> - -Introduction ------------- -This document does not describe what a WatchDog Timer (WDT) Driver or Device is. -It also does not describe the API which can be used by user space to communicate -with a WatchDog Timer. If you want to know this then please read the following -file: Documentation/watchdog/watchdog-api.txt . - -So what does this document describe? It describes the API that can be used by -WatchDog Timer Drivers that want to use the WatchDog Timer Driver Core -Framework. This framework provides all interfacing towards user space so that -the same code does not have to be reproduced each time. This also means that -a watchdog timer driver then only needs to provide the different routines -(operations) that control the watchdog timer (WDT). - -The API -------- -Each watchdog timer driver that wants to use the WatchDog Timer Driver Core -must #include <linux/watchdog.h> (you would have to do this anyway when -writing a watchdog device driver). This include file contains following -register/unregister routines: - -extern int watchdog_register_device(struct watchdog_device *); -extern void watchdog_unregister_device(struct watchdog_device *); - -The watchdog_register_device routine registers a watchdog timer device. -The parameter of this routine is a pointer to a watchdog_device structure. -This routine returns zero on success and a negative errno code for failure. - -The watchdog_unregister_device routine deregisters a registered watchdog timer -device. The parameter of this routine is the pointer to the registered -watchdog_device structure. - -The watchdog device structure looks like this: - -struct watchdog_device { - int id; - struct cdev cdev; - struct device *dev; - struct device *parent; - const struct watchdog_info *info; - const struct watchdog_ops *ops; - unsigned int bootstatus; - unsigned int timeout; - unsigned int min_timeout; - unsigned int max_timeout; - void *driver_data; - struct mutex lock; - unsigned long status; -}; - -It contains following fields: -* id: set by watchdog_register_device, id 0 is special. It has both a - /dev/watchdog0 cdev (dynamic major, minor 0) as well as the old - /dev/watchdog miscdev. The id is set automatically when calling - watchdog_register_device. -* cdev: cdev for the dynamic /dev/watchdog<id> device nodes. This - field is also populated by watchdog_register_device. -* dev: device under the watchdog class (created by watchdog_register_device). -* parent: set this to the parent device (or NULL) before calling - watchdog_register_device. -* info: a pointer to a watchdog_info structure. This structure gives some - additional information about the watchdog timer itself. (Like it's unique name) -* ops: a pointer to the list of watchdog operations that the watchdog supports. -* timeout: the watchdog timer's timeout value (in seconds). -* min_timeout: the watchdog timer's minimum timeout value (in seconds). -* max_timeout: the watchdog timer's maximum timeout value (in seconds). -* bootstatus: status of the device after booting (reported with watchdog - WDIOF_* status bits). -* driver_data: a pointer to the drivers private data of a watchdog device. - This data should only be accessed via the watchdog_set_drvdata and - watchdog_get_drvdata routines. -* lock: Mutex for WatchDog Timer Driver Core internal use only. -* status: this field contains a number of status bits that give extra - information about the status of the device (Like: is the watchdog timer - running/active, is the nowayout bit set, is the device opened via - the /dev/watchdog interface or not, ...). - -The list of watchdog operations is defined as: - -struct watchdog_ops { - struct module *owner; - /* mandatory operations */ - int (*start)(struct watchdog_device *); - int (*stop)(struct watchdog_device *); - /* optional operations */ - int (*ping)(struct watchdog_device *); - unsigned int (*status)(struct watchdog_device *); - int (*set_timeout)(struct watchdog_device *, unsigned int); - unsigned int (*get_timeleft)(struct watchdog_device *); - void (*ref)(struct watchdog_device *); - void (*unref)(struct watchdog_device *); - long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long); -}; - -It is important that you first define the module owner of the watchdog timer -driver's operations. This module owner will be used to lock the module when -the watchdog is active. (This to avoid a system crash when you unload the -module and /dev/watchdog is still open). - -If the watchdog_device struct is dynamically allocated, just locking the module -is not enough and a driver also needs to define the ref and unref operations to -ensure the structure holding the watchdog_device does not go away. - -The simplest (and usually sufficient) implementation of this is to: -1) Add a kref struct to the same structure which is holding the watchdog_device -2) Define a release callback for the kref which frees the struct holding both -3) Call kref_init on this kref *before* calling watchdog_register_device() -4) Define a ref operation calling kref_get on this kref -5) Define a unref operation calling kref_put on this kref -6) When it is time to cleanup: - * Do not kfree() the struct holding both, the last kref_put will do this! - * *After* calling watchdog_unregister_device() call kref_put on the kref - -Some operations are mandatory and some are optional. The mandatory operations -are: -* start: this is a pointer to the routine that starts the watchdog timer - device. - The routine needs a pointer to the watchdog timer device structure as a - parameter. It returns zero on success or a negative errno code for failure. -* stop: with this routine the watchdog timer device is being stopped. - The routine needs a pointer to the watchdog timer device structure as a - parameter. It returns zero on success or a negative errno code for failure. - Some watchdog timer hardware can only be started and not be stopped. The - driver supporting this hardware needs to make sure that a start and stop - routine is being provided. This can be done by using a timer in the driver - that regularly sends a keepalive ping to the watchdog timer hardware. - -Not all watchdog timer hardware supports the same functionality. That's why -all other routines/operations are optional. They only need to be provided if -they are supported. These optional routines/operations are: -* ping: this is the routine that sends a keepalive ping to the watchdog timer - hardware. - The routine needs a pointer to the watchdog timer device structure as a - parameter. It returns zero on success or a negative errno code for failure. - Most hardware that does not support this as a separate function uses the - start function to restart the watchdog timer hardware. And that's also what - the watchdog timer driver core does: to send a keepalive ping to the watchdog - timer hardware it will either use the ping operation (when available) or the - start operation (when the ping operation is not available). - (Note: the WDIOC_KEEPALIVE ioctl call will only be active when the - WDIOF_KEEPALIVEPING bit has been set in the option field on the watchdog's - info structure). -* status: this routine checks the status of the watchdog timer device. The - status of the device is reported with watchdog WDIOF_* status flags/bits. -* set_timeout: this routine checks and changes the timeout of the watchdog - timer device. It returns 0 on success, -EINVAL for "parameter out of range" - and -EIO for "could not write value to the watchdog". On success this - routine should set the timeout value of the watchdog_device to the - achieved timeout value (which may be different from the requested one - because the watchdog does not necessarily has a 1 second resolution). - (Note: the WDIOF_SETTIMEOUT needs to be set in the options field of the - watchdog's info structure). -* get_timeleft: this routines returns the time that's left before a reset. -* ref: the operation that calls kref_get on the kref of a dynamically - allocated watchdog_device struct. -* unref: the operation that calls kref_put on the kref of a dynamically - allocated watchdog_device struct. -* ioctl: if this routine is present then it will be called first before we do - our own internal ioctl call handling. This routine should return -ENOIOCTLCMD - if a command is not supported. The parameters that are passed to the ioctl - call are: watchdog_device, cmd and arg. - -The status bits should (preferably) be set with the set_bit and clear_bit alike -bit-operations. The status bits that are defined are: -* WDOG_ACTIVE: this status bit indicates whether or not a watchdog timer device - is active or not. When the watchdog is active after booting, then you should - set this status bit (Note: when you register the watchdog timer device with - this bit set, then opening /dev/watchdog will skip the start operation) -* WDOG_DEV_OPEN: this status bit shows whether or not the watchdog device - was opened via /dev/watchdog. - (This bit should only be used by the WatchDog Timer Driver Core). -* WDOG_ALLOW_RELEASE: this bit stores whether or not the magic close character - has been sent (so that we can support the magic close feature). - (This bit should only be used by the WatchDog Timer Driver Core). -* WDOG_NO_WAY_OUT: this bit stores the nowayout setting for the watchdog. - If this bit is set then the watchdog timer will not be able to stop. -* WDOG_UNREGISTERED: this bit gets set by the WatchDog Timer Driver Core - after calling watchdog_unregister_device, and then checked before calling - any watchdog_ops, so that you can be sure that no operations (other then - unref) will get called after unregister, even if userspace still holds a - reference to /dev/watchdog - - To set the WDOG_NO_WAY_OUT status bit (before registering your watchdog - timer device) you can either: - * set it statically in your watchdog_device struct with - .status = WATCHDOG_NOWAYOUT_INIT_STATUS, - (this will set the value the same as CONFIG_WATCHDOG_NOWAYOUT) or - * use the following helper function: - static inline void watchdog_set_nowayout(struct watchdog_device *wdd, int nowayout) - -Note: The WatchDog Timer Driver Core supports the magic close feature and -the nowayout feature. To use the magic close feature you must set the -WDIOF_MAGICCLOSE bit in the options field of the watchdog's info structure. -The nowayout feature will overrule the magic close feature. - -To get or set driver specific data the following two helper functions should be -used: - -static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data) -static inline void *watchdog_get_drvdata(struct watchdog_device *wdd) - -The watchdog_set_drvdata function allows you to add driver specific data. The -arguments of this function are the watchdog device where you want to add the -driver specific data to and a pointer to the data itself. - -The watchdog_get_drvdata function allows you to retrieve driver specific data. -The argument of this function is the watchdog device where you want to retrieve -data from. The function returns the pointer to the driver specific data. - -To initialize the timeout field, the following function can be used: - -extern int watchdog_init_timeout(struct watchdog_device *wdd, - unsigned int timeout_parm, struct device *dev); - -The watchdog_init_timeout function allows you to initialize the timeout field -using the module timeout parameter or by retrieving the timeout-sec property from -the device tree (if the module timeout parameter is invalid). Best practice is -to set the default timeout value as timeout value in the watchdog_device and -then use this function to set the user "preferred" timeout value. -This routine returns zero on success and a negative errno code for failure. |
