diff options
-rw-r--r-- | drivers/net/e1000e/82571.c | 38 | ||||
-rw-r--r-- | drivers/net/e1000e/e1000.h | 3 | ||||
-rw-r--r-- | drivers/net/e1000e/netdev.c | 22 |
3 files changed, 63 insertions, 0 deletions
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index ca663f19d7df..7236f1a53ba0 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c | |||
@@ -52,6 +52,10 @@ | |||
52 | (ID_LED_DEF1_DEF2)) | 52 | (ID_LED_DEF1_DEF2)) |
53 | 53 | ||
54 | #define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000 | 54 | #define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000 |
55 | #define E1000_BASE1000T_STATUS 10 | ||
56 | #define E1000_IDLE_ERROR_COUNT_MASK 0xFF | ||
57 | #define E1000_RECEIVE_ERROR_COUNTER 21 | ||
58 | #define E1000_RECEIVE_ERROR_MAX 0xFFFF | ||
55 | 59 | ||
56 | #define E1000_NVM_INIT_CTRL2_MNGM 0x6000 /* Manageability Operation Mode mask */ | 60 | #define E1000_NVM_INIT_CTRL2_MNGM 0x6000 /* Manageability Operation Mode mask */ |
57 | 61 | ||
@@ -1243,6 +1247,39 @@ static s32 e1000_led_on_82574(struct e1000_hw *hw) | |||
1243 | } | 1247 | } |
1244 | 1248 | ||
1245 | /** | 1249 | /** |
1250 | * e1000_check_phy_82574 - check 82574 phy hung state | ||
1251 | * @hw: pointer to the HW structure | ||
1252 | * | ||
1253 | * Returns whether phy is hung or not | ||
1254 | **/ | ||
1255 | bool e1000_check_phy_82574(struct e1000_hw *hw) | ||
1256 | { | ||
1257 | u16 status_1kbt = 0; | ||
1258 | u16 receive_errors = 0; | ||
1259 | bool phy_hung = false; | ||
1260 | s32 ret_val = 0; | ||
1261 | |||
1262 | /* | ||
1263 | * Read PHY Receive Error counter first, if its is max - all F's then | ||
1264 | * read the Base1000T status register If both are max then PHY is hung. | ||
1265 | */ | ||
1266 | ret_val = e1e_rphy(hw, E1000_RECEIVE_ERROR_COUNTER, &receive_errors); | ||
1267 | |||
1268 | if (ret_val) | ||
1269 | goto out; | ||
1270 | if (receive_errors == E1000_RECEIVE_ERROR_MAX) { | ||
1271 | ret_val = e1e_rphy(hw, E1000_BASE1000T_STATUS, &status_1kbt); | ||
1272 | if (ret_val) | ||
1273 | goto out; | ||
1274 | if ((status_1kbt & E1000_IDLE_ERROR_COUNT_MASK) == | ||
1275 | E1000_IDLE_ERROR_COUNT_MASK) | ||
1276 | phy_hung = true; | ||
1277 | } | ||
1278 | out: | ||
1279 | return phy_hung; | ||
1280 | } | ||
1281 | |||
1282 | /** | ||
1246 | * e1000_setup_link_82571 - Setup flow control and link settings | 1283 | * e1000_setup_link_82571 - Setup flow control and link settings |
1247 | * @hw: pointer to the HW structure | 1284 | * @hw: pointer to the HW structure |
1248 | * | 1285 | * |
@@ -1859,6 +1896,7 @@ struct e1000_info e1000_82574_info = { | |||
1859 | | FLAG_HAS_SMART_POWER_DOWN | 1896 | | FLAG_HAS_SMART_POWER_DOWN |
1860 | | FLAG_HAS_AMT | 1897 | | FLAG_HAS_AMT |
1861 | | FLAG_HAS_CTRLEXT_ON_LOAD, | 1898 | | FLAG_HAS_CTRLEXT_ON_LOAD, |
1899 | .flags2 = FLAG2_CHECK_PHY_HANG, | ||
1862 | .pba = 36, | 1900 | .pba = 36, |
1863 | .max_hw_frame_size = DEFAULT_JUMBO, | 1901 | .max_hw_frame_size = DEFAULT_JUMBO, |
1864 | .get_variants = e1000_get_variants_82571, | 1902 | .get_variants = e1000_get_variants_82571, |
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index cee882dd67bf..fdc67fead4ea 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h | |||
@@ -397,6 +397,7 @@ struct e1000_adapter { | |||
397 | struct work_struct print_hang_task; | 397 | struct work_struct print_hang_task; |
398 | 398 | ||
399 | bool idle_check; | 399 | bool idle_check; |
400 | int phy_hang_count; | ||
400 | }; | 401 | }; |
401 | 402 | ||
402 | struct e1000_info { | 403 | struct e1000_info { |
@@ -454,6 +455,7 @@ struct e1000_info { | |||
454 | #define FLAG2_HAS_EEE (1 << 5) | 455 | #define FLAG2_HAS_EEE (1 << 5) |
455 | #define FLAG2_DMA_BURST (1 << 6) | 456 | #define FLAG2_DMA_BURST (1 << 6) |
456 | #define FLAG2_DISABLE_AIM (1 << 8) | 457 | #define FLAG2_DISABLE_AIM (1 << 8) |
458 | #define FLAG2_CHECK_PHY_HANG (1 << 9) | ||
457 | 459 | ||
458 | #define E1000_RX_DESC_PS(R, i) \ | 460 | #define E1000_RX_DESC_PS(R, i) \ |
459 | (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) | 461 | (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) |
@@ -631,6 +633,7 @@ extern s32 e1000_get_phy_info_ife(struct e1000_hw *hw); | |||
631 | extern s32 e1000_check_polarity_ife(struct e1000_hw *hw); | 633 | extern s32 e1000_check_polarity_ife(struct e1000_hw *hw); |
632 | extern s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw); | 634 | extern s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw); |
633 | extern s32 e1000_check_polarity_igp(struct e1000_hw *hw); | 635 | extern s32 e1000_check_polarity_igp(struct e1000_hw *hw); |
636 | extern bool e1000_check_phy_82574(struct e1000_hw *hw); | ||
634 | 637 | ||
635 | static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw) | 638 | static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw) |
636 | { | 639 | { |
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index ec8cf3f51423..35a9dd4353d7 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
@@ -4098,6 +4098,25 @@ static void e1000e_enable_receives(struct e1000_adapter *adapter) | |||
4098 | } | 4098 | } |
4099 | } | 4099 | } |
4100 | 4100 | ||
4101 | static void e1000e_check_82574_phy_workaround(struct e1000_adapter *adapter) | ||
4102 | { | ||
4103 | struct e1000_hw *hw = &adapter->hw; | ||
4104 | |||
4105 | /* | ||
4106 | * With 82574 controllers, PHY needs to be checked periodically | ||
4107 | * for hung state and reset, if two calls return true | ||
4108 | */ | ||
4109 | if (e1000_check_phy_82574(hw)) | ||
4110 | adapter->phy_hang_count++; | ||
4111 | else | ||
4112 | adapter->phy_hang_count = 0; | ||
4113 | |||
4114 | if (adapter->phy_hang_count > 1) { | ||
4115 | adapter->phy_hang_count = 0; | ||
4116 | schedule_work(&adapter->reset_task); | ||
4117 | } | ||
4118 | } | ||
4119 | |||
4101 | /** | 4120 | /** |
4102 | * e1000_watchdog - Timer Call-back | 4121 | * e1000_watchdog - Timer Call-back |
4103 | * @data: pointer to adapter cast into an unsigned long | 4122 | * @data: pointer to adapter cast into an unsigned long |
@@ -4333,6 +4352,9 @@ link_up: | |||
4333 | if (e1000e_get_laa_state_82571(hw)) | 4352 | if (e1000e_get_laa_state_82571(hw)) |
4334 | e1000e_rar_set(hw, adapter->hw.mac.addr, 0); | 4353 | e1000e_rar_set(hw, adapter->hw.mac.addr, 0); |
4335 | 4354 | ||
4355 | if (adapter->flags2 & FLAG2_CHECK_PHY_HANG) | ||
4356 | e1000e_check_82574_phy_workaround(adapter); | ||
4357 | |||
4336 | /* Reset the timer */ | 4358 | /* Reset the timer */ |
4337 | if (!test_bit(__E1000_DOWN, &adapter->state)) | 4359 | if (!test_bit(__E1000_DOWN, &adapter->state)) |
4338 | mod_timer(&adapter->watchdog_timer, | 4360 | mod_timer(&adapter->watchdog_timer, |