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

bnx2x: Adjust flow-control with the new scheme

Flow control implementation is split to be done in each PHY 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 62b29a5d
...@@ -171,13 +171,13 @@ ...@@ -171,13 +171,13 @@
#define CL45_WR_OVER_CL22(_bp, _phy, _bank, _addr, _val) \ #define CL45_WR_OVER_CL22(_bp, _phy, _bank, _addr, _val) \
bnx2x_cl45_write(_bp, _phy, \ bnx2x_cl45_write(_bp, _phy, \
DEFAULT_PHY_DEV_ADDR, \ (_phy)->def_md_devad, \
(_bank + (_addr & 0xf)), \ (_bank + (_addr & 0xf)), \
_val) _val)
#define CL45_RD_OVER_CL22(_bp, _phy, _bank, _addr, _val) \ #define CL45_RD_OVER_CL22(_bp, _phy, _bank, _addr, _val) \
bnx2x_cl45_read(_bp, _phy, \ bnx2x_cl45_read(_bp, _phy, \
DEFAULT_PHY_DEV_ADDR, \ (_phy)->def_md_devad, \
(_bank + (_addr & 0xf)), \ (_bank + (_addr & 0xf)), \
_val) _val)
...@@ -634,24 +634,22 @@ void bnx2x_link_status_update(struct link_params *params, ...@@ -634,24 +634,22 @@ void bnx2x_link_status_update(struct link_params *params,
break; break;
} }
vars->flow_ctrl = 0;
if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED) if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
vars->flow_ctrl |= BNX2X_FLOW_CTRL_TX; vars->flow_ctrl |= BNX2X_FLOW_CTRL_TX;
else
vars->flow_ctrl &= ~BNX2X_FLOW_CTRL_TX;
if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED) if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
vars->flow_ctrl |= BNX2X_FLOW_CTRL_RX; vars->flow_ctrl |= BNX2X_FLOW_CTRL_RX;
else
vars->flow_ctrl &= ~BNX2X_FLOW_CTRL_RX;
if (vars->phy_flags & PHY_XGXS_FLAG) { if (!vars->flow_ctrl)
if (vars->line_speed && vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
((vars->line_speed == SPEED_10) ||
(vars->line_speed == SPEED_100))) { if (vars->line_speed &&
vars->phy_flags |= PHY_SGMII_FLAG; ((vars->line_speed == SPEED_10) ||
} else { (vars->line_speed == SPEED_100))) {
vars->phy_flags &= ~PHY_SGMII_FLAG; vars->phy_flags |= PHY_SGMII_FLAG;
} } else {
vars->phy_flags &= ~PHY_SGMII_FLAG;
} }
/* anything 10 and over uses the bmac */ /* anything 10 and over uses the bmac */
...@@ -1137,12 +1135,12 @@ static void bnx2x_set_parallel_detection(struct bnx2x_phy *phy, ...@@ -1137,12 +1135,12 @@ static void bnx2x_set_parallel_detection(struct bnx2x_phy *phy,
MDIO_REG_BANK_SERDES_DIGITAL, MDIO_REG_BANK_SERDES_DIGITAL,
MDIO_SERDES_DIGITAL_A_1000X_CONTROL2, MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
&control2); &control2);
if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN; control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
else else
control2 &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN; control2 &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
DP(NETIF_MSG_LINK, "params->speed_cap_mask = 0x%x, control2 = 0x%x\n", DP(NETIF_MSG_LINK, "phy->speed_cap_mask = 0x%x, control2 = 0x%x\n",
params->speed_cap_mask, control2); phy->speed_cap_mask, control2);
CL45_WR_OVER_CL22(bp, phy, CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_SERDES_DIGITAL, MDIO_REG_BANK_SERDES_DIGITAL,
MDIO_SERDES_DIGITAL_A_1000X_CONTROL2, MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
...@@ -1261,10 +1259,10 @@ static void bnx2x_set_autoneg(struct bnx2x_phy *phy, ...@@ -1261,10 +1259,10 @@ static void bnx2x_set_autoneg(struct bnx2x_phy *phy,
MDIO_REG_BANK_CL73_IEEEB1, MDIO_REG_BANK_CL73_IEEEB1,
MDIO_CL73_IEEEB1_AN_ADV2, MDIO_CL73_IEEEB1_AN_ADV2,
&reg_val); &reg_val);
if (params->speed_cap_mask & if (phy->speed_cap_mask &
PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4; reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4;
if (params->speed_cap_mask & if (phy->speed_cap_mask &
PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX; reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;
...@@ -1299,7 +1297,7 @@ static void bnx2x_program_serdes(struct bnx2x_phy *phy, ...@@ -1299,7 +1297,7 @@ static void bnx2x_program_serdes(struct bnx2x_phy *phy,
reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX | reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX |
MDIO_COMBO_IEEO_MII_CONTROL_AN_EN | MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK); MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK);
if (params->req_duplex == DUPLEX_FULL) if (phy->req_duplex == DUPLEX_FULL)
reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX; reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
CL45_WR_OVER_CL22(bp, phy, CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_COMBO_IEEE0, MDIO_REG_BANK_COMBO_IEEE0,
...@@ -1345,9 +1343,9 @@ static void bnx2x_set_brcm_cl37_advertisment(struct bnx2x_phy *phy, ...@@ -1345,9 +1343,9 @@ static void bnx2x_set_brcm_cl37_advertisment(struct bnx2x_phy *phy,
/* configure the 48 bits for BAM AN */ /* configure the 48 bits for BAM AN */
/* set extended capabilities */ /* set extended capabilities */
if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
val |= MDIO_OVER_1G_UP1_2_5G; val |= MDIO_OVER_1G_UP1_2_5G;
if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
val |= MDIO_OVER_1G_UP1_10G; val |= MDIO_OVER_1G_UP1_10G;
CL45_WR_OVER_CL22(bp, phy, CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_OVER_1G, MDIO_REG_BANK_OVER_1G,
...@@ -1366,7 +1364,7 @@ static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy, ...@@ -1366,7 +1364,7 @@ static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
/* resolve pause mode and advertisement /* resolve pause mode and advertisement
* Please refer to Table 28B-3 of the 802.3ab-1999 spec */ * Please refer to Table 28B-3 of the 802.3ab-1999 spec */
switch (params->req_flow_ctrl) { switch (phy->req_flow_ctrl) {
case BNX2X_FLOW_CTRL_AUTO: case BNX2X_FLOW_CTRL_AUTO:
if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH) { if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH) {
*ieee_fc |= *ieee_fc |=
...@@ -1511,7 +1509,7 @@ static void bnx2x_initialize_sgmii_process(struct bnx2x_phy *phy, ...@@ -1511,7 +1509,7 @@ static void bnx2x_initialize_sgmii_process(struct bnx2x_phy *phy,
} }
/* setting the full duplex */ /* setting the full duplex */
if (params->req_duplex == DUPLEX_FULL) if (phy->req_duplex == DUPLEX_FULL)
mii_control |= mii_control |=
MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX; MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
CL45_WR_OVER_CL22(bp, phy, CL45_WR_OVER_CL22(bp, phy,
...@@ -1551,6 +1549,11 @@ static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result) ...@@ -1551,6 +1549,11 @@ static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
default: default:
break; break;
} }
if (pause_result & (1<<0))
vars->link_status |= LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE;
if (pause_result & (1<<1))
vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
} }
static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy, static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
...@@ -1560,19 +1563,17 @@ static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy, ...@@ -1560,19 +1563,17 @@ static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
struct bnx2x *bp = params->bp; struct bnx2x *bp = params->bp;
u16 ld_pause; /* local */ u16 ld_pause; /* local */
u16 lp_pause; /* link partner */ u16 lp_pause; /* link partner */
u16 an_complete; /* AN complete */
u16 pause_result; u16 pause_result;
u8 ret = 0; u8 ret = 0;
/* read twice */ /* read twice */
bnx2x_cl45_read(bp, phy, vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
MDIO_AN_DEVAD,
MDIO_AN_REG_STATUS, &an_complete);
bnx2x_cl45_read(bp, phy,
MDIO_AN_DEVAD,
MDIO_AN_REG_STATUS, &an_complete);
if (an_complete & MDIO_AN_REG_STATUS_AN_COMPLETE) { if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
vars->flow_ctrl = phy->req_flow_ctrl;
else if (phy->req_line_speed != SPEED_AUTO_NEG)
vars->flow_ctrl = params->req_fc_auto_adv;
else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
ret = 1; ret = 1;
bnx2x_cl45_read(bp, phy, bnx2x_cl45_read(bp, phy,
MDIO_AN_DEVAD, MDIO_AN_DEVAD,
...@@ -1587,24 +1588,6 @@ static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy, ...@@ -1587,24 +1588,6 @@ static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n", DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n",
pause_result); pause_result);
bnx2x_pause_resolve(vars, pause_result); bnx2x_pause_resolve(vars, pause_result);
if (vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE &&
phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
bnx2x_cl45_read(bp, phy,
MDIO_AN_DEVAD,
MDIO_AN_REG_CL37_FC_LD, &ld_pause);
bnx2x_cl45_read(bp, phy,
MDIO_AN_DEVAD,
MDIO_AN_REG_CL37_FC_LP, &lp_pause);
pause_result = (ld_pause &
MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
pause_result |= (lp_pause &
MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
bnx2x_pause_resolve(vars, pause_result);
DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x\n",
pause_result);
}
} }
return ret; return ret;
} }
...@@ -1614,6 +1597,8 @@ static u8 bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy, ...@@ -1614,6 +1597,8 @@ static u8 bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy,
{ {
struct bnx2x *bp = params->bp; struct bnx2x *bp = params->bp;
u16 pd_10g, status2_1000x; u16 pd_10g, status2_1000x;
if (phy->req_line_speed != SPEED_AUTO_NEG)
return 0;
CL45_RD_OVER_CL22(bp, phy, CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_SERDES_DIGITAL, MDIO_REG_BANK_SERDES_DIGITAL,
MDIO_SERDES_DIGITAL_A_1000X_STATUS2, MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
...@@ -1654,10 +1639,12 @@ static void bnx2x_flow_ctrl_resolve(struct bnx2x_phy *phy, ...@@ -1654,10 +1639,12 @@ static void bnx2x_flow_ctrl_resolve(struct bnx2x_phy *phy,
vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
/* resolve from gp_status in case of AN complete and not sgmii */ /* resolve from gp_status in case of AN complete and not sgmii */
if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) && if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
(gp_status & MDIO_AN_CL73_OR_37_COMPLETE) && vars->flow_ctrl = phy->req_flow_ctrl;
(!(vars->phy_flags & PHY_SGMII_FLAG)) && else if (phy->req_line_speed != SPEED_AUTO_NEG)
(phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)) { vars->flow_ctrl = params->req_fc_auto_adv;
else if ((gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
(!(vars->phy_flags & PHY_SGMII_FLAG))) {
if (bnx2x_direct_parallel_detect_used(phy, params)) { if (bnx2x_direct_parallel_detect_used(phy, params)) {
vars->flow_ctrl = params->req_fc_auto_adv; vars->flow_ctrl = params->req_fc_auto_adv;
return; return;
...@@ -1701,14 +1688,6 @@ static void bnx2x_flow_ctrl_resolve(struct bnx2x_phy *phy, ...@@ -1701,14 +1688,6 @@ static void bnx2x_flow_ctrl_resolve(struct bnx2x_phy *phy,
pause_result); pause_result);
} }
bnx2x_pause_resolve(vars, pause_result); bnx2x_pause_resolve(vars, pause_result);
} else if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
(bnx2x_ext_phy_resolve_fc(phy, params, vars))) {
return;
} else {
if (params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO)
vars->flow_ctrl = params->req_fc_auto_adv;
else
vars->flow_ctrl = params->req_flow_ctrl;
} }
DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl); DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl);
} }
...@@ -1776,6 +1755,21 @@ static void bnx2x_check_fallback_to_cl37(struct bnx2x_phy *phy, ...@@ -1776,6 +1755,21 @@ static void bnx2x_check_fallback_to_cl37(struct bnx2x_phy *phy,
bnx2x_restart_autoneg(phy, params, 0); bnx2x_restart_autoneg(phy, params, 0);
DP(NETIF_MSG_LINK, "Disabling CL73, and restarting CL37 autoneg\n"); DP(NETIF_MSG_LINK, "Disabling CL73, and restarting CL37 autoneg\n");
} }
static void bnx2x_xgxs_an_resolve(struct bnx2x_phy *phy,
struct link_params *params,
struct link_vars *vars,
u32 gp_status)
{
if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE)
vars->link_status |=
LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
if (bnx2x_direct_parallel_detect_used(phy, params))
vars->link_status |=
LINK_STATUS_PARALLEL_DETECTION_USED;
}
static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy, static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
struct link_params *params, struct link_params *params,
struct link_vars *vars) struct link_vars *vars)
...@@ -1789,7 +1783,8 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy, ...@@ -1789,7 +1783,8 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
MDIO_REG_BANK_GP_STATUS, MDIO_REG_BANK_GP_STATUS,
MDIO_GP_STATUS_TOP_AN_STATUS1, MDIO_GP_STATUS_TOP_AN_STATUS1,
&gp_status); &gp_status);
if (phy->req_line_speed == SPEED_AUTO_NEG)
vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) { if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n", DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n",
gp_status); gp_status);
...@@ -1802,8 +1797,12 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy, ...@@ -1802,8 +1797,12 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
else else
vars->duplex = DUPLEX_HALF; vars->duplex = DUPLEX_HALF;
bnx2x_flow_ctrl_resolve(&params->phy[INT_PHY], if (SINGLE_MEDIA_DIRECT(params)) {
params, vars, gp_status); bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status);
if (phy->req_line_speed == SPEED_AUTO_NEG)
bnx2x_xgxs_an_resolve(phy, params, vars,
gp_status);
}
switch (gp_status & GP_STATUS_SPEED_MASK) { switch (gp_status & GP_STATUS_SPEED_MASK) {
case GP_STATUS_10M: case GP_STATUS_10M:
...@@ -1910,14 +1909,6 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy, ...@@ -1910,14 +1909,6 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
LINK_STATUS_PARALLEL_DETECTION_USED; LINK_STATUS_PARALLEL_DETECTION_USED;
} }
if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
vars->link_status |=
LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
vars->link_status |=
LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
} else { /* link_down */ } else { /* link_down */
DP(NETIF_MSG_LINK, "phy link down\n"); DP(NETIF_MSG_LINK, "phy link down\n");
...@@ -3025,7 +3016,7 @@ static void bnx2x_ext_phy_set_pause(struct link_params *params, ...@@ -3025,7 +3016,7 @@ static void bnx2x_ext_phy_set_pause(struct link_params *params,
val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH; val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
/* Please refer to Table 28B-3 of 802.3ab-1999 spec. */ /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
if ((vars->ieee_fc & if ((vars->ieee_fc &
MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) == MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) { MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
...@@ -3821,6 +3812,24 @@ static u8 bnx2x_8481_config_init(struct bnx2x_phy *phy, ...@@ -3821,6 +3812,24 @@ static u8 bnx2x_8481_config_init(struct bnx2x_phy *phy,
bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15); bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
return bnx2x_848xx_cmn_config_init(phy, params, vars); return bnx2x_848xx_cmn_config_init(phy, params, vars);
} }
static void bnx2x_ext_phy_10G_an_resolve(struct bnx2x *bp,
struct bnx2x_phy *phy,
struct link_vars *vars)
{
u16 val;
bnx2x_cl45_read(bp, phy,
MDIO_AN_DEVAD,
MDIO_AN_REG_STATUS, &val);
bnx2x_cl45_read(bp, phy,
MDIO_AN_DEVAD,
MDIO_AN_REG_STATUS, &val);
if (val & (1<<5))
vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
if ((val & (1<<0)) == 0)
vars->link_status |= LINK_STATUS_PARALLEL_DETECTION_USED;
}
static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy, static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
struct link_params *params) struct link_params *params)
{ {
...@@ -4114,6 +4123,40 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy, ...@@ -4114,6 +4123,40 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
return link_up; return link_up;
} }
static void bnx2x_8073_resolve_fc(struct bnx2x_phy *phy,
struct link_params *params,
struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
if (phy->req_line_speed == SPEED_10 ||
phy->req_line_speed == SPEED_100) {
vars->flow_ctrl = phy->req_flow_ctrl;
return;
}
if (bnx2x_ext_phy_resolve_fc(phy, params, vars) &&
(vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE)) {
u16 pause_result;
u16 ld_pause; /* local */
u16 lp_pause; /* link partner */
bnx2x_cl45_read(bp, phy,
MDIO_AN_DEVAD,
MDIO_AN_REG_CL37_FC_LD, &ld_pause);
bnx2x_cl45_read(bp, phy,
MDIO_AN_DEVAD,
MDIO_AN_REG_CL37_FC_LP, &lp_pause);
pause_result = (ld_pause &
MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
pause_result |= (lp_pause &
MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
bnx2x_pause_resolve(vars, pause_result);
DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x\n",
pause_result);
}
}
static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy, static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
struct link_params *params, struct link_params *params,
struct link_vars *vars) struct link_vars *vars)
...@@ -4218,6 +4261,10 @@ static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy, ...@@ -4218,6 +4261,10 @@ static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
params->port); params->port);
} }
if (link_up) {
bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
bnx2x_8073_resolve_fc(phy, params, vars);
}
return link_up; return link_up;
} }
...@@ -4251,6 +4298,8 @@ static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy, ...@@ -4251,6 +4298,8 @@ static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy,
vars->line_speed = SPEED_10000; vars->line_speed = SPEED_10000;
DP(NETIF_MSG_LINK, "SFX7101 AN status 0x%x->Master=%x\n", DP(NETIF_MSG_LINK, "SFX7101 AN status 0x%x->Master=%x\n",
val2, (val2 & (1<<14))); val2, (val2 & (1<<14)));
bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
bnx2x_ext_phy_resolve_fc(phy, params, vars);
} }
return link_up; return link_up;
} }
...@@ -4276,6 +4325,7 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy, ...@@ -4276,6 +4325,7 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
if (val2 & (1<<11)) { if (val2 & (1<<11)) {
vars->line_speed = SPEED_10000; vars->line_speed = SPEED_10000;
link_up = 1; link_up = 1;
bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
} else { /* Check Legacy speed link */ } else { /* Check Legacy speed link */
u16 legacy_status, legacy_speed; u16 legacy_status, legacy_speed;
...@@ -4330,6 +4380,12 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy, ...@@ -4330,6 +4380,12 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
LINK_STATUS_PARALLEL_DETECTION_USED; LINK_STATUS_PARALLEL_DETECTION_USED;
} }
} }
if (link_up) {
DP(NETIF_MSG_LINK, "BCM84823: link speed is %d\n",
vars->line_speed);
bnx2x_ext_phy_resolve_fc(phy, params, vars);
}
return link_up; return link_up;
} }
static void bnx2x_link_int_enable(struct link_params *params) static void bnx2x_link_int_enable(struct link_params *params)
...@@ -5298,6 +5354,13 @@ static u8 bnx2x_update_link_up(struct link_params *params, ...@@ -5298,6 +5354,13 @@ static u8 bnx2x_update_link_up(struct link_params *params,
u8 rc = 0; u8 rc = 0;
vars->link_status |= LINK_STATUS_LINK_UP; vars->link_status |= LINK_STATUS_LINK_UP;
if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
vars->link_status |=
LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
vars->link_status |=
LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
if (link_10g) { if (link_10g) {
bnx2x_bmac_enable(params, vars, 0); bnx2x_bmac_enable(params, vars, 0);
bnx2x_set_led(params, LED_MODE_OPER, SPEED_10000); bnx2x_set_led(params, LED_MODE_OPER, SPEED_10000);
......
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