7b5541
commit c0e49c708814ec783726fe92202371847703c5ed
7b5541
Author: Miroslav Lichvar <mlichvar@redhat.com>
7b5541
Date:   Mon Nov 12 17:27:58 2018 +0100
7b5541
7b5541
    sysoff: Initialize data for ioctl(PTP_SYS_OFFSET).
7b5541
    
7b5541
    This fixes valgrind errors.
7b5541
    
7b5541
    Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
7b5541
7b5541
diff --git a/sysoff.c b/sysoff.c
7b5541
index f7b6240..407a01c 100644
7b5541
--- a/sysoff.c
7b5541
+++ b/sysoff.c
7b5541
@@ -18,6 +18,7 @@
7b5541
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
7b5541
  */
7b5541
 #include <stdio.h>
7b5541
+#include <string.h>
7b5541
 #include <sys/ioctl.h>
7b5541
 #include <linux/ptp_clock.h>
7b5541
 
7b5541
@@ -76,6 +77,7 @@ int sysoff_measure(int fd, int n_samples,
7b5541
 		   int64_t *result, uint64_t *ts, int64_t *delay)
7b5541
 {
7b5541
 	struct ptp_sys_offset pso;
7b5541
+	memset(&pso, 0, sizeof(pso));
7b5541
 	pso.n_samples = n_samples;
7b5541
 	if (ioctl(fd, PTP_SYS_OFFSET, &pso)) {
7b5541
 		perror("ioctl PTP_SYS_OFFSET");
7b5541
7b5541
commit 93baf34adb81046a5e1c3b9a3e685029f2046993
7b5541
Author: Miroslav Lichvar <mlichvar@redhat.com>
7b5541
Date:   Mon Nov 12 17:27:59 2018 +0100
7b5541
7b5541
    sysoff: Extend API for different sysoff methods.
7b5541
    
7b5541
    The kernel supports different PTP_SYS_OFFSET* ioctls. Use the sysoff
7b5541
    enum to allow selecting between them in sysoff_measure().
7b5541
    
7b5541
    Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
7b5541
7b5541
diff --git a/phc2sys.c b/phc2sys.c
7b5541
index 15f8d75..2cd477a 100644
7b5541
--- a/phc2sys.c
7b5541
+++ b/phc2sys.c
7b5541
@@ -74,7 +74,7 @@ struct clock {
7b5541
 	LIST_ENTRY(clock) dst_list;
7b5541
 	clockid_t clkid;
7b5541
 	int phc_index;
7b5541
-	int sysoff_supported;
7b5541
+	int sysoff_method;
7b5541
 	int is_utc;
7b5541
 	int dest_only;
7b5541
 	int state;
7b5541
@@ -255,9 +255,8 @@ static struct clock *clock_add(struct node *node, char *device)
7b5541
 		c->servo = servo_add(node, c);
7b5541
 
7b5541
 	if (clkid != CLOCK_INVALID && clkid != CLOCK_REALTIME)
7b5541
-		c->sysoff_supported = (SYSOFF_SUPPORTED ==
7b5541
-				       sysoff_probe(CLOCKID_TO_FD(clkid),
7b5541
-						    node->phc_readings));
7b5541
+		c->sysoff_method = sysoff_probe(CLOCKID_TO_FD(clkid),
7b5541
+						node->phc_readings);
7b5541
 
7b5541
 	LIST_INSERT_HEAD(&node->clocks, c, list);
7b5541
 	return c;
7b5541
@@ -784,11 +783,12 @@ static int do_loop(struct node *node, int subscriptions)
7b5541
 				continue;
7b5541
 
7b5541
 			if (clock->clkid == CLOCK_REALTIME &&
7b5541
-			    node->master->sysoff_supported) {
7b5541
+			    node->master->sysoff_method >= 0) {
7b5541
 				/* use sysoff */
7b5541
 				if (sysoff_measure(CLOCKID_TO_FD(node->master->clkid),
7b5541
+						   node->master->sysoff_method,
7b5541
 						   node->phc_readings,
7b5541
-						   &offset, &ts, &delay))
7b5541
+						   &offset, &ts, &delay) < 0)
7b5541
 					return -1;
7b5541
 			} else {
7b5541
 				/* use phc */
7b5541
diff --git a/phc_ctl.c b/phc_ctl.c
7b5541
index 4a78a19..b9a9cf4 100644
7b5541
--- a/phc_ctl.c
7b5541
+++ b/phc_ctl.c
7b5541
@@ -367,10 +367,12 @@ static int do_cmp(clockid_t clkid, int cmdc, char *cmdv[])
7b5541
 	struct timespec ts, rta, rtb;
7b5541
 	int64_t sys_offset, delay = 0, offset;
7b5541
 	uint64_t sys_ts;
7b5541
+	int method;
7b5541
 
7b5541
-	if (SYSOFF_SUPPORTED ==
7b5541
-	    sysoff_measure(CLOCKID_TO_FD(clkid),
7b5541
-			   9, &sys_offset, &sys_ts, &delay)) {
7b5541
+	method = sysoff_probe(CLOCKID_TO_FD(clkid), 9);
7b5541
+
7b5541
+	if (method >= 0 && sysoff_measure(CLOCKID_TO_FD(clkid), method, 9,
7b5541
+					  &sys_offset, &sys_ts, &delay) >= 0) {
7b5541
 		pr_notice( "offset from CLOCK_REALTIME is %"PRId64"ns\n",
7b5541
 			sys_offset);
7b5541
 		return 0;
7b5541
diff --git a/sysoff.c b/sysoff.c
7b5541
index 407a01c..f709a9b 100644
7b5541
--- a/sysoff.c
7b5541
+++ b/sysoff.c
7b5541
@@ -73,8 +73,8 @@ static int64_t sysoff_estimate(struct ptp_clock_time *pct, int n_samples,
7b5541
 	return samples[0].offset;
7b5541
 }
7b5541
 
7b5541
-int sysoff_measure(int fd, int n_samples,
7b5541
-		   int64_t *result, uint64_t *ts, int64_t *delay)
7b5541
+static int sysoff_basic(int fd, int n_samples,
7b5541
+			int64_t *result, uint64_t *ts, int64_t *delay)
7b5541
 {
7b5541
 	struct ptp_sys_offset pso;
7b5541
 	memset(&pso, 0, sizeof(pso));
7b5541
@@ -84,13 +84,24 @@ int sysoff_measure(int fd, int n_samples,
7b5541
 		return SYSOFF_RUN_TIME_MISSING;
7b5541
 	}
7b5541
 	*result = sysoff_estimate(pso.ts, n_samples, ts, delay);
7b5541
-	return SYSOFF_SUPPORTED;
7b5541
+	return SYSOFF_BASIC;
7b5541
+}
7b5541
+
7b5541
+int sysoff_measure(int fd, int method, int n_samples,
7b5541
+		   int64_t *result, uint64_t *ts, int64_t *delay)
7b5541
+{
7b5541
+	switch (method) {
7b5541
+	case SYSOFF_BASIC:
7b5541
+		return sysoff_basic(fd, n_samples, result, ts, delay);
7b5541
+	}
7b5541
+	return SYSOFF_COMPILE_TIME_MISSING;
7b5541
 }
7b5541
 
7b5541
 int sysoff_probe(int fd, int n_samples)
7b5541
 {
7b5541
 	int64_t junk, delay;
7b5541
 	uint64_t ts;
7b5541
+	int i;
7b5541
 
7b5541
 	if (n_samples > PTP_MAX_SAMPLES) {
7b5541
 		fprintf(stderr, "warning: %d exceeds kernel max readings %d\n",
7b5541
@@ -99,7 +110,13 @@ int sysoff_probe(int fd, int n_samples)
7b5541
 		return SYSOFF_RUN_TIME_MISSING;
7b5541
 	}
7b5541
 
7b5541
-	return sysoff_measure(fd, n_samples, &junk, &ts, &delay);
7b5541
+	for (i = 0; i < SYSOFF_LAST; i++) {
7b5541
+		if (sysoff_measure(fd, i, n_samples, &junk, &ts, &delay) < 0)
7b5541
+			continue;
7b5541
+		return i;
7b5541
+	}
7b5541
+
7b5541
+	return SYSOFF_RUN_TIME_MISSING;
7b5541
 }
7b5541
 
7b5541
 #else /* !PTP_SYS_OFFSET */
7b5541
diff --git a/sysoff.h b/sysoff.h
7b5541
index cb70265..02ecdfa 100644
7b5541
--- a/sysoff.h
7b5541
+++ b/sysoff.h
7b5541
@@ -21,13 +21,14 @@
7b5541
 #include <stdint.h>
7b5541
 
7b5541
 enum {
7b5541
-	SYSOFF_SUPPORTED,
7b5541
-	SYSOFF_COMPILE_TIME_MISSING,
7b5541
-	SYSOFF_RUN_TIME_MISSING,
7b5541
+	SYSOFF_COMPILE_TIME_MISSING = -2,
7b5541
+	SYSOFF_RUN_TIME_MISSING = -1,
7b5541
+	SYSOFF_BASIC,
7b5541
+	SYSOFF_LAST,
7b5541
 };
7b5541
 
7b5541
 /**
7b5541
- * Check to see if the PTP_SYS_OFFSET ioctl is supported.
7b5541
+ * Check to see if a PTP_SYS_OFFSET ioctl is supported.
7b5541
  * @param fd  An open file descriptor to a PHC device.
7b5541
  * @return  One of the SYSOFF_ enumeration values.
7b5541
  */
7b5541
@@ -36,11 +37,12 @@ int sysoff_probe(int fd, int n_samples);
7b5541
 /**
7b5541
  * Measure the offset between a PHC and the system time.
7b5541
  * @param fd         An open file descriptor to a PHC device.
7b5541
+ * @param method     A non-negative SYSOFF_ value returned by sysoff_probe().
7b5541
  * @param n_samples  The number of consecutive readings to make.
7b5541
  * @param result     The estimated offset in nanoseconds.
7b5541
  * @param ts         The system time corresponding to the 'result'.
7b5541
  * @param delay      The delay in reading of the clock in nanoseconds.
7b5541
  * @return  One of the SYSOFF_ enumeration values.
7b5541
  */
7b5541
-int sysoff_measure(int fd, int n_samples,
7b5541
+int sysoff_measure(int fd, int method, int n_samples,
7b5541
 		   int64_t *result, uint64_t *ts, int64_t *delay);
7b5541
7b5541
commit 192b8e315c4585489d7aa7f59683035998805e40
7b5541
Author: Miroslav Lichvar <mlichvar@redhat.com>
7b5541
Date:   Mon Nov 12 17:28:00 2018 +0100
7b5541
7b5541
    sysoff: Add support for PTP_SYS_OFFSET_PRECISE ioctl.
7b5541
    
7b5541
    This ioctl uses cross timestamping for a more accurate measurement of
7b5541
    the offset. It is supported on some onboard Intel NICs using the e1000e
7b5541
    driver and a virtual PHC with the ptp_kvm driver.
7b5541
    
7b5541
    Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
7b5541
7b5541
diff --git a/sysoff.c b/sysoff.c
7b5541
index f709a9b..9f65d95 100644
7b5541
--- a/sysoff.c
7b5541
+++ b/sysoff.c
7b5541
@@ -22,6 +22,7 @@
7b5541
 #include <sys/ioctl.h>
7b5541
 #include <linux/ptp_clock.h>
7b5541
 
7b5541
+#include "print.h"
7b5541
 #include "sysoff.h"
7b5541
 
7b5541
 #define NS_PER_SEC 1000000000LL
7b5541
@@ -39,6 +40,23 @@ static struct {
7b5541
 	uint64_t timestamp;
7b5541
 } samples[PTP_MAX_SAMPLES];
7b5541
 
7b5541
+static int sysoff_precise(int fd, int64_t *result, uint64_t *ts)
7b5541
+{
7b5541
+#ifdef PTP_SYS_OFFSET_PRECISE
7b5541
+	struct ptp_sys_offset_precise pso;
7b5541
+	memset(&pso, 0, sizeof(pso));
7b5541
+	if (ioctl(fd, PTP_SYS_OFFSET_PRECISE, &pso)) {
7b5541
+		pr_debug("ioctl PTP_SYS_OFFSET_PRECISE: %m");
7b5541
+		return SYSOFF_RUN_TIME_MISSING;
7b5541
+	}
7b5541
+	*result = pctns(&pso.sys_realtime) - pctns(&pso.device);
7b5541
+	*ts = pctns(&pso.sys_realtime);
7b5541
+	return SYSOFF_PRECISE;
7b5541
+#else
7b5541
+	return SYSOFF_COMPILE_TIME_MISSING;
7b5541
+#endif
7b5541
+}
7b5541
+
7b5541
 static void insertion_sort(int length, int64_t interval, int64_t offset, uint64_t ts)
7b5541
 {
7b5541
 	int i = length - 1;
7b5541
@@ -91,6 +109,9 @@ int sysoff_measure(int fd, int method, int n_samples,
7b5541
 		   int64_t *result, uint64_t *ts, int64_t *delay)
7b5541
 {
7b5541
 	switch (method) {
7b5541
+	case SYSOFF_PRECISE:
7b5541
+		*delay = 0;
7b5541
+		return sysoff_precise(fd, result, ts);
7b5541
 	case SYSOFF_BASIC:
7b5541
 		return sysoff_basic(fd, n_samples, result, ts, delay);
7b5541
 	}
7b5541
diff --git a/sysoff.h b/sysoff.h
7b5541
index 02ecdfa..37f7353 100644
7b5541
--- a/sysoff.h
7b5541
+++ b/sysoff.h
7b5541
@@ -23,6 +23,7 @@
7b5541
 enum {
7b5541
 	SYSOFF_COMPILE_TIME_MISSING = -2,
7b5541
 	SYSOFF_RUN_TIME_MISSING = -1,
7b5541
+	SYSOFF_PRECISE,
7b5541
 	SYSOFF_BASIC,
7b5541
 	SYSOFF_LAST,
7b5541
 };
7b5541
7b5541
commit 68a9011c9d7d859920da339ba59c14dc1d617a45
7b5541
Author: Miroslav Lichvar <mlichvar@redhat.com>
7b5541
Date:   Mon Nov 12 17:28:01 2018 +0100
7b5541
7b5541
    sysoff: Add support for PTP_SYS_OFFSET_EXTENDED ioctl.
7b5541
    
7b5541
    This is a more accurate variant of the the PTP_SYS_OFFSET ioctl, which
7b5541
    will probably be supported in future kernel versions.
7b5541
    
7b5541
    Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
7b5541
7b5541
diff --git a/sysoff.c b/sysoff.c
7b5541
index 9f65d95..b993ee9 100644
7b5541
--- a/sysoff.c
7b5541
+++ b/sysoff.c
7b5541
@@ -71,17 +71,23 @@ static void insertion_sort(int length, int64_t interval, int64_t offset, uint64_
7b5541
 	samples[i+1].timestamp = ts;
7b5541
 }
7b5541
 
7b5541
-static int64_t sysoff_estimate(struct ptp_clock_time *pct, int n_samples,
7b5541
-			       uint64_t *ts, int64_t *delay)
7b5541
+static int64_t sysoff_estimate(struct ptp_clock_time *pct, int extended,
7b5541
+			       int n_samples, uint64_t *ts, int64_t *delay)
7b5541
 {
7b5541
 	int64_t t1, t2, tp;
7b5541
 	int64_t interval, offset;
7b5541
 	int i;
7b5541
 
7b5541
 	for (i = 0; i < n_samples; i++) {
7b5541
-		t1 = pctns(&pct[2*i]);
7b5541
-		tp = pctns(&pct[2*i+1]);
7b5541
-		t2 = pctns(&pct[2*i+2]);
7b5541
+		if (extended) {
7b5541
+			t1 = pctns(&pct[3*i]);
7b5541
+			tp = pctns(&pct[3*i+1]);
7b5541
+			t2 = pctns(&pct[3*i+2]);
7b5541
+		} else {
7b5541
+			t1 = pctns(&pct[2*i]);
7b5541
+			tp = pctns(&pct[2*i+1]);
7b5541
+			t2 = pctns(&pct[2*i+2]);
7b5541
+		}
7b5541
 		interval = t2 - t1;
7b5541
 		offset = (t2 + t1) / 2 - tp;
7b5541
 		insertion_sort(i, interval, offset, (t2 + t1) / 2);
7b5541
@@ -91,6 +97,24 @@ static int64_t sysoff_estimate(struct ptp_clock_time *pct, int n_samples,
7b5541
 	return samples[0].offset;
7b5541
 }
7b5541
 
7b5541
+static int sysoff_extended(int fd, int n_samples,
7b5541
+			   int64_t *result, uint64_t *ts, int64_t *delay)
7b5541
+{
7b5541
+#ifdef PTP_SYS_OFFSET_EXTENDED
7b5541
+	struct ptp_sys_offset_extended pso;
7b5541
+	memset(&pso, 0, sizeof(pso));
7b5541
+	pso.n_samples = n_samples;
7b5541
+	if (ioctl(fd, PTP_SYS_OFFSET_EXTENDED, &pso)) {
7b5541
+		pr_debug("ioctl PTP_SYS_OFFSET_EXTENDED: %m");
7b5541
+		return SYSOFF_RUN_TIME_MISSING;
7b5541
+	}
7b5541
+	*result = sysoff_estimate(&pso.ts[0][0], 1, n_samples, ts, delay);
7b5541
+	return SYSOFF_EXTENDED;
7b5541
+#else
7b5541
+	return SYSOFF_COMPILE_TIME_MISSING;
7b5541
+#endif
7b5541
+}
7b5541
+
7b5541
 static int sysoff_basic(int fd, int n_samples,
7b5541
 			int64_t *result, uint64_t *ts, int64_t *delay)
7b5541
 {
7b5541
@@ -101,7 +125,7 @@ static int sysoff_basic(int fd, int n_samples,
7b5541
 		perror("ioctl PTP_SYS_OFFSET");
7b5541
 		return SYSOFF_RUN_TIME_MISSING;
7b5541
 	}
7b5541
-	*result = sysoff_estimate(pso.ts, n_samples, ts, delay);
7b5541
+	*result = sysoff_estimate(pso.ts, 0, n_samples, ts, delay);
7b5541
 	return SYSOFF_BASIC;
7b5541
 }
7b5541
 
7b5541
@@ -112,6 +136,8 @@ int sysoff_measure(int fd, int method, int n_samples,
7b5541
 	case SYSOFF_PRECISE:
7b5541
 		*delay = 0;
7b5541
 		return sysoff_precise(fd, result, ts);
7b5541
+	case SYSOFF_EXTENDED:
7b5541
+		return sysoff_extended(fd, n_samples, result, ts, delay);
7b5541
 	case SYSOFF_BASIC:
7b5541
 		return sysoff_basic(fd, n_samples, result, ts, delay);
7b5541
 	}
7b5541
diff --git a/sysoff.h b/sysoff.h
7b5541
index 37f7353..79d2290 100644
7b5541
--- a/sysoff.h
7b5541
+++ b/sysoff.h
7b5541
@@ -24,6 +24,7 @@ enum {
7b5541
 	SYSOFF_COMPILE_TIME_MISSING = -2,
7b5541
 	SYSOFF_RUN_TIME_MISSING = -1,
7b5541
 	SYSOFF_PRECISE,
7b5541
+	SYSOFF_EXTENDED,
7b5541
 	SYSOFF_BASIC,
7b5541
 	SYSOFF_LAST,
7b5541
 };
7b5541
7b5541
commit 8142da41b61fb5b9ee4ad8f5ab56adb0447cd37b
7b5541
Author: Miroslav Lichvar <mlichvar@redhat.com>
7b5541
Date:   Mon Nov 12 17:28:02 2018 +0100
7b5541
7b5541
    phc2sys: Use reversed sysoff when synchronizing to system clock.
7b5541
    
7b5541
    If synchronizing a PHC to the system clock, use one of the
7b5541
    PTP_SYS_OFFSET ioctls (if supported) to measure the offset between the
7b5541
    two clocks. Negate the offset and switch the timestamp before passing
7b5541
    them to the servo.
7b5541
    
7b5541
    This makes the synchronization between PHC and system clock symmetric.
7b5541
    
7b5541
    Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
7b5541
7b5541
diff --git a/phc2sys.c b/phc2sys.c
7b5541
index 2cd477a..b8f1ea0 100644
7b5541
--- a/phc2sys.c
7b5541
+++ b/phc2sys.c
7b5541
@@ -790,6 +790,16 @@ static int do_loop(struct node *node, int subscriptions)
7b5541
 						   node->phc_readings,
7b5541
 						   &offset, &ts, &delay) < 0)
7b5541
 					return -1;
7b5541
+			} else if (node->master->clkid == CLOCK_REALTIME &&
7b5541
+				   clock->sysoff_method >= 0) {
7b5541
+				/* use reversed sysoff */
7b5541
+				if (sysoff_measure(CLOCKID_TO_FD(clock->clkid),
7b5541
+						   clock->sysoff_method,
7b5541
+						   node->phc_readings,
7b5541
+						   &offset, &ts, &delay) < 0)
7b5541
+					return -1;
7b5541
+				ts += offset;
7b5541
+				offset = -offset;
7b5541
 			} else {
7b5541
 				/* use phc */
7b5541
 				if (!read_phc(node->master->clkid, clock->clkid,