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
parent
24385005b8
commit
b96e73994b
3
config.c
3
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;
|
||||
|
||||
|
|
13
port.c
13
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;
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
|
|
27
ptp4l.c
27
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++) {
|
||||
|
|
15
sk.c
15
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;
|
||||
|
|
|
@ -48,6 +48,7 @@ enum timestamp_type {
|
|||
TS_SOFTWARE,
|
||||
TS_HARDWARE,
|
||||
TS_LEGACY_HW,
|
||||
TS_ONESTEP,
|
||||
};
|
||||
|
||||
struct hw_timestamp {
|
||||
|
|
Loading…
Reference in New Issue