Skip to content

Commit 90702dc

Browse files
Joakim Zhangdavem330
authored andcommitted
net: stmmac: fix MAC not working when system resume back with WoL active
We can reproduce this issue with below steps: 1) enable WoL on the host 2) host system suspended 3) remote client send out wakeup packets We can see that host system resume back, but can't work, such as ping failed. After a bit digging, this issue is introduced by the commit 46f69de ("net: stmmac: Use resolved link config in mac_link_up()"), which use the finalised link parameters in mac_link_up() rather than the parameters in mac_config(). There are two scenarios for MAC suspend/resume in STMMAC driver: 1) MAC suspend with WoL inactive, stmmac_suspend() call phylink_mac_change() to notify phylink machine that a change in MAC state, then .mac_link_down callback would be invoked. Further, it will call phylink_stop() to stop the phylink instance. When MAC resume back, firstly phylink_start() is called to start the phylink instance, then call phylink_mac_change() which will finally trigger phylink machine to invoke .mac_config and .mac_link_up callback. All is fine since configuration in these two callbacks will be initialized, that means MAC can restore the state. 2) MAC suspend with WoL active, phylink_mac_change() will put link down, but there is no phylink_stop() to stop the phylink instance, so it will link up again, that means .mac_config and .mac_link_up would be invoked before system suspended. After system resume back, it will do DMA initialization and SW reset which let MAC lost the hardware setting (i.e MAC_Configuration register(offset 0x0) is reset). Since link is up before system suspended, so .mac_link_up would not be invoked after system resume back, lead to there is no chance to initialize the configuration in .mac_link_up callback, as a result, MAC can't work any longer. After discussed with Russell King [1], we confirm that phylink framework have not take WoL into consideration yet. This patch calls phylink_suspend()/phylink_resume() functions which is newly introduced by Russell King to fix this issue. [1] https://lore.kernel.org/netdev/[email protected]/ Fixes: 46f69de ("net: stmmac: Use resolved link config in mac_link_up()") Signed-off-by: Joakim Zhang <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f974936 commit 90702dc

File tree

1 file changed

+18
-18
lines changed

1 file changed

+18
-18
lines changed

drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7123,8 +7123,6 @@ int stmmac_suspend(struct device *dev)
71237123
if (!ndev || !netif_running(ndev))
71247124
return 0;
71257125

7126-
phylink_mac_change(priv->phylink, false);
7127-
71287126
mutex_lock(&priv->lock);
71297127

71307128
netif_device_detach(ndev);
@@ -7150,14 +7148,6 @@ int stmmac_suspend(struct device *dev)
71507148
stmmac_pmt(priv, priv->hw, priv->wolopts);
71517149
priv->irq_wake = 1;
71527150
} else {
7153-
mutex_unlock(&priv->lock);
7154-
rtnl_lock();
7155-
if (device_may_wakeup(priv->device))
7156-
phylink_speed_down(priv->phylink, false);
7157-
phylink_stop(priv->phylink);
7158-
rtnl_unlock();
7159-
mutex_lock(&priv->lock);
7160-
71617151
stmmac_mac_set(priv, priv->ioaddr, false);
71627152
pinctrl_pm_select_sleep_state(priv->device);
71637153
/* Disable clock in case of PWM is off */
@@ -7171,6 +7161,16 @@ int stmmac_suspend(struct device *dev)
71717161

71727162
mutex_unlock(&priv->lock);
71737163

7164+
rtnl_lock();
7165+
if (device_may_wakeup(priv->device) && priv->plat->pmt) {
7166+
phylink_suspend(priv->phylink, true);
7167+
} else {
7168+
if (device_may_wakeup(priv->device))
7169+
phylink_speed_down(priv->phylink, false);
7170+
phylink_suspend(priv->phylink, false);
7171+
}
7172+
rtnl_unlock();
7173+
71747174
if (priv->dma_cap.fpesel) {
71757175
/* Disable FPE */
71767176
stmmac_fpe_configure(priv, priv->ioaddr,
@@ -7261,13 +7261,15 @@ int stmmac_resume(struct device *dev)
72617261
return ret;
72627262
}
72637263

7264-
if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
7265-
rtnl_lock();
7266-
phylink_start(priv->phylink);
7267-
/* We may have called phylink_speed_down before */
7268-
phylink_speed_up(priv->phylink);
7269-
rtnl_unlock();
7264+
rtnl_lock();
7265+
if (device_may_wakeup(priv->device) && priv->plat->pmt) {
7266+
phylink_resume(priv->phylink);
7267+
} else {
7268+
phylink_resume(priv->phylink);
7269+
if (device_may_wakeup(priv->device))
7270+
phylink_speed_up(priv->phylink);
72707271
}
7272+
rtnl_unlock();
72717273

72727274
rtnl_lock();
72737275
mutex_lock(&priv->lock);
@@ -7288,8 +7290,6 @@ int stmmac_resume(struct device *dev)
72887290
mutex_unlock(&priv->lock);
72897291
rtnl_unlock();
72907292

7291-
phylink_mac_change(priv->phylink, true);
7292-
72937293
netif_device_attach(ndev);
72947294

72957295
return 0;

0 commit comments

Comments
 (0)