Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: gpio-keys - fix a sleep while atomic with PREEMPT_RT

When enabling PREEMPT_RT, the gpio_keys_irq_timer() callback runs in
hard irq context, but the input_event() takes a spin_lock, which isn't
allowed there as it is converted to a rt_spin_lock().

[ 4054.289999] BUG: sleeping function called from invalid context at kernel/locking/spinlock_rt.c:48
[ 4054.290028] in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 0, name: swapper/0
...
[ 4054.290195] __might_resched+0x13c/0x1f4
[ 4054.290209] rt_spin_lock+0x54/0x11c
[ 4054.290219] input_event+0x48/0x80
[ 4054.290230] gpio_keys_irq_timer+0x4c/0x78
[ 4054.290243] __hrtimer_run_queues+0x1a4/0x438
[ 4054.290257] hrtimer_interrupt+0xe4/0x240
[ 4054.290269] arch_timer_handler_phys+0x2c/0x44
[ 4054.290283] handle_percpu_devid_irq+0x8c/0x14c
[ 4054.290297] handle_irq_desc+0x40/0x58
[ 4054.290307] generic_handle_domain_irq+0x1c/0x28
[ 4054.290316] gic_handle_irq+0x44/0xcc

Considering the gpio_keys_irq_isr() can run in any context, e.g. it can
be threaded, it seems there's no point in requesting the timer isr to
run in hard irq context.

Relax the hrtimer not to use the hard context.

Fixes: 019002f20cb5 ("Input: gpio-keys - use hrtimer for release timer")
Suggested-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
Signed-off-by: Gatien Chevallier <gatien.chevallier@foss.st.com>
Link: https://lore.kernel.org/r/20250528-gpio_keys_preempt_rt-v2-1-3fc55a9c3619@foss.st.com
Cc: stable@vger.kernel.org
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Fabrice Gasnier and committed by
Dmitry Torokhov
f4a8f561 e8fe33fd

+2 -2
+2 -2
drivers/input/keyboard/gpio_keys.c
··· 486 486 if (bdata->release_delay) 487 487 hrtimer_start(&bdata->release_timer, 488 488 ms_to_ktime(bdata->release_delay), 489 - HRTIMER_MODE_REL_HARD); 489 + HRTIMER_MODE_REL); 490 490 out: 491 491 return IRQ_HANDLED; 492 492 } ··· 628 628 629 629 bdata->release_delay = button->debounce_interval; 630 630 hrtimer_setup(&bdata->release_timer, gpio_keys_irq_timer, 631 - CLOCK_REALTIME, HRTIMER_MODE_REL_HARD); 631 + CLOCK_REALTIME, HRTIMER_MODE_REL); 632 632 633 633 isr = gpio_keys_irq_isr; 634 634 irqflags = 0;