5734e3
From e24385dbf7bd21c48ee68cf585b6f63d4745b9c7 Mon Sep 17 00:00:00 2001
5734e3
From: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
5734e3
Date: Wed, 17 Feb 2021 00:37:07 +0530
5734e3
Subject: [PATCH 07/14] net: amd-xgbe: Reset the PHY rx data path when mailbox
5734e3
 command timeout
5734e3
Git-commit: 30b7edc82ec82578f4f5e6706766f0a9535617d3
5734e3
Patch-mainline: v5.12-rc1
5734e3
References: git-fixes
5734e3
5734e3
Sometimes mailbox commands timeout when the RX data path becomes
5734e3
unresponsive. This prevents the submission of new mailbox commands to DXIO.
5734e3
This patch identifies the timeout and resets the RX data path so that the
5734e3
next message can be submitted properly.
5734e3
5734e3
Fixes: 549b32af9f7c ("amd-xgbe: Simplify mailbox interface rate change code")
5734e3
Co-developed-by: Sudheesh Mavila <sudheesh.mavila@amd.com>
5734e3
Signed-off-by: Sudheesh Mavila <sudheesh.mavila@amd.com>
5734e3
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
5734e3
Acked-by: Tom Lendacky <thomas.lendacky@amd.com>
5734e3
Signed-off-by: David S. Miller <davem@davemloft.net>
5734e3
Signed-off-by: Denis Kirjanov <denis.kirjanov@suse.com>
5734e3
---
5734e3
 drivers/net/ethernet/amd/xgbe/xgbe-common.h | 14 ++++++++++++++
5734e3
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 28 +++++++++++++++++++++++++++-
5734e3
 2 files changed, 41 insertions(+), 1 deletion(-)
5734e3
5734e3
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
5734e3
index b40d4377cc71..b2cd3bdba9f8 100644
5734e3
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
5734e3
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
5734e3
@@ -1279,10 +1279,18 @@
5734e3
 #define MDIO_PMA_10GBR_FECCTRL		0x00ab
5734e3
 #endif
5734e3
 
5734e3
+#ifndef MDIO_PMA_RX_CTRL1
5734e3
+#define MDIO_PMA_RX_CTRL1		0x8051
5734e3
+#endif
5734e3
+
5734e3
 #ifndef MDIO_PCS_DIG_CTRL
5734e3
 #define MDIO_PCS_DIG_CTRL		0x8000
5734e3
 #endif
5734e3
 
5734e3
+#ifndef MDIO_PCS_DIGITAL_STAT
5734e3
+#define MDIO_PCS_DIGITAL_STAT		0x8010
5734e3
+#endif
5734e3
+
5734e3
 #ifndef MDIO_AN_XNP
5734e3
 #define MDIO_AN_XNP			0x0016
5734e3
 #endif
5734e3
@@ -1358,6 +1366,8 @@
5734e3
 #define XGBE_KR_TRAINING_ENABLE		BIT(1)
5734e3
 
5734e3
 #define XGBE_PCS_CL37_BP		BIT(12)
5734e3
+#define XGBE_PCS_PSEQ_STATE_MASK	0x1c
5734e3
+#define XGBE_PCS_PSEQ_STATE_POWER_GOOD	0x10
5734e3
 
5734e3
 #define XGBE_AN_CL37_INT_CMPLT		BIT(0)
5734e3
 #define XGBE_AN_CL37_INT_MASK		0x01
5734e3
@@ -1375,6 +1385,10 @@
5734e3
 #define XGBE_PMA_CDR_TRACK_EN_OFF	0x00
5734e3
 #define XGBE_PMA_CDR_TRACK_EN_ON	0x01
5734e3
 
5734e3
+#define XGBE_PMA_RX_RST_0_MASK		BIT(4)
5734e3
+#define XGBE_PMA_RX_RST_0_RESET_ON	0x10
5734e3
+#define XGBE_PMA_RX_RST_0_RESET_OFF	0x00
5734e3
+
5734e3
 /* Bit setting and getting macros
5734e3
  *  The get macro will extract the current bit field value from within
5734e3
  *  the variable
5734e3
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
5734e3
index 128cd648ba99..f024db6d9015 100644
5734e3
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
5734e3
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
5734e3
@@ -1948,6 +1948,27 @@ static void xgbe_phy_set_redrv_mode(struct xgbe_prv_data *pdata)
5734e3
 	xgbe_phy_put_comm_ownership(pdata);
5734e3
 }
5734e3
 
5734e3
+static void xgbe_phy_rx_reset(struct xgbe_prv_data *pdata)
5734e3
+{
5734e3
+	int reg;
5734e3
+
5734e3
+	reg = XMDIO_READ_BITS(pdata, MDIO_MMD_PCS, MDIO_PCS_DIGITAL_STAT,
5734e3
+			      XGBE_PCS_PSEQ_STATE_MASK);
5734e3
+	if (reg == XGBE_PCS_PSEQ_STATE_POWER_GOOD) {
5734e3
+		/* Mailbox command timed out, reset of RX block is required.
5734e3
+		 * This can be done by asseting the reset bit and wait for
5734e3
+		 * its compeletion.
5734e3
+		 */
5734e3
+		XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1,
5734e3
+				 XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_ON);
5734e3
+		ndelay(20);
5734e3
+		XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1,
5734e3
+				 XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_OFF);
5734e3
+		usleep_range(40, 50);
5734e3
+		netif_err(pdata, link, pdata->netdev, "firmware mailbox reset performed\n");
5734e3
+	}
5734e3
+}
5734e3
+
5734e3
 static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata,
5734e3
 					unsigned int cmd, unsigned int sub_cmd)
5734e3
 {
5734e3
@@ -1955,9 +1976,11 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata,
5734e3
 	unsigned int wait;
5734e3
 
5734e3
 	/* Log if a previous command did not complete */
5734e3
-	if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS))
5734e3
+	if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) {
5734e3
 		netif_dbg(pdata, link, pdata->netdev,
5734e3
 			  "firmware mailbox not ready for command\n");
5734e3
+		xgbe_phy_rx_reset(pdata);
5734e3
+	}
5734e3
 
5734e3
 	/* Construct the command */
5734e3
 	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, cmd);
5734e3
@@ -1979,6 +2002,9 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata,
5734e3
 
5734e3
 	netif_dbg(pdata, link, pdata->netdev,
5734e3
 		  "firmware mailbox command did not complete\n");
5734e3
+
5734e3
+	/* Reset on error */
5734e3
+	xgbe_phy_rx_reset(pdata);
5734e3
 }
5734e3
 
5734e3
 static void xgbe_phy_rrc(struct xgbe_prv_data *pdata)
5734e3
-- 
5734e3
2.16.4
5734e3