diff mbox

[Precise,5/5] e1000e: Workaround for dropped packets in Gig/100 speeds on 82579

Message ID 1427770232-17937-6-git-send-email-inaddy@ubuntu.com
State New
Headers show

Commit Message

Rafael David Tinoco (Inaddy) March 31, 2015, 2:50 a.m. UTC
From: David Ertman <davidx.m.ertman@intel.com>

BugLink: http://bugs.launchpad.net/bugs/1425333

This is a workaround for a HW erratum on 82579 devices.
Erratum is #23 in Intel 6 Series Chipset and Intel C200 Series Chipset
specification Update June 2013.

Problem: 82579 parts experience packet loss in Gig and 100 speeds
when interconnect between PHY and MAC is exiting K1 power saving state.
This was previously believed to only affect 1Gig speed, but has been observed
at 100Mbs also.

Workaround: Disable K1 for 82579 devices at Gig and 100 speeds.

[Conflicts]
    - Did not include commit 1b41db3 with cosmetic changes

Signed-off-by: Dave Ertman <davidx.m.ertman@intel.com>
(cherry picked from commit 77e61146c67765deae45faa7db088c64a9fbca00) 
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: Rafael David Tinoco (Inaddy) <inaddy@ubuntu.com>
---
 drivers/net/ethernet/intel/e1000e/e1000.h   |  1 +
 drivers/net/ethernet/intel/e1000e/ich8lan.c | 55 +++++++++++++----------------
 2 files changed, 26 insertions(+), 30 deletions(-)
diff mbox

Patch

diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index 8e362bb..7ab787f 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -153,6 +153,7 @@  struct e1000_info;
 #define HV_M_STATUS_AUTONEG_COMPLETE      0x1000
 #define HV_M_STATUS_SPEED_MASK            0x0300
 #define HV_M_STATUS_SPEED_1000            0x0200
+#define HV_M_STATUS_SPEED_100             0x0100
 #define HV_M_STATUS_LINK_UP               0x0040
 
 #define E1000_ICH_FWSM_PCIM2PCI		0x01000000 /* ME PCIm-to-PCI active */
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index f0244a2..c4f793e 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -136,6 +136,7 @@ 
 /* PHY Power Management Control */
 #define HV_PM_CTRL		PHY_REG(770, 17)
 #define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA	0x100
+#define HV_PM_CTRL_K1_ENABLE           0x4000
 
 /* PHY Low Power Idle Control */
 #define I82579_LPI_CTRL				PHY_REG(772, 20)
@@ -1701,51 +1702,45 @@  out:
  *  e1000_k1_gig_workaround_lv - K1 Si workaround
  *  @hw:   pointer to the HW structure
  *
- *  Workaround to set the K1 beacon duration for 82579 parts
+ *  Workaround to set the K1 beacon duration for 82579 parts in 10Mbps
+ *  Disable K1 in 1000Mbps and 100Mbps
  **/
 static s32 e1000_k1_workaround_lv(struct e1000_hw *hw)
 {
 	s32 ret_val = 0;
 	u16 status_reg = 0;
-	u32 mac_reg;
-	u16 phy_reg;
 
 	if (hw->mac.type != e1000_pch2lan)
 		goto out;
 
-	/* Set K1 beacon duration based on 1Gbps speed or otherwise */
+	/* Set K1 beacon duration based on 10Mbs speed */
 	ret_val = e1e_rphy(hw, HV_M_STATUS, &status_reg);
 	if (ret_val)
 		goto out;
 
 	if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE))
-	    == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) {
-		mac_reg = er32(FEXTNVM4);
-		mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK;
-
-		ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg);
-		if (ret_val)
-			goto out;
-
-		if (status_reg & HV_M_STATUS_SPEED_1000) {
-			u16 pm_phy_reg;
-
-			mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC;
-			phy_reg &= ~I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT;
-			/* LV 1G Packet drop issue wa  */
-			ret_val = e1e_rphy(hw, HV_PM_CTRL, &pm_phy_reg);
-			if (ret_val)
-				return ret_val;
-			pm_phy_reg &= ~HV_PM_CTRL_PLL_STOP_IN_K1_GIGA;
-			ret_val = e1e_wphy(hw, HV_PM_CTRL, pm_phy_reg);
-			if (ret_val)
-				return ret_val;
-		} else {
-			mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC;
-			phy_reg |= I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT;
+			== (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) {
+			if (status_reg &
+					(HV_M_STATUS_SPEED_1000 | HV_M_STATUS_SPEED_100)) {
+
+				u16 pm_phy_reg;
+
+				/* LV 1G/100 Packet drop issue wa  */
+				ret_val = e1e_rphy(hw, HV_PM_CTRL, &pm_phy_reg);
+				if (ret_val)
+					return ret_val;
+				pm_phy_reg &= ~HV_PM_CTRL_K1_ENABLE;
+				ret_val = e1e_wphy(hw, HV_PM_CTRL, pm_phy_reg);
+				if (ret_val)
+					return ret_val;
+			} else {
+				u32 mac_reg;
+
+				mac_reg = er32(FEXTNVM4);
+				mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK;
+				mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC;
+				ew32(FEXTNVM4, mac_reg);
 		}
-		ew32(FEXTNVM4, mac_reg);
-		ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg);
 	}
 
 out: