Skip to content

Commit c3a7421

Browse files
authored
Refactor PPS GPIO IRQ handler to use threaded IRQ
1 parent afa31cb commit c3a7421

File tree

1 file changed

+27
-12
lines changed

1 file changed

+27
-12
lines changed

drivers/pps/clients/pps-gpio.c

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,33 +35,44 @@ struct pps_gpio_device_data {
3535
bool capture_clear;
3636
unsigned int echo_active_ms; /* PPS echo active duration */
3737
unsigned long echo_timeout; /* timer timeout value in jiffies */
38+
struct pps_event_time ts; /* timestamp captured in hardirq */
3839
};
3940

4041
/*
4142
* Report the PPS event
4243
*/
4344

44-
static irqreturn_t pps_gpio_irq_handler(int irq, void *data)
45+
/*
46+
* Primary hardirq handler — runs in hardirq context even on PREEMPT_RT.
47+
* Only captures the timestamp; all other work is deferred to the thread.
48+
*/
49+
static irqreturn_t pps_gpio_irq_hardirq(int irq, void *data)
4550
{
46-
const struct pps_gpio_device_data *info;
47-
struct pps_event_time ts;
48-
int rising_edge;
51+
struct pps_gpio_device_data *info = data;
52+
53+
pps_get_ts(&info->ts);
4954

50-
/* Get the time stamp first */
51-
pps_get_ts(&ts);
55+
return IRQ_WAKE_THREAD;
56+
}
5257

53-
info = data;
58+
/*
59+
* Threaded handler — processes the PPS event using the timestamp
60+
* captured in hardirq context above.
61+
*/
62+
static irqreturn_t pps_gpio_irq_thread(int irq, void *data)
63+
{
64+
struct pps_gpio_device_data *info = data;
65+
int rising_edge;
5466

55-
/* Small trick to bypass the check on edge's direction when capture_clear is unset */
5667
rising_edge = info->capture_clear ?
5768
gpiod_get_value(info->gpio_pin) : !info->assert_falling_edge;
5869
if ((rising_edge && !info->assert_falling_edge) ||
5970
(!rising_edge && info->assert_falling_edge))
60-
pps_event(info->pps, &ts, PPS_CAPTUREASSERT, data);
71+
pps_event(info->pps, &info->ts, PPS_CAPTUREASSERT, data);
6172
else if (info->capture_clear &&
6273
((rising_edge && info->assert_falling_edge) ||
6374
(!rising_edge && !info->assert_falling_edge)))
64-
pps_event(info->pps, &ts, PPS_CAPTURECLEAR, data);
75+
pps_event(info->pps, &info->ts, PPS_CAPTURECLEAR, data);
6576
else
6677
dev_warn_ratelimited(&info->pps->dev, "IRQ did not trigger any PPS event\n");
6778

@@ -213,8 +224,12 @@ static int pps_gpio_probe(struct platform_device *pdev)
213224
}
214225

215226
/* register IRQ interrupt handler */
216-
ret = request_irq(data->irq, pps_gpio_irq_handler,
217-
get_irqf_trigger_flags(data), data->info.name, data);
227+
228+
ret = request_threaded_irq(data->irq,
229+
pps_gpio_irq_hardirq, pps_gpio_irq_thread,
230+
get_irqf_trigger_flags(data) | IRQF_ONESHOT,
231+
data->info.name, data);
232+
218233
if (ret) {
219234
pps_unregister_source(data->pps);
220235
dev_err(dev, "failed to acquire IRQ %d\n", data->irq);

0 commit comments

Comments
 (0)