[PATCH 8/9] net/ngbe: fix link status in no LSC mode

Jiawen Wu jiawenwu at trustnetic.com
Wed Jun 14 04:34:28 CEST 2023


When using no LSC mode, device link status is sometimes get incorrectly.
Introduce hw->lsc to fix this issue.

Fixes: 3d0af7066759 ("net/ngbe: setup PHY link")
Fixes: 3518df5774c7 ("net/ngbe: support device start/stop")
Cc: stable at dpdk.org

Signed-off-by: Jiawen Wu <jiawenwu at trustnetic.com>
---
 drivers/net/ngbe/base/ngbe_hw.c      | 10 +++++++---
 drivers/net/ngbe/base/ngbe_phy_rtl.c | 20 ++++++++++++++++++++
 drivers/net/ngbe/base/ngbe_phy_rtl.h |  2 ++
 drivers/net/ngbe/base/ngbe_phy_yt.c  | 16 +++++++++-------
 drivers/net/ngbe/base/ngbe_type.h    |  1 +
 drivers/net/ngbe/ngbe_ethdev.c       |  2 ++
 6 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c
index 283cdca367..27243d85c8 100644
--- a/drivers/net/ngbe/base/ngbe_hw.c
+++ b/drivers/net/ngbe/base/ngbe_hw.c
@@ -1541,11 +1541,15 @@ s32 ngbe_clear_vfta(struct ngbe_hw *hw)
 s32 ngbe_check_mac_link_em(struct ngbe_hw *hw, u32 *speed,
 			bool *link_up, bool link_up_wait_to_complete)
 {
-	u32 i, reg;
+	u32 i;
 	s32 status = 0;
 
-	reg = rd32(hw, NGBE_GPIOINTSTAT);
-	wr32(hw, NGBE_GPIOEOI, reg);
+	if (hw->lsc) {
+		u32 reg;
+
+		reg = rd32(hw, NGBE_GPIOINTSTAT);
+		wr32(hw, NGBE_GPIOEOI, reg);
+	}
 
 	if (link_up_wait_to_complete) {
 		for (i = 0; i < hw->mac.max_link_up_time; i++) {
diff --git a/drivers/net/ngbe/base/ngbe_phy_rtl.c b/drivers/net/ngbe/base/ngbe_phy_rtl.c
index 88bacec114..b0eb6c97c0 100644
--- a/drivers/net/ngbe/base/ngbe_phy_rtl.c
+++ b/drivers/net/ngbe/base/ngbe_phy_rtl.c
@@ -392,6 +392,26 @@ s32 ngbe_check_phy_link_rtl(struct ngbe_hw *hw, u32 *speed, bool *link_up)
 			*speed = NGBE_LINK_SPEED_10M_FULL;
 	}
 
+	if (hw->lsc)
+		return status;
+
+	/*
+	 * Because of the slow speed of getting link state, RTL_PHYSR
+	 * may still be up while the actual link state is down.
+	 * So we read RTL_GBSR to get accurate state when speed is 1G
+	 * in polling mode.
+	 */
+	if (*speed == NGBE_LINK_SPEED_1GB_FULL) {
+		status = hw->phy.read_reg(hw, RTL_GBSR,
+				RTL_DEV_ZERO, &phy_data);
+		phy_link = phy_data & RTL_GBSR_LRS;
+
+		/* Only need to detect link down */
+		if (!phy_link) {
+			*link_up = false;
+			*speed = NGBE_LINK_SPEED_UNKNOWN;
+		}
+	}
 	return status;
 }
 
diff --git a/drivers/net/ngbe/base/ngbe_phy_rtl.h b/drivers/net/ngbe/base/ngbe_phy_rtl.h
index b2fbc4f74d..6093ee7d5c 100644
--- a/drivers/net/ngbe/base/ngbe_phy_rtl.h
+++ b/drivers/net/ngbe/base/ngbe_phy_rtl.h
@@ -35,6 +35,8 @@
 #define   RTL_ANLPAR_LP			MS16(10, 0x3)
 #define RTL_GBCR			0x9
 #define   RTL_GBCR_1000F		MS16(9, 0x1)
+#define RTL_GBSR			0xA
+#define   RTL_GBSR_LRS			MS16(13, 0x1)
 /* Page 0xa42*/
 #define RTL_GSR				0x10
 #define   RTL_GSR_ST			MS16(0, 0x7)
diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.c b/drivers/net/ngbe/base/ngbe_phy_yt.c
index 726d6c8ef5..754faadd6a 100644
--- a/drivers/net/ngbe/base/ngbe_phy_yt.c
+++ b/drivers/net/ngbe/base/ngbe_phy_yt.c
@@ -102,13 +102,15 @@ s32 ngbe_init_phy_yt(struct ngbe_hw *hw)
 {
 	rte_spinlock_init(&hw->phy_lock);
 
-	rte_spinlock_lock(&hw->phy_lock);
-	/* close sds area register */
-	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
-	/* enable interrupts */
-	ngbe_write_phy_reg_mdi(hw, YT_INTR, 0,
-				YT_INTR_ENA_MASK | YT_SDS_INTR_ENA_MASK);
-	rte_spinlock_unlock(&hw->phy_lock);
+	if (hw->lsc) {
+		rte_spinlock_lock(&hw->phy_lock);
+		/* close sds area register */
+		ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
+		/* enable interrupts */
+		ngbe_write_phy_reg_mdi(hw, YT_INTR, 0,
+					YT_INTR_ENA_MASK | YT_SDS_INTR_ENA_MASK);
+		rte_spinlock_unlock(&hw->phy_lock);
+	}
 
 	hw->phy.set_phy_power(hw, false);
 
diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h
index 05804eeab7..37be288a74 100644
--- a/drivers/net/ngbe/base/ngbe_type.h
+++ b/drivers/net/ngbe/base/ngbe_type.h
@@ -431,6 +431,7 @@ struct ngbe_hw {
 	bool offset_loaded;
 	bool is_pf;
 	bool gpio_ctl;
+	bool lsc;
 	u32 led_conf;
 	bool init_phy;
 	rte_spinlock_t phy_lock;
diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c
index 836ecfa2da..317ad6999c 100644
--- a/drivers/net/ngbe/ngbe_ethdev.c
+++ b/drivers/net/ngbe/ngbe_ethdev.c
@@ -1052,6 +1052,8 @@ ngbe_dev_start(struct rte_eth_dev *dev)
 	if (hw->is_pf && dev->data->dev_conf.lpbk_mode)
 		goto skip_link_setup;
 
+	hw->lsc = dev->data->dev_conf.intr_conf.lsc;
+
 	err = hw->mac.check_link(hw, &speed, &link_up, 0);
 	if (err != 0)
 		goto error;
-- 
2.27.0



More information about the stable mailing list