[PATCH net v2] net: dsa: mt7530: do not advertise EEE on MT7621/MT7530 switch
Vladislav Karmanov <[email protected]>
| Newsgroups | org.infradead.lists.linux-mediatek,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel,org.kernel.vger.netdev |
|---|---|
| Message-ID | <[email protected]> |
From: Shiji Yang <[email protected]> There are hardware defects in the MT7530 internal GE PHY EEE support: with EEE advertised, some link partners cannot establish a stable connection. On a 2-pair (4-wire) cable where both ends advertise gigabit, 1000BASE-T training cannot succeed, and instead of falling back to 100 Mbps the port flaps in a loop and no link/DHCP lease is obtained. This is confined to the WAN / phylib bring-up path; the DSA/LAN side on the same device is unaffected. The MT7530 internal GE PHY advertises EEE by hardware default. The eee-broken-100tx / eee-broken-1000t device-tree properties only take effect during the late PHY config_init path, which is too late for these link partners: they negotiate EEE before the OS disables it and then fail to fall back cleanly. Commit af3b4b0e59de ("net: phy: mediatek-ge: do not disable EEE advertisement") removed the early EEE-advertisement disable from mtk_gephy_config_init(), on the rationale that "disabling EEE advertisement before the PHY driver initialises keeps it off", i.e. that the DSA subdriver already performs that early disable. That rationale holds for MT7531, whose mt7531_setup() clears MDIO_AN_EEE_ADV on each switch PHY, but not for MT7621 (and the dedicated MT7530 IC), whose mt7530_setup() never had such a loop. So af3b4b0e59de removed the only early EEE disable covering MT7621/MT7530, reintroducing the flapping. Regarding the MAC-vs-PHY question: the broken hardware is the PHY (the MT7530 internal GE PHY, PHY ID 0x03a29412, driven by mediatek-ge), and MediaTek's own recommendation (Landen Chao, 2021) confirms it: "EEE of the 10-year-old MT7530 internal gephy has many IOT problems, so it is recommended to disable its EEE." However, the disable belongs on the DSA side, not in the PHY driver: af3b4b0e59de itself established that the PHY-driver-side disable "is somehow enabled afterwards" (it does not stick), whereas the early disable done in the DSA setup path is what keeps EEE off -- which is exactly why MT7531 does it in mt7531_setup() and why af3b4b0e59de considered the mtk-ge disable redundant for MT7531. Restore the early disable for the affected silicon by clearing MDIO_AN_EEE_ADV on each switch PHY in mt7530_setup(), gated on a new `broken_eee` flag in struct mt753x_info rather than an open-coded ID check, mirroring the existing mt7531_setup() loop. Set broken_eee for ID_MT7621 and ID_MT7530, which share the same mt7530_setup() and the same internal GE PHY. Auto-negotiation then falls back to a stable 100 Mbps link instead of hanging at gigabit. Tested on ASUS RT-AX53U (MT7621): a single clean "Link is Up - 100Mbps/Full - flow control off" + DHCP lease on a 2-pair cable, where the unpatched driver loops. Confirmed on kernel 6.12 and 6.18; also confirmed on Netgear R6220 and EdgeRouter-X (both MT7621). Fixes: af3b4b0e59de ("net: phy: mediatek-ge: do not disable EEE advertisement") Signed-off-by: Shiji Yang <[email protected]> Signed-off-by: Vladislav Karmanov <[email protected]> --- Changes in v2: - Gate the disable on a new `broken_eee` flag in struct mt753x_info instead of an open-coded priv->id == ID_MT7621 check, so it is easy to extend to further affected silicon (suggested by Daniel Golle). - Cover ID_MT7530 (the dedicated MT7530 IC, e.g. BananaPi R2) in addition to ID_MT7621: both share mt7530_setup() and the same internal GE PHY (suggested by Daniel Golle). - Address the MAC-vs-PHY placement question in the commit message: the broken hardware is the PHY, but the disable belongs on the DSA side because af3b4b0e59de showed the PHY-driver-side disable does not stick (question by Andrew Lunn). v1: https://lore.kernel.org/netdev/[email protected]/ drivers/net/dsa/mt7530.c | 11 +++++++++++ drivers/net/dsa/mt7530.h | 1 + 2 files changed, 12 insertions(+) diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 2a70fa4..cab46c6 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -2446,6 +2446,15 @@ mt7530_setup(struct dsa_switch *ds) if ((val & MT7530_XTAL_MASK) == MT7530_XTAL_40MHZ) mt7530_pll_setup(priv); + if (priv->info->broken_eee) { + /* Disable EEE advertisement on the switch PHYs. */ + for (i = MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr); + i < MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr) + MT7530_NUM_PHYS; + i++) { + mt7530_phy_write_c45(priv, i, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0); + } + } + mt753x_trap_frames(priv); /* Enable and reset MIB counters */ @@ -3298,6 +3307,7 @@ static const struct phylink_mac_ops mt753x_phylink_mac_ops = { const struct mt753x_info mt753x_table[] = { [ID_MT7621] = { .id = ID_MT7621, + .broken_eee = true, .pcs_ops = &mt7530_pcs_ops, .sw_setup = mt7530_setup, .phy_read_c22 = mt7530_phy_read_c22, @@ -3309,6 +3319,7 @@ const struct mt753x_info mt753x_table[] = { }, [ID_MT7530] = { .id = ID_MT7530, + .broken_eee = true, .pcs_ops = &mt7530_pcs_ops, .sw_setup = mt7530_setup, .phy_read_c22 = mt7530_phy_read_c22, diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h index 7e47cd9..fff310f 100644 --- a/drivers/net/dsa/mt7530.h +++ b/drivers/net/dsa/mt7530.h @@ -851,6 +851,7 @@ struct mt753x_info { void (*mac_port_config)(struct dsa_switch *ds, int port, unsigned int mode, phy_interface_t interface); + bool broken_eee; }; /* struct mt7530_priv - This is the main data structure for holding the state -- 2.43.0