Commit 2b6b168d authored by Bruce Allan's avatar Bruce Allan Committed by Jeff Kirsher

e1000e: access multiple PHY registers on same page at the same time

Doing a PHY page select can take a long time, relatively speaking. This
can cause a significant delay when updating a number of PHY registers on
the same page by unnecessarily setting the page for each PHY access. For
example when going to Sx, all the PHY wakeup registers (WUC, RAR[], MTA[],
SHRAR[], IP4AT[], IP6AT[], etc.) on 82577/8/9 need to be updated which
takes a long time which can cause issues when suspending.

This patch introduces new PHY ops function pointers to allow callers to
set the page directly and do any number of PHY accesses on that page.
This feature is currently only implemented for 82577, 82578 and 82579
PHYs for both the normally addressed registers as well as the special-
case addressing of the PHY wakeup registers on page 800. For the latter
registers, the existing function for accessing the wakeup registers has
been divided up into three- 1) enable access to the wakeup register page,
2) perform the register access and 3) disable access to the wakeup register
page. The two functions that enable/disable access to the wakeup register
page are necessarily available to the caller so that the caller can restore
the value of the Port Control (a.k.a. Wakeup Enable) register after the
wakeup register accesses are done.

All instances of writing to multiple PHY registers on the same page are
updated to use this new method and to acquire any PHY locking mechanism
before setting the page and performing the register accesses, and release
the locking mechanism afterward.

Some affiliated magic number cleanup is done as well.
Signed-off-by: default avatarBruce Allan <bruce.w.allan@intel.com>
Tested-by: default avatarJeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 400484fa
...@@ -122,20 +122,21 @@ struct e1000_info; ...@@ -122,20 +122,21 @@ struct e1000_info;
#define BM_RCTL_PMCF 0x0040 /* Pass MAC Control Frames */ #define BM_RCTL_PMCF 0x0040 /* Pass MAC Control Frames */
#define BM_RCTL_RFCE 0x0080 /* Rx Flow Control Enable */ #define BM_RCTL_RFCE 0x0080 /* Rx Flow Control Enable */
#define HV_SCC_UPPER PHY_REG(778, 16) /* Single Collision Count */ #define HV_STATS_PAGE 778
#define HV_SCC_LOWER PHY_REG(778, 17) #define HV_SCC_UPPER PHY_REG(HV_STATS_PAGE, 16) /* Single Collision Count */
#define HV_ECOL_UPPER PHY_REG(778, 18) /* Excessive Collision Count */ #define HV_SCC_LOWER PHY_REG(HV_STATS_PAGE, 17)
#define HV_ECOL_LOWER PHY_REG(778, 19) #define HV_ECOL_UPPER PHY_REG(HV_STATS_PAGE, 18) /* Excessive Coll. Count */
#define HV_MCC_UPPER PHY_REG(778, 20) /* Multiple Collision Count */ #define HV_ECOL_LOWER PHY_REG(HV_STATS_PAGE, 19)
#define HV_MCC_LOWER PHY_REG(778, 21) #define HV_MCC_UPPER PHY_REG(HV_STATS_PAGE, 20) /* Multiple Coll. Count */
#define HV_LATECOL_UPPER PHY_REG(778, 23) /* Late Collision Count */ #define HV_MCC_LOWER PHY_REG(HV_STATS_PAGE, 21)
#define HV_LATECOL_LOWER PHY_REG(778, 24) #define HV_LATECOL_UPPER PHY_REG(HV_STATS_PAGE, 23) /* Late Collision Count */
#define HV_COLC_UPPER PHY_REG(778, 25) /* Collision Count */ #define HV_LATECOL_LOWER PHY_REG(HV_STATS_PAGE, 24)
#define HV_COLC_LOWER PHY_REG(778, 26) #define HV_COLC_UPPER PHY_REG(HV_STATS_PAGE, 25) /* Collision Count */
#define HV_DC_UPPER PHY_REG(778, 27) /* Defer Count */ #define HV_COLC_LOWER PHY_REG(HV_STATS_PAGE, 26)
#define HV_DC_LOWER PHY_REG(778, 28) #define HV_DC_UPPER PHY_REG(HV_STATS_PAGE, 27) /* Defer Count */
#define HV_TNCRS_UPPER PHY_REG(778, 29) /* Transmit with no CRS */ #define HV_DC_LOWER PHY_REG(HV_STATS_PAGE, 28)
#define HV_TNCRS_LOWER PHY_REG(778, 30) #define HV_TNCRS_UPPER PHY_REG(HV_STATS_PAGE, 29) /* Transmit with no CRS */
#define HV_TNCRS_LOWER PHY_REG(HV_STATS_PAGE, 30)
#define E1000_FCRTV_PCH 0x05F40 /* PCH Flow Control Refresh Timer Value */ #define E1000_FCRTV_PCH 0x05F40 /* PCH Flow Control Refresh Timer Value */
...@@ -585,6 +586,7 @@ extern s32 e1000e_check_reset_block_generic(struct e1000_hw *hw); ...@@ -585,6 +586,7 @@ extern s32 e1000e_check_reset_block_generic(struct e1000_hw *hw);
extern s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw); extern s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw);
extern s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw); extern s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw);
extern s32 e1000e_get_phy_info_igp(struct e1000_hw *hw); extern s32 e1000e_get_phy_info_igp(struct e1000_hw *hw);
extern s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page);
extern s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); extern s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data);
extern s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, extern s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset,
u16 *data); u16 *data);
...@@ -605,6 +607,10 @@ extern enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id); ...@@ -605,6 +607,10 @@ extern enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id);
extern s32 e1000e_determine_phy_address(struct e1000_hw *hw); extern s32 e1000e_determine_phy_address(struct e1000_hw *hw);
extern s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data); extern s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data);
extern s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data); extern s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data);
extern s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw,
u16 *phy_reg);
extern s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw,
u16 *phy_reg);
extern s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data); extern s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data);
extern s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data); extern s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data);
extern void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); extern void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl);
...@@ -625,9 +631,13 @@ extern s32 e1000e_check_downshift(struct e1000_hw *hw); ...@@ -625,9 +631,13 @@ extern s32 e1000e_check_downshift(struct e1000_hw *hw);
extern s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data); extern s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data);
extern s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, extern s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset,
u16 *data); u16 *data);
extern s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset,
u16 *data);
extern s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data); extern s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data);
extern s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, extern s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset,
u16 data); u16 data);
extern s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset,
u16 data);
extern s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw); extern s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw);
extern s32 e1000_copper_link_setup_82577(struct e1000_hw *hw); extern s32 e1000_copper_link_setup_82577(struct e1000_hw *hw);
extern s32 e1000_check_polarity_82577(struct e1000_hw *hw); extern s32 e1000_check_polarity_82577(struct e1000_hw *hw);
......
...@@ -246,6 +246,7 @@ enum e1e_registers { ...@@ -246,6 +246,7 @@ enum e1e_registers {
#define BM_WUC_ENABLE_REG 17 #define BM_WUC_ENABLE_REG 17
#define BM_WUC_ENABLE_BIT (1 << 2) #define BM_WUC_ENABLE_BIT (1 << 2)
#define BM_WUC_HOST_WU_BIT (1 << 4) #define BM_WUC_HOST_WU_BIT (1 << 4)
#define BM_WUC_ME_WU_BIT (1 << 5)
#define BM_WUC PHY_REG(BM_WUC_PAGE, 1) #define BM_WUC PHY_REG(BM_WUC_PAGE, 1)
#define BM_WUFC PHY_REG(BM_WUC_PAGE, 2) #define BM_WUFC PHY_REG(BM_WUC_PAGE, 2)
...@@ -778,7 +779,21 @@ struct e1000_mac_operations { ...@@ -778,7 +779,21 @@ struct e1000_mac_operations {
s32 (*read_mac_addr)(struct e1000_hw *); s32 (*read_mac_addr)(struct e1000_hw *);
}; };
/* Function pointers for the PHY. */ /*
* When to use various PHY register access functions:
*
* Func Caller
* Function Does Does When to use
* ~~~~~~~~~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* X_reg L,P,A n/a for simple PHY reg accesses
* X_reg_locked P,A L for multiple accesses of different regs
* on different pages
* X_reg_page A L,P for multiple accesses of different regs
* on the same page
*
* Where X=[read|write], L=locking, P=sets page, A=register access
*
*/
struct e1000_phy_operations { struct e1000_phy_operations {
s32 (*acquire)(struct e1000_hw *); s32 (*acquire)(struct e1000_hw *);
s32 (*cfg_on_link_up)(struct e1000_hw *); s32 (*cfg_on_link_up)(struct e1000_hw *);
...@@ -789,14 +804,17 @@ struct e1000_phy_operations { ...@@ -789,14 +804,17 @@ struct e1000_phy_operations {
s32 (*get_cfg_done)(struct e1000_hw *hw); s32 (*get_cfg_done)(struct e1000_hw *hw);
s32 (*get_cable_length)(struct e1000_hw *); s32 (*get_cable_length)(struct e1000_hw *);
s32 (*get_info)(struct e1000_hw *); s32 (*get_info)(struct e1000_hw *);
s32 (*set_page)(struct e1000_hw *, u16);
s32 (*read_reg)(struct e1000_hw *, u32, u16 *); s32 (*read_reg)(struct e1000_hw *, u32, u16 *);
s32 (*read_reg_locked)(struct e1000_hw *, u32, u16 *); s32 (*read_reg_locked)(struct e1000_hw *, u32, u16 *);
s32 (*read_reg_page)(struct e1000_hw *, u32, u16 *);
void (*release)(struct e1000_hw *); void (*release)(struct e1000_hw *);
s32 (*reset)(struct e1000_hw *); s32 (*reset)(struct e1000_hw *);
s32 (*set_d0_lplu_state)(struct e1000_hw *, bool); s32 (*set_d0_lplu_state)(struct e1000_hw *, bool);
s32 (*set_d3_lplu_state)(struct e1000_hw *, bool); s32 (*set_d3_lplu_state)(struct e1000_hw *, bool);
s32 (*write_reg)(struct e1000_hw *, u32, u16); s32 (*write_reg)(struct e1000_hw *, u32, u16);
s32 (*write_reg_locked)(struct e1000_hw *, u32, u16); s32 (*write_reg_locked)(struct e1000_hw *, u32, u16);
s32 (*write_reg_page)(struct e1000_hw *, u32, u16);
void (*power_up)(struct e1000_hw *); void (*power_up)(struct e1000_hw *);
void (*power_down)(struct e1000_hw *); void (*power_down)(struct e1000_hw *);
}; };
......
...@@ -303,12 +303,15 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) ...@@ -303,12 +303,15 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
phy->addr = 1; phy->addr = 1;
phy->reset_delay_us = 100; phy->reset_delay_us = 100;
phy->ops.set_page = e1000_set_page_igp;
phy->ops.read_reg = e1000_read_phy_reg_hv; phy->ops.read_reg = e1000_read_phy_reg_hv;
phy->ops.read_reg_locked = e1000_read_phy_reg_hv_locked; phy->ops.read_reg_locked = e1000_read_phy_reg_hv_locked;
phy->ops.read_reg_page = e1000_read_phy_reg_page_hv;
phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan; phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan;
phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan; phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan;
phy->ops.write_reg = e1000_write_phy_reg_hv; phy->ops.write_reg = e1000_write_phy_reg_hv;
phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked; phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked;
phy->ops.write_reg_page = e1000_write_phy_reg_page_hv;
phy->ops.power_up = e1000_power_up_phy_copper; phy->ops.power_up = e1000_power_up_phy_copper;
phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; phy->ops.power_down = e1000_power_down_phy_copper_ich8lan;
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
...@@ -1409,17 +1412,36 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) ...@@ -1409,17 +1412,36 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw) void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw)
{ {
u32 mac_reg; u32 mac_reg;
u16 i; u16 i, phy_reg = 0;
s32 ret_val;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return;
ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
if (ret_val)
goto release;
/* Copy both RAL/H (rar_entry_count) and SHRAL/H (+4) to PHY */ /* Copy both RAL/H (rar_entry_count) and SHRAL/H (+4) to PHY */
for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) { for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
mac_reg = er32(RAL(i)); mac_reg = er32(RAL(i));
e1e_wphy(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF)); hw->phy.ops.write_reg_page(hw, BM_RAR_L(i),
e1e_wphy(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF)); (u16)(mac_reg & 0xFFFF));
hw->phy.ops.write_reg_page(hw, BM_RAR_M(i),
(u16)((mac_reg >> 16) & 0xFFFF));
mac_reg = er32(RAH(i)); mac_reg = er32(RAH(i));
e1e_wphy(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF)); hw->phy.ops.write_reg_page(hw, BM_RAR_H(i),
e1e_wphy(hw, BM_RAR_CTRL(i), (u16)((mac_reg >> 16) & 0x8000)); (u16)(mac_reg & 0xFFFF));
hw->phy.ops.write_reg_page(hw, BM_RAR_CTRL(i),
(u16)((mac_reg & E1000_RAH_AV)
>> 16));
} }
e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
release:
hw->phy.ops.release(hw);
} }
/** /**
...@@ -3897,6 +3919,7 @@ static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw) ...@@ -3897,6 +3919,7 @@ static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw)
static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
{ {
u16 phy_data; u16 phy_data;
s32 ret_val;
e1000e_clear_hw_cntrs_base(hw); e1000e_clear_hw_cntrs_base(hw);
...@@ -3918,20 +3941,29 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) ...@@ -3918,20 +3941,29 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
if ((hw->phy.type == e1000_phy_82578) || if ((hw->phy.type == e1000_phy_82578) ||
(hw->phy.type == e1000_phy_82579) || (hw->phy.type == e1000_phy_82579) ||
(hw->phy.type == e1000_phy_82577)) { (hw->phy.type == e1000_phy_82577)) {
e1e_rphy(hw, HV_SCC_UPPER, &phy_data); ret_val = hw->phy.ops.acquire(hw);
e1e_rphy(hw, HV_SCC_LOWER, &phy_data); if (ret_val)
e1e_rphy(hw, HV_ECOL_UPPER, &phy_data); return;
e1e_rphy(hw, HV_ECOL_LOWER, &phy_data); ret_val = hw->phy.ops.set_page(hw,
e1e_rphy(hw, HV_MCC_UPPER, &phy_data); HV_STATS_PAGE << IGP_PAGE_SHIFT);
e1e_rphy(hw, HV_MCC_LOWER, &phy_data); if (ret_val)
e1e_rphy(hw, HV_LATECOL_UPPER, &phy_data); goto release;
e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data);
e1e_rphy(hw, HV_COLC_UPPER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data);
e1e_rphy(hw, HV_COLC_LOWER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data);
e1e_rphy(hw, HV_DC_UPPER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data);
e1e_rphy(hw, HV_DC_LOWER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data);
e1e_rphy(hw, HV_TNCRS_UPPER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data);
e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data);
hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data);
hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data);
hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data);
hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data);
hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data);
hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data);
hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data);
release:
hw->phy.ops.release(hw);
} }
} }
......
...@@ -3833,6 +3833,8 @@ static void e1000_update_phy_info(unsigned long data) ...@@ -3833,6 +3833,8 @@ static void e1000_update_phy_info(unsigned long data)
/** /**
* e1000e_update_phy_stats - Update the PHY statistics counters * e1000e_update_phy_stats - Update the PHY statistics counters
* @adapter: board private structure * @adapter: board private structure
*
* Read/clear the upper 16-bit PHY registers and read/accumulate lower
**/ **/
static void e1000e_update_phy_stats(struct e1000_adapter *adapter) static void e1000e_update_phy_stats(struct e1000_adapter *adapter)
{ {
...@@ -3844,89 +3846,61 @@ static void e1000e_update_phy_stats(struct e1000_adapter *adapter) ...@@ -3844,89 +3846,61 @@ static void e1000e_update_phy_stats(struct e1000_adapter *adapter)
if (ret_val) if (ret_val)
return; return;
hw->phy.addr = 1;
#define HV_PHY_STATS_PAGE 778
/* /*
* A page set is expensive so check if already on desired page. * A page set is expensive so check if already on desired page.
* If not, set to the page with the PHY status registers. * If not, set to the page with the PHY status registers.
*/ */
hw->phy.addr = 1;
ret_val = e1000e_read_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, ret_val = e1000e_read_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
&phy_data); &phy_data);
if (ret_val) if (ret_val)
goto release; goto release;
if (phy_data != (HV_PHY_STATS_PAGE << IGP_PAGE_SHIFT)) { if (phy_data != (HV_STATS_PAGE << IGP_PAGE_SHIFT)) {
ret_val = e1000e_write_phy_reg_mdic(hw, ret_val = hw->phy.ops.set_page(hw,
IGP01E1000_PHY_PAGE_SELECT, HV_STATS_PAGE << IGP_PAGE_SHIFT);
(HV_PHY_STATS_PAGE <<
IGP_PAGE_SHIFT));
if (ret_val) if (ret_val)
goto release; goto release;
} }
/* Read/clear the upper 16-bit registers and read/accumulate lower */
/* Single Collision Count */ /* Single Collision Count */
e1000e_read_phy_reg_mdic(hw, HV_SCC_UPPER & MAX_PHY_REG_ADDRESS, hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data);
&phy_data); ret_val = hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data);
ret_val = e1000e_read_phy_reg_mdic(hw,
HV_SCC_LOWER & MAX_PHY_REG_ADDRESS,
&phy_data);
if (!ret_val) if (!ret_val)
adapter->stats.scc += phy_data; adapter->stats.scc += phy_data;
/* Excessive Collision Count */ /* Excessive Collision Count */
e1000e_read_phy_reg_mdic(hw, HV_ECOL_UPPER & MAX_PHY_REG_ADDRESS, hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data);
&phy_data); ret_val = hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data);
ret_val = e1000e_read_phy_reg_mdic(hw,
HV_ECOL_LOWER & MAX_PHY_REG_ADDRESS,
&phy_data);
if (!ret_val) if (!ret_val)
adapter->stats.ecol += phy_data; adapter->stats.ecol += phy_data;
/* Multiple Collision Count */ /* Multiple Collision Count */
e1000e_read_phy_reg_mdic(hw, HV_MCC_UPPER & MAX_PHY_REG_ADDRESS, hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data);
&phy_data); ret_val = hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data);
ret_val = e1000e_read_phy_reg_mdic(hw,
HV_MCC_LOWER & MAX_PHY_REG_ADDRESS,
&phy_data);
if (!ret_val) if (!ret_val)
adapter->stats.mcc += phy_data; adapter->stats.mcc += phy_data;
/* Late Collision Count */ /* Late Collision Count */
e1000e_read_phy_reg_mdic(hw, HV_LATECOL_UPPER & MAX_PHY_REG_ADDRESS, hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data);
&phy_data); ret_val = hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data);
ret_val = e1000e_read_phy_reg_mdic(hw,
HV_LATECOL_LOWER &
MAX_PHY_REG_ADDRESS,
&phy_data);
if (!ret_val) if (!ret_val)
adapter->stats.latecol += phy_data; adapter->stats.latecol += phy_data;
/* Collision Count - also used for adaptive IFS */ /* Collision Count - also used for adaptive IFS */
e1000e_read_phy_reg_mdic(hw, HV_COLC_UPPER & MAX_PHY_REG_ADDRESS, hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data);
&phy_data); ret_val = hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data);
ret_val = e1000e_read_phy_reg_mdic(hw,
HV_COLC_LOWER & MAX_PHY_REG_ADDRESS,
&phy_data);
if (!ret_val) if (!ret_val)
hw->mac.collision_delta = phy_data; hw->mac.collision_delta = phy_data;
/* Defer Count */ /* Defer Count */
e1000e_read_phy_reg_mdic(hw, HV_DC_UPPER & MAX_PHY_REG_ADDRESS, hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data);
&phy_data); ret_val = hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data);
ret_val = e1000e_read_phy_reg_mdic(hw,
HV_DC_LOWER & MAX_PHY_REG_ADDRESS,
&phy_data);
if (!ret_val) if (!ret_val)
adapter->stats.dc += phy_data; adapter->stats.dc += phy_data;
/* Transmit with no CRS */ /* Transmit with no CRS */
e1000e_read_phy_reg_mdic(hw, HV_TNCRS_UPPER & MAX_PHY_REG_ADDRESS, hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data);
&phy_data); ret_val = hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data);
ret_val = e1000e_read_phy_reg_mdic(hw,
HV_TNCRS_LOWER & MAX_PHY_REG_ADDRESS,
&phy_data);
if (!ret_val) if (!ret_val)
adapter->stats.tncrs += phy_data; adapter->stats.tncrs += phy_data;
...@@ -5154,21 +5128,34 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc) ...@@ -5154,21 +5128,34 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc)
{ {
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
u32 i, mac_reg; u32 i, mac_reg;
u16 phy_reg; u16 phy_reg, wuc_enable;
int retval = 0; int retval = 0;
/* copy MAC RARs to PHY RARs */ /* copy MAC RARs to PHY RARs */
e1000_copy_rx_addrs_to_phy_ich8lan(hw); e1000_copy_rx_addrs_to_phy_ich8lan(hw);
/* copy MAC MTA to PHY MTA */ retval = hw->phy.ops.acquire(hw);
if (retval) {
e_err("Could not acquire PHY\n");
return retval;
}
/* Enable access to wakeup registers on and set page to BM_WUC_PAGE */
retval = e1000_enable_phy_wakeup_reg_access_bm(hw, &wuc_enable);
if (retval)
goto out;
/* copy MAC MTA to PHY MTA - only needed for pchlan */
for (i = 0; i < adapter->hw.mac.mta_reg_count; i++) { for (i = 0; i < adapter->hw.mac.mta_reg_count; i++) {
mac_reg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i); mac_reg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i);
e1e_wphy(hw, BM_MTA(i), (u16)(mac_reg & 0xFFFF)); hw->phy.ops.write_reg_page(hw, BM_MTA(i),
e1e_wphy(hw, BM_MTA(i) + 1, (u16)((mac_reg >> 16) & 0xFFFF)); (u16)(mac_reg & 0xFFFF));
hw->phy.ops.write_reg_page(hw, BM_MTA(i) + 1,
(u16)((mac_reg >> 16) & 0xFFFF));
} }
/* configure PHY Rx Control register */ /* configure PHY Rx Control register */
e1e_rphy(&adapter->hw, BM_RCTL, &phy_reg); hw->phy.ops.read_reg_page(&adapter->hw, BM_RCTL, &phy_reg);
mac_reg = er32(RCTL); mac_reg = er32(RCTL);
if (mac_reg & E1000_RCTL_UPE) if (mac_reg & E1000_RCTL_UPE)
phy_reg |= BM_RCTL_UPE; phy_reg |= BM_RCTL_UPE;
...@@ -5185,31 +5172,19 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc) ...@@ -5185,31 +5172,19 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc)
mac_reg = er32(CTRL); mac_reg = er32(CTRL);
if (mac_reg & E1000_CTRL_RFCE) if (mac_reg & E1000_CTRL_RFCE)
phy_reg |= BM_RCTL_RFCE; phy_reg |= BM_RCTL_RFCE;
e1e_wphy(&adapter->hw, BM_RCTL, phy_reg); hw->phy.ops.write_reg_page(&adapter->hw, BM_RCTL, phy_reg);
/* enable PHY wakeup in MAC register */ /* enable PHY wakeup in MAC register */
ew32(WUFC, wufc); ew32(WUFC, wufc);
ew32(WUC, E1000_WUC_PHY_WAKE | E1000_WUC_PME_EN); ew32(WUC, E1000_WUC_PHY_WAKE | E1000_WUC_PME_EN);
/* configure and enable PHY wakeup in PHY registers */ /* configure and enable PHY wakeup in PHY registers */
e1e_wphy(&adapter->hw, BM_WUFC, wufc); hw->phy.ops.write_reg_page(&adapter->hw, BM_WUFC, wufc);
e1e_wphy(&adapter->hw, BM_WUC, E1000_WUC_PME_EN); hw->phy.ops.write_reg_page(&adapter->hw, BM_WUC, E1000_WUC_PME_EN);
/* activate PHY wakeup */ /* activate PHY wakeup */
retval = hw->phy.ops.acquire(hw); wuc_enable |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT;
if (retval) { retval = e1000_disable_phy_wakeup_reg_access_bm(hw, &wuc_enable);
e_err("Could not acquire PHY\n");
return retval;
}
e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
(BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
retval = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg);
if (retval) {
e_err("Could not read PHY page 769\n");
goto out;
}
phy_reg |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT;
retval = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
if (retval) if (retval)
e_err("Could not set PHY Host Wakeup bit\n"); e_err("Could not set PHY Host Wakeup bit\n");
out: out:
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment