Now that we are registering a clock even for the PPS master when it supports that (i.e. when it is a PHC), introduce a new API to retrieve its clock in order to add timestamps to it.
The timestamps are a mere approximation. We configure the kernel to emit periodic output and then never hear back from that PHC again. We just assume that it emits periodic output as promised, and that each pulse is emitted at the beginning of each second. We rely on the slaves to report an extts event first, and we know who generated that - the master, of course. So then we proceed to read the master's PHC time, and round that to what is the most plausible integer second in its time base. We believe that to be the 'timestamp'. This is fed into the servo algorithm. The PHC master can be synchronized to the extts events of a PHC slave, when in automatic mode. Signed-off-by: Vladimir Oltean <olte...@gmail.com> --- Changes in v4: Add one more paragraph to commit message. Changes in v3: Implement ts2phc_master_get_clock() as part of ts2phc_master.c instead of ts2phc_phc_master.c. ts2phc.c | 45 ++++++++++++++++++++++++++++++++++++++++- ts2phc_master.c | 8 ++++++++ ts2phc_master.h | 2 ++ ts2phc_master_private.h | 1 + ts2phc_phc_master.c | 9 +++++++++ 5 files changed, 64 insertions(+), 1 deletion(-) diff --git a/ts2phc.c b/ts2phc.c index dbe7bf954943..ce2ceb97888a 100644 --- a/ts2phc.c +++ b/ts2phc.c @@ -482,6 +482,42 @@ static void ts2phc_synchronize_clocks(struct ts2phc_private *priv, int autocfg) } } +static int ts2phc_collect_master_tstamp(struct ts2phc_private *priv) +{ + struct clock *master_clock; + struct timespec master_ts; + int err; + + master_clock = ts2phc_master_get_clock(priv->master); + /* + * Master isn't a PHC (it may be a generic or a GPS master), + * don't error out, just don't do anything. If it doesn't have a PHC, + * there is nothing to synchronize, which is the only point of + * collecting its perout timestamp in the first place. + */ + if (!master_clock) + return 0; + + err = ts2phc_master_getppstime(priv->master, &master_ts); + if (err < 0) { + pr_err("source ts not valid"); + return err; + } + + /* + * As long as the kernel doesn't support a proper API for reporting + * a precise perout timestamp, we'll have to use this crude + * approximation. + */ + if (master_ts.tv_nsec > NS_PER_SEC / 2) + master_ts.tv_sec++; + master_ts.tv_nsec = 0; + + clock_add_tstamp(master_clock, timespec_to_tmv(master_ts)); + + return 0; +} + static void usage(char *progname) { fprintf(stderr, @@ -702,8 +738,15 @@ int main(int argc, char *argv[]) pr_err("poll failed"); break; } - if (err > 0) + if (err > 0) { + err = ts2phc_collect_master_tstamp(&priv); + if (err) { + pr_err("failed to collect master tstamp"); + break; + } + ts2phc_synchronize_clocks(&priv, autocfg); + } } ts2phc_cleanup(&priv); diff --git a/ts2phc_master.c b/ts2phc_master.c index 4617c4aecbe5..0dc02a103859 100644 --- a/ts2phc_master.c +++ b/ts2phc_master.c @@ -38,3 +38,11 @@ int ts2phc_master_getppstime(struct ts2phc_master *master, struct timespec *ts) { return master->getppstime(master, ts); } + +struct clock *ts2phc_master_get_clock(struct ts2phc_master *m) +{ + if (m->get_clock) + return m->get_clock(m); + + return NULL; +} diff --git a/ts2phc_master.h b/ts2phc_master.h index a7e7186f79a1..6edf8c013af9 100644 --- a/ts2phc_master.h +++ b/ts2phc_master.h @@ -51,4 +51,6 @@ void ts2phc_master_destroy(struct ts2phc_master *master); */ int ts2phc_master_getppstime(struct ts2phc_master *master, struct timespec *ts); +struct clock *ts2phc_master_get_clock(struct ts2phc_master *m); + #endif diff --git a/ts2phc_master_private.h b/ts2phc_master_private.h index 463a1f003a21..deef1b520a3f 100644 --- a/ts2phc_master_private.h +++ b/ts2phc_master_private.h @@ -15,6 +15,7 @@ struct ts2phc_master { void (*destroy)(struct ts2phc_master *ts2phc_master); int (*getppstime)(struct ts2phc_master *master, struct timespec *ts); + struct clock *(*get_clock)(struct ts2phc_master *m); }; #endif diff --git a/ts2phc_phc_master.c b/ts2phc_phc_master.c index 1a944a960f18..233c95f5c181 100644 --- a/ts2phc_phc_master.c +++ b/ts2phc_phc_master.c @@ -83,6 +83,14 @@ static int ts2phc_phc_master_getppstime(struct ts2phc_master *m, return clock_gettime(master->clock->clkid, ts); } +struct clock *ts2phc_phc_master_get_clock(struct ts2phc_master *m) +{ + struct ts2phc_phc_master *master = + container_of(m, struct ts2phc_phc_master, master); + + return master->clock; +} + struct ts2phc_master *ts2phc_phc_master_create(struct ts2phc_private *priv, const char *dev) { @@ -94,6 +102,7 @@ struct ts2phc_master *ts2phc_phc_master_create(struct ts2phc_private *priv, } master->master.destroy = ts2phc_phc_master_destroy; master->master.getppstime = ts2phc_phc_master_getppstime; + master->master.get_clock = ts2phc_phc_master_get_clock; master->clock = clock_add(priv, dev); if (!master->clock) { -- 2.25.1 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel