diff --git a/clock.c b/clock.c index 1999098..9f9cfdf 100644 --- a/clock.c +++ b/clock.c @@ -823,6 +823,7 @@ int clock_required_modes(struct clock *c) break; case TS_HARDWARE: case TS_ONESTEP: + case TS_P2P1STEP: required_modes |= SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; @@ -947,6 +948,7 @@ struct clock *clock_create(enum clock_type type, struct config *config, return NULL; break; case TS_ONESTEP: + case TS_P2P1STEP: break; } } diff --git a/incdefs.sh b/incdefs.sh index 8232b5c..19e620e 100755 --- a/incdefs.sh +++ b/incdefs.sh @@ -82,6 +82,10 @@ kernel_flags() if grep -q HWTSTAMP_TX_ONESTEP_SYNC ${prefix}${tstamp}; then printf " -DHAVE_ONESTEP_SYNC" fi + + if grep -q HWTSTAMP_TX_ONESTEP_P2P ${prefix}${tstamp}; then + printf " -DHAVE_ONESTEP_P2P" + fi } flags="$(user_flags)$(kernel_flags)" diff --git a/missing.h b/missing.h index 6d5d550..b5ca270 100644 --- a/missing.h +++ b/missing.h @@ -54,6 +54,12 @@ enum _missing_hwtstamp_tx_types { }; #endif +#ifndef HAVE_ONESTEP_P2P +enum { + HWTSTAMP_TX_ONESTEP_P2P = 3, +}; +#endif + #ifndef SIOCGHWTSTAMP #define SIOCGHWTSTAMP 0x89b1 #endif diff --git a/msg.h b/msg.h index 5da50e1..f41a0e7 100644 --- a/msg.h +++ b/msg.h @@ -61,6 +61,7 @@ enum timestamp_type { TS_HARDWARE, TS_LEGACY_HW, TS_ONESTEP, + TS_P2P1STEP, }; struct hw_timestamp { diff --git a/port.c b/port.c index cf41725..454c60d 100644 --- a/port.c +++ b/port.c @@ -1450,7 +1450,21 @@ static int port_tx_sync(struct port *p, struct address *dst) struct ptp_message *msg, *fup; int err, event; - event = p->timestamping == TS_ONESTEP ? TRANS_ONESTEP : TRANS_EVENT; + switch (p->timestamping) { + case TS_SOFTWARE: + case TS_LEGACY_HW: + case TS_HARDWARE: + event = TRANS_EVENT; + break; + case TS_ONESTEP: + event = TRANS_ONESTEP; + break; + case TS_P2P1STEP: + event = TRANS_P2P1STEP; + break; + default: + return -1; + } if (!port_capable(p)) { return 0; @@ -1478,7 +1492,7 @@ static int port_tx_sync(struct port *p, struct address *dst) msg->header.control = CTL_SYNC; msg->header.logMessageInterval = p->logSyncInterval; - if (p->timestamping != TS_ONESTEP) + if (p->timestamping != TS_ONESTEP && p->timestamping != TS_P2P1STEP) msg->header.flagField[0] |= TWO_STEP; if (dst) { @@ -1490,7 +1504,7 @@ static int port_tx_sync(struct port *p, struct address *dst) pr_err("port %hu: send sync failed", portnum(p)); goto out; } - if (p->timestamping == TS_ONESTEP) { + if (p->timestamping == TS_ONESTEP || p->timestamping == TS_P2P1STEP) { goto out; } else if (msg_sots_missing(msg)) { pr_err("missing timestamp on transmitted sync"); @@ -1934,7 +1948,21 @@ static void process_follow_up(struct port *p, struct ptp_message *m) static int process_pdelay_req(struct port *p, struct ptp_message *m) { struct ptp_message *rsp, *fup; - int err; + int err, event; + + switch (p->timestamping) { + case TS_SOFTWARE: + case TS_LEGACY_HW: + case TS_HARDWARE: + case TS_ONESTEP: + event = TRANS_EVENT; + break; + case TS_P2P1STEP: + event = TRANS_P2P1STEP; + break; + default: + return -1; + } if (p->delayMechanism == DM_E2E) { pr_warning("port %hu: pdelay_req on E2E port", portnum(p)); @@ -1980,19 +2008,36 @@ 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; /* * NB - We do not have any fraction nanoseconds for the correction * fields, neither in the response or the follow up. */ - rsp->pdelay_resp.requestReceiptTimestamp = tmv_to_Timestamp(m->hwts.ts); + if (p->timestamping == TS_P2P1STEP) { + rsp->header.correction = m->header.correction; + } else { + rsp->header.flagField[0] |= TWO_STEP; + rsp->pdelay_resp.requestReceiptTimestamp = + tmv_to_Timestamp(m->hwts.ts); + } rsp->pdelay_resp.requestingPortIdentity = m->header.sourcePortIdentity; + err = peer_prepare_and_send(p, rsp, event); + if (err) { + pr_err("port %hu: send peer delay response failed", portnum(p)); + goto out; + } + if (p->timestamping == TS_P2P1STEP) { + goto out; + } else if (msg_sots_missing(rsp)) { + pr_err("missing timestamp on transmitted peer delay response"); + err = -1; + goto out; + } + + /* + * Send the follow up message right away. + */ fup->hwts.type = p->timestamping; fup->header.tsmt = PDELAY_RESP_FOLLOW_UP | p->transportSpecific; @@ -2007,23 +2052,12 @@ static int process_pdelay_req(struct port *p, struct ptp_message *m) fup->pdelay_resp_fup.requestingPortIdentity = m->header.sourcePortIdentity; - err = peer_prepare_and_send(p, rsp, 1); - if (err) { - pr_err("port %hu: send peer delay response failed", portnum(p)); - goto out; - } - if (msg_sots_missing(rsp)) { - pr_err("missing timestamp on transmitted peer delay response"); - goto out; - } - fup->pdelay_resp_fup.responseOriginTimestamp = tmv_to_Timestamp(rsp->hwts.ts); err = peer_prepare_and_send(p, fup, 0); if (err) pr_err("port %hu: send pdelay_resp_fup failed", portnum(p)); - out: msg_put(rsp); msg_put(fup); @@ -2530,7 +2564,8 @@ enum fsm_event port_event(struct port *p, int fd_index) msg_put(msg); return EV_NONE; } - if (msg_sots_missing(msg)) { + if (msg_sots_missing(msg) && + !(p->timestamping == TS_P2P1STEP && msg_type(msg) == PDELAY_REQ)) { pr_err("port %hu: received %s without timestamp", portnum(p), msg_type_string(msg_type(msg))); msg_put(msg); diff --git a/sk.c b/sk.c index 72926ab..9c98c1d 100644 --- a/sk.c +++ b/sk.c @@ -43,7 +43,7 @@ int sk_check_fupsync; /* private methods */ -static int hwts_init(int fd, const char *device, int rx_filter, int one_step) +static int hwts_init(int fd, const char *device, int rx_filter, int tx_type) { struct ifreq ifreq; struct hwtstamp_config cfg, req; @@ -55,7 +55,7 @@ static int hwts_init(int fd, const char *device, int rx_filter, int one_step) strncpy(ifreq.ifr_name, device, sizeof(ifreq.ifr_name) - 1); ifreq.ifr_data = (void *) &cfg; - cfg.tx_type = one_step ? HWTSTAMP_TX_ONESTEP_SYNC : HWTSTAMP_TX_ON; + cfg.tx_type = tx_type; cfg.rx_filter = rx_filter; req = cfg; err = ioctl(fd, SIOCSHWTSTAMP, &ifreq); @@ -359,6 +359,7 @@ int sk_receive(int fd, void *buf, int buflen, break; case TS_HARDWARE: case TS_ONESTEP: + case TS_P2P1STEP: hwts->ts = timespec_to_tmv(ts[2]); break; case TS_LEGACY_HW: @@ -394,7 +395,7 @@ int sk_set_priority(int fd, uint8_t dscp) int sk_timestamping_init(int fd, const char *device, enum timestamp_type type, enum transport_type transport) { - int err, filter1, filter2 = 0, flags, one_step; + int err, filter1, filter2 = 0, flags, tx_type; switch (type) { case TS_SOFTWARE: @@ -404,6 +405,7 @@ int sk_timestamping_init(int fd, const char *device, enum timestamp_type type, break; case TS_HARDWARE: case TS_ONESTEP: + case TS_P2P1STEP: flags = SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; @@ -419,7 +421,21 @@ int sk_timestamping_init(int fd, const char *device, enum timestamp_type type, if (type != TS_SOFTWARE) { filter1 = HWTSTAMP_FILTER_PTP_V2_EVENT; - one_step = type == TS_ONESTEP ? 1 : 0; + switch (type) { + case TS_SOFTWARE: + tx_type = HWTSTAMP_TX_OFF; + break; + case TS_HARDWARE: + case TS_LEGACY_HW: + tx_type = HWTSTAMP_TX_ON; + break; + case TS_ONESTEP: + tx_type = HWTSTAMP_TX_ONESTEP_SYNC; + break; + case TS_P2P1STEP: + tx_type = HWTSTAMP_TX_ONESTEP_P2P; + break; + } switch (transport) { case TRANS_UDP_IPV4: case TRANS_UDP_IPV6: @@ -434,10 +450,10 @@ int sk_timestamping_init(int fd, const char *device, enum timestamp_type type, case TRANS_UDS: return -1; } - err = hwts_init(fd, device, filter1, one_step); + err = hwts_init(fd, device, filter1, tx_type); if (err) { pr_info("driver rejected most general HWTSTAMP filter"); - err = hwts_init(fd, device, filter2, one_step); + err = hwts_init(fd, device, filter2, tx_type); if (err) { pr_err("ioctl SIOCSHWTSTAMP failed: %m"); return err; diff --git a/transport.h b/transport.h index 15616bb..05df53b 100644 --- a/transport.h +++ b/transport.h @@ -49,6 +49,7 @@ enum transport_event { TRANS_GENERAL, TRANS_EVENT, TRANS_ONESTEP, + TRANS_P2P1STEP, }; struct transport;