diff options
Diffstat (limited to 'drivers/net/e1000e')
-rw-r--r-- | drivers/net/e1000e/82571.c | 5 | ||||
-rw-r--r-- | drivers/net/e1000e/e1000.h | 51 | ||||
-rw-r--r-- | drivers/net/e1000e/es2lan.c | 8 | ||||
-rw-r--r-- | drivers/net/e1000e/ethtool.c | 1 | ||||
-rw-r--r-- | drivers/net/e1000e/hw.h | 21 | ||||
-rw-r--r-- | drivers/net/e1000e/ich8lan.c | 191 | ||||
-rw-r--r-- | drivers/net/e1000e/lib.c | 4 | ||||
-rw-r--r-- | drivers/net/e1000e/netdev.c | 171 | ||||
-rw-r--r-- | drivers/net/e1000e/phy.c | 352 |
9 files changed, 512 insertions, 292 deletions
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 8295f219243..480f2592f8a 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -431,8 +431,6 @@ static s32 e1000_get_variants_82571(struct e1000_adapter *adapter) adapter->flags &= ~FLAG_HAS_WOL; break; case e1000_82573: - case e1000_82574: - case e1000_82583: if (pdev->device == E1000_DEV_ID_82573L) { adapter->flags |= FLAG_HAS_JUMBO_FRAMES; adapter->max_hw_frame_size = DEFAULT_JUMBO; @@ -2104,10 +2102,11 @@ struct e1000_info e1000_82583_info = { | FLAG_RX_CSUM_ENABLED | FLAG_HAS_SMART_POWER_DOWN | FLAG_HAS_AMT + | FLAG_HAS_JUMBO_FRAMES | FLAG_HAS_CTRLEXT_ON_LOAD, .flags2 = FLAG2_DISABLE_ASPM_L0S, .pba = 32, - .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, + .max_hw_frame_size = DEFAULT_JUMBO, .get_variants = e1000_get_variants_82571, .mac_ops = &e82571_mac_ops, .phy_ops = &e82_phy_ops_bm, diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 9549879e66a..638d175792c 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -104,6 +104,7 @@ struct e1000_info; (((reg) & ~MAX_PHY_REG_ADDRESS) << (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT))) /* PHY Wakeup Registers and defines */ +#define BM_PORT_GEN_CFG PHY_REG(BM_PORT_CTRL_PAGE, 17) #define BM_RCTL PHY_REG(BM_WUC_PAGE, 0) #define BM_WUC PHY_REG(BM_WUC_PAGE, 1) #define BM_WUFC PHY_REG(BM_WUC_PAGE, 2) @@ -122,20 +123,21 @@ struct e1000_info; #define BM_RCTL_PMCF 0x0040 /* Pass MAC Control Frames */ #define BM_RCTL_RFCE 0x0080 /* Rx Flow Control Enable */ -#define HV_SCC_UPPER PHY_REG(778, 16) /* Single Collision Count */ -#define HV_SCC_LOWER PHY_REG(778, 17) -#define HV_ECOL_UPPER PHY_REG(778, 18) /* Excessive Collision Count */ -#define HV_ECOL_LOWER PHY_REG(778, 19) -#define HV_MCC_UPPER PHY_REG(778, 20) /* Multiple Collision Count */ -#define HV_MCC_LOWER PHY_REG(778, 21) -#define HV_LATECOL_UPPER PHY_REG(778, 23) /* Late Collision Count */ -#define HV_LATECOL_LOWER PHY_REG(778, 24) -#define HV_COLC_UPPER PHY_REG(778, 25) /* Collision Count */ -#define HV_COLC_LOWER PHY_REG(778, 26) -#define HV_DC_UPPER PHY_REG(778, 27) /* Defer Count */ -#define HV_DC_LOWER PHY_REG(778, 28) -#define HV_TNCRS_UPPER PHY_REG(778, 29) /* Transmit with no CRS */ -#define HV_TNCRS_LOWER PHY_REG(778, 30) +#define HV_STATS_PAGE 778 +#define HV_SCC_UPPER PHY_REG(HV_STATS_PAGE, 16) /* Single Collision Count */ +#define HV_SCC_LOWER PHY_REG(HV_STATS_PAGE, 17) +#define HV_ECOL_UPPER PHY_REG(HV_STATS_PAGE, 18) /* Excessive Coll. Count */ +#define HV_ECOL_LOWER PHY_REG(HV_STATS_PAGE, 19) +#define HV_MCC_UPPER PHY_REG(HV_STATS_PAGE, 20) /* Multiple Coll. Count */ +#define HV_MCC_LOWER PHY_REG(HV_STATS_PAGE, 21) +#define HV_LATECOL_UPPER PHY_REG(HV_STATS_PAGE, 23) /* Late Collision Count */ +#define HV_LATECOL_LOWER PHY_REG(HV_STATS_PAGE, 24) +#define HV_COLC_UPPER PHY_REG(HV_STATS_PAGE, 25) /* Collision Count */ +#define HV_COLC_LOWER PHY_REG(HV_STATS_PAGE, 26) +#define HV_DC_UPPER PHY_REG(HV_STATS_PAGE, 27) /* Defer Count */ +#define HV_DC_LOWER PHY_REG(HV_STATS_PAGE, 28) +#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 */ @@ -197,11 +199,6 @@ enum e1000_boards { board_pch2lan, }; -struct e1000_queue_stats { - u64 packets; - u64 bytes; -}; - struct e1000_ps_page { struct page *page; u64 dma; /* must be u64 - written to hw */ @@ -255,8 +252,6 @@ struct e1000_ring { int set_itr; struct sk_buff *rx_skb_top; - - struct e1000_queue_stats stats; }; /* PHY register snapshot values */ @@ -339,7 +334,7 @@ struct e1000_adapter { int *work_done, int work_to_do) ____cacheline_aligned_in_smp; void (*alloc_rx_buf) (struct e1000_adapter *adapter, - int cleaned_count); + int cleaned_count, gfp_t gfp); struct e1000_ring *rx_ring; u32 rx_int_delay; @@ -533,7 +528,8 @@ extern void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, bool state); extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); extern void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw); -extern void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw); +extern void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw); +extern void e1000_resume_workarounds_pchlan(struct e1000_hw *hw); extern s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable); extern s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable); extern void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw); @@ -584,6 +580,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_get_cable_length_igp_2(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_locked(struct e1000_hw *hw, u32 offset, u16 *data); @@ -604,6 +601,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_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 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_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); @@ -624,9 +625,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_locked(struct e1000_hw *hw, u32 offset, 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_locked(struct e1000_hw *hw, u32 offset, 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_copper_link_setup_82577(struct e1000_hw *hw); extern s32 e1000_check_polarity_82577(struct e1000_hw *hw); diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c index f4bbeb22f51..c0ecb2d9fdb 100644 --- a/drivers/net/e1000e/es2lan.c +++ b/drivers/net/e1000e/es2lan.c @@ -836,6 +836,7 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw) struct e1000_mac_info *mac = &hw->mac; u32 reg_data; s32 ret_val; + u16 kum_reg_data; u16 i; e1000_initialize_hw_bits_80003es2lan(hw); @@ -861,6 +862,13 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw) /* Setup link and flow control */ ret_val = e1000e_setup_link(hw); + /* Disable IBIST slave mode (far-end loopback) */ + e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, + &kum_reg_data); + kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; + e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, + kum_reg_data); + /* Set the transmit descriptor write-back policy */ reg_data = er32(TXDCTL(0)); reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 859d0d3af6c..cb1a3623253 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -28,6 +28,7 @@ /* ethtool support for e1000 */ +#include <linux/interrupt.h> #include <linux/netdevice.h> #include <linux/ethtool.h> #include <linux/pci.h> diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 6c2fa8327f5..29670397079 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -246,6 +246,7 @@ enum e1e_registers { #define BM_WUC_ENABLE_REG 17 #define BM_WUC_ENABLE_BIT (1 << 2) #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_WUFC PHY_REG(BM_WUC_PAGE, 2) @@ -312,6 +313,7 @@ enum e1e_registers { #define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ #define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */ #define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */ +#define E1000_KMRNCTRLSTA_IBIST_DISABLE 0x0200 /* Kumeran IBIST Disable */ #define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ #define E1000_KMRNCTRLSTA_K1_CONFIG 0x7 #define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002 @@ -777,7 +779,21 @@ struct e1000_mac_operations { 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 { s32 (*acquire)(struct e1000_hw *); s32 (*cfg_on_link_up)(struct e1000_hw *); @@ -788,14 +804,17 @@ struct e1000_phy_operations { s32 (*get_cfg_done)(struct e1000_hw *hw); s32 (*get_cable_length)(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_locked)(struct e1000_hw *, u32, u16 *); + s32 (*read_reg_page)(struct e1000_hw *, u32, u16 *); void (*release)(struct e1000_hw *); s32 (*reset)(struct e1000_hw *); s32 (*set_d0_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_locked)(struct e1000_hw *, u32, u16); + s32 (*write_reg_page)(struct e1000_hw *, u32, u16); void (*power_up)(struct e1000_hw *); void (*power_down)(struct e1000_hw *); }; diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 3369d1f6a39..c1752124f3c 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -275,6 +275,19 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val) #define ew16flash(reg,val) __ew16flash(hw, (reg), (val)) #define ew32flash(reg,val) __ew32flash(hw, (reg), (val)) +static void e1000_toggle_lanphypc_value_ich8lan(struct e1000_hw *hw) +{ + u32 ctrl; + + ctrl = er32(CTRL); + ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE; + ctrl &= ~E1000_CTRL_LANPHYPC_VALUE; + ew32(CTRL, ctrl); + udelay(10); + ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE; + ew32(CTRL, ctrl); +} + /** * e1000_init_phy_params_pchlan - Initialize PHY function pointers * @hw: pointer to the HW structure @@ -284,18 +297,21 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val) static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; - u32 ctrl, fwsm; + u32 fwsm; s32 ret_val = 0; phy->addr = 1; 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_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_d3_lplu_state = e1000_set_lplu_state_pchlan; phy->ops.write_reg = e1000_write_phy_reg_hv; 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_down = e1000_power_down_phy_copper_ich8lan; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; @@ -308,13 +324,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) */ fwsm = er32(FWSM); if (!(fwsm & E1000_ICH_FWSM_FW_VALID) && !e1000_check_reset_block(hw)) { - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE; - ctrl &= ~E1000_CTRL_LANPHYPC_VALUE; - ew32(CTRL, ctrl); - udelay(10); - ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE; - ew32(CTRL, ctrl); + e1000_toggle_lanphypc_value_ich8lan(hw); msleep(50); /* @@ -882,8 +892,13 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw) u32 extcnf_ctrl; extcnf_ctrl = er32(EXTCNF_CTRL); - extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; - ew32(EXTCNF_CTRL, extcnf_ctrl); + + if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) { + extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; + ew32(EXTCNF_CTRL, extcnf_ctrl); + } else { + e_dbg("Semaphore unexpectedly released by sw/fw/hw\n"); + } mutex_unlock(&swflag_mutex); } @@ -1376,14 +1391,11 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; - ret_val = hw->phy.ops.read_reg_locked(hw, - PHY_REG(BM_PORT_CTRL_PAGE, 17), - &phy_data); + ret_val = hw->phy.ops.read_reg_locked(hw, BM_PORT_GEN_CFG, &phy_data); if (ret_val) goto release; - ret_val = hw->phy.ops.write_reg_locked(hw, - PHY_REG(BM_PORT_CTRL_PAGE, 17), - phy_data & 0x00FF); + ret_val = hw->phy.ops.write_reg_locked(hw, BM_PORT_GEN_CFG, + phy_data & 0x00FF); release: hw->phy.ops.release(hw); out: @@ -1397,17 +1409,36 @@ out: void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw) { 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 */ for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) { mac_reg = er32(RAL(i)); - e1e_wphy(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF)); - e1e_wphy(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF)); + hw->phy.ops.write_reg_page(hw, BM_RAR_L(i), + (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)); - e1e_wphy(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF)); - e1e_wphy(hw, BM_RAR_CTRL(i), (u16)((mac_reg >> 16) & 0x8000)); + hw->phy.ops.write_reg_page(hw, BM_RAR_H(i), + (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); } /** @@ -1726,9 +1757,12 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) break; } - /* Dummy read to clear the phy wakeup bit after lcd reset */ - if (hw->mac.type >= e1000_pchlan) - e1e_rphy(hw, BM_WUC, ®); + /* Clear the host wakeup bit after lcd reset */ + if (hw->mac.type >= e1000_pchlan) { + e1e_rphy(hw, BM_PORT_GEN_CFG, ®); + reg &= ~BM_WUC_HOST_WU_BIT; + e1e_wphy(hw, BM_PORT_GEN_CFG, reg); + } /* Configure the LCD with the extended configuration region in NVM */ ret_val = e1000_sw_lcd_config_ich8lan(hw); @@ -3059,7 +3093,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) msleep(20); if (!ret_val) - e1000_release_swflag_ich8lan(hw); + mutex_unlock(&swflag_mutex); if (ctrl & E1000_CTRL_PHY_RST) { ret_val = hw->phy.ops.get_cfg_done(hw); @@ -3127,11 +3161,13 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) /* * The 82578 Rx buffer will stall if wakeup is enabled in host and - * the ME. Reading the BM_WUC register will clear the host wakeup bit. + * the ME. Disable wakeup by clearing the host wakeup bit. * Reset the phy after disabling host wakeup to reset the Rx buffer. */ if (hw->phy.type == e1000_phy_82578) { - e1e_rphy(hw, BM_WUC, &i); + e1e_rphy(hw, BM_PORT_GEN_CFG, &i); + i &= ~BM_WUC_HOST_WU_BIT; + e1e_wphy(hw, BM_PORT_GEN_CFG, i); ret_val = e1000_phy_hw_reset_ich8lan(hw); if (ret_val) return ret_val; @@ -3586,17 +3622,16 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw) } /** - * e1000e_disable_gig_wol_ich8lan - disable gig during WoL + * e1000_suspend_workarounds_ich8lan - workarounds needed during S0->Sx * @hw: pointer to the HW structure * * During S0 to Sx transition, it is possible the link remains at gig * instead of negotiating to a lower speed. Before going to Sx, set * 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation - * to a lower speed. - * - * Should only be called for applicable parts. + * to a lower speed. For PCH and newer parts, the OEM bits PHY register + * (LED, GbE disable and LPLU configurations) also needs to be written. **/ -void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw) +void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) { u32 phy_ctrl; s32 ret_val; @@ -3616,6 +3651,60 @@ void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw) } /** + * e1000_resume_workarounds_pchlan - workarounds needed during Sx->S0 + * @hw: pointer to the HW structure + * + * During Sx to S0 transitions on non-managed devices or managed devices + * on which PHY resets are not blocked, if the PHY registers cannot be + * accessed properly by the s/w toggle the LANPHYPC value to power cycle + * the PHY. + **/ +void e1000_resume_workarounds_pchlan(struct e1000_hw *hw) +{ + u32 fwsm; + + if (hw->mac.type != e1000_pch2lan) + return; + + fwsm = er32(FWSM); + if (!(fwsm & E1000_ICH_FWSM_FW_VALID) || !e1000_check_reset_block(hw)) { + u16 phy_id1, phy_id2; + s32 ret_val; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) { + e_dbg("Failed to acquire PHY semaphore in resume\n"); + return; + } + + /* Test access to the PHY registers by reading the ID regs */ + ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_id1); + if (ret_val) + goto release; + ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_id2); + if (ret_val) + goto release; + + if (hw->phy.id == ((u32)(phy_id1 << 16) | + (u32)(phy_id2 & PHY_REVISION_MASK))) + goto release; + + e1000_toggle_lanphypc_value_ich8lan(hw); + + hw->phy.ops.release(hw); + msleep(50); + e1000_phy_hw_reset(hw); + msleep(50); + return; + } + +release: + hw->phy.ops.release(hw); + + return; +} + +/** * e1000_cleanup_led_ich8lan - Restore the default LED operation * @hw: pointer to the HW structure * @@ -3832,6 +3921,7 @@ static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw) static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) { u16 phy_data; + s32 ret_val; e1000e_clear_hw_cntrs_base(hw); @@ -3853,20 +3943,29 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) if ((hw->phy.type == e1000_phy_82578) || (hw->phy.type == e1000_phy_82579) || (hw->phy.type == e1000_phy_82577)) { - e1e_rphy(hw, HV_SCC_UPPER, &phy_data); - e1e_rphy(hw, HV_SCC_LOWER, &phy_data); - e1e_rphy(hw, HV_ECOL_UPPER, &phy_data); - e1e_rphy(hw, HV_ECOL_LOWER, &phy_data); - e1e_rphy(hw, HV_MCC_UPPER, &phy_data); - e1e_rphy(hw, HV_MCC_LOWER, &phy_data); - e1e_rphy(hw, HV_LATECOL_UPPER, &phy_data); - e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data); - e1e_rphy(hw, HV_COLC_UPPER, &phy_data); - e1e_rphy(hw, HV_COLC_LOWER, &phy_data); - e1e_rphy(hw, HV_DC_UPPER, &phy_data); - e1e_rphy(hw, HV_DC_LOWER, &phy_data); - e1e_rphy(hw, HV_TNCRS_UPPER, &phy_data); - e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data); + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return; + ret_val = hw->phy.ops.set_page(hw, + HV_STATS_PAGE << IGP_PAGE_SHIFT); + if (ret_val) + goto release; + hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data); + hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data); + hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data); + hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data); + hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data); + hw->phy.ops.read_reg_page(hw, HV_MCC_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); } } diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index dd8ab05b559..65580b40594 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -56,7 +56,7 @@ s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw) struct e1000_adapter *adapter = hw->adapter; u16 pcie_link_status, cap_offset; - cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP); + cap_offset = adapter->pdev->pcie_cap; if (!cap_offset) { bus->width = e1000_bus_width_unknown; } else { @@ -220,7 +220,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) } /* if multicast bit is set, the alternate address will not be used */ - if (alt_mac_addr[0] & 0x01) { + if (is_multicast_ether_addr(alt_mac_addr)) { e_dbg("Ignoring Alternate Mac Address with MC bit set\n"); goto out; } diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 3310c3d477d..4353ad56cf1 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -31,6 +31,7 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/pci.h> #include <linux/vmalloc.h> #include <linux/pagemap.h> @@ -53,9 +54,9 @@ #include "e1000.h" -#define DRV_EXTRAVERSION "-k2" +#define DRV_EXTRAVERSION "-k" -#define DRV_VERSION "1.3.10" DRV_EXTRAVERSION +#define DRV_VERSION "1.3.16" DRV_EXTRAVERSION char e1000e_driver_name[] = "e1000e"; const char e1000e_driver_version[] = DRV_VERSION; @@ -522,7 +523,7 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err, * @adapter: address of board private structure **/ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, - int cleaned_count) + int cleaned_count, gfp_t gfp) { struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; @@ -543,7 +544,7 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, goto map_skb; } - skb = netdev_alloc_skb_ip_align(netdev, bufsz); + skb = __netdev_alloc_skb_ip_align(netdev, bufsz, gfp); if (!skb) { /* Better luck next round */ adapter->alloc_rx_buff_failed++; @@ -588,7 +589,7 @@ map_skb: * @adapter: address of board private structure **/ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, - int cleaned_count) + int cleaned_count, gfp_t gfp) { struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; @@ -614,7 +615,7 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, continue; } if (!ps_page->page) { - ps_page->page = alloc_page(GFP_ATOMIC); + ps_page->page = alloc_page(gfp); if (!ps_page->page) { adapter->alloc_rx_buff_failed++; goto no_buffers; @@ -640,8 +641,9 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, cpu_to_le64(ps_page->dma); } - skb = netdev_alloc_skb_ip_align(netdev, - adapter->rx_ps_bsize0); + skb = __netdev_alloc_skb_ip_align(netdev, + adapter->rx_ps_bsize0, + gfp); if (!skb) { adapter->alloc_rx_buff_failed++; @@ -691,7 +693,7 @@ no_buffers: **/ static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter, - int cleaned_count) + int cleaned_count, gfp_t gfp) { struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; @@ -712,7 +714,7 @@ static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter, goto check_page; } - skb = netdev_alloc_skb_ip_align(netdev, bufsz); + skb = __netdev_alloc_skb_ip_align(netdev, bufsz, gfp); if (unlikely(!skb)) { /* Better luck next round */ adapter->alloc_rx_buff_failed++; @@ -723,7 +725,7 @@ static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter, check_page: /* allocate a new page if necessary */ if (!buffer_info->page) { - buffer_info->page = alloc_page(GFP_ATOMIC); + buffer_info->page = alloc_page(gfp); if (unlikely(!buffer_info->page)) { adapter->alloc_rx_buff_failed++; break; @@ -887,7 +889,8 @@ next_desc: /* return some buffers to hardware, one at a time is too slow */ if (cleaned_count >= E1000_RX_BUFFER_WRITE) { - adapter->alloc_rx_buf(adapter, cleaned_count); + adapter->alloc_rx_buf(adapter, cleaned_count, + GFP_ATOMIC); cleaned_count = 0; } @@ -899,7 +902,7 @@ next_desc: cleaned_count = e1000_desc_unused(rx_ring); if (cleaned_count) - adapter->alloc_rx_buf(adapter, cleaned_count); + adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC); adapter->total_rx_bytes += total_rx_bytes; adapter->total_rx_packets += total_rx_packets; @@ -1229,7 +1232,8 @@ next_desc: /* return some buffers to hardware, one at a time is too slow */ if (cleaned_count >= E1000_RX_BUFFER_WRITE) { - adapter->alloc_rx_buf(adapter, cleaned_count); + adapter->alloc_rx_buf(adapter, cleaned_count, + GFP_ATOMIC); cleaned_count = 0; } @@ -1243,7 +1247,7 @@ next_desc: cleaned_count = e1000_desc_unused(rx_ring); if (cleaned_count) - adapter->alloc_rx_buf(adapter, cleaned_count); + adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC); adapter->total_rx_bytes += total_rx_bytes; adapter->total_rx_packets += total_rx_packets; @@ -1410,7 +1414,8 @@ next_desc: /* return some buffers to hardware, one at a time is too slow */ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { - adapter->alloc_rx_buf(adapter, cleaned_count); + adapter->alloc_rx_buf(adapter, cleaned_count, + GFP_ATOMIC); cleaned_count = 0; } @@ -1422,7 +1427,7 @@ next_desc: cleaned_count = e1000_desc_unused(rx_ring); if (cleaned_count) - adapter->alloc_rx_buf(adapter, cleaned_count); + adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC); adapter->total_rx_bytes += total_rx_bytes; adapter->total_rx_packets += total_rx_packets; @@ -3104,7 +3109,8 @@ static void e1000_configure(struct e1000_adapter *adapter) e1000_configure_tx(adapter); e1000_setup_rctl(adapter); e1000_configure_rx(adapter); - adapter->alloc_rx_buf(adapter, e1000_desc_unused(adapter->rx_ring)); + adapter->alloc_rx_buf(adapter, e1000_desc_unused(adapter->rx_ring), + GFP_KERNEL); } /** @@ -3346,7 +3352,7 @@ int e1000e_up(struct e1000_adapter *adapter) e1000_configure_msix(adapter); e1000_irq_enable(adapter); - netif_wake_queue(adapter->netdev); + netif_start_queue(adapter->netdev); /* fire a link change interrupt to start the watchdog */ if (adapter->msix_entries) @@ -3413,17 +3419,16 @@ void e1000e_down(struct e1000_adapter *adapter) e1000e_update_stats(adapter); spin_unlock(&adapter->stats64_lock); + e1000e_flush_descriptors(adapter); + e1000_clean_tx_ring(adapter); + e1000_clean_rx_ring(adapter); + adapter->link_speed = 0; adapter->link_duplex = 0; if (!pci_channel_offline(adapter->pdev)) e1000e_reset(adapter); - e1000e_flush_descriptors(adapter); - - e1000_clean_tx_ring(adapter); - e1000_clean_rx_ring(adapter); - /* * TODO: for power management, we could drop the link and * pci_disable_device here. @@ -3833,6 +3838,8 @@ static void e1000_update_phy_info(unsigned long data) /** * e1000e_update_phy_stats - Update the PHY statistics counters * @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) { @@ -3844,89 +3851,61 @@ static void e1000e_update_phy_stats(struct e1000_adapter *adapter) if (ret_val) return; - hw->phy.addr = 1; - -#define HV_PHY_STATS_PAGE 778 /* * A page set is expensive so check if already on desired page. * 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, &phy_data); if (ret_val) goto release; - if (phy_data != (HV_PHY_STATS_PAGE << IGP_PAGE_SHIFT)) { - ret_val = e1000e_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (HV_PHY_STATS_PAGE << - IGP_PAGE_SHIFT)); + if (phy_data != (HV_STATS_PAGE << IGP_PAGE_SHIFT)) { + ret_val = hw->phy.ops.set_page(hw, + HV_STATS_PAGE << IGP_PAGE_SHIFT); if (ret_val) goto release; } - /* Read/clear the upper 16-bit registers and read/accumulate lower */ - /* Single Collision Count */ - e1000e_read_phy_reg_mdic(hw, HV_SCC_UPPER & MAX_PHY_REG_ADDRESS, - &phy_data); - ret_val = e1000e_read_phy_reg_mdic(hw, - HV_SCC_LOWER & MAX_PHY_REG_ADDRESS, - &phy_data); + hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data); + ret_val = hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data); if (!ret_val) adapter->stats.scc += phy_data; /* Excessive Collision Count */ - e1000e_read_phy_reg_mdic(hw, HV_ECOL_UPPER & MAX_PHY_REG_ADDRESS, - &phy_data); - ret_val = e1000e_read_phy_reg_mdic(hw, - HV_ECOL_LOWER & MAX_PHY_REG_ADDRESS, - &phy_data); + hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data); + ret_val = hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data); if (!ret_val) adapter->stats.ecol += phy_data; /* Multiple Collision Count */ - e1000e_read_phy_reg_mdic(hw, HV_MCC_UPPER & MAX_PHY_REG_ADDRESS, - &phy_data); - ret_val = e1000e_read_phy_reg_mdic(hw, - HV_MCC_LOWER & MAX_PHY_REG_ADDRESS, - &phy_data); + hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data); + ret_val = hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data); if (!ret_val) adapter->stats.mcc += phy_data; /* Late Collision Count */ - e1000e_read_phy_reg_mdic(hw, HV_LATECOL_UPPER & MAX_PHY_REG_ADDRESS, - &phy_data); - ret_val = e1000e_read_phy_reg_mdic(hw, - HV_LATECOL_LOWER & - MAX_PHY_REG_ADDRESS, - &phy_data); + hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data); + ret_val = hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data); if (!ret_val) adapter->stats.latecol += phy_data; /* Collision Count - also used for adaptive IFS */ - e1000e_read_phy_reg_mdic(hw, HV_COLC_UPPER & MAX_PHY_REG_ADDRESS, - &phy_data); - ret_val = e1000e_read_phy_reg_mdic(hw, - HV_COLC_LOWER & MAX_PHY_REG_ADDRESS, - &phy_data); + hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data); + ret_val = hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data); if (!ret_val) hw->mac.collision_delta = phy_data; /* Defer Count */ - e1000e_read_phy_reg_mdic(hw, HV_DC_UPPER & MAX_PHY_REG_ADDRESS, - &phy_data); - ret_val = e1000e_read_phy_reg_mdic(hw, - HV_DC_LOWER & MAX_PHY_REG_ADDRESS, - &phy_data); + hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data); + ret_val = hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data); if (!ret_val) adapter->stats.dc += phy_data; /* Transmit with no CRS */ - e1000e_read_phy_reg_mdic(hw, HV_TNCRS_UPPER & MAX_PHY_REG_ADDRESS, - &phy_data); - ret_val = e1000e_read_phy_reg_mdic(hw, - HV_TNCRS_LOWER & MAX_PHY_REG_ADDRESS, - &phy_data); + hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data); + ret_val = hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data); if (!ret_val) adapter->stats.tncrs += phy_data; @@ -5154,21 +5133,34 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc) { struct e1000_hw *hw = &adapter->hw; u32 i, mac_reg; - u16 phy_reg; + u16 phy_reg, wuc_enable; int retval = 0; /* copy MAC RARs to PHY RARs */ 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++) { mac_reg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i); - e1e_wphy(hw, BM_MTA(i), (u16)(mac_reg & 0xFFFF)); - e1e_wphy(hw, BM_MTA(i) + 1, (u16)((mac_reg >> 16) & 0xFFFF)); + hw->phy.ops.write_reg_page(hw, BM_MTA(i), + (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 */ - e1e_rphy(&adapter->hw, BM_RCTL, &phy_reg); + hw->phy.ops.read_reg_page(&adapter->hw, BM_RCTL, &phy_reg); mac_reg = er32(RCTL); if (mac_reg & E1000_RCTL_UPE) phy_reg |= BM_RCTL_UPE; @@ -5185,31 +5177,19 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc) mac_reg = er32(CTRL); if (mac_reg & E1000_CTRL_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 */ ew32(WUFC, wufc); ew32(WUC, E1000_WUC_PHY_WAKE | E1000_WUC_PME_EN); /* configure and enable PHY wakeup in PHY registers */ - e1e_wphy(&adapter->hw, BM_WUFC, wufc); - e1e_wphy(&adapter->hw, BM_WUC, E1000_WUC_PME_EN); + hw->phy.ops.write_reg_page(&adapter->hw, BM_WUFC, wufc); + hw->phy.ops.write_reg_page(&adapter->hw, BM_WUC, E1000_WUC_PME_EN); /* activate PHY wakeup */ - retval = hw->phy.ops.acquire(hw); - if (retval) { - 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); + wuc_enable |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT; + retval = e1000_disable_phy_wakeup_reg_access_bm(hw, &wuc_enable); if (retval) e_err("Could not set PHY Host Wakeup bit\n"); out: @@ -5277,7 +5257,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake, } if (adapter->flags & FLAG_IS_ICH) - e1000e_disable_gig_wol_ich8lan(&adapter->hw); + e1000_suspend_workarounds_ich8lan(&adapter->hw); /* Allow time for pending master requests to run */ e1000e_disable_pcie_master(&adapter->hw); @@ -5343,7 +5323,7 @@ static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep, */ if (adapter->flags & FLAG_IS_QUAD_PORT) { struct pci_dev *us_dev = pdev->bus->self; - int pos = pci_find_capability(us_dev, PCI_CAP_ID_EXP); + int pos = pci_pcie_cap(us_dev); u16 devctl; pci_read_config_word(us_dev, pos + PCI_EXP_DEVCTL, &devctl); @@ -5428,6 +5408,9 @@ static int __e1000_resume(struct pci_dev *pdev) return err; } + if (hw->mac.type == e1000_pch2lan) + e1000_resume_workarounds_pchlan(&adapter->hw); + e1000e_power_up_phy(adapter); /* report the system wakeup cause from S3/S4 */ diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 484774c13c2..2a6ee13285b 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -36,7 +36,7 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active); static s32 e1000_wait_autoneg(struct e1000_hw *hw); static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg); static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, - u16 *data, bool read); + u16 *data, bool read, bool page_set); static u32 e1000_get_phy_addr_for_hv_page(u32 page); static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, u16 *data, bool read); @@ -348,6 +348,24 @@ s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) } /** + * e1000_set_page_igp - Set page as on IGP-like PHY(s) + * @hw: pointer to the HW structure + * @page: page to set (shifted left when necessary) + * + * Sets PHY page required for PHY register access. Assumes semaphore is + * already acquired. Note, this function sets phy.addr to 1 so the caller + * must set it appropriately (if necessary) after this function returns. + **/ +s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page) +{ + e_dbg("Setting page 0x%x\n", page); + + hw->phy.addr = 1; + + return e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, page); +} + +/** * __e1000e_read_phy_reg_igp - Read igp PHY register * @hw: pointer to the HW structure * @offset: register offset to be read @@ -2418,7 +2436,7 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, - false); + false, false); goto out; } @@ -2477,7 +2495,7 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, - true); + true, false); goto out; } @@ -2535,7 +2553,7 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data) /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, - true); + true, false); goto out; } @@ -2579,7 +2597,7 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, - false); + false, false); goto out; } @@ -2603,104 +2621,163 @@ out: } /** - * e1000_access_phy_wakeup_reg_bm - Read BM PHY wakeup register + * e1000_enable_phy_wakeup_reg_access_bm - enable access to BM wakeup registers * @hw: pointer to the HW structure - * @offset: register offset to be read or written - * @data: pointer to the data to read or write - * @read: determines if operation is read or write + * @phy_reg: pointer to store original contents of BM_WUC_ENABLE_REG * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired - * semaphores before exiting. Note that procedure to read the wakeup - * registers are different. It works as such: - * 1) Set page 769, register 17, bit 2 = 1 - * 2) Set page to 800 for host (801 if we were manageability) - * 3) Write the address using the address opcode (0x11) - * 4) Read or write the data using the data opcode (0x12) - * 5) Restore 769_17.2 to its original value - * - * Assumes semaphore already acquired. + * Assumes semaphore already acquired and phy_reg points to a valid memory + * address to store contents of the BM_WUC_ENABLE_REG register. **/ -static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, - u16 *data, bool read) +s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) { s32 ret_val; - u16 reg = BM_PHY_REG_NUM(offset); - u16 phy_reg = 0; + u16 temp; - /* Gig must be disabled for MDIO accesses to page 800 */ - if ((hw->mac.type == e1000_pchlan) && - (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE))) - e_dbg("Attempting to access page 800 while gig enabled.\n"); - - /* All operations in this function are phy address 1 */ + /* All page select, port ctrl and wakeup registers use phy address 1 */ hw->phy.addr = 1; - /* Set page 769 */ - e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, - (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); + /* Select Port Control Registers page */ + ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); + if (ret_val) { + e_dbg("Could not set Port Control page\n"); + goto out; + } - ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg); + ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); if (ret_val) { - e_dbg("Could not read PHY page 769\n"); + e_dbg("Could not read PHY register %d.%d\n", + BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG); goto out; } - /* First clear bit 4 to avoid a power state change */ - phy_reg &= ~(BM_WUC_HOST_WU_BIT); - ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); + /* + * Enable both PHY wakeup mode and Wakeup register page writes. + * Prevent a power state change by disabling ME and Host PHY wakeup. + */ + temp = *phy_reg; + temp |= BM_WUC_ENABLE_BIT; + temp &= ~(BM_WUC_ME_WU_BIT | BM_WUC_HOST_WU_BIT); + + ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, temp); if (ret_val) { - e_dbg("Could not clear PHY page 769 bit 4\n"); + e_dbg("Could not write PHY register %d.%d\n", + BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG); goto out; } - /* Write bit 2 = 1, and clear bit 4 to 769_17 */ - ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, - phy_reg | BM_WUC_ENABLE_BIT); + /* Select Host Wakeup Registers page */ + ret_val = e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT)); + + /* caller now able to write registers on the Wakeup registers page */ +out: + return ret_val; +} + +/** + * e1000_disable_phy_wakeup_reg_access_bm - disable access to BM wakeup regs + * @hw: pointer to the HW structure + * @phy_reg: pointer to original contents of BM_WUC_ENABLE_REG + * + * Restore BM_WUC_ENABLE_REG to its original value. + * + * Assumes semaphore already acquired and *phy_reg is the contents of the + * BM_WUC_ENABLE_REG before register(s) on BM_WUC_PAGE were accessed by + * caller. + **/ +s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) +{ + s32 ret_val = 0; + + /* Select Port Control Registers page */ + ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); if (ret_val) { - e_dbg("Could not write PHY page 769 bit 2\n"); + e_dbg("Could not set Port Control page\n"); goto out; } - /* Select page 800 */ - ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, - (BM_WUC_PAGE << IGP_PAGE_SHIFT)); + /* Restore 769.17 to its original value */ + ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, *phy_reg); + if (ret_val) + e_dbg("Could not restore PHY register %d.%d\n", + BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG); +out: + return ret_val; +} - /* Write the page 800 offset value using opcode 0x11 */ +/** + * e1000_access_phy_wakeup_reg_bm - Read/write BM PHY wakeup register + * @hw: pointer to the HW structure + * @offset: register offset to be read or written + * @data: pointer to the data to read or write + * @read: determines if operation is read or write + * @page_set: BM_WUC_PAGE already set and access enabled + * + * Read the PHY register at offset and store the retrieved information in + * data, or write data to PHY register at offset. Note the procedure to + * access the PHY wakeup registers is different than reading the other PHY + * registers. It works as such: + * 1) Set 769.17.2 (page 769, register 17, bit 2) = 1 + * 2) Set page to 800 for host (801 if we were manageability) + * 3) Write the address using the address opcode (0x11) + * 4) Read or write the data using the data opcode (0x12) + * 5) Restore 769.17.2 to its original value + * + * Steps 1 and 2 are done by e1000_enable_phy_wakeup_reg_access_bm() and + * step 5 is done by e1000_disable_phy_wakeup_reg_access_bm(). + * + * Assumes semaphore is already acquired. When page_set==true, assumes + * the PHY page is set to BM_WUC_PAGE (i.e. a function in the call stack + * is responsible for calls to e1000_[enable|disable]_phy_wakeup_reg_bm()). + **/ +static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, + u16 *data, bool read, bool page_set) +{ + s32 ret_val; + u16 reg = BM_PHY_REG_NUM(offset); + u16 page = BM_PHY_REG_PAGE(offset); + u16 phy_reg = 0; + + /* Gig must be disabled for MDIO accesses to Host Wakeup reg page */ + if ((hw->mac.type == e1000_pchlan) && + (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE))) + e_dbg("Attempting to access page %d while gig enabled.\n", + page); + + if (!page_set) { + /* Enable access to PHY wakeup registers */ + ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg); + if (ret_val) { + e_dbg("Could not enable PHY wakeup reg access\n"); + goto out; + } + } + + e_dbg("Accessing PHY page %d reg 0x%x\n", page, reg); + + /* Write the Wakeup register page offset value using opcode 0x11 */ ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg); if (ret_val) { - e_dbg("Could not write address opcode to page 800\n"); + e_dbg("Could not write address opcode to page %d\n", page); goto out; } if (read) { - /* Read the page 800 value using opcode 0x12 */ + /* Read the Wakeup register page value using opcode 0x12 */ ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, data); } else { - /* Write the page 800 value using opcode 0x12 */ + /* Write the Wakeup register page value using opcode 0x12 */ ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, *data); } if (ret_val) { - e_dbg("Could not access data value from page 800\n"); + e_dbg("Could not access PHY reg %d.%d\n", page, reg); goto out; } - /* - * Restore 769_17.2 to its original value - * Set page 769 - */ - e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, - (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); - - /* Clear 769_17.2 */ - ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); - if (ret_val) { - e_dbg("Could not clear PHY page 769 bit 2\n"); - goto out; - } + if (!page_set) + ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg); out: return ret_val; @@ -2792,11 +2869,12 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active) * semaphore before exiting. **/ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, - bool locked) + bool locked, bool page_set) { s32 ret_val; u16 page = BM_PHY_REG_PAGE(offset); u16 reg = BM_PHY_REG_NUM(offset); + u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); if (!locked) { ret_val = hw->phy.ops.acquire(hw); @@ -2806,8 +2884,8 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { - ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, - data, true); + ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, + true, page_set); goto out; } @@ -2817,26 +2895,25 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, goto out; } - hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); - - if (page == HV_INTC_FC_PAGE_START) - page = 0; + if (!page_set) { + if (page == HV_INTC_FC_PAGE_START) + page = 0; - if (reg > MAX_PHY_MULTI_PAGE_REG) { - u32 phy_addr = hw->phy.addr; + if (reg > MAX_PHY_MULTI_PAGE_REG) { + /* Page is shifted left, PHY expects (page x 32) */ + ret_val = e1000_set_page_igp(hw, + (page << IGP_PAGE_SHIFT)); - hw->phy.addr = 1; - - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000e_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (page << IGP_PAGE_SHIFT)); - hw->phy.addr = phy_addr; + hw->phy.addr = phy_addr; - if (ret_val) - goto out; + if (ret_val) + goto out; + } } + e_dbg("reading PHY page %d (or 0x%x shifted) reg 0x%x\n", page, + page << IGP_PAGE_SHIFT, reg); + ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, data); out: @@ -2858,7 +2935,7 @@ out: **/ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) { - return __e1000_read_phy_reg_hv(hw, offset, data, false); + return __e1000_read_phy_reg_hv(hw, offset, data, false, false); } /** @@ -2872,7 +2949,21 @@ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) **/ s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data) { - return __e1000_read_phy_reg_hv(hw, offset, data, true); + return __e1000_read_phy_reg_hv(hw, offset, data, true, false); +} + +/** + * e1000_read_phy_reg_page_hv - Read HV PHY register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Reads the PHY register at offset and stores the retrieved information + * in data. Assumes semaphore already acquired and page already set. + **/ +s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data) +{ + return __e1000_read_phy_reg_hv(hw, offset, data, true, true); } /** @@ -2886,11 +2977,12 @@ s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data) * at the offset. Release any acquired semaphores before exiting. **/ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, - bool locked) + bool locked, bool page_set) { s32 ret_val; u16 page = BM_PHY_REG_PAGE(offset); u16 reg = BM_PHY_REG_NUM(offset); + u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); if (!locked) { ret_val = hw->phy.ops.acquire(hw); @@ -2900,8 +2992,8 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { - ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, - &data, false); + ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, + false, page_set); goto out; } @@ -2911,42 +3003,41 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, goto out; } - hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); - - if (page == HV_INTC_FC_PAGE_START) - page = 0; - - /* - * Workaround MDIO accesses being disabled after entering IEEE Power - * Down (whenever bit 11 of the PHY Control register is set) - */ - if ((hw->phy.type == e1000_phy_82578) && - (hw->phy.revision >= 1) && - (hw->phy.addr == 2) && - ((MAX_PHY_REG_ADDRESS & reg) == 0) && - (data & (1 << 11))) { - u16 data2 = 0x7EFF; - ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3, - &data2, false); - if (ret_val) - goto out; - } + if (!page_set) { + if (page == HV_INTC_FC_PAGE_START) + page = 0; - if (reg > MAX_PHY_MULTI_PAGE_REG) { - u32 phy_addr = hw->phy.addr; + /* + * Workaround MDIO accesses being disabled after entering IEEE + * Power Down (when bit 11 of the PHY Control register is set) + */ + if ((hw->phy.type == e1000_phy_82578) && + (hw->phy.revision >= 1) && + (hw->phy.addr == 2) && + ((MAX_PHY_REG_ADDRESS & reg) == 0) && (data & (1 << 11))) { + u16 data2 = 0x7EFF; + ret_val = e1000_access_phy_debug_regs_hv(hw, + (1 << 6) | 0x3, + &data2, false); + if (ret_val) + goto out; + } - hw->phy.addr = 1; + if (reg > MAX_PHY_MULTI_PAGE_REG) { + /* Page is shifted left, PHY expects (page x 32) */ + ret_val = e1000_set_page_igp(hw, + (page << IGP_PAGE_SHIFT)); - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000e_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (page << IGP_PAGE_SHIFT)); - hw->phy.addr = phy_addr; + hw->phy.addr = phy_addr; - if (ret_val) - goto out; + if (ret_val) + goto out; + } } + e_dbg("writing PHY page %d (or 0x%x shifted) reg 0x%x\n", page, + page << IGP_PAGE_SHIFT, reg); + ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, data); @@ -2968,7 +3059,7 @@ out: **/ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) { - return __e1000_write_phy_reg_hv(hw, offset, data, false); + return __e1000_write_phy_reg_hv(hw, offset, data, false, false); } /** @@ -2982,7 +3073,21 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) **/ s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data) { - return __e1000_write_phy_reg_hv(hw, offset, data, true); + return __e1000_write_phy_reg_hv(hw, offset, data, true, false); +} + +/** + * e1000_write_phy_reg_page_hv - Write HV PHY register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Writes the data to PHY register at the offset. Assumes semaphore + * already acquired and page already set. + **/ +s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data) +{ + return __e1000_write_phy_reg_hv(hw, offset, data, true, true); } /** @@ -3004,11 +3109,12 @@ static u32 e1000_get_phy_addr_for_hv_page(u32 page) * @hw: pointer to the HW structure * @offset: register offset to be read or written * @data: pointer to the data to be read or written - * @read: determines if operation is read or written + * @read: determines if operation is read or write * * Reads the PHY register at offset and stores the retreived information * in data. Assumes semaphore already acquired. Note that the procedure - * to read these regs uses the address port and data port to read/write. + * to access these regs uses the address port and data port to read/write. + * These accesses done with PHY address 2 and without using pages. **/ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, u16 *data, bool read) @@ -3028,7 +3134,7 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, /* masking with 0x3F to remove the page from offset */ ret_val = e1000e_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F); if (ret_val) { - e_dbg("Could not write PHY the HV address register\n"); + e_dbg("Could not write the Address Offset port register\n"); goto out; } @@ -3039,7 +3145,7 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, ret_val = e1000e_write_phy_reg_mdic(hw, data_reg, *data); if (ret_val) { - e_dbg("Could not read data value from HV data register\n"); + e_dbg("Could not access the Data port register\n"); goto out; } |