]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/6.6.26/e1000e-workaround-for-sporadic-mdi-error-on-meteor-l.patch
Linux 6.6.26
[thirdparty/kernel/stable-queue.git] / releases / 6.6.26 / e1000e-workaround-for-sporadic-mdi-error-on-meteor-l.patch
CommitLineData
7e19d03b
SL
1From e4d37a59973992e085fd0f2453b8845ce2f9a98d Mon Sep 17 00:00:00 2001
2From: Sasha Levin <sashal@kernel.org>
3Date: Thu, 4 Jan 2024 16:16:52 +0200
4Subject: e1000e: Workaround for sporadic MDI error on Meteor Lake systems
5
6From: Vitaly Lifshits <vitaly.lifshits@intel.com>
7
8[ Upstream commit 6dbdd4de0362c37e54e8b049781402e5a409e7d0 ]
9
10On some Meteor Lake systems accessing the PHY via the MDIO interface may
11result in an MDI error. This issue happens sporadically and in most cases
12a second access to the PHY via the MDIO interface results in success.
13
14As a workaround, introduce a retry counter which is set to 3 on Meteor
15Lake systems. The driver will only return an error if 3 consecutive PHY
16access attempts fail. The retry mechanism is disabled in specific flows,
17where MDI errors are expected.
18
19Fixes: cc23f4f0b6b9 ("e1000e: Add support for Meteor Lake")
20Suggested-by: Nikolay Mushayev <nikolay.mushayev@intel.com>
21Co-developed-by: Nir Efrati <nir.efrati@intel.com>
22Signed-off-by: Nir Efrati <nir.efrati@intel.com>
23Signed-off-by: Vitaly Lifshits <vitaly.lifshits@intel.com>
24Tested-by: Naama Meir <naamax.meir@linux.intel.com>
25Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
26Signed-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
34diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h
35index 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 {
54diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
55index 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;
152diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c
153index 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 /**
389diff --git a/drivers/net/ethernet/intel/e1000e/phy.h b/drivers/net/ethernet/intel/e1000e/phy.h
390index 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--
4032.43.0
404