diff mbox series

[1/4] amd-xgbe: Reset the PHY rx data path when mailbox command timeout

Message ID 20210212180010.221129-2-Shyam-sundar.S-k@amd.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series Bug fixes to amd-xgbe driver | expand

Checks

Context Check Description
netdev/cover_letter success Link
netdev/fixes_present success Link
netdev/patch_count success Link
netdev/tree_selection success Guessed tree name to be net-next
netdev/subject_prefix warning Target tree name not specified in the subject
netdev/cc_maintainers success CCed 4 of 4 maintainers
netdev/source_inline success Was 0 now: 0
netdev/verify_signedoff success Link
netdev/module_param success Was 0 now: 0
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/verify_fixes success Link
netdev/checkpatch warning WARNING: line length of 85 exceeds 80 columns WARNING: line length of 86 exceeds 80 columns
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/header_inline success Link
netdev/stable success Stable not CCed

Commit Message

Shyam Sundar S K Feb. 12, 2021, 6 p.m. UTC
Sometimes mailbox commands timeout when the RX data path becomes
unresponsive. This prevents the submission of new mailbox commands to DXIO.
This patch identifies the timeout and resets the RX data path so that the
next message can be submitted properly.

Signed-off-by: Sudheesh Mavila <sudheesh.mavila@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-common.h | 13 +++++++++++
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 25 ++++++++++++++++++++-
 2 files changed, 37 insertions(+), 1 deletion(-)

Comments

Tom Lendacky Feb. 12, 2021, 6:43 p.m. UTC | #1
On 2/12/21 12:00 PM, Shyam Sundar S K wrote:
> Sometimes mailbox commands timeout when the RX data path becomes
> unresponsive. This prevents the submission of new mailbox commands to DXIO.
> This patch identifies the timeout and resets the RX data path so that the
> next message can be submitted properly.
> 
> Signed-off-by: Sudheesh Mavila <sudheesh.mavila@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>

I believe you need a Co-developed-by: before Sudheesh's Signed-off-by: 
if he was a co-developer.

> ---
>   drivers/net/ethernet/amd/xgbe/xgbe-common.h | 13 +++++++++++
>   drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 25 ++++++++++++++++++++-
>   2 files changed, 37 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
> index b40d4377cc71..318817450fbd 100644
> --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
> +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
> @@ -1279,10 +1279,18 @@
>   #define MDIO_PMA_10GBR_FECCTRL		0x00ab
>   #endif
>   
> +#ifndef MDIO_PMA_RX_CTRL1
> +#define MDIO_PMA_RX_CTRL1		0x8051
> +#endif
> +
>   #ifndef MDIO_PCS_DIG_CTRL
>   #define MDIO_PCS_DIG_CTRL		0x8000
>   #endif
>   
> +#ifndef MDIO_PCS_DIGITAL_STAT
> +#define MDIO_PCS_DIGITAL_STAT		0x8010
> +#endif
> +
>   #ifndef MDIO_AN_XNP
>   #define MDIO_AN_XNP			0x0016
>   #endif
> @@ -1358,6 +1366,7 @@
>   #define XGBE_KR_TRAINING_ENABLE		BIT(1)
>   
>   #define XGBE_PCS_CL37_BP		BIT(12)
> +#define XGBE_PCS_PSEQ_STATE_BIT		0x10

See comment below, this is a 3-bit field.

>   
>   #define XGBE_AN_CL37_INT_CMPLT		BIT(0)
>   #define XGBE_AN_CL37_INT_MASK		0x01
> @@ -1375,6 +1384,10 @@
>   #define XGBE_PMA_CDR_TRACK_EN_OFF	0x00
>   #define XGBE_PMA_CDR_TRACK_EN_ON	0x01
>   
> +#define XGBE_PMA_RX_RST_0_MASK		BIT(4)
> +#define XGBE_PMA_RX_RST_0_RESET_ON	0x10
> +#define XGBE_PMA_RX_RST_0_RESET_OFF	0x00
> +
>   /* Bit setting and getting macros
>    *  The get macro will extract the current bit field value from within
>    *  the variable
> diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
> index 859ded0c06b0..489f1f86df99 100644
> --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
> +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
> @@ -1953,6 +1953,24 @@ static void xgbe_phy_set_redrv_mode(struct xgbe_prv_data *pdata)
>   	xgbe_phy_put_comm_ownership(pdata);
>   }
>   
> +static void xgbe_phy_rx_reset(struct xgbe_prv_data *pdata)
> +{
> +	int reg;
> +
> +	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_PCS_DIGITAL_STAT);
> +	if (reg & XGBE_PCS_PSEQ_STATE_BIT) {

The PSEQ_STATE field is a 3 bit field and I believe you're looking for a 
POWER_GOOD state, so this should be:

	reg = XMDIO_READ_BITS(pdata, MDIO_MMD_PCS, MDIO_PCS_DIGITAL_STAT
			      XGBE_PCS_PSEQ_STATE_MASK);
	if (reg == XGBE_PCS_PSEQ_STATE_POWER_GOOD) {

where the constants define in xgbe-common.h should be:

#define XGBE_PCS_PSEQ_STATE_MASK	0x1c
#define XGBE_PCS_PSEQ_STATE_POWER_GOOD	0x10


> +		/* mailbox command timed out, reset Rx block */
> +		/* Assert reset bit for 8ns and wait for 40us */

Please combine this comment and be sure to capitalize appropriately.

> +		XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1,
> +				 XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_ON);
> +		ndelay(20);

This time doesn't match the comment of 8ns... which one is correct?

> +		XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1,
> +				 XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_OFF);
> +		usleep_range(40, 50);
> +		netif_err(pdata, link, pdata->netdev, "firmware mailbox reset performed\n");
> +	}
> +}
> +
>   static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata,
>   					unsigned int cmd, unsigned int sub_cmd)
>   {
> @@ -1960,9 +1978,11 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata,
>   	unsigned int wait;
>   
>   	/* Log if a previous command did not complete */
> -	if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS))
> +	if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) {
>   		netif_dbg(pdata, link, pdata->netdev,
>   			  "firmware mailbox not ready for command\n");
> +			xgbe_phy_rx_reset(pdata);

An extra tab here.

Thanks,
Tom

> +	}
>   
>   	/* Construct the command */
>   	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, cmd);
> @@ -1984,6 +2004,9 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata,
>   
>   	netif_dbg(pdata, link, pdata->netdev,
>   		  "firmware mailbox command did not complete\n");
> +
> +	/* Reset on error */
> +	xgbe_phy_rx_reset(pdata);
>   }
>   
>   static void xgbe_phy_rrc(struct xgbe_prv_data *pdata)
>
diff mbox series

Patch

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index b40d4377cc71..318817450fbd 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -1279,10 +1279,18 @@ 
 #define MDIO_PMA_10GBR_FECCTRL		0x00ab
 #endif
 
+#ifndef MDIO_PMA_RX_CTRL1
+#define MDIO_PMA_RX_CTRL1		0x8051
+#endif
+
 #ifndef MDIO_PCS_DIG_CTRL
 #define MDIO_PCS_DIG_CTRL		0x8000
 #endif
 
+#ifndef MDIO_PCS_DIGITAL_STAT
+#define MDIO_PCS_DIGITAL_STAT		0x8010
+#endif
+
 #ifndef MDIO_AN_XNP
 #define MDIO_AN_XNP			0x0016
 #endif
@@ -1358,6 +1366,7 @@ 
 #define XGBE_KR_TRAINING_ENABLE		BIT(1)
 
 #define XGBE_PCS_CL37_BP		BIT(12)
+#define XGBE_PCS_PSEQ_STATE_BIT		0x10
 
 #define XGBE_AN_CL37_INT_CMPLT		BIT(0)
 #define XGBE_AN_CL37_INT_MASK		0x01
@@ -1375,6 +1384,10 @@ 
 #define XGBE_PMA_CDR_TRACK_EN_OFF	0x00
 #define XGBE_PMA_CDR_TRACK_EN_ON	0x01
 
+#define XGBE_PMA_RX_RST_0_MASK		BIT(4)
+#define XGBE_PMA_RX_RST_0_RESET_ON	0x10
+#define XGBE_PMA_RX_RST_0_RESET_OFF	0x00
+
 /* Bit setting and getting macros
  *  The get macro will extract the current bit field value from within
  *  the variable
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 859ded0c06b0..489f1f86df99 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -1953,6 +1953,24 @@  static void xgbe_phy_set_redrv_mode(struct xgbe_prv_data *pdata)
 	xgbe_phy_put_comm_ownership(pdata);
 }
 
+static void xgbe_phy_rx_reset(struct xgbe_prv_data *pdata)
+{
+	int reg;
+
+	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_PCS_DIGITAL_STAT);
+	if (reg & XGBE_PCS_PSEQ_STATE_BIT) {
+		/* mailbox command timed out, reset Rx block */
+		/* Assert reset bit for 8ns and wait for 40us */
+		XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1,
+				 XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_ON);
+		ndelay(20);
+		XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1,
+				 XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_OFF);
+		usleep_range(40, 50);
+		netif_err(pdata, link, pdata->netdev, "firmware mailbox reset performed\n");
+	}
+}
+
 static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata,
 					unsigned int cmd, unsigned int sub_cmd)
 {
@@ -1960,9 +1978,11 @@  static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata,
 	unsigned int wait;
 
 	/* Log if a previous command did not complete */
-	if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS))
+	if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) {
 		netif_dbg(pdata, link, pdata->netdev,
 			  "firmware mailbox not ready for command\n");
+			xgbe_phy_rx_reset(pdata);
+	}
 
 	/* Construct the command */
 	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, cmd);
@@ -1984,6 +2004,9 @@  static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata,
 
 	netif_dbg(pdata, link, pdata->netdev,
 		  "firmware mailbox command did not complete\n");
+
+	/* Reset on error */
+	xgbe_phy_rx_reset(pdata);
 }
 
 static void xgbe_phy_rrc(struct xgbe_prv_data *pdata)