ptp/ioctl: support MONOTONIC{,_RAW} timestamps for PTP_SYS_OFFSET_EXTENDED
authorMahesh Bandewar <maheshb@google.com>
Wed, 4 Sep 2024 14:13:05 +0000 (07:13 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sun, 8 Sep 2024 17:40:33 +0000 (18:40 +0100)
The ability to read the PHC (Physical Hardware Clock) alongside
multiple system clocks is currently dependent on the specific
hardware architecture. This limitation restricts the use of
PTP_SYS_OFFSET_PRECISE to certain hardware configurations.

The generic soultion which would work across all architectures
is to read the PHC along with the latency to perform PHC-read as
offered by PTP_SYS_OFFSET_EXTENDED which provides pre and post
timestamps.  However, these timestamps are currently limited
to the CLOCK_REALTIME timebase. Since CLOCK_REALTIME is affected
by NTP (or similar time synchronization services), it can
experience significant jumps forward or backward. This hinders
the precise latency measurements that PTP_SYS_OFFSET_EXTENDED
is designed to provide.

This problem could be addressed by supporting MONOTONIC_RAW
timestamps within PTP_SYS_OFFSET_EXTENDED. Unlike CLOCK_REALTIME
or CLOCK_MONOTONIC, the MONOTONIC_RAW timebase is unaffected
by NTP adjustments.

This enhancement can be implemented by utilizing one of the three
reserved words within the PTP_SYS_OFFSET_EXTENDED struct to pass
the clock-id for timestamps.  The current behavior aligns with
clock-id for CLOCK_REALTIME timebase (value of 0), ensuring
backward compatibility of the UAPI.

Signed-off-by: Mahesh Bandewar <maheshb@google.com>
Signed-off-by: Vadim Fedorenko <vadfed@meta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/ptp/ptp_chardev.c
include/linux/ptp_clock_kernel.h
include/uapi/linux/ptp_clock.h

index 2067b0120d083d868e0f8fee2119fb0a4cd6a2b4..ea96a14d72d141a4b255563b66bac8ed568b45e9 100644 (file)
@@ -359,11 +359,15 @@ long ptp_ioctl(struct posix_clock_context *pccontext, unsigned int cmd,
                        extoff = NULL;
                        break;
                }
-               if (extoff->n_samples > PTP_MAX_SAMPLES
-                   || extoff->rsv[0] || extoff->rsv[1] || extoff->rsv[2]) {
+               if (extoff->n_samples > PTP_MAX_SAMPLES ||
+                   extoff->rsv[0] || extoff->rsv[1] ||
+                   (extoff->clockid != CLOCK_REALTIME &&
+                    extoff->clockid != CLOCK_MONOTONIC &&
+                    extoff->clockid != CLOCK_MONOTONIC_RAW)) {
                        err = -EINVAL;
                        break;
                }
+               sts.clockid = extoff->clockid;
                for (i = 0; i < extoff->n_samples; i++) {
                        err = ptp->info->gettimex64(ptp->info, &ts, &sts);
                        if (err)
index 6e4b8206c7d0a2a327bd06f6e3333688ad79e36b..c892d22ce0a7bffae7def45866add060136cbbf7 100644 (file)
@@ -47,10 +47,12 @@ struct system_device_crosststamp;
  * struct ptp_system_timestamp - system time corresponding to a PHC timestamp
  * @pre_ts: system timestamp before capturing PHC
  * @post_ts: system timestamp after capturing PHC
+ * @clockid: clock-base used for capturing the system timestamps
  */
 struct ptp_system_timestamp {
        struct timespec64 pre_ts;
        struct timespec64 post_ts;
+       clockid_t clockid;
 };
 
 /**
@@ -457,14 +459,40 @@ static inline ktime_t ptp_convert_timestamp(const ktime_t *hwtstamp,
 
 static inline void ptp_read_system_prets(struct ptp_system_timestamp *sts)
 {
-       if (sts)
-               ktime_get_real_ts64(&sts->pre_ts);
+       if (sts) {
+               switch (sts->clockid) {
+               case CLOCK_REALTIME:
+                       ktime_get_real_ts64(&sts->pre_ts);
+                       break;
+               case CLOCK_MONOTONIC:
+                       ktime_get_ts64(&sts->pre_ts);
+                       break;
+               case CLOCK_MONOTONIC_RAW:
+                       ktime_get_raw_ts64(&sts->pre_ts);
+                       break;
+               default:
+                       break;
+               }
+       }
 }
 
 static inline void ptp_read_system_postts(struct ptp_system_timestamp *sts)
 {
-       if (sts)
-               ktime_get_real_ts64(&sts->post_ts);
+       if (sts) {
+               switch (sts->clockid) {
+               case CLOCK_REALTIME:
+                       ktime_get_real_ts64(&sts->post_ts);
+                       break;
+               case CLOCK_MONOTONIC:
+                       ktime_get_ts64(&sts->post_ts);
+                       break;
+               case CLOCK_MONOTONIC_RAW:
+                       ktime_get_raw_ts64(&sts->post_ts);
+                       break;
+               default:
+                       break;
+               }
+       }
 }
 
 #endif
index 053b40d642de28c35223fcf2bb3611bf0db78464..18eefa6d93d62fc34edae8ae904db8cfad978c83 100644 (file)
@@ -155,13 +155,25 @@ struct ptp_sys_offset {
        struct ptp_clock_time ts[2 * PTP_MAX_SAMPLES + 1];
 };
 
+/*
+ * ptp_sys_offset_extended - data structure for IOCTL operation
+ *                          PTP_SYS_OFFSET_EXTENDED
+ *
+ * @n_samples: Desired number of measurements.
+ * @clockid:   clockid of a clock-base used for pre/post timestamps.
+ * @rsv:       Reserved for future use.
+ * @ts:                Array of samples in the form [pre-TS, PHC, post-TS]. The
+ *             kernel provides @n_samples.
+ *
+ * Starting from kernel 6.12 and onwards, the first word of the reserved-field
+ * is used for @clockid. That's backward compatible since previous kernel
+ * expect all three reserved words (@rsv[3]) to be 0 while the clockid (first
+ * word in the new structure) for CLOCK_REALTIME is '0'.
+ */
 struct ptp_sys_offset_extended {
-       unsigned int n_samples; /* Desired number of measurements. */
-       unsigned int rsv[3];    /* Reserved for future use. */
-       /*
-        * Array of [system, phc, system] time stamps. The kernel will provide
-        * 3*n_samples time stamps.
-        */
+       unsigned int n_samples;
+       __kernel_clockid_t clockid;
+       unsigned int rsv[2];
        struct ptp_clock_time ts[PTP_MAX_SAMPLES][3];
 };
 
This page took 0.109793 seconds and 4 git commands to generate.