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