From bbb7479baba6fe58a02aee0898777cbdb0c9005b Mon Sep 17 00:00:00 2001
From: Ramesh Gowda <ramesh.gowda@mavenir.com>
Date: Thu, 12 Oct 2023 15:26:27 +0530
Subject: [PATCH] Problem: Under GNSS error condition/fluctuation, ts2phc
 updating 1sec time into PHC resulting in wrong time. This issue of 1sec jump
 is seen momentarily.

Mar 10 15:17:40 sno-cluster-nrnl04-master1 ts2phc: [161756.611] nmea delay: 89943030 ns
Mar 10 15:17:40 sno-cluster-nrnl04-master1 ts2phc: [161756.611] enp81s0f0 extts index 0 at 1678461497.000000000 corr 0 src 1678461498.844774711 diff -1000000000
Mar 10 15:17:40 sno-cluster-nrnl04-master1 ts2phc: [161756.611] enp81s0f0 master offset -1000000000 s2 freq -100000000
Mar 10 15:17:40 sno-cluster-nrnl04-master1 ts2phc: [161756.612] nmea delay: 89943030 ns
Mar 10 15:17:40 sno-cluster-nrnl04-master1 ts2phc: [161756.612] enp138s0f0 extts index 0 at 1678461497.000000000 corr 0 src 1678461498.845574965 diff -1000000000
Mar 10 15:17:40 sno-cluster-nrnl04-master1 ts2phc: [161756.612] enp138s0f0 master offset -1000000000 s2 freq -100000000

Fix:
Defined new configurable skip count variable.
Under normal condition ts2phc time diff will be around +-1 nsec.
During problem condition ts2phc time diff will be around 1 sec.
With servo in SERVO_LOCKED state and ts2phc time diff is more than 500 millsecond,
will skip update of PHC for configured skip count value.
---
 ts2phc.c       |  3 +++
 ts2phc_slave.c | 23 +++++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/ts2phc.c b/ts2phc.c
index 2342858..5687c9b 100644
--- a/ts2phc.c
+++ b/ts2phc.c
@@ -15,6 +15,8 @@
 #include "ts2phc_slave.h"
 #include "version.h"
 
+int max_phc_update_skip_count;
+
 struct interface {
 	STAILQ_ENTRY(interface) list;
 };
@@ -146,6 +148,7 @@ int main(int argc, char *argv[])
 	print_set_verbose(config_get_int(cfg, NULL, "verbose"));
 	print_set_syslog(config_get_int(cfg, NULL, "use_syslog"));
 	print_set_level(config_get_int(cfg, NULL, "logging_level"));
+	max_phc_update_skip_count = config_get_int(cfg, NULL, "max_phc_update_skip_cnt");
 
 	STAILQ_FOREACH(iface, &cfg->interfaces, list) {
 		if (1 == config_get_int(cfg, interface_name(iface), "ts2phc.master")) {
diff --git a/ts2phc_slave.c b/ts2phc_slave.c
index 749efe5..6af1aeb 100644
--- a/ts2phc_slave.c
+++ b/ts2phc_slave.c
@@ -29,6 +29,8 @@
 #define SAMPLE_WEIGHT		1.0
 #define SERVO_SYNC_INTERVAL	1.0
 
+extern int max_phc_update_skip_count;
+
 struct ts2phc_slave {
 	char *name;
 	STAILQ_ENTRY(ts2phc_slave) list;
@@ -42,6 +44,8 @@ struct ts2phc_slave {
 	clockid_t clk;
 	int no_adj;
 	int fd;
+	int max_offset_skip_count;
+	int current_offset_skip_count;
 };
 
 struct ts2phc_slave_array {
@@ -219,6 +223,10 @@ static struct ts2phc_slave *ts2phc_slave_create(struct config *cfg, const char *
 		goto no_ext_ts;
 	}
 
+	slave->max_offset_skip_count = max_phc_update_skip_count;
+	slave->current_offset_skip_count = 0;
+	pr_debug("PHC slave %s has skip cnt %d", device, slave->max_offset_skip_count);
+
 	return slave;
 no_ext_ts:
 no_pin_func:
@@ -278,6 +286,17 @@ static int ts2phc_slave_event(struct ts2phc_slave *slave,
 	adj = servo_sample(slave->servo, offset, extts_ts,
 			   SAMPLE_WEIGHT, &slave->state);
 
+	if ((slave->state == SERVO_LOCKED) || (slave->state == SERVO_LOCKED_STABLE)) {
+		if (llabs(offset) >= NS_PER_SEC / 2) {
+			if (slave->current_offset_skip_count < slave->max_offset_skip_count) {
+				pr_debug("Skip current PHC update %s offset %10" PRId64 " s%d freq %+7.0f",
+					slave->name, offset, slave->state, adj);
+				slave->current_offset_skip_count++;
+				return 0;
+			}
+		}
+	}
+
 	pr_debug("%s master offset %10" PRId64 " s%d freq %+7.0f",
 		 slave->name, offset, slave->state, adj);
 
@@ -290,6 +309,10 @@ static int ts2phc_slave_event(struct ts2phc_slave *slave,
 		break;
 	case SERVO_LOCKED:
 	case SERVO_LOCKED_STABLE:
+		if (llabs(offset) < 500) {
+			slave->current_offset_skip_count = 0;
+		}
+
 		clockadj_set_freq(slave->clk, -adj);
 		break;
 	}
-- 
2.20.1

