aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2x_link.c
diff options
context:
space:
mode:
authorYaniv Rosner <yanivr@broadcom.com>2008-08-13 18:55:28 -0400
committerDavid S. Miller <davem@davemloft.net>2008-08-13 19:04:03 -0400
commit57963ed94c27e94a7533434da5943195ea072a35 (patch)
tree295ecff7ffef1e4c4349ec04b5463ad6af9a93b4 /drivers/net/bnx2x_link.c
parentdf0f23439a69eb5ca30668612f1c4e20041b5341 (diff)
bnx2x: Link order with external PHY
Link order with external PHY When external PHY exists (second chip with the PHY to translate to another physical medium) the link with the eternal PHY and the network should be established before setting the link between the 5771x and the PHY. This is the right order and it is important when using autoneg - the link to the network should use the autoneg and the link between the two chips should be forced to the network result. 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/bnx2x_link.c')
-rw-r--r--drivers/net/bnx2x_link.c380
1 files changed, 214 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
2310static 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
2305static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars) 2368static 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
3184static void bnx2x_turn_on_sf(struct bnx2x *bp, u8 port, u8 ext_phy_addr) 3251static 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
4022static 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
4051static 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)