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,
+ ®);
+ 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, ®);
+ 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)