Skip to content

Commit 019002f

Browse files
pcercueidtor
authored andcommitted
Input: gpio-keys - use hrtimer for release timer
Dealing with input, timing is important; if the button should be released in one millisecond, then it should be done in one millisecond and not a hundred milliseconds. Therefore, the standard timer API is not really suitable for this task. Convert the gpio-keys driver to use a hrtimer instead of the standard timer to address this issue. Note that by using a hard IRQ for the hrtimer callback, we can get rid of the spin_lock_irqsave() and spin_unlock_irqrestore(). Signed-off-by: Paul Cercueil <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 36a8fc6 commit 019002f

File tree

1 file changed

+16
-11
lines changed

1 file changed

+16
-11
lines changed

drivers/input/keyboard/gpio_keys.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <linux/module.h>
1010

11+
#include <linux/hrtimer.h>
1112
#include <linux/init.h>
1213
#include <linux/fs.h>
1314
#include <linux/interrupt.h>
@@ -36,7 +37,7 @@ struct gpio_button_data {
3637

3738
unsigned short *code;
3839

39-
struct timer_list release_timer;
40+
struct hrtimer release_timer;
4041
unsigned int release_delay; /* in msecs, for IRQ-only buttons */
4142

4243
struct delayed_work work;
@@ -146,7 +147,7 @@ static void gpio_keys_disable_button(struct gpio_button_data *bdata)
146147
if (bdata->gpiod)
147148
cancel_delayed_work_sync(&bdata->work);
148149
else
149-
del_timer_sync(&bdata->release_timer);
150+
hrtimer_cancel(&bdata->release_timer);
150151

151152
bdata->disabled = true;
152153
}
@@ -415,19 +416,20 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id)
415416
return IRQ_HANDLED;
416417
}
417418

418-
static void gpio_keys_irq_timer(struct timer_list *t)
419+
static enum hrtimer_restart gpio_keys_irq_timer(struct hrtimer *t)
419420
{
420-
struct gpio_button_data *bdata = from_timer(bdata, t, release_timer);
421+
struct gpio_button_data *bdata = container_of(t,
422+
struct gpio_button_data,
423+
release_timer);
421424
struct input_dev *input = bdata->input;
422-
unsigned long flags;
423425

424-
spin_lock_irqsave(&bdata->lock, flags);
425426
if (bdata->key_pressed) {
426427
input_event(input, EV_KEY, *bdata->code, 0);
427428
input_sync(input);
428429
bdata->key_pressed = false;
429430
}
430-
spin_unlock_irqrestore(&bdata->lock, flags);
431+
432+
return HRTIMER_NORESTART;
431433
}
432434

433435
static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
@@ -457,8 +459,9 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
457459
}
458460

459461
if (bdata->release_delay)
460-
mod_timer(&bdata->release_timer,
461-
jiffies + msecs_to_jiffies(bdata->release_delay));
462+
hrtimer_start(&bdata->release_timer,
463+
ms_to_ktime(bdata->release_delay),
464+
HRTIMER_MODE_REL_HARD);
462465
out:
463466
spin_unlock_irqrestore(&bdata->lock, flags);
464467
return IRQ_HANDLED;
@@ -471,7 +474,7 @@ static void gpio_keys_quiesce_key(void *data)
471474
if (bdata->gpiod)
472475
cancel_delayed_work_sync(&bdata->work);
473476
else
474-
del_timer_sync(&bdata->release_timer);
477+
hrtimer_cancel(&bdata->release_timer);
475478
}
476479

477480
static int gpio_keys_setup_key(struct platform_device *pdev,
@@ -595,7 +598,9 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
595598
}
596599

597600
bdata->release_delay = button->debounce_interval;
598-
timer_setup(&bdata->release_timer, gpio_keys_irq_timer, 0);
601+
hrtimer_init(&bdata->release_timer,
602+
CLOCK_REALTIME, HRTIMER_MODE_REL_HARD);
603+
bdata->release_timer.function = gpio_keys_irq_timer;
599604

600605
isr = gpio_keys_irq_isr;
601606
irqflags = 0;

0 commit comments

Comments
 (0)