hc
2024-05-14 bedbef8ad3e75a304af6361af235302bcc61d06b
kernel/drivers/watchdog/watchdog_dev.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0+
12 /*
23 * watchdog_dev.c
34 *
....@@ -19,11 +20,6 @@
1920 * Rusty Lynch <rusty@linux.co.intel.com>
2021 * Satyam Sharma <satyam@infradead.org>
2122 * Randy Dunlap <randy.dunlap@oracle.com>
22
- *
23
- * This program is free software; you can redistribute it and/or
24
- * modify it under the terms of the GNU General Public License
25
- * as published by the Free Software Foundation; either version
26
- * 2 of the License, or (at your option) any later version.
2723 *
2824 * Neither Alan Cox, CymruNet Ltd., Wim Van Sebroeck nor Iguana vzw.
2925 * admit liability nor provide warranty for any of this software.
....@@ -47,8 +43,6 @@
4743 #include <linux/watchdog.h> /* For watchdog specific items */
4844 #include <linux/uaccess.h> /* For copy_to_user/put_user/... */
4945
50
-#include <uapi/linux/sched/types.h> /* For struct sched_param */
51
-
5246 #include "watchdog_core.h"
5347 #include "watchdog_pretimeout.h"
5448
....@@ -67,6 +61,7 @@
6761 struct mutex lock;
6862 ktime_t last_keepalive;
6963 ktime_t last_hw_keepalive;
64
+ ktime_t open_deadline;
7065 struct hrtimer timer;
7166 struct kthread_work work;
7267 unsigned long status; /* Internal status bits */
....@@ -84,6 +79,19 @@
8479
8580 static bool handle_boot_enabled =
8681 IS_ENABLED(CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED);
82
+
83
+static unsigned open_timeout = CONFIG_WATCHDOG_OPEN_TIMEOUT;
84
+
85
+static bool watchdog_past_open_deadline(struct watchdog_core_data *data)
86
+{
87
+ return ktime_after(ktime_get(), data->open_deadline);
88
+}
89
+
90
+static void watchdog_set_open_deadline(struct watchdog_core_data *data)
91
+{
92
+ data->open_deadline = open_timeout ?
93
+ ktime_get() + ktime_set(open_timeout, 0) : KTIME_MAX;
94
+}
8795
8896 static inline bool watchdog_need_worker(struct watchdog_device *wdd)
8997 {
....@@ -117,13 +125,14 @@
117125 ktime_t virt_timeout;
118126 unsigned int hw_heartbeat_ms;
119127
120
- virt_timeout = ktime_add(wd_data->last_keepalive,
121
- ms_to_ktime(timeout_ms));
128
+ if (watchdog_active(wdd))
129
+ virt_timeout = ktime_add(wd_data->last_keepalive,
130
+ ms_to_ktime(timeout_ms));
131
+ else
132
+ virt_timeout = wd_data->open_deadline;
133
+
122134 hw_heartbeat_ms = min_not_zero(timeout_ms, wdd->max_hw_heartbeat_ms);
123135 keepalive_interval = ms_to_ktime(hw_heartbeat_ms / 2);
124
-
125
- if (!watchdog_active(wdd))
126
- return keepalive_interval;
127136
128137 /*
129138 * To ensure that the watchdog times out wdd->timeout seconds
....@@ -145,7 +154,8 @@
145154 ktime_t t = watchdog_next_keepalive(wdd);
146155
147156 if (t > 0)
148
- hrtimer_start(&wd_data->timer, t, HRTIMER_MODE_REL);
157
+ hrtimer_start(&wd_data->timer, t,
158
+ HRTIMER_MODE_REL_HARD);
149159 } else {
150160 hrtimer_cancel(&wd_data->timer);
151161 }
....@@ -164,7 +174,7 @@
164174 if (ktime_after(earliest_keepalive, now)) {
165175 hrtimer_start(&wd_data->timer,
166176 ktime_sub(earliest_keepalive, now),
167
- HRTIMER_MODE_REL);
177
+ HRTIMER_MODE_REL_HARD);
168178 return 0;
169179 }
170180
....@@ -209,7 +219,13 @@
209219 {
210220 struct watchdog_device *wdd = wd_data->wdd;
211221
212
- return wdd && (watchdog_active(wdd) || watchdog_hw_running(wdd));
222
+ if (!wdd)
223
+ return false;
224
+
225
+ if (watchdog_active(wdd))
226
+ return true;
227
+
228
+ return watchdog_hw_running(wdd) && !watchdog_past_open_deadline(wd_data);
213229 }
214230
215231 static void watchdog_ping_work(struct kthread_work *work)
....@@ -257,15 +273,18 @@
257273 set_bit(_WDOG_KEEPALIVE, &wd_data->status);
258274
259275 started_at = ktime_get();
260
- if (watchdog_hw_running(wdd) && wdd->ops->ping)
261
- err = wdd->ops->ping(wdd);
262
- else
276
+ if (watchdog_hw_running(wdd) && wdd->ops->ping) {
277
+ err = __watchdog_ping(wdd);
278
+ if (err == 0)
279
+ set_bit(WDOG_ACTIVE, &wdd->status);
280
+ } else {
263281 err = wdd->ops->start(wdd);
264
- if (err == 0) {
265
- set_bit(WDOG_ACTIVE, &wdd->status);
266
- wd_data->last_keepalive = started_at;
267
- wd_data->last_hw_keepalive = started_at;
268
- watchdog_update_worker(wdd);
282
+ if (err == 0) {
283
+ set_bit(WDOG_ACTIVE, &wdd->status);
284
+ wd_data->last_keepalive = started_at;
285
+ wd_data->last_hw_keepalive = started_at;
286
+ watchdog_update_worker(wdd);
287
+ }
269288 }
270289
271290 return err;
....@@ -434,7 +453,26 @@
434453
435454 return sprintf(buf, "%d\n", !!test_bit(WDOG_NO_WAY_OUT, &wdd->status));
436455 }
437
-static DEVICE_ATTR_RO(nowayout);
456
+
457
+static ssize_t nowayout_store(struct device *dev, struct device_attribute *attr,
458
+ const char *buf, size_t len)
459
+{
460
+ struct watchdog_device *wdd = dev_get_drvdata(dev);
461
+ unsigned int value;
462
+ int ret;
463
+
464
+ ret = kstrtouint(buf, 0, &value);
465
+ if (ret)
466
+ return ret;
467
+ if (value > 1)
468
+ return -EINVAL;
469
+ /* nowayout cannot be disabled once set */
470
+ if (test_bit(WDOG_NO_WAY_OUT, &wdd->status) && !value)
471
+ return -EPERM;
472
+ watchdog_set_nowayout(wdd, value);
473
+ return len;
474
+}
475
+static DEVICE_ATTR_RW(nowayout);
438476
439477 static ssize_t status_show(struct device *dev, struct device_attribute *attr,
440478 char *buf)
....@@ -550,7 +588,7 @@
550588 static umode_t wdt_is_visible(struct kobject *kobj, struct attribute *attr,
551589 int n)
552590 {
553
- struct device *dev = container_of(kobj, struct device, kobj);
591
+ struct device *dev = kobj_to_dev(kobj);
554592 struct watchdog_device *wdd = dev_get_drvdata(dev);
555593 umode_t mode = attr->mode;
556594
....@@ -739,7 +777,7 @@
739777 err = watchdog_ping(wdd);
740778 if (err < 0)
741779 break;
742
- /* fall through */
780
+ fallthrough;
743781 case WDIOC_GETTIMEOUT:
744782 /* timeout == 0 means that we don't know the timeout */
745783 if (wdd->timeout == 0) {
....@@ -823,8 +861,17 @@
823861 if (!hw_running)
824862 get_device(&wd_data->dev);
825863
864
+ /*
865
+ * open_timeout only applies for the first open from
866
+ * userspace. Set open_deadline to infinity so that the kernel
867
+ * will take care of an always-running hardware watchdog in
868
+ * case the device gets magic-closed or WDIOS_DISABLECARD is
869
+ * applied.
870
+ */
871
+ wd_data->open_deadline = KTIME_MAX;
872
+
826873 /* dev/watchdog is a virtual (and thus non-seekable) filesystem */
827
- return nonseekable_open(inode, file);
874
+ return stream_open(inode, file);
828875
829876 out_mod:
830877 module_put(wd_data->wdd->ops->owner);
....@@ -870,7 +917,7 @@
870917 * or if WDIOF_MAGICCLOSE is not set. If nowayout was set then
871918 * watchdog_stop will fail.
872919 */
873
- if (!test_bit(WDOG_ACTIVE, &wdd->status))
920
+ if (!watchdog_active(wdd))
874921 err = 0;
875922 else if (test_and_clear_bit(_WDOG_ALLOW_RELEASE, &wd_data->status) ||
876923 !(wdd->info->options & WDIOF_MAGICCLOSE))
....@@ -906,6 +953,7 @@
906953 .owner = THIS_MODULE,
907954 .write = watchdog_write,
908955 .unlocked_ioctl = watchdog_ioctl,
956
+ .compat_ioctl = compat_ptr_ioctl,
909957 .open = watchdog_open,
910958 .release = watchdog_release,
911959 };
....@@ -959,7 +1007,7 @@
9591007 dev_set_name(&wd_data->dev, "watchdog%d", wdd->id);
9601008
9611009 kthread_init_work(&wd_data->work, watchdog_ping_work);
962
- hrtimer_init(&wd_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
1010
+ hrtimer_init(&wd_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
9631011 wd_data->timer.function = watchdog_timer_expired;
9641012
9651013 if (wdd->id == 0) {
....@@ -989,8 +1037,8 @@
9891037 if (wdd->id == 0) {
9901038 misc_deregister(&watchdog_miscdev);
9911039 old_wd_data = NULL;
992
- put_device(&wd_data->dev);
9931040 }
1041
+ put_device(&wd_data->dev);
9941042 return err;
9951043 }
9961044
....@@ -998,6 +1046,7 @@
9981046
9991047 /* Record time of most recent heartbeat as 'just before now'. */
10001048 wd_data->last_hw_keepalive = ktime_sub(ktime_get(), 1);
1049
+ watchdog_set_open_deadline(wd_data);
10011050
10021051 /*
10031052 * If the watchdog is running, prevent its driver from being unloaded,
....@@ -1007,7 +1056,8 @@
10071056 __module_get(wdd->ops->owner);
10081057 get_device(&wd_data->dev);
10091058 if (handle_boot_enabled)
1010
- hrtimer_start(&wd_data->timer, 0, HRTIMER_MODE_REL);
1059
+ hrtimer_start(&wd_data->timer, 0,
1060
+ HRTIMER_MODE_REL_HARD);
10111061 else
10121062 pr_info("watchdog%d running and kernel based pre-userspace handler disabled\n",
10131063 wdd->id);
....@@ -1089,6 +1139,39 @@
10891139 }
10901140
10911141 /*
1142
+ * watchdog_set_last_hw_keepalive: set last HW keepalive time for watchdog
1143
+ * @wdd: watchdog device
1144
+ * @last_ping_ms: time since last HW heartbeat
1145
+ *
1146
+ * Adjusts the last known HW keepalive time for a watchdog timer.
1147
+ * This is needed if the watchdog is already running when the probe
1148
+ * function is called, and it can't be pinged immediately. This
1149
+ * function must be called immediately after watchdog registration,
1150
+ * and min_hw_heartbeat_ms must be set for this to be useful.
1151
+ */
1152
+int watchdog_set_last_hw_keepalive(struct watchdog_device *wdd,
1153
+ unsigned int last_ping_ms)
1154
+{
1155
+ struct watchdog_core_data *wd_data;
1156
+ ktime_t now;
1157
+
1158
+ if (!wdd)
1159
+ return -EINVAL;
1160
+
1161
+ wd_data = wdd->wd_data;
1162
+
1163
+ now = ktime_get();
1164
+
1165
+ wd_data->last_hw_keepalive = ktime_sub(now, ms_to_ktime(last_ping_ms));
1166
+
1167
+ if (watchdog_hw_running(wdd) && handle_boot_enabled)
1168
+ return __watchdog_ping(wdd);
1169
+
1170
+ return 0;
1171
+}
1172
+EXPORT_SYMBOL_GPL(watchdog_set_last_hw_keepalive);
1173
+
1174
+/*
10921175 * watchdog_dev_init: init dev part of watchdog core
10931176 *
10941177 * Allocate a range of chardev nodes to use for watchdog devices
....@@ -1097,14 +1180,13 @@
10971180 int __init watchdog_dev_init(void)
10981181 {
10991182 int err;
1100
- struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1,};
11011183
11021184 watchdog_kworker = kthread_create_worker(0, "watchdogd");
11031185 if (IS_ERR(watchdog_kworker)) {
11041186 pr_err("Failed to create watchdog kworker\n");
11051187 return PTR_ERR(watchdog_kworker);
11061188 }
1107
- sched_setscheduler(watchdog_kworker->task, SCHED_FIFO, &param);
1189
+ sched_set_fifo(watchdog_kworker->task);
11081190
11091191 err = class_register(&watchdog_class);
11101192 if (err < 0) {
....@@ -1144,3 +1226,8 @@
11441226 MODULE_PARM_DESC(handle_boot_enabled,
11451227 "Watchdog core auto-updates boot enabled watchdogs before userspace takes over (default="
11461228 __MODULE_STRING(IS_ENABLED(CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED)) ")");
1229
+
1230
+module_param(open_timeout, uint, 0644);
1231
+MODULE_PARM_DESC(open_timeout,
1232
+ "Maximum time (in seconds, 0 means infinity) for userspace to take over a running watchdog (default="
1233
+ __MODULE_STRING(CONFIG_WATCHDOG_OPEN_TIMEOUT) ")");