handle missing pulses in ts2phc (RHEL-112193)

Resolves: RHEL-112193
This commit is contained in:
Miroslav Lichvar 2025-09-01 16:12:26 +02:00
parent bfa8bed97e
commit 699f7b12f6
2 changed files with 81 additions and 0 deletions

79
linuxptp-ppsmiss.patch Normal file
View File

@ -0,0 +1,79 @@
commit 4e172c83520852d41e5c2ec3ae324d50c42a0416
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Aug 28 15:14:01 2025 +0200
ts2phc: Better handle missing pulses with multiple sinks.
The ts2phc_pps_sink_poll() function waits until it has collected pulses
for all active sinks, or a timeout of 2 seconds between events is
reached.
If a sink missed a pulse (e.g. after a port state change and switching
PPS signal direction in the external PPS mode) and the next pulse of
that sink came before pulses of the other sinks, it was mixed with
events of the previous pulse and the measured offset had an error of
1/rate seconds.
To avoid mixing events corresponding to different pulses, adjust the
poll() timeout so that it waits only up to a third of the pulse period
after the first received event.
(Rebased to 4.4)
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/ts2phc_pps_sink.c b/ts2phc_pps_sink.c
index 9076de9..72d8ea4 100644
--- a/ts2phc_pps_sink.c
+++ b/ts2phc_pps_sink.c
@@ -381,10 +381,11 @@ void ts2phc_pps_sink_cleanup(struct ts2phc_private *priv)
int ts2phc_pps_sink_poll(struct ts2phc_private *priv)
{
struct ts2phc_sink_array *polling_array = priv->polling_array;
+ bool first_poll = true, ignore_any = false;
bool all_sinks_have_events = false;
- bool ignore_any = false;
+ struct timespec first_ts = {0}, ts;
+ int cnt, timeout;
unsigned int i;
- int cnt;
for (i = 0; i < priv->n_sinks; i++)
polling_array->collected_events[i] = 0;
@@ -395,7 +396,22 @@ int ts2phc_pps_sink_poll(struct ts2phc_private *priv)
if (!is_running())
return 0;
- cnt = poll(polling_array->pfd, priv->n_sinks, 2000);
+ /*
+ * Collect only events within a third of the pulse period to
+ * avoid mixing events corresponding to different pulses.
+ */
+ if (first_poll) {
+ timeout = 2000;
+ } else {
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ timeout = 333;
+ timeout -= (ts.tv_sec - first_ts.tv_sec) * 1000 +
+ (ts.tv_nsec - first_ts.tv_nsec) / 1000000;
+ if (timeout < 0)
+ timeout = 0;
+ }
+
+ cnt = poll(polling_array->pfd, priv->n_sinks, timeout);
if (cnt < 0) {
if (errno == EINTR) {
return 0;
@@ -408,6 +424,11 @@ int ts2phc_pps_sink_poll(struct ts2phc_private *priv)
return 0;
}
+ if (first_poll) {
+ clock_gettime(CLOCK_MONOTONIC, &first_ts);
+ first_poll = false;
+ }
+
for (i = 0; i < priv->n_sinks; i++) {
if (polling_array->pfd[i].revents & POLLERR) {
sink = polling_array->sink[i];

View File

@ -43,6 +43,8 @@ Patch10: linuxptp-rtnlinit.patch
Patch11: linuxptp-unirecover.patch
# check for EL-specific kernels with vclock support
Patch12: linuxptp-vclock.patch
# handle missing pulses in ts2phc
Patch13: linuxptp-ppsmiss.patch
BuildRequires: gcc gcc-c++ gnutls-devel make systemd