diff options
author | Yaniv Rosner <yanivr@broadcom.com> | 2009-11-05 12:18:07 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-05 23:00:29 -0500 |
commit | 7846e471b5b5cac5e09c8e6ebeb67e18279db8e3 (patch) | |
tree | cf80dc2865c0d00997643ad35771820d8759d9b3 /drivers/net/bnx2x_link.c | |
parent | 18afb0a6fa69efb76b7a67a151c0530d63789141 (diff) |
bnx2x: Fix CL73 autoneg issues
- Advertise 1G KX4 in CL73 when 1G speed capability is enabled
- Add flow-control negotiation over CL73
- External loopback test on Serdes should be done in FORCE mode, since in
CL73 it is unable to link up with the same core using AUTONEG
- Fix bnx2x_set_led function to support CL73 link leds
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.c | 132 |
1 files changed, 84 insertions, 48 deletions
diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index b5964cb7e761..eabdd1155a5a 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c | |||
@@ -1228,7 +1228,7 @@ static void bnx2x_set_autoneg(struct link_params *params, | |||
1228 | params->phy_addr, | 1228 | params->phy_addr, |
1229 | MDIO_REG_BANK_CL73_USERB0, | 1229 | MDIO_REG_BANK_CL73_USERB0, |
1230 | MDIO_CL73_USERB0_CL73_UCTRL, | 1230 | MDIO_CL73_USERB0_CL73_UCTRL, |
1231 | MDIO_CL73_USERB0_CL73_UCTRL_USTAT1_MUXSEL); | 1231 | 0xe); |
1232 | 1232 | ||
1233 | /* Enable BAM Station Manager*/ | 1233 | /* Enable BAM Station Manager*/ |
1234 | CL45_WR_OVER_CL22(bp, params->port, | 1234 | CL45_WR_OVER_CL22(bp, params->port, |
@@ -1239,29 +1239,25 @@ static void bnx2x_set_autoneg(struct link_params *params, | |||
1239 | MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN | | 1239 | MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN | |
1240 | MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN); | 1240 | MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN); |
1241 | 1241 | ||
1242 | /* Merge CL73 and CL37 aneg resolution */ | 1242 | /* Advertise CL73 link speeds */ |
1243 | CL45_RD_OVER_CL22(bp, params->port, | ||
1244 | params->phy_addr, | ||
1245 | MDIO_REG_BANK_CL73_USERB0, | ||
1246 | MDIO_CL73_USERB0_CL73_BAM_CTRL3, | ||
1247 | ®_val); | ||
1248 | |||
1249 | if (params->speed_cap_mask & | ||
1250 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) { | ||
1251 | /* Set the CL73 AN speed */ | ||
1252 | CL45_RD_OVER_CL22(bp, params->port, | 1243 | CL45_RD_OVER_CL22(bp, params->port, |
1253 | params->phy_addr, | 1244 | params->phy_addr, |
1254 | MDIO_REG_BANK_CL73_IEEEB1, | 1245 | MDIO_REG_BANK_CL73_IEEEB1, |
1255 | MDIO_CL73_IEEEB1_AN_ADV2, | 1246 | MDIO_CL73_IEEEB1_AN_ADV2, |
1256 | ®_val); | 1247 | ®_val); |
1248 | if (params->speed_cap_mask & | ||
1249 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) | ||
1250 | reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4; | ||
1251 | if (params->speed_cap_mask & | ||
1252 | PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) | ||
1253 | reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX; | ||
1257 | 1254 | ||
1258 | CL45_WR_OVER_CL22(bp, params->port, | 1255 | CL45_WR_OVER_CL22(bp, params->port, |
1259 | params->phy_addr, | 1256 | params->phy_addr, |
1260 | MDIO_REG_BANK_CL73_IEEEB1, | 1257 | MDIO_REG_BANK_CL73_IEEEB1, |
1261 | MDIO_CL73_IEEEB1_AN_ADV2, | 1258 | MDIO_CL73_IEEEB1_AN_ADV2, |
1262 | reg_val | MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4); | 1259 | reg_val); |
1263 | 1260 | ||
1264 | } | ||
1265 | /* CL73 Autoneg Enabled */ | 1261 | /* CL73 Autoneg Enabled */ |
1266 | reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN; | 1262 | reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN; |
1267 | 1263 | ||
@@ -1389,12 +1385,23 @@ static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params, | |||
1389 | u16 ieee_fc) | 1385 | u16 ieee_fc) |
1390 | { | 1386 | { |
1391 | struct bnx2x *bp = params->bp; | 1387 | struct bnx2x *bp = params->bp; |
1388 | u16 val; | ||
1392 | /* for AN, we are always publishing full duplex */ | 1389 | /* for AN, we are always publishing full duplex */ |
1393 | 1390 | ||
1394 | CL45_WR_OVER_CL22(bp, params->port, | 1391 | CL45_WR_OVER_CL22(bp, params->port, |
1395 | params->phy_addr, | 1392 | params->phy_addr, |
1396 | MDIO_REG_BANK_COMBO_IEEE0, | 1393 | MDIO_REG_BANK_COMBO_IEEE0, |
1397 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV, ieee_fc); | 1394 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV, ieee_fc); |
1395 | CL45_RD_OVER_CL22(bp, params->port, | ||
1396 | params->phy_addr, | ||
1397 | MDIO_REG_BANK_CL73_IEEEB1, | ||
1398 | MDIO_CL73_IEEEB1_AN_ADV1, &val); | ||
1399 | val &= ~MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_BOTH; | ||
1400 | val |= ((ieee_fc<<3) & MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK); | ||
1401 | CL45_WR_OVER_CL22(bp, params->port, | ||
1402 | params->phy_addr, | ||
1403 | MDIO_REG_BANK_CL73_IEEEB1, | ||
1404 | MDIO_CL73_IEEEB1_AN_ADV1, val); | ||
1398 | } | 1405 | } |
1399 | 1406 | ||
1400 | static void bnx2x_restart_autoneg(struct link_params *params, u8 enable_cl73) | 1407 | static void bnx2x_restart_autoneg(struct link_params *params, u8 enable_cl73) |
@@ -1630,21 +1637,49 @@ static void bnx2x_flow_ctrl_resolve(struct link_params *params, | |||
1630 | (!(vars->phy_flags & PHY_SGMII_FLAG)) && | 1637 | (!(vars->phy_flags & PHY_SGMII_FLAG)) && |
1631 | (XGXS_EXT_PHY_TYPE(params->ext_phy_config) == | 1638 | (XGXS_EXT_PHY_TYPE(params->ext_phy_config) == |
1632 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)) { | 1639 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)) { |
1633 | CL45_RD_OVER_CL22(bp, params->port, | 1640 | if ((gp_status & |
1634 | params->phy_addr, | 1641 | (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE | |
1635 | MDIO_REG_BANK_COMBO_IEEE0, | 1642 | MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) == |
1636 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV, | 1643 | (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE | |
1637 | &ld_pause); | 1644 | MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) { |
1638 | CL45_RD_OVER_CL22(bp, params->port, | 1645 | |
1639 | params->phy_addr, | 1646 | CL45_RD_OVER_CL22(bp, params->port, |
1640 | MDIO_REG_BANK_COMBO_IEEE0, | 1647 | params->phy_addr, |
1641 | MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1, | 1648 | MDIO_REG_BANK_CL73_IEEEB1, |
1642 | &lp_pause); | 1649 | MDIO_CL73_IEEEB1_AN_ADV1, |
1643 | pause_result = (ld_pause & | 1650 | &ld_pause); |
1651 | CL45_RD_OVER_CL22(bp, params->port, | ||
1652 | params->phy_addr, | ||
1653 | MDIO_REG_BANK_CL73_IEEEB1, | ||
1654 | MDIO_CL73_IEEEB1_AN_LP_ADV1, | ||
1655 | &lp_pause); | ||
1656 | pause_result = (ld_pause & | ||
1657 | MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK) | ||
1658 | >> 8; | ||
1659 | pause_result |= (lp_pause & | ||
1660 | MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK) | ||
1661 | >> 10; | ||
1662 | DP(NETIF_MSG_LINK, "pause_result CL73 0x%x\n", | ||
1663 | pause_result); | ||
1664 | } else { | ||
1665 | |||
1666 | CL45_RD_OVER_CL22(bp, params->port, | ||
1667 | params->phy_addr, | ||
1668 | MDIO_REG_BANK_COMBO_IEEE0, | ||
1669 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV, | ||
1670 | &ld_pause); | ||
1671 | CL45_RD_OVER_CL22(bp, params->port, | ||
1672 | params->phy_addr, | ||
1673 | MDIO_REG_BANK_COMBO_IEEE0, | ||
1674 | MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1, | ||
1675 | &lp_pause); | ||
1676 | pause_result = (ld_pause & | ||
1644 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5; | 1677 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5; |
1645 | pause_result |= (lp_pause & | 1678 | pause_result |= (lp_pause & |
1646 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7; | 1679 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7; |
1647 | DP(NETIF_MSG_LINK, "pause_result 0x%x\n", pause_result); | 1680 | DP(NETIF_MSG_LINK, "pause_result CL37 0x%x\n", |
1681 | pause_result); | ||
1682 | } | ||
1648 | bnx2x_pause_resolve(vars, pause_result); | 1683 | bnx2x_pause_resolve(vars, pause_result); |
1649 | } else if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) && | 1684 | } else if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) && |
1650 | (bnx2x_ext_phy_resolve_fc(params, vars))) { | 1685 | (bnx2x_ext_phy_resolve_fc(params, vars))) { |
@@ -1990,8 +2025,7 @@ static u8 bnx2x_emac_program(struct link_params *params, | |||
1990 | GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE, | 2025 | GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE, |
1991 | mode); | 2026 | mode); |
1992 | 2027 | ||
1993 | bnx2x_set_led(bp, params->port, LED_MODE_OPER, | 2028 | bnx2x_set_led(params, LED_MODE_OPER, line_speed); |
1994 | line_speed, params->hw_led_mode, params->chip_id); | ||
1995 | return 0; | 2029 | return 0; |
1996 | } | 2030 | } |
1997 | 2031 | ||
@@ -3547,7 +3581,10 @@ static void bnx2x_init_internal_phy(struct link_params *params, | |||
3547 | bnx2x_set_preemphasis(params); | 3581 | bnx2x_set_preemphasis(params); |
3548 | 3582 | ||
3549 | /* forced speed requested? */ | 3583 | /* forced speed requested? */ |
3550 | if (vars->line_speed != SPEED_AUTO_NEG) { | 3584 | if (vars->line_speed != SPEED_AUTO_NEG || |
3585 | ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) == | ||
3586 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) && | ||
3587 | params->loopback_mode == LOOPBACK_EXT)) { | ||
3551 | DP(NETIF_MSG_LINK, "not SGMII, no AN\n"); | 3588 | DP(NETIF_MSG_LINK, "not SGMII, no AN\n"); |
3552 | 3589 | ||
3553 | /* disable autoneg */ | 3590 | /* disable autoneg */ |
@@ -5731,13 +5768,15 @@ u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port, | |||
5731 | } | 5768 | } |
5732 | 5769 | ||
5733 | 5770 | ||
5734 | u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed, | 5771 | u8 bnx2x_set_led(struct link_params *params, u8 mode, u32 speed) |
5735 | u16 hw_led_mode, u32 chip_id) | ||
5736 | { | 5772 | { |
5773 | u8 port = params->port; | ||
5774 | u16 hw_led_mode = params->hw_led_mode; | ||
5737 | u8 rc = 0; | 5775 | u8 rc = 0; |
5738 | u32 tmp; | 5776 | u32 tmp; |
5739 | u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; | 5777 | u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; |
5740 | 5778 | u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config); | |
5779 | struct bnx2x *bp = params->bp; | ||
5741 | DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode); | 5780 | DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode); |
5742 | DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n", | 5781 | DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n", |
5743 | speed, hw_led_mode); | 5782 | speed, hw_led_mode); |
@@ -5752,7 +5791,14 @@ u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed, | |||
5752 | break; | 5791 | break; |
5753 | 5792 | ||
5754 | case LED_MODE_OPER: | 5793 | case LED_MODE_OPER: |
5755 | REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, hw_led_mode); | 5794 | if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) { |
5795 | REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0); | ||
5796 | REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1); | ||
5797 | } else { | ||
5798 | REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, | ||
5799 | hw_led_mode); | ||
5800 | } | ||
5801 | |||
5756 | REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 + | 5802 | REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 + |
5757 | port*4, 0); | 5803 | port*4, 0); |
5758 | /* Set blinking rate to ~15.9Hz */ | 5804 | /* Set blinking rate to ~15.9Hz */ |
@@ -5764,7 +5810,7 @@ u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed, | |||
5764 | EMAC_WR(bp, EMAC_REG_EMAC_LED, | 5810 | EMAC_WR(bp, EMAC_REG_EMAC_LED, |
5765 | (tmp & (~EMAC_LED_OVERRIDE))); | 5811 | (tmp & (~EMAC_LED_OVERRIDE))); |
5766 | 5812 | ||
5767 | if (!CHIP_IS_E1H(bp) && | 5813 | if (CHIP_IS_E1(bp) && |
5768 | ((speed == SPEED_2500) || | 5814 | ((speed == SPEED_2500) || |
5769 | (speed == SPEED_1000) || | 5815 | (speed == SPEED_1000) || |
5770 | (speed == SPEED_100) || | 5816 | (speed == SPEED_100) || |
@@ -6033,10 +6079,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars) | |||
6033 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + | 6079 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + |
6034 | params->port*4, 0); | 6080 | params->port*4, 0); |
6035 | 6081 | ||
6036 | bnx2x_set_led(bp, params->port, LED_MODE_OPER, | 6082 | bnx2x_set_led(params, LED_MODE_OPER, vars->line_speed); |
6037 | vars->line_speed, params->hw_led_mode, | ||
6038 | params->chip_id); | ||
6039 | |||
6040 | } else | 6083 | } else |
6041 | /* No loopback */ | 6084 | /* No loopback */ |
6042 | { | 6085 | { |
@@ -6094,8 +6137,6 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars, | |||
6094 | { | 6137 | { |
6095 | struct bnx2x *bp = params->bp; | 6138 | struct bnx2x *bp = params->bp; |
6096 | u32 ext_phy_config = params->ext_phy_config; | 6139 | u32 ext_phy_config = params->ext_phy_config; |
6097 | u16 hw_led_mode = params->hw_led_mode; | ||
6098 | u32 chip_id = params->chip_id; | ||
6099 | u8 port = params->port; | 6140 | u8 port = params->port; |
6100 | u32 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config); | 6141 | u32 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config); |
6101 | u32 val = REG_RD(bp, params->shmem_base + | 6142 | u32 val = REG_RD(bp, params->shmem_base + |
@@ -6130,7 +6171,7 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars, | |||
6130 | * Hold it as vars low | 6171 | * Hold it as vars low |
6131 | */ | 6172 | */ |
6132 | /* clear link led */ | 6173 | /* clear link led */ |
6133 | bnx2x_set_led(bp, port, LED_MODE_OFF, 0, hw_led_mode, chip_id); | 6174 | bnx2x_set_led(params, LED_MODE_OFF, 0); |
6134 | if (reset_ext_phy) { | 6175 | if (reset_ext_phy) { |
6135 | switch (ext_phy_type) { | 6176 | switch (ext_phy_type) { |
6136 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: | 6177 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: |
@@ -6201,9 +6242,7 @@ static u8 bnx2x_update_link_down(struct link_params *params, | |||
6201 | u8 port = params->port; | 6242 | u8 port = params->port; |
6202 | 6243 | ||
6203 | DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port); | 6244 | DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port); |
6204 | bnx2x_set_led(bp, port, LED_MODE_OFF, | 6245 | bnx2x_set_led(params, LED_MODE_OFF, 0); |
6205 | 0, params->hw_led_mode, | ||
6206 | params->chip_id); | ||
6207 | 6246 | ||
6208 | /* indicate no mac active */ | 6247 | /* indicate no mac active */ |
6209 | vars->mac_type = MAC_TYPE_NONE; | 6248 | vars->mac_type = MAC_TYPE_NONE; |
@@ -6240,10 +6279,7 @@ static u8 bnx2x_update_link_up(struct link_params *params, | |||
6240 | vars->link_status |= LINK_STATUS_LINK_UP; | 6279 | vars->link_status |= LINK_STATUS_LINK_UP; |
6241 | if (link_10g) { | 6280 | if (link_10g) { |
6242 | bnx2x_bmac_enable(params, vars, 0); | 6281 | bnx2x_bmac_enable(params, vars, 0); |
6243 | bnx2x_set_led(bp, port, LED_MODE_OPER, | 6282 | bnx2x_set_led(params, LED_MODE_OPER, SPEED_10000); |
6244 | SPEED_10000, params->hw_led_mode, | ||
6245 | params->chip_id); | ||
6246 | |||
6247 | } else { | 6283 | } else { |
6248 | bnx2x_emac_enable(params, vars, 0); | 6284 | bnx2x_emac_enable(params, vars, 0); |
6249 | rc = bnx2x_emac_program(params, vars->line_speed, | 6285 | rc = bnx2x_emac_program(params, vars->line_speed, |