Commit a9077bfd authored by Yaniv Rosner's avatar Yaniv Rosner Committed by David S. Miller

bnx2x: Add link retry to 578xx-KR

This fix solves a problem of no link on 578xx-KR by retrying to link up to
four timer using the periodic function.
Signed-off-by: default avatarYaniv Rosner <yanivr@broadcom.com>
Signed-off-by: default avatarEilon Greenstein <eilong@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 26ffaf36
...@@ -261,6 +261,7 @@ ...@@ -261,6 +261,7 @@
#define MAX_PACKET_SIZE (9700) #define MAX_PACKET_SIZE (9700)
#define WC_UC_TIMEOUT 100 #define WC_UC_TIMEOUT 100
#define MAX_KR_LINK_RETRY 4
/**********************************************************/ /**********************************************************/
/* INTERFACE */ /* INTERFACE */
...@@ -3578,6 +3579,11 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, ...@@ -3578,6 +3579,11 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
u16 val16 = 0, lane, bam37 = 0; u16 val16 = 0, lane, bam37 = 0;
struct bnx2x *bp = params->bp; struct bnx2x *bp = params->bp;
DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n"); DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n");
/* Disable Autoneg: re-enable it after adv is done. */
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
MDIO_WC_REG_IEEE0BLK_MIICNTL, 0);
/* Check adding advertisement for 1G KX */ /* Check adding advertisement for 1G KX */
if (((vars->line_speed == SPEED_AUTO_NEG) && if (((vars->line_speed == SPEED_AUTO_NEG) &&
(phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) || (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
...@@ -3619,9 +3625,6 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, ...@@ -3619,9 +3625,6 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_CL72_USERB0_CL72_2P5_DEF_CTRL, MDIO_WC_REG_CL72_USERB0_CL72_2P5_DEF_CTRL,
0x03f0); 0x03f0);
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
0x383f);
/* Advertised speeds */ /* Advertised speeds */
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
...@@ -3648,19 +3651,22 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, ...@@ -3648,19 +3651,22 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
/* Advertise pause */ /* Advertise pause */
bnx2x_ext_phy_set_pause(params, phy, vars); bnx2x_ext_phy_set_pause(params, phy, vars);
/* Enable Autoneg */ vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1000);
/* Over 1G - AN local device user page 1 */
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_DIGITAL3_UP1, 0x1f);
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_DIGITAL5_MISC7, &val16); MDIO_WC_REG_DIGITAL5_MISC7, &val16);
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_DIGITAL5_MISC7, val16 | 0x100); MDIO_WC_REG_DIGITAL5_MISC7, val16 | 0x100);
/* Over 1G - AN local device user page 1 */
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_DIGITAL3_UP1, 0x1f);
/* Enable Autoneg */
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1000);
} }
static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy, static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
...@@ -4129,6 +4135,85 @@ static int bnx2x_is_sfp_module_plugged(struct bnx2x_phy *phy, ...@@ -4129,6 +4135,85 @@ static int bnx2x_is_sfp_module_plugged(struct bnx2x_phy *phy,
else else
return 0; return 0;
} }
static int bnx2x_warpcore_get_sigdet(struct bnx2x_phy *phy,
struct link_params *params)
{
u16 gp2_status_reg0, lane;
struct bnx2x *bp = params->bp;
lane = bnx2x_get_warpcore_lane(phy, params);
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, MDIO_WC_REG_GP2_STATUS_GP_2_0,
&gp2_status_reg0);
return (gp2_status_reg0 >> (8+lane)) & 0x1;
}
static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy,
struct link_params *params,
struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u32 serdes_net_if;
u16 gp_status1 = 0, lnkup = 0, lnkup_kr = 0;
u16 lane = bnx2x_get_warpcore_lane(phy, params);
vars->turn_to_run_wc_rt = vars->turn_to_run_wc_rt ? 0 : 1;
if (!vars->turn_to_run_wc_rt)
return;
/* return if there is no link partner */
if (!(bnx2x_warpcore_get_sigdet(phy, params))) {
DP(NETIF_MSG_LINK, "bnx2x_warpcore_get_sigdet false\n");
return;
}
if (vars->rx_tx_asic_rst) {
serdes_net_if = (REG_RD(bp, params->shmem_base +
offsetof(struct shmem_region, dev_info.
port_hw_config[params->port].default_cfg)) &
PORT_HW_CFG_NET_SERDES_IF_MASK);
switch (serdes_net_if) {
case PORT_HW_CFG_NET_SERDES_IF_KR:
/* Do we get link yet? */
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, 0x81d1,
&gp_status1);
lnkup = (gp_status1 >> (8+lane)) & 0x1;/* 1G */
/*10G KR*/
lnkup_kr = (gp_status1 >> (12+lane)) & 0x1;
DP(NETIF_MSG_LINK,
"gp_status1 0x%x\n", gp_status1);
if (lnkup_kr || lnkup) {
vars->rx_tx_asic_rst = 0;
DP(NETIF_MSG_LINK,
"link up, rx_tx_asic_rst 0x%x\n",
vars->rx_tx_asic_rst);
} else {
/*reset the lane to see if link comes up.*/
bnx2x_warpcore_reset_lane(bp, phy, 1);
bnx2x_warpcore_reset_lane(bp, phy, 0);
/* restart Autoneg */
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200);
vars->rx_tx_asic_rst--;
DP(NETIF_MSG_LINK, "0x%x retry left\n",
vars->rx_tx_asic_rst);
}
break;
default:
break;
}
} /*params->rx_tx_asic_rst*/
}
static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy, static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
struct link_params *params, struct link_params *params,
...@@ -12339,11 +12424,6 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars) ...@@ -12339,11 +12424,6 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
{ {
struct bnx2x *bp = params->bp; struct bnx2x *bp = params->bp;
u16 phy_idx; u16 phy_idx;
if (!params) {
DP(NETIF_MSG_LINK, "Uninitialized params !\n");
return;
}
for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) { for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) { if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) {
bnx2x_set_aer_mmd(params, &params->phy[phy_idx]); bnx2x_set_aer_mmd(params, &params->phy[phy_idx]);
...@@ -12352,8 +12432,13 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars) ...@@ -12352,8 +12432,13 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
} }
} }
if (CHIP_IS_E3(bp)) if (CHIP_IS_E3(bp)) {
struct bnx2x_phy *phy = &params->phy[INT_PHY];
bnx2x_set_aer_mmd(params, phy);
bnx2x_check_over_curr(params, vars); bnx2x_check_over_curr(params, vars);
bnx2x_warpcore_config_runtime(phy, params, vars);
}
} }
u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base) u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base)
......
...@@ -303,6 +303,9 @@ struct link_vars { ...@@ -303,6 +303,9 @@ struct link_vars {
#define PERIODIC_FLAGS_LINK_EVENT 0x0001 #define PERIODIC_FLAGS_LINK_EVENT 0x0001
u32 aeu_int_mask; u32 aeu_int_mask;
u8 rx_tx_asic_rst;
u8 turn_to_run_wc_rt;
u16 rsrv2;
}; };
/***********************************************************/ /***********************************************************/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment