diff options
author | Yaniv Rosner <yanivr@broadcom.com> | 2008-08-13 18:56:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-08-13 19:04:30 -0400 |
commit | 8c99e7b0436473593a68e740d1032909bc5335a1 (patch) | |
tree | 621557728da3ea1bb7cf4e4e08a4c184bf037b4e /drivers/net/bnx2x_link.c | |
parent | 57963ed94c27e94a7533434da5943195ea072a35 (diff) |
bnx2x: Pause settings
Pause settings
- 1G pause was not working due to missing write to the emac block
(TX_MODE_FLOW_EN)
- The flow control should use the negotiated result (after autoneg) so
we should save both the requested autoneg and the result
- The HW credits with flow control at 1G speed were not optimized and
caused low throughput
- It is recommended to turn off flow control if the MTU is bigger than
5000B due to internal buffers size
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 | 202 |
1 files changed, 114 insertions, 88 deletions
diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index 3b63c8ce952a..36fa356c74fa 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #define ETH_MAX_JUMBO_PACKET_SIZE 9600 | 38 | #define ETH_MAX_JUMBO_PACKET_SIZE 9600 |
39 | #define MDIO_ACCESS_TIMEOUT 1000 | 39 | #define MDIO_ACCESS_TIMEOUT 1000 |
40 | #define BMAC_CONTROL_RX_ENABLE 2 | 40 | #define BMAC_CONTROL_RX_ENABLE 2 |
41 | #define MAX_MTU_SIZE 5000 | ||
42 | 41 | ||
43 | /***********************************************************/ | 42 | /***********************************************************/ |
44 | /* Shortcut definitions */ | 43 | /* Shortcut definitions */ |
@@ -298,11 +297,13 @@ static u8 bnx2x_emac_enable(struct link_params *params, | |||
298 | EMAC_RX_MODE_FLOW_EN); | 297 | EMAC_RX_MODE_FLOW_EN); |
299 | 298 | ||
300 | bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_TX_MODE, | 299 | bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_TX_MODE, |
301 | EMAC_TX_MODE_EXT_PAUSE_EN); | 300 | (EMAC_TX_MODE_EXT_PAUSE_EN | |
301 | EMAC_TX_MODE_FLOW_EN)); | ||
302 | if (vars->flow_ctrl & FLOW_CTRL_TX) | 302 | if (vars->flow_ctrl & FLOW_CTRL_TX) |
303 | bnx2x_bits_en(bp, emac_base + | 303 | bnx2x_bits_en(bp, emac_base + |
304 | EMAC_REG_EMAC_TX_MODE, | 304 | EMAC_REG_EMAC_TX_MODE, |
305 | EMAC_TX_MODE_EXT_PAUSE_EN); | 305 | (EMAC_TX_MODE_EXT_PAUSE_EN | |
306 | EMAC_TX_MODE_FLOW_EN)); | ||
306 | } | 307 | } |
307 | 308 | ||
308 | /* KEEP_VLAN_TAG, promiscuous */ | 309 | /* KEEP_VLAN_TAG, promiscuous */ |
@@ -591,9 +592,9 @@ void bnx2x_link_status_update(struct link_params *params, | |||
591 | vars->flow_ctrl &= ~FLOW_CTRL_RX; | 592 | vars->flow_ctrl &= ~FLOW_CTRL_RX; |
592 | 593 | ||
593 | if (vars->phy_flags & PHY_XGXS_FLAG) { | 594 | if (vars->phy_flags & PHY_XGXS_FLAG) { |
594 | if (params->req_line_speed && | 595 | if (vars->line_speed && |
595 | ((params->req_line_speed == SPEED_10) || | 596 | ((vars->line_speed == SPEED_10) || |
596 | (params->req_line_speed == SPEED_100))) { | 597 | (vars->line_speed == SPEED_100))) { |
597 | vars->phy_flags |= PHY_SGMII_FLAG; | 598 | vars->phy_flags |= PHY_SGMII_FLAG; |
598 | } else { | 599 | } else { |
599 | vars->phy_flags &= ~PHY_SGMII_FLAG; | 600 | vars->phy_flags &= ~PHY_SGMII_FLAG; |
@@ -670,7 +671,6 @@ static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl, | |||
670 | u8 port = params->port; | 671 | u8 port = params->port; |
671 | u32 init_crd, crd; | 672 | u32 init_crd, crd; |
672 | u32 count = 1000; | 673 | u32 count = 1000; |
673 | u32 pause = 0; | ||
674 | 674 | ||
675 | /* disable port */ | 675 | /* disable port */ |
676 | REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x1); | 676 | REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x1); |
@@ -693,33 +693,25 @@ static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl, | |||
693 | return -EINVAL; | 693 | return -EINVAL; |
694 | } | 694 | } |
695 | 695 | ||
696 | if (flow_ctrl & FLOW_CTRL_RX) | 696 | if (flow_ctrl & FLOW_CTRL_RX || |
697 | pause = 1; | 697 | line_speed == SPEED_10 || |
698 | REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, pause); | 698 | line_speed == SPEED_100 || |
699 | if (pause) { | 699 | line_speed == SPEED_1000 || |
700 | line_speed == SPEED_2500) { | ||
701 | REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 1); | ||
700 | /* update threshold */ | 702 | /* update threshold */ |
701 | REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, 0); | 703 | REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, 0); |
702 | /* update init credit */ | 704 | /* update init credit */ |
703 | init_crd = 778; /* (800-18-4) */ | 705 | init_crd = 778; /* (800-18-4) */ |
704 | 706 | ||
705 | } else { | 707 | } else { |
706 | u32 thresh = (ETH_MAX_JUMBO_PACKET_SIZE + | 708 | u32 thresh = (ETH_MAX_JUMBO_PACKET_SIZE + |
707 | ETH_OVREHEAD)/16; | 709 | ETH_OVREHEAD)/16; |
708 | 710 | REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0); | |
709 | /* update threshold */ | 711 | /* update threshold */ |
710 | REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, thresh); | 712 | REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, thresh); |
711 | /* update init credit */ | 713 | /* update init credit */ |
712 | switch (line_speed) { | 714 | switch (line_speed) { |
713 | case SPEED_10: | ||
714 | case SPEED_100: | ||
715 | case SPEED_1000: | ||
716 | init_crd = thresh + 55 - 22; | ||
717 | break; | ||
718 | |||
719 | case SPEED_2500: | ||
720 | init_crd = thresh + 138 - 22; | ||
721 | break; | ||
722 | |||
723 | case SPEED_10000: | 715 | case SPEED_10000: |
724 | init_crd = thresh + 553 - 22; | 716 | init_crd = thresh + 553 - 22; |
725 | break; | 717 | break; |
@@ -1114,7 +1106,7 @@ static void bnx2x_set_autoneg(struct link_params *params, | |||
1114 | MDIO_COMBO_IEEE0_MII_CONTROL, ®_val); | 1106 | MDIO_COMBO_IEEE0_MII_CONTROL, ®_val); |
1115 | 1107 | ||
1116 | /* CL37 Autoneg Enabled */ | 1108 | /* CL37 Autoneg Enabled */ |
1117 | if (params->req_line_speed == SPEED_AUTO_NEG) | 1109 | if (vars->line_speed == SPEED_AUTO_NEG) |
1118 | reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_AN_EN; | 1110 | reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_AN_EN; |
1119 | else /* CL37 Autoneg Disabled */ | 1111 | else /* CL37 Autoneg Disabled */ |
1120 | reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN | | 1112 | reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN | |
@@ -1132,7 +1124,7 @@ static void bnx2x_set_autoneg(struct link_params *params, | |||
1132 | MDIO_REG_BANK_SERDES_DIGITAL, | 1124 | MDIO_REG_BANK_SERDES_DIGITAL, |
1133 | MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, ®_val); | 1125 | MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, ®_val); |
1134 | reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN; | 1126 | reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN; |
1135 | if (params->req_line_speed == SPEED_AUTO_NEG) | 1127 | if (vars->line_speed == SPEED_AUTO_NEG) |
1136 | reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET; | 1128 | reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET; |
1137 | else | 1129 | else |
1138 | reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET; | 1130 | reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET; |
@@ -1148,7 +1140,7 @@ static void bnx2x_set_autoneg(struct link_params *params, | |||
1148 | MDIO_REG_BANK_BAM_NEXT_PAGE, | 1140 | MDIO_REG_BANK_BAM_NEXT_PAGE, |
1149 | MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL, | 1141 | MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL, |
1150 | ®_val); | 1142 | ®_val); |
1151 | if (params->req_line_speed == SPEED_AUTO_NEG) { | 1143 | if (vars->line_speed == SPEED_AUTO_NEG) { |
1152 | /* Enable BAM aneg Mode and TetonII aneg Mode */ | 1144 | /* Enable BAM aneg Mode and TetonII aneg Mode */ |
1153 | reg_val |= (MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE | | 1145 | reg_val |= (MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE | |
1154 | MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN); | 1146 | MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN); |
@@ -1164,7 +1156,7 @@ static void bnx2x_set_autoneg(struct link_params *params, | |||
1164 | reg_val); | 1156 | reg_val); |
1165 | 1157 | ||
1166 | /* Enable Clause 73 Aneg */ | 1158 | /* Enable Clause 73 Aneg */ |
1167 | if ((params->req_line_speed == SPEED_AUTO_NEG) && | 1159 | if ((vars->line_speed == SPEED_AUTO_NEG) && |
1168 | (SUPPORT_CL73)) { | 1160 | (SUPPORT_CL73)) { |
1169 | /* Enable BAM Station Manager */ | 1161 | /* Enable BAM Station Manager */ |
1170 | 1162 | ||
@@ -1226,7 +1218,8 @@ static void bnx2x_set_autoneg(struct link_params *params, | |||
1226 | } | 1218 | } |
1227 | 1219 | ||
1228 | /* program SerDes, forced speed */ | 1220 | /* program SerDes, forced speed */ |
1229 | static void bnx2x_program_serdes(struct link_params *params) | 1221 | static void bnx2x_program_serdes(struct link_params *params, |
1222 | struct link_vars *vars) | ||
1230 | { | 1223 | { |
1231 | struct bnx2x *bp = params->bp; | 1224 | struct bnx2x *bp = params->bp; |
1232 | u16 reg_val; | 1225 | u16 reg_val; |
@@ -1248,28 +1241,35 @@ static void bnx2x_program_serdes(struct link_params *params) | |||
1248 | 1241 | ||
1249 | /* program speed | 1242 | /* program speed |
1250 | - needed only if the speed is greater than 1G (2.5G or 10G) */ | 1243 | - needed only if the speed is greater than 1G (2.5G or 10G) */ |
1251 | if (!((params->req_line_speed == SPEED_1000) || | 1244 | CL45_RD_OVER_CL22(bp, params->port, |
1252 | (params->req_line_speed == SPEED_100) || | ||
1253 | (params->req_line_speed == SPEED_10))) { | ||
1254 | CL45_RD_OVER_CL22(bp, params->port, | ||
1255 | params->phy_addr, | 1245 | params->phy_addr, |
1256 | MDIO_REG_BANK_SERDES_DIGITAL, | 1246 | MDIO_REG_BANK_SERDES_DIGITAL, |
1257 | MDIO_SERDES_DIGITAL_MISC1, ®_val); | 1247 | MDIO_SERDES_DIGITAL_MISC1, ®_val); |
1258 | /* clearing the speed value before setting the right speed */ | 1248 | /* clearing the speed value before setting the right speed */ |
1259 | reg_val &= ~MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_MASK; | 1249 | DP(NETIF_MSG_LINK, "MDIO_REG_BANK_SERDES_DIGITAL = 0x%x\n", reg_val); |
1250 | |||
1251 | reg_val &= ~(MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_MASK | | ||
1252 | MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL); | ||
1253 | |||
1254 | if (!((vars->line_speed == SPEED_1000) || | ||
1255 | (vars->line_speed == SPEED_100) || | ||
1256 | (vars->line_speed == SPEED_10))) { | ||
1257 | |||
1260 | reg_val |= (MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_156_25M | | 1258 | reg_val |= (MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_156_25M | |
1261 | MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL); | 1259 | MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL); |
1262 | if (params->req_line_speed == SPEED_10000) | 1260 | if (vars->line_speed == SPEED_10000) |
1263 | reg_val |= | 1261 | reg_val |= |
1264 | MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4; | 1262 | MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4; |
1265 | if (params->req_line_speed == SPEED_13000) | 1263 | if (vars->line_speed == SPEED_13000) |
1266 | reg_val |= | 1264 | reg_val |= |
1267 | MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G; | 1265 | MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G; |
1268 | CL45_WR_OVER_CL22(bp, params->port, | 1266 | } |
1267 | |||
1268 | CL45_WR_OVER_CL22(bp, params->port, | ||
1269 | params->phy_addr, | 1269 | params->phy_addr, |
1270 | MDIO_REG_BANK_SERDES_DIGITAL, | 1270 | MDIO_REG_BANK_SERDES_DIGITAL, |
1271 | MDIO_SERDES_DIGITAL_MISC1, reg_val); | 1271 | MDIO_SERDES_DIGITAL_MISC1, reg_val); |
1272 | } | 1272 | |
1273 | } | 1273 | } |
1274 | 1274 | ||
1275 | static void bnx2x_set_brcm_cl37_advertisment(struct link_params *params) | 1275 | static void bnx2x_set_brcm_cl37_advertisment(struct link_params *params) |
@@ -1295,48 +1295,49 @@ static void bnx2x_set_brcm_cl37_advertisment(struct link_params *params) | |||
1295 | MDIO_OVER_1G_UP3, 0); | 1295 | MDIO_OVER_1G_UP3, 0); |
1296 | } | 1296 | } |
1297 | 1297 | ||
1298 | static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params, | 1298 | static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u32 *ieee_fc) |
1299 | u32 *ieee_fc) | ||
1300 | { | 1299 | { |
1301 | struct bnx2x *bp = params->bp; | 1300 | *ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX; |
1302 | /* for AN, we are always publishing full duplex */ | ||
1303 | u16 an_adv = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX; | ||
1304 | |||
1305 | /* resolve pause mode and advertisement | 1301 | /* resolve pause mode and advertisement |
1306 | * Please refer to Table 28B-3 of the 802.3ab-1999 spec */ | 1302 | * Please refer to Table 28B-3 of the 802.3ab-1999 spec */ |
1307 | 1303 | ||
1308 | switch (params->req_flow_ctrl) { | 1304 | switch (params->req_flow_ctrl) { |
1309 | case FLOW_CTRL_AUTO: | 1305 | case FLOW_CTRL_AUTO: |
1310 | if (params->mtu <= MAX_MTU_SIZE) { | 1306 | if (params->req_fc_auto_adv == FLOW_CTRL_BOTH) { |
1311 | an_adv |= | 1307 | *ieee_fc |= |
1312 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; | 1308 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; |
1313 | } else { | 1309 | } else { |
1314 | an_adv |= | 1310 | *ieee_fc |= |
1315 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; | 1311 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; |
1316 | } | 1312 | } |
1317 | break; | 1313 | break; |
1318 | case FLOW_CTRL_TX: | 1314 | case FLOW_CTRL_TX: |
1319 | an_adv |= | 1315 | *ieee_fc |= |
1320 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; | 1316 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; |
1321 | break; | 1317 | break; |
1322 | 1318 | ||
1323 | case FLOW_CTRL_RX: | 1319 | case FLOW_CTRL_RX: |
1324 | case FLOW_CTRL_BOTH: | 1320 | case FLOW_CTRL_BOTH: |
1325 | an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; | 1321 | *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; |
1326 | break; | 1322 | break; |
1327 | 1323 | ||
1328 | case FLOW_CTRL_NONE: | 1324 | case FLOW_CTRL_NONE: |
1329 | default: | 1325 | default: |
1330 | an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE; | 1326 | *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE; |
1331 | break; | 1327 | break; |
1332 | } | 1328 | } |
1329 | } | ||
1333 | 1330 | ||
1334 | *ieee_fc = an_adv; | 1331 | static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params, |
1332 | u32 ieee_fc) | ||
1333 | { | ||
1334 | struct bnx2x *bp = params->bp; | ||
1335 | /* for AN, we are always publishing full duplex */ | ||
1335 | 1336 | ||
1336 | CL45_WR_OVER_CL22(bp, params->port, | 1337 | CL45_WR_OVER_CL22(bp, params->port, |
1337 | params->phy_addr, | 1338 | params->phy_addr, |
1338 | MDIO_REG_BANK_COMBO_IEEE0, | 1339 | MDIO_REG_BANK_COMBO_IEEE0, |
1339 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV, an_adv); | 1340 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV, (u16)ieee_fc); |
1340 | } | 1341 | } |
1341 | 1342 | ||
1342 | static void bnx2x_restart_autoneg(struct link_params *params) | 1343 | static void bnx2x_restart_autoneg(struct link_params *params) |
@@ -1382,7 +1383,8 @@ static void bnx2x_restart_autoneg(struct link_params *params) | |||
1382 | } | 1383 | } |
1383 | } | 1384 | } |
1384 | 1385 | ||
1385 | static void bnx2x_initialize_sgmii_process(struct link_params *params) | 1386 | static void bnx2x_initialize_sgmii_process(struct link_params *params, |
1387 | struct link_vars *vars) | ||
1386 | { | 1388 | { |
1387 | struct bnx2x *bp = params->bp; | 1389 | struct bnx2x *bp = params->bp; |
1388 | u16 control1; | 1390 | u16 control1; |
@@ -1406,7 +1408,7 @@ static void bnx2x_initialize_sgmii_process(struct link_params *params) | |||
1406 | control1); | 1408 | control1); |
1407 | 1409 | ||
1408 | /* if forced speed */ | 1410 | /* if forced speed */ |
1409 | if (!(params->req_line_speed == SPEED_AUTO_NEG)) { | 1411 | if (!(vars->line_speed == SPEED_AUTO_NEG)) { |
1410 | /* set speed, disable autoneg */ | 1412 | /* set speed, disable autoneg */ |
1411 | u16 mii_control; | 1413 | u16 mii_control; |
1412 | 1414 | ||
@@ -1419,7 +1421,7 @@ static void bnx2x_initialize_sgmii_process(struct link_params *params) | |||
1419 | MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK| | 1421 | MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK| |
1420 | MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX); | 1422 | MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX); |
1421 | 1423 | ||
1422 | switch (params->req_line_speed) { | 1424 | switch (vars->line_speed) { |
1423 | case SPEED_100: | 1425 | case SPEED_100: |
1424 | mii_control |= | 1426 | mii_control |= |
1425 | MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_100; | 1427 | MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_100; |
@@ -1433,8 +1435,8 @@ static void bnx2x_initialize_sgmii_process(struct link_params *params) | |||
1433 | break; | 1435 | break; |
1434 | default: | 1436 | default: |
1435 | /* invalid speed for SGMII */ | 1437 | /* invalid speed for SGMII */ |
1436 | DP(NETIF_MSG_LINK, "Invalid req_line_speed 0x%x\n", | 1438 | DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n", |
1437 | params->req_line_speed); | 1439 | vars->line_speed); |
1438 | break; | 1440 | break; |
1439 | } | 1441 | } |
1440 | 1442 | ||
@@ -1460,20 +1462,20 @@ static void bnx2x_initialize_sgmii_process(struct link_params *params) | |||
1460 | */ | 1462 | */ |
1461 | 1463 | ||
1462 | static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result) | 1464 | static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result) |
1463 | { | 1465 | { /* LD LP */ |
1464 | switch (pause_result) { /* ASYM P ASYM P */ | 1466 | switch (pause_result) { /* ASYM P ASYM P */ |
1465 | case 0xb: /* 1 0 1 1 */ | 1467 | case 0xb: /* 1 0 1 1 */ |
1466 | vars->flow_ctrl = FLOW_CTRL_TX; | 1468 | vars->flow_ctrl = FLOW_CTRL_TX; |
1467 | break; | 1469 | break; |
1468 | 1470 | ||
1469 | case 0xe: /* 1 1 1 0 */ | 1471 | case 0xe: /* 1 1 1 0 */ |
1470 | vars->flow_ctrl = FLOW_CTRL_RX; | 1472 | vars->flow_ctrl = FLOW_CTRL_RX; |
1471 | break; | 1473 | break; |
1472 | 1474 | ||
1473 | case 0x5: /* 0 1 0 1 */ | 1475 | case 0x5: /* 0 1 0 1 */ |
1474 | case 0x7: /* 0 1 1 1 */ | 1476 | case 0x7: /* 0 1 1 1 */ |
1475 | case 0xd: /* 1 1 0 1 */ | 1477 | case 0xd: /* 1 1 0 1 */ |
1476 | case 0xf: /* 1 1 1 1 */ | 1478 | case 0xf: /* 1 1 1 1 */ |
1477 | vars->flow_ctrl = FLOW_CTRL_BOTH; | 1479 | vars->flow_ctrl = FLOW_CTRL_BOTH; |
1478 | break; | 1480 | break; |
1479 | 1481 | ||
@@ -1487,8 +1489,8 @@ static u8 bnx2x_ext_phy_resove_fc(struct link_params *params, | |||
1487 | { | 1489 | { |
1488 | struct bnx2x *bp = params->bp; | 1490 | struct bnx2x *bp = params->bp; |
1489 | u8 ext_phy_addr; | 1491 | u8 ext_phy_addr; |
1490 | u16 ld_pause; /* local */ | 1492 | u16 ld_pause; /* local */ |
1491 | u16 lp_pause; /* link partner */ | 1493 | u16 lp_pause; /* link partner */ |
1492 | u16 an_complete; /* AN complete */ | 1494 | u16 an_complete; /* AN complete */ |
1493 | u16 pause_result; | 1495 | u16 pause_result; |
1494 | u8 ret = 0; | 1496 | u8 ret = 0; |
@@ -1531,6 +1533,28 @@ static u8 bnx2x_ext_phy_resove_fc(struct link_params *params, | |||
1531 | DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x \n", | 1533 | DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x \n", |
1532 | pause_result); | 1534 | pause_result); |
1533 | bnx2x_pause_resolve(vars, pause_result); | 1535 | bnx2x_pause_resolve(vars, pause_result); |
1536 | if (vars->flow_ctrl == FLOW_CTRL_NONE && | ||
1537 | ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) { | ||
1538 | bnx2x_cl45_read(bp, port, | ||
1539 | ext_phy_type, | ||
1540 | ext_phy_addr, | ||
1541 | MDIO_AN_DEVAD, | ||
1542 | MDIO_AN_REG_CL37_FC_LD, &ld_pause); | ||
1543 | |||
1544 | bnx2x_cl45_read(bp, port, | ||
1545 | ext_phy_type, | ||
1546 | ext_phy_addr, | ||
1547 | MDIO_AN_DEVAD, | ||
1548 | MDIO_AN_REG_CL37_FC_LP, &lp_pause); | ||
1549 | pause_result = (ld_pause & | ||
1550 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5; | ||
1551 | pause_result |= (lp_pause & | ||
1552 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7; | ||
1553 | |||
1554 | bnx2x_pause_resolve(vars, pause_result); | ||
1555 | DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x \n", | ||
1556 | pause_result); | ||
1557 | } | ||
1534 | } | 1558 | } |
1535 | return ret; | 1559 | return ret; |
1536 | } | 1560 | } |
@@ -1573,13 +1597,10 @@ static void bnx2x_flow_ctrl_resolve(struct link_params *params, | |||
1573 | (bnx2x_ext_phy_resove_fc(params, vars))) { | 1597 | (bnx2x_ext_phy_resove_fc(params, vars))) { |
1574 | return; | 1598 | return; |
1575 | } else { | 1599 | } else { |
1576 | vars->flow_ctrl = params->req_flow_ctrl; | 1600 | if (params->req_flow_ctrl == FLOW_CTRL_AUTO) |
1577 | if (vars->flow_ctrl == FLOW_CTRL_AUTO) { | 1601 | vars->flow_ctrl = params->req_fc_auto_adv; |
1578 | if (params->mtu <= MAX_MTU_SIZE) | 1602 | else |
1579 | vars->flow_ctrl = FLOW_CTRL_BOTH; | 1603 | vars->flow_ctrl = params->req_flow_ctrl; |
1580 | else | ||
1581 | vars->flow_ctrl = FLOW_CTRL_TX; | ||
1582 | } | ||
1583 | } | 1604 | } |
1584 | DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl); | 1605 | DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl); |
1585 | } | 1606 | } |
@@ -1709,12 +1730,12 @@ static u8 bnx2x_link_settings_status(struct link_params *params, | |||
1709 | 1730 | ||
1710 | } | 1731 | } |
1711 | if (vars->flow_ctrl & FLOW_CTRL_TX) | 1732 | if (vars->flow_ctrl & FLOW_CTRL_TX) |
1712 | vars->link_status |= | 1733 | vars->link_status |= |
1713 | LINK_STATUS_TX_FLOW_CONTROL_ENABLED; | 1734 | LINK_STATUS_TX_FLOW_CONTROL_ENABLED; |
1714 | 1735 | ||
1715 | if (vars->flow_ctrl & FLOW_CTRL_RX) | 1736 | if (vars->flow_ctrl & FLOW_CTRL_RX) |
1716 | vars->link_status |= | 1737 | vars->link_status |= |
1717 | LINK_STATUS_RX_FLOW_CONTROL_ENABLED; | 1738 | LINK_STATUS_RX_FLOW_CONTROL_ENABLED; |
1718 | 1739 | ||
1719 | } else { /* link_down */ | 1740 | } else { /* link_down */ |
1720 | DP(NETIF_MSG_LINK, "phy link down\n"); | 1741 | DP(NETIF_MSG_LINK, "phy link down\n"); |
@@ -2286,13 +2307,16 @@ static void bnx2x_ext_phy_set_pause(struct link_params *params, | |||
2286 | MDIO_AN_REG_ADV_PAUSE, &val); | 2307 | MDIO_AN_REG_ADV_PAUSE, &val); |
2287 | 2308 | ||
2288 | val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH; | 2309 | val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH; |
2310 | |||
2289 | /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */ | 2311 | /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */ |
2290 | 2312 | ||
2291 | if (vars->ieee_fc & | 2313 | if ((vars->ieee_fc & |
2314 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) == | ||
2292 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) { | 2315 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) { |
2293 | val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC; | 2316 | val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC; |
2294 | } | 2317 | } |
2295 | if (vars->ieee_fc & | 2318 | if ((vars->ieee_fc & |
2319 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) == | ||
2296 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) { | 2320 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) { |
2297 | val |= | 2321 | val |= |
2298 | MDIO_AN_REG_ADV_PAUSE_PAUSE; | 2322 | MDIO_AN_REG_ADV_PAUSE_PAUSE; |
@@ -2339,7 +2363,7 @@ static void bnx2x_init_internal_phy(struct link_params *params, | |||
2339 | bnx2x_set_autoneg(params, vars); | 2363 | bnx2x_set_autoneg(params, vars); |
2340 | 2364 | ||
2341 | /* program speed and duplex */ | 2365 | /* program speed and duplex */ |
2342 | bnx2x_program_serdes(params); | 2366 | bnx2x_program_serdes(params, vars); |
2343 | 2367 | ||
2344 | } else { /* AN_mode */ | 2368 | } else { /* AN_mode */ |
2345 | DP(NETIF_MSG_LINK, "not SGMII, AN\n"); | 2369 | DP(NETIF_MSG_LINK, "not SGMII, AN\n"); |
@@ -2349,7 +2373,7 @@ static void bnx2x_init_internal_phy(struct link_params *params, | |||
2349 | 2373 | ||
2350 | /* program duplex & pause advertisement (for aneg) */ | 2374 | /* program duplex & pause advertisement (for aneg) */ |
2351 | bnx2x_set_ieee_aneg_advertisment(params, | 2375 | bnx2x_set_ieee_aneg_advertisment(params, |
2352 | &vars->ieee_fc); | 2376 | vars->ieee_fc); |
2353 | 2377 | ||
2354 | /* enable autoneg */ | 2378 | /* enable autoneg */ |
2355 | bnx2x_set_autoneg(params, vars); | 2379 | bnx2x_set_autoneg(params, vars); |
@@ -2361,7 +2385,7 @@ static void bnx2x_init_internal_phy(struct link_params *params, | |||
2361 | } else { /* SGMII mode */ | 2385 | } else { /* SGMII mode */ |
2362 | DP(NETIF_MSG_LINK, "SGMII\n"); | 2386 | DP(NETIF_MSG_LINK, "SGMII\n"); |
2363 | 2387 | ||
2364 | bnx2x_initialize_sgmii_process(params); | 2388 | bnx2x_initialize_sgmii_process(params, vars); |
2365 | } | 2389 | } |
2366 | } | 2390 | } |
2367 | 2391 | ||
@@ -2481,7 +2505,7 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars) | |||
2481 | ext_phy_type, | 2505 | ext_phy_type, |
2482 | ext_phy_addr, | 2506 | ext_phy_addr, |
2483 | MDIO_AN_DEVAD, | 2507 | MDIO_AN_DEVAD, |
2484 | MDIO_AN_REG_CL37_FD, | 2508 | MDIO_AN_REG_CL37_FC_LP, |
2485 | 0x0020); | 2509 | 0x0020); |
2486 | /* Enable CL37 AN */ | 2510 | /* Enable CL37 AN */ |
2487 | bnx2x_cl45_write(bp, params->port, | 2511 | bnx2x_cl45_write(bp, params->port, |
@@ -2657,13 +2681,13 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars) | |||
2657 | ext_phy_type, | 2681 | ext_phy_type, |
2658 | ext_phy_addr, | 2682 | ext_phy_addr, |
2659 | MDIO_AN_DEVAD, | 2683 | MDIO_AN_DEVAD, |
2660 | MDIO_AN_REG_CL37_CL73, 0x040c); | 2684 | MDIO_AN_REG_CL37_FC_LD, 0x040c); |
2661 | /* Add support for CL37 (passive mode) II */ | 2685 | /* Add support for CL37 (passive mode) II */ |
2662 | bnx2x_cl45_write(bp, params->port, | 2686 | bnx2x_cl45_write(bp, params->port, |
2663 | ext_phy_type, | 2687 | ext_phy_type, |
2664 | ext_phy_addr, | 2688 | ext_phy_addr, |
2665 | MDIO_AN_DEVAD, | 2689 | MDIO_AN_DEVAD, |
2666 | MDIO_AN_REG_CL37_FD, 0x20); | 2690 | MDIO_AN_REG_CL37_FC_LD, 0x20); |
2667 | /* Add support for CL37 (passive mode) III */ | 2691 | /* Add support for CL37 (passive mode) III */ |
2668 | bnx2x_cl45_write(bp, params->port, | 2692 | bnx2x_cl45_write(bp, params->port, |
2669 | ext_phy_type, | 2693 | ext_phy_type, |
@@ -2785,7 +2809,7 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars) | |||
2785 | 2809 | ||
2786 | 2810 | ||
2787 | static u8 bnx2x_ext_phy_is_link_up(struct link_params *params, | 2811 | static u8 bnx2x_ext_phy_is_link_up(struct link_params *params, |
2788 | struct link_vars *vars) | 2812 | struct link_vars *vars) |
2789 | { | 2813 | { |
2790 | struct bnx2x *bp = params->bp; | 2814 | struct bnx2x *bp = params->bp; |
2791 | u32 ext_phy_type; | 2815 | u32 ext_phy_type; |
@@ -2826,6 +2850,8 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params, | |||
2826 | MDIO_PMA_REG_RX_SD, &rx_sd); | 2850 | MDIO_PMA_REG_RX_SD, &rx_sd); |
2827 | DP(NETIF_MSG_LINK, "8705 rx_sd 0x%x\n", rx_sd); | 2851 | DP(NETIF_MSG_LINK, "8705 rx_sd 0x%x\n", rx_sd); |
2828 | ext_phy_link_up = (rx_sd & 0x1); | 2852 | ext_phy_link_up = (rx_sd & 0x1); |
2853 | if (ext_phy_link_up) | ||
2854 | vars->line_speed = SPEED_10000; | ||
2829 | break; | 2855 | break; |
2830 | 2856 | ||
2831 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: | 2857 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: |
@@ -3734,7 +3760,7 @@ static u8 bnx2x_link_initialize(struct link_params *params, | |||
3734 | req_line_speed*/ | 3760 | req_line_speed*/ |
3735 | vars->line_speed = params->req_line_speed; | 3761 | vars->line_speed = params->req_line_speed; |
3736 | 3762 | ||
3737 | bnx2x_set_ieee_aneg_advertisment(params, &vars->ieee_fc); | 3763 | bnx2x_calc_ieee_aneg_adv(params, &vars->ieee_fc); |
3738 | 3764 | ||
3739 | /* init ext phy and enable link state int */ | 3765 | /* init ext phy and enable link state int */ |
3740 | non_ext_phy = ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) || | 3766 | non_ext_phy = ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) || |