diff options
-rw-r--r-- | drivers/net/bnx2x_link.c | 380 | ||||
-rw-r--r-- | drivers/net/bnx2x_reg.h | 2 |
2 files changed, 216 insertions, 166 deletions
diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index ff2743db10d9..3b63c8ce952a 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c | |||
@@ -1690,7 +1690,11 @@ static u8 bnx2x_link_settings_status(struct link_params *params, | |||
1690 | 1690 | ||
1691 | vars->link_status |= LINK_STATUS_SERDES_LINK; | 1691 | vars->link_status |= LINK_STATUS_SERDES_LINK; |
1692 | 1692 | ||
1693 | if (params->req_line_speed == SPEED_AUTO_NEG) { | 1693 | if ((params->req_line_speed == SPEED_AUTO_NEG) && |
1694 | ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) == | ||
1695 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) || | ||
1696 | (XGXS_EXT_PHY_TYPE(params->ext_phy_config) == | ||
1697 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705))) { | ||
1694 | vars->autoneg = AUTO_NEG_ENABLED; | 1698 | vars->autoneg = AUTO_NEG_ENABLED; |
1695 | 1699 | ||
1696 | if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) { | 1700 | if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) { |
@@ -1716,7 +1720,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params, | |||
1716 | DP(NETIF_MSG_LINK, "phy link down\n"); | 1720 | DP(NETIF_MSG_LINK, "phy link down\n"); |
1717 | 1721 | ||
1718 | vars->phy_link_up = 0; | 1722 | vars->phy_link_up = 0; |
1719 | vars->line_speed = 0; | 1723 | |
1720 | vars->duplex = DUPLEX_FULL; | 1724 | vars->duplex = DUPLEX_FULL; |
1721 | vars->flow_ctrl = FLOW_CTRL_NONE; | 1725 | vars->flow_ctrl = FLOW_CTRL_NONE; |
1722 | vars->autoneg = AUTO_NEG_DISABLED; | 1726 | vars->autoneg = AUTO_NEG_DISABLED; |
@@ -2302,6 +2306,65 @@ static void bnx2x_ext_phy_set_pause(struct link_params *params, | |||
2302 | MDIO_AN_REG_ADV_PAUSE, val); | 2306 | MDIO_AN_REG_ADV_PAUSE, val); |
2303 | } | 2307 | } |
2304 | 2308 | ||
2309 | |||
2310 | static void bnx2x_init_internal_phy(struct link_params *params, | ||
2311 | struct link_vars *vars) | ||
2312 | { | ||
2313 | struct bnx2x *bp = params->bp; | ||
2314 | u8 port = params->port; | ||
2315 | if (!(vars->phy_flags & PHY_SGMII_FLAG)) { | ||
2316 | u16 bank, rx_eq; | ||
2317 | |||
2318 | rx_eq = ((params->serdes_config & | ||
2319 | PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_MASK) >> | ||
2320 | PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT); | ||
2321 | |||
2322 | DP(NETIF_MSG_LINK, "setting rx eq to 0x%x\n", rx_eq); | ||
2323 | for (bank = MDIO_REG_BANK_RX0; bank <= MDIO_REG_BANK_RX_ALL; | ||
2324 | bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0)) { | ||
2325 | CL45_WR_OVER_CL22(bp, port, | ||
2326 | params->phy_addr, | ||
2327 | bank , | ||
2328 | MDIO_RX0_RX_EQ_BOOST, | ||
2329 | ((rx_eq & | ||
2330 | MDIO_RX0_RX_EQ_BOOST_EQUALIZER_CTRL_MASK) | | ||
2331 | MDIO_RX0_RX_EQ_BOOST_OFFSET_CTRL)); | ||
2332 | } | ||
2333 | |||
2334 | /* forced speed requested? */ | ||
2335 | if (vars->line_speed != SPEED_AUTO_NEG) { | ||
2336 | DP(NETIF_MSG_LINK, "not SGMII, no AN\n"); | ||
2337 | |||
2338 | /* disable autoneg */ | ||
2339 | bnx2x_set_autoneg(params, vars); | ||
2340 | |||
2341 | /* program speed and duplex */ | ||
2342 | bnx2x_program_serdes(params); | ||
2343 | |||
2344 | } else { /* AN_mode */ | ||
2345 | DP(NETIF_MSG_LINK, "not SGMII, AN\n"); | ||
2346 | |||
2347 | /* AN enabled */ | ||
2348 | bnx2x_set_brcm_cl37_advertisment(params); | ||
2349 | |||
2350 | /* program duplex & pause advertisement (for aneg) */ | ||
2351 | bnx2x_set_ieee_aneg_advertisment(params, | ||
2352 | &vars->ieee_fc); | ||
2353 | |||
2354 | /* enable autoneg */ | ||
2355 | bnx2x_set_autoneg(params, vars); | ||
2356 | |||
2357 | /* enable and restart AN */ | ||
2358 | bnx2x_restart_autoneg(params); | ||
2359 | } | ||
2360 | |||
2361 | } else { /* SGMII mode */ | ||
2362 | DP(NETIF_MSG_LINK, "SGMII\n"); | ||
2363 | |||
2364 | bnx2x_initialize_sgmii_process(params); | ||
2365 | } | ||
2366 | } | ||
2367 | |||
2305 | static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars) | 2368 | static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars) |
2306 | { | 2369 | { |
2307 | struct bnx2x *bp = params->bp; | 2370 | struct bnx2x *bp = params->bp; |
@@ -2343,7 +2406,6 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars) | |||
2343 | 2406 | ||
2344 | switch (ext_phy_type) { | 2407 | switch (ext_phy_type) { |
2345 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: | 2408 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: |
2346 | DP(NETIF_MSG_LINK, "XGXS Direct\n"); | ||
2347 | break; | 2409 | break; |
2348 | 2410 | ||
2349 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: | 2411 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: |
@@ -2701,10 +2763,7 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars) | |||
2701 | } | 2763 | } |
2702 | 2764 | ||
2703 | } else { /* SerDes */ | 2765 | } else { /* SerDes */ |
2704 | /* ext_phy_addr = ((bp->ext_phy_config & | 2766 | |
2705 | PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK) >> | ||
2706 | PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT); | ||
2707 | */ | ||
2708 | ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config); | 2767 | ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config); |
2709 | switch (ext_phy_type) { | 2768 | switch (ext_phy_type) { |
2710 | case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT: | 2769 | case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT: |
@@ -2810,6 +2869,13 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params, | |||
2810 | */ | 2869 | */ |
2811 | ext_phy_link_up = ((rx_sd & pcs_status & 0x1) || | 2870 | ext_phy_link_up = ((rx_sd & pcs_status & 0x1) || |
2812 | (val2 & (1<<1))); | 2871 | (val2 & (1<<1))); |
2872 | if (ext_phy_link_up) { | ||
2873 | if (val2 & (1<<1)) | ||
2874 | vars->line_speed = SPEED_1000; | ||
2875 | else | ||
2876 | vars->line_speed = SPEED_10000; | ||
2877 | } | ||
2878 | |||
2813 | /* clear LASI indication*/ | 2879 | /* clear LASI indication*/ |
2814 | bnx2x_cl45_read(bp, params->port, ext_phy_type, | 2880 | bnx2x_cl45_read(bp, params->port, ext_phy_type, |
2815 | ext_phy_addr, | 2881 | ext_phy_addr, |
@@ -3006,6 +3072,7 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params, | |||
3006 | MDIO_AN_DEVAD, | 3072 | MDIO_AN_DEVAD, |
3007 | MDIO_AN_REG_MASTER_STATUS, | 3073 | MDIO_AN_REG_MASTER_STATUS, |
3008 | &val2); | 3074 | &val2); |
3075 | vars->line_speed = SPEED_10000; | ||
3009 | DP(NETIF_MSG_LINK, | 3076 | DP(NETIF_MSG_LINK, |
3010 | "SFX7101 AN status 0x%x->Master=%x\n", | 3077 | "SFX7101 AN status 0x%x->Master=%x\n", |
3011 | val2, | 3078 | val2, |
@@ -3181,7 +3248,8 @@ static u8 bnx2x_format_ver(u32 num, u8 *str, u16 len) | |||
3181 | } | 3248 | } |
3182 | 3249 | ||
3183 | 3250 | ||
3184 | static void bnx2x_turn_on_sf(struct bnx2x *bp, u8 port, u8 ext_phy_addr) | 3251 | static void bnx2x_turn_on_ef(struct bnx2x *bp, u8 port, u8 ext_phy_addr, |
3252 | u32 ext_phy_type) | ||
3185 | { | 3253 | { |
3186 | u32 cnt = 0; | 3254 | u32 cnt = 0; |
3187 | u16 ctrl = 0; | 3255 | u16 ctrl = 0; |
@@ -3205,7 +3273,7 @@ static void bnx2x_turn_on_sf(struct bnx2x *bp, u8 port, u8 ext_phy_addr) | |||
3205 | for (cnt = 0; cnt < 1000; cnt++) { | 3273 | for (cnt = 0; cnt < 1000; cnt++) { |
3206 | msleep(1); | 3274 | msleep(1); |
3207 | bnx2x_cl45_read(bp, port, | 3275 | bnx2x_cl45_read(bp, port, |
3208 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101, | 3276 | ext_phy_type, |
3209 | ext_phy_addr, | 3277 | ext_phy_addr, |
3210 | MDIO_PMA_DEVAD, | 3278 | MDIO_PMA_DEVAD, |
3211 | MDIO_PMA_REG_CTRL, | 3279 | MDIO_PMA_REG_CTRL, |
@@ -3253,7 +3321,8 @@ u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded, | |||
3253 | 3321 | ||
3254 | /* Take ext phy out of reset */ | 3322 | /* Take ext phy out of reset */ |
3255 | if (!driver_loaded) | 3323 | if (!driver_loaded) |
3256 | bnx2x_turn_on_sf(bp, params->port, ext_phy_addr); | 3324 | bnx2x_turn_on_ef(bp, params->port, ext_phy_addr, |
3325 | ext_phy_type); | ||
3257 | 3326 | ||
3258 | /* wait for 1ms */ | 3327 | /* wait for 1ms */ |
3259 | msleep(1); | 3328 | msleep(1); |
@@ -3281,6 +3350,11 @@ u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded, | |||
3281 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: | 3350 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: |
3282 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: | 3351 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: |
3283 | { | 3352 | { |
3353 | /* Take ext phy out of reset */ | ||
3354 | if (!driver_loaded) | ||
3355 | bnx2x_turn_on_ef(bp, params->port, ext_phy_addr, | ||
3356 | ext_phy_type); | ||
3357 | |||
3284 | bnx2x_cl45_read(bp, params->port, ext_phy_type, | 3358 | bnx2x_cl45_read(bp, params->port, ext_phy_type, |
3285 | ext_phy_addr, | 3359 | ext_phy_addr, |
3286 | MDIO_PMA_DEVAD, | 3360 | MDIO_PMA_DEVAD, |
@@ -3622,7 +3696,8 @@ static u8 bnx2x_link_initialize(struct link_params *params, | |||
3622 | struct bnx2x *bp = params->bp; | 3696 | struct bnx2x *bp = params->bp; |
3623 | u8 port = params->port; | 3697 | u8 port = params->port; |
3624 | u8 rc = 0; | 3698 | u8 rc = 0; |
3625 | 3699 | u8 non_ext_phy; | |
3700 | u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config); | ||
3626 | /* Activate the external PHY */ | 3701 | /* Activate the external PHY */ |
3627 | bnx2x_ext_phy_reset(params, vars); | 3702 | bnx2x_ext_phy_reset(params, vars); |
3628 | 3703 | ||
@@ -3644,10 +3719,6 @@ static u8 bnx2x_link_initialize(struct link_params *params, | |||
3644 | bnx2x_set_swap_lanes(params); | 3719 | bnx2x_set_swap_lanes(params); |
3645 | } | 3720 | } |
3646 | 3721 | ||
3647 | /* Set Parallel Detect */ | ||
3648 | if (params->req_line_speed == SPEED_AUTO_NEG) | ||
3649 | bnx2x_set_parallel_detection(params, vars->phy_flags); | ||
3650 | |||
3651 | if (vars->phy_flags & PHY_XGXS_FLAG) { | 3722 | if (vars->phy_flags & PHY_XGXS_FLAG) { |
3652 | if (params->req_line_speed && | 3723 | if (params->req_line_speed && |
3653 | ((params->req_line_speed == SPEED_100) || | 3724 | ((params->req_line_speed == SPEED_100) || |
@@ -3657,68 +3728,33 @@ static u8 bnx2x_link_initialize(struct link_params *params, | |||
3657 | vars->phy_flags &= ~PHY_SGMII_FLAG; | 3728 | vars->phy_flags &= ~PHY_SGMII_FLAG; |
3658 | } | 3729 | } |
3659 | } | 3730 | } |
3731 | /* In case of external phy existance, the line speed would be the | ||
3732 | line speed linked up by the external phy. In case it is direct only, | ||
3733 | then the line_speed during initialization will be equal to the | ||
3734 | req_line_speed*/ | ||
3735 | vars->line_speed = params->req_line_speed; | ||
3660 | 3736 | ||
3661 | if (!(vars->phy_flags & PHY_SGMII_FLAG)) { | 3737 | bnx2x_set_ieee_aneg_advertisment(params, &vars->ieee_fc); |
3662 | u16 bank, rx_eq; | ||
3663 | |||
3664 | rx_eq = ((params->serdes_config & | ||
3665 | PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_MASK) >> | ||
3666 | PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT); | ||
3667 | |||
3668 | DP(NETIF_MSG_LINK, "setting rx eq to 0x%x\n", rx_eq); | ||
3669 | for (bank = MDIO_REG_BANK_RX0; bank <= MDIO_REG_BANK_RX_ALL; | ||
3670 | bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0)) { | ||
3671 | CL45_WR_OVER_CL22(bp, port, | ||
3672 | params->phy_addr, | ||
3673 | bank , | ||
3674 | MDIO_RX0_RX_EQ_BOOST, | ||
3675 | ((rx_eq & | ||
3676 | MDIO_RX0_RX_EQ_BOOST_EQUALIZER_CTRL_MASK) | | ||
3677 | MDIO_RX0_RX_EQ_BOOST_OFFSET_CTRL)); | ||
3678 | } | ||
3679 | |||
3680 | /* forced speed requested? */ | ||
3681 | if (params->req_line_speed != SPEED_AUTO_NEG) { | ||
3682 | DP(NETIF_MSG_LINK, "not SGMII, no AN\n"); | ||
3683 | |||
3684 | /* disable autoneg */ | ||
3685 | bnx2x_set_autoneg(params, vars); | ||
3686 | |||
3687 | /* program speed and duplex */ | ||
3688 | bnx2x_program_serdes(params); | ||
3689 | vars->ieee_fc = | ||
3690 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE; | ||
3691 | |||
3692 | } else { /* AN_mode */ | ||
3693 | DP(NETIF_MSG_LINK, "not SGMII, AN\n"); | ||
3694 | |||
3695 | /* AN enabled */ | ||
3696 | bnx2x_set_brcm_cl37_advertisment(params); | ||
3697 | |||
3698 | /* program duplex & pause advertisement (for aneg) */ | ||
3699 | bnx2x_set_ieee_aneg_advertisment(params, | ||
3700 | &vars->ieee_fc); | ||
3701 | |||
3702 | /* enable autoneg */ | ||
3703 | bnx2x_set_autoneg(params, vars); | ||
3704 | |||
3705 | /* enable and restart AN */ | ||
3706 | bnx2x_restart_autoneg(params); | ||
3707 | } | ||
3708 | 3738 | ||
3709 | } else { /* SGMII mode */ | 3739 | /* init ext phy and enable link state int */ |
3710 | DP(NETIF_MSG_LINK, "SGMII\n"); | 3740 | non_ext_phy = ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) || |
3711 | 3741 | (params->loopback_mode == LOOPBACK_XGXS_10) || | |
3712 | bnx2x_initialize_sgmii_process(params); | 3742 | (params->loopback_mode == LOOPBACK_EXT_PHY)); |
3743 | |||
3744 | if (non_ext_phy || | ||
3745 | (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705)) { | ||
3746 | if (params->req_line_speed == SPEED_AUTO_NEG) | ||
3747 | bnx2x_set_parallel_detection(params, vars->phy_flags); | ||
3748 | bnx2x_init_internal_phy(params, vars); | ||
3713 | } | 3749 | } |
3714 | 3750 | ||
3715 | /* init ext phy and enable link state int */ | 3751 | if (!non_ext_phy) |
3716 | rc |= bnx2x_ext_phy_init(params, vars); | 3752 | rc |= bnx2x_ext_phy_init(params, vars); |
3717 | 3753 | ||
3718 | bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, | 3754 | bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, |
3719 | (NIG_STATUS_XGXS0_LINK10G | | 3755 | (NIG_STATUS_XGXS0_LINK10G | |
3720 | NIG_STATUS_XGXS0_LINK_STATUS | | 3756 | NIG_STATUS_XGXS0_LINK_STATUS | |
3721 | NIG_STATUS_SERDES0_LINK_STATUS)); | 3757 | NIG_STATUS_SERDES0_LINK_STATUS)); |
3722 | 3758 | ||
3723 | return rc; | 3759 | return rc; |
3724 | 3760 | ||
@@ -3734,6 +3770,13 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars) | |||
3734 | DP(NETIF_MSG_LINK, "req_speed = %d, req_flowctrl=%d\n", | 3770 | DP(NETIF_MSG_LINK, "req_speed = %d, req_flowctrl=%d\n", |
3735 | params->req_line_speed, params->req_flow_ctrl); | 3771 | params->req_line_speed, params->req_flow_ctrl); |
3736 | vars->link_status = 0; | 3772 | vars->link_status = 0; |
3773 | vars->phy_link_up = 0; | ||
3774 | vars->link_up = 0; | ||
3775 | vars->line_speed = 0; | ||
3776 | vars->duplex = DUPLEX_FULL; | ||
3777 | vars->flow_ctrl = FLOW_CTRL_NONE; | ||
3778 | vars->mac_type = MAC_TYPE_NONE; | ||
3779 | |||
3737 | if (params->switch_cfg == SWITCH_CFG_1G) | 3780 | if (params->switch_cfg == SWITCH_CFG_1G) |
3738 | vars->phy_flags = PHY_SERDES_FLAG; | 3781 | vars->phy_flags = PHY_SERDES_FLAG; |
3739 | else | 3782 | else |
@@ -3894,6 +3937,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars) | |||
3894 | } | 3937 | } |
3895 | 3938 | ||
3896 | bnx2x_link_initialize(params, vars); | 3939 | bnx2x_link_initialize(params, vars); |
3940 | msleep(30); | ||
3897 | bnx2x_link_int_enable(params); | 3941 | bnx2x_link_int_enable(params); |
3898 | } | 3942 | } |
3899 | return 0; | 3943 | return 0; |
@@ -3949,33 +3993,13 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars) | |||
3949 | MISC_REGISTERS_GPIO_OUTPUT_LOW); | 3993 | MISC_REGISTERS_GPIO_OUTPUT_LOW); |
3950 | 3994 | ||
3951 | DP(NETIF_MSG_LINK, "reset external PHY\n"); | 3995 | DP(NETIF_MSG_LINK, "reset external PHY\n"); |
3952 | } else { | 3996 | } else if (ext_phy_type == |
3953 | 3997 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) { | |
3954 | u8 ext_phy_addr = ((ext_phy_config & | 3998 | DP(NETIF_MSG_LINK, "Setting 8073 port %d into " |
3955 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> | ||
3956 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); | ||
3957 | |||
3958 | /* SW reset */ | ||
3959 | bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr, | ||
3960 | MDIO_PMA_DEVAD, | ||
3961 | MDIO_PMA_REG_CTRL, | ||
3962 | 1<<15); | ||
3963 | |||
3964 | /* Set Low Power Mode */ | ||
3965 | bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr, | ||
3966 | MDIO_PMA_DEVAD, | ||
3967 | MDIO_PMA_REG_CTRL, | ||
3968 | 1<<11); | ||
3969 | |||
3970 | |||
3971 | if (ext_phy_type == | ||
3972 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) { | ||
3973 | DP(NETIF_MSG_LINK, "Setting 8073 port %d into" | ||
3974 | "low power mode\n", | 3999 | "low power mode\n", |
3975 | port); | 4000 | port); |
3976 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, | 4001 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, |
3977 | MISC_REGISTERS_GPIO_OUTPUT_LOW); | 4002 | MISC_REGISTERS_GPIO_OUTPUT_LOW); |
3978 | } | ||
3979 | } | 4003 | } |
3980 | } | 4004 | } |
3981 | /* reset the SerDes/XGXS */ | 4005 | /* reset the SerDes/XGXS */ |
@@ -3995,6 +4019,73 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars) | |||
3995 | return 0; | 4019 | return 0; |
3996 | } | 4020 | } |
3997 | 4021 | ||
4022 | static u8 bnx2x_update_link_down(struct link_params *params, | ||
4023 | struct link_vars *vars) | ||
4024 | { | ||
4025 | struct bnx2x *bp = params->bp; | ||
4026 | u8 port = params->port; | ||
4027 | DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port); | ||
4028 | bnx2x_set_led(bp, port, LED_MODE_OFF, | ||
4029 | 0, params->hw_led_mode, | ||
4030 | params->chip_id); | ||
4031 | |||
4032 | /* indicate no mac active */ | ||
4033 | vars->mac_type = MAC_TYPE_NONE; | ||
4034 | |||
4035 | /* update shared memory */ | ||
4036 | vars->link_status = 0; | ||
4037 | vars->line_speed = 0; | ||
4038 | bnx2x_update_mng(params, vars->link_status); | ||
4039 | |||
4040 | /* activate nig drain */ | ||
4041 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1); | ||
4042 | |||
4043 | /* reset BigMac */ | ||
4044 | bnx2x_bmac_rx_disable(bp, params->port); | ||
4045 | REG_WR(bp, GRCBASE_MISC + | ||
4046 | MISC_REGISTERS_RESET_REG_2_CLEAR, | ||
4047 | (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); | ||
4048 | return 0; | ||
4049 | } | ||
4050 | |||
4051 | static u8 bnx2x_update_link_up(struct link_params *params, | ||
4052 | struct link_vars *vars, | ||
4053 | u8 link_10g, u32 gp_status) | ||
4054 | { | ||
4055 | struct bnx2x *bp = params->bp; | ||
4056 | u8 port = params->port; | ||
4057 | u8 rc = 0; | ||
4058 | vars->link_status |= LINK_STATUS_LINK_UP; | ||
4059 | if (link_10g) { | ||
4060 | bnx2x_bmac_enable(params, vars, 0); | ||
4061 | bnx2x_set_led(bp, port, LED_MODE_OPER, | ||
4062 | SPEED_10000, params->hw_led_mode, | ||
4063 | params->chip_id); | ||
4064 | |||
4065 | } else { | ||
4066 | bnx2x_emac_enable(params, vars, 0); | ||
4067 | rc = bnx2x_emac_program(params, vars->line_speed, | ||
4068 | vars->duplex); | ||
4069 | |||
4070 | /* AN complete? */ | ||
4071 | if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) { | ||
4072 | if (!(vars->phy_flags & | ||
4073 | PHY_SGMII_FLAG)) | ||
4074 | bnx2x_set_sgmii_tx_driver(params); | ||
4075 | } | ||
4076 | } | ||
4077 | |||
4078 | /* PBF - link up */ | ||
4079 | rc |= bnx2x_pbf_update(params, vars->flow_ctrl, | ||
4080 | vars->line_speed); | ||
4081 | |||
4082 | /* disable drain */ | ||
4083 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0); | ||
4084 | |||
4085 | /* update shared memory */ | ||
4086 | bnx2x_update_mng(params, vars->link_status); | ||
4087 | return rc; | ||
4088 | } | ||
3998 | /* This function should called upon link interrupt */ | 4089 | /* This function should called upon link interrupt */ |
3999 | /* In case vars->link_up, driver needs to | 4090 | /* In case vars->link_up, driver needs to |
4000 | 1. Update the pbf | 4091 | 1. Update the pbf |
@@ -4012,10 +4103,10 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars) | |||
4012 | { | 4103 | { |
4013 | struct bnx2x *bp = params->bp; | 4104 | struct bnx2x *bp = params->bp; |
4014 | u8 port = params->port; | 4105 | u8 port = params->port; |
4015 | u16 i; | ||
4016 | u16 gp_status; | 4106 | u16 gp_status; |
4017 | u16 link_10g; | 4107 | u8 link_10g; |
4018 | u8 rc = 0; | 4108 | u8 ext_phy_link_up, rc = 0; |
4109 | u32 ext_phy_type; | ||
4019 | 4110 | ||
4020 | DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n", | 4111 | DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n", |
4021 | port, | 4112 | port, |
@@ -4031,15 +4122,16 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars) | |||
4031 | REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68), | 4122 | REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68), |
4032 | REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68)); | 4123 | REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68)); |
4033 | 4124 | ||
4125 | ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config); | ||
4034 | 4126 | ||
4035 | /* avoid fast toggling */ | 4127 | /* Check external link change only for non-direct */ |
4036 | for (i = 0; i < 10; i++) { | 4128 | ext_phy_link_up = bnx2x_ext_phy_is_link_up(params, vars); |
4037 | msleep(10); | 4129 | |
4038 | CL45_RD_OVER_CL22(bp, port, params->phy_addr, | 4130 | /* Read gp_status */ |
4039 | MDIO_REG_BANK_GP_STATUS, | 4131 | CL45_RD_OVER_CL22(bp, port, params->phy_addr, |
4040 | MDIO_GP_STATUS_TOP_AN_STATUS1, | 4132 | MDIO_REG_BANK_GP_STATUS, |
4041 | &gp_status); | 4133 | MDIO_GP_STATUS_TOP_AN_STATUS1, |
4042 | } | 4134 | &gp_status); |
4043 | 4135 | ||
4044 | rc = bnx2x_link_settings_status(params, vars, gp_status); | 4136 | rc = bnx2x_link_settings_status(params, vars, gp_status); |
4045 | if (rc != 0) | 4137 | if (rc != 0) |
@@ -4055,69 +4147,25 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars) | |||
4055 | 4147 | ||
4056 | bnx2x_link_int_ack(params, vars, link_10g); | 4148 | bnx2x_link_int_ack(params, vars, link_10g); |
4057 | 4149 | ||
4058 | /* link is up only if both local phy and external phy are up */ | 4150 | /* In case external phy link is up, and internal link is down |
4059 | vars->link_up = (vars->phy_link_up && | 4151 | ( not initialized yet probably after link initialization, it needs |
4060 | bnx2x_ext_phy_is_link_up(params, vars)); | 4152 | to be initialized. |
4061 | 4153 | Note that after link down-up as result of cable plug, | |
4062 | if (!vars->phy_link_up && | 4154 | the xgxs link would probably become up again without the need to |
4063 | REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18)) { | 4155 | initialize it*/ |
4064 | bnx2x_ext_phy_is_link_up(params, vars); /* Clear interrupt */ | ||
4065 | } | ||
4066 | |||
4067 | if (vars->link_up) { | ||
4068 | vars->link_status |= LINK_STATUS_LINK_UP; | ||
4069 | if (link_10g) { | ||
4070 | bnx2x_bmac_enable(params, vars, 0); | ||
4071 | bnx2x_set_led(bp, port, LED_MODE_OPER, | ||
4072 | SPEED_10000, params->hw_led_mode, | ||
4073 | params->chip_id); | ||
4074 | |||
4075 | } else { | ||
4076 | bnx2x_emac_enable(params, vars, 0); | ||
4077 | rc = bnx2x_emac_program(params, vars->line_speed, | ||
4078 | vars->duplex); | ||
4079 | |||
4080 | /* AN complete? */ | ||
4081 | if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) { | ||
4082 | if (!(vars->phy_flags & | ||
4083 | PHY_SGMII_FLAG)) | ||
4084 | bnx2x_set_sgmii_tx_driver(params); | ||
4085 | } | ||
4086 | } | ||
4087 | |||
4088 | /* PBF - link up */ | ||
4089 | rc |= bnx2x_pbf_update(params, vars->flow_ctrl, | ||
4090 | vars->line_speed); | ||
4091 | 4156 | ||
4092 | /* disable drain */ | 4157 | if ((ext_phy_type != PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) && |
4093 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0); | 4158 | (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) && |
4159 | (ext_phy_link_up && !vars->phy_link_up)) | ||
4160 | bnx2x_init_internal_phy(params, vars); | ||
4094 | 4161 | ||
4095 | /* update shared memory */ | 4162 | /* link is up only if both local phy and external phy are up */ |
4096 | bnx2x_update_mng(params, vars->link_status); | 4163 | vars->link_up = (ext_phy_link_up && vars->phy_link_up); |
4097 | |||
4098 | } else { /* link down */ | ||
4099 | DP(NETIF_MSG_LINK, "Port %x: Link is down\n", params->port); | ||
4100 | bnx2x_set_led(bp, port, LED_MODE_OFF, | ||
4101 | 0, params->hw_led_mode, | ||
4102 | params->chip_id); | ||
4103 | |||
4104 | /* indicate no mac active */ | ||
4105 | vars->mac_type = MAC_TYPE_NONE; | ||
4106 | |||
4107 | /* update shared memory */ | ||
4108 | vars->link_status = 0; | ||
4109 | bnx2x_update_mng(params, vars->link_status); | ||
4110 | |||
4111 | /* activate nig drain */ | ||
4112 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1); | ||
4113 | |||
4114 | /* reset BigMac */ | ||
4115 | bnx2x_bmac_rx_disable(bp, params->port); | ||
4116 | REG_WR(bp, GRCBASE_MISC + | ||
4117 | MISC_REGISTERS_RESET_REG_2_CLEAR, | ||
4118 | (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); | ||
4119 | 4164 | ||
4120 | } | 4165 | if (vars->link_up) |
4166 | rc = bnx2x_update_link_up(params, vars, link_10g, gp_status); | ||
4167 | else | ||
4168 | rc = bnx2x_update_link_down(params, vars); | ||
4121 | 4169 | ||
4122 | return rc; | 4170 | return rc; |
4123 | } | 4171 | } |
@@ -4508,7 +4556,7 @@ u8 bnx2x_flash_download(struct bnx2x *bp, u8 port, u32 ext_phy_config, | |||
4508 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: | 4556 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: |
4509 | /* Take ext phy out of reset */ | 4557 | /* Take ext phy out of reset */ |
4510 | if (!driver_loaded) | 4558 | if (!driver_loaded) |
4511 | bnx2x_turn_on_sf(bp, port, ext_phy_addr); | 4559 | bnx2x_turn_on_ef(bp, port, ext_phy_addr, ext_phy_type); |
4512 | rc = bnx2x_sfx7101_flash_download(bp, port, ext_phy_addr, | 4560 | rc = bnx2x_sfx7101_flash_download(bp, port, ext_phy_addr, |
4513 | data, size); | 4561 | data, size); |
4514 | if (!driver_loaded) | 4562 | if (!driver_loaded) |
diff --git a/drivers/net/bnx2x_reg.h b/drivers/net/bnx2x_reg.h index a85ff2073681..58fbeb1cf78d 100644 --- a/drivers/net/bnx2x_reg.h +++ b/drivers/net/bnx2x_reg.h | |||
@@ -5559,6 +5559,8 @@ Theotherbitsarereservedandshouldbezero*/ | |||
5559 | #define MDIO_PMA_REG_GEN_CTRL 0xca10 | 5559 | #define MDIO_PMA_REG_GEN_CTRL 0xca10 |
5560 | #define MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP 0x0188 | 5560 | #define MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP 0x0188 |
5561 | #define MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET 0x018a | 5561 | #define MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET 0x018a |
5562 | #define MDIO_PMA_REG_M8051_MSGIN_REG 0xca12 | ||
5563 | #define MDIO_PMA_REG_M8051_MSGOUT_REG 0xca13 | ||
5562 | #define MDIO_PMA_REG_ROM_VER1 0xca19 | 5564 | #define MDIO_PMA_REG_ROM_VER1 0xca19 |
5563 | #define MDIO_PMA_REG_ROM_VER2 0xca1a | 5565 | #define MDIO_PMA_REG_ROM_VER2 0xca1a |
5564 | #define MDIO_PMA_REG_EDC_FFE_MAIN 0xca1b | 5566 | #define MDIO_PMA_REG_EDC_FFE_MAIN 0xca1b |