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: [email protected]
Signed-off-by: Zaiyu Wang <[email protected]>
---
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