Skip to content

Commit

Permalink
Introduce peer to peer one step.
Browse files Browse the repository at this point in the history
The 1588 standard defines one step operation for both Sync and
PDelay_Resp messages.  Up until now, hardware with P2P one step has
been rare, and kernel support was lacking.  This patch adds support of
the mode in anticipation of new kernel and hardware developments.

Signed-off-by: Richard Cochran <[email protected]>
  • Loading branch information
richardcochran committed Mar 28, 2018
1 parent 510777d commit 4842d2c
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 28 deletions.
2 changes: 2 additions & 0 deletions clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
Expand Down
4 changes: 4 additions & 0 deletions incdefs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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)"
Expand Down
6 changes: 6 additions & 0 deletions missing.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ enum timestamp_type {
TS_HARDWARE,
TS_LEGACY_HW,
TS_ONESTEP,
TS_P2P1STEP,
};

struct hw_timestamp {
Expand Down
79 changes: 57 additions & 22 deletions port.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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");
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
28 changes: 22 additions & 6 deletions sk.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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;
Expand All @@ -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:
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions transport.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ enum transport_event {
TRANS_GENERAL,
TRANS_EVENT,
TRANS_ONESTEP,
TRANS_P2P1STEP,
};

struct transport;
Expand Down

0 comments on commit 4842d2c

Please sign in to comment.