summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorPetr Oros <poros@redhat.com>2026-04-27 22:22:20 -0700
committerPaolo Abeni <pabeni@redhat.com>2026-04-30 11:37:39 +0200
commit6f9d8393c9f50fbc68b9c9e99f78ca5a7b43ff44 (patch)
treea6be3b768a9ab77971f9b0cac5ccce5a330b333e /drivers/net
parent56a643aed0f0af5c29ebb4593d4917b78344dd48 (diff)
ice: fix SMA and U.FL pin state changes affecting paired pin
SMA and U.FL pins share physical signal paths in pairs (SMA1/U.FL1 and SMA2/U.FL2) controlled by the PCA9575 GPIO expander. Each pair can only have one active pin at a time: SMA1 output and U.FL1 output share the same CGU output, SMA2 input and U.FL2 input share the same CGU input. The PCA9575 register bits determine which connector in each pair owns the signal path. The driver does not account for this pairing in two places: ice_dpll_ufl_pin_state_set() modifies PCA9575 bits and disables the backing CGU pin without checking whether the U.FL pin is currently active. Disconnecting an already inactive U.FL pin flips bits that the paired SMA pin relies on, breaking its connection. ice_dpll_sma_direction_set() does not propagate direction changes to the paired U.FL pin. For SMA2/U.FL2 the ICE_SMA2_UFL2_RX_DIS bit is never managed, so U.FL2 stays disconnected after SMA2 switches to output. For both pairs the backing CGU pin of the U.FL side is never enabled when a direction change activates it, so userspace sees the pin as disconnected even though the routing is correct. Fix by guarding the U.FL disconnect path against inactive pins and by updating the paired U.FL pin fully on SMA direction changes: manage ICE_SMA2_UFL2_RX_DIS for the SMA2/U.FL2 pair and enable the backing CGU pin whenever the peer becomes active. Fixes: 2dd5d03c77e2 ("ice: redesign dpll sma/u.fl pins control") Signed-off-by: Petr Oros <poros@redhat.com> Tested-by: Alexander Nowlin <alexander.nowlin@intel.com> Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> Link: https://patch.msgid.link/20260427-jk-iwl-net-petr-oros-fixes-v1-8-cdcb48303fd8@intel.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/intel/ice/ice_dpll.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c
index 498ec2c045f3..3f8cd5b8298b 100644
--- a/drivers/net/ethernet/intel/ice/ice_dpll.c
+++ b/drivers/net/ethernet/intel/ice/ice_dpll.c
@@ -1171,6 +1171,8 @@ static int ice_dpll_sma_direction_set(struct ice_dpll_pin *p,
enum dpll_pin_direction direction,
struct netlink_ext_ack *extack)
{
+ struct ice_dplls *d = &p->pf->dplls;
+ struct ice_dpll_pin *peer;
u8 data;
int ret;
@@ -1189,8 +1191,9 @@ static int ice_dpll_sma_direction_set(struct ice_dpll_pin *p,
case ICE_DPLL_PIN_SW_2_IDX:
if (direction == DPLL_PIN_DIRECTION_INPUT) {
data &= ~ICE_SMA2_DIR_EN;
+ data |= ICE_SMA2_UFL2_RX_DIS;
} else {
- data &= ~ICE_SMA2_TX_EN;
+ data &= ~(ICE_SMA2_TX_EN | ICE_SMA2_UFL2_RX_DIS);
data |= ICE_SMA2_DIR_EN;
}
break;
@@ -1202,6 +1205,34 @@ static int ice_dpll_sma_direction_set(struct ice_dpll_pin *p,
ret = ice_dpll_pin_state_update(p->pf, p,
ICE_DPLL_PIN_TYPE_SOFTWARE,
extack);
+ if (ret)
+ return ret;
+
+ /* When a direction change activates the paired U.FL pin, enable
+ * its backing CGU pin so the pin reports as connected. Without
+ * this the U.FL routing is correct but the CGU pin stays disabled
+ * and userspace sees the pin as disconnected. Do not disable the
+ * backing pin when U.FL becomes inactive because the SMA pin may
+ * still be using it.
+ */
+ peer = &d->ufl[p->idx];
+ if (peer->active) {
+ struct ice_dpll_pin *target;
+ enum ice_dpll_pin_type type;
+
+ if (peer->output) {
+ target = peer->output;
+ type = ICE_DPLL_PIN_TYPE_OUTPUT;
+ } else {
+ target = peer->input;
+ type = ICE_DPLL_PIN_TYPE_INPUT;
+ }
+ ret = ice_dpll_pin_enable(&p->pf->hw, target,
+ d->eec.dpll_idx, type, extack);
+ if (!ret)
+ ret = ice_dpll_pin_state_update(p->pf, target,
+ type, extack);
+ }
return ret;
}
@@ -1253,6 +1284,14 @@ ice_dpll_ufl_pin_state_set(const struct dpll_pin *pin, void *pin_priv,
data &= ~ICE_SMA1_MASK;
enable = true;
} else if (state == DPLL_PIN_STATE_DISCONNECTED) {
+ /* Skip if U.FL1 is not active, setting TX_EN
+ * while DIR_EN is set would also deactivate
+ * the paired SMA1 output.
+ */
+ if (data & (ICE_SMA1_DIR_EN | ICE_SMA1_TX_EN)) {
+ ret = 0;
+ goto unlock;
+ }
data |= ICE_SMA1_TX_EN;
enable = false;
} else {
@@ -1267,6 +1306,15 @@ ice_dpll_ufl_pin_state_set(const struct dpll_pin *pin, void *pin_priv,
data &= ~ICE_SMA2_UFL2_RX_DIS;
enable = true;
} else if (state == DPLL_PIN_STATE_DISCONNECTED) {
+ /* Skip if U.FL2 is not active, setting
+ * UFL2_RX_DIS could also disable the paired
+ * SMA2 input.
+ */
+ if (!(data & ICE_SMA2_DIR_EN) ||
+ (data & ICE_SMA2_UFL2_RX_DIS)) {
+ ret = 0;
+ goto unlock;
+ }
data |= ICE_SMA2_UFL2_RX_DIS;
enable = false;
} else {