diff mbox series

[SRU,J:linux-bluefield,v2,1/1] UBUNTU: SAUCE: mlxbf-gige: autonegotiation fails to complete on BF2

Message ID 20240430183627.12961-2-asmaa@nvidia.com
State New
Headers show
Series UBUNTU: SAUCE: mlxbf-gige: autonegotiation fails to complete on BF2 | expand

Commit Message

Asmaa Mnebhi April 30, 2024, 6:36 p.m. UTC
BugLink: https://bugs.launchpad.net/bugs/2062384

During their reboot test, QA found an intermittent issue where the OOB link is down.
The link is down because the KSZ9031 PHY fails to complete autonegotiation.
Even under "normal" circumstances where autonegotiation completes,
it takes an abnormal time to do so (on average, at least 8 seconds).

Hence, the hardware team and Microchip are involved in this debug but the root cause is still unknown.
In the meantime, we need to provide a software workaround since customers are starting to see this issue as well.

Signed-off-by: Asmaa Mnebhi <asmaa@nvidia.com>
Reviewed-by: David Thompson <davthompson@nvidia.com>
---
 .../mellanox/mlxbf_gige/mlxbf_gige_main.c       | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
diff mbox series

Patch

diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
index 56235cef5cd6..9c86b3b973a2 100644
--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
+++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
@@ -132,6 +132,7 @@  static int mlxbf_gige_open(struct net_device *netdev)
 {
 	struct mlxbf_gige *priv = netdev_priv(netdev);
 	struct phy_device *phydev = netdev->phydev;
+	u8 timeout = 10;
 	u64 control;
 	u64 int_en;
 	int err;
@@ -154,6 +155,22 @@  static int mlxbf_gige_open(struct net_device *netdev)
 
 	phy_start(phydev);
 
+	if (priv->hw_version == MLXBF_GIGE_VERSION_BF2) {
+		/* On BlueField-2 systems, the KSZ9031 PHY hardware could fail
+		 * to complete autonegotiation and so the link remains down.
+		 * The software workaround is to restart autonegotiation.
+		 */
+		while (timeout) {
+			if (phy_aneg_done(phydev))
+				break;
+			msleep(1000);
+			timeout--;
+		};
+
+		if (timeout == 0)
+			phy_restart_aneg(phydev);
+	}
+
 	err = mlxbf_gige_tx_init(priv);
 	if (err)
 		goto phy_deinit;