[PATCH iwl-net v4 05/13] ice: call PTP link change only from link events
flat view
WARM1d
SUPERSEDED: 3 (0M)
From: Jacob Keller <jacob.e.keller@intel.com>
Date: 2026-10-20 09:46:18
Subsystem:
intel ethernet drivers, networking drivers, the rest · Maintainers:
Tony Nguyen, Przemek Kitszel, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
Revision v4 of 6 in this series; 3 review trailers.
Revisions (6)
From: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
The ice_ptp_link_change() function is currently called from
ice_up_complete() and ice_down(). The up and down functions are called from
many places including a variety of administrative tasks such as MTU change.
When called, the ice_ptp_link_change() function forces the PHY to restart,
which can be destructive to ongoing timestamps. We must restart the
timestamping block if the link has changed, but we do not need to restart
it for most of the administrative tasks. The calls also cause unnecessary
re-initialization at every ice_open(), and trigger premature cleanup at
ice_down() even if the actual link hasn't dropped.
Ideally we only want to toggle a PHY timestamping block restart if the
physical link has changed or we are fully reconfiguring the clock. To that
end, stop calling ice_ptp_link_change() during ice_up_complete() and
ice_down().
Initialize the PTP link_up field at probe as part of ice_init_link(),
before the service task and link event handling are enabled. Change
ice_link_event() to call ice_ptp_link_change first before checking if the
link value is the same. Update ice_ptp_link_change to check the current PTP
link status and avoid triggering a restart when the link states match.
For the ice_rebuild() path, call ice_ptp_link_change() to ensure that the
PTP reflects the current link status if it changed while down. Make sure
the link state is current by having ice_update_pf_netdev_link() setting the
get_link_info field of the PF port info, ensuring the state is accurate.
These changes ensure that the link status will reflect the current state of
the physical link without needing to start and stop on every internal
ice_down_up() sequence.
This sequencing should ensure that any link transition will properly update
the PTP state to reflect the new mode, without causing unnecessary
duplicate starts and stops. By removing the calls from ice_up_complete()
and ice_down() the driver no longer unnecessarily thrashes the PTP state in
the hardware.
Finally, for E825, call ice_ptp_port_phy_restart() even when link is down.
This will ensure that the PHY is properly disabled immediately instead of
only calling the stop implementation after some other flow triggers a
restart.
Fixes: 6b1ff5d39228 ("ice: always call ice_ptp_link_change and make it void")
Reviewed-by: Aleksandr Loktionov <redacted>
Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Signed-off-by: Przemyslaw Korba <redacted>
Signed-off-by: Petr Oros <redacted>
Reviewed-by: Maciek Machnikowski <redacted>
Tested-by: Alexander Nowlin <redacted>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
---
drivers/net/ethernet/intel/ice/ice_main.c | 38 ++++++++++++++++++++-----------
drivers/net/ethernet/intel/ice/ice_ptp.c | 8 +++----
2 files changed, 29 insertions(+), 17 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index d88835482d3a..910ebdcdde19 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c@@ -1144,6 +1144,8 @@ ice_link_event(struct ice_pf *pf, struct ice_port_info *pi, bool link_up, ice_set_link(vsi, false); } + ice_ptp_link_change(pf, link_up); + /* if the old link up/down and speed is the same as the new */ if (link_up == old_link && link_speed == old_link_speed) return 0;
@@ -1151,8 +1153,6 @@ ice_link_event(struct ice_pf *pf, struct ice_port_info *pi, bool link_up, if (!link_up && old_link) pf->link_down_events++; - ice_ptp_link_change(pf, link_up); - if (ice_is_dcb_active(pf)) { if (test_bit(ICE_FLAG_DCB_ENA, pf->flags)) ice_dcb_rebuild(pf);
@@ -4810,6 +4810,14 @@ static void ice_init_link(struct ice_pf *pf) ice_init_link_dflt_override(pf->hw.port_info); + /* Seed PTP link status from current PHY status, since link may + * already be up (e.g. after PXE boot) without a link-change edge to + * catch it later. + */ + WRITE_ONCE(pf->ptp.port.link_up, + !!(pf->hw.port_info->phy.link_info.link_info & + ICE_AQ_LINK_UP)); + ice_check_link_cfg_err(pf, pf->hw.port_info->phy.link_info.link_cfg_err);
@@ -6745,7 +6753,6 @@ static int ice_up_complete(struct ice_vsi *vsi) ice_print_link_msg(vsi, true); netif_tx_start_all_queues(vsi->netdev); netif_carrier_on(vsi->netdev); - ice_ptp_link_change(pf, true); } /* Perform an initial read of the statistics registers now to
@@ -7273,7 +7280,6 @@ int ice_down(struct ice_vsi *vsi) if (vsi->netdev) { vlan_err = ice_vsi_del_vlan_zero(vsi); - ice_ptp_link_change(vsi->back, false); netif_carrier_off(vsi->netdev); netif_tx_disable(vsi->netdev); }
@@ -7623,13 +7629,15 @@ static void ice_update_pf_netdev_link(struct ice_pf *pf) if (!vsi || vsi->type != ICE_VSI_PF) return; - ice_get_link_status(pf->vsi[i]->port_info, &link_up); + /* Make sure to get current link info */ + vsi->port_info->phy.get_link_info = true; + ice_get_link_status(vsi->port_info, &link_up); if (link_up) { - netif_carrier_on(pf->vsi[i]->netdev); - netif_tx_wake_all_queues(pf->vsi[i]->netdev); + netif_carrier_on(vsi->netdev); + netif_tx_wake_all_queues(vsi->netdev); } else { - netif_carrier_off(pf->vsi[i]->netdev); - netif_tx_stop_all_queues(pf->vsi[i]->netdev); + netif_carrier_off(vsi->netdev); + netif_tx_stop_all_queues(vsi->netdev); } } }
@@ -7745,10 +7753,6 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) if (test_bit(ICE_FLAG_DCB_ENA, pf->flags)) ice_dcb_rebuild(pf); - /* If the PF previously had enabled PTP, PTP init needs to happen before - * the VSI rebuild. If not, this causes the PTP link status events to - * fail. - */ if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags)) ice_ptp_rebuild(pf, reset_type);
@@ -7794,6 +7798,14 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) ice_update_pf_netdev_link(pf); + if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags) && pf->hw.port_info) { + bool link_up; + + link_up = !!(pf->hw.port_info->phy.link_info.link_info & + ICE_AQ_LINK_UP); + ice_ptp_link_change(pf, link_up); + } + /* tell the firmware we are up */ err = ice_send_version(pf); if (err) {
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index 1e6ba6bbf6c2..f43918f334e8 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c@@ -1319,6 +1319,9 @@ void ice_ptp_link_change(struct ice_pf *pf, bool linkup) mutex_lock(&pf->adapter->ps_lock); + if (READ_ONCE(ptp_port->link_up) == linkup) + goto out_unlock; + WRITE_ONCE(ptp_port->link_up, linkup); if (pf->ptp.state != ICE_PTP_READY || pf->hw.reset_ongoing)
@@ -1367,11 +1370,8 @@ void ice_ptp_link_change(struct ice_pf *pf, bool linkup) /* Do not reconfigure E810 or E830 PHY */ break; case ICE_MAC_GENERIC: - ice_ptp_port_phy_restart(ptp_port); - break; case ICE_MAC_GENERIC_3K_E825: - if (linkup) - ice_ptp_port_phy_restart(ptp_port); + ice_ptp_port_phy_restart(ptp_port); break; default: dev_warn(ice_pf_to_dev(pf), "%s: Unknown PHY type\n", __func__);
--
2.56.0.212.g129ede20d986