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

gpiolib: cdev: allow edge event timestamps to be configured as REALTIME

Using CLOCK_REALTIME as the source for event timestamps is crucial for
some specific applications, particularly those requiring timetamps
relative to a PTP clock, so provide an option to switch the event
timestamp source from the default CLOCK_MONOTONIC to CLOCK_REALTIME.

Note that CLOCK_REALTIME was the default source clock for GPIO until
Linux 5.7 when it was changed to CLOCK_MONOTONIC due to issues with the
shifting of the realtime clock.
Providing this option maintains the CLOCK_MONOTONIC as the default,
while also providing a path forward for those dependent on the pre-5.7
behaviour.

Suggested-by: Jack Winch <sunt.un.morcov@gmail.com>
Signed-off-by: Kent Gibson <warthog618@gmail.com>
Link: https://lore.kernel.org/r/20201014231158.34117-2-warthog618@gmail.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Kent Gibson and committed by
Linus Walleij
26d060e4 93224edf

+28 -6
+18 -3
drivers/gpio/gpiolib-cdev.c
··· 509 509 GPIO_V2_LINE_DIRECTION_FLAGS | \ 510 510 GPIO_V2_LINE_DRIVE_FLAGS | \ 511 511 GPIO_V2_LINE_EDGE_FLAGS | \ 512 + GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME | \ 512 513 GPIO_V2_LINE_BIAS_FLAGS) 513 514 514 515 static void linereq_put_event(struct linereq *lr, ··· 530 529 pr_debug_ratelimited("event FIFO is full - event dropped\n"); 531 530 } 532 531 532 + static u64 line_event_timestamp(struct line *line) 533 + { 534 + if (test_bit(FLAG_EVENT_CLOCK_REALTIME, &line->desc->flags)) 535 + return ktime_get_real_ns(); 536 + 537 + return ktime_get_ns(); 538 + } 539 + 533 540 static irqreturn_t edge_irq_thread(int irq, void *p) 534 541 { 535 542 struct line *line = p; ··· 555 546 * which case we didn't get the timestamp from 556 547 * edge_irq_handler(). 557 548 */ 558 - le.timestamp_ns = ktime_get_ns(); 549 + le.timestamp_ns = line_event_timestamp(line); 559 550 if (lr->num_lines != 1) 560 551 line->req_seqno = atomic_inc_return(&lr->seqno); 561 552 } ··· 599 590 * Just store the timestamp in hardirq context so we get it as 600 591 * close in time as possible to the actual event. 601 592 */ 602 - line->timestamp_ns = ktime_get_ns(); 593 + line->timestamp_ns = line_event_timestamp(line); 603 594 604 595 if (lr->num_lines != 1) 605 596 line->req_seqno = atomic_inc_return(&lr->seqno); ··· 672 663 memset(&le, 0, sizeof(le)); 673 664 674 665 lr = line->req; 675 - le.timestamp_ns = ktime_get_ns(); 666 + le.timestamp_ns = line_event_timestamp(line); 676 667 le.offset = gpio_chip_hwgpio(line->desc); 677 668 line->line_seqno++; 678 669 le.line_seqno = line->line_seqno; ··· 976 967 flags & GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN); 977 968 assign_bit(FLAG_BIAS_DISABLE, flagsp, 978 969 flags & GPIO_V2_LINE_FLAG_BIAS_DISABLED); 970 + 971 + assign_bit(FLAG_EVENT_CLOCK_REALTIME, flagsp, 972 + flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME); 979 973 } 980 974 981 975 static long linereq_get_values(struct linereq *lr, void __user *ip) ··· 1941 1929 info->flags |= GPIO_V2_LINE_FLAG_EDGE_RISING; 1942 1930 if (test_bit(FLAG_EDGE_FALLING, &desc->flags)) 1943 1931 info->flags |= GPIO_V2_LINE_FLAG_EDGE_FALLING; 1932 + 1933 + if (test_bit(FLAG_EVENT_CLOCK_REALTIME, &desc->flags)) 1934 + info->flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME; 1944 1935 1945 1936 debounce_period_us = READ_ONCE(desc->debounce_period_us); 1946 1937 if (debounce_period_us) {
+1
drivers/gpio/gpiolib.h
··· 116 116 #define FLAG_BIAS_DISABLE 15 /* GPIO has pull disabled */ 117 117 #define FLAG_EDGE_RISING 16 /* GPIO CDEV detects rising edge events */ 118 118 #define FLAG_EDGE_FALLING 17 /* GPIO CDEV detects falling edge events */ 119 + #define FLAG_EVENT_CLOCK_REALTIME 18 /* GPIO CDEV reports REALTIME timestamps in events */ 119 120 120 121 /* Connection label */ 121 122 const char *label;
+9 -3
include/uapi/linux/gpio.h
··· 65 65 * @GPIO_V2_LINE_FLAG_BIAS_PULL_UP: line has pull-up bias enabled 66 66 * @GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN: line has pull-down bias enabled 67 67 * @GPIO_V2_LINE_FLAG_BIAS_DISABLED: line has bias disabled 68 + * @GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME: line events contain REALTIME timestamps 68 69 */ 69 70 enum gpio_v2_line_flag { 70 71 GPIO_V2_LINE_FLAG_USED = _BITULL(0), ··· 79 78 GPIO_V2_LINE_FLAG_BIAS_PULL_UP = _BITULL(8), 80 79 GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN = _BITULL(9), 81 80 GPIO_V2_LINE_FLAG_BIAS_DISABLED = _BITULL(10), 81 + GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME = _BITULL(11), 82 82 }; 83 83 84 84 /** ··· 272 270 /** 273 271 * struct gpio_v2_line_event - The actual event being pushed to userspace 274 272 * @timestamp_ns: best estimate of time of event occurrence, in nanoseconds. 275 - * The @timestamp_ns is read from %CLOCK_MONOTONIC and is intended to allow 276 - * the accurate measurement of the time between events. It does not provide 277 - * the wall-clock time. 278 273 * @id: event identifier with value from &enum gpio_v2_line_event_id 279 274 * @offset: the offset of the line that triggered the event 280 275 * @seqno: the sequence number for this event in the sequence of events for ··· 279 280 * @line_seqno: the sequence number for this event in the sequence of 280 281 * events on this particular line 281 282 * @padding: reserved for future use 283 + * 284 + * By default the @timestamp_ns is read from %CLOCK_MONOTONIC and is 285 + * intended to allow the accurate measurement of the time between events. 286 + * It does not provide the wall-clock time. 287 + * 288 + * If the %GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME flag is set then the 289 + * @timestamp_ns is read from %CLOCK_REALTIME. 282 290 */ 283 291 struct gpio_v2_line_event { 284 292 __aligned_u64 timestamp_ns;