Modify the pmc to allow non-blocking operation. Run it on each clock
update to have the sync offset updated from currentUtcOffset with every
other call.
Signed-off-by: Miroslav Lichvar <***@redhat.com>
---
phc2sys.8 | 15 ++++---
phc2sys.c | 152 ++++++++++++++++++++++++++++++++++++++++++--------------------
2 files changed, 112 insertions(+), 55 deletions(-)
diff --git a/phc2sys.8 b/phc2sys.8
index 0542ba7..10faea9 100644
--- a/phc2sys.8
+++ b/phc2sys.8
@@ -106,13 +106,10 @@ minimize the error caused by random delays in scheduling and bus utilization.
The default is 5.
.TP
.BI \-O " offset"
-Specify the offset between the slave and master times in seconds. With the
+Specify the offset between the slave and master times in seconds. The default
+is set automatically with the
.B \-w
-option the default value is set automatically according to the currentUtcOffset
-value obtained from ptp4l and the direction of the clock synchronization.
-Without
-.B \-w
-the default is 0.
+option, 0 otherwise.
.TP
.BI \-u " summary-updates"
Specify the number of clock updates included in summary statistics. The
@@ -124,7 +121,11 @@ statistics. The messages are printed at the LOG_INFO level.
The default is 0 (disabled).
.TP
.B \-w
-Wait until ptp4l is in a synchronized state.
+Wait until ptp4l is in a synchronized state. If the
+.B \-O
+option is not used, also keep the offset between the slave and master
+times updated according to the currentUtcOffset value obtained from ptp4l and
+the direction of the clock synchronization.
.TP
.BI \-l " print-level"
Set the maximum syslog level of messages which should be printed or sent to
diff --git a/phc2sys.c b/phc2sys.c
index 582492d..a600709 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -55,6 +55,9 @@
#define PHC_PPS_OFFSET_LIMIT 10000000
+struct clock;
+static int update_sync_offset(struct clock *clock);
+
static clockid_t clock_open(char *device)
{
int fd;
@@ -160,6 +163,11 @@ struct clock {
struct stats *freq_stats;
struct stats *delay_stats;
unsigned int stats_max_count;
+ int sync_offset;
+ int sync_offset_direction;
+ struct pmc *pmc;
+ int pmc_ds_idx;
+ int pmc_ds_requested;
};
static void update_clock_stats(struct clock *clock,
@@ -203,6 +211,13 @@ static void update_clock(struct clock *clock,
enum servo_state state;
double ppb;
+ if (update_sync_offset(clock))
+ return;
+
+ if (clock->sync_offset_direction)
+ offset += clock->sync_offset * NS_PER_SEC *
+ clock->sync_offset_direction;
+
ppb = servo_sample(clock->servo, offset, ts, &state);
switch (state) {
@@ -253,13 +268,17 @@ static int read_pps(int fd, int64_t *offset, uint64_t *ts)
}
static int do_pps_loop(struct clock *clock, int fd,
- clockid_t src, int n_readings, int sync_offset)
+ clockid_t src, int n_readings)
{
int64_t pps_offset, phc_offset, phc_delay;
uint64_t pps_ts, phc_ts;
clock->source_label = "pps";
+ /* The sync offset can't be applied with PPS alone. */
+ if (src == CLOCK_INVALID)
+ clock->sync_offset_direction = 0;
+
while (1) {
if (!read_pps(fd, &pps_offset, &pps_ts)) {
continue;
@@ -284,7 +303,6 @@ static int do_pps_loop(struct clock *clock, int fd,
phc_ts = phc_ts / NS_PER_SEC * NS_PER_SEC;
pps_offset = pps_ts - phc_ts;
- pps_offset -= sync_offset * NS_PER_SEC;
}
update_clock(clock, pps_offset, pps_ts, -1);
@@ -294,7 +312,7 @@ static int do_pps_loop(struct clock *clock, int fd,
}
static int do_sysoff_loop(struct clock *clock, clockid_t src,
- int rate, int n_readings, int sync_offset)
+ int rate, int n_readings)
{
uint64_t ts;
int64_t offset, delay;
@@ -308,14 +326,13 @@ static int do_sysoff_loop(struct clock *clock, clockid_t src,
err = -1;
break;
}
- offset -= sync_offset * NS_PER_SEC;
update_clock(clock, offset, ts, delay);
}
return err;
}
static int do_phc_loop(struct clock *clock, clockid_t src,
- int rate, int n_readings, int sync_offset)
+ int rate, int n_readings)
{
uint64_t ts;
int64_t offset, delay;
@@ -328,7 +345,6 @@ static int do_phc_loop(struct clock *clock, clockid_t src,
&offset, &ts, &delay)) {
continue;
}
- offset -= sync_offset * NS_PER_SEC;
update_clock(clock, offset, ts, delay);
}
return 0;
@@ -360,58 +376,75 @@ static void *get_mgt_data(struct ptp_message *msg)
return ((struct management_tlv *) msg->management.suffix)->data;
}
-static int run_pmc(int wait_sync, int *utc_offset)
+static int init_pmc(struct clock *clock)
+{
+ clock->pmc = pmc_create(TRANS_UDS, "/var/run/phc2sys", 0, 0, 0);
+ if (!clock->pmc) {
+ pr_err("failed to create pmc");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int run_pmc(struct clock *clock, int timeout,
+ int wait_sync, int get_utc_offset)
{
struct ptp_message *msg;
- struct pmc *pmc;
void *data;
#define N_FD 1
struct pollfd pollfd[N_FD];
+ int cnt, ds_done;
#define N_ID 2
- int cnt, i = 0, ds_done, ds_requested = 0;
int ds_ids[N_ID] = {
PORT_DATA_SET,
TIME_PROPERTIES_DATA_SET
};
- pmc = pmc_create(TRANS_UDS, "/var/run/phc2sys", 0, 0, 0);
- if (!pmc) {
- pr_err("failed to create pmc");
- return -1;
- }
+ while (clock->pmc_ds_idx < N_ID) {
+ /* Check if the data set is really needed. */
+ if ((ds_ids[clock->pmc_ds_idx] == PORT_DATA_SET &&
+ !wait_sync) ||
+ (ds_ids[clock->pmc_ds_idx] == TIME_PROPERTIES_DATA_SET &&
+ !get_utc_offset)) {
+ clock->pmc_ds_idx++;
+ continue;
+ }
- while (i < N_ID) {
- pollfd[0].fd = pmc_get_transport_fd(pmc);
+ pollfd[0].fd = pmc_get_transport_fd(clock->pmc);
pollfd[0].events = POLLIN|POLLPRI;
- if (!ds_requested)
+ if (!clock->pmc_ds_requested)
pollfd[0].events |= POLLOUT;
- cnt = poll(pollfd, N_FD, 1000);
+ cnt = poll(pollfd, N_FD, timeout);
if (cnt < 0) {
pr_err("poll failed");
return -1;
}
if (!cnt) {
- /* Request the data set again. */
- ds_requested = 0;
- pr_notice("Waiting for ptp4l...");
- continue;
+ /* Request the data set again in the next run. */
+ clock->pmc_ds_requested = 0;
+ return 0;
}
- if (pollfd[0].revents & POLLOUT) {
- pmc_send_get_action(pmc, ds_ids[i]);
- ds_requested = 1;
+ /* Send a new request if there are no pending messages. */
+ if ((pollfd[0].revents & POLLOUT) &&
+ !(pollfd[0].revents & (POLLIN|POLLPRI))) {
+ pmc_send_get_action(clock->pmc,
+ ds_ids[clock->pmc_ds_idx]);
+ clock->pmc_ds_requested = 1;
}
if (!(pollfd[0].revents & (POLLIN|POLLPRI)))
continue;
- msg = pmc_recv(pmc);
+ msg = pmc_recv(clock->pmc);
if (!msg)
continue;
- if (!is_msg_mgt(msg) || get_mgt_id(msg) != ds_ids[i]) {
+ if (!is_msg_mgt(msg) ||
+ get_mgt_id(msg) != ds_ids[clock->pmc_ds_idx]) {
msg_put(msg);
continue;
}
@@ -421,9 +454,6 @@ static int run_pmc(int wait_sync, int *utc_offset)
switch (get_mgt_id(msg)) {
case PORT_DATA_SET:
- if (!wait_sync)
- ds_done = 1;
-
switch (((struct portDS *)data)->portState) {
case PS_MASTER:
case PS_SLAVE:
@@ -433,22 +463,35 @@ static int run_pmc(int wait_sync, int *utc_offset)
break;
case TIME_PROPERTIES_DATA_SET:
- *utc_offset = ((struct timePropertiesDS *)data)->
- currentUtcOffset;
+ clock->sync_offset = ((struct timePropertiesDS *)data)->
+ currentUtcOffset;
ds_done = 1;
break;
}
if (ds_done) {
/* Proceed with the next data set. */
- i++;
- ds_requested = 0;
+ clock->pmc_ds_idx++;
+ clock->pmc_ds_requested = 0;
}
msg_put(msg);
}
- pmc_destroy(pmc);
+ clock->pmc_ds_idx = 0;
+ return 1;
+}
+
+static void close_pmc(struct clock *clock)
+{
+ pmc_destroy(clock->pmc);
+ clock->pmc = NULL;
+}
+static int update_sync_offset(struct clock *clock)
+{
+ if (clock->pmc) {
+ run_pmc(clock, 0, 0, 1);
+ }
return 0;
}
@@ -479,8 +522,8 @@ int main(int argc, char *argv[])
{
char *progname, *ethdev = NULL;
clockid_t src = CLOCK_INVALID;
- int c, phc_readings = 5, phc_rate = 1, sync_offset = 0, pps_fd = -1;
- int wait_sync = 0, forced_sync_offset = 0;
+ int c, phc_readings = 5, phc_rate = 1, pps_fd = -1;
+ int r, wait_sync = 0, forced_sync_offset = 0;
int print_level = LOG_INFO, use_syslog = 1, verbose = 0;
double ppb;
struct clock dst_clock = { .clkid = CLOCK_REALTIME };
@@ -524,7 +567,8 @@ int main(int argc, char *argv[])
phc_readings = atoi(optarg);
break;
case 'O':
- sync_offset = atoi(optarg);
+ dst_clock.sync_offset = atoi(optarg);
+ dst_clock.sync_offset_direction = -1;
forced_sync_offset = 1;
break;
case 'i':
@@ -596,18 +640,33 @@ int main(int argc, char *argv[])
print_set_level(print_level);
if (wait_sync) {
- int ptp_utc_offset;
+ if (init_pmc(&dst_clock))
+ return -1;
- run_pmc(wait_sync, &ptp_utc_offset);
+ while (1) {
+ r = run_pmc(&dst_clock, 1000,
+ wait_sync, !forced_sync_offset);
+ if (r < 0)
+ return -1;
+ else if (r > 0)
+ break;
+ else
+ pr_notice("Waiting for ptp4l...");
+ }
if (!forced_sync_offset) {
if (src != CLOCK_REALTIME &&
dst_clock.clkid == CLOCK_REALTIME)
- sync_offset = -ptp_utc_offset;
+ dst_clock.sync_offset_direction = 1;
else if (src == CLOCK_REALTIME &&
dst_clock.clkid != CLOCK_REALTIME)
- sync_offset = ptp_utc_offset;
+ dst_clock.sync_offset_direction = -1;
+ else
+ dst_clock.sync_offset_direction = 0;
}
+
+ if (forced_sync_offset || !dst_clock.sync_offset_direction)
+ close_pmc(&dst_clock);
}
ppb = clock_ppb_read(dst_clock.clkid);
@@ -618,14 +677,11 @@ int main(int argc, char *argv[])
dst_clock.servo = servo_create(CLOCK_SERVO_PI, -ppb, max_ppb, 0);
if (pps_fd >= 0)
- return do_pps_loop(&dst_clock, pps_fd, src,
- phc_readings, sync_offset);
+ return do_pps_loop(&dst_clock, pps_fd, src, phc_readings);
if (dst_clock.clkid == CLOCK_REALTIME &&
SYSOFF_SUPPORTED == sysoff_probe(CLOCKID_TO_FD(src), phc_readings))
- return do_sysoff_loop(&dst_clock, src, phc_rate,
- phc_readings, sync_offset);
+ return do_sysoff_loop(&dst_clock, src, phc_rate, phc_readings);
- return do_phc_loop(&dst_clock, src, phc_rate,
- phc_readings, sync_offset);
+ return do_phc_loop(&dst_clock, src, phc_rate, phc_readings);
}
--
1.8.1.2