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

Reply via email to