diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c')
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c | 160 |
1 files changed, 130 insertions, 30 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index 1077cb2b38db..1073aea5da40 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c | |||
@@ -62,7 +62,6 @@ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, | |||
62 | bool autoneg, | 62 | bool autoneg, |
63 | bool autoneg_wait_to_complete); | 63 | bool autoneg_wait_to_complete); |
64 | static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw); | 64 | static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw); |
65 | static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw); | ||
66 | 65 | ||
67 | static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) | 66 | static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) |
68 | { | 67 | { |
@@ -99,9 +98,8 @@ static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) | |||
99 | static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw) | 98 | static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw) |
100 | { | 99 | { |
101 | s32 ret_val = 0; | 100 | s32 ret_val = 0; |
102 | u32 reg_anlp1 = 0; | ||
103 | u32 i = 0; | ||
104 | u16 list_offset, data_offset, data_value; | 101 | u16 list_offset, data_offset, data_value; |
102 | bool got_lock = false; | ||
105 | 103 | ||
106 | if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) { | 104 | if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) { |
107 | ixgbe_init_mac_link_ops_82599(hw); | 105 | ixgbe_init_mac_link_ops_82599(hw); |
@@ -137,28 +135,36 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw) | |||
137 | usleep_range(hw->eeprom.semaphore_delay * 1000, | 135 | usleep_range(hw->eeprom.semaphore_delay * 1000, |
138 | hw->eeprom.semaphore_delay * 2000); | 136 | hw->eeprom.semaphore_delay * 2000); |
139 | 137 | ||
140 | /* Now restart DSP by setting Restart_AN and clearing LMS */ | 138 | /* Need SW/FW semaphore around AUTOC writes if LESM on, |
141 | IXGBE_WRITE_REG(hw, IXGBE_AUTOC, ((IXGBE_READ_REG(hw, | 139 | * likewise reset_pipeline requires lock as it also writes |
142 | IXGBE_AUTOC) & ~IXGBE_AUTOC_LMS_MASK) | | 140 | * AUTOC. |
143 | IXGBE_AUTOC_AN_RESTART)); | 141 | */ |
144 | 142 | if (ixgbe_verify_lesm_fw_enabled_82599(hw)) { | |
145 | /* Wait for AN to leave state 0 */ | 143 | ret_val = hw->mac.ops.acquire_swfw_sync(hw, |
146 | for (i = 0; i < 10; i++) { | 144 | IXGBE_GSSR_MAC_CSR_SM); |
147 | usleep_range(4000, 8000); | 145 | if (ret_val) |
148 | reg_anlp1 = IXGBE_READ_REG(hw, IXGBE_ANLP1); | 146 | goto setup_sfp_out; |
149 | if (reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK) | 147 | |
150 | break; | 148 | got_lock = true; |
149 | } | ||
150 | |||
151 | /* Restart DSP and set SFI mode */ | ||
152 | IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (IXGBE_READ_REG(hw, | ||
153 | IXGBE_AUTOC) | IXGBE_AUTOC_LMS_10G_SERIAL)); | ||
154 | |||
155 | ret_val = ixgbe_reset_pipeline_82599(hw); | ||
156 | |||
157 | if (got_lock) { | ||
158 | hw->mac.ops.release_swfw_sync(hw, | ||
159 | IXGBE_GSSR_MAC_CSR_SM); | ||
160 | got_lock = false; | ||
151 | } | 161 | } |
152 | if (!(reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK)) { | 162 | |
153 | hw_dbg(hw, "sfp module setup not complete\n"); | 163 | if (ret_val) { |
164 | hw_dbg(hw, " sfp module setup not complete\n"); | ||
154 | ret_val = IXGBE_ERR_SFP_SETUP_NOT_COMPLETE; | 165 | ret_val = IXGBE_ERR_SFP_SETUP_NOT_COMPLETE; |
155 | goto setup_sfp_out; | 166 | goto setup_sfp_out; |
156 | } | 167 | } |
157 | |||
158 | /* Restart DSP by setting Restart_AN and return to SFI mode */ | ||
159 | IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (IXGBE_READ_REG(hw, | ||
160 | IXGBE_AUTOC) | IXGBE_AUTOC_LMS_10G_SERIAL | | ||
161 | IXGBE_AUTOC_AN_RESTART)); | ||
162 | } | 168 | } |
163 | 169 | ||
164 | setup_sfp_out: | 170 | setup_sfp_out: |
@@ -394,14 +400,26 @@ static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, | |||
394 | u32 links_reg; | 400 | u32 links_reg; |
395 | u32 i; | 401 | u32 i; |
396 | s32 status = 0; | 402 | s32 status = 0; |
403 | bool got_lock = false; | ||
404 | |||
405 | if (ixgbe_verify_lesm_fw_enabled_82599(hw)) { | ||
406 | status = hw->mac.ops.acquire_swfw_sync(hw, | ||
407 | IXGBE_GSSR_MAC_CSR_SM); | ||
408 | if (status) | ||
409 | goto out; | ||
410 | |||
411 | got_lock = true; | ||
412 | } | ||
397 | 413 | ||
398 | /* Restart link */ | 414 | /* Restart link */ |
399 | autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); | 415 | ixgbe_reset_pipeline_82599(hw); |
400 | autoc_reg |= IXGBE_AUTOC_AN_RESTART; | 416 | |
401 | IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); | 417 | if (got_lock) |
418 | hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); | ||
402 | 419 | ||
403 | /* Only poll for autoneg to complete if specified to do so */ | 420 | /* Only poll for autoneg to complete if specified to do so */ |
404 | if (autoneg_wait_to_complete) { | 421 | if (autoneg_wait_to_complete) { |
422 | autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); | ||
405 | if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) == | 423 | if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) == |
406 | IXGBE_AUTOC_LMS_KX4_KX_KR || | 424 | IXGBE_AUTOC_LMS_KX4_KX_KR || |
407 | (autoc_reg & IXGBE_AUTOC_LMS_MASK) == | 425 | (autoc_reg & IXGBE_AUTOC_LMS_MASK) == |
@@ -425,6 +443,7 @@ static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, | |||
425 | /* Add delay to filter out noises during initial link setup */ | 443 | /* Add delay to filter out noises during initial link setup */ |
426 | msleep(50); | 444 | msleep(50); |
427 | 445 | ||
446 | out: | ||
428 | return status; | 447 | return status; |
429 | } | 448 | } |
430 | 449 | ||
@@ -779,6 +798,7 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, | |||
779 | u32 links_reg; | 798 | u32 links_reg; |
780 | u32 i; | 799 | u32 i; |
781 | ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN; | 800 | ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN; |
801 | bool got_lock = false; | ||
782 | 802 | ||
783 | /* Check to see if speed passed in is supported. */ | 803 | /* Check to see if speed passed in is supported. */ |
784 | status = hw->mac.ops.get_link_capabilities(hw, &link_capabilities, | 804 | status = hw->mac.ops.get_link_capabilities(hw, &link_capabilities, |
@@ -836,9 +856,26 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, | |||
836 | } | 856 | } |
837 | 857 | ||
838 | if (autoc != start_autoc) { | 858 | if (autoc != start_autoc) { |
859 | /* Need SW/FW semaphore around AUTOC writes if LESM is on, | ||
860 | * likewise reset_pipeline requires us to hold this lock as | ||
861 | * it also writes to AUTOC. | ||
862 | */ | ||
863 | if (ixgbe_verify_lesm_fw_enabled_82599(hw)) { | ||
864 | status = hw->mac.ops.acquire_swfw_sync(hw, | ||
865 | IXGBE_GSSR_MAC_CSR_SM); | ||
866 | if (status != 0) | ||
867 | goto out; | ||
868 | |||
869 | got_lock = true; | ||
870 | } | ||
871 | |||
839 | /* Restart link */ | 872 | /* Restart link */ |
840 | autoc |= IXGBE_AUTOC_AN_RESTART; | ||
841 | IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc); | 873 | IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc); |
874 | ixgbe_reset_pipeline_82599(hw); | ||
875 | |||
876 | if (got_lock) | ||
877 | hw->mac.ops.release_swfw_sync(hw, | ||
878 | IXGBE_GSSR_MAC_CSR_SM); | ||
842 | 879 | ||
843 | /* Only poll for autoneg to complete if specified to do so */ | 880 | /* Only poll for autoneg to complete if specified to do so */ |
844 | if (autoneg_wait_to_complete) { | 881 | if (autoneg_wait_to_complete) { |
@@ -994,9 +1031,28 @@ mac_reset_top: | |||
994 | hw->mac.orig_autoc2 = autoc2; | 1031 | hw->mac.orig_autoc2 = autoc2; |
995 | hw->mac.orig_link_settings_stored = true; | 1032 | hw->mac.orig_link_settings_stored = true; |
996 | } else { | 1033 | } else { |
997 | if (autoc != hw->mac.orig_autoc) | 1034 | if (autoc != hw->mac.orig_autoc) { |
998 | IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (hw->mac.orig_autoc | | 1035 | /* Need SW/FW semaphore around AUTOC writes if LESM is |
999 | IXGBE_AUTOC_AN_RESTART)); | 1036 | * on, likewise reset_pipeline requires us to hold |
1037 | * this lock as it also writes to AUTOC. | ||
1038 | */ | ||
1039 | bool got_lock = false; | ||
1040 | if (ixgbe_verify_lesm_fw_enabled_82599(hw)) { | ||
1041 | status = hw->mac.ops.acquire_swfw_sync(hw, | ||
1042 | IXGBE_GSSR_MAC_CSR_SM); | ||
1043 | if (status) | ||
1044 | goto reset_hw_out; | ||
1045 | |||
1046 | got_lock = true; | ||
1047 | } | ||
1048 | |||
1049 | IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc); | ||
1050 | ixgbe_reset_pipeline_82599(hw); | ||
1051 | |||
1052 | if (got_lock) | ||
1053 | hw->mac.ops.release_swfw_sync(hw, | ||
1054 | IXGBE_GSSR_MAC_CSR_SM); | ||
1055 | } | ||
1000 | 1056 | ||
1001 | if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) != | 1057 | if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) != |
1002 | (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) { | 1058 | (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) { |
@@ -1022,7 +1078,7 @@ mac_reset_top: | |||
1022 | hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr); | 1078 | hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr); |
1023 | 1079 | ||
1024 | /* Add the SAN MAC address to the RAR only if it's a valid address */ | 1080 | /* Add the SAN MAC address to the RAR only if it's a valid address */ |
1025 | if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) { | 1081 | if (is_valid_ether_addr(hw->mac.san_addr)) { |
1026 | hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1, | 1082 | hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1, |
1027 | hw->mac.san_addr, 0, IXGBE_RAH_AV); | 1083 | hw->mac.san_addr, 0, IXGBE_RAH_AV); |
1028 | 1084 | ||
@@ -1983,7 +2039,7 @@ fw_version_out: | |||
1983 | * Returns true if the LESM FW module is present and enabled. Otherwise | 2039 | * Returns true if the LESM FW module is present and enabled. Otherwise |
1984 | * returns false. Smart Speed must be disabled if LESM FW module is enabled. | 2040 | * returns false. Smart Speed must be disabled if LESM FW module is enabled. |
1985 | **/ | 2041 | **/ |
1986 | static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw) | 2042 | bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw) |
1987 | { | 2043 | { |
1988 | bool lesm_enabled = false; | 2044 | bool lesm_enabled = false; |
1989 | u16 fw_offset, fw_lesm_param_offset, fw_lesm_state; | 2045 | u16 fw_offset, fw_lesm_param_offset, fw_lesm_state; |
@@ -2080,6 +2136,50 @@ static s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw, | |||
2080 | return ret_val; | 2136 | return ret_val; |
2081 | } | 2137 | } |
2082 | 2138 | ||
2139 | /** | ||
2140 | * ixgbe_reset_pipeline_82599 - perform pipeline reset | ||
2141 | * | ||
2142 | * @hw: pointer to hardware structure | ||
2143 | * | ||
2144 | * Reset pipeline by asserting Restart_AN together with LMS change to ensure | ||
2145 | * full pipeline reset. Note - We must hold the SW/FW semaphore before writing | ||
2146 | * to AUTOC, so this function assumes the semaphore is held. | ||
2147 | **/ | ||
2148 | s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw) | ||
2149 | { | ||
2150 | s32 i, autoc_reg, ret_val; | ||
2151 | s32 anlp1_reg = 0; | ||
2152 | |||
2153 | autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); | ||
2154 | autoc_reg |= IXGBE_AUTOC_AN_RESTART; | ||
2155 | |||
2156 | /* Write AUTOC register with toggled LMS[2] bit and Restart_AN */ | ||
2157 | IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg ^ IXGBE_AUTOC_LMS_1G_AN); | ||
2158 | |||
2159 | /* Wait for AN to leave state 0 */ | ||
2160 | for (i = 0; i < 10; i++) { | ||
2161 | usleep_range(4000, 8000); | ||
2162 | anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1); | ||
2163 | if (anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK) | ||
2164 | break; | ||
2165 | } | ||
2166 | |||
2167 | if (!(anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)) { | ||
2168 | hw_dbg(hw, "auto negotiation not completed\n"); | ||
2169 | ret_val = IXGBE_ERR_RESET_FAILED; | ||
2170 | goto reset_pipeline_out; | ||
2171 | } | ||
2172 | |||
2173 | ret_val = 0; | ||
2174 | |||
2175 | reset_pipeline_out: | ||
2176 | /* Write AUTOC register with original LMS field and Restart_AN */ | ||
2177 | IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); | ||
2178 | IXGBE_WRITE_FLUSH(hw); | ||
2179 | |||
2180 | return ret_val; | ||
2181 | } | ||
2182 | |||
2083 | static struct ixgbe_mac_operations mac_ops_82599 = { | 2183 | static struct ixgbe_mac_operations mac_ops_82599 = { |
2084 | .init_hw = &ixgbe_init_hw_generic, | 2184 | .init_hw = &ixgbe_init_hw_generic, |
2085 | .reset_hw = &ixgbe_reset_hw_82599, | 2185 | .reset_hw = &ixgbe_reset_hw_82599, |