diff options
author | Yaniv Rosner <yanivr@broadcom.com> | 2011-10-27 01:09:46 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-10-27 16:14:15 -0400 |
commit | a9077bfd0b3fdcd1051cc3d09bf8c28f9d4d506a (patch) | |
tree | 2a42fe02ff38608a80fdf73006044fe67fcb07a5 /drivers | |
parent | 26ffaf36c8e0a0eefb6ff031d6166b5ee82eb3de (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')
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 117 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h | 3 |
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 | ||
3666 | static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy, | 3672 | 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 | else | 4135 | else |
4130 | return 0; | 4136 | return 0; |
4131 | } | 4137 | } |
4138 | static 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 | |||
4152 | static 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 | ||
4133 | static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy, | 4218 | static 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, ¶ms->phy[phy_idx]); | 12429 | bnx2x_set_aer_mmd(params, ¶ms->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 = ¶ms->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 | ||
12359 | u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base) | 12444 | u8 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 | /***********************************************************/ |