Add the RHEL 687.11.1..687.12.1 backports (1198-1252) sourced from centos-stream-9 and upstream stable, on top of 687.10.1. Bump to 5.14.0-687.12.1.
137 lines
5.6 KiB
Diff
137 lines
5.6 KiB
Diff
From c0a575a801a2040eb1e0db54b488f8c548c8458a Mon Sep 17 00:00:00 2001
|
|
From: Grzegorz Nitka <grzegorz.nitka@intel.com>
|
|
Date: Mon, 20 Apr 2026 17:51:25 -0700
|
|
Subject: [PATCH] ice: fix timestamp interrupt configuration for E825C
|
|
|
|
The E825C ice_phy_cfg_intr_eth56g() function is responsible for programming
|
|
the PHY interrupt for a given port. This function writes to the
|
|
PHY_REG_TS_INT_CONFIG register of the port. The register is responsible for
|
|
configuring whether the port interrupt logic is enabled, as well as
|
|
programming the threshold of waiting timestamps that will trigger an
|
|
interrupt from this port.
|
|
|
|
This threshold value must not be programmed to zero while the interrupt is
|
|
enabled. Doing so puts the port in a misconfigured state where the PHY
|
|
timestamp interrupt for the quad of connected ports will become stuck.
|
|
|
|
This occurs, because a threshold of zero results in the timestamp interrupt
|
|
status for the port becoming stuck high. The four ports in the connected
|
|
quad have their timestamp status indicators muxed together. A new interrupt
|
|
cannot be generated until the timestamp status indicators return low for
|
|
all four ports.
|
|
|
|
Normally, the timestamp status for a port will clear once there are fewer
|
|
timestamps in that ports timestamp memory bank than the threshold. A
|
|
threshold of zero makes this impossible, so the timestamp status for the
|
|
port does not clear.
|
|
|
|
The ice driver never intentionally programs the threshold to zero, indeed
|
|
the driver always programs it to a value of 1, intending to get an
|
|
interrupt immediately as soon as even a single packet is waiting for a
|
|
timestamp.
|
|
|
|
However, there is a subtle flaw in the programming logic in the
|
|
ice_phy_cfg_intr_eth56g() function. Due to the way that the hardware
|
|
handles enabling the PHY interrupt. If the threshold value is modified at
|
|
the same time as the interrupt is enabled, the HW PHY state machine might
|
|
enable the interrupt before the new threshold value is actually updated.
|
|
This leaves a potential race condition caused by the hardware logic where
|
|
a PHY timestamp interrupt might be triggered before the non-zero threshold
|
|
is written, resulting in the PHY timestamp logic becoming stuck.
|
|
|
|
Once the PHY timestamp status is stuck high, it will remain stuck even
|
|
after attempting to reprogram the PHY block by changing its threshold or
|
|
disabling the interrupt. Even a typical PF or CORE reset will not reset the
|
|
particular block of the PHY that becomes stuck. Even a warm power cycle is
|
|
not guaranteed to cause the PHY block to reset, and a cold power cycle is
|
|
required.
|
|
|
|
Prevent this by always writing the PHY_REG_TS_INT_CONFIG in two stages.
|
|
First write the threshold value with the interrupt disabled, and only write
|
|
the enable bit after the threshold has been programmed. When disabling the
|
|
interrupt, leave the threshold unchanged. Additionally, re-read the
|
|
register after writing it to guarantee that the write to the PHY has been
|
|
flushed upon exit of the function.
|
|
|
|
While we're modifying this function implementation, explicitly reject
|
|
programming a threshold of 0 when enabling the interrupt. No caller does
|
|
this today, but the consequences of doing so are significant. An explicit
|
|
rejection in the code makes this clear.
|
|
|
|
Fixes: 7cab44f1c35f ("ice: Introduce ETH56G PHY model for E825C products")
|
|
Signed-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
|
|
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
|
|
Reviewed-by: Petr Oros <poros@redhat.com>
|
|
Tested-by: Sunitha Mekala <sunithax.d.mekala@intel.com>
|
|
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
|
|
Reviewed-by: Simon Horman <horms@kernel.org>
|
|
Link: https://patch.msgid.link/20260420-jk-iwl-net-2026-04-20-ptp-e825c-phy-interrupt-fixes-v1-1-bc2240f42251@intel.com
|
|
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
|
|
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
|
|
index 5a5c511ccbb6..7f2f7440e705 100644
|
|
--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
|
|
+++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
|
|
@@ -1847,6 +1847,8 @@ static int ice_phy_cfg_mac_eth56g(struct ice_hw *hw, u8 port)
|
|
* @ena: enable or disable interrupt
|
|
* @threshold: interrupt threshold
|
|
*
|
|
+ * The threshold cannot be 0 while the interrupt is enabled.
|
|
+ *
|
|
* Configure TX timestamp interrupt for the specified port
|
|
*
|
|
* Return:
|
|
@@ -1858,19 +1860,45 @@ int ice_phy_cfg_intr_eth56g(struct ice_hw *hw, u8 port, bool ena, u8 threshold)
|
|
int err;
|
|
u32 val;
|
|
|
|
+ if (ena && !threshold)
|
|
+ return -EINVAL;
|
|
+
|
|
err = ice_read_ptp_reg_eth56g(hw, port, PHY_REG_TS_INT_CONFIG, &val);
|
|
if (err)
|
|
return err;
|
|
|
|
+ val &= ~PHY_TS_INT_CONFIG_ENA_M;
|
|
if (ena) {
|
|
- val |= PHY_TS_INT_CONFIG_ENA_M;
|
|
val &= ~PHY_TS_INT_CONFIG_THRESHOLD_M;
|
|
val |= FIELD_PREP(PHY_TS_INT_CONFIG_THRESHOLD_M, threshold);
|
|
- } else {
|
|
- val &= ~PHY_TS_INT_CONFIG_ENA_M;
|
|
+ err = ice_write_ptp_reg_eth56g(hw, port, PHY_REG_TS_INT_CONFIG,
|
|
+ val);
|
|
+ if (err) {
|
|
+ ice_debug(hw, ICE_DBG_PTP,
|
|
+ "Failed to update 'threshold' PHY_REG_TS_INT_CONFIG port=%u ena=%u threshold=%u\n",
|
|
+ port, !!ena, threshold);
|
|
+ return err;
|
|
+ }
|
|
+ val |= PHY_TS_INT_CONFIG_ENA_M;
|
|
}
|
|
|
|
- return ice_write_ptp_reg_eth56g(hw, port, PHY_REG_TS_INT_CONFIG, val);
|
|
+ err = ice_write_ptp_reg_eth56g(hw, port, PHY_REG_TS_INT_CONFIG, val);
|
|
+ if (err) {
|
|
+ ice_debug(hw, ICE_DBG_PTP,
|
|
+ "Failed to update 'ena' PHY_REG_TS_INT_CONFIG port=%u ena=%u threshold=%u\n",
|
|
+ port, !!ena, threshold);
|
|
+ return err;
|
|
+ }
|
|
+
|
|
+ err = ice_read_ptp_reg_eth56g(hw, port, PHY_REG_TS_INT_CONFIG, &val);
|
|
+ if (err) {
|
|
+ ice_debug(hw, ICE_DBG_PTP,
|
|
+ "Failed to read PHY_REG_TS_INT_CONFIG port=%u ena=%u threshold=%u\n",
|
|
+ port, !!ena, threshold);
|
|
+ return err;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
/**
|
|
--
|
|
2.50.1 (Apple Git-155)
|
|
|