[PATCH v4 02/16] net/txgbe: use the requested speed in E56 AN setup
DORMANTno replies
From: Zaiyu Wang <hidden>
Date: 2026-09-22 12:54:43
Subsystem:
networking drivers, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
txgbe_e56_set_phy_link_mode() takes the speeds to advertise, but the
port does not use the argument: it is passed to
UNREFERENCED_PARAMETER(), and the AN base page is built from the
device id and from hw->phy.fiber_suppport_speed instead. The caller
therefore cannot narrow what is advertised, which is what kept a
10G request from reaching the base page on a 10G/40G part even
after the capability mask had been opened up.
Take the argument as a speed bitmask, as the base layer of the
out-of-tree driver does: gate the 10G and 25G advertisement on
speed, keep the 40G case on the device id, and use speed rather than
hw->phy.fiber_suppport_speed on the fiber/DAC path.
The AN restart paths also have no record of the caller speed to
re-apply. Record it in hw->phy.autoneg_advertised before setup_link(),
as the base layer does, and pass it from the watchdog and
training-restart paths instead of the hardcoded 10. The two readers
of that field keep their existing fallback to get_link_capabilities()
when it is zero.
Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane mode")
Cc: stable@dpdk.org
Signed-off-by: Zaiyu Wang <redacted>
---
drivers/net/txgbe/base/txgbe_aml40.c | 2 +-
drivers/net/txgbe/base/txgbe_e56_bp.c | 23 +++++++++++------------
drivers/net/txgbe/base/txgbe_e56_bp.h | 2 +-
drivers/net/txgbe/txgbe_ethdev.c | 22 +++++++++++++++++++---
4 files changed, 32 insertions(+), 17 deletions(-)
diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c
index 7c72b53f64..7476759d4d 100644
--- a/drivers/net/txgbe/base/txgbe_aml40.c
+++ b/drivers/net/txgbe/base/txgbe_aml40.c@@ -172,7 +172,7 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, if (link_up && hw->an_done && !autoneg_wait_to_complete) return status; rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 40, autoneg_wait_to_complete); + txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); rte_spinlock_unlock(&hw->phy_lock); return status; }
diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c
index d376d918df..7b8af0638d 100644
--- a/drivers/net/txgbe/base/txgbe_e56_bp.c
+++ b/drivers/net/txgbe/base/txgbe_e56_bp.c@@ -2091,13 +2091,11 @@ static int txgbe_set_phy_link_mode(struct txgbe_hw *hw, } int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, - u8 bp_link_mode, u32 need_restart) + u32 speed, u32 need_restart) { int status = 0; u32 rdata; - UNREFERENCED_PARAMETER(bp_link_mode); - hw->an_done = false; if (hw->curbp_link_mode == 10 && !need_restart) return 0;
@@ -2130,14 +2128,18 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, /* backplane 10G/25G/40G */ /* 10GKR:7-25KR:14/15-40GKR:8-40GCR:9 */ /* default all speed */ - if ((hw->device_id & 0xFF) == 0x10) { + if (speed & TXGBE_LINK_SPEED_10GB_FULL) { backplane_mode |= BIT(7); fec_advertise |= TXGBE_10G_FEC_ABL; - } else if ((hw->device_id & 0xFF) == 0x25) { + } + + if (speed & TXGBE_LINK_SPEED_25GB_FULL) { backplane_mode |= BIT(14) | BIT(15); fec_advertise |= TXGBE_25G_RS_FEC_REQ | TXGBE_25G_BASE_FEC_REQ; - } else if ((hw->device_id & 0xFF) == 0x40) { + } + + if ((hw->device_id & 0xFF) == 0x40) { if (hw->phy.bp_capa == 0) /* original configure: KR4 + CR4 */ backplane_mode |= BIT(9) | BIT(8);
@@ -2151,21 +2153,18 @@ int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, BP_LOG("Advertised abilities: %d\n", backplane_mode); } } else { - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_10GB_FULL) - == TXGBE_LINK_SPEED_10GB_FULL) { + if (speed & TXGBE_LINK_SPEED_10GB_FULL) { backplane_mode |= 0x80; fec_advertise |= TXGBE_10G_FEC_ABL; } - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_25GB_FULL) - == TXGBE_LINK_SPEED_25GB_FULL) { + if (speed & TXGBE_LINK_SPEED_25GB_FULL) { backplane_mode |= 0xc000; fec_advertise |= TXGBE_25G_RS_FEC_REQ | TXGBE_25G_BASE_FEC_REQ; } - if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_40GB_FULL) - == TXGBE_LINK_SPEED_40GB_FULL) { + if (speed & TXGBE_LINK_SPEED_40GB_FULL) { backplane_mode |= BIT(9) | BIT(8); fec_advertise |= TXGBE_10G_FEC_ABL; }
diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h
index d2c49c2fce..8089e5b971 100644
--- a/drivers/net/txgbe/base/txgbe_e56_bp.h
+++ b/drivers/net/txgbe/base/txgbe_e56_bp.h@@ -277,6 +277,6 @@ typedef union { #define E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I 8, 4 int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, - u8 bp_link_mode, u32 need_restart); + u32 speed, u32 need_restart); int txgbe_handle_e56_bkp_an73_flow(struct txgbe_hw *hw); #endif
diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c
index bc2e11e801..69c94992ae 100644
--- a/drivers/net/txgbe/txgbe_ethdev.c
+++ b/drivers/net/txgbe/txgbe_ethdev.c@@ -1936,6 +1936,20 @@ txgbe_dev_start(struct rte_eth_dev *dev) hw->autoneg = false; } + /* Record the caller speed before setup_link so that the AN + * restart paths can re-apply the same configuration. + */ + hw->phy.autoneg_advertised = 0; + + if (speed & TXGBE_LINK_SPEED_40GB_FULL) + hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_40GB_FULL; + + if (speed & TXGBE_LINK_SPEED_25GB_FULL) + hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_25GB_FULL; + + if (speed & TXGBE_LINK_SPEED_10GB_FULL) + hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_10GB_FULL; + err = hw->mac.setup_link(hw, speed, link_up); if (err) goto error;
@@ -3017,7 +3031,7 @@ void txgbe_dev_e56_check_bp_event(void *param) value &= ~TXGBE_E56_AN_TXDIS; wr32_epcs(hw, VR_AN_INTR, value); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); goto an_status; }
@@ -3032,7 +3046,8 @@ void txgbe_dev_e56_check_bp_event(void *param) if (ret) { BP_LOG("Training FAILED, do reset\n"); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, + hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); } else { BP_LOG("ALL SUCCEEDED\n");
@@ -3041,7 +3056,8 @@ void txgbe_dev_e56_check_bp_event(void *param) if (ret) { BP_LOG("Training FAILED, do reset\n"); rte_spinlock_lock(&hw->phy_lock); - txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + txgbe_e56_set_phy_link_mode(hw, hw->phy.autoneg_advertised, + hw->bypass_ctle); rte_spinlock_unlock(&hw->phy_lock); } else { hw->an_done = true;
--
2.55.0.windows.2