gpiolib: cdev: allow edge event timestamps to be configured as REALTIME
Kent Gibson
reviewercover gpiolib: cdev: allow edge event timestamps to be configured as REALTIME
This patch set adds the option to select CLOCK_REALTIME as the source clock for line events.
The first patch is the core of the change, while the remaining two update the GPIO tools to make use of the new option.
Kent Gibson (3):
gpiolib: cdev: allow edge event timestamps to be configured as
REALTIME
tools: gpio: add support for reporting realtime event clock to lsgpio
tools: gpio: add option to report wall-clock time to gpio-event-mon
drivers/gpio/gpiolib-cdev.c | 21 ++++++++++++++++++--- drivers/gpio/gpiolib.h | 1 + include/uapi/linux/gpio.h | 12 +++++++++--- tools/gpio/gpio-event-mon.c | 6 +++++- tools/gpio/lsgpio.c | 4 ++++ 5 files changed, 37 insertions(+), 7 deletions(-)
Signature · 1 line
2.28.0
Quoted 20 lines · Kent Gibson
This patch set adds the option to select
CLOCK_REALTIMEas the source clock for line events.The first patch is the core of the change, while the remaining two update the GPIO tools to make use of the new option.
Kent Gibson (3):
gpiolib: cdev: allow edge event timestamps to be configured as
REALTIME
tools: gpio: add support for reporting realtime event clock to lsgpio
tools: gpio: add option to report wall-clock time to gpio-event-mondrivers/gpio/gpiolib-cdev.c | 21 ++++++++++++++++++--- drivers/gpio/gpiolib.h | 1 + include/uapi/linux/gpio.h | 12 +++++++++--- tools/gpio/gpio-event-mon.c | 6 +++++- tools/gpio/lsgpio.c | 4 ++++ 5 files changed, 37 insertions(+), 7 deletions(-)
Quoted 3 lines
--
2.28.0
The entire series looks good to me.
Linus: do you think this can still make it into v5.10 as an improvement to the new uAPI or do we have to wait until the next merge window? Will you send another PR in this cycle?
Bartosz
Kent Gibson
reviewerPATCH 1/3 gpiolib: cdev: allow edge event timestamps to be configured as REALTIME
In reply to Kent GibsonUsing 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.
--- drivers/gpio/gpiolib-cdev.c | 21 ++++++++++++++++++--- drivers/gpio/gpiolib.h | 1 + include/uapi/linux/gpio.h | 12 +++++++++--- 3 files changed, 28 insertions(+), 6 deletions(-)
drivers/gpio/gpiolib-cdev.c +18 -3
@@ -515,6 +515,7 @@ struct linereq { GPIO_V2_LINE_DIRECTION_FLAGS | \ GPIO_V2_LINE_DRIVE_FLAGS | \ GPIO_V2_LINE_EDGE_FLAGS | \ + GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME | \ GPIO_V2_LINE_BIAS_FLAGS) static void linereq_put_event(struct linereq *lr,
@@ -535,6 +536,14 @@ static void linereq_put_event(struct linereq *lr,pr_debug_ratelimited ("event FIFO is full - event dropped\n" ); } +static unsigned long line_event_timestamp (struct line *line) +{ +if (test_bit (FLAG_EVENT_CLOCK_REALTIME , &line->desc->flags)) +return ktime_get_real_ns (); + +return ktime_get_ns (); + +}static irqreturn_t edge_irq_thread (int irq,void *p) {struct line *line = p;
@@ -553,7 +562,7 @@ static irqreturn_t edge_irq_thread(int irq, void *p)* which case we didn't get the timestamp from * edge_irq_handler(). */ - le.timestamp_ns =ktime_get_ns (); + le.timestamp_ns =line_event_timestamp (line);if (lr->num_lines !=1 ) line->req_seqno =atomic_inc_return (&lr->seqno); }
@@ -598,7 +607,7 @@ static irqreturn_t edge_irq_handler(int irq, void *p)* Just store the timestamp in hardirq context so we get it as * close in time as possible to the actual event. */ - line->timestamp_ns =ktime_get_ns (); + line->timestamp_ns =line_event_timestamp (line);if (lr->num_lines !=1 ) line->req_seqno =atomic_inc_return (&lr->seqno);
@@ -673,7 +682,7 @@ static void debounce_work_func(struct work_struct *work)memset (&le,0 ,sizeof (le)); lr = line->req; - le.timestamp_ns =ktime_get_ns (); + le.timestamp_ns =line_event_timestamp (line); le.offset =gpio_chip_hwgpio (line->desc); line->line_seqno++; le.line_seqno = line->line_seqno;
@@ -977,6 +986,9 @@ static void gpio_v2_line_config_flags_to_desc_flags(u64 flags, flags & GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN);assign_bit (FLAG_BIAS_DISABLE , flagsp, flags &GPIO_V2_LINE_FLAG_BIAS_DISABLED ); + +assign_bit (FLAG_EVENT_CLOCK_REALTIME , flagsp, + flags &GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME ); }static long linereq_get_values (struct linereq *lr,void __user *ip)
@@ -1940,6 +1952,9 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc,if (test_bit (FLAG_EDGE_FALLING , &desc->flags)) info->flags |=GPIO_V2_LINE_FLAG_EDGE_FALLING ; +if (test_bit (FLAG_EVENT_CLOCK_REALTIME , &desc->flags)) + info->flags |=GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME ; + debounce_period_us =READ_ONCE (desc->debounce_period_us);if (debounce_period_us) { info->attrs[num_attrs].id =GPIO_V2_LINE_ATTR_ID_DEBOUNCE ;
drivers/gpio/gpiolib.h +1 -0
@@ -116,6 +116,7 @@ struct gpio_desc {#define FLAG_BIAS_DISABLE 15/* GPIO has pull disabled */ #define FLAG_EDGE_RISING 16/* GPIO CDEV detects rising edge events */ #define FLAG_EDGE_FALLING 17/* GPIO CDEV detects falling edge events */ +#define FLAG_EVENT_CLOCK_REALTIME 18/* GPIO CDEV reports REALTIME timestamps in events */ /* Connection label */ const char *label;
include/uapi/linux/gpio.h +9 -3
@@ -65,6 +65,7 @@ struct gpiochip_info {* @GPIO_V2_LINE_FLAG_BIAS_PULL_UP: line has pull-up bias enabled * @GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN: line has pull-down bias enabled * @GPIO_V2_LINE_FLAG_BIAS_DISABLED: line has bias disabled +* @GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME: line events contain REALTIME timestamps */ enum gpio_v2_line_flag {GPIO_V2_LINE_FLAG_USED =_BITULL (0 ),
@@ -78,6 +79,7 @@ enum gpio_v2_line_flag {GPIO_V2_LINE_FLAG_BIAS_PULL_UP =_BITULL (8 ),GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN =_BITULL (9 ),GPIO_V2_LINE_FLAG_BIAS_DISABLED =_BITULL (10 ), + GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME = _BITULL(11), };/**
@@ -270,9 +272,6 @@ enum gpio_v2_line_event_id {/** * struct gpio_v2_line_event - The actual event being pushed to userspace * @timestamp_ns: best estimate of time of event occurrence, in nanoseconds. -* The @timestamp_ns is read from %CLOCK_MONOTONIC and is intended to allow -* the accurate measurement of the time between events. It does not provide -* the wall-clock time. * @id: event identifier with value from &enum gpio_v2_line_event_id * @offset: the offset of the line that triggered the event * @seqno: the sequence number for this event in the sequence of events for
@@ -280,6 +279,13 @@ enum gpio_v2_line_event_id {* @line_seqno: the sequence number for this event in the sequence of * events on this particular line * @padding: reserved for future use +* +* By default the @timestamp_ns is read from %CLOCK_MONOTONIC and is +* intended to allow the accurate measurement of the time between events. +* It does not provide the wall-clock time. +* +* If the %GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME flag is set then the +* @timestamp_ns is read from %CLOCK_REALTIME. */ struct gpio_v2_line_event {__aligned_u64 timestamp_ns;
Signature · 1 line
2.28.0
Kent Gibson
reviewerQuoted 5 lines · Kent Gibson
Using
CLOCK_REALTIMEas 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 defaultCLOCK_MONOTONICtoCLOCK_REALTIME.
[snip]
Quoted 4 lines
static void linereq_put_event(struct linereq *lr,
drivers/gpio/gpiolib-cdev.c +0
-0@@ -535,6 +536,14 @@ static void linereq_put_event(struct linereq *lr,pr_debug_ratelimited ("event FIFO is full - event dropped\n" );
drivers/gpio/gpiolib-cdev.c static void linereq_put_event(struct linereq *lr, · line 546
Quoted 10 lines
drivers/gpio/gpiolib-cdev.c +8
-0} +static unsigned long line_event_timestamp (struct line *line) +{ +if (test_bit (FLAG_EVENT_CLOCK_REALTIME , &line->desc->flags)) +return ktime_get_real_ns (); + +return ktime_get_ns (); + +}
One minor hitch - that should be returning u64, not unsigned long, or the time gets reduced to 32bit on 32bit platforms.
It's getting late though, so I'll send out an update tomorrow.
Cheers,
Kent.
Kent Gibson
reviewerPATCH 2/3 tools: gpio: add support for reporting realtime event clock to lsgpio
In reply to Kent GibsonAdd support for reporting if a line is configured to report realtime timestamps in events.
--- tools/gpio/lsgpio.c | 4 ++++ 1 file changed, 4 insertions(+)
tools/gpio/lsgpio.c +4 -0
@@ -65,6 +65,10 @@ struct gpio_flag flagnames[] = { .name = "bias-disabled", .mask = GPIO_V2_LINE_FLAG_BIAS_DISABLED, }, + { + .name = "clock-realtime", + .mask = GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME, + }, };static void print_attributes (struct gpio_v2_line_info *info)
Signature · 1 line
2.28.0
Kent Gibson
reviewerPATCH 3/3 tools: gpio: add option to report wall-clock time to gpio-event-mon
In reply to Kent GibsonAdd support for selecting the realtime clock for events.
--- tools/gpio/gpio-event-mon.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
tools/gpio/gpio-event-mon.c +5 -1
@@ -148,6 +148,7 @@ void print_usage(void)" -s Set line as open source\n" " -r Listen for rising edges\n" " -f Listen for falling edges\n" +" -w Report the wall-clock time for events\n" " -b <n> Debounce the line with period n microseconds\n" " [-c <n>] Do <n> loops (optional, infinite loop if not stated)\n" " -? This helptext\n"
@@ -173,7 +174,7 @@ int main(int argc, char **argv)memset (&config,0 ,sizeof (config)); config.flags =GPIO_V2_LINE_FLAG_INPUT ; -while ((c =getopt (argc, argv,"c:n:o:b:dsrf?" )) !=-1 ) { +while ((c =getopt (argc, argv,"c:n:o:b:dsrfw?" )) !=-1 ) {switch (c) {case 'c' : loops =strtoul (optarg,NULL ,10 );
@@ -204,6 +205,9 @@ int main(int argc, char **argv)case 'f' : config.flags |=GPIO_V2_LINE_FLAG_EDGE_FALLING ;break ; +case 'w' : + config.flags |=GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME ; +break ;case '?' :print_usage ();return -1 ;
Signature · 1 line
2.28.0