if (watchdog_pretimeout_invalid(wdd, timeout))
return -EINVAL;
- if (wdd->ops->set_pretimeout)
+ if (wdd->ops->set_pretimeout && (wdd->info->options & WDIOF_PRETIMEOUT))
err = wdd->ops->set_pretimeout(wdd, timeout);
else
wdd->pretimeout = timeout;
watchdog_stop(wdd);
}
+ watchdog_hrtimer_pretimeout_stop(wdd);
+
mutex_lock(&wd_data->lock);
wd_data->wdd = NULL;
wdd->wd_data = NULL;
hrtimer_cancel(&wd_data->timer);
kthread_cancel_work_sync(&wd_data->work);
- watchdog_hrtimer_pretimeout_stop(wdd);
put_device(&wd_data->dev);
}
wd_data->last_hw_keepalive = ktime_sub(now, ms_to_ktime(last_ping_ms));
- return __watchdog_ping(wdd);
+ if (watchdog_hw_running(wdd) && handle_boot_enabled)
+ return __watchdog_ping(wdd);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(watchdog_set_last_hw_keepalive);
kthread_destroy_worker(watchdog_kworker);
}
+int watchdog_dev_suspend(struct watchdog_device *wdd)
+{
+ struct watchdog_core_data *wd_data = wdd->wd_data;
+ int ret = 0;
+
+ 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;
+}
+
+int watchdog_dev_resume(struct watchdog_device *wdd)
+{
+ struct watchdog_core_data *wd_data = wdd->wd_data;
+ int ret = 0;
+
+ 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;
+}
+
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="