1 From e4d37a59973992e085fd0f2453b8845ce2f9a98d Mon Sep 17 00:00:00 2001
2 From: Sasha Levin <sashal@kernel.org>
3 Date: Thu, 4 Jan 2024 16:16:52 +0200
4 Subject: e1000e: Workaround for sporadic MDI error on Meteor Lake systems
6 From: Vitaly Lifshits <vitaly.lifshits@intel.com>
8 [ Upstream commit 6dbdd4de0362c37e54e8b049781402e5a409e7d0 ]
10 On some Meteor Lake systems accessing the PHY via the MDIO interface may
11 result in an MDI error. This issue happens sporadically and in most cases
12 a second access to the PHY via the MDIO interface results in success.
14 As a workaround, introduce a retry counter which is set to 3 on Meteor
15 Lake systems. The driver will only return an error if 3 consecutive PHY
16 access attempts fail. The retry mechanism is disabled in specific flows,
17 where MDI errors are expected.
19 Fixes: cc23f4f0b6b9 ("e1000e: Add support for Meteor Lake")
20 Suggested-by: Nikolay Mushayev <nikolay.mushayev@intel.com>
21 Co-developed-by: Nir Efrati <nir.efrati@intel.com>
22 Signed-off-by: Nir Efrati <nir.efrati@intel.com>
23 Signed-off-by: Vitaly Lifshits <vitaly.lifshits@intel.com>
24 Tested-by: Naama Meir <naamax.meir@linux.intel.com>
25 Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
26 Signed-off-by: Sasha Levin <sashal@kernel.org>
28 drivers/net/ethernet/intel/e1000e/hw.h | 2 +
29 drivers/net/ethernet/intel/e1000e/ich8lan.c | 33 ++++
30 drivers/net/ethernet/intel/e1000e/phy.c | 182 ++++++++++++--------
31 drivers/net/ethernet/intel/e1000e/phy.h | 2 +
32 4 files changed, 150 insertions(+), 69 deletions(-)
34 diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h
35 index 1fef6bb5a5fbc..4b6e7536170ab 100644
36 --- a/drivers/net/ethernet/intel/e1000e/hw.h
37 +++ b/drivers/net/ethernet/intel/e1000e/hw.h
38 @@ -628,6 +628,7 @@ struct e1000_phy_info {
40 u32 reset_delay_us; /* in usec */
44 enum e1000_media_type media_type;
46 @@ -644,6 +645,7 @@ struct e1000_phy_info {
47 bool polarity_correction;
48 bool speed_downgraded;
49 bool autoneg_wait_to_complete;
53 struct e1000_nvm_info {
54 diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
55 index a2788fd5f8bb8..717c52913e84b 100644
56 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
57 +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
58 @@ -222,11 +222,18 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
59 if (hw->mac.type >= e1000_pch_lpt) {
60 /* Only unforce SMBus if ME is not active */
61 if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
62 + /* Switching PHY interface always returns MDI error
63 + * so disable retry mechanism to avoid wasting time
65 + e1000e_disable_phy_retry(hw);
67 /* Unforce SMBus mode in PHY */
68 e1e_rphy_locked(hw, CV_SMB_CTRL, &phy_reg);
69 phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
70 e1e_wphy_locked(hw, CV_SMB_CTRL, phy_reg);
72 + e1000e_enable_phy_retry(hw);
74 /* Unforce SMBus mode in MAC */
75 mac_reg = er32(CTRL_EXT);
76 mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
77 @@ -310,6 +317,11 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
81 + /* There is no guarantee that the PHY is accessible at this time
82 + * so disable retry mechanism to avoid wasting time
84 + e1000e_disable_phy_retry(hw);
86 /* The MAC-PHY interconnect may be in SMBus mode. If the PHY is
87 * inaccessible and resetting the PHY is not blocked, toggle the
88 * LANPHYPC Value bit to force the interconnect to PCIe mode.
89 @@ -380,6 +392,8 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
93 + e1000e_enable_phy_retry(hw);
95 hw->phy.ops.release(hw);
98 @@ -449,6 +463,11 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
100 phy->id = e1000_phy_unknown;
102 + if (hw->mac.type == e1000_pch_mtp) {
103 + phy->retry_count = 2;
104 + e1000e_enable_phy_retry(hw);
107 ret_val = e1000_init_phy_workarounds_pchlan(hw);
110 @@ -1146,6 +1165,11 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
114 + /* Switching PHY interface always returns MDI error
115 + * so disable retry mechanism to avoid wasting time
117 + e1000e_disable_phy_retry(hw);
119 /* Force SMBus mode in PHY */
120 ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg);
122 @@ -1153,6 +1177,8 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
123 phy_reg |= CV_SMB_CTRL_FORCE_SMBUS;
124 e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg);
126 + e1000e_enable_phy_retry(hw);
128 /* Force SMBus mode in MAC */
129 mac_reg = er32(CTRL_EXT);
130 mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
131 @@ -1313,6 +1339,11 @@ static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force)
132 /* Toggle LANPHYPC Value bit */
133 e1000_toggle_lanphypc_pch_lpt(hw);
135 + /* Switching PHY interface always returns MDI error
136 + * so disable retry mechanism to avoid wasting time
138 + e1000e_disable_phy_retry(hw);
140 /* Unforce SMBus mode in PHY */
141 ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg);
143 @@ -1333,6 +1364,8 @@ static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force)
144 phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
145 e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg);
147 + e1000e_enable_phy_retry(hw);
149 /* Unforce SMBus mode in MAC */
150 mac_reg = er32(CTRL_EXT);
151 mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
152 diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c
153 index 96ff0ca561b6c..395746bcf8f7c 100644
154 --- a/drivers/net/ethernet/intel/e1000e/phy.c
155 +++ b/drivers/net/ethernet/intel/e1000e/phy.c
156 @@ -107,6 +107,16 @@ s32 e1000e_phy_reset_dsp(struct e1000_hw *hw)
157 return e1e_wphy(hw, M88E1000_PHY_GEN_CONTROL, 0);
160 +void e1000e_disable_phy_retry(struct e1000_hw *hw)
162 + hw->phy.retry_enabled = false;
165 +void e1000e_enable_phy_retry(struct e1000_hw *hw)
167 + hw->phy.retry_enabled = true;
171 * e1000e_read_phy_reg_mdic - Read MDI control register
172 * @hw: pointer to the HW structure
173 @@ -118,55 +128,73 @@ s32 e1000e_phy_reset_dsp(struct e1000_hw *hw)
175 s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
177 + u32 i, mdic = 0, retry_counter, retry_max;
178 struct e1000_phy_info *phy = &hw->phy;
182 if (offset > MAX_PHY_REG_ADDRESS) {
183 e_dbg("PHY Address %d is out of range\n", offset);
184 return -E1000_ERR_PARAM;
187 + retry_max = phy->retry_enabled ? phy->retry_count : 0;
189 /* Set up Op-code, Phy Address, and register offset in the MDI
190 * Control register. The MAC will take care of interfacing with the
191 * PHY to retrieve the desired data.
193 - mdic = ((offset << E1000_MDIC_REG_SHIFT) |
194 - (phy->addr << E1000_MDIC_PHY_SHIFT) |
195 - (E1000_MDIC_OP_READ));
196 + for (retry_counter = 0; retry_counter <= retry_max; retry_counter++) {
200 + mdic = ((offset << E1000_MDIC_REG_SHIFT) |
201 + (phy->addr << E1000_MDIC_PHY_SHIFT) |
202 + (E1000_MDIC_OP_READ));
204 - /* Poll the ready bit to see if the MDI read completed
205 - * Increasing the time out as testing showed failures with
206 - * the lower time out
208 - for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
211 - if (mdic & E1000_MDIC_READY)
214 - if (!(mdic & E1000_MDIC_READY)) {
215 - e_dbg("MDI Read PHY Reg Address %d did not complete\n", offset);
216 - return -E1000_ERR_PHY;
218 - if (mdic & E1000_MDIC_ERROR) {
219 - e_dbg("MDI Read PHY Reg Address %d Error\n", offset);
220 - return -E1000_ERR_PHY;
222 - if (FIELD_GET(E1000_MDIC_REG_MASK, mdic) != offset) {
223 - e_dbg("MDI Read offset error - requested %d, returned %d\n",
224 - offset, FIELD_GET(E1000_MDIC_REG_MASK, mdic));
225 - return -E1000_ERR_PHY;
228 + /* Poll the ready bit to see if the MDI read completed
229 + * Increasing the time out as testing showed failures with
230 + * the lower time out
232 + for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
233 + usleep_range(50, 60);
235 + if (mdic & E1000_MDIC_READY)
238 + if (!(mdic & E1000_MDIC_READY)) {
239 + e_dbg("MDI Read PHY Reg Address %d did not complete\n",
243 + if (mdic & E1000_MDIC_ERROR) {
244 + e_dbg("MDI Read PHY Reg Address %d Error\n", offset);
247 + if (FIELD_GET(E1000_MDIC_REG_MASK, mdic) != offset) {
248 + e_dbg("MDI Read offset error - requested %d, returned %d\n",
249 + offset, FIELD_GET(E1000_MDIC_REG_MASK, mdic));
253 + /* Allow some time after each MDIC transaction to avoid
254 + * reading duplicate data in the next MDIC transaction.
256 + if (hw->mac.type == e1000_pch2lan)
257 + usleep_range(100, 150);
264 + if (retry_counter != retry_max) {
265 + e_dbg("Perform retry on PHY transaction...\n");
271 - /* Allow some time after each MDIC transaction to avoid
272 - * reading duplicate data in the next MDIC transaction.
274 - if (hw->mac.type == e1000_pch2lan)
277 + return -E1000_ERR_PHY;
281 @@ -179,56 +207,72 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
283 s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
285 + u32 i, mdic = 0, retry_counter, retry_max;
286 struct e1000_phy_info *phy = &hw->phy;
290 if (offset > MAX_PHY_REG_ADDRESS) {
291 e_dbg("PHY Address %d is out of range\n", offset);
292 return -E1000_ERR_PARAM;
295 + retry_max = phy->retry_enabled ? phy->retry_count : 0;
297 /* Set up Op-code, Phy Address, and register offset in the MDI
298 * Control register. The MAC will take care of interfacing with the
299 * PHY to retrieve the desired data.
301 - mdic = (((u32)data) |
302 - (offset << E1000_MDIC_REG_SHIFT) |
303 - (phy->addr << E1000_MDIC_PHY_SHIFT) |
304 - (E1000_MDIC_OP_WRITE));
305 + for (retry_counter = 0; retry_counter <= retry_max; retry_counter++) {
309 + mdic = (((u32)data) |
310 + (offset << E1000_MDIC_REG_SHIFT) |
311 + (phy->addr << E1000_MDIC_PHY_SHIFT) |
312 + (E1000_MDIC_OP_WRITE));
314 - /* Poll the ready bit to see if the MDI read completed
315 - * Increasing the time out as testing showed failures with
316 - * the lower time out
318 - for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
321 - if (mdic & E1000_MDIC_READY)
324 - if (!(mdic & E1000_MDIC_READY)) {
325 - e_dbg("MDI Write PHY Reg Address %d did not complete\n", offset);
326 - return -E1000_ERR_PHY;
328 - if (mdic & E1000_MDIC_ERROR) {
329 - e_dbg("MDI Write PHY Red Address %d Error\n", offset);
330 - return -E1000_ERR_PHY;
332 - if (FIELD_GET(E1000_MDIC_REG_MASK, mdic) != offset) {
333 - e_dbg("MDI Write offset error - requested %d, returned %d\n",
334 - offset, FIELD_GET(E1000_MDIC_REG_MASK, mdic));
335 - return -E1000_ERR_PHY;
339 - /* Allow some time after each MDIC transaction to avoid
340 - * reading duplicate data in the next MDIC transaction.
342 - if (hw->mac.type == e1000_pch2lan)
344 + /* Poll the ready bit to see if the MDI read completed
345 + * Increasing the time out as testing showed failures with
346 + * the lower time out
348 + for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
349 + usleep_range(50, 60);
351 + if (mdic & E1000_MDIC_READY)
354 + if (!(mdic & E1000_MDIC_READY)) {
355 + e_dbg("MDI Write PHY Reg Address %d did not complete\n",
359 + if (mdic & E1000_MDIC_ERROR) {
360 + e_dbg("MDI Write PHY Reg Address %d Error\n", offset);
363 + if (FIELD_GET(E1000_MDIC_REG_MASK, mdic) != offset) {
364 + e_dbg("MDI Write offset error - requested %d, returned %d\n",
365 + offset, FIELD_GET(E1000_MDIC_REG_MASK, mdic));
370 + /* Allow some time after each MDIC transaction to avoid
371 + * reading duplicate data in the next MDIC transaction.
373 + if (hw->mac.type == e1000_pch2lan)
374 + usleep_range(100, 150);
379 + if (retry_counter != retry_max) {
380 + e_dbg("Perform retry on PHY transaction...\n");
385 + return -E1000_ERR_PHY;
389 diff --git a/drivers/net/ethernet/intel/e1000e/phy.h b/drivers/net/ethernet/intel/e1000e/phy.h
390 index c48777d095235..049bb325b4b14 100644
391 --- a/drivers/net/ethernet/intel/e1000e/phy.h
392 +++ b/drivers/net/ethernet/intel/e1000e/phy.h
393 @@ -51,6 +51,8 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data);
394 s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data);
395 void e1000_power_up_phy_copper(struct e1000_hw *hw);
396 void e1000_power_down_phy_copper(struct e1000_hw *hw);
397 +void e1000e_disable_phy_retry(struct e1000_hw *hw);
398 +void e1000e_enable_phy_retry(struct e1000_hw *hw);
399 s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
400 s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
401 s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data);