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