diff options
Diffstat (limited to '')
-rw-r--r-- | debian/patches-rt/0350-timers-Don-t-block-on-expiry_lock-for-TIMER_IRQSAFE-.patch | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/debian/patches-rt/0350-timers-Don-t-block-on-expiry_lock-for-TIMER_IRQSAFE-.patch b/debian/patches-rt/0350-timers-Don-t-block-on-expiry_lock-for-TIMER_IRQSAFE-.patch new file mode 100644 index 000000000..7bf384e14 --- /dev/null +++ b/debian/patches-rt/0350-timers-Don-t-block-on-expiry_lock-for-TIMER_IRQSAFE-.patch @@ -0,0 +1,68 @@ +From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +Date: Mon, 31 Oct 2022 16:50:06 +0100 +Subject: [PATCH 350/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=deb2c700cef1bff119c5b7fe75b105e1918ad70f + +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. + +[ bigeasy: Dropping that lockdep_assert_preemption_enabled() check in + backport ] + +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 +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +Signed-off-by: Daniel Wagner <wagi@monom.org> +--- + kernel/time/timer.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/kernel/time/timer.c b/kernel/time/timer.c +index 603985720f54..8c7bfcee9609 100644 +--- a/kernel/time/timer.c ++++ b/kernel/time/timer.c +@@ -1304,7 +1304,7 @@ static void del_timer_wait_running(struct timer_list *timer) + u32 tf; + + tf = READ_ONCE(timer->flags); +- if (!(tf & TIMER_MIGRATING)) { ++ if (!(tf & (TIMER_MIGRATING | TIMER_IRQSAFE))) { + struct timer_base *base = get_timer_base(tf); + + /* +@@ -1388,6 +1388,15 @@ int del_timer_sync(struct timer_list *timer) + */ + WARN_ON(in_irq() && !(timer->flags & TIMER_IRQSAFE)); + ++ /* ++ * Must be able to sleep on PREEMPT_RT because of the slowpath in ++ * del_timer_wait_running(). ++ */ ++#if 0 ++ if (IS_ENABLED(CONFIG_PREEMPT_RT) && !(timer->flags & TIMER_IRQSAFE)) ++ lockdep_assert_preemption_enabled(); ++#endif ++ + do { + ret = try_to_del_timer_sync(timer); + |