The ts2phc program will introduce clock synchronization which is orthogonal to the direction in which PPS is emitted (from the master to the slave).
To have a more consistent terminology, we can avoid using the ultra-generic term "slave" and replace it with "PPS sink", which describes the role of the data structure in the new interpretation of the program in a much clearer way. Signed-off-by: Vladimir Oltean <olte...@gmail.com> --- v4->v5: patch is new ts2phc.c | 24 ++--- ts2phc_pps_sink.c | 255 +++++++++++++++++++++++----------------------- ts2phc_pps_sink.h | 12 +-- 3 files changed, 146 insertions(+), 145 deletions(-) diff --git a/ts2phc.c b/ts2phc.c index 8f2039085812..812ac78b4875 100644 --- a/ts2phc.c +++ b/ts2phc.c @@ -21,7 +21,7 @@ struct interface { static void ts2phc_cleanup(struct config *cfg, struct ts2phc_master *master) { - ts2phc_slave_cleanup(); + ts2phc_pps_sink_cleanup(); if (master) { ts2phc_master_destroy(master); } @@ -55,7 +55,7 @@ static void usage(char *progname) int main(int argc, char *argv[]) { - int c, err = 0, have_slave = 0, index, print_level; + int c, err = 0, have_sink = 0, index, print_level; struct ts2phc_master *master = NULL; enum ts2phc_master_type pps_type; char *config = NULL, *progname; @@ -87,11 +87,11 @@ int main(int argc, char *argv[]) break; case 'c': if (!config_create_interface(optarg, cfg)) { - fprintf(stderr, "failed to add slave\n"); + fprintf(stderr, "failed to add PPS sink\n"); ts2phc_cleanup(cfg, master); return -1; } - have_slave = 1; + have_sink = 1; break; case 'f': config = optarg; @@ -156,16 +156,16 @@ int main(int argc, char *argv[]) } pps_source = interface_name(iface); } else { - if (ts2phc_slave_add(cfg, interface_name(iface))) { - fprintf(stderr, "failed to add slave\n"); + if (ts2phc_pps_sink_add(cfg, interface_name(iface))) { + fprintf(stderr, "failed to add PPS sink\n"); ts2phc_cleanup(cfg, master); return -1; } - have_slave = 1; + have_sink = 1; } } - if (!have_slave) { - fprintf(stderr, "no slave clocks specified\n"); + if (!have_sink) { + fprintf(stderr, "no PPS sinks specified\n"); ts2phc_cleanup(cfg, master); usage(progname); return -1; @@ -176,8 +176,8 @@ int main(int argc, char *argv[]) usage(progname); return -1; } - if (ts2phc_slave_arm()) { - fprintf(stderr, "failed to arm slaves\n"); + if (ts2phc_pps_sink_arm()) { + fprintf(stderr, "failed to arm PPS sinks\n"); ts2phc_cleanup(cfg, master); return -1; } @@ -197,7 +197,7 @@ int main(int argc, char *argv[]) } while (is_running()) { - err = ts2phc_slave_poll(master); + err = ts2phc_pps_sink_poll(master); if (err) { pr_err("poll failed"); break; diff --git a/ts2phc_pps_sink.c b/ts2phc_pps_sink.c index a2245e62d58c..7da850c718eb 100644 --- a/ts2phc_pps_sink.c +++ b/ts2phc_pps_sink.c @@ -1,5 +1,5 @@ /** - * @file ts2phc_slave.c + * @file ts2phc_pps_sink.c * @brief Utility program to synchronize the PHC clock to external events * @note Copyright (C) 2019 Balint Ferencz <fer...@sch.bme.hu> * @note SPDX-License-Identifier: GPL-2.0+ @@ -29,9 +29,9 @@ #define SAMPLE_WEIGHT 1.0 #define SERVO_SYNC_INTERVAL 1.0 -struct ts2phc_slave { +struct ts2phc_pps_sink { char *name; - STAILQ_ENTRY(ts2phc_slave) list; + STAILQ_ENTRY(ts2phc_pps_sink) list; struct ptp_pin_desc pin_desc; enum servo_state state; unsigned int polarity; @@ -44,8 +44,8 @@ struct ts2phc_slave { int fd; }; -struct ts2phc_slave_array { - struct ts2phc_slave **slave; +struct ts2phc_sink_array { + struct ts2phc_pps_sink **sink; struct pollfd *pfd; } polling_array; @@ -60,61 +60,61 @@ enum extts_result { EXTTS_IGNORE = 1, }; -static enum extts_result ts2phc_slave_offset(struct ts2phc_slave *slave, - struct ts2phc_source_timestamp ts, - int64_t *offset, - uint64_t *local_ts); +static enum extts_result +ts2phc_pps_sink_offset(struct ts2phc_pps_sink *sink, + struct ts2phc_source_timestamp ts, + int64_t *offset, uint64_t *local_ts); -static STAILQ_HEAD(slave_ifaces_head, ts2phc_slave) ts2phc_slaves = - STAILQ_HEAD_INITIALIZER(ts2phc_slaves); +static STAILQ_HEAD(pps_sink_ifaces_head, ts2phc_pps_sink) ts2phc_sinks = + STAILQ_HEAD_INITIALIZER(ts2phc_sinks); -static unsigned int ts2phc_n_slaves; +static unsigned int ts2phc_n_sinks; -static int ts2phc_slave_array_create(void) +static int ts2phc_pps_sink_array_create(void) { - struct ts2phc_slave *slave; + struct ts2phc_pps_sink *sink; unsigned int i; - if (polling_array.slave) { + if (polling_array.sink) { return 0; } - polling_array.slave = malloc(ts2phc_n_slaves * sizeof(*polling_array.slave)); - if (!polling_array.slave) { + polling_array.sink = malloc(ts2phc_n_sinks * sizeof(*polling_array.sink)); + if (!polling_array.sink) { pr_err("low memory"); return -1; } - polling_array.pfd = malloc(ts2phc_n_slaves * sizeof(*polling_array.pfd)); + polling_array.pfd = malloc(ts2phc_n_sinks * sizeof(*polling_array.pfd)); if (!polling_array.pfd) { pr_err("low memory"); - free(polling_array.slave); - polling_array.slave = NULL; + free(polling_array.sink); + polling_array.sink = NULL; return -1; } i = 0; - STAILQ_FOREACH(slave, &ts2phc_slaves, list) { - polling_array.slave[i] = slave; + STAILQ_FOREACH(sink, &ts2phc_sinks, list) { + polling_array.sink[i] = sink; i++; } - for (i = 0; i < ts2phc_n_slaves; i++) { + for (i = 0; i < ts2phc_n_sinks; i++) { polling_array.pfd[i].events = POLLIN | POLLPRI; - polling_array.pfd[i].fd = polling_array.slave[i]->fd; + polling_array.pfd[i].fd = polling_array.sink[i]->fd; } return 0; } -static void ts2phc_slave_array_destroy(void) +static void ts2phc_pps_sink_array_destroy(void) { - free(polling_array.slave); + free(polling_array.sink); free(polling_array.pfd); - polling_array.slave = NULL; + polling_array.sink = NULL; polling_array.pfd = NULL; } -static int ts2phc_slave_clear_fifo(struct ts2phc_slave *slave) +static int ts2phc_pps_sink_clear_fifo(struct ts2phc_pps_sink *sink) { struct pollfd pfd = { .events = POLLIN | POLLPRI, - .fd = slave->fd, + .fd = sink->fd, }; struct ptp_extts_event event; int cnt, size; @@ -137,69 +137,70 @@ static int ts2phc_slave_clear_fifo(struct ts2phc_slave *slave) return -1; } pr_debug("%s SKIP extts index %u at %lld.%09u", - slave->name, event.index, event.t.sec, event.t.nsec); + sink->name, event.index, event.t.sec, event.t.nsec); } return 0; } -static struct ts2phc_slave *ts2phc_slave_create(struct config *cfg, const char *device) +static struct ts2phc_pps_sink *ts2phc_pps_sink_create(struct config *cfg, + const char *device) { enum servo_type servo = config_get_int(cfg, NULL, "clock_servo"); int err, fadj, junk, max_adj, pulsewidth; struct ptp_extts_request extts; - struct ts2phc_slave *slave; + struct ts2phc_pps_sink *sink; - slave = calloc(1, sizeof(*slave)); - if (!slave) { + sink = calloc(1, sizeof(*sink)); + if (!sink) { pr_err("low memory"); return NULL; } - slave->name = strdup(device); - if (!slave->name) { + sink->name = strdup(device); + if (!sink->name) { pr_err("low memory"); - free(slave); + free(sink); return NULL; } - slave->pin_desc.index = config_get_int(cfg, device, "ts2phc.pin_index"); - slave->pin_desc.func = PTP_PF_EXTTS; - slave->pin_desc.chan = config_get_int(cfg, device, "ts2phc.channel"); - slave->polarity = config_get_int(cfg, device, "ts2phc.extts_polarity"); - slave->correction = config_get_int(cfg, device, "ts2phc.extts_correction"); + sink->pin_desc.index = config_get_int(cfg, device, "ts2phc.pin_index"); + sink->pin_desc.func = PTP_PF_EXTTS; + sink->pin_desc.chan = config_get_int(cfg, device, "ts2phc.channel"); + sink->polarity = config_get_int(cfg, device, "ts2phc.extts_polarity"); + sink->correction = config_get_int(cfg, device, "ts2phc.extts_correction"); pulsewidth = config_get_int(cfg, device, "ts2phc.pulsewidth"); pulsewidth /= 2; - slave->ignore_upper = 1000000000 - pulsewidth; - slave->ignore_lower = pulsewidth; + sink->ignore_upper = 1000000000 - pulsewidth; + sink->ignore_lower = pulsewidth; - slave->clk = posix_clock_open(device, &junk); - if (slave->clk == CLOCK_INVALID) { + sink->clk = posix_clock_open(device, &junk); + if (sink->clk == CLOCK_INVALID) { pr_err("failed to open clock"); goto no_posix_clock; } - slave->no_adj = config_get_int(cfg, NULL, "free_running"); - slave->fd = CLOCKID_TO_FD(slave->clk); + sink->no_adj = config_get_int(cfg, NULL, "free_running"); + sink->fd = CLOCKID_TO_FD(sink->clk); - pr_debug("PHC slave %s has ptp index %d", device, junk); + pr_debug("PPS sink %s has ptp index %d", device, junk); - fadj = (int) clockadj_get_freq(slave->clk); + fadj = (int) clockadj_get_freq(sink->clk); /* Due to a bug in older kernels, the reading may silently fail and return 0. Set the frequency back to make sure fadj is the actual frequency of the clock. */ - if (!slave->no_adj) { - clockadj_set_freq(slave->clk, fadj); + if (!sink->no_adj) { + clockadj_set_freq(sink->clk, fadj); } - max_adj = phc_max_adj(slave->clk); + max_adj = phc_max_adj(sink->clk); - slave->servo = servo_create(cfg, servo, -fadj, max_adj, 0); - if (!slave->servo) { + sink->servo = servo_create(cfg, servo, -fadj, max_adj, 0); + if (!sink->servo) { pr_err("failed to create servo"); goto no_servo; } - servo_sync_interval(slave->servo, SERVO_SYNC_INTERVAL); + servo_sync_interval(sink->servo, SERVO_SYNC_INTERVAL); - if (phc_number_pins(slave->clk) > 0) { - err = phc_pin_setfunc(slave->clk, &slave->pin_desc); + if (phc_number_pins(sink->clk) > 0) { + err = phc_pin_setfunc(sink->clk, &sink->pin_desc); if (err < 0) { pr_err("PTP_PIN_SETFUNC request failed"); goto no_pin_func; @@ -211,52 +212,52 @@ static struct ts2phc_slave *ts2phc_slave_create(struct config *cfg, const char * * time stamps. */ memset(&extts, 0, sizeof(extts)); - extts.index = slave->pin_desc.chan; + extts.index = sink->pin_desc.chan; extts.flags = 0; - if (ioctl(slave->fd, PTP_EXTTS_REQUEST2, &extts)) { + if (ioctl(sink->fd, PTP_EXTTS_REQUEST2, &extts)) { pr_err(PTP_EXTTS_REQUEST_FAILED); } - if (ts2phc_slave_clear_fifo(slave)) { + if (ts2phc_pps_sink_clear_fifo(sink)) { goto no_ext_ts; } - return slave; + return sink; no_ext_ts: no_pin_func: - servo_destroy(slave->servo); + servo_destroy(sink->servo); no_servo: - posix_clock_close(slave->clk); + posix_clock_close(sink->clk); no_posix_clock: - free(slave->name); - free(slave); + free(sink->name); + free(sink); return NULL; } -static void ts2phc_slave_destroy(struct ts2phc_slave *slave) +static void ts2phc_pps_sink_destroy(struct ts2phc_pps_sink *sink) { struct ptp_extts_request extts; memset(&extts, 0, sizeof(extts)); - extts.index = slave->pin_desc.chan; + extts.index = sink->pin_desc.chan; extts.flags = 0; - if (ioctl(slave->fd, PTP_EXTTS_REQUEST2, &extts)) { + if (ioctl(sink->fd, PTP_EXTTS_REQUEST2, &extts)) { pr_err(PTP_EXTTS_REQUEST_FAILED); } - servo_destroy(slave->servo); - posix_clock_close(slave->clk); - free(slave->name); - free(slave); + servo_destroy(sink->servo); + posix_clock_close(sink->clk); + free(sink->name); + free(sink); } -static int ts2phc_slave_event(struct ts2phc_slave *slave, - struct ts2phc_source_timestamp source_ts) +static int ts2phc_pps_sink_event(struct ts2phc_pps_sink *sink, + struct ts2phc_source_timestamp source_ts) { enum extts_result result; uint64_t extts_ts; int64_t offset; double adj; - result = ts2phc_slave_offset(slave, source_ts, &offset, &extts_ts); + result = ts2phc_pps_sink_offset(sink, source_ts, &offset, &extts_ts); switch (result) { case EXTTS_ERROR: return -1; @@ -266,65 +267,65 @@ static int ts2phc_slave_event(struct ts2phc_slave *slave, return 0; } - if (slave->no_adj) { - pr_info("%s master offset %10" PRId64, slave->name, offset); + if (sink->no_adj) { + pr_info("%s master offset %10" PRId64, sink->name, offset); return 0; } if (!source_ts.valid) { - pr_debug("%s ignoring invalid master time stamp", slave->name); + pr_debug("%s ignoring invalid master time stamp", sink->name); return 0; } - adj = servo_sample(slave->servo, offset, extts_ts, - SAMPLE_WEIGHT, &slave->state); + adj = servo_sample(sink->servo, offset, extts_ts, + SAMPLE_WEIGHT, &sink->state); pr_debug("%s master offset %10" PRId64 " s%d freq %+7.0f", - slave->name, offset, slave->state, adj); + sink->name, offset, sink->state, adj); - switch (slave->state) { + switch (sink->state) { case SERVO_UNLOCKED: break; case SERVO_JUMP: - clockadj_set_freq(slave->clk, -adj); - clockadj_step(slave->clk, -offset); + clockadj_set_freq(sink->clk, -adj); + clockadj_step(sink->clk, -offset); break; case SERVO_LOCKED: case SERVO_LOCKED_STABLE: - clockadj_set_freq(slave->clk, -adj); + clockadj_set_freq(sink->clk, -adj); break; } return 0; } -static enum extts_result ts2phc_slave_offset(struct ts2phc_slave *slave, - struct ts2phc_source_timestamp src, - int64_t *offset, - uint64_t *local_ts) +static enum extts_result +ts2phc_pps_sink_offset(struct ts2phc_pps_sink *sink, + struct ts2phc_source_timestamp src, + int64_t *offset, uint64_t *local_ts) { struct timespec source_ts = src.ts; struct ptp_extts_event event; uint64_t event_ns, source_ns; int cnt; - cnt = read(slave->fd, &event, sizeof(event)); + cnt = read(sink->fd, &event, sizeof(event)); if (cnt != sizeof(event)) { pr_err("read extts event failed: %m"); return EXTTS_ERROR; } - if (event.index != slave->pin_desc.chan) { + if (event.index != sink->pin_desc.chan) { pr_err("extts on unexpected channel"); return EXTTS_ERROR; } event_ns = event.t.sec * NS_PER_SEC; event_ns += event.t.nsec; - if (slave->polarity == (PTP_RISING_EDGE | PTP_FALLING_EDGE) && - source_ts.tv_nsec > slave->ignore_lower && - source_ts.tv_nsec < slave->ignore_upper) { + if (sink->polarity == (PTP_RISING_EDGE | PTP_FALLING_EDGE) && + source_ts.tv_nsec > sink->ignore_lower && + source_ts.tv_nsec < sink->ignore_upper) { pr_debug("%s SKIP extts index %u at %lld.%09u src %" PRIi64 ".%ld", - slave->name, event.index, event.t.sec, event.t.nsec, + sink->name, event.index, event.t.sec, event.t.nsec, (int64_t) source_ts.tv_sec, source_ts.tv_nsec); return EXTTS_IGNORE; @@ -333,13 +334,13 @@ static enum extts_result ts2phc_slave_offset(struct ts2phc_slave *slave, source_ts.tv_sec++; } source_ns = source_ts.tv_sec * NS_PER_SEC; - *offset = event_ns + slave->correction - source_ns; - *local_ts = event_ns + slave->correction; + *offset = event_ns + sink->correction - source_ns; + *local_ts = event_ns + sink->correction; pr_debug("%s extts index %u at %lld.%09u corr %d src %" PRIi64 ".%ld diff %" PRId64, - slave->name, event.index, event.t.sec, event.t.nsec, - slave->correction, + sink->name, event.index, event.t.sec, event.t.nsec, + sink->correction, (int64_t) source_ts.tv_sec, source_ts.tv_nsec, *offset); return EXTTS_OK; @@ -347,39 +348,39 @@ static enum extts_result ts2phc_slave_offset(struct ts2phc_slave *slave, /* public methods */ -int ts2phc_slave_add(struct config *cfg, const char *name) +int ts2phc_pps_sink_add(struct config *cfg, const char *name) { - struct ts2phc_slave *slave; + struct ts2phc_pps_sink *sink; /* Create each interface only once. */ - STAILQ_FOREACH(slave, &ts2phc_slaves, list) { - if (0 == strcmp(name, slave->name)) { + STAILQ_FOREACH(sink, &ts2phc_sinks, list) { + if (0 == strcmp(name, sink->name)) { return 0; } } - slave = ts2phc_slave_create(cfg, name); - if (!slave) { - pr_err("failed to create slave"); + sink = ts2phc_pps_sink_create(cfg, name); + if (!sink) { + pr_err("failed to create sink"); return -1; } - STAILQ_INSERT_TAIL(&ts2phc_slaves, slave, list); - ts2phc_n_slaves++; + STAILQ_INSERT_TAIL(&ts2phc_sinks, sink, list); + ts2phc_n_sinks++; return 0; } -int ts2phc_slave_arm(void) +int ts2phc_pps_sink_arm(void) { struct ptp_extts_request extts; - struct ts2phc_slave *slave; + struct ts2phc_pps_sink *sink; int err; memset(&extts, 0, sizeof(extts)); - STAILQ_FOREACH(slave, &ts2phc_slaves, list) { - extts.index = slave->pin_desc.chan; - extts.flags = slave->polarity | PTP_ENABLE_FEATURE; - err = ioctl(slave->fd, PTP_EXTTS_REQUEST2, &extts); + STAILQ_FOREACH(sink, &ts2phc_sinks, list) { + extts.index = sink->pin_desc.chan; + extts.flags = sink->polarity | PTP_ENABLE_FEATURE; + err = ioctl(sink->fd, PTP_EXTTS_REQUEST2, &extts); if (err < 0) { pr_err(PTP_EXTTS_REQUEST_FAILED); return -1; @@ -388,29 +389,29 @@ int ts2phc_slave_arm(void) return 0; } -void ts2phc_slave_cleanup(void) +void ts2phc_pps_sink_cleanup(void) { - struct ts2phc_slave *slave; + struct ts2phc_pps_sink *sink; - ts2phc_slave_array_destroy(); + ts2phc_pps_sink_array_destroy(); - while ((slave = STAILQ_FIRST(&ts2phc_slaves))) { - STAILQ_REMOVE_HEAD(&ts2phc_slaves, list); - ts2phc_slave_destroy(slave); - ts2phc_n_slaves--; + while ((sink = STAILQ_FIRST(&ts2phc_sinks))) { + STAILQ_REMOVE_HEAD(&ts2phc_sinks, list); + ts2phc_pps_sink_destroy(sink); + ts2phc_n_sinks--; } } -int ts2phc_slave_poll(struct ts2phc_master *master) +int ts2phc_pps_sink_poll(struct ts2phc_master *master) { struct ts2phc_source_timestamp source_ts; unsigned int i; int cnt, err; - if (ts2phc_slave_array_create()) { + if (ts2phc_pps_sink_array_create()) { return -1; } - cnt = poll(polling_array.pfd, ts2phc_n_slaves, 2000); + cnt = poll(polling_array.pfd, ts2phc_n_sinks, 2000); if (cnt < 0) { if (EINTR == errno) { return 0; @@ -426,9 +427,9 @@ int ts2phc_slave_poll(struct ts2phc_master *master) err = ts2phc_master_getppstime(master, &source_ts.ts); source_ts.valid = err ? false : true; - for (i = 0; i < ts2phc_n_slaves; i++) { + for (i = 0; i < ts2phc_n_sinks; i++) { if (polling_array.pfd[i].revents & (POLLIN|POLLPRI)) { - ts2phc_slave_event(polling_array.slave[i], source_ts); + ts2phc_pps_sink_event(polling_array.sink[i], source_ts); } } return 0; diff --git a/ts2phc_pps_sink.h b/ts2phc_pps_sink.h index 842e5b9ebe6e..47afc2f04e34 100644 --- a/ts2phc_pps_sink.h +++ b/ts2phc_pps_sink.h @@ -4,17 +4,17 @@ * @note Copyright (C) 2019 Balint Ferencz <fer...@sch.bme.hu> * @note SPDX-License-Identifier: GPL-2.0+ */ -#ifndef HAVE_TS2PHC_SLAVE_H -#define HAVE_TS2PHC_SLAVE_H +#ifndef HAVE_TS2PHC_PPS_SINK_H +#define HAVE_TS2PHC_PPS_SINK_H #include "ts2phc_pps_source.h" -int ts2phc_slave_add(struct config *cfg, const char *name); +int ts2phc_pps_sink_add(struct config *cfg, const char *name); -int ts2phc_slave_arm(void); +int ts2phc_pps_sink_arm(void); -void ts2phc_slave_cleanup(void); +void ts2phc_pps_sink_cleanup(void); -int ts2phc_slave_poll(struct ts2phc_master *master); +int ts2phc_pps_sink_poll(struct ts2phc_master *master); #endif -- 2.25.1 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel