On Sun, Oct 12, 2014 at 09:53:28PM +0200, Claudio Jeker wrote:
> This seems to be enough to help em(4) in modern laptops like the X240 to
> no longer generate watchdog timeouts on high throughput.
> This should only affect I218 but tests on different em(4) devices would
> not hurt.
> 

I will commit this version somewhen tomorrow unless someone objects.

-- 
:wq Claudio

Index: dev/pci//if_em_hw.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_em_hw.c,v
retrieving revision 1.80
diff -u -p -r1.80 if_em_hw.c
--- dev/pci//if_em_hw.c 22 Jul 2014 13:12:11 -0000      1.80
+++ dev/pci//if_em_hw.c 3 Nov 2014 19:57:07 -0000
@@ -163,6 +163,7 @@ int32_t             em_lv_phy_workarounds_ich8lan(s
 int32_t                em_link_stall_workaround_hv(struct em_hw *);
 int32_t                em_k1_gig_workaround_hv(struct em_hw *, boolean_t);
 int32_t                em_k1_workaround_lv(struct em_hw *);
+int32_t                em_k1_workaround_lpt_lp(struct em_hw *, boolean_t);
 int32_t                em_configure_k1_ich8lan(struct em_hw *, boolean_t);
 void           em_gate_hw_phy_config_ich8lan(struct em_hw *, boolean_t);
 int32_t                em_access_phy_wakeup_reg_bm(struct em_hw *, uint32_t,
@@ -3709,6 +3710,16 @@ em_check_for_link(struct em_hw *hw)
                                if (ret_val)
                                        return ret_val;
                        }
+                       /* Work-around I218 hang issue */
+                       if ((hw->device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
+                           (hw->device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) ||
+                           (hw->device_id == E1000_DEV_ID_PCH_I218_LM3) ||
+                           (hw->device_id == E1000_DEV_ID_PCH_I218_V3)) {
+                               ret_val = em_k1_workaround_lpt_lp(hw,
+                                   hw->icp_xxxx_is_link_up);
+                               if (ret_val)
+                                       return ret_val;
+                       }
 
                        /*
                         * Check if there was DownShift, must be checked
@@ -10185,6 +10196,84 @@ em_k1_workaround_lv(struct em_hw *hw)
        
        return E1000_SUCCESS;
 }
+
+/**
+ *  em_k1_workaround_lpt_lp - K1 workaround on Lynxpoint-LP
+ *
+ *  When K1 is enabled for 1Gbps, the MAC can miss 2 DMA completion indications
+ *  preventing further DMA write requests.  Workaround the issue by disabling
+ *  the de-assertion of the clock request when in 1Gpbs mode.
+ *  Also, set appropriate Tx re-transmission timeouts for 10 and 100Half link
+ *  speeds in order to avoid Tx hangs.
+ **/
+int32_t
+em_k1_workaround_lpt_lp(struct em_hw *hw, boolean_t link)
+{
+       uint32_t fextnvm6 = E1000_READ_REG(hw, FEXTNVM6);
+       uint32_t status = E1000_READ_REG(hw, STATUS);
+       int32_t ret_val = E1000_SUCCESS;
+       uint16_t reg;
+
+       if (link && (status & E1000_STATUS_SPEED_1000)) {
+               ret_val = em_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_K1_CONFIG,
+                   &reg);
+               if (ret_val)
+                       return ret_val;
+
+               ret_val = em_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_K1_CONFIG,
+                   reg & ~E1000_KMRNCTRLSTA_K1_ENABLE);
+               if (ret_val)
+                       return ret_val;
+
+               usec_delay(10);
+
+               E1000_WRITE_REG(hw, FEXTNVM6,
+                               fextnvm6 | E1000_FEXTNVM6_REQ_PLL_CLK);
+
+               ret_val = em_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_K1_CONFIG,
+                   reg);
+       } else {
+               /* clear FEXTNVM6 bit 8 on link down or 10/100 */
+               fextnvm6 &= ~E1000_FEXTNVM6_REQ_PLL_CLK;
+
+               if (!link || ((status & E1000_STATUS_SPEED_100) &&
+                             (status & E1000_STATUS_FD)))
+                       goto update_fextnvm6;
+
+               ret_val = em_read_phy_reg(hw, I217_INBAND_CTRL, &reg);
+               if (ret_val)
+                       return ret_val;
+
+               /* Clear link status transmit timeout */
+               reg &= ~I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_MASK;
+
+               if (status & E1000_STATUS_SPEED_100) {
+                       /* Set inband Tx timeout to 5x10us for 100Half */
+                       reg |= 5 << I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT;
+
+                       /* Do not extend the K1 entry latency for 100Half */
+                       fextnvm6 &= ~E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION;
+               } else {
+                       /* Set inband Tx timeout to 50x10us for 10Full/Half */
+                       reg |= 50 <<
+                              I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT;
+
+                       /* Extend the K1 entry latency for 10 Mbps */
+                       fextnvm6 |= E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION;
+               }
+
+               ret_val = em_write_phy_reg(hw, I217_INBAND_CTRL, reg);
+               if (ret_val)
+                       return ret_val;
+
+update_fextnvm6:
+               E1000_WRITE_REG(hw, FEXTNVM6, fextnvm6);
+       }
+
+       return ret_val;
+
+}
+
 
 /***************************************************************************
  *  e1000_gate_hw_phy_config_ich8lan - disable PHY config via hardware
Index: dev/pci//if_em_hw.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_em_hw.h,v
retrieving revision 1.60
diff -u -p -r1.60 if_em_hw.h
--- dev/pci//if_em_hw.h 10 Mar 2014 04:09:53 -0000      1.60
+++ dev/pci//if_em_hw.h 28 Sep 2014 12:09:10 -0000
@@ -987,8 +987,9 @@ struct em_ffvt_entry {
 #define E1000_MDIC     0x00020  /* MDI Control - RW */
 #define E1000_MDICNFG  0x00E04  /* MDI Config - RW */
 #define E1000_SCTL     0x00024  /* SerDes Control - RW */
-#define E1000_FEXTNVM4 0x00024  /* Future Extended NVM 4 - RW */
 #define E1000_FEXTNVM  0x00028  /* Future Extended NVM register */
+#define E1000_FEXTNVM4 0x00024  /* Future Extended NVM 4 - RW */
+#define E1000_FEXTNVM6 0x00010  /* Future Extended NVM 6 - RW */
 #define E1000_FCAL     0x00028  /* Flow Control Address Low - RW */
 #define E1000_FCAH     0x0002C  /* Flow Control Address High -RW */
 #define E1000_FCT      0x00030  /* Flow Control Type - RW */
@@ -1215,8 +1216,9 @@ struct em_ffvt_entry {
 #define E1000_82542_FLA      E1000_FLA
 #define E1000_82542_MDIC     E1000_MDIC
 #define E1000_82542_SCTL     E1000_SCTL
-#define E1000_82542_FEXTNVM4 E1000_FEXTNVM4
 #define E1000_82542_FEXTNVM  E1000_FEXTNVM
+#define E1000_82542_FEXTNVM4 E1000_FEXTNVM4
+#define E1000_82542_FEXTNVM6 E1000_FEXTNVM6
 #define E1000_82542_FCAL     E1000_FCAL
 #define E1000_82542_FCAH     E1000_FCAH
 #define E1000_82542_FCT      E1000_FCT
@@ -1430,6 +1432,9 @@ struct em_ffvt_entry {
 #define E1000_FEXTNVM4_BEACON_DURATION_8USEC   0x7
 #define E1000_FEXTNVM4_BEACON_DURATION_16USEC  0x3
 
+#define E1000_FEXTNVM6_REQ_PLL_CLK     0x00000100
+#define E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION       0x00000200
+
 /* Statistics counters collected by the MAC */
 struct em_hw_stats {
     uint64_t crcerrs;
@@ -3719,6 +3724,11 @@ union ich8_hws_flash_regacc {
 #define HV_M_STATUS_SPEED_MASK            0x0300
 #define HV_M_STATUS_SPEED_1000            0x0200
 #define HV_M_STATUS_LINK_UP               0x0040
+
+/* Inband Control */
+#define I217_INBAND_CTRL                               PHY_REG(770, 18)
+#define I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_MASK     0x3F00
+#define I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT    8
 
 /* PHY Low Power Idle Control */
 #define I82579_LPI_CTRL                                PHY_REG(772, 20)

Reply via email to