diff options
author | Bruce Allan <bruce.w.allan@intel.com> | 2013-03-20 11:23:11 +0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2013-03-28 11:01:52 +0400 |
commit | d495bcb84d2c3abb5ad5e43cfeea0e305ceffb30 (patch) | |
tree | 6edb94fb74a39dee627bbaeb39b3d21df84acc29 /drivers/net/ethernet/intel/e1000e/ich8lan.c | |
parent | ea8179a72844b30d046cdcc932231872f2dbcc90 (diff) | |
download | linux-d495bcb84d2c3abb5ad5e43cfeea0e305ceffb30.tar.xz |
e1000e: EEE capability advertisement not set/disabled as required
Devices supported by the driver which support EEE (currently 82579, I217
and I218) are advertising EEE capabilities during auto-negotiation even
when EEE has been disabled. In addition to not acting as expected, this
also caused the EEE status reported by 'ethtool --show-eee' to be wrong
when two of these devices are connected back-to-back and EEE is disabled
on one. In addition to fixing this issue, the ability for the user to
specify which speeds (100 or 1000 full-duplex) to advertise EEE support
has been added.
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/e1000e/ich8lan.c')
-rw-r--r-- | drivers/net/ethernet/intel/e1000e/ich8lan.c | 55 |
1 files changed, 28 insertions, 27 deletions
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index 3b1c1a7e5dac..174507ccd7d7 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -695,7 +695,7 @@ s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data) * * Assumes the SW/FW/HW Semaphore is already acquired. **/ -static s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data) +s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data) { return __e1000_access_emi_reg_locked(hw, addr, &data, false); } @@ -712,11 +712,22 @@ static s32 e1000_set_eee_pchlan(struct e1000_hw *hw) { struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; s32 ret_val; - u16 lpi_ctrl; + u16 lpa, pcs_status, adv, adv_addr, lpi_ctrl, data; - if ((hw->phy.type != e1000_phy_82579) && - (hw->phy.type != e1000_phy_i217)) + switch (hw->phy.type) { + case e1000_phy_82579: + lpa = I82579_EEE_LP_ABILITY; + pcs_status = I82579_EEE_PCS_STATUS; + adv_addr = I82579_EEE_ADVERTISEMENT; + break; + case e1000_phy_i217: + lpa = I217_EEE_LP_ABILITY; + pcs_status = I217_EEE_PCS_STATUS; + adv_addr = I217_EEE_ADVERTISEMENT; + break; + default: return 0; + } ret_val = hw->phy.ops.acquire(hw); if (ret_val) @@ -731,34 +742,24 @@ static s32 e1000_set_eee_pchlan(struct e1000_hw *hw) /* Enable EEE if not disabled by user */ if (!dev_spec->eee_disable) { - u16 lpa, pcs_status, data; - /* Save off link partner's EEE ability */ - switch (hw->phy.type) { - case e1000_phy_82579: - lpa = I82579_EEE_LP_ABILITY; - pcs_status = I82579_EEE_PCS_STATUS; - break; - case e1000_phy_i217: - lpa = I217_EEE_LP_ABILITY; - pcs_status = I217_EEE_PCS_STATUS; - break; - default: - ret_val = -E1000_ERR_PHY; - goto release; - } ret_val = e1000_read_emi_reg_locked(hw, lpa, &dev_spec->eee_lp_ability); if (ret_val) goto release; + /* Read EEE advertisement */ + ret_val = e1000_read_emi_reg_locked(hw, adv_addr, &adv); + if (ret_val) + goto release; + /* Enable EEE only for speeds in which the link partner is - * EEE capable. + * EEE capable and for which we advertise EEE. */ - if (dev_spec->eee_lp_ability & I82579_EEE_1000_SUPPORTED) + if (adv & dev_spec->eee_lp_ability & I82579_EEE_1000_SUPPORTED) lpi_ctrl |= I82579_LPI_CTRL_1000_ENABLE; - if (dev_spec->eee_lp_ability & I82579_EEE_100_SUPPORTED) { + if (adv & dev_spec->eee_lp_ability & I82579_EEE_100_SUPPORTED) { e1e_rphy_locked(hw, MII_LPA, &data); if (data & LPA_100FULL) lpi_ctrl |= I82579_LPI_CTRL_100_ENABLE; @@ -770,13 +771,13 @@ static s32 e1000_set_eee_pchlan(struct e1000_hw *hw) dev_spec->eee_lp_ability &= ~I82579_EEE_100_SUPPORTED; } - - /* R/Clr IEEE MMD 3.1 bits 11:10 - Tx/Rx LPI Received */ - ret_val = e1000_read_emi_reg_locked(hw, pcs_status, &data); - if (ret_val) - goto release; } + /* R/Clr IEEE MMD 3.1 bits 11:10 - Tx/Rx LPI Received */ + ret_val = e1000_read_emi_reg_locked(hw, pcs_status, &data); + if (ret_val) + goto release; + ret_val = e1e_wphy_locked(hw, I82579_LPI_CTRL, lpi_ctrl); release: hw->phy.ops.release(hw); |