Latest Linux kernel has supported getting PHC from bond directly. This would
help topology like VLAN over bond to get PHC natively. To achieve this,
the new hwtstamp flag is needed when passing hwtstamp_config to kernel.

We use ifdef to check if the build kernel support this new flag. And
fall back without flag if user run new build on old kernel for hwts_init().

Split port_change_phc() from function port_link_status() so the event
functions could call it directly. Add a new link_state flag PHC_INDEX_CHANGED
as we may skip TS_LABEL_CHANGED setting if get PHC directly.

In clock_create(), try get ts info first, if failed, try the old way.

In e2e_event(), p2p_event() and bc_event(), if we find the phc changed,
we can call port_change_phc() directly.

Signed-off-by: Hangbin Liu <liuhang...@gmail.com>
---
 clock.c        | 19 ++++++++++---
 e2e_tc.c       | 14 +++++++--
 p2p_tc.c       | 14 +++++++--
 port.c         | 77 +++++++++++++++++++++++++++++++-------------------
 port_private.h |  2 ++
 sk.c           |  7 +++++
 6 files changed, 96 insertions(+), 37 deletions(-)

diff --git a/clock.c b/clock.c
index 07bf582..6d1b4df 100644
--- a/clock.c
+++ b/clock.c
@@ -1001,10 +1001,18 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
        c->timestamping = timestamping;
        required_modes = clock_required_modes(c);
        STAILQ_FOREACH(iface, &config->interfaces, list) {
-               memset(ts_label, 0, sizeof(ts_label));
-               if (!rtnl_get_ts_device(interface_name(iface), ts_label))
-                       interface_set_label(iface, ts_label);
-               interface_get_tsinfo(iface);
+#ifdef HWTSTAMP_FLAG_BONDED_PHC_INDEX
+               if (interface_get_tsinfo(iface) ||
+                   (interface_tsinfo_valid(iface) &&
+                    !interface_tsmodes_supported(iface, required_modes))) {
+#endif
+                       memset(ts_label, 0, sizeof(ts_label));
+                       if (!rtnl_get_ts_device(interface_name(iface), 
ts_label))
+                               interface_set_label(iface, ts_label);
+                       interface_get_tsinfo(iface);
+#ifdef HWTSTAMP_FLAG_BONDED_PHC_INDEX
+               }
+#endif
                if (interface_tsinfo_valid(iface) &&
                    !interface_tsmodes_supported(iface, required_modes)) {
                        pr_err("interface '%s' does not support requested 
timestamping mode",
@@ -1762,6 +1770,9 @@ int clock_switch_phc(struct clock *c, int phc_index)
        c->clkid = clkid;
        c->servo = servo;
        c->servo_state = SERVO_UNLOCKED;
+
+       pr_info("Switched to /dev/ptp%d as PTP clock", phc_index);
+
        return 0;
 }
 
diff --git a/e2e_tc.c b/e2e_tc.c
index 2f8e821..0a0dee7 100644
--- a/e2e_tc.c
+++ b/e2e_tc.c
@@ -17,6 +17,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA.
  */
 #include <errno.h>
+#include <linux/net_tstamp.h>
 
 #include "port.h"
 #include "port_private.h"
@@ -123,11 +124,20 @@ enum fsm_event e2e_event(struct port *p, int fd_index)
 
        case FD_RTNL:
                pr_debug("%s: received link status notification", p->log_name);
-               rtnl_link_status(fd, p->name, port_link_status, p);
+
+#ifdef HWTSTAMP_FLAG_BONDED_PHC_INDEX
+               if (!interface_get_tsinfo(p->iface) &&
+                   (p->phc_index != interface_phc_index(p->iface)))
+                       port_change_phc(p);
+               else
+#endif
+                       rtnl_link_status(fd, p->name, port_link_status, p);
+
                if (p->link_status == (LINK_UP|LINK_STATE_CHANGED)) {
                        return EV_FAULT_CLEARED;
                } else if ((p->link_status == (LINK_DOWN|LINK_STATE_CHANGED)) ||
-                          (p->link_status & TS_LABEL_CHANGED)) {
+                          (p->link_status & TS_LABEL_CHANGED) ||
+                          (p->link_status & PHC_INDEX_CHANGED)) {
                        return EV_FAULT_DETECTED;
                } else {
                        return EV_NONE;
diff --git a/p2p_tc.c b/p2p_tc.c
index 75cb3b9..972e1c4 100644
--- a/p2p_tc.c
+++ b/p2p_tc.c
@@ -17,6 +17,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA.
  */
 #include <errno.h>
+#include <linux/net_tstamp.h>
 
 #include "port.h"
 #include "port_private.h"
@@ -126,11 +127,20 @@ enum fsm_event p2p_event(struct port *p, int fd_index)
 
        case FD_RTNL:
                pr_debug("%s: received link status notification", p->log_name);
-               rtnl_link_status(fd, p->name, port_link_status, p);
+
+#ifdef HWTSTAMP_FLAG_BONDED_PHC_INDEX
+               if (!interface_get_tsinfo(p->iface) &&
+                   (p->phc_index != interface_phc_index(p->iface)))
+                       port_change_phc(p);
+               else
+#endif
+                       rtnl_link_status(fd, p->name, port_link_status, p);
+
                if (p->link_status == (LINK_UP|LINK_STATE_CHANGED)) {
                        return EV_FAULT_CLEARED;
                } else if ((p->link_status == (LINK_DOWN|LINK_STATE_CHANGED)) ||
-                          (p->link_status & TS_LABEL_CHANGED)) {
+                          (p->link_status & TS_LABEL_CHANGED) ||
+                          (p->link_status & PHC_INDEX_CHANGED)) {
                        return EV_FAULT_DETECTED;
                } else {
                        return EV_NONE;
diff --git a/port.c b/port.c
index 7e51e77..96d41d5 100644
--- a/port.c
+++ b/port.c
@@ -24,6 +24,7 @@
 #include <unistd.h>
 #include <sys/queue.h>
 #include <net/if.h>
+#include <linux/net_tstamp.h>
 
 #include "bmc.h"
 #include "clock.h"
@@ -2568,10 +2569,44 @@ static void bc_dispatch(struct port *p, enum fsm_event 
event, int mdiff)
        }
 }
 
+void port_change_phc(struct port *p)
+{
+       int required_modes;
+
+       /* Only switch phc with HW time stamping mode */
+       if (!interface_tsinfo_valid(p->iface) &&
+           interface_phc_index(p->iface) < 0)
+               return;
+
+       required_modes = clock_required_modes(p->clock);
+       if (!interface_tsmodes_supported(p->iface, required_modes)) {
+               pr_err("interface '%s' does not support requested "
+                      "timestamping mode, set link status down by force.",
+                      interface_label(p->iface));
+               p->link_status = LINK_DOWN | LINK_STATE_CHANGED;
+       } else if (p->phc_from_cmdline) {
+               pr_warning("%s: taking /dev/ptp%d from the "
+                          "command line, not the attached ptp%d",
+                          p->log_name, p->phc_index,
+                          interface_phc_index(p->iface));
+       } else if (p->phc_index != interface_phc_index(p->iface)) {
+               p->phc_index = interface_phc_index(p->iface);
+
+               if (clock_switch_phc(p->clock, p->phc_index)) {
+                       p->last_fault_type = FT_SWITCH_PHC;
+                       port_dispatch(p, EV_FAULT_DETECTED, 0);
+                       return;
+               }
+               clock_sync_interval(p->clock, p->log_sync_interval);
+
+               p->link_status |= PHC_INDEX_CHANGED;
+       }
+}
+
 void port_link_status(void *ctx, int linkup, int ts_index)
 {
        char ts_label[MAX_IFNAME_SIZE + 1] = {0};
-       int link_state, required_modes;
+       int link_state;
        const char *old_ts_label;
        struct port *p = ctx;
 
@@ -2595,32 +2630,7 @@ void port_link_status(void *ctx, int linkup, int 
ts_index)
        if (p->link_status & LINK_UP &&
            (p->link_status & LINK_STATE_CHANGED || p->link_status & 
TS_LABEL_CHANGED)) {
                interface_get_tsinfo(p->iface);
-
-               /* Only switch phc with HW time stamping mode */
-               if (interface_tsinfo_valid(p->iface) &&
-                   interface_phc_index(p->iface) >= 0) {
-                       required_modes = clock_required_modes(p->clock);
-                       if (!interface_tsmodes_supported(p->iface, 
required_modes)) {
-                               pr_err("interface '%s' does not support 
requested "
-                                      "timestamping mode, set link status down 
by force.",
-                                      interface_label(p->iface));
-                               p->link_status = LINK_DOWN | LINK_STATE_CHANGED;
-                       } else if (p->phc_from_cmdline) {
-                               pr_warning("%s: taking /dev/ptp%d from the "
-                                          "command line, not the attached 
ptp%d",
-                                          p->log_name, p->phc_index,
-                                          interface_phc_index(p->iface));
-                       } else if (p->phc_index != 
interface_phc_index(p->iface)) {
-                               p->phc_index = interface_phc_index(p->iface);
-
-                               if (clock_switch_phc(p->clock, p->phc_index)) {
-                                       p->last_fault_type = FT_SWITCH_PHC;
-                                       port_dispatch(p, EV_FAULT_DETECTED, 0);
-                                       return;
-                               }
-                               clock_sync_interval(p->clock, 
p->log_sync_interval);
-                       }
-               }
+               port_change_phc(p);
        }
 
        /*
@@ -2722,11 +2732,20 @@ static enum fsm_event bc_event(struct port *p, int 
fd_index)
 
        case FD_RTNL:
                pr_debug("%s: received link status notification", p->log_name);
-               rtnl_link_status(fd, p->name, port_link_status, p);
+
+#ifdef HWTSTAMP_FLAG_BONDED_PHC_INDEX
+               if (!interface_get_tsinfo(p->iface) &&
+                   (p->phc_index != interface_phc_index(p->iface)))
+                       port_change_phc(p);
+               else
+#endif
+                       rtnl_link_status(fd, p->name, port_link_status, p);
+
                if (p->link_status == (LINK_UP | LINK_STATE_CHANGED))
                        return EV_FAULT_CLEARED;
                else if ((p->link_status == (LINK_DOWN | LINK_STATE_CHANGED)) ||
-                        (p->link_status & TS_LABEL_CHANGED))
+                        (p->link_status & TS_LABEL_CHANGED) ||
+                        (p->link_status & PHC_INDEX_CHANGED))
                        return EV_FAULT_DETECTED;
                else
                        return EV_NONE;
diff --git a/port_private.h b/port_private.h
index 19eb944..f05d884 100644
--- a/port_private.h
+++ b/port_private.h
@@ -41,6 +41,7 @@ enum link_state {
        LINK_UP  = (1<<1),
        LINK_STATE_CHANGED = (1<<3),
        TS_LABEL_CHANGED  = (1<<4),
+       PHC_INDEX_CHANGED  = (1<<5),
 };
 
 struct nrate_estimator {
@@ -178,6 +179,7 @@ int port_delay_request(struct port *p);
 void port_disable(struct port *p);
 int port_initialize(struct port *p);
 int port_is_enabled(struct port *p);
+void port_change_phc(struct port *p);
 void port_link_status(void *ctx, int index, int linkup);
 int port_set_announce_tmo(struct port *p);
 int port_set_delay_tmo(struct port *p);
diff --git a/sk.c b/sk.c
index 8be0708..f832d99 100644
--- a/sk.c
+++ b/sk.c
@@ -66,6 +66,13 @@ static int hwts_init(int fd, const char *device, int 
rx_filter,
 
        init_ifreq(&ifreq, &cfg, device);
 
+#ifdef HWTSTAMP_FLAG_BONDED_PHC_INDEX
+       cfg.flags = HWTSTAMP_FLAG_BONDED_PHC_INDEX;
+       /* Fall back without flag if user run new build on old kernel */
+       if (ioctl(fd, SIOCGHWTSTAMP, &ifreq) == -EINVAL)
+               init_ifreq(&ifreq, &cfg, device);
+#endif
+
        switch (sk_hwts_filter_mode) {
        case HWTS_FILTER_CHECK:
                err = ioctl(fd, SIOCGHWTSTAMP, &ifreq);
-- 
2.31.1



_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to