82 lines
3.2 KiB
Diff
82 lines
3.2 KiB
Diff
From e0da41ef4940b26cb433c9598a4940e2476d3dbe Mon Sep 17 00:00:00 2001
|
|
From: Julia Cartwright <julia@ni.com>
|
|
Date: Fri, 28 Sep 2018 21:03:51 +0000
|
|
Subject: [PATCH 252/328] watchdog: prevent deferral of watchdogd wakeup on RT
|
|
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/older/patches-4.19.106-rt46.tar.xz
|
|
|
|
When PREEMPT_RT_FULL is enabled, all hrtimer expiry functions are
|
|
deferred for execution into the context of ktimersoftd unless otherwise
|
|
annotated.
|
|
|
|
Deferring the expiry of the hrtimer used by the watchdog core, however,
|
|
is a waste, as the callback does nothing but queue a kthread work item
|
|
and wakeup watchdogd.
|
|
|
|
It's worst then that, too: the deferral through ktimersoftd also means
|
|
that for correct behavior a user must adjust the scheduling parameters
|
|
of both watchdogd _and_ ktimersoftd, which is unnecessary and has other
|
|
side effects (like causing unrelated expiry functions to execute at
|
|
potentially elevated priority).
|
|
|
|
Instead, mark the hrtimer used by the watchdog core as being _HARD to
|
|
allow it's execution directly from hardirq context. The work done in
|
|
this expiry function is well-bounded and minimal.
|
|
|
|
A user still must adjust the scheduling parameters of the watchdogd
|
|
to be correct w.r.t. their application needs.
|
|
|
|
Cc: Guenter Roeck <linux@roeck-us.net>
|
|
Reported-and-tested-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
|
|
Reported-by: Tim Sander <tim@krieglstein.org>
|
|
Signed-off-by: Julia Cartwright <julia@ni.com>
|
|
Acked-by: Guenter Roeck <linux@roeck-us.net>
|
|
[bigeasy: use only HRTIMER_MODE_REL_HARD]
|
|
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
---
|
|
drivers/watchdog/watchdog_dev.c | 8 ++++----
|
|
1 file changed, 4 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
|
|
index e64aa88e99da..11ba2c3b187f 100644
|
|
--- a/drivers/watchdog/watchdog_dev.c
|
|
+++ b/drivers/watchdog/watchdog_dev.c
|
|
@@ -145,7 +145,7 @@ static inline void watchdog_update_worker(struct watchdog_device *wdd)
|
|
ktime_t t = watchdog_next_keepalive(wdd);
|
|
|
|
if (t > 0)
|
|
- hrtimer_start(&wd_data->timer, t, HRTIMER_MODE_REL);
|
|
+ hrtimer_start(&wd_data->timer, t, HRTIMER_MODE_REL_HARD);
|
|
} else {
|
|
hrtimer_cancel(&wd_data->timer);
|
|
}
|
|
@@ -164,7 +164,7 @@ static int __watchdog_ping(struct watchdog_device *wdd)
|
|
if (ktime_after(earliest_keepalive, now)) {
|
|
hrtimer_start(&wd_data->timer,
|
|
ktime_sub(earliest_keepalive, now),
|
|
- HRTIMER_MODE_REL);
|
|
+ HRTIMER_MODE_REL_HARD);
|
|
return 0;
|
|
}
|
|
|
|
@@ -947,7 +947,7 @@ static int watchdog_cdev_register(struct watchdog_device *wdd)
|
|
return -ENODEV;
|
|
|
|
kthread_init_work(&wd_data->work, watchdog_ping_work);
|
|
- hrtimer_init(&wd_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
|
+ hrtimer_init(&wd_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
|
|
wd_data->timer.function = watchdog_timer_expired;
|
|
|
|
if (wdd->id == 0) {
|
|
@@ -1004,7 +1004,7 @@ static int watchdog_cdev_register(struct watchdog_device *wdd)
|
|
__module_get(wdd->ops->owner);
|
|
get_device(&wd_data->dev);
|
|
if (handle_boot_enabled)
|
|
- hrtimer_start(&wd_data->timer, 0, HRTIMER_MODE_REL);
|
|
+ hrtimer_start(&wd_data->timer, 0, HRTIMER_MODE_REL_HARD);
|
|
else
|
|
pr_info("watchdog%d running and kernel based pre-userspace handler disabled\n",
|
|
wdd->id);
|
|
--
|
|
2.25.1
|
|
|