Skip to content

Commit ff10e13

Browse files
Carolyn Wybornydavem330
authored andcommitted
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 <[email protected]> Signed-off-by: Carolyn Wyborny <[email protected]> Tested-by: Emil Tantilov <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 116c1ea commit ff10e13

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

drivers/net/e1000e/82571.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@
5252
(ID_LED_DEF1_DEF2))
5353

5454
#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
5559

5660
#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 /* Manageability Operation Mode mask */
5761

@@ -1242,6 +1246,39 @@ static s32 e1000_led_on_82574(struct e1000_hw *hw)
12421246
return 0;
12431247
}
12441248

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+
12451282
/**
12461283
* e1000_setup_link_82571 - Setup flow control and link settings
12471284
* @hw: pointer to the HW structure
@@ -1859,6 +1896,7 @@ struct e1000_info e1000_82574_info = {
18591896
| FLAG_HAS_SMART_POWER_DOWN
18601897
| FLAG_HAS_AMT
18611898
| FLAG_HAS_CTRLEXT_ON_LOAD,
1899+
.flags2 = FLAG2_CHECK_PHY_HANG,
18621900
.pba = 36,
18631901
.max_hw_frame_size = DEFAULT_JUMBO,
18641902
.get_variants = e1000_get_variants_82571,

drivers/net/e1000e/e1000.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ struct e1000_adapter {
397397
struct work_struct print_hang_task;
398398

399399
bool idle_check;
400+
int phy_hang_count;
400401
};
401402

402403
struct e1000_info {
@@ -454,6 +455,7 @@ struct e1000_info {
454455
#define FLAG2_HAS_EEE (1 << 5)
455456
#define FLAG2_DMA_BURST (1 << 6)
456457
#define FLAG2_DISABLE_AIM (1 << 8)
458+
#define FLAG2_CHECK_PHY_HANG (1 << 9)
457459

458460
#define E1000_RX_DESC_PS(R, i) \
459461
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
@@ -631,6 +633,7 @@ extern s32 e1000_get_phy_info_ife(struct e1000_hw *hw);
631633
extern s32 e1000_check_polarity_ife(struct e1000_hw *hw);
632634
extern s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw);
633635
extern s32 e1000_check_polarity_igp(struct e1000_hw *hw);
636+
extern bool e1000_check_phy_82574(struct e1000_hw *hw);
634637

635638
static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw)
636639
{

drivers/net/e1000e/netdev.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4098,6 +4098,25 @@ static void e1000e_enable_receives(struct e1000_adapter *adapter)
40984098
}
40994099
}
41004100

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+
41014120
/**
41024121
* e1000_watchdog - Timer Call-back
41034122
* @data: pointer to adapter cast into an unsigned long
@@ -4333,6 +4352,9 @@ static void e1000_watchdog_task(struct work_struct *work)
43334352
if (e1000e_get_laa_state_82571(hw))
43344353
e1000e_rar_set(hw, adapter->hw.mac.addr, 0);
43354354

4355+
if (adapter->flags2 & FLAG2_CHECK_PHY_HANG)
4356+
e1000e_check_82574_phy_workaround(adapter);
4357+
43364358
/* Reset the timer */
43374359
if (!test_bit(__E1000_DOWN, &adapter->state))
43384360
mod_timer(&adapter->watchdog_timer,

0 commit comments

Comments
 (0)