ACK: [PULL][SRU Xenial] net: thunderx: Fix link status reporting
diff mbox

Message ID 577BB6B8.9070400@canonical.com
State New
Headers show

Commit Message

Tim Gardner July 5, 2016, 1:31 p.m. UTC
See attached

Comments

Kamal Mostafa July 5, 2016, 7:43 p.m. UTC | #1
On Tue, Jul 05, 2016 at 07:31:36AM -0600, Tim Gardner wrote:
> See attached
> -- 
> Tim Gardner tim.gardner@canonical.com

Applied to Xenial (and inserted Dann's Signed-off-by).

 -Kamal


> From 1daf7dcae0185a15bc9a3fdf557c2d2e7a608a98 Mon Sep 17 00:00:00 2001
> From: Sunil Goutham <sgoutham@cavium.com>
> Date: Mon, 27 Jun 2016 15:30:02 +0530
> Subject: [PATCH] net: thunderx: Fix link status reporting
> 
> BugLink: http://bugs.launchpad.net/bugs/1597867
> 
> Check for SMU RX local/remote faults along with SPU LINK
> status. Otherwise at times link is UP at our end but DOWN
> at link partner's side. Also due to an issue in BGX it's
> rarely seen that initialization doesn't happen properly
> and SMU RX reports faults with everything fine at SPU.
> This patch tries to reinitialize LMAC to fix it.
> 
> Also fixed LMAC disable sequence to properly bring down link.
> 
> Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
> Signed-off-by: Tao Wang <tao.wang@cavium.com>
> Signed-off-by: David S. Miller <davem@davemloft.net>
> (cherry picked from commit 3f4c68cfde30caa1f6d8368fd19590671411ade2)
> Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
> ---
>  drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 91 +++++++++++++++--------
>  drivers/net/ethernet/cavium/thunder/thunder_bgx.h |  2 +
>  2 files changed, 62 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
> index feed231..f6ef7c96 100644
> --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
> +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
> @@ -549,7 +549,9 @@ static int bgx_xaui_check_link(struct lmac *lmac)
>  	}
>  
>  	/* Clear rcvflt bit (latching high) and read it back */
> -	bgx_reg_modify(bgx, lmacid, BGX_SPUX_STATUS2, SPU_STATUS2_RCVFLT);
> +	if (bgx_reg_read(bgx, lmacid, BGX_SPUX_STATUS2) & SPU_STATUS2_RCVFLT)
> +		bgx_reg_modify(bgx, lmacid,
> +			       BGX_SPUX_STATUS2, SPU_STATUS2_RCVFLT);
>  	if (bgx_reg_read(bgx, lmacid, BGX_SPUX_STATUS2) & SPU_STATUS2_RCVFLT) {
>  		dev_err(&bgx->pdev->dev, "Receive fault, retry training\n");
>  		if (bgx->use_training) {
> @@ -568,13 +570,6 @@ static int bgx_xaui_check_link(struct lmac *lmac)
>  		return -1;
>  	}
>  
> -	/* Wait for MAC RX to be ready */
> -	if (bgx_poll_reg(bgx, lmacid, BGX_SMUX_RX_CTL,
> -			 SMU_RX_CTL_STATUS, true)) {
> -		dev_err(&bgx->pdev->dev, "SMU RX link not okay\n");
> -		return -1;
> -	}
> -
>  	/* Wait for BGX RX to be idle */
>  	if (bgx_poll_reg(bgx, lmacid, BGX_SMUX_CTL, SMU_CTL_RX_IDLE, false)) {
>  		dev_err(&bgx->pdev->dev, "SMU RX not idle\n");
> @@ -587,29 +582,30 @@ static int bgx_xaui_check_link(struct lmac *lmac)
>  		return -1;
>  	}
>  
> -	if (bgx_reg_read(bgx, lmacid, BGX_SPUX_STATUS2) & SPU_STATUS2_RCVFLT) {
> -		dev_err(&bgx->pdev->dev, "Receive fault\n");
> -		return -1;
> -	}
> -
> -	/* Receive link is latching low. Force it high and verify it */
> -	bgx_reg_modify(bgx, lmacid, BGX_SPUX_STATUS1, SPU_STATUS1_RCV_LNK);
> -	if (bgx_poll_reg(bgx, lmacid, BGX_SPUX_STATUS1,
> -			 SPU_STATUS1_RCV_LNK, false)) {
> -		dev_err(&bgx->pdev->dev, "SPU receive link down\n");
> -		return -1;
> -	}
> -
> +	/* Clear receive packet disable */
>  	cfg = bgx_reg_read(bgx, lmacid, BGX_SPUX_MISC_CONTROL);
>  	cfg &= ~SPU_MISC_CTL_RX_DIS;
>  	bgx_reg_write(bgx, lmacid, BGX_SPUX_MISC_CONTROL, cfg);
> -	return 0;
> +
> +	/* Check for MAC RX faults */
> +	cfg = bgx_reg_read(bgx, lmacid, BGX_SMUX_RX_CTL);
> +	/* 0 - Link is okay, 1 - Local fault, 2 - Remote fault */
> +	cfg &= SMU_RX_CTL_STATUS;
> +	if (!cfg)
> +		return 0;
> +
> +	/* Rx local/remote fault seen.
> +	 * Do lmac reinit to see if condition recovers
> +	 */
> +	bgx_lmac_xaui_init(bgx, lmacid, bgx->lmac_type);
> +
> +	return -1;
>  }
>  
>  static void bgx_poll_for_link(struct work_struct *work)
>  {
>  	struct lmac *lmac;
> -	u64 link;
> +	u64 spu_link, smu_link;
>  
>  	lmac = container_of(work, struct lmac, dwork.work);
>  
> @@ -619,8 +615,11 @@ static void bgx_poll_for_link(struct work_struct *work)
>  	bgx_poll_reg(lmac->bgx, lmac->lmacid, BGX_SPUX_STATUS1,
>  		     SPU_STATUS1_RCV_LNK, false);
>  
> -	link = bgx_reg_read(lmac->bgx, lmac->lmacid, BGX_SPUX_STATUS1);
> -	if (link & SPU_STATUS1_RCV_LNK) {
> +	spu_link = bgx_reg_read(lmac->bgx, lmac->lmacid, BGX_SPUX_STATUS1);
> +	smu_link = bgx_reg_read(lmac->bgx, lmac->lmacid, BGX_SMUX_RX_CTL);
> +
> +	if ((spu_link & SPU_STATUS1_RCV_LNK) &&
> +	    !(smu_link & SMU_RX_CTL_STATUS)) {
>  		lmac->link_up = 1;
>  		if (lmac->bgx->lmac_type == BGX_MODE_XLAUI)
>  			lmac->last_speed = 40000;
> @@ -634,9 +633,15 @@ static void bgx_poll_for_link(struct work_struct *work)
>  	}
>  
>  	if (lmac->last_link != lmac->link_up) {
> +		if (lmac->link_up) {
> +			if (bgx_xaui_check_link(lmac)) {
> +				/* Errors, clear link_up state */
> +				lmac->link_up = 0;
> +				lmac->last_speed = SPEED_UNKNOWN;
> +				lmac->last_duplex = DUPLEX_UNKNOWN;
> +			}
> +		}
>  		lmac->last_link = lmac->link_up;
> -		if (lmac->link_up)
> -			bgx_xaui_check_link(lmac);
>  	}
>  
>  	queue_delayed_work(lmac->check_link, &lmac->dwork, HZ * 2);
> @@ -708,7 +713,7 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
>  static void bgx_lmac_disable(struct bgx *bgx, u8 lmacid)
>  {
>  	struct lmac *lmac;
> -	u64 cmrx_cfg;
> +	u64 cfg;
>  
>  	lmac = &bgx->lmac[lmacid];
>  	if (lmac->check_link) {
> @@ -717,9 +722,33 @@ static void bgx_lmac_disable(struct bgx *bgx, u8 lmacid)
>  		destroy_workqueue(lmac->check_link);
>  	}
>  
> -	cmrx_cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG);
> -	cmrx_cfg &= ~(1 << 15);
> -	bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cmrx_cfg);
> +	/* Disable packet reception */
> +	cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG);
> +	cfg &= ~CMR_PKT_RX_EN;
> +	bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg);
> +
> +	/* Give chance for Rx/Tx FIFO to get drained */
> +	bgx_poll_reg(bgx, lmacid, BGX_CMRX_RX_FIFO_LEN, (u64)0x1FFF, true);
> +	bgx_poll_reg(bgx, lmacid, BGX_CMRX_TX_FIFO_LEN, (u64)0x3FFF, true);
> +
> +	/* Disable packet transmission */
> +	cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG);
> +	cfg &= ~CMR_PKT_TX_EN;
> +	bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg);
> +
> +	/* Disable serdes lanes */
> +        if (!lmac->is_sgmii)
> +                bgx_reg_modify(bgx, lmacid,
> +                               BGX_SPUX_CONTROL1, SPU_CTL_LOW_POWER);
> +        else
> +                bgx_reg_modify(bgx, lmacid,
> +                               BGX_GMP_PCS_MRX_CTL, PCS_MRX_CTL_PWR_DN);
> +
> +	/* Disable LMAC */
> +	cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG);
> +	cfg &= ~CMR_EN;
> +	bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg);
> +
>  	bgx_flush_dmac_addrs(bgx, lmacid);
>  
>  	if ((bgx->lmac_type != BGX_MODE_XFI) &&
> diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
> index 149e179..42010d2 100644
> --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
> +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
> @@ -41,6 +41,7 @@
>  #define BGX_CMRX_RX_STAT10		0xC0
>  #define BGX_CMRX_RX_BP_DROP		0xC8
>  #define BGX_CMRX_RX_DMAC_CTL		0x0E8
> +#define BGX_CMRX_RX_FIFO_LEN		0x108
>  #define BGX_CMR_RX_DMACX_CAM		0x200
>  #define  RX_DMACX_CAM_EN			BIT_ULL(48)
>  #define  RX_DMACX_CAM_LMACID(x)			(x << 49)
> @@ -50,6 +51,7 @@
>  #define BGX_CMR_CHAN_MSK_AND		0x450
>  #define BGX_CMR_BIST_STATUS		0x460
>  #define BGX_CMR_RX_LMACS		0x468
> +#define BGX_CMRX_TX_FIFO_LEN		0x518
>  #define BGX_CMRX_TX_STAT0		0x600
>  #define BGX_CMRX_TX_STAT1		0x608
>  #define BGX_CMRX_TX_STAT2		0x610
> -- 
> 1.9.1
> 

> -- 
> kernel-team mailing list
> kernel-team@lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team

Patch
diff mbox

From 1daf7dcae0185a15bc9a3fdf557c2d2e7a608a98 Mon Sep 17 00:00:00 2001
From: Sunil Goutham <sgoutham@cavium.com>
Date: Mon, 27 Jun 2016 15:30:02 +0530
Subject: [PATCH] net: thunderx: Fix link status reporting

BugLink: http://bugs.launchpad.net/bugs/1597867

Check for SMU RX local/remote faults along with SPU LINK
status. Otherwise at times link is UP at our end but DOWN
at link partner's side. Also due to an issue in BGX it's
rarely seen that initialization doesn't happen properly
and SMU RX reports faults with everything fine at SPU.
This patch tries to reinitialize LMAC to fix it.

Also fixed LMAC disable sequence to properly bring down link.

Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
Signed-off-by: Tao Wang <tao.wang@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
(cherry picked from commit 3f4c68cfde30caa1f6d8368fd19590671411ade2)
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
---
 drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 91 +++++++++++++++--------
 drivers/net/ethernet/cavium/thunder/thunder_bgx.h |  2 +
 2 files changed, 62 insertions(+), 31 deletions(-)

diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index feed231..f6ef7c96 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -549,7 +549,9 @@  static int bgx_xaui_check_link(struct lmac *lmac)
 	}
 
 	/* Clear rcvflt bit (latching high) and read it back */
-	bgx_reg_modify(bgx, lmacid, BGX_SPUX_STATUS2, SPU_STATUS2_RCVFLT);
+	if (bgx_reg_read(bgx, lmacid, BGX_SPUX_STATUS2) & SPU_STATUS2_RCVFLT)
+		bgx_reg_modify(bgx, lmacid,
+			       BGX_SPUX_STATUS2, SPU_STATUS2_RCVFLT);
 	if (bgx_reg_read(bgx, lmacid, BGX_SPUX_STATUS2) & SPU_STATUS2_RCVFLT) {
 		dev_err(&bgx->pdev->dev, "Receive fault, retry training\n");
 		if (bgx->use_training) {
@@ -568,13 +570,6 @@  static int bgx_xaui_check_link(struct lmac *lmac)
 		return -1;
 	}
 
-	/* Wait for MAC RX to be ready */
-	if (bgx_poll_reg(bgx, lmacid, BGX_SMUX_RX_CTL,
-			 SMU_RX_CTL_STATUS, true)) {
-		dev_err(&bgx->pdev->dev, "SMU RX link not okay\n");
-		return -1;
-	}
-
 	/* Wait for BGX RX to be idle */
 	if (bgx_poll_reg(bgx, lmacid, BGX_SMUX_CTL, SMU_CTL_RX_IDLE, false)) {
 		dev_err(&bgx->pdev->dev, "SMU RX not idle\n");
@@ -587,29 +582,30 @@  static int bgx_xaui_check_link(struct lmac *lmac)
 		return -1;
 	}
 
-	if (bgx_reg_read(bgx, lmacid, BGX_SPUX_STATUS2) & SPU_STATUS2_RCVFLT) {
-		dev_err(&bgx->pdev->dev, "Receive fault\n");
-		return -1;
-	}
-
-	/* Receive link is latching low. Force it high and verify it */
-	bgx_reg_modify(bgx, lmacid, BGX_SPUX_STATUS1, SPU_STATUS1_RCV_LNK);
-	if (bgx_poll_reg(bgx, lmacid, BGX_SPUX_STATUS1,
-			 SPU_STATUS1_RCV_LNK, false)) {
-		dev_err(&bgx->pdev->dev, "SPU receive link down\n");
-		return -1;
-	}
-
+	/* Clear receive packet disable */
 	cfg = bgx_reg_read(bgx, lmacid, BGX_SPUX_MISC_CONTROL);
 	cfg &= ~SPU_MISC_CTL_RX_DIS;
 	bgx_reg_write(bgx, lmacid, BGX_SPUX_MISC_CONTROL, cfg);
-	return 0;
+
+	/* Check for MAC RX faults */
+	cfg = bgx_reg_read(bgx, lmacid, BGX_SMUX_RX_CTL);
+	/* 0 - Link is okay, 1 - Local fault, 2 - Remote fault */
+	cfg &= SMU_RX_CTL_STATUS;
+	if (!cfg)
+		return 0;
+
+	/* Rx local/remote fault seen.
+	 * Do lmac reinit to see if condition recovers
+	 */
+	bgx_lmac_xaui_init(bgx, lmacid, bgx->lmac_type);
+
+	return -1;
 }
 
 static void bgx_poll_for_link(struct work_struct *work)
 {
 	struct lmac *lmac;
-	u64 link;
+	u64 spu_link, smu_link;
 
 	lmac = container_of(work, struct lmac, dwork.work);
 
@@ -619,8 +615,11 @@  static void bgx_poll_for_link(struct work_struct *work)
 	bgx_poll_reg(lmac->bgx, lmac->lmacid, BGX_SPUX_STATUS1,
 		     SPU_STATUS1_RCV_LNK, false);
 
-	link = bgx_reg_read(lmac->bgx, lmac->lmacid, BGX_SPUX_STATUS1);
-	if (link & SPU_STATUS1_RCV_LNK) {
+	spu_link = bgx_reg_read(lmac->bgx, lmac->lmacid, BGX_SPUX_STATUS1);
+	smu_link = bgx_reg_read(lmac->bgx, lmac->lmacid, BGX_SMUX_RX_CTL);
+
+	if ((spu_link & SPU_STATUS1_RCV_LNK) &&
+	    !(smu_link & SMU_RX_CTL_STATUS)) {
 		lmac->link_up = 1;
 		if (lmac->bgx->lmac_type == BGX_MODE_XLAUI)
 			lmac->last_speed = 40000;
@@ -634,9 +633,15 @@  static void bgx_poll_for_link(struct work_struct *work)
 	}
 
 	if (lmac->last_link != lmac->link_up) {
+		if (lmac->link_up) {
+			if (bgx_xaui_check_link(lmac)) {
+				/* Errors, clear link_up state */
+				lmac->link_up = 0;
+				lmac->last_speed = SPEED_UNKNOWN;
+				lmac->last_duplex = DUPLEX_UNKNOWN;
+			}
+		}
 		lmac->last_link = lmac->link_up;
-		if (lmac->link_up)
-			bgx_xaui_check_link(lmac);
 	}
 
 	queue_delayed_work(lmac->check_link, &lmac->dwork, HZ * 2);
@@ -708,7 +713,7 @@  static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
 static void bgx_lmac_disable(struct bgx *bgx, u8 lmacid)
 {
 	struct lmac *lmac;
-	u64 cmrx_cfg;
+	u64 cfg;
 
 	lmac = &bgx->lmac[lmacid];
 	if (lmac->check_link) {
@@ -717,9 +722,33 @@  static void bgx_lmac_disable(struct bgx *bgx, u8 lmacid)
 		destroy_workqueue(lmac->check_link);
 	}
 
-	cmrx_cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG);
-	cmrx_cfg &= ~(1 << 15);
-	bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cmrx_cfg);
+	/* Disable packet reception */
+	cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG);
+	cfg &= ~CMR_PKT_RX_EN;
+	bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg);
+
+	/* Give chance for Rx/Tx FIFO to get drained */
+	bgx_poll_reg(bgx, lmacid, BGX_CMRX_RX_FIFO_LEN, (u64)0x1FFF, true);
+	bgx_poll_reg(bgx, lmacid, BGX_CMRX_TX_FIFO_LEN, (u64)0x3FFF, true);
+
+	/* Disable packet transmission */
+	cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG);
+	cfg &= ~CMR_PKT_TX_EN;
+	bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg);
+
+	/* Disable serdes lanes */
+        if (!lmac->is_sgmii)
+                bgx_reg_modify(bgx, lmacid,
+                               BGX_SPUX_CONTROL1, SPU_CTL_LOW_POWER);
+        else
+                bgx_reg_modify(bgx, lmacid,
+                               BGX_GMP_PCS_MRX_CTL, PCS_MRX_CTL_PWR_DN);
+
+	/* Disable LMAC */
+	cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG);
+	cfg &= ~CMR_EN;
+	bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg);
+
 	bgx_flush_dmac_addrs(bgx, lmacid);
 
 	if ((bgx->lmac_type != BGX_MODE_XFI) &&
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
index 149e179..42010d2 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
@@ -41,6 +41,7 @@ 
 #define BGX_CMRX_RX_STAT10		0xC0
 #define BGX_CMRX_RX_BP_DROP		0xC8
 #define BGX_CMRX_RX_DMAC_CTL		0x0E8
+#define BGX_CMRX_RX_FIFO_LEN		0x108
 #define BGX_CMR_RX_DMACX_CAM		0x200
 #define  RX_DMACX_CAM_EN			BIT_ULL(48)
 #define  RX_DMACX_CAM_LMACID(x)			(x << 49)
@@ -50,6 +51,7 @@ 
 #define BGX_CMR_CHAN_MSK_AND		0x450
 #define BGX_CMR_BIST_STATUS		0x460
 #define BGX_CMR_RX_LMACS		0x468
+#define BGX_CMRX_TX_FIFO_LEN		0x518
 #define BGX_CMRX_TX_STAT0		0x600
 #define BGX_CMRX_TX_STAT1		0x608
 #define BGX_CMRX_TX_STAT2		0x610
-- 
1.9.1