aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2x_link.c
diff options
context:
space:
mode:
authorYaniv Rosner <yanivr@broadcom.com>2008-08-13 18:56:17 -0400
committerDavid S. Miller <davem@davemloft.net>2008-08-13 19:04:30 -0400
commit8c99e7b0436473593a68e740d1032909bc5335a1 (patch)
tree621557728da3ea1bb7cf4e4e08a4c184bf037b4e /drivers/net/bnx2x_link.c
parent57963ed94c27e94a7533434da5943195ea072a35 (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.c202
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, &reg_val); 1106 MDIO_COMBO_IEEE0_MII_CONTROL, &reg_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, &reg_val); 1125 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, &reg_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 &reg_val); 1142 &reg_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 */
1229static void bnx2x_program_serdes(struct link_params *params) 1221static 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, &reg_val); 1247 MDIO_SERDES_DIGITAL_MISC1, &reg_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
1275static void bnx2x_set_brcm_cl37_advertisment(struct link_params *params) 1275static 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
1298static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params, 1298static 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; 1331static 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
1342static void bnx2x_restart_autoneg(struct link_params *params) 1343static 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
1385static void bnx2x_initialize_sgmii_process(struct link_params *params) 1386static 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
1462static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result) 1464static 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
2787static u8 bnx2x_ext_phy_is_link_up(struct link_params *params, 2811static 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) ||