diff options
-rw-r--r-- | drivers/net/bnx2x/bnx2x_link.c | 211 |
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 | ®_val); | 1261 | ®_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 | ||
1556 | static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy, | 1559 | 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 | 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 | |||
1759 | static 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 | |||
1779 | static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy, | 1773 | static 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(¶ms->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 | |||
3817 | static 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 | } | ||
3824 | static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy, | 3833 | static 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 | ||
4126 | static 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 | |||
4117 | static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy, | 4160 | static 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 | } |
4335 | static void bnx2x_link_int_enable(struct link_params *params) | 4391 | 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 | 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); |