Commit c259acab authored by Mahesh Bandewar's avatar Mahesh Bandewar Committed by David S. Miller
Browse files

ptp/ioctl: support MONOTONIC{,_RAW} timestamps for PTP_SYS_OFFSET_EXTENDED



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: default avatarMahesh Bandewar <maheshb@google.com>
Signed-off-by: default avatarVadim Fedorenko <vadfed@meta.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d5c45460
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -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)
+32 −4
Original line number Diff line number Diff line
@@ -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)
	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)
	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
+18 −6
Original line number Diff line number Diff line
@@ -155,13 +155,25 @@ struct ptp_sys_offset {
	struct ptp_clock_time ts[2 * PTP_MAX_SAMPLES + 1];
};

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.
 * 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;
	__kernel_clockid_t clockid;
	unsigned int rsv[2];
	struct ptp_clock_time ts[PTP_MAX_SAMPLES][3];
};