diff --git a/config.c b/config.c index 7e31a33..1fc5da4 100644 --- a/config.c +++ b/config.c @@ -163,8 +163,7 @@ static enum parser_result parse_global_setting(const char *option, return r; if (!strcmp(option, "twoStepFlag")) { - /* TODO - implement one step */ - if (1 != sscanf(value, "%d", &val) || !val) + if (1 != sscanf(value, "%d", &val)) return BAD_VALUE; dds->twoStepFlag = val ? 1 : 0; diff --git a/port.c b/port.c index 7dcce0d..defd7d5 100644 --- a/port.c +++ b/port.c @@ -670,6 +670,7 @@ static int port_tx_sync(struct port *p) { struct ptp_message *msg, *fup; int cnt, err = 0, pdulen; + int event = p->timestamping == TS_ONESTEP ? TRANS_ONESTEP : TRANS_EVENT; msg = msg_allocate(); if (!msg) @@ -692,19 +693,22 @@ static int port_tx_sync(struct port *p) msg->header.control = CTL_SYNC; msg->header.logMessageInterval = p->logSyncInterval; - msg->header.flagField[0] |= TWO_STEP; + if (p->timestamping != TS_ONESTEP) + msg->header.flagField[0] |= TWO_STEP; if (msg_pre_send(msg)) { err = -1; goto out; } - cnt = transport_send(p->trp, &p->fda, 1, msg, pdulen, &msg->hwts); + cnt = transport_send(p->trp, &p->fda, event, msg, pdulen, &msg->hwts); if (cnt <= 0) { pr_err("port %hu: send sync failed", portnum(p)); err = -1; goto out; } - if (msg_sots_missing(msg)) { + if (p->timestamping == TS_ONESTEP) { + goto out; + } else if (msg_sots_missing(msg)) { pr_err("missing timestamp on transmitted sync"); err = -1; goto out; @@ -1097,7 +1101,10 @@ static int process_pdelay_req(struct port *p, struct ptp_message *m) rsp->header.sequenceId = m->header.sequenceId; rsp->header.control = CTL_OTHER; rsp->header.logMessageInterval = 0x7f; - + /* + * NB - There is no kernel support for one step P2P messaging, + * so we always send a follow up message. + */ rsp->header.flagField[0] |= TWO_STEP; /* diff --git a/ptp4l.c b/ptp4l.c index 1c9aad0..0132d38 100644 --- a/ptp4l.c +++ b/ptp4l.c @@ -256,18 +256,39 @@ int main(int argc, char *argv[]) return -1; } - if (*timestamping == TS_SOFTWARE) + if (!ds->twoStepFlag) { + switch (*timestamping) { + case TS_SOFTWARE: + case TS_LEGACY_HW: + fprintf(stderr, "one step is only possible " + "with hardware time stamping\n"); + return -1; + case TS_HARDWARE: + *timestamping = TS_ONESTEP; + break; + case TS_ONESTEP: + break; + } + } + + switch (*timestamping) { + case TS_SOFTWARE: required_modes |= SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE; - else if (*timestamping == TS_LEGACY_HW) + break; + case TS_LEGACY_HW: required_modes |= SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_SYS_HARDWARE; - else if (*timestamping == TS_HARDWARE) + break; + case TS_HARDWARE: + case TS_ONESTEP: required_modes |= SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; + break; + } /* check whether timestamping mode is supported. */ for (i = 0; i < cfg_settings.nports; i++) { diff --git a/sk.c b/sk.c index 35ac335..452f898 100644 --- a/sk.c +++ b/sk.c @@ -36,7 +36,7 @@ int sk_tx_retries = 100; /* private methods */ -static int hwts_init(int fd, char *device, int rx_filter) +static int hwts_init(int fd, char *device, int rx_filter, int one_step) { struct ifreq ifreq; struct hwtstamp_config cfg, req; @@ -48,7 +48,7 @@ static int hwts_init(int fd, char *device, int rx_filter) strncpy(ifreq.ifr_name, device, sizeof(ifreq.ifr_name)); ifreq.ifr_data = (void *) &cfg; - cfg.tx_type = HWTSTAMP_TX_ON; + cfg.tx_type = one_step ? HWTSTAMP_TX_ONESTEP_SYNC : HWTSTAMP_TX_ON; cfg.rx_filter = rx_filter; req = cfg; err = ioctl(fd, SIOCSHWTSTAMP, &ifreq); @@ -61,7 +61,7 @@ static int hwts_init(int fd, char *device, int rx_filter) pr_warning("tx_type %d not %d", cfg.tx_type, req.tx_type); pr_warning("rx_filter %d not %d", cfg.rx_filter, req.rx_filter); - if (cfg.tx_type != HWTSTAMP_TX_ON || + if (cfg.tx_type != req.tx_type || (cfg.rx_filter != HWTSTAMP_FILTER_ALL && cfg.rx_filter != HWTSTAMP_FILTER_PTP_V2_EVENT)) { return -1; @@ -221,6 +221,7 @@ int sk_receive(int fd, void *buf, int buflen, hwts->ts = ts[0]; break; case TS_HARDWARE: + case TS_ONESTEP: hwts->ts = ts[2]; break; case TS_LEGACY_HW: @@ -233,7 +234,7 @@ int sk_receive(int fd, void *buf, int buflen, int sk_timestamping_init(int fd, char *device, enum timestamp_type type, enum transport_type transport) { - int err, filter1, filter2, flags; + int err, filter1, filter2, flags, one_step; switch (type) { case TS_SOFTWARE: @@ -242,6 +243,7 @@ int sk_timestamping_init(int fd, char *device, enum timestamp_type type, SOF_TIMESTAMPING_SOFTWARE; break; case TS_HARDWARE: + case TS_ONESTEP: flags = SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; @@ -257,6 +259,7 @@ int sk_timestamping_init(int fd, char *device, enum timestamp_type type, if (type != TS_SOFTWARE) { filter1 = HWTSTAMP_FILTER_PTP_V2_EVENT; + one_step = type == TS_ONESTEP ? 1 : 0; switch (transport) { case TRANS_UDP_IPV4: case TRANS_UDP_IPV6: @@ -271,10 +274,10 @@ int sk_timestamping_init(int fd, char *device, enum timestamp_type type, case TRANS_UDS: return -1; } - err = hwts_init(fd, device, filter1); + err = hwts_init(fd, device, filter1, one_step); if (err) { pr_info("driver rejected most general HWTSTAMP filter"); - err = hwts_init(fd, device, filter2); + err = hwts_init(fd, device, filter2, one_step); if (err) { pr_err("ioctl SIOCSHWTSTAMP failed: %m"); return err; diff --git a/transport.h b/transport.h index bfdff3d..03fcb79 100644 --- a/transport.h +++ b/transport.h @@ -48,6 +48,7 @@ enum timestamp_type { TS_SOFTWARE, TS_HARDWARE, TS_LEGACY_HW, + TS_ONESTEP, }; struct hw_timestamp {