diff options
Diffstat (limited to 'drivers/watchdog/watchdog_dev.c')
-rw-r--r-- | drivers/watchdog/watchdog_dev.c | 47 |
1 files changed, 17 insertions, 30 deletions
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index 7c1007ab1b71..3bab32485273 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -7,6 +7,7 @@ * * (c) Copyright 2008-2011 Wim Van Sebroeck <wim@iguana.be>. * + * (c) Copyright 2021 Hewlett Packard Enterprise Development LP. * * This source code is part of the generic code that can be used * by all the watchdog timer drivers. @@ -46,30 +47,6 @@ #include "watchdog_core.h" #include "watchdog_pretimeout.h" -/* - * struct watchdog_core_data - watchdog core internal data - * @dev: The watchdog's internal device - * @cdev: The watchdog's Character device. - * @wdd: Pointer to watchdog device. - * @lock: Lock for watchdog core. - * @status: Watchdog core internal status bits. - */ -struct watchdog_core_data { - struct device dev; - struct cdev cdev; - struct watchdog_device *wdd; - struct mutex lock; - ktime_t last_keepalive; - ktime_t last_hw_keepalive; - ktime_t open_deadline; - struct hrtimer timer; - struct kthread_work work; - unsigned long status; /* Internal status bits */ -#define _WDOG_DEV_OPEN 0 /* Opened ? */ -#define _WDOG_ALLOW_RELEASE 1 /* Did we receive the magic char ? */ -#define _WDOG_KEEPALIVE 2 /* Did we receive a keepalive ? */ -}; - /* the dev_t structure to store the dynamically allocated watchdog devices */ static dev_t watchdog_devt; /* Reference to watchdog device behind /dev/watchdog */ @@ -185,6 +162,9 @@ static int __watchdog_ping(struct watchdog_device *wdd) else err = wdd->ops->start(wdd); /* restart watchdog */ + if (err == 0) + watchdog_hrtimer_pretimeout_start(wdd); + watchdog_update_worker(wdd); return err; @@ -275,8 +255,10 @@ static int watchdog_start(struct watchdog_device *wdd) started_at = ktime_get(); if (watchdog_hw_running(wdd) && wdd->ops->ping) { err = __watchdog_ping(wdd); - if (err == 0) + if (err == 0) { set_bit(WDOG_ACTIVE, &wdd->status); + watchdog_hrtimer_pretimeout_start(wdd); + } } else { err = wdd->ops->start(wdd); if (err == 0) { @@ -284,6 +266,7 @@ static int watchdog_start(struct watchdog_device *wdd) wd_data->last_keepalive = started_at; wd_data->last_hw_keepalive = started_at; watchdog_update_worker(wdd); + watchdog_hrtimer_pretimeout_start(wdd); } } @@ -325,6 +308,7 @@ static int watchdog_stop(struct watchdog_device *wdd) if (err == 0) { clear_bit(WDOG_ACTIVE, &wdd->status); watchdog_update_worker(wdd); + watchdog_hrtimer_pretimeout_stop(wdd); } return err; @@ -361,6 +345,9 @@ static unsigned int watchdog_get_status(struct watchdog_device *wdd) if (test_and_clear_bit(_WDOG_KEEPALIVE, &wd_data->status)) status |= WDIOF_KEEPALIVEPING; + if (IS_ENABLED(CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT)) + status |= WDIOF_PRETIMEOUT; + return status; } @@ -408,7 +395,7 @@ static int watchdog_set_pretimeout(struct watchdog_device *wdd, { int err = 0; - if (!(wdd->info->options & WDIOF_PRETIMEOUT)) + if (!watchdog_have_pretimeout(wdd)) return -EOPNOTSUPP; if (watchdog_pretimeout_invalid(wdd, timeout)) @@ -613,13 +600,11 @@ static umode_t wdt_is_visible(struct kobject *kobj, struct attribute *attr, if (attr == &dev_attr_timeleft.attr && !wdd->ops->get_timeleft) mode = 0; - else if (attr == &dev_attr_pretimeout.attr && - !(wdd->info->options & WDIOF_PRETIMEOUT)) + else if (attr == &dev_attr_pretimeout.attr && !watchdog_have_pretimeout(wdd)) mode = 0; else if ((attr == &dev_attr_pretimeout_governor.attr || attr == &dev_attr_pretimeout_available_governors.attr) && - (!(wdd->info->options & WDIOF_PRETIMEOUT) || - !IS_ENABLED(CONFIG_WATCHDOG_PRETIMEOUT_GOV))) + (!watchdog_have_pretimeout(wdd) || !IS_ENABLED(CONFIG_WATCHDOG_PRETIMEOUT_GOV))) mode = 0; return mode; @@ -1030,6 +1015,7 @@ static int watchdog_cdev_register(struct watchdog_device *wdd) kthread_init_work(&wd_data->work, watchdog_ping_work); hrtimer_init(&wd_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD); wd_data->timer.function = watchdog_timer_expired; + watchdog_hrtimer_pretimeout_init(wdd); if (wdd->id == 0) { old_wd_data = wd_data; @@ -1117,6 +1103,7 @@ static void watchdog_cdev_unregister(struct watchdog_device *wdd) hrtimer_cancel(&wd_data->timer); kthread_cancel_work_sync(&wd_data->work); + watchdog_hrtimer_pretimeout_stop(wdd); put_device(&wd_data->dev); } |