]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-6.6/e1000e-workaround-for-sporadic-mdi-error-on-meteor-l.patch
Fixes for 6.6
[thirdparty/kernel/stable-queue.git] / queue-6.6 / e1000e-workaround-for-sporadic-mdi-error-on-meteor-l.patch
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
5
6 From: Vitaly Lifshits <vitaly.lifshits@intel.com>
7
8 [ Upstream commit 6dbdd4de0362c37e54e8b049781402e5a409e7d0 ]
9
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.
13
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.
18
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>
27 ---
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(-)
33
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 {
39 u32 id;
40 u32 reset_delay_us; /* in usec */
41 u32 revision;
42 + u32 retry_count;
43
44 enum e1000_media_type media_type;
45
46 @@ -644,6 +645,7 @@ struct e1000_phy_info {
47 bool polarity_correction;
48 bool speed_downgraded;
49 bool autoneg_wait_to_complete;
50 + bool retry_enabled;
51 };
52
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
64 + */
65 + e1000e_disable_phy_retry(hw);
66 +
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);
71
72 + e1000e_enable_phy_retry(hw);
73 +
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)
78 goto out;
79 }
80
81 + /* There is no guarantee that the PHY is accessible at this time
82 + * so disable retry mechanism to avoid wasting time
83 + */
84 + e1000e_disable_phy_retry(hw);
85 +
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)
90 break;
91 }
92
93 + e1000e_enable_phy_retry(hw);
94 +
95 hw->phy.ops.release(hw);
96 if (!ret_val) {
97
98 @@ -449,6 +463,11 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
99
100 phy->id = e1000_phy_unknown;
101
102 + if (hw->mac.type == e1000_pch_mtp) {
103 + phy->retry_count = 2;
104 + e1000e_enable_phy_retry(hw);
105 + }
106 +
107 ret_val = e1000_init_phy_workarounds_pchlan(hw);
108 if (ret_val)
109 return ret_val;
110 @@ -1146,6 +1165,11 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
111 if (ret_val)
112 goto out;
113
114 + /* Switching PHY interface always returns MDI error
115 + * so disable retry mechanism to avoid wasting time
116 + */
117 + e1000e_disable_phy_retry(hw);
118 +
119 /* Force SMBus mode in PHY */
120 ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg);
121 if (ret_val)
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);
125
126 + e1000e_enable_phy_retry(hw);
127 +
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);
134
135 + /* Switching PHY interface always returns MDI error
136 + * so disable retry mechanism to avoid wasting time
137 + */
138 + e1000e_disable_phy_retry(hw);
139 +
140 /* Unforce SMBus mode in PHY */
141 ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg);
142 if (ret_val) {
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);
146
147 + e1000e_enable_phy_retry(hw);
148 +
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);
158 }
159
160 +void e1000e_disable_phy_retry(struct e1000_hw *hw)
161 +{
162 + hw->phy.retry_enabled = false;
163 +}
164 +
165 +void e1000e_enable_phy_retry(struct e1000_hw *hw)
166 +{
167 + hw->phy.retry_enabled = true;
168 +}
169 +
170 /**
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)
174 **/
175 s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
176 {
177 + u32 i, mdic = 0, retry_counter, retry_max;
178 struct e1000_phy_info *phy = &hw->phy;
179 - u32 i, mdic = 0;
180 + bool success;
181
182 if (offset > MAX_PHY_REG_ADDRESS) {
183 e_dbg("PHY Address %d is out of range\n", offset);
184 return -E1000_ERR_PARAM;
185 }
186
187 + retry_max = phy->retry_enabled ? phy->retry_count : 0;
188 +
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.
192 */
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++) {
197 + success = true;
198
199 - ew32(MDIC, mdic);
200 + mdic = ((offset << E1000_MDIC_REG_SHIFT) |
201 + (phy->addr << E1000_MDIC_PHY_SHIFT) |
202 + (E1000_MDIC_OP_READ));
203
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
207 - */
208 - for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
209 - udelay(50);
210 - mdic = er32(MDIC);
211 - if (mdic & E1000_MDIC_READY)
212 - break;
213 - }
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;
217 - }
218 - if (mdic & E1000_MDIC_ERROR) {
219 - e_dbg("MDI Read PHY Reg Address %d Error\n", offset);
220 - return -E1000_ERR_PHY;
221 - }
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;
226 + ew32(MDIC, mdic);
227 +
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
231 + */
232 + for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
233 + usleep_range(50, 60);
234 + mdic = er32(MDIC);
235 + if (mdic & E1000_MDIC_READY)
236 + break;
237 + }
238 + if (!(mdic & E1000_MDIC_READY)) {
239 + e_dbg("MDI Read PHY Reg Address %d did not complete\n",
240 + offset);
241 + success = false;
242 + }
243 + if (mdic & E1000_MDIC_ERROR) {
244 + e_dbg("MDI Read PHY Reg Address %d Error\n", offset);
245 + success = false;
246 + }
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));
250 + success = false;
251 + }
252 +
253 + /* Allow some time after each MDIC transaction to avoid
254 + * reading duplicate data in the next MDIC transaction.
255 + */
256 + if (hw->mac.type == e1000_pch2lan)
257 + usleep_range(100, 150);
258 +
259 + if (success) {
260 + *data = (u16)mdic;
261 + return 0;
262 + }
263 +
264 + if (retry_counter != retry_max) {
265 + e_dbg("Perform retry on PHY transaction...\n");
266 + mdelay(10);
267 + }
268 }
269 - *data = (u16)mdic;
270
271 - /* Allow some time after each MDIC transaction to avoid
272 - * reading duplicate data in the next MDIC transaction.
273 - */
274 - if (hw->mac.type == e1000_pch2lan)
275 - udelay(100);
276 - return 0;
277 + return -E1000_ERR_PHY;
278 }
279
280 /**
281 @@ -179,56 +207,72 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
282 **/
283 s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
284 {
285 + u32 i, mdic = 0, retry_counter, retry_max;
286 struct e1000_phy_info *phy = &hw->phy;
287 - u32 i, mdic = 0;
288 + bool success;
289
290 if (offset > MAX_PHY_REG_ADDRESS) {
291 e_dbg("PHY Address %d is out of range\n", offset);
292 return -E1000_ERR_PARAM;
293 }
294
295 + retry_max = phy->retry_enabled ? phy->retry_count : 0;
296 +
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.
300 */
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++) {
306 + success = true;
307
308 - ew32(MDIC, mdic);
309 + mdic = (((u32)data) |
310 + (offset << E1000_MDIC_REG_SHIFT) |
311 + (phy->addr << E1000_MDIC_PHY_SHIFT) |
312 + (E1000_MDIC_OP_WRITE));
313
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
317 - */
318 - for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
319 - udelay(50);
320 - mdic = er32(MDIC);
321 - if (mdic & E1000_MDIC_READY)
322 - break;
323 - }
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;
327 - }
328 - if (mdic & E1000_MDIC_ERROR) {
329 - e_dbg("MDI Write PHY Red Address %d Error\n", offset);
330 - return -E1000_ERR_PHY;
331 - }
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;
336 - }
337 + ew32(MDIC, mdic);
338
339 - /* Allow some time after each MDIC transaction to avoid
340 - * reading duplicate data in the next MDIC transaction.
341 - */
342 - if (hw->mac.type == e1000_pch2lan)
343 - udelay(100);
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
347 + */
348 + for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
349 + usleep_range(50, 60);
350 + mdic = er32(MDIC);
351 + if (mdic & E1000_MDIC_READY)
352 + break;
353 + }
354 + if (!(mdic & E1000_MDIC_READY)) {
355 + e_dbg("MDI Write PHY Reg Address %d did not complete\n",
356 + offset);
357 + success = false;
358 + }
359 + if (mdic & E1000_MDIC_ERROR) {
360 + e_dbg("MDI Write PHY Reg Address %d Error\n", offset);
361 + success = false;
362 + }
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));
366 + success = false;
367 + }
368
369 - return 0;
370 + /* Allow some time after each MDIC transaction to avoid
371 + * reading duplicate data in the next MDIC transaction.
372 + */
373 + if (hw->mac.type == e1000_pch2lan)
374 + usleep_range(100, 150);
375 +
376 + if (success)
377 + return 0;
378 +
379 + if (retry_counter != retry_max) {
380 + e_dbg("Perform retry on PHY transaction...\n");
381 + mdelay(10);
382 + }
383 + }
384 +
385 + return -E1000_ERR_PHY;
386 }
387
388 /**
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);
402 --
403 2.43.0
404