summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/0345-timers-Don-t-block-on-expiry_lock-for-TIMER_IRQSAFE-.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-rt/0345-timers-Don-t-block-on-expiry_lock-for-TIMER_IRQSAFE-.patch')
-rw-r--r--debian/patches-rt/0345-timers-Don-t-block-on-expiry_lock-for-TIMER_IRQSAFE-.patch68
1 files changed, 68 insertions, 0 deletions
diff --git a/debian/patches-rt/0345-timers-Don-t-block-on-expiry_lock-for-TIMER_IRQSAFE-.patch b/debian/patches-rt/0345-timers-Don-t-block-on-expiry_lock-for-TIMER_IRQSAFE-.patch
new file mode 100644
index 000000000..c7a563449
--- /dev/null
+++ b/debian/patches-rt/0345-timers-Don-t-block-on-expiry_lock-for-TIMER_IRQSAFE-.patch
@@ -0,0 +1,68 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Mon, 24 Oct 2022 10:17:22 +0200
+Subject: [PATCH 345/351] timers: Don't block on ->expiry_lock for
+ TIMER_IRQSAFE timers
+Origin: https://git.kernel.org/cgit/linux/kernel/git/rt/linux-stable-rt.git/commit?id=9841dc5af8b334fa1a9f4c0e9acde4a0b3839d6f
+
+Upstream commit c725dafc95f1b37027840aaeaa8b7e4e9cd20516
+
+PREEMPT_RT does not spin and wait until a running timer completes its
+callback but instead it blocks on a sleeping lock to prevent a livelock in
+the case that the task waiting for the callback completion preempted the
+callback.
+
+This cannot be done for timers flagged with TIMER_IRQSAFE. These timers can
+be canceled from an interrupt disabled context even on RT kernels.
+
+The expiry callback of such timers is invoked with interrupts disabled so
+there is no need to use the expiry lock mechanism because obviously the
+callback cannot be preempted even on RT kernels.
+
+Do not use the timer_base::expiry_lock mechanism when waiting for a running
+callback to complete if the timer is flagged with TIMER_IRQSAFE.
+
+Also add a lockdep assertion for RT kernels to validate that the expiry
+lock mechanism is always invoked in preemptible context.
+
+Reported-by: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/r/20201103190937.hga67rqhvknki3tp@linutronix.de
+[bigeasy: The logic in v4.19 is slightly different but the outcome is the
+ same as we must not sleep while waiting for the irqsafe timer to
+ complete. The IRQSAFE timer can not be preempted.
+ The "lockdep annotation" is not available and has been replaced with
+ might_sleep()]
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Daniel Wagner <wagi@monom.org>
+---
+ kernel/time/timer.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/kernel/time/timer.c b/kernel/time/timer.c
+index 3e2c0bd03004..0a6d60b3e67c 100644
+--- a/kernel/time/timer.c
++++ b/kernel/time/timer.c
+@@ -1272,6 +1272,9 @@ static int __del_timer_sync(struct timer_list *timer)
+ if (ret >= 0)
+ return ret;
+
++ if (READ_ONCE(timer->flags) & TIMER_IRQSAFE)
++ continue;
++
+ /*
+ * When accessing the lock, timers of base are no longer expired
+ * and so timer is no longer running.
+@@ -1336,6 +1339,12 @@ int del_timer_sync(struct timer_list *timer)
+ * could lead to deadlock.
+ */
+ WARN_ON(in_irq() && !(timer->flags & TIMER_IRQSAFE));
++ /*
++ * Must be able to sleep on PREEMPT_RT because of the slowpath in
++ * __del_timer_sync().
++ */
++ if (IS_ENABLED(CONFIG_PREEMPT_RT) && !(timer->flags & TIMER_IRQSAFE))
++ might_sleep();
+
+ return __del_timer_sync(timer);
+ }