dcavalca / rpms / linuxptp

Forked from rpms/linuxptp 2 years ago
Clone
ddc8b9
commit f32a8469a236728fb158ce997385b53f92b821cc
ddc8b9
Author: Jacob Keller <jacob.e.keller@intel.com>
ddc8b9
Date:   Tue Nov 23 14:43:26 2021 -0800
ddc8b9
ddc8b9
    phc2sys: move read_phc into clock_adj.c
ddc8b9
    
ddc8b9
    The read_phc function implemented in phc2sys.c is used to perform clock
ddc8b9
    comparison between two arbitrary clocks using clock_gettime.
ddc8b9
    
ddc8b9
    This support is used to allow phc2sys to work on any pair of clocks and
ddc8b9
    is implemented in a very similar manner as the kernel PTP_SYS_OFFSET
ddc8b9
    ioctls.
ddc8b9
    
ddc8b9
    Make this function easier to re-use by moving it out of phc2sys.c and
ddc8b9
    into a more accessible location. clockadj.c seems like a reasonable
ddc8b9
    location as this file has many functions which deal with clockid_t
ddc8b9
    values, and this functionality is tangentially related to adjusting
ddc8b9
    clocks.
ddc8b9
    
ddc8b9
    Moving this function will allow using it in the phc_ctl program in a
ddc8b9
    future change.
ddc8b9
    
ddc8b9
    Notice that read_phc returned 0 on failure and 1 on success. This is
ddc8b9
    fairly non-standard, so lets update clockadj_compare to return 0 on
ddc8b9
    success and -1 on failure. Fix the call sites to check correctly and
ddc8b9
    report an error.
ddc8b9
    
ddc8b9
    Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
ddc8b9
ddc8b9
diff --git a/clockadj.c b/clockadj.c
ddc8b9
index b5c78cd..e8c5789 100644
ddc8b9
--- a/clockadj.c
ddc8b9
+++ b/clockadj.c
ddc8b9
@@ -139,6 +139,37 @@ int clockadj_max_freq(clockid_t clkid)
ddc8b9
 	return f;
ddc8b9
 }
ddc8b9
 
ddc8b9
+int clockadj_compare(clockid_t clkid, clockid_t sysclk, int readings,
ddc8b9
+		     int64_t *offset, uint64_t *ts, int64_t *delay)
ddc8b9
+{
ddc8b9
+	struct timespec tdst1, tdst2, tsrc;
ddc8b9
+	int i;
ddc8b9
+	int64_t interval, best_interval = INT64_MAX;
ddc8b9
+
ddc8b9
+	/* Pick the quickest clkid reading. */
ddc8b9
+	for (i = 0; i < readings; i++) {
ddc8b9
+		if (clock_gettime(sysclk, &tdst1) ||
ddc8b9
+				clock_gettime(clkid, &tsrc) ||
ddc8b9
+				clock_gettime(sysclk, &tdst2)) {
ddc8b9
+			pr_err("failed to read clock: %m");
ddc8b9
+			return -1;
ddc8b9
+		}
ddc8b9
+
ddc8b9
+		interval = (tdst2.tv_sec - tdst1.tv_sec) * NS_PER_SEC +
ddc8b9
+			tdst2.tv_nsec - tdst1.tv_nsec;
ddc8b9
+
ddc8b9
+		if (best_interval > interval) {
ddc8b9
+			best_interval = interval;
ddc8b9
+			*offset = (tdst1.tv_sec - tsrc.tv_sec) * NS_PER_SEC +
ddc8b9
+				tdst1.tv_nsec - tsrc.tv_nsec + interval / 2;
ddc8b9
+			*ts = tdst2.tv_sec * NS_PER_SEC + tdst2.tv_nsec;
ddc8b9
+		}
ddc8b9
+	}
ddc8b9
+	*delay = best_interval;
ddc8b9
+
ddc8b9
+	return 0;
ddc8b9
+}
ddc8b9
+
ddc8b9
 void sysclk_set_leap(int leap)
ddc8b9
 {
ddc8b9
 	clockid_t clkid = CLOCK_REALTIME;
ddc8b9
diff --git a/clockadj.h b/clockadj.h
ddc8b9
index 43325c8..b63ae38 100644
ddc8b9
--- a/clockadj.h
ddc8b9
+++ b/clockadj.h
ddc8b9
@@ -63,6 +63,24 @@ void clockadj_step(clockid_t clkid, int64_t step);
ddc8b9
  */
ddc8b9
 int clockadj_max_freq(clockid_t clkid);
ddc8b9
 
ddc8b9
+/**
ddc8b9
+ * Compare offset between two clocks
ddc8b9
+ * @param clkid     A clock ID obtained using phc_open() or CLOCK_REALTIME
ddc8b9
+ * @param sysclk    A clock ID obtained using phc_open() or CLOCK_REALTIME
ddc8b9
+ * @param readings  Number of readings to try
ddc8b9
+ * @param offset    On return, the nanoseconds offset between the clocks
ddc8b9
+ * @param ts        On return, the time of sysclk in nanoseconds that was used
ddc8b9
+ * @param delay     On return, the interval between two reads of sysclk
ddc8b9
+ * @return Zero on success and non-zero on failure.
ddc8b9
+ *
ddc8b9
+ * Compare the offset between two clocks in a similar manner as the
ddc8b9
+ * PTP_SYS_OFFSET ioctls. Performs multiple reads of sysclk with a read of
ddc8b9
+ * clkid between in order to calculate the time difference of sysclk minus
ddc8b9
+ * clkid.
ddc8b9
+ */
ddc8b9
+int clockadj_compare(clockid_t clkid, clockid_t sysclk, int readings,
ddc8b9
+		     int64_t *offset, uint64_t *ts, int64_t *delay);
ddc8b9
+
ddc8b9
 /**
ddc8b9
  * Set the system clock to insert/delete leap second at midnight.
ddc8b9
  * @param leap  +1 to insert leap second, -1 to delete leap second,
ddc8b9
diff --git a/phc2sys.c b/phc2sys.c
ddc8b9
index a36cbe0..7a547fa 100644
ddc8b9
--- a/phc2sys.c
ddc8b9
+++ b/phc2sys.c
ddc8b9
@@ -486,37 +486,6 @@ static void reconfigure(struct phc2sys_private *priv)
ddc8b9
 	pr_info("selecting %s as the master clock", src->device);
ddc8b9
 }
ddc8b9
 
ddc8b9
-static int read_phc(clockid_t clkid, clockid_t sysclk, int readings,
ddc8b9
-		    int64_t *offset, uint64_t *ts, int64_t *delay)
ddc8b9
-{
ddc8b9
-	struct timespec tdst1, tdst2, tsrc;
ddc8b9
-	int i;
ddc8b9
-	int64_t interval, best_interval = INT64_MAX;
ddc8b9
-
ddc8b9
-	/* Pick the quickest clkid reading. */
ddc8b9
-	for (i = 0; i < readings; i++) {
ddc8b9
-		if (clock_gettime(sysclk, &tdst1) ||
ddc8b9
-				clock_gettime(clkid, &tsrc) ||
ddc8b9
-				clock_gettime(sysclk, &tdst2)) {
ddc8b9
-			pr_err("failed to read clock: %m");
ddc8b9
-			return 0;
ddc8b9
-		}
ddc8b9
-
ddc8b9
-		interval = (tdst2.tv_sec - tdst1.tv_sec) * NS_PER_SEC +
ddc8b9
-			tdst2.tv_nsec - tdst1.tv_nsec;
ddc8b9
-
ddc8b9
-		if (best_interval > interval) {
ddc8b9
-			best_interval = interval;
ddc8b9
-			*offset = (tdst1.tv_sec - tsrc.tv_sec) * NS_PER_SEC +
ddc8b9
-				tdst1.tv_nsec - tsrc.tv_nsec + interval / 2;
ddc8b9
-			*ts = tdst2.tv_sec * NS_PER_SEC + tdst2.tv_nsec;
ddc8b9
-		}
ddc8b9
-	}
ddc8b9
-	*delay = best_interval;
ddc8b9
-
ddc8b9
-	return 1;
ddc8b9
-}
ddc8b9
-
ddc8b9
 static int64_t get_sync_offset(struct phc2sys_private *priv, struct clock *dst)
ddc8b9
 {
ddc8b9
 	int direction = priv->forced_sync_offset;
ddc8b9
@@ -672,8 +641,10 @@ static int do_pps_loop(struct phc2sys_private *priv, struct clock *clock,
ddc8b9
 		/* If a PHC is available, use it to get the whole number
ddc8b9
 		   of seconds in the offset and PPS for the rest. */
ddc8b9
 		if (src != CLOCK_INVALID) {
ddc8b9
-			if (!read_phc(src, clock->clkid, priv->phc_readings,
ddc8b9
-				      &phc_offset, &phc_ts, &phc_delay))
ddc8b9
+			if (clockadj_compare(src, clock->clkid,
ddc8b9
+					     priv->phc_readings,
ddc8b9
+					     &phc_offset, &phc_ts,
ddc8b9
+					     &phc_delay))
ddc8b9
 				return -1;
ddc8b9
 
ddc8b9
 			/* Convert the time stamp to the PHC time. */
ddc8b9
@@ -781,10 +752,11 @@ static int do_loop(struct phc2sys_private *priv, int subscriptions)
ddc8b9
 				ts += offset;
ddc8b9
 			} else {
ddc8b9
 				/* use phc */
ddc8b9
-				if (!read_phc(priv->master->clkid, clock->clkid,
ddc8b9
-					      priv->phc_readings,
ddc8b9
-					      &offset, &ts, &delay))
ddc8b9
-					continue;
ddc8b9
+				if (clockadj_compare(priv->master->clkid,
ddc8b9
+						     clock->clkid,
ddc8b9
+						     priv->phc_readings,
ddc8b9
+						     &offset, &ts, &delay))
ddc8b9
+					return -1;
ddc8b9
 			}
ddc8b9
 			update_clock(priv, clock, offset, ts, delay);
ddc8b9
 		}
ddc8b9
ddc8b9
commit 96486bda9ac1613fb36feb84d76ababd8972bba6
ddc8b9
Author: Miroslav Lichvar <mlichvar@redhat.com>
ddc8b9
Date:   Tue May 17 12:31:45 2022 +0200
ddc8b9
ddc8b9
    clockadj: Change clockadj_compare() to return errno.
ddc8b9
    
ddc8b9
    Return -errno from the failed clock_gettime() to allow the callers to
ddc8b9
    check for specific errors.
ddc8b9
    
ddc8b9
    Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
ddc8b9
ddc8b9
diff --git a/clockadj.c b/clockadj.c
ddc8b9
index e8c5789..957dc57 100644
ddc8b9
--- a/clockadj.c
ddc8b9
+++ b/clockadj.c
ddc8b9
@@ -17,6 +17,7 @@
ddc8b9
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ddc8b9
  */
ddc8b9
 
ddc8b9
+#include <errno.h>
ddc8b9
 #include <math.h>
ddc8b9
 #include <string.h>
ddc8b9
 #include <unistd.h>
ddc8b9
@@ -152,7 +153,7 @@ int clockadj_compare(clockid_t clkid, clockid_t sysclk, int readings,
ddc8b9
 				clock_gettime(clkid, &tsrc) ||
ddc8b9
 				clock_gettime(sysclk, &tdst2)) {
ddc8b9
 			pr_err("failed to read clock: %m");
ddc8b9
-			return -1;
ddc8b9
+			return -errno;
ddc8b9
 		}
ddc8b9
 
ddc8b9
 		interval = (tdst2.tv_sec - tdst1.tv_sec) * NS_PER_SEC +
ddc8b9
diff --git a/clockadj.h b/clockadj.h
ddc8b9
index b63ae38..6db1d79 100644
ddc8b9
--- a/clockadj.h
ddc8b9
+++ b/clockadj.h
ddc8b9
@@ -71,7 +71,7 @@ int clockadj_max_freq(clockid_t clkid);
ddc8b9
  * @param offset    On return, the nanoseconds offset between the clocks
ddc8b9
  * @param ts        On return, the time of sysclk in nanoseconds that was used
ddc8b9
  * @param delay     On return, the interval between two reads of sysclk
ddc8b9
- * @return Zero on success and non-zero on failure.
ddc8b9
+ * @return Zero on success, or negative error code on failure.
ddc8b9
  *
ddc8b9
  * Compare the offset between two clocks in a similar manner as the
ddc8b9
  * PTP_SYS_OFFSET ioctls. Performs multiple reads of sysclk with a read of
ddc8b9
ddc8b9
commit a523e893a15001025379e3c2dedb231e99cc886f
ddc8b9
Author: Miroslav Lichvar <mlichvar@redhat.com>
ddc8b9
Date:   Thu Mar 24 11:55:35 2022 +0100
ddc8b9
ddc8b9
    sysoff: Change sysoff_measure() to return errno.
ddc8b9
    
ddc8b9
    Return -errno from failed ioctl instead of the SYSOFF_* enum from the
ddc8b9
    measurement functions to allow the callers to check for specific errors.
ddc8b9
    
ddc8b9
    Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
ddc8b9
ddc8b9
diff --git a/sysoff.c b/sysoff.c
ddc8b9
index 2743859..5d3b907 100644
ddc8b9
--- a/sysoff.c
ddc8b9
+++ b/sysoff.c
ddc8b9
@@ -17,6 +17,7 @@
ddc8b9
  * with this program; if not, write to the Free Software Foundation, Inc.,
ddc8b9
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ddc8b9
  */
ddc8b9
+#include <errno.h>
ddc8b9
 #include <stdio.h>
ddc8b9
 #include <string.h>
ddc8b9
 #include <sys/ioctl.h>
ddc8b9
@@ -38,11 +39,11 @@ static int sysoff_precise(int fd, int64_t *result, uint64_t *ts)
ddc8b9
 	memset(&pso, 0, sizeof(pso));
ddc8b9
 	if (ioctl(fd, PTP_SYS_OFFSET_PRECISE, &pso)) {
ddc8b9
 		pr_debug("ioctl PTP_SYS_OFFSET_PRECISE: %m");
ddc8b9
-		return SYSOFF_RUN_TIME_MISSING;
ddc8b9
+		return -errno;
ddc8b9
 	}
ddc8b9
 	*result = pctns(&pso.sys_realtime) - pctns(&pso.device);
ddc8b9
 	*ts = pctns(&pso.sys_realtime);
ddc8b9
-	return SYSOFF_PRECISE;
ddc8b9
+	return 0;
ddc8b9
 }
ddc8b9
 
ddc8b9
 static int64_t sysoff_estimate(struct ptp_clock_time *pct, int extended,
ddc8b9
@@ -98,10 +99,10 @@ static int sysoff_extended(int fd, int n_samples,
ddc8b9
 	pso.n_samples = n_samples;
ddc8b9
 	if (ioctl(fd, PTP_SYS_OFFSET_EXTENDED, &pso)) {
ddc8b9
 		pr_debug("ioctl PTP_SYS_OFFSET_EXTENDED: %m");
ddc8b9
-		return SYSOFF_RUN_TIME_MISSING;
ddc8b9
+		return -errno;
ddc8b9
 	}
ddc8b9
 	*result = sysoff_estimate(&pso.ts[0][0], 1, n_samples, ts, delay);
ddc8b9
-	return SYSOFF_EXTENDED;
ddc8b9
+	return 0;
ddc8b9
 }
ddc8b9
 
ddc8b9
 static int sysoff_basic(int fd, int n_samples,
ddc8b9
@@ -112,10 +113,10 @@ static int sysoff_basic(int fd, int n_samples,
ddc8b9
 	pso.n_samples = n_samples;
ddc8b9
 	if (ioctl(fd, PTP_SYS_OFFSET, &pso)) {
ddc8b9
 		perror("ioctl PTP_SYS_OFFSET");
ddc8b9
-		return SYSOFF_RUN_TIME_MISSING;
ddc8b9
+		return -errno;
ddc8b9
 	}
ddc8b9
 	*result = sysoff_estimate(pso.ts, 0, n_samples, ts, delay);
ddc8b9
-	return SYSOFF_BASIC;
ddc8b9
+	return 0;
ddc8b9
 }
ddc8b9
 
ddc8b9
 int sysoff_measure(int fd, int method, int n_samples,
ddc8b9
@@ -130,7 +131,7 @@ int sysoff_measure(int fd, int method, int n_samples,
ddc8b9
 	case SYSOFF_BASIC:
ddc8b9
 		return sysoff_basic(fd, n_samples, result, ts, delay);
ddc8b9
 	}
ddc8b9
-	return SYSOFF_RUN_TIME_MISSING;
ddc8b9
+	return -EOPNOTSUPP;
ddc8b9
 }
ddc8b9
 
ddc8b9
 int sysoff_probe(int fd, int n_samples)
ddc8b9
diff --git a/sysoff.h b/sysoff.h
ddc8b9
index e4de919..5480f8f 100644
ddc8b9
--- a/sysoff.h
ddc8b9
+++ b/sysoff.h
ddc8b9
@@ -44,7 +44,7 @@ int sysoff_probe(int fd, int n_samples);
ddc8b9
  * @param result     The estimated offset in nanoseconds.
ddc8b9
  * @param ts         The system time corresponding to the 'result'.
ddc8b9
  * @param delay      The delay in reading of the clock in nanoseconds.
ddc8b9
- * @return  One of the SYSOFF_ enumeration values.
ddc8b9
+ * @return  Zero on success, negative error code otherwise.
ddc8b9
  */
ddc8b9
 int sysoff_measure(int fd, int method, int n_samples,
ddc8b9
 		   int64_t *result, uint64_t *ts, int64_t *delay);
ddc8b9
ddc8b9
commit 25b340eb1daad807d9485728f0917ec25a376e0c
ddc8b9
Author: Miroslav Lichvar <mlichvar@redhat.com>
ddc8b9
Date:   Wed May 18 10:21:29 2022 +0200
ddc8b9
ddc8b9
    sysoff: Change log level of ioctl error messages.
ddc8b9
    
ddc8b9
    Change the log level of ioctl error messages to the error level to make
ddc8b9
    them visible in default configuration, with the exception of EOPNOTSUPP
ddc8b9
    which is expected in probing and should stay at the debug level to avoid
ddc8b9
    confusing users.
ddc8b9
    
ddc8b9
    Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
ddc8b9
ddc8b9
diff --git a/sysoff.c b/sysoff.c
ddc8b9
index 5d3b907..a425275 100644
ddc8b9
--- a/sysoff.c
ddc8b9
+++ b/sysoff.c
ddc8b9
@@ -28,6 +28,14 @@
ddc8b9
 
ddc8b9
 #define NS_PER_SEC 1000000000LL
ddc8b9
 
ddc8b9
+static void print_ioctl_error(const char *name)
ddc8b9
+{
ddc8b9
+	if (errno == EOPNOTSUPP)
ddc8b9
+		pr_debug("ioctl %s: %s", name, strerror(errno));
ddc8b9
+	else
ddc8b9
+		pr_err("ioctl %s: %s", name, strerror(errno));
ddc8b9
+}
ddc8b9
+
ddc8b9
 static int64_t pctns(struct ptp_clock_time *t)
ddc8b9
 {
ddc8b9
 	return t->sec * NS_PER_SEC + t->nsec;
ddc8b9
@@ -38,7 +46,7 @@ static int sysoff_precise(int fd, int64_t *result, uint64_t *ts)
ddc8b9
 	struct ptp_sys_offset_precise pso;
ddc8b9
 	memset(&pso, 0, sizeof(pso));
ddc8b9
 	if (ioctl(fd, PTP_SYS_OFFSET_PRECISE, &pso)) {
ddc8b9
-		pr_debug("ioctl PTP_SYS_OFFSET_PRECISE: %m");
ddc8b9
+		print_ioctl_error("PTP_SYS_OFFSET_PRECISE");
ddc8b9
 		return -errno;
ddc8b9
 	}
ddc8b9
 	*result = pctns(&pso.sys_realtime) - pctns(&pso.device);
ddc8b9
@@ -98,7 +106,7 @@ static int sysoff_extended(int fd, int n_samples,
ddc8b9
 	memset(&pso, 0, sizeof(pso));
ddc8b9
 	pso.n_samples = n_samples;
ddc8b9
 	if (ioctl(fd, PTP_SYS_OFFSET_EXTENDED, &pso)) {
ddc8b9
-		pr_debug("ioctl PTP_SYS_OFFSET_EXTENDED: %m");
ddc8b9
+		print_ioctl_error("PTP_SYS_OFFSET_EXTENDED");
ddc8b9
 		return -errno;
ddc8b9
 	}
ddc8b9
 	*result = sysoff_estimate(&pso.ts[0][0], 1, n_samples, ts, delay);
ddc8b9
@@ -112,7 +120,7 @@ static int sysoff_basic(int fd, int n_samples,
ddc8b9
 	memset(&pso, 0, sizeof(pso));
ddc8b9
 	pso.n_samples = n_samples;
ddc8b9
 	if (ioctl(fd, PTP_SYS_OFFSET, &pso)) {
ddc8b9
-		perror("ioctl PTP_SYS_OFFSET");
ddc8b9
+		print_ioctl_error("PTP_SYS_OFFSET");
ddc8b9
 		return -errno;
ddc8b9
 	}
ddc8b9
 	*result = sysoff_estimate(pso.ts, 0, n_samples, ts, delay);
ddc8b9
ddc8b9
commit 755cf11ad6e5d02e11519b6e2644ee0f71da91ea
ddc8b9
Author: Miroslav Lichvar <mlichvar@redhat.com>
ddc8b9
Date:   Thu Mar 24 12:41:49 2022 +0100
ddc8b9
ddc8b9
    sysoff: Retry on EBUSY when probing supported ioctls.
ddc8b9
    
ddc8b9
    Handle EBUSY when probing support for a PTP_SYS_OFFSET ioctl. Try each
ddc8b9
    ioctl up to three times before giving up on it to make the detection
ddc8b9
    more reliable.
ddc8b9
    
ddc8b9
    Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
ddc8b9
ddc8b9
diff --git a/sysoff.c b/sysoff.c
ddc8b9
index a425275..fc1f7ca 100644
ddc8b9
--- a/sysoff.c
ddc8b9
+++ b/sysoff.c
ddc8b9
@@ -145,8 +145,8 @@ int sysoff_measure(int fd, int method, int n_samples,
ddc8b9
 int sysoff_probe(int fd, int n_samples)
ddc8b9
 {
ddc8b9
 	int64_t junk, delay;
ddc8b9
+	int i, j, err;
ddc8b9
 	uint64_t ts;
ddc8b9
-	int i;
ddc8b9
 
ddc8b9
 	if (n_samples > PTP_MAX_SAMPLES) {
ddc8b9
 		fprintf(stderr, "warning: %d exceeds kernel max readings %d\n",
ddc8b9
@@ -156,9 +156,15 @@ int sysoff_probe(int fd, int n_samples)
ddc8b9
 	}
ddc8b9
 
ddc8b9
 	for (i = 0; i < SYSOFF_LAST; i++) {
ddc8b9
-		if (sysoff_measure(fd, i, n_samples, &junk, &ts, &delay) < 0)
ddc8b9
-			continue;
ddc8b9
-		return i;
ddc8b9
+		for (j = 0; j < 3; j++) {
ddc8b9
+			err = sysoff_measure(fd, i, n_samples, &junk, &ts,
ddc8b9
+					     &delay);
ddc8b9
+			if (err == -EBUSY)
ddc8b9
+				continue;
ddc8b9
+			if (err)
ddc8b9
+				break;
ddc8b9
+			return i;
ddc8b9
+		}
ddc8b9
 	}
ddc8b9
 
ddc8b9
 	return SYSOFF_RUN_TIME_MISSING;
ddc8b9
ddc8b9
commit d1e8ea2405a42b42bcaf2166717fe0da6e9871ae
ddc8b9
Author: Miroslav Lichvar <mlichvar@redhat.com>
ddc8b9
Date:   Tue Mar 8 12:18:31 2022 +0100
ddc8b9
ddc8b9
    phc2sys: Don't exit when reading of PHC fails with EBUSY.
ddc8b9
    
ddc8b9
    Reading of the PHC can occasionally fail with some drivers, e.g. the ice
ddc8b9
    driver returns EBUSY when it fails to get a lock. Continue in the loop
ddc8b9
    instead of exiting on the error.
ddc8b9
    
ddc8b9
    Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
ddc8b9
ddc8b9
diff --git a/phc2sys.c b/phc2sys.c
ddc8b9
index 7a547fa..b4e2e87 100644
ddc8b9
--- a/phc2sys.c
ddc8b9
+++ b/phc2sys.c
ddc8b9
@@ -623,6 +623,7 @@ static int do_pps_loop(struct phc2sys_private *priv, struct clock *clock,
ddc8b9
 	int64_t pps_offset, phc_offset, phc_delay;
ddc8b9
 	uint64_t pps_ts, phc_ts;
ddc8b9
 	clockid_t src = priv->master->clkid;
ddc8b9
+	int err;
ddc8b9
 
ddc8b9
 	priv->master->source_label = "pps";
ddc8b9
 
ddc8b9
@@ -641,10 +642,13 @@ static int do_pps_loop(struct phc2sys_private *priv, struct clock *clock,
ddc8b9
 		/* If a PHC is available, use it to get the whole number
ddc8b9
 		   of seconds in the offset and PPS for the rest. */
ddc8b9
 		if (src != CLOCK_INVALID) {
ddc8b9
-			if (clockadj_compare(src, clock->clkid,
ddc8b9
-					     priv->phc_readings,
ddc8b9
-					     &phc_offset, &phc_ts,
ddc8b9
-					     &phc_delay))
ddc8b9
+			err = clockadj_compare(src, clock->clkid,
ddc8b9
+					       priv->phc_readings,
ddc8b9
+					       &phc_offset, &phc_ts,
ddc8b9
+					       &phc_delay);
ddc8b9
+			if (err == -EBUSY)
ddc8b9
+				continue;
ddc8b9
+			if (err)
ddc8b9
 				return -1;
ddc8b9
 
ddc8b9
 			/* Convert the time stamp to the PHC time. */
ddc8b9
@@ -692,6 +696,7 @@ static int do_loop(struct phc2sys_private *priv, int subscriptions)
ddc8b9
 	struct clock *clock;
ddc8b9
 	uint64_t ts;
ddc8b9
 	int64_t offset, delay;
ddc8b9
+	int err;
ddc8b9
 
ddc8b9
 	interval.tv_sec = priv->phc_interval;
ddc8b9
 	interval.tv_nsec = (priv->phc_interval - interval.tv_sec) * 1e9;
ddc8b9
@@ -735,29 +740,32 @@ static int do_loop(struct phc2sys_private *priv, int subscriptions)
ddc8b9
 			if (clock->clkid == CLOCK_REALTIME &&
ddc8b9
 			    priv->master->sysoff_method >= 0) {
ddc8b9
 				/* use sysoff */
ddc8b9
-				if (sysoff_measure(CLOCKID_TO_FD(priv->master->clkid),
ddc8b9
-						   priv->master->sysoff_method,
ddc8b9
-						   priv->phc_readings,
ddc8b9
-						   &offset, &ts, &delay) < 0)
ddc8b9
-					return -1;
ddc8b9
+				err = sysoff_measure(CLOCKID_TO_FD(priv->master->clkid),
ddc8b9
+						     priv->master->sysoff_method,
ddc8b9
+						     priv->phc_readings,
ddc8b9
+						     &offset, &ts, &delay);
ddc8b9
 			} else if (priv->master->clkid == CLOCK_REALTIME &&
ddc8b9
 				   clock->sysoff_method >= 0) {
ddc8b9
 				/* use reversed sysoff */
ddc8b9
-				if (sysoff_measure(CLOCKID_TO_FD(clock->clkid),
ddc8b9
-						   clock->sysoff_method,
ddc8b9
-						   priv->phc_readings,
ddc8b9
-						   &offset, &ts, &delay) < 0)
ddc8b9
-					return -1;
ddc8b9
-				offset = -offset;
ddc8b9
-				ts += offset;
ddc8b9
+				err = sysoff_measure(CLOCKID_TO_FD(clock->clkid),
ddc8b9
+						     clock->sysoff_method,
ddc8b9
+						     priv->phc_readings,
ddc8b9
+						     &offset, &ts, &delay);
ddc8b9
+				if (!err) {
ddc8b9
+					offset = -offset;
ddc8b9
+					ts += offset;
ddc8b9
+				}
ddc8b9
 			} else {
ddc8b9
 				/* use phc */
ddc8b9
-				if (clockadj_compare(priv->master->clkid,
ddc8b9
-						     clock->clkid,
ddc8b9
-						     priv->phc_readings,
ddc8b9
-						     &offset, &ts, &delay))
ddc8b9
-					return -1;
ddc8b9
+				err = clockadj_compare(priv->master->clkid,
ddc8b9
+						       clock->clkid,
ddc8b9
+						       priv->phc_readings,
ddc8b9
+						       &offset, &ts, &delay);
ddc8b9
 			}
ddc8b9
+			if (err == -EBUSY)
ddc8b9
+				continue;
ddc8b9
+			if (err)
ddc8b9
+				return -1;
ddc8b9
 			update_clock(priv, clock, offset, ts, delay);
ddc8b9
 		}
ddc8b9
 	}