From 3302126a9b2bf587aa8335c5de6bc2369aae5c46 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Tue, 3 Feb 2026 10:01:14 +0000 Subject: net: stmmac: add wrappers for serdes_power[up|down]() methods Add wrappers for the serdes_power[up|down]() methods and update all call sites. This will allow us to add state tracking. Signed-off-by: Russell King (Oracle) Link: https://patch.msgid.link/E1vnDDe-00000007Xww-2VUU@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 48 ++++++++++++++--------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 9500b332a152..93d18709bc13 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -882,6 +882,26 @@ static void stmmac_release_ptp(struct stmmac_priv *priv) clk_disable_unprepare(priv->plat->clk_ptp_ref); } +static void stmmac_legacy_serdes_power_down(struct stmmac_priv *priv) +{ + if (priv->plat->serdes_powerdown) + priv->plat->serdes_powerdown(priv->dev, priv->plat->bsp_priv); +} + +static int stmmac_legacy_serdes_power_up(struct stmmac_priv *priv) +{ + int ret; + + if (!priv->plat->serdes_powerup) + return 0; + + ret = priv->plat->serdes_powerup(priv->dev, priv->plat->bsp_priv); + if (ret < 0) + netdev_err(priv->dev, "SerDes powerup failed\n"); + + return ret; +} + /** * stmmac_mac_flow_ctrl - Configure flow control in all queues * @priv: driver private structure @@ -981,9 +1001,8 @@ static void stmmac_mac_link_up(struct phylink_config *config, u32 old_ctrl, ctrl; int ret; - if ((priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP) && - priv->plat->serdes_powerup) - priv->plat->serdes_powerup(priv->dev, priv->plat->bsp_priv); + if (priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP) + stmmac_legacy_serdes_power_up(priv); old_ctrl = readl(priv->ioaddr + MAC_CTRL_REG); ctrl = old_ctrl & ~priv->hw->link.speed_mask; @@ -4111,14 +4130,10 @@ static int __stmmac_open(struct net_device *dev, stmmac_reset_queues_param(priv); - if (!(priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP) && - priv->plat->serdes_powerup) { - ret = priv->plat->serdes_powerup(dev, priv->plat->bsp_priv); - if (ret < 0) { - netdev_err(priv->dev, "%s: Serdes powerup failed\n", - __func__); + if (!(priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP)) { + ret = stmmac_legacy_serdes_power_up(priv); + if (ret < 0) goto init_error; - } } ret = stmmac_hw_setup(dev); @@ -4222,8 +4237,7 @@ static void __stmmac_release(struct net_device *dev) free_dma_desc_resources(priv, &priv->dma_conf); /* Powerdown Serdes if there is */ - if (priv->plat->serdes_powerdown) - priv->plat->serdes_powerdown(dev, priv->plat->bsp_priv); + stmmac_legacy_serdes_power_down(priv); stmmac_release_ptp(priv); @@ -8130,8 +8144,7 @@ int stmmac_suspend(struct device *dev) /* Stop TX/RX DMA */ stmmac_stop_all_dma(priv); - if (priv->plat->serdes_powerdown) - priv->plat->serdes_powerdown(ndev, priv->plat->bsp_priv); + stmmac_legacy_serdes_power_down(priv); /* Enable Power down mode by programming the PMT regs */ if (priv->wolopts) { @@ -8233,11 +8246,8 @@ int stmmac_resume(struct device *dev) stmmac_mdio_reset(priv->mii); } - if (!(priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP) && - priv->plat->serdes_powerup) { - ret = priv->plat->serdes_powerup(ndev, - priv->plat->bsp_priv); - + if (!(priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP)) { + ret = stmmac_legacy_serdes_power_up(priv); if (ret < 0) return ret; } -- cgit v1.2.3 From 9bfcf5460b70161c161ee7041c5bb2ee6a82a219 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Tue, 3 Feb 2026 10:01:19 +0000 Subject: net: stmmac: add state tracking for legacy serdes power state Avoid calling the serdes_powerdown() method if we have not had a preceeding successful call to the serdes_powerup() method. This avoids unbalancing refcounted resources that may be used in the these platform glue serdes methods. Signed-off-by: Russell King (Oracle) Link: https://patch.msgid.link/E1vnDDj-00000007Xx3-2xZ0@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 012b0a477255..5bd97aaaba86 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -303,6 +303,7 @@ struct stmmac_priv { bool eee_enabled; bool eee_active; bool eee_sw_timer_en; + bool legacy_serdes_is_powered; unsigned int mode; unsigned int chain_mode; int extend_desc; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 93d18709bc13..9efdde915229 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -884,8 +884,10 @@ static void stmmac_release_ptp(struct stmmac_priv *priv) static void stmmac_legacy_serdes_power_down(struct stmmac_priv *priv) { - if (priv->plat->serdes_powerdown) + if (priv->plat->serdes_powerdown && priv->legacy_serdes_is_powered) priv->plat->serdes_powerdown(priv->dev, priv->plat->bsp_priv); + + priv->legacy_serdes_is_powered = false; } static int stmmac_legacy_serdes_power_up(struct stmmac_priv *priv) @@ -898,6 +900,8 @@ static int stmmac_legacy_serdes_power_up(struct stmmac_priv *priv) ret = priv->plat->serdes_powerup(priv->dev, priv->plat->bsp_priv); if (ret < 0) netdev_err(priv->dev, "SerDes powerup failed\n"); + else + priv->legacy_serdes_is_powered = true; return ret; } -- cgit v1.2.3 From 3019a1333e667ee7e1b6f7a236b5b4f81782870c Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Tue, 3 Feb 2026 10:01:24 +0000 Subject: net: stmmac: add missing serdes power down in error paths The open path is missing cleanup of a successful serdes power up if stmmac_hw_setup() or stmmac_request_irq() fails. stmmac_resume() is also missing cleanup of the serdes power up if stmmac_hw_setup() fails. Add the missing cleanups. Signed-off-by: Russell King (Oracle) Link: https://patch.msgid.link/E1vnDDo-00000007Xx9-3RZ8@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 9efdde915229..05b0b080bade 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -4137,7 +4137,7 @@ static int __stmmac_open(struct net_device *dev, if (!(priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP)) { ret = stmmac_legacy_serdes_power_up(priv); if (ret < 0) - goto init_error; + return ret; } ret = stmmac_hw_setup(dev); @@ -4170,6 +4170,7 @@ irq_error: stmmac_release_ptp(priv); init_error: + stmmac_legacy_serdes_power_down(priv); return ret; } @@ -8273,6 +8274,7 @@ int stmmac_resume(struct device *dev) ret = stmmac_hw_setup(ndev); if (ret < 0) { netdev_err(priv->dev, "%s: Hw setup failed\n", __func__); + stmmac_legacy_serdes_power_down(priv); mutex_unlock(&priv->lock); rtnl_unlock(); return ret; -- cgit v1.2.3 From 61aaa625371440938b55d703501f8820018f737e Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Tue, 3 Feb 2026 10:01:29 +0000 Subject: net: stmmac: move serdes power methods to stmmac_[open|release]() Move the SerDes power up and down calls for the non-"after linkup" case out of __stmmac_open() and __stmmac_release() into the stmmac_open() and stmmac_release() methods, which means the SerDes will only change power state on administrative changes or suspend/ resume, not while changing the interface MTU. Signed-off-by: Russell King (Oracle) Link: https://patch.msgid.link/E1vnDDt-00000007XxF-3uUK@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 05b0b080bade..d561b0a0f5ac 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -4134,12 +4134,6 @@ static int __stmmac_open(struct net_device *dev, stmmac_reset_queues_param(priv); - if (!(priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP)) { - ret = stmmac_legacy_serdes_power_up(priv); - if (ret < 0) - return ret; - } - ret = stmmac_hw_setup(dev); if (ret < 0) { netdev_err(priv->dev, "%s: Hw setup failed\n", __func__); @@ -4170,7 +4164,6 @@ irq_error: stmmac_release_ptp(priv); init_error: - stmmac_legacy_serdes_power_down(priv); return ret; } @@ -4196,9 +4189,15 @@ static int stmmac_open(struct net_device *dev) if (ret) goto err_runtime_pm; + if (!(priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP)) { + ret = stmmac_legacy_serdes_power_up(priv); + if (ret < 0) + goto err_disconnect_phy; + } + ret = __stmmac_open(dev, dma_conf); if (ret) - goto err_disconnect_phy; + goto err_serdes; kfree(dma_conf); @@ -4207,6 +4206,8 @@ static int stmmac_open(struct net_device *dev) return ret; +err_serdes: + stmmac_legacy_serdes_power_down(priv); err_disconnect_phy: phylink_disconnect_phy(priv->phylink); err_runtime_pm: @@ -4241,9 +4242,6 @@ static void __stmmac_release(struct net_device *dev) /* Release and free the Rx/Tx resources */ free_dma_desc_resources(priv, &priv->dma_conf); - /* Powerdown Serdes if there is */ - stmmac_legacy_serdes_power_down(priv); - stmmac_release_ptp(priv); if (stmmac_fpe_supported(priv)) @@ -4269,6 +4267,7 @@ static int stmmac_release(struct net_device *dev) __stmmac_release(dev); + stmmac_legacy_serdes_power_down(priv); phylink_disconnect_phy(priv->phylink); pm_runtime_put(priv->device); -- cgit v1.2.3