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 <richardcoch...@gmail.com>
---
 clock.c     |  2 ++
 incdefs.sh  |  4 ++++
 missing.h   |  6 +++++
 msg.h       |  1 +
 port.c      | 79 ++++++++++++++++++++++++++++++++++++++++++++-----------------
 sk.c        | 28 +++++++++++++++++-----
 transport.h |  1 +
 7 files changed, 93 insertions(+), 28 deletions(-)

diff --git a/clock.c b/clock.c
index cf087e8..5b44860 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 16ae97a..7669754 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 561b832..43d17af 100644
--- a/port.c
+++ b/port.c
@@ -1426,7 +1426,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;
@@ -1454,7 +1468,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) {
@@ -1466,7 +1480,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");
@@ -1901,7 +1915,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));
@@ -1947,19 +1975,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;
@@ -1974,23 +2019,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);
@@ -2495,7 +2529,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;
-- 
2.11.0


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to