aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2x/bnx2x_link.c
diff options
context:
space:
mode:
authorYaniv Rosner <yaniv.rosner@broadcom.com>2010-09-07 07:41:01 -0400
committerDavid S. Miller <davem@davemloft.net>2010-09-07 16:13:37 -0400
commit7aa0711f32bf911add9e2ced165f8006864f973e (patch)
treef0aab6beee2083ae8828bf15db5f38475de7e781 /drivers/net/bnx2x/bnx2x_link.c
parent62b29a5dd0930e0c956b6740f32d5b3bbaf20136 (diff)
bnx2x: Adjust flow-control with the new scheme
Flow control implementation is split to be done in each PHY 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/bnx2x/bnx2x_link.c')
-rw-r--r--drivers/net/bnx2x/bnx2x_link.c211
1 files changed, 137 insertions, 74 deletions
diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c
index c2f1e3c24c0b..bb42104b2377 100644
--- a/drivers/net/bnx2x/bnx2x_link.c
+++ b/drivers/net/bnx2x/bnx2x_link.c
@@ -171,13 +171,13 @@
171 171
172#define CL45_WR_OVER_CL22(_bp, _phy, _bank, _addr, _val) \ 172#define CL45_WR_OVER_CL22(_bp, _phy, _bank, _addr, _val) \
173 bnx2x_cl45_write(_bp, _phy, \ 173 bnx2x_cl45_write(_bp, _phy, \
174 DEFAULT_PHY_DEV_ADDR, \ 174 (_phy)->def_md_devad, \
175 (_bank + (_addr & 0xf)), \ 175 (_bank + (_addr & 0xf)), \
176 _val) 176 _val)
177 177
178#define CL45_RD_OVER_CL22(_bp, _phy, _bank, _addr, _val) \ 178#define CL45_RD_OVER_CL22(_bp, _phy, _bank, _addr, _val) \
179 bnx2x_cl45_read(_bp, _phy, \ 179 bnx2x_cl45_read(_bp, _phy, \
180 DEFAULT_PHY_DEV_ADDR, \ 180 (_phy)->def_md_devad, \
181 (_bank + (_addr & 0xf)), \ 181 (_bank + (_addr & 0xf)), \
182 _val) 182 _val)
183 183
@@ -634,24 +634,22 @@ void bnx2x_link_status_update(struct link_params *params,
634 break; 634 break;
635 } 635 }
636 636
637 vars->flow_ctrl = 0;
637 if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED) 638 if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
638 vars->flow_ctrl |= BNX2X_FLOW_CTRL_TX; 639 vars->flow_ctrl |= BNX2X_FLOW_CTRL_TX;
639 else
640 vars->flow_ctrl &= ~BNX2X_FLOW_CTRL_TX;
641 640
642 if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED) 641 if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
643 vars->flow_ctrl |= BNX2X_FLOW_CTRL_RX; 642 vars->flow_ctrl |= BNX2X_FLOW_CTRL_RX;
644 else
645 vars->flow_ctrl &= ~BNX2X_FLOW_CTRL_RX;
646 643
647 if (vars->phy_flags & PHY_XGXS_FLAG) { 644 if (!vars->flow_ctrl)
648 if (vars->line_speed && 645 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
649 ((vars->line_speed == SPEED_10) || 646
650 (vars->line_speed == SPEED_100))) { 647 if (vars->line_speed &&
651 vars->phy_flags |= PHY_SGMII_FLAG; 648 ((vars->line_speed == SPEED_10) ||
652 } else { 649 (vars->line_speed == SPEED_100))) {
653 vars->phy_flags &= ~PHY_SGMII_FLAG; 650 vars->phy_flags |= PHY_SGMII_FLAG;
654 } 651 } else {
652 vars->phy_flags &= ~PHY_SGMII_FLAG;
655 } 653 }
656 654
657 /* anything 10 and over uses the bmac */ 655 /* anything 10 and over uses the bmac */
@@ -1137,12 +1135,12 @@ static void bnx2x_set_parallel_detection(struct bnx2x_phy *phy,
1137 MDIO_REG_BANK_SERDES_DIGITAL, 1135 MDIO_REG_BANK_SERDES_DIGITAL,
1138 MDIO_SERDES_DIGITAL_A_1000X_CONTROL2, 1136 MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
1139 &control2); 1137 &control2);
1140 if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) 1138 if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
1141 control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN; 1139 control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
1142 else 1140 else
1143 control2 &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN; 1141 control2 &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
1144 DP(NETIF_MSG_LINK, "params->speed_cap_mask = 0x%x, control2 = 0x%x\n", 1142 DP(NETIF_MSG_LINK, "phy->speed_cap_mask = 0x%x, control2 = 0x%x\n",
1145 params->speed_cap_mask, control2); 1143 phy->speed_cap_mask, control2);
1146 CL45_WR_OVER_CL22(bp, phy, 1144 CL45_WR_OVER_CL22(bp, phy,
1147 MDIO_REG_BANK_SERDES_DIGITAL, 1145 MDIO_REG_BANK_SERDES_DIGITAL,
1148 MDIO_SERDES_DIGITAL_A_1000X_CONTROL2, 1146 MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
@@ -1261,10 +1259,10 @@ static void bnx2x_set_autoneg(struct bnx2x_phy *phy,
1261 MDIO_REG_BANK_CL73_IEEEB1, 1259 MDIO_REG_BANK_CL73_IEEEB1,
1262 MDIO_CL73_IEEEB1_AN_ADV2, 1260 MDIO_CL73_IEEEB1_AN_ADV2,
1263 &reg_val); 1261 &reg_val);
1264 if (params->speed_cap_mask & 1262 if (phy->speed_cap_mask &
1265 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) 1263 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
1266 reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4; 1264 reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4;
1267 if (params->speed_cap_mask & 1265 if (phy->speed_cap_mask &
1268 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) 1266 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
1269 reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX; 1267 reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;
1270 1268
@@ -1299,7 +1297,7 @@ static void bnx2x_program_serdes(struct bnx2x_phy *phy,
1299 reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX | 1297 reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX |
1300 MDIO_COMBO_IEEO_MII_CONTROL_AN_EN | 1298 MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
1301 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK); 1299 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK);
1302 if (params->req_duplex == DUPLEX_FULL) 1300 if (phy->req_duplex == DUPLEX_FULL)
1303 reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX; 1301 reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
1304 CL45_WR_OVER_CL22(bp, phy, 1302 CL45_WR_OVER_CL22(bp, phy,
1305 MDIO_REG_BANK_COMBO_IEEE0, 1303 MDIO_REG_BANK_COMBO_IEEE0,
@@ -1345,9 +1343,9 @@ static void bnx2x_set_brcm_cl37_advertisment(struct bnx2x_phy *phy,
1345 /* configure the 48 bits for BAM AN */ 1343 /* configure the 48 bits for BAM AN */
1346 1344
1347 /* set extended capabilities */ 1345 /* set extended capabilities */
1348 if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) 1346 if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
1349 val |= MDIO_OVER_1G_UP1_2_5G; 1347 val |= MDIO_OVER_1G_UP1_2_5G;
1350 if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) 1348 if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
1351 val |= MDIO_OVER_1G_UP1_10G; 1349 val |= MDIO_OVER_1G_UP1_10G;
1352 CL45_WR_OVER_CL22(bp, phy, 1350 CL45_WR_OVER_CL22(bp, phy,
1353 MDIO_REG_BANK_OVER_1G, 1351 MDIO_REG_BANK_OVER_1G,
@@ -1366,7 +1364,7 @@ static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
1366 /* resolve pause mode and advertisement 1364 /* resolve pause mode and advertisement
1367 * Please refer to Table 28B-3 of the 802.3ab-1999 spec */ 1365 * Please refer to Table 28B-3 of the 802.3ab-1999 spec */
1368 1366
1369 switch (params->req_flow_ctrl) { 1367 switch (phy->req_flow_ctrl) {
1370 case BNX2X_FLOW_CTRL_AUTO: 1368 case BNX2X_FLOW_CTRL_AUTO:
1371 if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH) { 1369 if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH) {
1372 *ieee_fc |= 1370 *ieee_fc |=
@@ -1511,7 +1509,7 @@ static void bnx2x_initialize_sgmii_process(struct bnx2x_phy *phy,
1511 } 1509 }
1512 1510
1513 /* setting the full duplex */ 1511 /* setting the full duplex */
1514 if (params->req_duplex == DUPLEX_FULL) 1512 if (phy->req_duplex == DUPLEX_FULL)
1515 mii_control |= 1513 mii_control |=
1516 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX; 1514 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
1517 CL45_WR_OVER_CL22(bp, phy, 1515 CL45_WR_OVER_CL22(bp, phy,
@@ -1551,6 +1549,11 @@ static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
1551 default: 1549 default:
1552 break; 1550 break;
1553 } 1551 }
1552 if (pause_result & (1<<0))
1553 vars->link_status |= LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE;
1554 if (pause_result & (1<<1))
1555 vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
1556
1554} 1557}
1555 1558
1556static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy, 1559static 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 struct bnx2x *bp = params->bp; 1563 struct bnx2x *bp = params->bp;
1561 u16 ld_pause; /* local */ 1564 u16 ld_pause; /* local */
1562 u16 lp_pause; /* link partner */ 1565 u16 lp_pause; /* link partner */
1563 u16 an_complete; /* AN complete */
1564 u16 pause_result; 1566 u16 pause_result;
1565 u8 ret = 0; 1567 u8 ret = 0;
1566 /* read twice */ 1568 /* read twice */
1567 1569
1568 bnx2x_cl45_read(bp, phy, 1570 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
1569 MDIO_AN_DEVAD,
1570 MDIO_AN_REG_STATUS, &an_complete);
1571 bnx2x_cl45_read(bp, phy,
1572 MDIO_AN_DEVAD,
1573 MDIO_AN_REG_STATUS, &an_complete);
1574 1571
1575 if (an_complete & MDIO_AN_REG_STATUS_AN_COMPLETE) { 1572 if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
1573 vars->flow_ctrl = phy->req_flow_ctrl;
1574 else if (phy->req_line_speed != SPEED_AUTO_NEG)
1575 vars->flow_ctrl = params->req_fc_auto_adv;
1576 else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
1576 ret = 1; 1577 ret = 1;
1577 bnx2x_cl45_read(bp, phy, 1578 bnx2x_cl45_read(bp, phy,
1578 MDIO_AN_DEVAD, 1579 MDIO_AN_DEVAD,
@@ -1587,24 +1588,6 @@ static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
1587 DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n", 1588 DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n",
1588 pause_result); 1589 pause_result);
1589 bnx2x_pause_resolve(vars, pause_result); 1590 bnx2x_pause_resolve(vars, pause_result);
1590 if (vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE &&
1591 phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
1592 bnx2x_cl45_read(bp, phy,
1593 MDIO_AN_DEVAD,
1594 MDIO_AN_REG_CL37_FC_LD, &ld_pause);
1595
1596 bnx2x_cl45_read(bp, phy,
1597 MDIO_AN_DEVAD,
1598 MDIO_AN_REG_CL37_FC_LP, &lp_pause);
1599 pause_result = (ld_pause &
1600 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
1601 pause_result |= (lp_pause &
1602 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
1603
1604 bnx2x_pause_resolve(vars, pause_result);
1605 DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x\n",
1606 pause_result);
1607 }
1608 } 1591 }
1609 return ret; 1592 return ret;
1610} 1593}
@@ -1614,6 +1597,8 @@ static u8 bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy,
1614{ 1597{
1615 struct bnx2x *bp = params->bp; 1598 struct bnx2x *bp = params->bp;
1616 u16 pd_10g, status2_1000x; 1599 u16 pd_10g, status2_1000x;
1600 if (phy->req_line_speed != SPEED_AUTO_NEG)
1601 return 0;
1617 CL45_RD_OVER_CL22(bp, phy, 1602 CL45_RD_OVER_CL22(bp, phy,
1618 MDIO_REG_BANK_SERDES_DIGITAL, 1603 MDIO_REG_BANK_SERDES_DIGITAL,
1619 MDIO_SERDES_DIGITAL_A_1000X_STATUS2, 1604 MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
@@ -1654,10 +1639,12 @@ static void bnx2x_flow_ctrl_resolve(struct bnx2x_phy *phy,
1654 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; 1639 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
1655 1640
1656 /* resolve from gp_status in case of AN complete and not sgmii */ 1641 /* resolve from gp_status in case of AN complete and not sgmii */
1657 if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) && 1642 if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
1658 (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) && 1643 vars->flow_ctrl = phy->req_flow_ctrl;
1659 (!(vars->phy_flags & PHY_SGMII_FLAG)) && 1644 else if (phy->req_line_speed != SPEED_AUTO_NEG)
1660 (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)) { 1645 vars->flow_ctrl = params->req_fc_auto_adv;
1646 else if ((gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
1647 (!(vars->phy_flags & PHY_SGMII_FLAG))) {
1661 if (bnx2x_direct_parallel_detect_used(phy, params)) { 1648 if (bnx2x_direct_parallel_detect_used(phy, params)) {
1662 vars->flow_ctrl = params->req_fc_auto_adv; 1649 vars->flow_ctrl = params->req_fc_auto_adv;
1663 return; 1650 return;
@@ -1701,14 +1688,6 @@ static void bnx2x_flow_ctrl_resolve(struct bnx2x_phy *phy,
1701 pause_result); 1688 pause_result);
1702 } 1689 }
1703 bnx2x_pause_resolve(vars, pause_result); 1690 bnx2x_pause_resolve(vars, pause_result);
1704 } else if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
1705 (bnx2x_ext_phy_resolve_fc(phy, params, vars))) {
1706 return;
1707 } else {
1708 if (params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO)
1709 vars->flow_ctrl = params->req_fc_auto_adv;
1710 else
1711 vars->flow_ctrl = params->req_flow_ctrl;
1712 } 1691 }
1713 DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl); 1692 DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl);
1714} 1693}
@@ -1776,6 +1755,21 @@ static void bnx2x_check_fallback_to_cl37(struct bnx2x_phy *phy,
1776 bnx2x_restart_autoneg(phy, params, 0); 1755 bnx2x_restart_autoneg(phy, params, 0);
1777 DP(NETIF_MSG_LINK, "Disabling CL73, and restarting CL37 autoneg\n"); 1756 DP(NETIF_MSG_LINK, "Disabling CL73, and restarting CL37 autoneg\n");
1778} 1757}
1758
1759static void bnx2x_xgxs_an_resolve(struct bnx2x_phy *phy,
1760 struct link_params *params,
1761 struct link_vars *vars,
1762 u32 gp_status)
1763{
1764 if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE)
1765 vars->link_status |=
1766 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
1767
1768 if (bnx2x_direct_parallel_detect_used(phy, params))
1769 vars->link_status |=
1770 LINK_STATUS_PARALLEL_DETECTION_USED;
1771}
1772
1779static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy, 1773static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
1780 struct link_params *params, 1774 struct link_params *params,
1781 struct link_vars *vars) 1775 struct link_vars *vars)
@@ -1789,7 +1783,8 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
1789 MDIO_REG_BANK_GP_STATUS, 1783 MDIO_REG_BANK_GP_STATUS,
1790 MDIO_GP_STATUS_TOP_AN_STATUS1, 1784 MDIO_GP_STATUS_TOP_AN_STATUS1,
1791 &gp_status); 1785 &gp_status);
1792 1786 if (phy->req_line_speed == SPEED_AUTO_NEG)
1787 vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
1793 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) { 1788 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
1794 DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n", 1789 DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n",
1795 gp_status); 1790 gp_status);
@@ -1802,8 +1797,12 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
1802 else 1797 else
1803 vars->duplex = DUPLEX_HALF; 1798 vars->duplex = DUPLEX_HALF;
1804 1799
1805 bnx2x_flow_ctrl_resolve(&params->phy[INT_PHY], 1800 if (SINGLE_MEDIA_DIRECT(params)) {
1806 params, vars, gp_status); 1801 bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status);
1802 if (phy->req_line_speed == SPEED_AUTO_NEG)
1803 bnx2x_xgxs_an_resolve(phy, params, vars,
1804 gp_status);
1805 }
1807 1806
1808 switch (gp_status & GP_STATUS_SPEED_MASK) { 1807 switch (gp_status & GP_STATUS_SPEED_MASK) {
1809 case GP_STATUS_10M: 1808 case GP_STATUS_10M:
@@ -1910,14 +1909,6 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
1910 LINK_STATUS_PARALLEL_DETECTION_USED; 1909 LINK_STATUS_PARALLEL_DETECTION_USED;
1911 1910
1912 } 1911 }
1913 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
1914 vars->link_status |=
1915 LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
1916
1917 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
1918 vars->link_status |=
1919 LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
1920
1921 1912
1922 } else { /* link_down */ 1913 } else { /* link_down */
1923 DP(NETIF_MSG_LINK, "phy link down\n"); 1914 DP(NETIF_MSG_LINK, "phy link down\n");
@@ -3025,7 +3016,7 @@ static void bnx2x_ext_phy_set_pause(struct link_params *params,
3025 val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH; 3016 val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
3026 3017
3027 /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */ 3018 /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
3028 3019 bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
3029 if ((vars->ieee_fc & 3020 if ((vars->ieee_fc &
3030 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) == 3021 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
3031 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) { 3022 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
@@ -3821,6 +3812,24 @@ static u8 bnx2x_8481_config_init(struct bnx2x_phy *phy,
3821 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15); 3812 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
3822 return bnx2x_848xx_cmn_config_init(phy, params, vars); 3813 return bnx2x_848xx_cmn_config_init(phy, params, vars);
3823} 3814}
3815
3816
3817static void bnx2x_ext_phy_10G_an_resolve(struct bnx2x *bp,
3818 struct bnx2x_phy *phy,
3819 struct link_vars *vars)
3820{
3821 u16 val;
3822 bnx2x_cl45_read(bp, phy,
3823 MDIO_AN_DEVAD,
3824 MDIO_AN_REG_STATUS, &val);
3825 bnx2x_cl45_read(bp, phy,
3826 MDIO_AN_DEVAD,
3827 MDIO_AN_REG_STATUS, &val);
3828 if (val & (1<<5))
3829 vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
3830 if ((val & (1<<0)) == 0)
3831 vars->link_status |= LINK_STATUS_PARALLEL_DETECTION_USED;
3832}
3824static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy, 3833static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
3825 struct link_params *params) 3834 struct link_params *params)
3826{ 3835{
@@ -4114,6 +4123,40 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
4114 return link_up; 4123 return link_up;
4115} 4124}
4116 4125
4126static void bnx2x_8073_resolve_fc(struct bnx2x_phy *phy,
4127 struct link_params *params,
4128 struct link_vars *vars)
4129{
4130 struct bnx2x *bp = params->bp;
4131 if (phy->req_line_speed == SPEED_10 ||
4132 phy->req_line_speed == SPEED_100) {
4133 vars->flow_ctrl = phy->req_flow_ctrl;
4134 return;
4135 }
4136
4137 if (bnx2x_ext_phy_resolve_fc(phy, params, vars) &&
4138 (vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE)) {
4139 u16 pause_result;
4140 u16 ld_pause; /* local */
4141 u16 lp_pause; /* link partner */
4142 bnx2x_cl45_read(bp, phy,
4143 MDIO_AN_DEVAD,
4144 MDIO_AN_REG_CL37_FC_LD, &ld_pause);
4145
4146 bnx2x_cl45_read(bp, phy,
4147 MDIO_AN_DEVAD,
4148 MDIO_AN_REG_CL37_FC_LP, &lp_pause);
4149 pause_result = (ld_pause &
4150 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
4151 pause_result |= (lp_pause &
4152 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
4153
4154 bnx2x_pause_resolve(vars, pause_result);
4155 DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x\n",
4156 pause_result);
4157 }
4158}
4159
4117static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy, 4160static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
4118 struct link_params *params, 4161 struct link_params *params,
4119 struct link_vars *vars) 4162 struct link_vars *vars)
@@ -4218,6 +4261,10 @@ static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
4218 params->port); 4261 params->port);
4219 } 4262 }
4220 4263
4264 if (link_up) {
4265 bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
4266 bnx2x_8073_resolve_fc(phy, params, vars);
4267 }
4221 return link_up; 4268 return link_up;
4222} 4269}
4223 4270
@@ -4251,6 +4298,8 @@ static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy,
4251 vars->line_speed = SPEED_10000; 4298 vars->line_speed = SPEED_10000;
4252 DP(NETIF_MSG_LINK, "SFX7101 AN status 0x%x->Master=%x\n", 4299 DP(NETIF_MSG_LINK, "SFX7101 AN status 0x%x->Master=%x\n",
4253 val2, (val2 & (1<<14))); 4300 val2, (val2 & (1<<14)));
4301 bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
4302 bnx2x_ext_phy_resolve_fc(phy, params, vars);
4254 } 4303 }
4255 return link_up; 4304 return link_up;
4256} 4305}
@@ -4276,6 +4325,7 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
4276 if (val2 & (1<<11)) { 4325 if (val2 & (1<<11)) {
4277 vars->line_speed = SPEED_10000; 4326 vars->line_speed = SPEED_10000;
4278 link_up = 1; 4327 link_up = 1;
4328 bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
4279 } else { /* Check Legacy speed link */ 4329 } else { /* Check Legacy speed link */
4280 u16 legacy_status, legacy_speed; 4330 u16 legacy_status, legacy_speed;
4281 4331
@@ -4330,6 +4380,12 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
4330 LINK_STATUS_PARALLEL_DETECTION_USED; 4380 LINK_STATUS_PARALLEL_DETECTION_USED;
4331 } 4381 }
4332 } 4382 }
4383 if (link_up) {
4384 DP(NETIF_MSG_LINK, "BCM84823: link speed is %d\n",
4385 vars->line_speed);
4386 bnx2x_ext_phy_resolve_fc(phy, params, vars);
4387 }
4388
4333 return link_up; 4389 return link_up;
4334} 4390}
4335static void bnx2x_link_int_enable(struct link_params *params) 4391static void bnx2x_link_int_enable(struct link_params *params)
@@ -5298,6 +5354,13 @@ static u8 bnx2x_update_link_up(struct link_params *params,
5298 u8 rc = 0; 5354 u8 rc = 0;
5299 5355
5300 vars->link_status |= LINK_STATUS_LINK_UP; 5356 vars->link_status |= LINK_STATUS_LINK_UP;
5357 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
5358 vars->link_status |=
5359 LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
5360
5361 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
5362 vars->link_status |=
5363 LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
5301 if (link_10g) { 5364 if (link_10g) {
5302 bnx2x_bmac_enable(params, vars, 0); 5365 bnx2x_bmac_enable(params, vars, 0);
5303 bnx2x_set_led(params, LED_MODE_OPER, SPEED_10000); 5366 bnx2x_set_led(params, LED_MODE_OPER, SPEED_10000);