Skip to content

Commit 3c78f91

Browse files
committed
Merge branch 'net-phy-smsc-robustness-fixes-for-lan87xx-lan9500'
Oleksij Rempel says: ==================== net: phy: smsc: robustness fixes for LAN87xx/LAN9500 The SMSC 10/100 PHYs (LAN87xx family) found in smsc95xx (lan95xx) USB-Ethernet adapters show several quirks around the Auto-MDIX feature: - A hardware strap (AUTOMDIX_EN) may boot the PHY in fixed-MDI mode, and the current driver cannot always override it. - When Auto-MDIX is left enabled while autonegotiation is forced off, the PHY endlessly swaps the TX/RX pairs and never links up. - The driver sets the enable bit for Auto-MDIX but forgets the override bit, so userspace requests are silently ignored. - Rapid configuration changes can wedge the link if PHY IRQs are enabled. The four patches below make the MDIX state fully predictable and prevent link failures in every tested strap / autoneg / MDI-X permutation. Tested on LAN9512 Eval board. ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 78b7920 + 9dfe110 commit 3c78f91

File tree

1 file changed

+52
-5
lines changed

1 file changed

+52
-5
lines changed

drivers/net/phy/smsc.c

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,29 @@ static int smsc_phy_reset(struct phy_device *phydev)
155155

156156
static int lan87xx_config_aneg(struct phy_device *phydev)
157157
{
158-
int rc;
158+
u8 mdix_ctrl;
159159
int val;
160+
int rc;
161+
162+
/* When auto-negotiation is disabled (forced mode), the PHY's
163+
* Auto-MDIX will continue toggling the TX/RX pairs.
164+
*
165+
* To establish a stable link, we must select a fixed MDI mode.
166+
* If the user has not specified a fixed MDI mode (i.e., mdix_ctrl is
167+
* 'auto'), we default to ETH_TP_MDI. This choice of a ETH_TP_MDI mode
168+
* mirrors the behavior the hardware would exhibit if the AUTOMDIX_EN
169+
* strap were configured for a fixed MDI connection.
170+
*/
171+
if (phydev->autoneg == AUTONEG_DISABLE) {
172+
if (phydev->mdix_ctrl == ETH_TP_MDI_AUTO)
173+
mdix_ctrl = ETH_TP_MDI;
174+
else
175+
mdix_ctrl = phydev->mdix_ctrl;
176+
} else {
177+
mdix_ctrl = phydev->mdix_ctrl;
178+
}
160179

161-
switch (phydev->mdix_ctrl) {
180+
switch (mdix_ctrl) {
162181
case ETH_TP_MDI:
163182
val = SPECIAL_CTRL_STS_OVRRD_AMDIX_;
164183
break;
@@ -167,7 +186,8 @@ static int lan87xx_config_aneg(struct phy_device *phydev)
167186
SPECIAL_CTRL_STS_AMDIX_STATE_;
168187
break;
169188
case ETH_TP_MDI_AUTO:
170-
val = SPECIAL_CTRL_STS_AMDIX_ENABLE_;
189+
val = SPECIAL_CTRL_STS_OVRRD_AMDIX_ |
190+
SPECIAL_CTRL_STS_AMDIX_ENABLE_;
171191
break;
172192
default:
173193
return genphy_config_aneg(phydev);
@@ -183,7 +203,7 @@ static int lan87xx_config_aneg(struct phy_device *phydev)
183203
rc |= val;
184204
phy_write(phydev, SPECIAL_CTRL_STS, rc);
185205

186-
phydev->mdix = phydev->mdix_ctrl;
206+
phydev->mdix = mdix_ctrl;
187207
return genphy_config_aneg(phydev);
188208
}
189209

@@ -261,6 +281,33 @@ int lan87xx_read_status(struct phy_device *phydev)
261281
}
262282
EXPORT_SYMBOL_GPL(lan87xx_read_status);
263283

284+
static int lan87xx_phy_config_init(struct phy_device *phydev)
285+
{
286+
int rc;
287+
288+
/* The LAN87xx PHY's initial MDI-X mode is determined by the AUTOMDIX_EN
289+
* hardware strap, but the driver cannot read the strap's status. This
290+
* creates an unpredictable initial state.
291+
*
292+
* To ensure consistent and reliable behavior across all boards,
293+
* override the strap configuration on initialization and force the PHY
294+
* into a known state with Auto-MDIX enabled, which is the expected
295+
* default for modern hardware.
296+
*/
297+
rc = phy_modify(phydev, SPECIAL_CTRL_STS,
298+
SPECIAL_CTRL_STS_OVRRD_AMDIX_ |
299+
SPECIAL_CTRL_STS_AMDIX_ENABLE_ |
300+
SPECIAL_CTRL_STS_AMDIX_STATE_,
301+
SPECIAL_CTRL_STS_OVRRD_AMDIX_ |
302+
SPECIAL_CTRL_STS_AMDIX_ENABLE_);
303+
if (rc < 0)
304+
return rc;
305+
306+
phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
307+
308+
return smsc_phy_config_init(phydev);
309+
}
310+
264311
static int lan874x_phy_config_init(struct phy_device *phydev)
265312
{
266313
u16 val;
@@ -695,7 +742,7 @@ static struct phy_driver smsc_phy_driver[] = {
695742

696743
/* basic functions */
697744
.read_status = lan87xx_read_status,
698-
.config_init = smsc_phy_config_init,
745+
.config_init = lan87xx_phy_config_init,
699746
.soft_reset = smsc_phy_reset,
700747
.config_aneg = lan87xx_config_aneg,
701748

0 commit comments

Comments
 (0)