123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- The Linux WatchDog Timer Driver Core kernel API.
- ===============================================
- Last reviewed: 12-Feb-2013
- Wim Van Sebroeck <[email protected]>
- 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 subsystem includes an registration deferral mechanism,
- which allows you to register an watchdog as early as you wish during
- the boot process.
- The watchdog device structure looks like this:
- struct watchdog_device {
- int id;
- struct device *parent;
- const struct attribute_group **groups;
- const struct watchdog_info *info;
- const struct watchdog_ops *ops;
- const struct watchdog_governor *gov;
- unsigned int bootstatus;
- unsigned int timeout;
- unsigned int pretimeout;
- unsigned int min_timeout;
- unsigned int max_timeout;
- unsigned int min_hw_heartbeat_ms;
- unsigned int max_hw_heartbeat_ms;
- struct notifier_block reboot_nb;
- struct notifier_block restart_nb;
- void *driver_data;
- struct watchdog_core_data *wd_data;
- unsigned long status;
- struct list_head deferred;
- };
- 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.
- * parent: set this to the parent device (or NULL) before calling
- watchdog_register_device.
- * groups: List of sysfs attribute groups to create when creating the watchdog
- 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.
- * gov: a pointer to the assigned watchdog device pretimeout governor or NULL.
- * timeout: the watchdog timer's timeout value (in seconds).
- This is the time after which the system will reboot if user space does
- not send a heartbeat request if WDOG_ACTIVE is set.
- * pretimeout: the watchdog timer's pretimeout value (in seconds).
- * min_timeout: the watchdog timer's minimum timeout value (in seconds).
- If set, the minimum configurable value for 'timeout'.
- * max_timeout: the watchdog timer's maximum timeout value (in seconds),
- as seen from userspace. If set, the maximum configurable value for
- 'timeout'. Not used if max_hw_heartbeat_ms is non-zero.
- * min_hw_heartbeat_ms: Hardware limit for minimum time between heartbeats,
- in milli-seconds. This value is normally 0; it should only be provided
- if the hardware can not tolerate lower intervals between heartbeats.
- * max_hw_heartbeat_ms: Maximum hardware heartbeat, in milli-seconds.
- If set, the infrastructure will send heartbeats to the watchdog driver
- if 'timeout' is larger than max_hw_heartbeat_ms, unless WDOG_ACTIVE
- is set and userspace failed to send a heartbeat for at least 'timeout'
- seconds. max_hw_heartbeat_ms must be set if a driver does not implement
- the stop function.
- * reboot_nb: notifier block that is registered for reboot notifications, for
- internal use only. If the driver calls watchdog_stop_on_reboot, watchdog core
- will stop the watchdog on such notifications.
- * restart_nb: notifier block that is registered for machine restart, for
- internal use only. If a watchdog is capable of restarting the machine, it
- should define ops->restart. Priority can be changed through
- watchdog_set_restart_priority.
- * 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.
- * wd_data: a pointer to watchdog core internal data.
- * 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, or is the nowayout bit set).
- * deferred: entry in wtd_deferred_reg_list which is used to
- register early initialized watchdogs.
- 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);
- int (*set_pretimeout)(struct watchdog_device *, unsigned int);
- unsigned int (*get_timeleft)(struct watchdog_device *);
- int (*restart)(struct watchdog_device *);
- void (*ref)(struct watchdog_device *) __deprecated;
- void (*unref)(struct watchdog_device *) __deprecated;
- 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).
- 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.
- 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:
- * 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. A
- driver supporting such hardware does not have to implement the stop routine.
- If a driver has no stop function, the watchdog core will set WDOG_HW_RUNNING
- and start calling the driver's keepalive pings function after the watchdog
- device is closed.
- If a watchdog driver does not implement the stop function, it must set
- max_hw_heartbeat_ms.
- * 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.
- WDIOF_MAGICCLOSE and WDIOF_KEEPALIVEPING are reported by the watchdog core;
- it is not necessary to report those bits from the driver. Also, if no status
- function is provided by the driver, the watchdog core reports the status bits
- provided in the bootstatus variable of struct watchdog_device.
- * 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 have a 1 second resolution).
- Drivers implementing max_hw_heartbeat_ms set the hardware watchdog heartbeat
- to the minimum of timeout and max_hw_heartbeat_ms. Those drivers set the
- timeout value of the watchdog_device either to the requested timeout value
- (if it is larger than max_hw_heartbeat_ms), or to the achieved timeout value.
- (Note: the WDIOF_SETTIMEOUT needs to be set in the options field of the
- watchdog's info structure).
- If the watchdog driver does not have to perform any action but setting the
- watchdog_device.timeout, this callback can be omitted.
- If set_timeout is not provided but, WDIOF_SETTIMEOUT is set, the watchdog
- infrastructure updates the timeout value of the watchdog_device internally
- to the requested value.
- If the pretimeout feature is used (WDIOF_PRETIMEOUT), then set_timeout must
- also take care of checking if pretimeout is still valid and set up the timer
- accordingly. This can't be done in the core without races, so it is the
- duty of the driver.
- * set_pretimeout: this routine checks and changes the pretimeout value of
- the watchdog. It is optional because not all watchdogs support pretimeout
- notification. The timeout value is not an absolute time, but the number of
- seconds before the actual timeout would happen. It returns 0 on success,
- -EINVAL for "parameter out of range" and -EIO for "could not write value to
- the watchdog". A value of 0 disables pretimeout notification.
- (Note: the WDIOF_PRETIMEOUT needs to be set in the options field of the
- watchdog's info structure).
- If the watchdog driver does not have to perform any action but setting the
- watchdog_device.pretimeout, this callback can be omitted. That means if
- set_pretimeout is not provided but WDIOF_PRETIMEOUT is set, the watchdog
- infrastructure updates the pretimeout value of the watchdog_device internally
- to the requested value.
- * get_timeleft: this routines returns the time that's left before a reset.
- * restart: this routine restarts the machine. It returns 0 on success or a
- negative errno code for failure.
- * 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 'ref' and 'unref' operations are no longer used and deprecated.
- 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 from user perspective. User space is expected to send
- heartbeat requests to the driver while this flag is set.
- * 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_HW_RUNNING: Set by the watchdog driver if the hardware watchdog is
- running. The bit must be set if the watchdog timer hardware can not be
- stopped. The bit may also be set if the watchdog timer is running after
- booting, before the watchdog device is opened. If set, the watchdog
- infrastructure will send keepalives to the watchdog hardware while
- WDOG_ACTIVE is not set.
- Note: when you register the watchdog timer device with this bit set,
- then opening /dev/watchdog will skip the start operation but send a keepalive
- request instead.
- 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.
- To disable the watchdog on reboot, the user must call the following helper:
- static inline void watchdog_stop_on_reboot(struct watchdog_device *wdd);
- To change the priority of the restart handler the following helper should be
- used:
- void watchdog_set_restart_priority(struct watchdog_device *wdd, int priority);
- User should follow the following guidelines for setting the priority:
- * 0: should be called in last resort, has limited restart capabilities
- * 128: default restart handler, use if no other handler is expected to be
- available, and/or if restart is sufficient to restart the entire system
- * 255: highest priority, will preempt all other restart handlers
- To raise a pretimeout notification, the following function should be used:
- void watchdog_notify_pretimeout(struct watchdog_device *wdd)
- The function can be called in the interrupt context. If watchdog pretimeout
- governor framework (kbuild CONFIG_WATCHDOG_PRETIMEOUT_GOV symbol) is enabled,
- an action is taken by a preconfigured pretimeout governor preassigned to
- the watchdog device. If watchdog pretimeout governor framework is not
- enabled, watchdog_notify_pretimeout() prints a notification message to
- the kernel log buffer.
|