Merge tag 'linux-watchdog-5.9-rc1' of git://www.linux-watchdog.org/linux-watchdog
[linux-2.6-microblaze.git] / drivers / watchdog / watchdog_dev.c
index b7d750b..6798add 100644 (file)
@@ -275,15 +275,18 @@ static int watchdog_start(struct watchdog_device *wdd)
        set_bit(_WDOG_KEEPALIVE, &wd_data->status);
 
        started_at = ktime_get();
-       if (watchdog_hw_running(wdd) && wdd->ops->ping)
-               err = wdd->ops->ping(wdd);
-       else
+       if (watchdog_hw_running(wdd) && wdd->ops->ping) {
+               err = __watchdog_ping(wdd);
+               if (err == 0)
+                       set_bit(WDOG_ACTIVE, &wdd->status);
+       } else {
                err = wdd->ops->start(wdd);
-       if (err == 0) {
-               set_bit(WDOG_ACTIVE, &wdd->status);
-               wd_data->last_keepalive = started_at;
-               wd_data->last_hw_keepalive = started_at;
-               watchdog_update_worker(wdd);
+               if (err == 0) {
+                       set_bit(WDOG_ACTIVE, &wdd->status);
+                       wd_data->last_keepalive = started_at;
+                       wd_data->last_hw_keepalive = started_at;
+                       watchdog_update_worker(wdd);
+               }
        }
 
        return err;
@@ -1135,6 +1138,36 @@ void watchdog_dev_unregister(struct watchdog_device *wdd)
        watchdog_cdev_unregister(wdd);
 }
 
+/*
+ *     watchdog_set_last_hw_keepalive: set last HW keepalive time for watchdog
+ *     @wdd: watchdog device
+ *     @last_ping_ms: time since last HW heartbeat
+ *
+ *     Adjusts the last known HW keepalive time for a watchdog timer.
+ *     This is needed if the watchdog is already running when the probe
+ *     function is called, and it can't be pinged immediately. This
+ *     function must be called immediately after watchdog registration,
+ *     and min_hw_heartbeat_ms must be set for this to be useful.
+ */
+int watchdog_set_last_hw_keepalive(struct watchdog_device *wdd,
+                                  unsigned int last_ping_ms)
+{
+       struct watchdog_core_data *wd_data;
+       ktime_t now;
+
+       if (!wdd)
+               return -EINVAL;
+
+       wd_data = wdd->wd_data;
+
+       now = ktime_get();
+
+       wd_data->last_hw_keepalive = ktime_sub(now, ms_to_ktime(last_ping_ms));
+
+       return __watchdog_ping(wdd);
+}
+EXPORT_SYMBOL_GPL(watchdog_set_last_hw_keepalive);
+
 /*
  *     watchdog_dev_init: init dev part of watchdog core
  *
@@ -1144,14 +1177,13 @@ void watchdog_dev_unregister(struct watchdog_device *wdd)
 int __init watchdog_dev_init(void)
 {
        int err;
-       struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1,};
 
        watchdog_kworker = kthread_create_worker(0, "watchdogd");
        if (IS_ERR(watchdog_kworker)) {
                pr_err("Failed to create watchdog kworker\n");
                return PTR_ERR(watchdog_kworker);
        }
-       sched_setscheduler(watchdog_kworker->task, SCHED_FIFO, &param);
+       sched_set_fifo(watchdog_kworker->task);
 
        err = class_register(&watchdog_class);
        if (err < 0) {