summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/intel/e1000e/ich8lan.c
diff options
context:
space:
mode:
authorBruce Allan <bruce.w.allan@intel.com>2013-03-20 11:23:11 +0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2013-03-28 11:01:52 +0400
commitd495bcb84d2c3abb5ad5e43cfeea0e305ceffb30 (patch)
tree6edb94fb74a39dee627bbaeb39b3d21df84acc29 /drivers/net/ethernet/intel/e1000e/ich8lan.c
parentea8179a72844b30d046cdcc932231872f2dbcc90 (diff)
downloadlinux-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.c55
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);