ACK+Applied: [PULL][SRU Xenial] net: thunderx: Fix link status reporting
Kamal Mostafa
kamal at canonical.com
Tue Jul 5 19:43:41 UTC 2016
On Tue, Jul 05, 2016 at 07:31:36AM -0600, Tim Gardner wrote:
> See attached
> --
> Tim Gardner tim.gardner at 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 at 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 at cavium.com>
> Signed-off-by: Tao Wang <tao.wang at cavium.com>
> Signed-off-by: David S. Miller <davem at davemloft.net>
> (cherry picked from commit 3f4c68cfde30caa1f6d8368fd19590671411ade2)
> Signed-off-by: Tim Gardner <tim.gardner at 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 at lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team
More information about the kernel-team
mailing list