diff --git a/src/freerun/sfptpd_freerun_module.c b/src/freerun/sfptpd_freerun_module.c index 5658d841..ed0bbe89 100644 --- a/src/freerun/sfptpd_freerun_module.c +++ b/src/freerun/sfptpd_freerun_module.c @@ -435,7 +435,8 @@ static int freerun_select_clock(freerun_module_t *fr, /* Set the NIC clock based on the system clock to ensure it has a sensible initial value */ - rc = sfptpd_clock_set_time(instance->clock, system_clock, NULL); + rc = sfptpd_clock_set_time(instance->clock, system_clock, NULL, true); + if (rc != 0) { TRACE_L4("freerun %s: failed to compare and set clock %s to system clock, error %s\n", SFPTPD_CONFIG_GET_NAME(config), diff --git a/src/include/sfptpd_clock.h b/src/include/sfptpd_clock.h index 12206c95..c6b21558 100644 --- a/src/include/sfptpd_clock.h +++ b/src/include/sfptpd_clock.h @@ -395,11 +395,14 @@ int sfptpd_clock_compare(struct sfptpd_clock *clock1, struct sfptpd_clock *clock * @param clock_from Pointer to the clock to use as a reference * @param threshold A threshold which below which the clock difference * should not trigger an adjustment or NULL. + * @param is_initial_correction This is an initial clock correction + * and should not be repeated if already done. * @return 0 for success otherwise an errno status code. */ int sfptpd_clock_set_time(struct sfptpd_clock *clock_to, struct sfptpd_clock *clock_from, - const struct sfptpd_timespec *threshold); + const struct sfptpd_timespec *threshold, + bool is_initial_correction); /** Report the sync status to the NIC associated with the clock. This is used * by the NIC firmware to report the sync status to other interested parties diff --git a/src/ptp/ptpd2/protocol.c b/src/ptp/ptpd2/protocol.c index b52aa046..c52444d8 100644 --- a/src/ptp/ptpd2/protocol.c +++ b/src/ptp/ptpd2/protocol.c @@ -528,7 +528,7 @@ doInitPort(RunTimeOpts *rtOpts, PtpClock *ptpClock) /* If using a NIC clock and we are in a PTP master mode then step the * NIC clock to the current system time. */ if ((ptpClock->clock != system_clock) && !ptpClock->rtOpts.slaveOnly) { - rc = sfptpd_clock_set_time(ptpClock->clock, system_clock, NULL); + rc = sfptpd_clock_set_time(ptpClock->clock, system_clock, NULL, true); if (rc != 0) { TRACE_L4("ptp: failed to compare and set clock %s to system clock, %s\n", sfptpd_clock_get_short_name(ptpClock->clock), diff --git a/src/sfptpd_clock.c b/src/sfptpd_clock.c index 548c8925..6d26637d 100644 --- a/src/sfptpd_clock.c +++ b/src/sfptpd_clock.c @@ -234,11 +234,14 @@ struct sfptpd_clock { struct sfptpd_clock_nic nic; } u; - bool cfg_non_sfc_nics; - bool cfg_avoid_efx; - bool cfg_rtc_adjust; - - bool lrc_been_locked; + /* Config options copied into state for convenience */ + bool cfg_non_sfc_nics:1; + bool cfg_avoid_efx:1; + bool cfg_rtc_adjust:1; + + /* Status flags */ + bool lrc_been_locked:1; + bool initial_correction_applied:1; }; @@ -2145,12 +2148,14 @@ int sfptpd_clock_compare(struct sfptpd_clock *clock1, struct sfptpd_clock *clock int sfptpd_clock_set_time(struct sfptpd_clock *clock_to, struct sfptpd_clock *clock_from, - const struct sfptpd_timespec *threshold) + const struct sfptpd_timespec *threshold, + bool is_initial_correction) { struct sfptpd_timespec diff; int rc; - if (clock_to == clock_from) + if (clock_to == clock_from || + clock_to->initial_correction_applied) return 0; clock_lock(); @@ -2166,8 +2171,11 @@ int sfptpd_clock_set_time(struct sfptpd_clock *clock_to, if (rc == 0 && (threshold == NULL || - sfptpd_time_cmp(&diff, threshold) >= 0)) + sfptpd_time_cmp(&diff, threshold) >= 0)) { rc = sfptpd_clock_adjust_time(clock_to, &diff); + if (rc == 0 && is_initial_correction) + clock_to->initial_correction_applied = true; + } clock_unlock(); return rc; @@ -2349,7 +2357,7 @@ void sfptpd_clock_correct_new(struct sfptpd_clock *clock) if (time.sec < SFPTPD_NIC_TIME_VALID_THRESHOLD || gconf->initial_clock_correction == SFPTPD_CLOCK_INITIAL_CORRECTION_ALWAYS) { - sfptpd_clock_set_time(clock, sfptpd_clock_system, NULL); + sfptpd_clock_set_time(clock, sfptpd_clock_system, NULL, true); } } }