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>zero-colors
parent
7b1bbbed90
commit
8b9e62cf99
|
@ -1167,6 +1167,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);
|
||||
|
||||
/* devres register variant */
|
||||
int devm_watchdog_register_device(struct device *dev, struct watchdog_device *);
|
||||
|
|
Loading…
Reference in New Issue