diff options
author | Carolyn Wyborny <carolyn.wyborny@intel.com> | 2012-10-23 08:54:33 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2012-12-01 06:30:20 -0500 |
commit | daf56e406a94675d454f996cab56c3d0b0a0d8a6 (patch) | |
tree | f8a4e6ab413490c02d3e4966d3736d65346e4c04 /drivers/net | |
parent | 3860a0bf748bf98a30f2bab73d5e3653583f7b47 (diff) |
igb: Fix SerDes autoneg flow control.
This patch enables flow control to be set in SerDes autoneg mode. This is
done the way it is done for copper, but relies on a different set of register/bit
checks since this is all done within the MAC registers.
Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_82575.c | 43 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_defines.h | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_mac.c | 124 |
3 files changed, 166 insertions, 8 deletions
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c index db40b68819d8..fdaaf2709d0a 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.c +++ b/drivers/net/ethernet/intel/igb/e1000_82575.c | |||
@@ -1028,6 +1028,15 @@ static s32 igb_check_for_link_82575(struct e1000_hw *hw) | |||
1028 | * continue to check for link. | 1028 | * continue to check for link. |
1029 | */ | 1029 | */ |
1030 | hw->mac.get_link_status = !hw->mac.serdes_has_link; | 1030 | hw->mac.get_link_status = !hw->mac.serdes_has_link; |
1031 | |||
1032 | /* Configure Flow Control now that Auto-Neg has completed. | ||
1033 | * First, we need to restore the desired flow control | ||
1034 | * settings because we may have had to re-autoneg with a | ||
1035 | * different link partner. | ||
1036 | */ | ||
1037 | ret_val = igb_config_fc_after_link_up(hw); | ||
1038 | if (ret_val) | ||
1039 | hw_dbg("Error configuring flow control\n"); | ||
1031 | } else { | 1040 | } else { |
1032 | ret_val = igb_check_for_copper_link(hw); | 1041 | ret_val = igb_check_for_copper_link(hw); |
1033 | } | 1042 | } |
@@ -1345,7 +1354,7 @@ out: | |||
1345 | **/ | 1354 | **/ |
1346 | static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw) | 1355 | static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw) |
1347 | { | 1356 | { |
1348 | u32 ctrl_ext, ctrl_reg, reg; | 1357 | u32 ctrl_ext, ctrl_reg, reg, anadv_reg; |
1349 | bool pcs_autoneg; | 1358 | bool pcs_autoneg; |
1350 | s32 ret_val = E1000_SUCCESS; | 1359 | s32 ret_val = E1000_SUCCESS; |
1351 | u16 data; | 1360 | u16 data; |
@@ -1433,27 +1442,45 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw) | |||
1433 | reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP | | 1442 | reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP | |
1434 | E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); | 1443 | E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); |
1435 | 1444 | ||
1436 | /* | ||
1437 | * We force flow control to prevent the CTRL register values from being | ||
1438 | * overwritten by the autonegotiated flow control values | ||
1439 | */ | ||
1440 | reg |= E1000_PCS_LCTL_FORCE_FCTRL; | ||
1441 | |||
1442 | if (pcs_autoneg) { | 1445 | if (pcs_autoneg) { |
1443 | /* Set PCS register for autoneg */ | 1446 | /* Set PCS register for autoneg */ |
1444 | reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */ | 1447 | reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */ |
1445 | E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */ | 1448 | E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */ |
1449 | |||
1450 | /* Disable force flow control for autoneg */ | ||
1451 | reg &= ~E1000_PCS_LCTL_FORCE_FCTRL; | ||
1452 | |||
1453 | /* Configure flow control advertisement for autoneg */ | ||
1454 | anadv_reg = rd32(E1000_PCS_ANADV); | ||
1455 | anadv_reg &= ~(E1000_TXCW_ASM_DIR | E1000_TXCW_PAUSE); | ||
1456 | switch (hw->fc.requested_mode) { | ||
1457 | case e1000_fc_full: | ||
1458 | case e1000_fc_rx_pause: | ||
1459 | anadv_reg |= E1000_TXCW_ASM_DIR; | ||
1460 | anadv_reg |= E1000_TXCW_PAUSE; | ||
1461 | break; | ||
1462 | case e1000_fc_tx_pause: | ||
1463 | anadv_reg |= E1000_TXCW_ASM_DIR; | ||
1464 | break; | ||
1465 | default: | ||
1466 | break; | ||
1467 | } | ||
1468 | wr32(E1000_PCS_ANADV, anadv_reg); | ||
1469 | |||
1446 | hw_dbg("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg); | 1470 | hw_dbg("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg); |
1447 | } else { | 1471 | } else { |
1448 | /* Set PCS register for forced link */ | 1472 | /* Set PCS register for forced link */ |
1449 | reg |= E1000_PCS_LCTL_FSD; /* Force Speed */ | 1473 | reg |= E1000_PCS_LCTL_FSD; /* Force Speed */ |
1450 | 1474 | ||
1475 | /* Force flow control for forced link */ | ||
1476 | reg |= E1000_PCS_LCTL_FORCE_FCTRL; | ||
1477 | |||
1451 | hw_dbg("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg); | 1478 | hw_dbg("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg); |
1452 | } | 1479 | } |
1453 | 1480 | ||
1454 | wr32(E1000_PCS_LCTL, reg); | 1481 | wr32(E1000_PCS_LCTL, reg); |
1455 | 1482 | ||
1456 | if (!igb_sgmii_active_82575(hw)) | 1483 | if (!pcs_autoneg && !igb_sgmii_active_82575(hw)) |
1457 | igb_force_mac_fc(hw); | 1484 | igb_force_mac_fc(hw); |
1458 | 1485 | ||
1459 | return ret_val; | 1486 | return ret_val; |
diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h index 198d14848820..45dce06eff26 100644 --- a/drivers/net/ethernet/intel/igb/e1000_defines.h +++ b/drivers/net/ethernet/intel/igb/e1000_defines.h | |||
@@ -431,6 +431,10 @@ | |||
431 | #define FLOW_CONTROL_ADDRESS_HIGH 0x00000100 | 431 | #define FLOW_CONTROL_ADDRESS_HIGH 0x00000100 |
432 | #define FLOW_CONTROL_TYPE 0x8808 | 432 | #define FLOW_CONTROL_TYPE 0x8808 |
433 | 433 | ||
434 | /* Transmit Config Word */ | ||
435 | #define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */ | ||
436 | #define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */ | ||
437 | |||
434 | /* 802.1q VLAN Packet Size */ | 438 | /* 802.1q VLAN Packet Size */ |
435 | #define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMA'd) */ | 439 | #define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMA'd) */ |
436 | #define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */ | 440 | #define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */ |
@@ -539,6 +543,9 @@ | |||
539 | /* mPHY Near End Digital Loopback Override Bit */ | 543 | /* mPHY Near End Digital Loopback Override Bit */ |
540 | #define E1000_MPHY_PCS_CLK_REG_DIGINELBEN 0x10 | 544 | #define E1000_MPHY_PCS_CLK_REG_DIGINELBEN 0x10 |
541 | 545 | ||
546 | #define E1000_PCS_LCTL_FORCE_FCTRL 0x80 | ||
547 | #define E1000_PCS_LSTS_AN_COMPLETE 0x10000 | ||
548 | |||
542 | /* PHY Control Register */ | 549 | /* PHY Control Register */ |
543 | #define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ | 550 | #define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ |
544 | #define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ | 551 | #define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ |
diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c index 7acddfe9e6d5..101e6e4da97f 100644 --- a/drivers/net/ethernet/intel/igb/e1000_mac.c +++ b/drivers/net/ethernet/intel/igb/e1000_mac.c | |||
@@ -839,6 +839,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) | |||
839 | { | 839 | { |
840 | struct e1000_mac_info *mac = &hw->mac; | 840 | struct e1000_mac_info *mac = &hw->mac; |
841 | s32 ret_val = 0; | 841 | s32 ret_val = 0; |
842 | u32 pcs_status_reg, pcs_adv_reg, pcs_lp_ability_reg, pcs_ctrl_reg; | ||
842 | u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; | 843 | u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; |
843 | u16 speed, duplex; | 844 | u16 speed, duplex; |
844 | 845 | ||
@@ -1040,6 +1041,129 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) | |||
1040 | goto out; | 1041 | goto out; |
1041 | } | 1042 | } |
1042 | } | 1043 | } |
1044 | /* Check for the case where we have SerDes media and auto-neg is | ||
1045 | * enabled. In this case, we need to check and see if Auto-Neg | ||
1046 | * has completed, and if so, how the PHY and link partner has | ||
1047 | * flow control configured. | ||
1048 | */ | ||
1049 | if ((hw->phy.media_type == e1000_media_type_internal_serdes) | ||
1050 | && mac->autoneg) { | ||
1051 | /* Read the PCS_LSTS and check to see if AutoNeg | ||
1052 | * has completed. | ||
1053 | */ | ||
1054 | pcs_status_reg = rd32(E1000_PCS_LSTAT); | ||
1055 | |||
1056 | if (!(pcs_status_reg & E1000_PCS_LSTS_AN_COMPLETE)) { | ||
1057 | hw_dbg("PCS Auto Neg has not completed.\n"); | ||
1058 | return ret_val; | ||
1059 | } | ||
1060 | |||
1061 | /* The AutoNeg process has completed, so we now need to | ||
1062 | * read both the Auto Negotiation Advertisement | ||
1063 | * Register (PCS_ANADV) and the Auto_Negotiation Base | ||
1064 | * Page Ability Register (PCS_LPAB) to determine how | ||
1065 | * flow control was negotiated. | ||
1066 | */ | ||
1067 | pcs_adv_reg = rd32(E1000_PCS_ANADV); | ||
1068 | pcs_lp_ability_reg = rd32(E1000_PCS_LPAB); | ||
1069 | |||
1070 | /* Two bits in the Auto Negotiation Advertisement Register | ||
1071 | * (PCS_ANADV) and two bits in the Auto Negotiation Base | ||
1072 | * Page Ability Register (PCS_LPAB) determine flow control | ||
1073 | * for both the PHY and the link partner. The following | ||
1074 | * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, | ||
1075 | * 1999, describes these PAUSE resolution bits and how flow | ||
1076 | * control is determined based upon these settings. | ||
1077 | * NOTE: DC = Don't Care | ||
1078 | * | ||
1079 | * LOCAL DEVICE | LINK PARTNER | ||
1080 | * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution | ||
1081 | *-------|---------|-------|---------|-------------------- | ||
1082 | * 0 | 0 | DC | DC | e1000_fc_none | ||
1083 | * 0 | 1 | 0 | DC | e1000_fc_none | ||
1084 | * 0 | 1 | 1 | 0 | e1000_fc_none | ||
1085 | * 0 | 1 | 1 | 1 | e1000_fc_tx_pause | ||
1086 | * 1 | 0 | 0 | DC | e1000_fc_none | ||
1087 | * 1 | DC | 1 | DC | e1000_fc_full | ||
1088 | * 1 | 1 | 0 | 0 | e1000_fc_none | ||
1089 | * 1 | 1 | 0 | 1 | e1000_fc_rx_pause | ||
1090 | * | ||
1091 | * Are both PAUSE bits set to 1? If so, this implies | ||
1092 | * Symmetric Flow Control is enabled at both ends. The | ||
1093 | * ASM_DIR bits are irrelevant per the spec. | ||
1094 | * | ||
1095 | * For Symmetric Flow Control: | ||
1096 | * | ||
1097 | * LOCAL DEVICE | LINK PARTNER | ||
1098 | * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result | ||
1099 | *-------|---------|-------|---------|-------------------- | ||
1100 | * 1 | DC | 1 | DC | e1000_fc_full | ||
1101 | * | ||
1102 | */ | ||
1103 | if ((pcs_adv_reg & E1000_TXCW_PAUSE) && | ||
1104 | (pcs_lp_ability_reg & E1000_TXCW_PAUSE)) { | ||
1105 | /* Now we need to check if the user selected Rx ONLY | ||
1106 | * of pause frames. In this case, we had to advertise | ||
1107 | * FULL flow control because we could not advertise Rx | ||
1108 | * ONLY. Hence, we must now check to see if we need to | ||
1109 | * turn OFF the TRANSMISSION of PAUSE frames. | ||
1110 | */ | ||
1111 | if (hw->fc.requested_mode == e1000_fc_full) { | ||
1112 | hw->fc.current_mode = e1000_fc_full; | ||
1113 | hw_dbg("Flow Control = FULL.\n"); | ||
1114 | } else { | ||
1115 | hw->fc.current_mode = e1000_fc_rx_pause; | ||
1116 | hw_dbg("Flow Control = Rx PAUSE frames only.\n"); | ||
1117 | } | ||
1118 | } | ||
1119 | /* For receiving PAUSE frames ONLY. | ||
1120 | * | ||
1121 | * LOCAL DEVICE | LINK PARTNER | ||
1122 | * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result | ||
1123 | *-------|---------|-------|---------|-------------------- | ||
1124 | * 0 | 1 | 1 | 1 | e1000_fc_tx_pause | ||
1125 | */ | ||
1126 | else if (!(pcs_adv_reg & E1000_TXCW_PAUSE) && | ||
1127 | (pcs_adv_reg & E1000_TXCW_ASM_DIR) && | ||
1128 | (pcs_lp_ability_reg & E1000_TXCW_PAUSE) && | ||
1129 | (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { | ||
1130 | hw->fc.current_mode = e1000_fc_tx_pause; | ||
1131 | hw_dbg("Flow Control = Tx PAUSE frames only.\n"); | ||
1132 | } | ||
1133 | /* For transmitting PAUSE frames ONLY. | ||
1134 | * | ||
1135 | * LOCAL DEVICE | LINK PARTNER | ||
1136 | * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result | ||
1137 | *-------|---------|-------|---------|-------------------- | ||
1138 | * 1 | 1 | 0 | 1 | e1000_fc_rx_pause | ||
1139 | */ | ||
1140 | else if ((pcs_adv_reg & E1000_TXCW_PAUSE) && | ||
1141 | (pcs_adv_reg & E1000_TXCW_ASM_DIR) && | ||
1142 | !(pcs_lp_ability_reg & E1000_TXCW_PAUSE) && | ||
1143 | (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { | ||
1144 | hw->fc.current_mode = e1000_fc_rx_pause; | ||
1145 | hw_dbg("Flow Control = Rx PAUSE frames only.\n"); | ||
1146 | } else { | ||
1147 | /* Per the IEEE spec, at this point flow control | ||
1148 | * should be disabled. | ||
1149 | */ | ||
1150 | hw->fc.current_mode = e1000_fc_none; | ||
1151 | hw_dbg("Flow Control = NONE.\n"); | ||
1152 | } | ||
1153 | |||
1154 | /* Now we call a subroutine to actually force the MAC | ||
1155 | * controller to use the correct flow control settings. | ||
1156 | */ | ||
1157 | pcs_ctrl_reg = rd32(E1000_PCS_LCTL); | ||
1158 | pcs_ctrl_reg |= E1000_PCS_LCTL_FORCE_FCTRL; | ||
1159 | wr32(E1000_PCS_LCTL, pcs_ctrl_reg); | ||
1160 | |||
1161 | ret_val = igb_force_mac_fc(hw); | ||
1162 | if (ret_val) { | ||
1163 | hw_dbg("Error forcing flow control settings\n"); | ||
1164 | return ret_val; | ||
1165 | } | ||
1166 | } | ||
1043 | 1167 | ||
1044 | out: | 1168 | out: |
1045 | return ret_val; | 1169 | return ret_val; |