watchdog: Make stop function optional

Not all hardware watchdogs can be stopped. The driver for
such watchdogs would typically only set the WATCHDOG_HW_RUNNING
flag in its stop function. Make the stop function optional and set
WATCHDOG_HW_RUNNING in the watchdog core if it is not provided.

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
This commit is contained in:
Guenter Roeck 2016-02-28 13:12:17 -08:00 committed by Wim Van Sebroeck
parent ee142889e3
commit d0684c8a93
3 changed files with 18 additions and 10 deletions

View File

@ -85,7 +85,8 @@ It contains following fields:
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.
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.
@ -134,17 +135,20 @@ are:
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.
If a watchdog can not be stopped, the watchdog driver must set the
WDOG_HW_RUNNING flag in its stop function to inform the watchdog core that
the watchdog is still running.
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

View File

@ -199,7 +199,7 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
return -EINVAL;
/* Mandatory operations need to be supported */
if (wdd->ops->start == NULL || wdd->ops->stop == NULL)
if (!wdd->ops->start || (!wdd->ops->stop && !wdd->max_hw_heartbeat_ms))
return -EINVAL;
watchdog_check_min_max_timeout(wdd);

View File

@ -246,7 +246,11 @@ static int watchdog_stop(struct watchdog_device *wdd)
return -EBUSY;
}
err = wdd->ops->stop(wdd);
if (wdd->ops->stop)
err = wdd->ops->stop(wdd);
else
set_bit(WDOG_HW_RUNNING, &wdd->status);
if (err == 0) {
clear_bit(WDOG_ACTIVE, &wdd->status);
watchdog_update_worker(wdd);