Skip to content

Commit

Permalink
Support one step sync operation.
Browse files Browse the repository at this point in the history
The Linux kernel supports a hardware time stamping mode that allows
sending a one step sync message. This commit adds support for this mode
by expanding the time stamp type enumeration. In order to enable this
mode, the configuration must specify both hardware time stamping and set
the twoStepFlag to false.

We still do not support the one step peer delay request mechanism since
there is neither kernel nor hardware support for it at this time.

Signed-off-by: Richard Cochran <[email protected]>
  • Loading branch information
richardcochran committed Nov 30, 2012
1 parent 2438500 commit b96e739
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 15 deletions.
3 changes: 1 addition & 2 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
15 changes: 11 additions & 4 deletions port.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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;

/*
Expand Down
27 changes: 24 additions & 3 deletions ptp4l.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {
Expand Down
15 changes: 9 additions & 6 deletions sk.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand All @@ -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;
Expand All @@ -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:
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions transport.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ enum timestamp_type {
TS_SOFTWARE,
TS_HARDWARE,
TS_LEGACY_HW,
TS_ONESTEP,
};

struct hw_timestamp {
Expand Down

0 comments on commit b96e739

Please sign in to comment.