]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: stmmac: address non-LPI resume failures properly
authorRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Thu, 20 Mar 2025 22:11:12 +0000 (22:11 +0000)
committerJakub Kicinski <kuba@kernel.org>
Tue, 25 Mar 2025 14:58:03 +0000 (07:58 -0700)
The Synopsys Designware GMAC core databook requires all clocks to be
active in order to complete software reset, which we perform during
resume.

However, IEEE 802.3 allows a PHY to stop its clocks when placed in
low-power mode, which happens when the system is suspended and WoL
is not enabled.

As an attempt to work around this, commit 36d18b5664ef ("net: stmmac:
start phylink instance before stmmac_hw_setup()") started phylink
early, but this has the side effect that the mac_link_up() method may
be called before or during the initialisation of GMAC hardware.

We also have the socfpga glue driver directly calling phy_resume()
also as an attempt to work around this.

In a previous commit, phylink_prepare_resume() has been introduced
to give MAC drivers a way to ensure that the PHY is resumed prior to
their initialisation of their MAC hardware. This commit adds the call,
and moves the phylink_resume() call back to where it should be before
the aforementioned commit.

Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Link: https://patch.msgid.link/E1tvO6a-008Vjh-FG@rmk-PC.armlinux.org.uk
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

index a6a533d8a45bebdd5ea4247cf2a5096e996e6d28..860f800cd014c47f756ebc015c361a7cfaba33e9 100644 (file)
@@ -7936,12 +7936,12 @@ int stmmac_resume(struct device *dev)
        }
 
        rtnl_lock();
-       phylink_resume(priv->phylink);
-       if (device_may_wakeup(priv->device) && !priv->plat->pmt)
-               phylink_speed_up(priv->phylink);
-       rtnl_unlock();
 
-       rtnl_lock();
+       /* Prepare the PHY to resume, ensuring that its clocks which are
+        * necessary for the MAC DMA reset to complete are running
+        */
+       phylink_prepare_resume(priv->phylink);
+
        mutex_lock(&priv->lock);
 
        stmmac_reset_queues_param(priv);
@@ -7959,6 +7959,15 @@ int stmmac_resume(struct device *dev)
        stmmac_enable_all_dma_irq(priv);
 
        mutex_unlock(&priv->lock);
+
+       /* phylink_resume() must be called after the hardware has been
+        * initialised because it may bring the link up immediately in a
+        * workqueue thread, which will race with initialisation.
+        */
+       phylink_resume(priv->phylink);
+       if (device_may_wakeup(priv->device) && !priv->plat->pmt)
+               phylink_speed_up(priv->phylink);
+
        rtnl_unlock();
 
        netif_device_attach(ndev);