Support one step sync operation.

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 <richardcochran@gmail.com>
master
Richard Cochran 2012-11-29 21:01:16 +01:00
parent 24385005b8
commit b96e73994b
5 changed files with 46 additions and 15 deletions

View File

@ -163,8 +163,7 @@ static enum parser_result parse_global_setting(const char *option,
return r; return r;
if (!strcmp(option, "twoStepFlag")) { if (!strcmp(option, "twoStepFlag")) {
/* TODO - implement one step */ if (1 != sscanf(value, "%d", &val))
if (1 != sscanf(value, "%d", &val) || !val)
return BAD_VALUE; return BAD_VALUE;
dds->twoStepFlag = val ? 1 : 0; dds->twoStepFlag = val ? 1 : 0;

15
port.c
View File

@ -670,6 +670,7 @@ static int port_tx_sync(struct port *p)
{ {
struct ptp_message *msg, *fup; struct ptp_message *msg, *fup;
int cnt, err = 0, pdulen; int cnt, err = 0, pdulen;
int event = p->timestamping == TS_ONESTEP ? TRANS_ONESTEP : TRANS_EVENT;
msg = msg_allocate(); msg = msg_allocate();
if (!msg) if (!msg)
@ -692,19 +693,22 @@ static int port_tx_sync(struct port *p)
msg->header.control = CTL_SYNC; msg->header.control = CTL_SYNC;
msg->header.logMessageInterval = p->logSyncInterval; 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)) { if (msg_pre_send(msg)) {
err = -1; err = -1;
goto out; 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) { if (cnt <= 0) {
pr_err("port %hu: send sync failed", portnum(p)); pr_err("port %hu: send sync failed", portnum(p));
err = -1; err = -1;
goto out; 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"); pr_err("missing timestamp on transmitted sync");
err = -1; err = -1;
goto out; 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.sequenceId = m->header.sequenceId;
rsp->header.control = CTL_OTHER; rsp->header.control = CTL_OTHER;
rsp->header.logMessageInterval = 0x7f; 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; rsp->header.flagField[0] |= TWO_STEP;
/* /*

27
ptp4l.c
View File

@ -256,18 +256,39 @@ int main(int argc, char *argv[])
return -1; 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 | required_modes |= SOF_TIMESTAMPING_TX_SOFTWARE |
SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_RX_SOFTWARE |
SOF_TIMESTAMPING_SOFTWARE; SOF_TIMESTAMPING_SOFTWARE;
else if (*timestamping == TS_LEGACY_HW) break;
case TS_LEGACY_HW:
required_modes |= SOF_TIMESTAMPING_TX_HARDWARE | required_modes |= SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_SYS_HARDWARE; SOF_TIMESTAMPING_SYS_HARDWARE;
else if (*timestamping == TS_HARDWARE) break;
case TS_HARDWARE:
case TS_ONESTEP:
required_modes |= SOF_TIMESTAMPING_TX_HARDWARE | required_modes |= SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE; SOF_TIMESTAMPING_RAW_HARDWARE;
break;
}
/* check whether timestamping mode is supported. */ /* check whether timestamping mode is supported. */
for (i = 0; i < cfg_settings.nports; i++) { for (i = 0; i < cfg_settings.nports; i++) {

15
sk.c
View File

@ -36,7 +36,7 @@ int sk_tx_retries = 100;
/* private methods */ /* 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 ifreq ifreq;
struct hwtstamp_config cfg, req; 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)); strncpy(ifreq.ifr_name, device, sizeof(ifreq.ifr_name));
ifreq.ifr_data = (void *) &cfg; 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; cfg.rx_filter = rx_filter;
req = cfg; req = cfg;
err = ioctl(fd, SIOCSHWTSTAMP, &ifreq); 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("tx_type %d not %d", cfg.tx_type, req.tx_type);
pr_warning("rx_filter %d not %d", cfg.rx_filter, req.rx_filter); 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_ALL &&
cfg.rx_filter != HWTSTAMP_FILTER_PTP_V2_EVENT)) { cfg.rx_filter != HWTSTAMP_FILTER_PTP_V2_EVENT)) {
return -1; return -1;
@ -221,6 +221,7 @@ int sk_receive(int fd, void *buf, int buflen,
hwts->ts = ts[0]; hwts->ts = ts[0];
break; break;
case TS_HARDWARE: case TS_HARDWARE:
case TS_ONESTEP:
hwts->ts = ts[2]; hwts->ts = ts[2];
break; break;
case TS_LEGACY_HW: 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, int sk_timestamping_init(int fd, char *device, enum timestamp_type type,
enum transport_type transport) enum transport_type transport)
{ {
int err, filter1, filter2, flags; int err, filter1, filter2, flags, one_step;
switch (type) { switch (type) {
case TS_SOFTWARE: case TS_SOFTWARE:
@ -242,6 +243,7 @@ int sk_timestamping_init(int fd, char *device, enum timestamp_type type,
SOF_TIMESTAMPING_SOFTWARE; SOF_TIMESTAMPING_SOFTWARE;
break; break;
case TS_HARDWARE: case TS_HARDWARE:
case TS_ONESTEP:
flags = SOF_TIMESTAMPING_TX_HARDWARE | flags = SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_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) { if (type != TS_SOFTWARE) {
filter1 = HWTSTAMP_FILTER_PTP_V2_EVENT; filter1 = HWTSTAMP_FILTER_PTP_V2_EVENT;
one_step = type == TS_ONESTEP ? 1 : 0;
switch (transport) { switch (transport) {
case TRANS_UDP_IPV4: case TRANS_UDP_IPV4:
case TRANS_UDP_IPV6: case TRANS_UDP_IPV6:
@ -271,10 +274,10 @@ int sk_timestamping_init(int fd, char *device, enum timestamp_type type,
case TRANS_UDS: case TRANS_UDS:
return -1; return -1;
} }
err = hwts_init(fd, device, filter1); err = hwts_init(fd, device, filter1, one_step);
if (err) { if (err) {
pr_info("driver rejected most general HWTSTAMP filter"); pr_info("driver rejected most general HWTSTAMP filter");
err = hwts_init(fd, device, filter2); err = hwts_init(fd, device, filter2, one_step);
if (err) { if (err) {
pr_err("ioctl SIOCSHWTSTAMP failed: %m"); pr_err("ioctl SIOCSHWTSTAMP failed: %m");
return err; return err;

View File

@ -48,6 +48,7 @@ enum timestamp_type {
TS_SOFTWARE, TS_SOFTWARE,
TS_HARDWARE, TS_HARDWARE,
TS_LEGACY_HW, TS_LEGACY_HW,
TS_ONESTEP,
}; };
struct hw_timestamp { struct hw_timestamp {