aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000e
diff options
context:
space:
mode:
authorCarolyn Wyborny <carolyn.wyborny@intel.com>2010-10-27 20:59:53 -0400
committerDavid S. Miller <davem@davemloft.net>2010-10-28 13:18:59 -0400
commitff10e13cd06f3dbe90e9fffc3c2dd2057a116e4b (patch)
tree673e0bf9ad8a7b78cc646e0c90cb390378202f2c /drivers/net/e1000e
parent116c1ea0aa871a2d6554e7fae124fc2880a596c1 (diff)
e1000e: reset PHY after errors detected
Some errors can be induced in the PHY via environmental testing (specifically extreme temperature changes and electro static discharge testing), and in the case of the PHY hanging due to this input, this detects the problem and resets to continue. This issue only applies to 82574 silicon. Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com> Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com> Tested-by: Emil Tantilov <emil.s.tantilov@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/e1000e')
-rw-r--r--drivers/net/e1000e/82571.c38
-rw-r--r--drivers/net/e1000e/e1000.h3
-rw-r--r--drivers/net/e1000e/netdev.c22
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 **/
1255bool 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 }
1278out:
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
402struct e1000_info { 403struct 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);
631extern s32 e1000_check_polarity_ife(struct e1000_hw *hw); 633extern s32 e1000_check_polarity_ife(struct e1000_hw *hw);
632extern s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw); 634extern s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw);
633extern s32 e1000_check_polarity_igp(struct e1000_hw *hw); 635extern s32 e1000_check_polarity_igp(struct e1000_hw *hw);
636extern bool e1000_check_phy_82574(struct e1000_hw *hw);
634 637
635static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw) 638static 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
4101static 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,