From: David Woodhouse __rwbase_read_unlock() uses raw_spin_lock_irq()/raw_spin_unlock_irq() which unconditionally disables and re-enables interrupts. When read_unlock() is called from hardirq context (e.g. after a successful read_trylock() in a timer callback), the raw_spin_unlock_irq() incorrectly re-enables interrupts within the hardirq handler. This causes lockdep warnings ('hardirqs_on_prepare' from hardirq context) and can lead to IRQ state corruption. Using read_trylock() in hardirq context on PREEMPT_RT is safe because it does not record the lock owner. The read_unlock() acquires the wait_lock which is hardirq safe. This change additionally allows rwlock_t during early boot. Switch to raw_spin_lock_irqsave()/raw_spin_unlock_irqrestore() to preserve the caller's IRQ state. Signed-off-by: David Woodhouse Reviewed-by: Sebastian Andrzej Siewior --- kernel/locking/rwbase_rt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/locking/rwbase_rt.c b/kernel/locking/rwbase_rt.c index 82e078c0665a..25744862d627 100644 --- a/kernel/locking/rwbase_rt.c +++ b/kernel/locking/rwbase_rt.c @@ -153,8 +153,9 @@ static void __sched __rwbase_read_unlock(struct rwbase_rt *rwb, struct rt_mutex_base *rtm = &rwb->rtmutex; struct task_struct *owner; DEFINE_RT_WAKE_Q(wqh); + unsigned long flags; - raw_spin_lock_irq(&rtm->wait_lock); + raw_spin_lock_irqsave(&rtm->wait_lock, flags); /* * Wake the writer, i.e. the rtmutex owner. It might release the * rtmutex concurrently in the fast path (due to a signal), but to @@ -167,7 +168,7 @@ static void __sched __rwbase_read_unlock(struct rwbase_rt *rwb, /* Pairs with the preempt_enable in rt_mutex_wake_up_q() */ preempt_disable(); - raw_spin_unlock_irq(&rtm->wait_lock); + raw_spin_unlock_irqrestore(&rtm->wait_lock, flags); rt_mutex_wake_up_q(&wqh); } -- 2.51.0