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 | |
| 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>
| -rw-r--r-- | drivers/net/bnx2x_link.c | 202 | ||||
| -rw-r--r-- | drivers/net/bnx2x_link.h | 4 | ||||
| -rw-r--r-- | drivers/net/bnx2x_main.c | 9 | ||||
| -rw-r--r-- | drivers/net/bnx2x_reg.h | 4 |
4 files changed, 128 insertions, 91 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) || |
diff --git a/drivers/net/bnx2x_link.h b/drivers/net/bnx2x_link.h index 714d37ac95de..b222552b868d 100644 --- a/drivers/net/bnx2x_link.h +++ b/drivers/net/bnx2x_link.h | |||
| @@ -58,11 +58,13 @@ struct link_params { | |||
| 58 | 58 | ||
| 59 | u16 req_duplex; | 59 | u16 req_duplex; |
| 60 | u16 req_flow_ctrl; | 60 | u16 req_flow_ctrl; |
| 61 | u16 req_fc_auto_adv; /* Should be set to TX / BOTH when | ||
| 62 | req_flow_ctrl is set to AUTO */ | ||
| 61 | u16 req_line_speed; /* Also determine AutoNeg */ | 63 | u16 req_line_speed; /* Also determine AutoNeg */ |
| 62 | 64 | ||
| 63 | /* Device parameters */ | 65 | /* Device parameters */ |
| 64 | u8 mac_addr[6]; | 66 | u8 mac_addr[6]; |
| 65 | u16 mtu; | 67 | |
| 66 | 68 | ||
| 67 | 69 | ||
| 68 | /* shmem parameters */ | 70 | /* shmem parameters */ |
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index d29f22763fec..a37549b5bc1c 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c | |||
| @@ -1946,7 +1946,14 @@ static u8 bnx2x_initial_phy_init(struct bnx2x *bp) | |||
| 1946 | u8 rc; | 1946 | u8 rc; |
| 1947 | 1947 | ||
| 1948 | /* Initialize link parameters structure variables */ | 1948 | /* Initialize link parameters structure variables */ |
| 1949 | bp->link_params.mtu = bp->dev->mtu; | 1949 | /* It is recommended to turn off RX FC for jumbo frames |
| 1950 | for better performance */ | ||
| 1951 | if (IS_E1HMF(bp)) | ||
| 1952 | bp->link_params.req_fc_auto_adv = FLOW_CTRL_BOTH; | ||
| 1953 | else if (bp->dev->mtu > 5000) | ||
| 1954 | bp->link_params.req_fc_auto_adv = FLOW_CTRL_TX; | ||
| 1955 | else | ||
| 1956 | bp->link_params.req_fc_auto_adv = FLOW_CTRL_BOTH; | ||
| 1950 | 1957 | ||
| 1951 | bnx2x_acquire_phy_lock(bp); | 1958 | bnx2x_acquire_phy_lock(bp); |
| 1952 | rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars); | 1959 | rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars); |
diff --git a/drivers/net/bnx2x_reg.h b/drivers/net/bnx2x_reg.h index 58fbeb1cf78d..5029d1e466f6 100644 --- a/drivers/net/bnx2x_reg.h +++ b/drivers/net/bnx2x_reg.h | |||
| @@ -4966,6 +4966,7 @@ | |||
| 4966 | #define EMAC_RX_MODE_PROMISCUOUS (1L<<8) | 4966 | #define EMAC_RX_MODE_PROMISCUOUS (1L<<8) |
| 4967 | #define EMAC_RX_MTU_SIZE_JUMBO_ENA (1L<<31) | 4967 | #define EMAC_RX_MTU_SIZE_JUMBO_ENA (1L<<31) |
| 4968 | #define EMAC_TX_MODE_EXT_PAUSE_EN (1L<<3) | 4968 | #define EMAC_TX_MODE_EXT_PAUSE_EN (1L<<3) |
| 4969 | #define EMAC_TX_MODE_FLOW_EN (1L<<4) | ||
| 4969 | #define MISC_REGISTERS_GPIO_0 0 | 4970 | #define MISC_REGISTERS_GPIO_0 0 |
| 4970 | #define MISC_REGISTERS_GPIO_1 1 | 4971 | #define MISC_REGISTERS_GPIO_1 1 |
| 4971 | #define MISC_REGISTERS_GPIO_2 2 | 4972 | #define MISC_REGISTERS_GPIO_2 2 |
| @@ -5615,7 +5616,8 @@ Theotherbitsarereservedandshouldbezero*/ | |||
| 5615 | #define MDIO_AN_REG_LINK_STATUS 0x8304 | 5616 | #define MDIO_AN_REG_LINK_STATUS 0x8304 |
| 5616 | #define MDIO_AN_REG_CL37_CL73 0x8370 | 5617 | #define MDIO_AN_REG_CL37_CL73 0x8370 |
| 5617 | #define MDIO_AN_REG_CL37_AN 0xffe0 | 5618 | #define MDIO_AN_REG_CL37_AN 0xffe0 |
| 5618 | #define MDIO_AN_REG_CL37_FD 0xffe4 | 5619 | #define MDIO_AN_REG_CL37_FC_LD 0xffe4 |
| 5620 | #define MDIO_AN_REG_CL37_FC_LP 0xffe5 | ||
| 5619 | 5621 | ||
| 5620 | 5622 | ||
| 5621 | #define IGU_FUNC_BASE 0x0400 | 5623 | #define IGU_FUNC_BASE 0x0400 |
