Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 220936
b: refs/heads/master
c: ff10e13
h: refs/heads/master
v: v3
  • Loading branch information
Carolyn Wyborny authored and David S. Miller committed Oct 28, 2010
1 parent de793e2 commit bc0b341
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 116c1ea0aa871a2d6554e7fae124fc2880a596c1
refs/heads/master: ff10e13cd06f3dbe90e9fffc3c2dd2057a116e4b
38 changes: 38 additions & 0 deletions trunk/drivers/net/e1000e/82571.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
(ID_LED_DEF1_DEF2))

#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
#define E1000_BASE1000T_STATUS 10
#define E1000_IDLE_ERROR_COUNT_MASK 0xFF
#define E1000_RECEIVE_ERROR_COUNTER 21
#define E1000_RECEIVE_ERROR_MAX 0xFFFF

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

Expand Down Expand Up @@ -1242,6 +1246,39 @@ static s32 e1000_led_on_82574(struct e1000_hw *hw)
return 0;
}

/**
* e1000_check_phy_82574 - check 82574 phy hung state
* @hw: pointer to the HW structure
*
* Returns whether phy is hung or not
**/
bool e1000_check_phy_82574(struct e1000_hw *hw)
{
u16 status_1kbt = 0;
u16 receive_errors = 0;
bool phy_hung = false;
s32 ret_val = 0;

/*
* Read PHY Receive Error counter first, if its is max - all F's then
* read the Base1000T status register If both are max then PHY is hung.
*/
ret_val = e1e_rphy(hw, E1000_RECEIVE_ERROR_COUNTER, &receive_errors);

if (ret_val)
goto out;
if (receive_errors == E1000_RECEIVE_ERROR_MAX) {
ret_val = e1e_rphy(hw, E1000_BASE1000T_STATUS, &status_1kbt);
if (ret_val)
goto out;
if ((status_1kbt & E1000_IDLE_ERROR_COUNT_MASK) ==
E1000_IDLE_ERROR_COUNT_MASK)
phy_hung = true;
}
out:
return phy_hung;
}

/**
* e1000_setup_link_82571 - Setup flow control and link settings
* @hw: pointer to the HW structure
Expand Down Expand Up @@ -1859,6 +1896,7 @@ struct e1000_info e1000_82574_info = {
| FLAG_HAS_SMART_POWER_DOWN
| FLAG_HAS_AMT
| FLAG_HAS_CTRLEXT_ON_LOAD,
.flags2 = FLAG2_CHECK_PHY_HANG,
.pba = 36,
.max_hw_frame_size = DEFAULT_JUMBO,
.get_variants = e1000_get_variants_82571,
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/net/e1000e/e1000.h
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ struct e1000_adapter {
struct work_struct print_hang_task;

bool idle_check;
int phy_hang_count;
};

struct e1000_info {
Expand Down Expand Up @@ -454,6 +455,7 @@ struct e1000_info {
#define FLAG2_HAS_EEE (1 << 5)
#define FLAG2_DMA_BURST (1 << 6)
#define FLAG2_DISABLE_AIM (1 << 8)
#define FLAG2_CHECK_PHY_HANG (1 << 9)

#define E1000_RX_DESC_PS(R, i) \
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
Expand Down Expand Up @@ -631,6 +633,7 @@ extern s32 e1000_get_phy_info_ife(struct e1000_hw *hw);
extern s32 e1000_check_polarity_ife(struct e1000_hw *hw);
extern s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw);
extern s32 e1000_check_polarity_igp(struct e1000_hw *hw);
extern bool e1000_check_phy_82574(struct e1000_hw *hw);

static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw)
{
Expand Down
22 changes: 22 additions & 0 deletions trunk/drivers/net/e1000e/netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -4098,6 +4098,25 @@ static void e1000e_enable_receives(struct e1000_adapter *adapter)
}
}

static void e1000e_check_82574_phy_workaround(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;

/*
* With 82574 controllers, PHY needs to be checked periodically
* for hung state and reset, if two calls return true
*/
if (e1000_check_phy_82574(hw))
adapter->phy_hang_count++;
else
adapter->phy_hang_count = 0;

if (adapter->phy_hang_count > 1) {
adapter->phy_hang_count = 0;
schedule_work(&adapter->reset_task);
}
}

/**
* e1000_watchdog - Timer Call-back
* @data: pointer to adapter cast into an unsigned long
Expand Down Expand Up @@ -4333,6 +4352,9 @@ static void e1000_watchdog_task(struct work_struct *work)
if (e1000e_get_laa_state_82571(hw))
e1000e_rar_set(hw, adapter->hw.mac.addr, 0);

if (adapter->flags2 & FLAG2_CHECK_PHY_HANG)
e1000e_check_82574_phy_workaround(adapter);

/* Reset the timer */
if (!test_bit(__E1000_DOWN, &adapter->state))
mod_timer(&adapter->watchdog_timer,
Expand Down

0 comments on commit bc0b341

Please sign in to comment.