Skip to content
Permalink
Browse files
watchdog: introduce watchdog_dev_suspend/resume
The watchdog drivers often disable wdog clock during suspend and then
enable it again during resume. Nevertheless the ping worker is still
running and can issue low-level ping while the wdog clock is disabled
causing the system hang. To prevent such condition introduce
watchdog_dev_suspend/resume which can be used by any wdog driver and
actually cancel ping worker during suspend and restore it back, if
needed, during resume.

Signed-off-by: Grzegorz Jaszczyk <grzegorz.jaszczyk@linaro.org>
  • Loading branch information
Grzegorz-J authored and intel-lab-lkp committed Jun 16, 2021
1 parent 8e6f6d9 commit 71dadcad8da1862c1205b19ddf4279d494e57545
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 0 deletions.
@@ -1219,6 +1219,55 @@ void __exit watchdog_dev_exit(void)
kthread_destroy_worker(watchdog_kworker);
}

int watchdog_dev_suspend(struct watchdog_device *wdd)
{
struct watchdog_core_data *wd_data = wdd->wd_data;
int ret;

if (!wdd->wd_data)
return -ENODEV;

/* ping for the last time before suspend */
mutex_lock(&wd_data->lock);
if (watchdog_worker_should_ping(wd_data))
ret = __watchdog_ping(wd_data->wdd);
mutex_unlock(&wd_data->lock);

if (ret)
return ret;

/*
* make sure that watchdog worker will not kick in when the wdog is
* suspended
*/
hrtimer_cancel(&wd_data->timer);
kthread_cancel_work_sync(&wd_data->work);

return 0;
}
EXPORT_SYMBOL_GPL(watchdog_dev_suspend);

int watchdog_dev_resume(struct watchdog_device *wdd)
{
struct watchdog_core_data *wd_data = wdd->wd_data;
int ret;

if (!wdd->wd_data)
return -ENODEV;

/*
* __watchdog_ping will also retrigger hrtimer and therefore restore the
* ping worker if needed.
*/
mutex_lock(&wd_data->lock);
if (watchdog_worker_should_ping(wd_data))
ret = __watchdog_ping(wd_data->wdd);
mutex_unlock(&wd_data->lock);

return ret;
}
EXPORT_SYMBOL_GPL(watchdog_dev_resume);

module_param(handle_boot_enabled, bool, 0444);
MODULE_PARM_DESC(handle_boot_enabled,
"Watchdog core auto-updates boot enabled watchdogs before userspace takes over (default="
@@ -209,6 +209,8 @@ extern int watchdog_init_timeout(struct watchdog_device *wdd,
unsigned int timeout_parm, struct device *dev);
extern int watchdog_register_device(struct watchdog_device *);
extern void watchdog_unregister_device(struct watchdog_device *);
int watchdog_dev_suspend(struct watchdog_device *wdd);
int watchdog_dev_resume(struct watchdog_device *wdd);

int watchdog_set_last_hw_keepalive(struct watchdog_device *, unsigned int);

0 comments on commit 71dadca

Please sign in to comment.