linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Input: gpio-keys - fix a sleep while atomic with PREEMPT_RT
@ 2025-05-26 13:56 Gatien Chevallier
  2025-05-26 14:13 ` Sebastian Andrzej Siewior
  0 siblings, 1 reply; 5+ messages in thread
From: Gatien Chevallier @ 2025-05-26 13:56 UTC (permalink / raw)
  To: Dmitry Torokhov, Sebastian Andrzej Siewior, Clark Williams,
	Steven Rostedt, Paul Cercueil
  Cc: linux-input, linux-kernel, linux-rt-devel, Fabrice Gasnier,
	Gatien Chevallier

From: Fabrice Gasnier <fabrice.gasnier@foss.st.com>

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.

So relax the hrtimer not to use the hard context. This requires the
spin_lock to be added back in gpio_keys_irq_timer().

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>
---
 drivers/input/keyboard/gpio_keys.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 5c39a217b94c8ad03a8542380eed741fccdca5da..99fc7d3c29ea5809604915782525fecacb151612 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -448,12 +448,15 @@ static enum hrtimer_restart gpio_keys_irq_timer(struct hrtimer *t)
 						      struct gpio_button_data,
 						      release_timer);
 	struct input_dev *input = bdata->input;
+	unsigned long flags;
 
+	spin_lock_irqsave(&bdata->lock, flags);
 	if (bdata->key_pressed) {
 		input_report_key(input, *bdata->code, 0);
 		input_sync(input);
 		bdata->key_pressed = false;
 	}
+	spin_unlock_irqrestore(&bdata->lock, flags);
 
 	return HRTIMER_NORESTART;
 }
@@ -486,7 +489,7 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
 	if (bdata->release_delay)
 		hrtimer_start(&bdata->release_timer,
 			      ms_to_ktime(bdata->release_delay),
-			      HRTIMER_MODE_REL_HARD);
+			      HRTIMER_MODE_REL);
 out:
 	return IRQ_HANDLED;
 }
@@ -628,7 +631,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
 
 		bdata->release_delay = button->debounce_interval;
 		hrtimer_setup(&bdata->release_timer, gpio_keys_irq_timer,
-			      CLOCK_REALTIME, HRTIMER_MODE_REL_HARD);
+			      CLOCK_REALTIME, HRTIMER_MODE_REL);
 
 		isr = gpio_keys_irq_isr;
 		irqflags = 0;

---
base-commit: 0ff41df1cb268fc69e703a08a57ee14ae967d0ca
change-id: 20250526-gpio_keys_preempt_rt-10619c8fa916

Best regards,
-- 
Gatien Chevallier <gatien.chevallier@foss.st.com>


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] Input: gpio-keys - fix a sleep while atomic with PREEMPT_RT
  2025-05-26 13:56 [PATCH] Input: gpio-keys - fix a sleep while atomic with PREEMPT_RT Gatien Chevallier
@ 2025-05-26 14:13 ` Sebastian Andrzej Siewior
  2025-05-27 13:36   ` Gatien CHEVALLIER
  0 siblings, 1 reply; 5+ messages in thread
From: Sebastian Andrzej Siewior @ 2025-05-26 14:13 UTC (permalink / raw)
  To: Gatien Chevallier
  Cc: Dmitry Torokhov, Clark Williams, Steven Rostedt, Paul Cercueil,
	linux-input, linux-kernel, linux-rt-devel, Fabrice Gasnier

On 2025-05-26 15:56:29 [+0200], Gatien Chevallier wrote:
> From: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
> 
> 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.
> 
> So relax the hrtimer not to use the hard context. This requires the
> spin_lock to be added back in gpio_keys_irq_timer().

Why does it? This needs to be explained or it deserves an independent
patch/ fix. This flag change makes not difference on !PREEMPT_RT and so
should be the requirements for locking here.

> 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>

Sebastian

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Input: gpio-keys - fix a sleep while atomic with PREEMPT_RT
  2025-05-26 14:13 ` Sebastian Andrzej Siewior
@ 2025-05-27 13:36   ` Gatien CHEVALLIER
  2025-05-27 14:41     ` Sebastian Andrzej Siewior
  0 siblings, 1 reply; 5+ messages in thread
From: Gatien CHEVALLIER @ 2025-05-27 13:36 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: Dmitry Torokhov, Clark Williams, Steven Rostedt, Paul Cercueil,
	linux-input, linux-kernel, linux-rt-devel, Fabrice Gasnier

Hello Sebastian,

On 5/26/25 16:13, Sebastian Andrzej Siewior wrote:
> On 2025-05-26 15:56:29 [+0200], Gatien Chevallier wrote:
>> From: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
>>
>> 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.
>>
>> So relax the hrtimer not to use the hard context. This requires the
>> spin_lock to be added back in gpio_keys_irq_timer().
> 
> Why does it? This needs to be explained or it deserves an independent
> patch/ fix. This flag change makes not difference on !PREEMPT_RT and so
> should be the requirements for locking here.
> 

Can you elaborate on "This flag change makes not difference on
!PREEMPT_RT" please? IIUC,this makes the callback not run in hard IRQ
context, even in !PREEMPT_RT, no?

Regarding the need of the spin_lock: gpio_keys_irq_timer() and
gpio_keys_irq_isr() appear to access the same resources. Can't we
have a concurrent access on it from:
HR timer interrupt // GPIO interrupt?

But looking back at the patch, this situation does not depend on
the HRTIMER_MODE_REL_HARD flag. So maybe it should be addressed
separately.

On the other hand, I should use the new
guard(spinlock_irqsave)(&bdata->lock);

>> 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>
> 
> Sebastian

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Input: gpio-keys - fix a sleep while atomic with PREEMPT_RT
  2025-05-27 13:36   ` Gatien CHEVALLIER
@ 2025-05-27 14:41     ` Sebastian Andrzej Siewior
  2025-05-28  7:55       ` Gatien CHEVALLIER
  0 siblings, 1 reply; 5+ messages in thread
From: Sebastian Andrzej Siewior @ 2025-05-27 14:41 UTC (permalink / raw)
  To: Gatien CHEVALLIER
  Cc: Dmitry Torokhov, Clark Williams, Steven Rostedt, Paul Cercueil,
	linux-input, linux-kernel, linux-rt-devel, Fabrice Gasnier

On 2025-05-27 15:36:37 [+0200], Gatien CHEVALLIER wrote:
> Hello Sebastian,
Hello Gatien,

> Can you elaborate on "This flag change makes not difference on
> !PREEMPT_RT" please? IIUC,this makes the callback not run in hard IRQ
> context, even in !PREEMPT_RT, no?

If you set
- HRTIMER_MODE_REL_HARD
  then the callback runs in
  - hardirq context on !PREEMPT_RT
  - hardirq context on PREEMPT_RT.

- HRTIMER_MODE_REL
  then the callback runs in
  - hardirq context on !PREEMPT_RT
  - preemptible softirq on PREEMPT_RT.

- HRTIMER_MODE_REL_SOFT
  then the callback runs in
  - softirq context on !PREEMPT_RT
  - preemptible softirq on PREEMPT_RT.

Therefore if you switch HRTIMER_MODE_REL_HARD -> HRTIMER_MODE_REL then
it is a nop on !PREEMPT_RT.

> Regarding the need of the spin_lock: gpio_keys_irq_timer() and
> gpio_keys_irq_isr() appear to access the same resources. Can't we
> have a concurrent access on it from:
> HR timer interrupt // GPIO interrupt?

Yes, it could.

> But looking back at the patch, this situation does not depend on
> the HRTIMER_MODE_REL_HARD flag. So maybe it should be addressed
> separately.

Yes, please.

> On the other hand, I should use the new
> guard(spinlock_irqsave)(&bdata->lock);

Yes, please. The other instance already does so.

Sebastian

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Input: gpio-keys - fix a sleep while atomic with PREEMPT_RT
  2025-05-27 14:41     ` Sebastian Andrzej Siewior
@ 2025-05-28  7:55       ` Gatien CHEVALLIER
  0 siblings, 0 replies; 5+ messages in thread
From: Gatien CHEVALLIER @ 2025-05-28  7:55 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: Dmitry Torokhov, Clark Williams, Steven Rostedt, Paul Cercueil,
	linux-input, linux-kernel, linux-rt-devel, Fabrice Gasnier

Hello Sebastian,

On 5/27/25 16:41, Sebastian Andrzej Siewior wrote:
> On 2025-05-27 15:36:37 [+0200], Gatien CHEVALLIER wrote:
>> Hello Sebastian,
> Hello Gatien,
> 
>> Can you elaborate on "This flag change makes not difference on
>> !PREEMPT_RT" please? IIUC,this makes the callback not run in hard IRQ
>> context, even in !PREEMPT_RT, no?
> 
> If you set
> - HRTIMER_MODE_REL_HARD
>    then the callback runs in
>    - hardirq context on !PREEMPT_RT
>    - hardirq context on PREEMPT_RT.
> 
> - HRTIMER_MODE_REL
>    then the callback runs in
>    - hardirq context on !PREEMPT_RT
>    - preemptible softirq on PREEMPT_RT.
> 
> - HRTIMER_MODE_REL_SOFT
>    then the callback runs in
>    - softirq context on !PREEMPT_RT
>    - preemptible softirq on PREEMPT_RT.
> 
> Therefore if you switch HRTIMER_MODE_REL_HARD -> HRTIMER_MODE_REL then
> it is a nop on !PREEMPT_RT.
> 

Thank you for the details.

>> Regarding the need of the spin_lock: gpio_keys_irq_timer() and
>> gpio_keys_irq_isr() appear to access the same resources. Can't we
>> have a concurrent access on it from:
>> HR timer interrupt // GPIO interrupt?
> 
> Yes, it could.
> 
>> But looking back at the patch, this situation does not depend on
>> the HRTIMER_MODE_REL_HARD flag. So maybe it should be addressed
>> separately.
> 
> Yes, please.
> 

Ok, I will do that in V2

>> On the other hand, I should use the new
>> guard(spinlock_irqsave)(&bdata->lock);
> 
> Yes, please. The other instance already does so.
> 
> Sebastian

Ok

Best regards,
Gatien

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2025-05-28  7:58 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-26 13:56 [PATCH] Input: gpio-keys - fix a sleep while atomic with PREEMPT_RT Gatien Chevallier
2025-05-26 14:13 ` Sebastian Andrzej Siewior
2025-05-27 13:36   ` Gatien CHEVALLIER
2025-05-27 14:41     ` Sebastian Andrzej Siewior
2025-05-28  7:55       ` Gatien CHEVALLIER

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).