* [PATCH net v5 1/2] net: dsa: mt7530: populate lpi_interfaces to fix EEE support
2026-09-03 12:36 [PATCH net v5 0/2] net: restore EEE on MediaTek switches and SoC MACs Aleksei Sviridkin
@ 2026-09-03 12:36 ` Aleksei Sviridkin
2026-09-03 12:36 ` [PATCH net v5 2/2] net: ethernet: mtk_eth_soc: " Aleksei Sviridkin
1 sibling, 0 replies; 3+ messages in thread
From: Aleksei Sviridkin @ 2026-09-03 12:36 UTC (permalink / raw)
To: chester.a.unal, daniel, andrew, olteanv, nbd, lorenzo, davem,
edumazet, kuba, pabeni, netdev
Cc: linux, dqfext, matthias.bgg, angelogioacchino.delregno,
linux-kernel, linux-arm-kernel, linux-mediatek
phylink_create() decides once and for all that a MAC supports managed
EEE, and it requires the tx_lpi ops plus non-empty lpi_capabilities and
lpi_interfaces. mt753x_phylink_get_caps() leaves lpi_interfaces empty.
So ever since the conversion to phylink managed EEE, ethtool has
answered "Not supported" on every mt753x port, and phy_disable_eee()
has locked userspace out of turning EEE on. That undoes what
commit 06dfcd4098cf ("net: dsa: mt7530: fix enabling EEE on MT7531
switch on all boards") arranged: EEE off by default, but reachable
with ethtool.
Leave the speeds above 1 Gbps out of both bitmaps. PMCR folds
SPEED_2500 and SPEED_10000 onto PMCR_FORCE_SPEED_1000, so
PMCR_FORCE_EEE1G would govern LPI on such a link, and that is
unvalidated rather than known unsupported: MediaTek's SDK driver sets
the EEE force bits for 100 Mbps and 1 Gbps only, and the unit of the
wakeup timers is undocumented with the port clock at 2.5 times the
rate.
LPI stays off until userspace enables it, but the EEE advertisement of
a PHY that advertises it out of reset comes back, since phylink stops
force-clearing it.
Fixes: 9cf21773f535 ("net: dsa: mt7530: convert to phylink managed EEE")
Signed-off-by: Aleksei Sviridkin <f@lex.la>
---
Ports that support neither 100 Mbps nor 1 Gbps are skipped because on
MT7988, EN7581 and AN7583 port 6 is 10 Gbps only and shares
PHY_INTERFACE_MODE_INTERNAL with the user ports, so the interface mask
alone cannot tell them apart. MT7531's internal PHYs keep the
advertisement mt7531_setup() zeroed and EN7528 keeps both bitmaps
empty, so EEE stays fully off there.
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. Before the phylink conversion
mt753x_set_mac_eee() wrote tx_lpi_timer into the field directly, so
the raw unit has always been what ethtool showed on these ports.
- 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.
v2, with the full argument for leaving the higher speeds out:
https://lore.kernel.org/netdev/20260824024117.46154-2-f@lex.la/
v4: lpi_capabilities is mac_capabilities masked to the two speeds
instead of both asserted. Every port that reaches the guard today has
both speeds, so nothing changes; it only stops the bitmap from claiming
a speed a port cannot link at.
v5: comments cut to one line (Maxime Chevallier); no code change.
drivers/net/dsa/mt7530.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 2b7be091c056..3e61eb3c2b1e 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -3172,23 +3172,31 @@ 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.
*/
- 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;
+ /* LPI above 1 Gbps is not supported */
+ config->lpi_capabilities = config->mac_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.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH net v5 2/2] net: ethernet: mtk_eth_soc: populate lpi_interfaces to fix EEE support
2026-09-03 12:36 [PATCH net v5 0/2] net: restore EEE on MediaTek switches and SoC MACs Aleksei Sviridkin
2026-09-03 12:36 ` [PATCH net v5 1/2] net: dsa: mt7530: populate lpi_interfaces to fix EEE support Aleksei Sviridkin
@ 2026-09-03 12:36 ` Aleksei Sviridkin
1 sibling, 0 replies; 3+ messages in thread
From: Aleksei Sviridkin @ 2026-09-03 12:36 UTC (permalink / raw)
To: chester.a.unal, daniel, andrew, olteanv, nbd, lorenzo, davem,
edumazet, kuba, pabeni, netdev
Cc: linux, dqfext, matthias.bgg, angelogioacchino.delregno,
linux-kernel, linux-arm-kernel, linux-mediatek
phylink_create() decides once and for all that a MAC supports managed
EEE, and it requires the tx_lpi ops plus non-empty lpi_capabilities and
lpi_interfaces. mtk_add_mac() leaves lpi_interfaces empty.
So ever since EEE support was added, ethtool has answered "Not
supported" on every MAC that uses mtk_phylink_ops, and
phy_disable_eee() has locked userspace out of turning EEE on. MT7628
is unaffected, as rt5350_phylink_ops has no tx_lpi methods.
Leave 2.5 Gbps out of both bitmaps, and the xGMII modes that
mtk_mac_enable_tx_lpi() already refuses. MAC_MCR folds SPEED_2500 onto
MAC_MCR_SPEED_1000, so MAC_MCR_EEE1G would govern LPI on such a link,
and that is unvalidated rather than known unsupported: MediaTek's SDK
driver sets the EEE force bits for 100 Mbps and 1 Gbps only, and the
unit of the wakeup timers is undocumented with the port clock at
2.5 times the rate.
mtk_mac_enable_tx_lpi() programs wake-up times taken from MT7531's
reset values, and the SoC's own field has no reset value to fall
back on. Only MT7981 has been seen to exit LPI cleanly with them, so
the LPI interfaces sit behind a new MTK_GMAC_EEE capability that only
MT7981 sets; every other SoC keeps the current behaviour until it has
been confirmed.
LPI stays off until userspace enables it, but the EEE advertisement of
a PHY that advertises it out of reset comes back, since phylink stops
force-clearing it.
Fixes: 952d7325362f ("net: ethernet: mediatek: add EEE support")
Signed-off-by: Aleksei Sviridkin <f@lex.la>
---
On the netsys v3 switch MAC the xGMII filter would empty lpi_interfaces
outright, as PHY_INTERFACE_MODE_INTERNAL is the only interface it
supports. MT7988 does not carry MTK_GMAC_EEE, so this is moot for now.
mtk_mac_enable_tx_lpi() programs MT7531's reset wakeup times (17 for
1 Gbps, 36 for 100 Mbps) whenever it runs, as its own comment says. The
capability gate exists because of that: MT7981 has been measured with
them (see the cover), the other SoCs have not, so they keep EEE
unreachable from userspace as before.
v2, with the full argument for leaving 2.5 Gbps out:
https://lore.kernel.org/netdev/20260824024117.46154-3-f@lex.la/
v4: the MTK_GMAC_EEE gate (Paolo Abeni).
v5: comments cut to one line (Maxime Chevallier); no code change.
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 18 +++++++++++++++---
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 +++-
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index be3bd025c41a..fd7a49ae88d0 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -4828,7 +4828,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
phy_interface_t phy_mode;
struct phylink *phylink;
struct mtk_mac *mac;
- int id, err;
+ int id, err, i;
int txqs = 1;
u32 val;
@@ -4907,8 +4907,8 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
mac->phylink_config.type = PHYLINK_NETDEV;
mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
- mac->phylink_config.lpi_capabilities = MAC_100FD | MAC_1000FD |
- MAC_2500FD;
+ /* LPI above 1 Gbps is not supported */
+ mac->phylink_config.lpi_capabilities = MAC_100FD | MAC_1000FD;
mac->phylink_config.lpi_timer_default = 1000;
/* MT7623 gmac0 is now missing its speed-specific PLL configuration
@@ -4966,6 +4966,18 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
mac->phylink_config.supported_interfaces);
+ /* LPI wake-up timing is only verified on MTK_GMAC_EEE SoCs */
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC_EEE)) {
+ phy_interface_copy(mac->phylink_config.lpi_interfaces,
+ mac->phylink_config.supported_interfaces);
+ __clear_bit(PHY_INTERFACE_MODE_2500BASEX,
+ mac->phylink_config.lpi_interfaces);
+ for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
+ if (mtk_interface_mode_is_xgmii(eth, i))
+ __clear_bit(i,
+ mac->phylink_config.lpi_interfaces);
+ }
+
phylink = phylink_create(&mac->phylink_config,
of_fwnode_handle(mac->of_node),
phy_mode, mac_ops);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 0168e2fbc619..88a9b3b23bea 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -994,6 +994,7 @@ enum mkt_eth_capabilities {
MTK_U3_COPHY_V2_BIT,
MTK_SRAM_BIT,
MTK_36BIT_DMA_BIT,
+ MTK_GMAC_EEE_BIT,
/* MUX BITS*/
MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT,
@@ -1034,6 +1035,7 @@ enum mkt_eth_capabilities {
#define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT)
#define MTK_SRAM BIT_ULL(MTK_SRAM_BIT)
#define MTK_36BIT_DMA BIT_ULL(MTK_36BIT_DMA_BIT)
+#define MTK_GMAC_EEE BIT_ULL(MTK_GMAC_EEE_BIT)
#define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \
BIT_ULL(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT)
@@ -1117,7 +1119,7 @@ enum mkt_eth_capabilities {
#define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \
MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \
- MTK_RSTCTRL_PPE1 | MTK_SRAM)
+ MTK_RSTCTRL_PPE1 | MTK_SRAM | MTK_GMAC_EEE)
#define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread