[PATCH net 1/2] net: dsa: mt7530: populate lpi_interfaces to fix EEE support
From: Aleksei Sviridkin
Date: Sat Aug 22 2026 - 15:54:29 EST
mt753x_phylink_get_caps() fills in config->lpi_capabilities and
config->lpi_timer_default, but never populates config->lpi_interfaces.
phylink only treats a MAC as supporting phylink managed EEE when the
tx_lpi methods are implemented and both the LPI capabilities and the
LPI interfaces are non-empty, so EEE is unavailable on every port:
# ethtool --show-eee lan1
Cannot get EEE settings: Not supported
even though the driver implements mac_enable_tx_lpi() and
mac_disable_tx_lpi() and reads the LPI threshold back out of PMEEECR.
Since the tx_lpi methods are implemented, phylink takes the other
branch and calls phy_disable_eee(), which fills eee_disabled_modes, so
userspace cannot enable EEE either.
Only the first half of what commit 06dfcd4098cf ("net: dsa: mt7530: fix
enabling EEE on MT7531 switch on all boards") arranged therefore
survives. It left EEE off out of the box on purpose, by having
mt7531_setup() clear the switch PHYs' EEE advertisement, and ended
"With this change, EEE can now be enabled using ethtool". It cannot be,
any more.
Copy the supported interfaces into lpi_interfaces. This requires moving
the mac_port_get_caps() call ahead of the EEE block, since that is what
populates supported_interfaces - copying it beforehand would copy an
empty bitmap.
LPI stays off by default. The driver does not set eee_enabled_default,
so phylink leaves tx_lpi_enabled false, and phy_check_link_status()
computes enable_tx_lpi as tx_lpi_enabled && eee_active - nothing
asserts LPI until userspace enables it with ethtool --set-eee. The EEE
advertisement is the part that does change: phylink no longer takes the
phy_disable_eee() branch, so a PHY that advertises EEE out of reset
advertises it again and the link may negotiate EEE. MT7531's five
internal PHYs are the exception, as mt7531_setup() zeroes
MDIO_AN_EEE_ADV before the switch MDIO bus is registered, so
phy_probe() reads an empty advertisement and records eee_cfg.eee_enabled
as false. Nothing does that for an external PHY on port 5 or 6, or on
the other mt753x variants, EN7528 aside - see below.
This also makes lpi_capabilities take effect for the first time, so
correct its value in the same change. PMCR only has force bits for
100 Mbps (PMCR_FORCE_EEE100) and 1 Gbps (PMCR_FORCE_EEE1G), and PMSR
only reports EEE state for those two speeds, so the MAC cannot signal
LPI at 2.5 Gbps: drop MAC_2500FD. Absence from the header is weak
evidence on its own, so for what it is worth, the Airoha AN8855 DSA
driver - posted but not merged [1] - describes a PMCR of the same shape
that does carry AN8855_PMCR_FORCE_EEE2P5G and AN8855_PMCR_FORCE_EEE5G
next to the 1 Gbps and 100 Mbps bits. Correcting the value here rather
than in a separate patch changes nothing observable: while
lpi_interfaces was empty, lpi_capabilities never reached
phy->advertising_eee, so no state ever claimed 2.5 Gbps LPI.
2500BASE-X has to come out of lpi_interfaces as well, because
lpi_capabilities cannot express it: it masks the PHY's EEE
advertisement, a media side property, and never gates LPI activation on
the MAC side speed. phylink raises the MAC speed to the interface
maximum when the PHY rate matches (RATE_MATCH_PAUSE in
phylink_link_up()), so a 1 Gbps media link behind a rate matching 2.5G
PHY would otherwise arm LPI while the MAC runs at 2.5 Gbps. What that
costs is limited to setups that keep the MAC on 2500BASE-X, where there
are no LPI bits to use anyway; a PHY that switches the interface down
to SGMII or 1000BASE-X keeps LPI, as those stay in the mask.
For the same reason, skip ports that support neither 100 Mbps nor
1 Gbps: on MT7988, EN7581 and AN7583, port 6 is 10 Gbps only, and it
shares PHY_INTERFACE_MODE_INTERNAL with the 1 Gbps user ports, so the
interface mask alone cannot tell them apart.
EEE remains unavailable on EN7528, whose GPHYs do not negotiate it
reliably. Both LPI bitmaps stay empty there, so phylink keeps taking
the phy_disable_eee() branch and its advertisement stays off.
[1] https://lore.kernel.org/r/20250315154407.26304-14-ansuelsmth@xxxxxxxxx
Fixes: 9cf21773f535 ("net: dsa: mt7530: convert to phylink managed EEE")
Signed-off-by: Aleksei Sviridkin <f@xxxxxx>
---
Two pre-existing things this patch makes live, neither addressed here:
- The unit of LPI_THRESH is still unspecified, as the comment above
lpi_timer_default says. With EEE reachable again, ethtool reports
that raw value as microseconds and writes userspace values back
unconverted, while mtk_eth_soc treats a structurally identical field
as milliseconds (DIV_ROUND_UP(timer, 1000)). Reading the default back
reproduces the same raw value whatever the unit is, but a timer set
from userspace in microseconds would be off by 1000 if the field is
in milliseconds. On an MT7531 board ethtool now reports 30 for a
switch port, which is the raw LPI_THRESH field; whether the hardware
means 30 microseconds is exactly the open question. Does anyone have
the datasheet answer?
- mt753x_phylink_mac_enable_tx_lpi() sets the PMCR force-EEE bits
without checking the resolved speed or interface, relying entirely on
phylink never calling it above 1 Gbps. A check there would make the
driver robust independently of lpi_interfaces being right;
deliberately not bundled into a fix.
drivers/net/dsa/mt7530.c | 24 +++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 2b7be091c056..17265eb79008 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -3172,23 +3172,37 @@ static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port,
config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE;
+ priv->info->mac_port_get_caps(ds, port, config);
+
/* The EN7528 GPHYs report EEE capability, but negotiating EEE with
* common link partners (e.g. Realtek GbE NICs) results in an unstable
* link with dropped frames. Leave the LPI capabilities empty so that
* phylink disables EEE on these PHYs and refuses to enable it from
- * userspace.
+ * userspace. Ports that run at neither 100 Mbps nor 1 Gbps are left
+ * empty too, as PMCR has no force bit that would apply to them.
*/
- if (priv->id != ID_EN7528) {
+ if (priv->id != ID_EN7528 &&
+ config->mac_capabilities & (MAC_100FD | MAC_1000FD)) {
u32 eeecr = mt7530_read(priv, MT753X_PMEEECR_P(port));
- config->lpi_capabilities = MAC_100FD | MAC_1000FD | MAC_2500FD;
+ /* PMCR only has force bits for 100 Mbps and 1 Gbps. That also
+ * rules out 2500BASE-X, which lpi_capabilities cannot express:
+ * it masks the PHY's EEE advertisement, a media side property,
+ * and never gates LPI activation on the MAC side speed. The
+ * MAC side of 2500BASE-X is never below 2.5 Gbps, not even
+ * when a rate matching PHY drops the media to 1 Gbps.
+ */
+ config->lpi_capabilities = MAC_100FD | MAC_1000FD;
+ phy_interface_copy(config->lpi_interfaces,
+ config->supported_interfaces);
+ __clear_bit(PHY_INTERFACE_MODE_2500BASEX,
+ config->lpi_interfaces);
+
/* tx_lpi_timer should be in microseconds. The time units for
* LPI threshold are unspecified.
*/
config->lpi_timer_default = FIELD_GET(LPI_THRESH_MASK, eeecr);
}
-
- priv->info->mac_port_get_caps(ds, port, config);
}
static int mt753x_pcs_validate(struct phylink_pcs *pcs,
--
2.55.0