From: Vincent Cheng <vincent.cheng...@renesas.com> When clock stepping is unable to happen instantaneously the subsequent timestamps after a clock step does not reflect the step result and undesired clock freq and step adjustments will occur.
When using ts2phc to synchronize timestamping clock using external 1 PPS, it could take up to 1 second for the timestamps to reflect the clock step. step_window, when set, indicates the number of Sync events after a clock step in which the clock servo will not do any frequency or step adjustments. Signed-off-by: Vincent Cheng <vincent.cheng...@renesas.com> Signed-off-by: Richard Cochran <richardcoch...@gmail.com> --- clock.c | 20 ++++++++++++++++++++ config.c | 1 + ptp4l.8 | 8 ++++++++ 3 files changed, 29 insertions(+) diff --git a/clock.c b/clock.c index e6be5fd..c1fcff6 100644 --- a/clock.c +++ b/clock.c @@ -134,6 +134,8 @@ struct clock { struct interface *uds_ro_if; LIST_HEAD(clock_subscribers_head, clock_subscriber) subscribers; struct monitor *slave_event_monitor; + int step_window_counter; + int step_window; }; struct clock the_clock; @@ -1097,6 +1099,7 @@ struct clock *clock_create(enum clock_type type, struct config *config, c->kernel_leap = config_get_int(config, NULL, "kernel_leap"); c->utc_offset = config_get_int(config, NULL, "utc_offset"); c->time_source = config_get_int(config, NULL, "timeSource"); + c->step_window = config_get_int(config, NULL, "step_window"); if (c->free_running) { c->clkid = CLOCK_INVALID; @@ -1748,6 +1751,14 @@ int clock_switch_phc(struct clock *c, int phc_index) return 0; } +static void clock_step_window(struct clock *c) +{ + if (!c->step_window) { + return; + } + c->step_window_counter = c->step_window; +} + static void clock_synchronize_locked(struct clock *c, double adj) { clockadj_set_freq(c->clkid, -adj); @@ -1765,6 +1776,14 @@ enum servo_state clock_synchronize(struct clock *c, tmv_t ingress, tmv_t origin) double adj, weight; int64_t offset; + if (c->step_window_counter) { + c->step_window_counter--; + pr_debug("skip sync after jump %d/%d", + c->step_window - c->step_window_counter, + c->step_window); + return c->servo_state; + } + c->ingress_ts = ingress; tsproc_down_ts(c->tsproc, origin, ingress); @@ -1809,6 +1828,7 @@ enum servo_state clock_synchronize(struct clock *c, tmv_t ingress, tmv_t origin) -tmv_to_nanoseconds(c->master_offset)); } tsproc_reset(c->tsproc, 0); + clock_step_window(c); break; case SERVO_LOCKED: clock_synchronize_locked(c, adj); diff --git a/config.c b/config.c index 341f887..c3deddb 100644 --- a/config.c +++ b/config.c @@ -303,6 +303,7 @@ struct config_item config_tab[] = { GLOB_ITEM_INT("slaveOnly", 0, 0, 1), /*deprecated*/ GLOB_ITEM_INT("socket_priority", 0, 0, 15), GLOB_ITEM_DBL("step_threshold", 0.0, 0.0, DBL_MAX), + GLOB_ITEM_INT("step_window", 0, 0, INT_MAX), GLOB_ITEM_INT("summary_interval", 0, INT_MIN, INT_MAX), PORT_ITEM_INT("syncReceiptTimeout", 0, 0, UINT8_MAX), GLOB_ITEM_INT("tc_spanning_tree", 0, 0, 1), diff --git a/ptp4l.8 b/ptp4l.8 index 0d19171..b04936a 100644 --- a/ptp4l.8 +++ b/ptp4l.8 @@ -705,6 +705,14 @@ one-second offset slowly by changing the clock frequency (unless the option is set to correct such offset by stepping). Relevant only with software time stamping. The default is 1 (enabled). .TP +.B step_window +When set, indicates the number of Sync events after a clock step that +the clock will not do any frequency or step adjustments. +This is used in situations where clock stepping is unable to happen +instantaneously so there is a lag before the timestamps can settle +properly to reflect the clock step. +The default is 0 (disabled). +.TP .B timeSource The time source is a single byte code that gives an idea of the kind of local clock in use. The value is purely informational, having no -- 2.20.1 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel