|
|
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 |
}
|