[PATCH 1/6] watchdog: watchdog_dev: WATCHDOG_KEEP_ON feature
Janusz Użycki
j.uzycki at elproma.com.pl
Tue Sep 30 05:58:15 PDT 2014
I sent also the changelog:
[PATCH 1/6] watchdog: watchdog_dev: WATCHDOG_KEEP_ON feature
* clean up old comments
* watchdog_keepon_start() renamed to watchdog_timer_start()
* watchdog_keepon_stop() renamed to watchdog_timer_stop()
* watchdog_timer_register() added
* watchdog_timer_unregister() added
* watchdog_timer_register() is the last action
in watchdog_dev_register().
FIXME: Really should be in probe()?
* TODO: should watchdog_timer_start() call watchdog_start()?
* watchdog_release() uses watchdog_timer_restart() helper function
* TODO: change WDOG_KEEP_ON to autostart module parameter
Here I am still not sure about module parameters.
> autostart:
> Set to 0 to disable, -1 to enable with unlimited timeout,
> or <n> for an initial timeout of <n> seconds.
[1/6]: support of 0 and -1, where -1 is instead of WDOG_KEEP_ON?
[2/6]: support of <n> instead of boottime
what about:
* int init_timeout; /* initial timeout in seconds */
It looks as <n> so why duplicate the autostart parameter?
* keep_running
It looks like -1 without watchdog_start()
* this_watchdog_is_running()
Where defined?
* watchdog_set_autostart()
How to split new patches?
Janusz
W dniu 2014-09-30 14:46, Janusz Uzycki pisze:
> Some applications require to start watchdog before userspace software.
> This patch enables such feature. Only the flag is necessary
> to enable it.
> Moreover kernel's ping is re-enabled when userspace software closed
> watchdog using the magic character. The features improves kernel's
> reliability if hardware watchdog is available.
>
> Signed-off-by: Janusz Uzycki <j.uzycki at elproma.com.pl>
> ---
> drivers/watchdog/watchdog_dev.c | 65 ++++++++++++++++++++++++++-
> include/linux/watchdog.h | 4 ++
> 2 files changed, 68 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
> index 6aaefba..afc14f7 100644
> --- a/drivers/watchdog/watchdog_dev.c
> +++ b/drivers/watchdog/watchdog_dev.c
> @@ -41,6 +41,7 @@
> #include <linux/miscdevice.h> /* For handling misc devices */
> #include <linux/init.h> /* For __init/__exit/... */
> #include <linux/uaccess.h> /* For copy_to_user/put_user/... */
> +#include <linux/jiffies.h> /* for ping timer */
>
> #include "watchdog_core.h"
>
> @@ -277,6 +278,60 @@ out_ioctl:
> return err;
> }
>
> +static void watchdog_ping_timer_cb(unsigned long data)
> +{
> + struct watchdog_device *wdd = (struct watchdog_device *)data;
> + watchdog_ping(wdd);
> + /* call next ping half the timeout value */
> + mod_timer(&wdd->ping_timer,
> + jiffies + msecs_to_jiffies(wdd->timeout * 500));
> +}
> +
> +static void watchdog_timer_start(struct watchdog_device *wdd)
> +{
> + /* TODO: watchdog_start():
> + * it should probably be handled by the caller, to let us separate
> + * cases where the watchdog is already running (for example on close). */
> + watchdog_start(wdd);
> + watchdog_ping_timer_cb((unsigned long)wdd);
> +}
> +
> +static void watchdog_timer_stop(struct watchdog_device *wdd)
> +{
> + del_timer_sync(&wdd->ping_timer);
> +}
> +
> +static int watchdog_timer_restart(struct watchdog_device *wdd)
> +{
> + if (test_bit(WDOG_KEEP_ON, &wdd->status)) {
> + watchdog_timer_start(wdd);
> + return 0;
> + }
> + return watchdog_stop(wdd);
> +}
> +
> +static int watchdog_timer_register(struct watchdog_device *wdd)
> +{
> + if (test_bit(WDOG_KEEP_ON, &wdd->status)) {
> + if (!try_module_get(wdd->ops->owner))
> + return -ENODEV;
> + setup_timer(&wdd->ping_timer, watchdog_ping_timer_cb,
> + (unsigned long)wdd);
> + watchdog_timer_start(wdd);
> + }
> + return 0;
> +}
> +
> +static int watchdog_timer_unregister(struct watchdog_device *wdd)
> +{
> + if (test_bit(WDOG_KEEP_ON, &wdd->status)) {
> + watchdog_timer_stop(wdd);
> + watchdog_stop(wdd);
> + module_put(wdd->ops->owner);
> + }
> + return 0;
> +}
> +
> /*
> * watchdog_write: writes to the watchdog.
> * @file: file from VFS
> @@ -430,6 +485,9 @@ static int watchdog_open(struct inode *inode, struct file *file)
> if (!try_module_get(wdd->ops->owner))
> goto out;
>
> + if (test_bit(WDOG_KEEP_ON, &wdd->status))
> + watchdog_timer_stop(wdd);
> +
> err = watchdog_start(wdd);
> if (err < 0)
> goto out_mod;
> @@ -473,7 +531,7 @@ static int watchdog_release(struct inode *inode, struct file *file)
> err = 0;
> else if (test_and_clear_bit(WDOG_ALLOW_RELEASE, &wdd->status) ||
> !(wdd->info->options & WDIOF_MAGICCLOSE))
> - err = watchdog_stop(wdd);
> + err = watchdog_timer_restart(wdd);
>
> /* If the watchdog was not stopped, send a keepalive ping */
> if (err < 0) {
> @@ -553,7 +611,10 @@ int watchdog_dev_register(struct watchdog_device *watchdog)
> misc_deregister(&watchdog_miscdev);
> old_wdd = NULL;
> }
> + return err;
> }
> +
> + err = watchdog_timer_register(watchdog);
> return err;
> }
>
> @@ -575,6 +636,8 @@ int watchdog_dev_unregister(struct watchdog_device *watchdog)
> misc_deregister(&watchdog_miscdev);
> old_wdd = NULL;
> }
> +
> + watchdog_timer_unregister(watchdog);
> return 0;
> }
>
> diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
> index 2a3038e..0afeabd 100644
> --- a/include/linux/watchdog.h
> +++ b/include/linux/watchdog.h
> @@ -12,6 +12,7 @@
> #include <linux/bitops.h>
> #include <linux/device.h>
> #include <linux/cdev.h>
> +#include <linux/timer.h> /* for ping timer */
> #include <uapi/linux/watchdog.h>
>
> struct watchdog_ops;
> @@ -95,6 +96,8 @@ struct watchdog_device {
> #define WDOG_ALLOW_RELEASE 2 /* Did we receive the magic char ? */
> #define WDOG_NO_WAY_OUT 3 /* Is 'nowayout' feature set ? */
> #define WDOG_UNREGISTERED 4 /* Has the device been unregistered */
> +#define WDOG_KEEP_ON 5 /* Is 'keep on' feature set? */
> + struct timer_list ping_timer; /* timer to keep on hardware ping */
> };
>
> #ifdef CONFIG_WATCHDOG_NOWAYOUT
> @@ -104,6 +107,7 @@ struct watchdog_device {
> #define WATCHDOG_NOWAYOUT 0
> #define WATCHDOG_NOWAYOUT_INIT_STATUS 0
> #endif
> +#define WATCHDOG_KEEP_ON (1 << WDOG_KEEP_ON)
>
> /* Use the following function to check whether or not the watchdog is active */
> static inline bool watchdog_active(struct watchdog_device *wdd)
More information about the linux-arm-kernel
mailing list