From nobody Tue Dec 2 02:19:09 2025 Received: from smtp.blochl.de (mail.blochl.de [151.80.40.192]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7B88534104E; Wed, 19 Nov 2025 16:15:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=151.80.40.192 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763568930; cv=none; b=FXbwlY34h4hqJ48gpURUdgT09al67ogzdocZuvdTWyR+vpCU2R6lzf9dFStGmUPuB44RJagPIvYIsjjCtB8dkTJ/OZ40ZwurVHJuUsEbnkfTPIbRHQzMEdiDuEIbA0H3boC053/kclm8YWfJc+2Rupv7Hsx28Cm5p4G25Vixi5s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763568930; c=relaxed/simple; bh=LdnLu++HLZnRwZZrapuQ9JqYkYCX+rox/PeY/x+F7VM=; h=Date:From:To:Cc:Subject:Message-ID:MIME-Version:Content-Type: Content-Disposition; b=dQ6FmcYBR1TVMnrK0AvU+kvlDEdpaFGZhS7aOA2BnxeTeKM88kDwEoM8LrmLNJGl88T7wpL/So2i+mZa6WRVuJOe3GZQ4chf0/32HROxRcAn2siPCns9kAsMlHtWOkF+PnpYK8QTMj3OxQKif0/Jh7wlcCdzUQoEgl6MAhApRuU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=blochl.de; spf=pass smtp.mailfrom=blochl.de; arc=none smtp.client-ip=151.80.40.192 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=blochl.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=blochl.de DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.blochl.de 101F94641E88 Authentication-Results: mail.blochl.de; dmarc=none (p=none dis=none) header.from=blochl.de Authentication-Results: mail.blochl.de; spf=fail smtp.mailfrom=blochl.de Received: from WorkKnecht (ppp-93-104-13-154.dynamic.mnet-online.de [93.104.13.154]) by smtp.blochl.de (Postfix) with ESMTPSA id 101F94641E88; Wed, 19 Nov 2025 16:09:49 +0000 (UTC) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 1.4.3 at 449b6f9d6baf Date: Wed, 19 Nov 2025 17:09:43 +0100 From: Markus =?utf-8?Q?Bl=C3=B6chl?= To: Tony Nguyen , Przemek Kitszel , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: Richard Cochran , Markus =?utf-8?Q?Bl=C3=B6chl?= , intel-wired-lan@lists.osuosl.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] i40e: fix ptp time increment while link is down Message-ID: <20251119-i40e_ptp_link_down-v1-1-b351fed254b3@blochl.de> X-B4-Tracking: v=1; b=H4sIAJjpHWkC/x3MQQqAIBBA0avErBOaUsKuEiGRUw2FiUYF4d2Tl m/x/wuRAlOErngh0MWRD5eBZQHTOrqFBNtsqKtaIaIWLCsy/vRmZ7cZe9xOyFY3ctaESlnIoQ8 08/NP+yGlD7UPWh5kAAAA X-Change-ID: 20251119-i40e_ptp_link_down-47934f9e155d X-Mailer: b4 0.14.3 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Disposition: inline Content-Transfer-Encoding: quoted-printable X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.6.4 (smtp.blochl.de [0.0.0.0]); Wed, 19 Nov 2025 16:09:49 +0000 (UTC) When an X710 ethernet port with an active ptp daemon (like the ptp4l and ph= c2sys combo) suddenly loses its link and regains it after a while, the ptp daemon has a = hard time to recover synchronization and sometimes entirely fails to do so. The issue seems to be related to a wrongly configured increment while the l= ink is down. This could not be observed with the Intel reference driver. We identified t= he fix to appear in Intels official ethernet-linux-i40e release version 2.17.4. Include the relevant changes in the kernel version of this driver. Fixes: beb0dff1251d ("i40e: enable PTP") Cc: stable@vger.kernel.org Signed-off-by: Markus Bl=C3=B6chl Reviewed-by: Jacob Keller --- Tested with an X710 at 10G link speed and kernel version 6.12.42. --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 9 +++ drivers/net/ethernet/intel/i40e/i40e_ptp.c | 68 +++++++++++++++++++= ++-- drivers/net/ethernet/intel/i40e/i40e_register.h | 9 +++ drivers/net/ethernet/intel/i40e/i40e_type.h | 8 +++ 4 files changed, 89 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/ne= t/ethernet/intel/i40e/i40e_adminq_cmd.h index cc02a85ad42b..ec176e9569ad 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -1488,6 +1488,15 @@ enum i40e_aq_link_speed { I40E_LINK_SPEED_25GB =3D BIT(I40E_LINK_SPEED_25GB_SHIFT), }; =20 +enum i40e_prt_mac_pcs_link_speed { + I40E_PRT_MAC_PCS_LINK_SPEED_UNKNOWN =3D 0, + I40E_PRT_MAC_PCS_LINK_SPEED_100MB, + I40E_PRT_MAC_PCS_LINK_SPEED_1GB, + I40E_PRT_MAC_PCS_LINK_SPEED_10GB, + I40E_PRT_MAC_PCS_LINK_SPEED_40GB, + I40E_PRT_MAC_PCS_LINK_SPEED_20GB +}; + struct i40e_aqc_module_desc { u8 oui[3]; u8 reserved1; diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ether= net/intel/i40e/i40e_ptp.c index 33535418178b..ee6927e2c6f8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c @@ -847,6 +847,65 @@ void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct s= k_buff *skb, u8 index) i40e_ptp_convert_to_hwtstamp(skb_hwtstamps(skb), ns); } =20 +/** + * i40e_ptp_get_link_speed_hw - get the link speed + * @pf: Board private structure + * + * Calculate link speed depending on the link status. + * Return the link speed. + **/ +static enum i40e_aq_link_speed i40e_ptp_get_link_speed_hw(struct i40e_pf *= pf) +{ + bool link_up =3D pf->hw.phy.link_info.link_info & I40E_AQ_LINK_UP; + enum i40e_aq_link_speed link_speed =3D I40E_LINK_SPEED_UNKNOWN; + struct i40e_hw *hw =3D &pf->hw; + + if (link_up) { + struct i40e_link_status *hw_link_info =3D &hw->phy.link_info; + + i40e_aq_get_link_info(hw, true, NULL, NULL); + link_speed =3D hw_link_info->link_speed; + } else { + enum i40e_prt_mac_link_speed prtmac_linksta; + u64 prtmac_pcs_linksta; + + prtmac_linksta =3D (rd32(hw, I40E_PRTMAC_LINKSTA(0)) + & I40E_PRTMAC_LINKSTA_MAC_LINK_SPEED_MASK) + >> I40E_PRTMAC_LINKSTA_MAC_LINK_SPEED_SHIFT; + if (prtmac_linksta =3D=3D I40E_PRT_MAC_LINK_SPEED_40GB) { + link_speed =3D I40E_LINK_SPEED_40GB; + } else { + i40e_aq_debug_read_register(hw, + I40E_PRTMAC_PCS_LINK_STATUS1(0), + &prtmac_pcs_linksta, + NULL); + + prtmac_pcs_linksta =3D (prtmac_pcs_linksta + & I40E_PRTMAC_PCS_LINK_STATUS1_LINK_SPEED_MASK) + >> I40E_PRTMAC_PCS_LINK_STATUS1_LINK_SPEED_SHIFT; + + switch (prtmac_pcs_linksta) { + case I40E_PRT_MAC_PCS_LINK_SPEED_100MB: + link_speed =3D I40E_LINK_SPEED_100MB; + break; + case I40E_PRT_MAC_PCS_LINK_SPEED_1GB: + link_speed =3D I40E_LINK_SPEED_1GB; + break; + case I40E_PRT_MAC_PCS_LINK_SPEED_10GB: + link_speed =3D I40E_LINK_SPEED_10GB; + break; + case I40E_PRT_MAC_PCS_LINK_SPEED_20GB: + link_speed =3D I40E_LINK_SPEED_20GB; + break; + default: + link_speed =3D I40E_LINK_SPEED_UNKNOWN; + } + } + } + + return link_speed; +} + /** * i40e_ptp_set_increment - Utility function to update clock increment rate * @pf: Board private structure @@ -857,16 +916,14 @@ void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct = sk_buff *skb, u8 index) **/ void i40e_ptp_set_increment(struct i40e_pf *pf) { - struct i40e_link_status *hw_link_info; + enum i40e_aq_link_speed link_speed; struct i40e_hw *hw =3D &pf->hw; u64 incval; u32 mult; =20 - hw_link_info =3D &hw->phy.link_info; + link_speed =3D i40e_ptp_get_link_speed_hw(pf); =20 - i40e_aq_get_link_info(&pf->hw, true, NULL, NULL); - - switch (hw_link_info->link_speed) { + switch (link_speed) { case I40E_LINK_SPEED_10GB: mult =3D I40E_PTP_10GB_INCVAL_MULT; break; @@ -909,6 +966,7 @@ void i40e_ptp_set_increment(struct i40e_pf *pf) /* Update the base adjustement value. */ WRITE_ONCE(pf->ptp_adj_mult, mult); smp_mb(); /* Force the above update. */ + i40e_ptp_set_1pps_signal_hw(pf); } =20 /** diff --git a/drivers/net/ethernet/intel/i40e/i40e_register.h b/drivers/net/= ethernet/intel/i40e/i40e_register.h index 432afbb64201..c4051dbcc297 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_register.h +++ b/drivers/net/ethernet/intel/i40e/i40e_register.h @@ -530,6 +530,15 @@ #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT 0 #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK I40E_MASK(0xFFFF,= \ I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT) +/* _i=3D0...3 */ /* Reset: GLOBR */ +#define I40E_PRTMAC_PCS_LINK_STATUS1(_i) (0x0008C200 + ((_i) * 4)) +#define I40E_PRTMAC_PCS_LINK_STATUS1_LINK_SPEED_SHIFT 24 +#define I40E_PRTMAC_PCS_LINK_STATUS1_LINK_SPEED_MASK I40E_MASK(0x7, I40E_P= RTMAC_PCS_LINK_STATUS1_LINK_SPEED_SHIFT) +#define I40E_PRTMAC_PCS_LINK_STATUS2 0x0008C220 +/* _i=3D0...3 */ /* Reset: GLOBR */ +#define I40E_PRTMAC_LINKSTA(_i) (0x001E2420 + ((_i) * 4)) +#define I40E_PRTMAC_LINKSTA_MAC_LINK_SPEED_SHIFT 27 +#define I40E_PRTMAC_LINKSTA_MAC_LINK_SPEED_MASK I40E_MASK(0x7, I40E_PRTMAC= _LINKSTA_MAC_LINK_SPEED_SHIFT) #define I40E_GLNVM_FLA 0x000B6108 /* Reset: POR */ #define I40E_GLNVM_FLA_LOCKED_SHIFT 6 #define I40E_GLNVM_FLA_LOCKED_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_LOCKED_SH= IFT) diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethe= rnet/intel/i40e/i40e_type.h index ed8bbdb586da..98c8c5709e5f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -115,6 +115,14 @@ enum i40e_queue_type { I40E_QUEUE_TYPE_UNKNOWN }; =20 +enum i40e_prt_mac_link_speed { + I40E_PRT_MAC_LINK_SPEED_100MB =3D 0, + I40E_PRT_MAC_LINK_SPEED_1GB, + I40E_PRT_MAC_LINK_SPEED_10GB, + I40E_PRT_MAC_LINK_SPEED_40GB, + I40E_PRT_MAC_LINK_SPEED_20GB +}; + struct i40e_link_status { enum i40e_aq_phy_type phy_type; enum i40e_aq_link_speed link_speed; --- base-commit: 8b690556d8fe074b4f9835075050fba3fb180e93 change-id: 20251119-i40e_ptp_link_down-47934f9e155d Best regards, --=20 Markus Bl=C3=B6chl --=20