summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2021-08-12 22:32:30 +0200
committerThomas Gleixner <tglx@linutronix.de>2021-08-12 22:34:40 +0200
commitf80e21489590c00f46226d5802d900e6f66e5633 (patch)
treebe70538430e3c05e1ce5e1ecd950b4b7c690729a
parent9482fd71dbb8f0d1a61821a83e467dc0a9d7b429 (diff)
downloadlinux-f80e21489590c00f46226d5802d900e6f66e5633.tar.bz2
hrtimer: Unbreak hrtimer_force_reprogram()
Since the recent consoliation of reprogramming functions, hrtimer_force_reprogram() is affected by a check whether the new expiry time is past the current expiry time. This breaks the NOHZ logic as that relies on the fact that the tick hrtimer is moved into the future. That means cpu_base->expires_next becomes stale and subsequent reprogramming attempts fail as well until the situation is cleaned up by an hrtimer interrupts. For some yet unknown reason this leads to a complete stall, so for now partially revert the offending commit to a known working state. The root cause for the stall is still investigated and will be fixed in a subsequent commit. Fixes: b14bca97c9f5 ("hrtimer: Consolidate reprogramming code") Reported-by: Mike Galbraith <efault@gmx.de> Reported-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Mike Galbraith <efault@gmx.de> Link: https://lore.kernel.org/r/8735recskh.ffs@tglx
-rw-r--r--kernel/time/hrtimer.c40
1 files changed, 20 insertions, 20 deletions
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 33b00e213e07..0ea8702eb516 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -652,24 +652,10 @@ static inline int hrtimer_hres_active(void)
return __hrtimer_hres_active(this_cpu_ptr(&hrtimer_bases));
}
-static void
-__hrtimer_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal,
- struct hrtimer *next_timer, ktime_t expires_next)
+static void __hrtimer_reprogram(struct hrtimer_cpu_base *cpu_base,
+ struct hrtimer *next_timer,
+ ktime_t expires_next)
{
- /*
- * If the hrtimer interrupt is running, then it will reevaluate the
- * clock bases and reprogram the clock event device.
- */
- if (cpu_base->in_hrtirq)
- return;
-
- if (expires_next > cpu_base->expires_next)
- return;
-
- if (skip_equal && expires_next == cpu_base->expires_next)
- return;
-
- cpu_base->next_timer = next_timer;
cpu_base->expires_next = expires_next;
/*
@@ -707,8 +693,10 @@ hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal)
expires_next = hrtimer_update_next_event(cpu_base);
- __hrtimer_reprogram(cpu_base, skip_equal, cpu_base->next_timer,
- expires_next);
+ if (skip_equal && expires_next == cpu_base->expires_next)
+ return;
+
+ __hrtimer_reprogram(cpu_base, cpu_base->next_timer, expires_next);
}
/* High resolution timer related functions */
@@ -863,7 +851,19 @@ static void hrtimer_reprogram(struct hrtimer *timer, bool reprogram)
if (base->cpu_base != cpu_base)
return;
- __hrtimer_reprogram(cpu_base, true, timer, expires);
+ if (expires >= cpu_base->expires_next)
+ return;
+
+ /*
+ * If the hrtimer interrupt is running, then it will reevaluate the
+ * clock bases and reprogram the clock event device.
+ */
+ if (cpu_base->in_hrtirq)
+ return;
+
+ cpu_base->next_timer = timer;
+
+ __hrtimer_reprogram(cpu_base, timer, expires);
}
static bool update_needs_ipi(struct hrtimer_cpu_base *cpu_base,