aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2x_link.c
diff options
context:
space:
mode:
authorYaniv Rosner <yanivr@broadcom.com>2009-11-05 12:18:07 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-05 23:00:29 -0500
commit7846e471b5b5cac5e09c8e6ebeb67e18279db8e3 (patch)
treecf80dc2865c0d00997643ad35771820d8759d9b3 /drivers/net/bnx2x_link.c
parent18afb0a6fa69efb76b7a67a151c0530d63789141 (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.c132
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 &reg_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 &reg_val); 1247 &reg_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
1400static void bnx2x_restart_autoneg(struct link_params *params, u8 enable_cl73) 1407static 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
5734u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed, 5771u8 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,