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. Let's supply the flag first, and fall back without flag if user run on old kernel.
Split port_change_phc() from function port_link_status() so the event functions could call it directly when find the phc changed. Signed-off-by: Hangbin Liu <liuhang...@gmail.com> v6: revert changes in clock_create(). Update ts_label by force and do interface_get_tsinfo() only once. v5: no update v4: define HWTSTAMP_FLAG_BONDED_PHC_INDEX in missing.h remove unneeded net_tstamp header files v3: remove ifdef in clock_create() and FD_RTNL event. v2: remove link state PHC_INDEX_CHANGED and use TS_LABEL_CHANGED only. --- clock.c | 3 ++ e2e_tc.c | 7 ++++- missing.h | 6 ++++ p2p_tc.c | 7 ++++- port.c | 74 +++++++++++++++++++++++++++++++------------------- port_private.h | 1 + sk.c | 5 ++++ 7 files changed, 73 insertions(+), 30 deletions(-) diff --git a/clock.c b/clock.c index 7be021f..16ca6ed 100644 --- a/clock.c +++ b/clock.c @@ -1767,6 +1767,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..42baea3 100644 --- a/e2e_tc.c +++ b/e2e_tc.c @@ -123,7 +123,12 @@ 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); + if (!interface_get_tsinfo(p->iface) && + (p->phc_index != interface_phc_index(p->iface))) + port_change_phc(p); + else + 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)) || diff --git a/missing.h b/missing.h index 20f7193..4c7ac57 100644 --- a/missing.h +++ b/missing.h @@ -73,6 +73,12 @@ struct so_timestamping { }; #endif +#ifndef HWTSTAMP_FLAG_BONDED_PHC_INDEX +enum { + HWTSTAMP_FLAG_BONDED_PHC_INDEX = (1<<0), +}; +#endif + #ifdef PTP_EXTTS_REQUEST2 #define PTP_EXTTS_REQUEST_FAILED "PTP_EXTTS_REQUEST2 failed: %m" #else diff --git a/p2p_tc.c b/p2p_tc.c index 75cb3b9..1164c9a 100644 --- a/p2p_tc.c +++ b/p2p_tc.c @@ -126,7 +126,12 @@ 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); + if (!interface_get_tsinfo(p->iface) && + (p->phc_index != interface_phc_index(p->iface))) + port_change_phc(p); + else + 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)) || diff --git a/port.c b/port.c index f2b666c..76e323f 100644 --- a/port.c +++ b/port.c @@ -2636,10 +2636,48 @@ 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); + + /* Ensure TS_LABEL_CHANGED is set for failover when + * PHC changed as we may not call port_change_phc() + * from port_link_status(). + */ + p->link_status |= TS_LABEL_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; @@ -2663,32 +2701,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); } /* @@ -2802,7 +2815,12 @@ 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); + if (!interface_get_tsinfo(p->iface) && + (p->phc_index != interface_phc_index(p->iface))) + port_change_phc(p); + else + 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)) || diff --git a/port_private.h b/port_private.h index d27dceb..2a800a9 100644 --- a/port_private.h +++ b/port_private.h @@ -179,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 b55d6b5..80075be 100644 --- a/sk.c +++ b/sk.c @@ -66,6 +66,11 @@ static int hwts_init(int fd, const char *device, int rx_filter, init_ifreq(&ifreq, &cfg, device); + 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); + switch (sk_hwts_filter_mode) { case HWTS_FILTER_CHECK: err = ioctl(fd, SIOCGHWTSTAMP, &ifreq); -- 2.35.1 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel