150 lines
5.3 KiB
Diff
150 lines
5.3 KiB
Diff
commit f20e568cb2bf3b0ea6105e5624409f02fb9aa2bc
|
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
|
Date: Thu Jan 9 15:46:05 2025 +0100
|
|
|
|
ts2phc: Add option for external reference in automatic mode.
|
|
|
|
ts2phc running in the automatic mode assumes that the PPS source is one
|
|
of the PHCs used by ptp4l. That doesn't always have to be the case. Add
|
|
"external_pps" option to use the non-automatic-mode reading of the
|
|
source timestamp and don't mark sink clocks as targets if they are
|
|
synchronized by ptp4l.
|
|
|
|
The use case is holdover with an externally controlled stabilized clock.
|
|
The clock is synchronized by an external process to the PHC when it's
|
|
synchronized by ptp4l and the PHC is synchronized to the external clock
|
|
by ts2phc when not synchronized by ptp4l. Multiple PHCs can be connected
|
|
to the external clock to make a JBOD boundary clock.
|
|
|
|
Don't require the PHC that is synchronized by ptp4l to be receiving the
|
|
PPS signal (providing timestamps) to make it possible to switch the PPS
|
|
direction to synchronize the external clock if there is only one
|
|
usable channel.
|
|
|
|
(This is a RHEL-specific downstream patch using "ts2phc.rh_external_pps"
|
|
name for the option to make it clear it's considered experimental.)
|
|
|
|
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
|
|
|
diff --git a/config.c b/config.c
|
|
index cbff976..fedc3a0 100644
|
|
--- a/config.c
|
|
+++ b/config.c
|
|
@@ -368,6 +368,7 @@ struct config_item config_tab[] = {
|
|
GLOB_ITEM_ENU("time_stamping", TS_HARDWARE, timestamping_enu),
|
|
PORT_ITEM_INT("transportSpecific", 0, 0, 0x0F),
|
|
PORT_ITEM_INT("ts2phc.channel", 0, 0, INT_MAX),
|
|
+ GLOB_ITEM_INT("ts2phc.rh_external_pps", 0, 0, 1),
|
|
PORT_ITEM_INT("ts2phc.extts_correction", 0, INT_MIN, INT_MAX),
|
|
PORT_ITEM_ENU("ts2phc.extts_polarity", PTP_RISING_EDGE, extts_polarity_enu),
|
|
PORT_ITEM_INT("ts2phc.holdover", 0, 0, INT_MAX),
|
|
diff --git a/ts2phc.8 b/ts2phc.8
|
|
index f17ed71..d57402c 100644
|
|
--- a/ts2phc.8
|
|
+++ b/ts2phc.8
|
|
@@ -287,6 +287,20 @@ the SERVO_LOCKED_STABLE state. The servo state needs be enabled by the
|
|
\fB-a\fP option and when \fBts2phc.extts_polarity\fP is set to \fIboth\fP.
|
|
The default is 0 (disabled).
|
|
|
|
+.TP
|
|
+.B ts2phc.rh_external_pps
|
|
+This is a RHEL-specific experimental option which can be renamed,
|
|
+removed, or the functionality changed, in a future minor update.
|
|
+
|
|
+It enables an external reference with the \fB-a\fP option. If set to 1, ts2phc
|
|
+will assume the source of the PPS signal is a different clock from the PHCs
|
|
+used by ptp4l (configured with the \fBboundary_clock_jbod\fP option). The use
|
|
+case is a holdover using an externally controlled stabilized clock, which is
|
|
+expected to be synchronized to the PHC that is synchronized by ptp4l, and
|
|
+running free when ptp4l is not synchronizing any of the PHCs. Note that it is a
|
|
+different holdover than the one enabled by the \fBts2phc.holdover\fP option
|
|
+below. The default is 0 (disabled).
|
|
+
|
|
.TP
|
|
.B ts2phc.nmea_delay
|
|
Specifies the minimum expected delay of NMEA RMC messages in nanoseconds.
|
|
diff --git a/ts2phc.c b/ts2phc.c
|
|
index 39d31b6..5448496 100644
|
|
--- a/ts2phc.c
|
|
+++ b/ts2phc.c
|
|
@@ -348,18 +348,26 @@ static void ts2phc_reconfigure(struct ts2phc_private *priv)
|
|
}
|
|
num_target_clocks++;
|
|
break;
|
|
- case PS_UNCALIBRATED:
|
|
- num_ref_clocks++;
|
|
- break;
|
|
case PS_SLAVE:
|
|
ref_clk = c;
|
|
+ /* Fall through */
|
|
+ case PS_UNCALIBRATED:
|
|
num_ref_clocks++;
|
|
+ if (priv->external_pps && c->is_target) {
|
|
+ pr_info("unselecting %s for synchronization",
|
|
+ c->name);
|
|
+ c->is_target = false;
|
|
+ }
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
last = c;
|
|
}
|
|
+ if (priv->external_pps) {
|
|
+ pr_info("assuming external reference clock");
|
|
+ return;
|
|
+ }
|
|
if (num_target_clocks >= 1 && !ref_clk) {
|
|
priv->ref_clock = last;
|
|
priv->ref_clock->is_target = false;
|
|
@@ -447,7 +455,7 @@ static void ts2phc_synchronize_clocks(struct ts2phc_private *priv, int autocfg)
|
|
struct ts2phc_clock *c;
|
|
int holdover, valid;
|
|
|
|
- if (autocfg) {
|
|
+ if (autocfg && !priv->external_pps) {
|
|
if (!priv->ref_clock) {
|
|
pr_debug("no reference clock, skipping");
|
|
return;
|
|
@@ -787,6 +795,8 @@ int main(int argc, char *argv[])
|
|
return -1;
|
|
}
|
|
|
|
+ priv.external_pps = config_get_int(cfg, NULL, "ts2phc.rh_external_pps");
|
|
+
|
|
priv.holdover_length = config_get_int(cfg, NULL, "ts2phc.holdover");
|
|
priv.holdover_start = 0;
|
|
|
|
diff --git a/ts2phc.h b/ts2phc.h
|
|
index 5dbde9b..63e6122 100644
|
|
--- a/ts2phc.h
|
|
+++ b/ts2phc.h
|
|
@@ -52,6 +52,7 @@ struct ts2phc_private {
|
|
struct config *cfg;
|
|
struct pmc_agent *agent;
|
|
struct ts2phc_clock *ref_clock;
|
|
+ bool external_pps;
|
|
bool state_changed;
|
|
LIST_HEAD(port_head, ts2phc_port) ports;
|
|
LIST_HEAD(clock_head, ts2phc_clock) clocks;
|
|
diff --git a/ts2phc_pps_sink.c b/ts2phc_pps_sink.c
|
|
index af34e39..9076de9 100644
|
|
--- a/ts2phc_pps_sink.c
|
|
+++ b/ts2phc_pps_sink.c
|
|
@@ -441,6 +441,15 @@ int ts2phc_pps_sink_poll(struct ts2phc_private *priv)
|
|
all_sinks_have_events = true;
|
|
|
|
for (i = 0; i < priv->n_sinks; i++) {
|
|
+ /*
|
|
+ * In the external PPS mode don't require non-target
|
|
+ * clocks to be receiving PPS to allow switching the
|
|
+ * PPS direction to synchronize the external clock.
|
|
+ */
|
|
+ if (priv->external_pps &&
|
|
+ !polling_array->sink[i]->clock->is_target)
|
|
+ continue;
|
|
+
|
|
if (!polling_array->collected_events[i]) {
|
|
all_sinks_have_events = false;
|
|
break;
|