aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorYaniv Rosner <yanivr@broadcom.com>2011-10-27 01:09:46 -0400
committerDavid S. Miller <davem@davemloft.net>2011-10-27 16:14:15 -0400
commita9077bfd0b3fdcd1051cc3d09bf8c28f9d4d506a (patch)
tree2a42fe02ff38608a80fdf73006044fe67fcb07a5 /drivers/net/ethernet
parent26ffaf36c8e0a0eefb6ff031d6166b5ee82eb3de (diff)
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: Yaniv Rosner <yanivr@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c117
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h3
2 files changed, 104 insertions, 16 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index edc9259f4be5..a47db9dc6c50 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -261,6 +261,7 @@
261 261
262#define MAX_PACKET_SIZE (9700) 262#define MAX_PACKET_SIZE (9700)
263#define WC_UC_TIMEOUT 100 263#define WC_UC_TIMEOUT 100
264#define MAX_KR_LINK_RETRY 4
264 265
265/**********************************************************/ 266/**********************************************************/
266/* INTERFACE */ 267/* INTERFACE */
@@ -3578,6 +3579,11 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
3578 u16 val16 = 0, lane, bam37 = 0; 3579 u16 val16 = 0, lane, bam37 = 0;
3579 struct bnx2x *bp = params->bp; 3580 struct bnx2x *bp = params->bp;
3580 DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n"); 3581 DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n");
3582
3583 /* Disable Autoneg: re-enable it after adv is done. */
3584 bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
3585 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0);
3586
3581 /* Check adding advertisement for 1G KX */ 3587 /* Check adding advertisement for 1G KX */
3582 if (((vars->line_speed == SPEED_AUTO_NEG) && 3588 if (((vars->line_speed == SPEED_AUTO_NEG) &&
3583 (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) || 3589 (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 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, 3625 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
3620 MDIO_WC_REG_CL72_USERB0_CL72_2P5_DEF_CTRL, 3626 MDIO_WC_REG_CL72_USERB0_CL72_2P5_DEF_CTRL,
3621 0x03f0); 3627 0x03f0);
3622 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
3623 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
3624 0x383f);
3625 3628
3626 /* Advertised speeds */ 3629 /* Advertised speeds */
3627 bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, 3630 bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
@@ -3648,19 +3651,22 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
3648 /* Advertise pause */ 3651 /* Advertise pause */
3649 bnx2x_ext_phy_set_pause(params, phy, vars); 3652 bnx2x_ext_phy_set_pause(params, phy, vars);
3650 3653
3651 /* Enable Autoneg */ 3654 vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
3652 bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
3653 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1000);
3654
3655 /* Over 1G - AN local device user page 1 */
3656 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
3657 MDIO_WC_REG_DIGITAL3_UP1, 0x1f);
3658 3655
3659 bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, 3656 bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
3660 MDIO_WC_REG_DIGITAL5_MISC7, &val16); 3657 MDIO_WC_REG_DIGITAL5_MISC7, &val16);
3661 3658
3662 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, 3659 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
3663 MDIO_WC_REG_DIGITAL5_MISC7, val16 | 0x100); 3660 MDIO_WC_REG_DIGITAL5_MISC7, val16 | 0x100);
3661
3662 /* Over 1G - AN local device user page 1 */
3663 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
3664 MDIO_WC_REG_DIGITAL3_UP1, 0x1f);
3665
3666 /* Enable Autoneg */
3667 bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
3668 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1000);
3669
3664} 3670}
3665 3671
3666static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy, 3672static 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 else 4135 else
4130 return 0; 4136 return 0;
4131} 4137}
4138static int bnx2x_warpcore_get_sigdet(struct bnx2x_phy *phy,
4139 struct link_params *params)
4140{
4141 u16 gp2_status_reg0, lane;
4142 struct bnx2x *bp = params->bp;
4143
4144 lane = bnx2x_get_warpcore_lane(phy, params);
4145
4146 bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, MDIO_WC_REG_GP2_STATUS_GP_2_0,
4147 &gp2_status_reg0);
4148
4149 return (gp2_status_reg0 >> (8+lane)) & 0x1;
4150}
4151
4152static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy,
4153 struct link_params *params,
4154 struct link_vars *vars)
4155{
4156 struct bnx2x *bp = params->bp;
4157 u32 serdes_net_if;
4158 u16 gp_status1 = 0, lnkup = 0, lnkup_kr = 0;
4159 u16 lane = bnx2x_get_warpcore_lane(phy, params);
4160
4161 vars->turn_to_run_wc_rt = vars->turn_to_run_wc_rt ? 0 : 1;
4162
4163 if (!vars->turn_to_run_wc_rt)
4164 return;
4165
4166 /* return if there is no link partner */
4167 if (!(bnx2x_warpcore_get_sigdet(phy, params))) {
4168 DP(NETIF_MSG_LINK, "bnx2x_warpcore_get_sigdet false\n");
4169 return;
4170 }
4171
4172 if (vars->rx_tx_asic_rst) {
4173 serdes_net_if = (REG_RD(bp, params->shmem_base +
4174 offsetof(struct shmem_region, dev_info.
4175 port_hw_config[params->port].default_cfg)) &
4176 PORT_HW_CFG_NET_SERDES_IF_MASK);
4177
4178 switch (serdes_net_if) {
4179 case PORT_HW_CFG_NET_SERDES_IF_KR:
4180 /* Do we get link yet? */
4181 bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, 0x81d1,
4182 &gp_status1);
4183 lnkup = (gp_status1 >> (8+lane)) & 0x1;/* 1G */
4184 /*10G KR*/
4185 lnkup_kr = (gp_status1 >> (12+lane)) & 0x1;
4186
4187 DP(NETIF_MSG_LINK,
4188 "gp_status1 0x%x\n", gp_status1);
4189
4190 if (lnkup_kr || lnkup) {
4191 vars->rx_tx_asic_rst = 0;
4192 DP(NETIF_MSG_LINK,
4193 "link up, rx_tx_asic_rst 0x%x\n",
4194 vars->rx_tx_asic_rst);
4195 } else {
4196 /*reset the lane to see if link comes up.*/
4197 bnx2x_warpcore_reset_lane(bp, phy, 1);
4198 bnx2x_warpcore_reset_lane(bp, phy, 0);
4199
4200 /* restart Autoneg */
4201 bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
4202 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200);
4203
4204 vars->rx_tx_asic_rst--;
4205 DP(NETIF_MSG_LINK, "0x%x retry left\n",
4206 vars->rx_tx_asic_rst);
4207 }
4208 break;
4209
4210 default:
4211 break;
4212 }
4213
4214 } /*params->rx_tx_asic_rst*/
4215
4216}
4132 4217
4133static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy, 4218static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
4134 struct link_params *params, 4219 struct link_params *params,
@@ -12339,11 +12424,6 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
12339{ 12424{
12340 struct bnx2x *bp = params->bp; 12425 struct bnx2x *bp = params->bp;
12341 u16 phy_idx; 12426 u16 phy_idx;
12342 if (!params) {
12343 DP(NETIF_MSG_LINK, "Uninitialized params !\n");
12344 return;
12345 }
12346
12347 for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) { 12427 for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
12348 if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) { 12428 if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) {
12349 bnx2x_set_aer_mmd(params, &params->phy[phy_idx]); 12429 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 } 12432 }
12353 } 12433 }
12354 12434
12355 if (CHIP_IS_E3(bp)) 12435 if (CHIP_IS_E3(bp)) {
12436 struct bnx2x_phy *phy = &params->phy[INT_PHY];
12437 bnx2x_set_aer_mmd(params, phy);
12356 bnx2x_check_over_curr(params, vars); 12438 bnx2x_check_over_curr(params, vars);
12439 bnx2x_warpcore_config_runtime(phy, params, vars);
12440 }
12441
12357} 12442}
12358 12443
12359u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base) 12444u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
index c12db6da213e..2a46e633abe9 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
@@ -303,6 +303,9 @@ struct link_vars {
303#define PERIODIC_FLAGS_LINK_EVENT 0x0001 303#define PERIODIC_FLAGS_LINK_EVENT 0x0001
304 304
305 u32 aeu_int_mask; 305 u32 aeu_int_mask;
306 u8 rx_tx_asic_rst;
307 u8 turn_to_run_wc_rt;
308 u16 rsrv2;
306}; 309};
307 310
308/***********************************************************/ 311/***********************************************************/