]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Sep 2021 09:01:25 +0000 (11:01 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Sep 2021 09:01:25 +0000 (11:01 +0200)
added patches:
net-stmmac-fix-mac-not-working-when-system-resume-back-with-wol-active.patch

queue-5.14/net-stmmac-fix-mac-not-working-when-system-resume-back-with-wol-active.patch [new file with mode: 0644]
queue-5.14/series

diff --git a/queue-5.14/net-stmmac-fix-mac-not-working-when-system-resume-back-with-wol-active.patch b/queue-5.14/net-stmmac-fix-mac-not-working-when-system-resume-back-with-wol-active.patch
new file mode 100644 (file)
index 0000000..c8367d3
--- /dev/null
@@ -0,0 +1,132 @@
+From 90702dcd19c093621b422ba16fcfd870afe2552f Mon Sep 17 00:00:00 2001
+From: Joakim Zhang <qiangqing.zhang@nxp.com>
+Date: Tue, 7 Sep 2021 18:56:47 +0800
+Subject: net: stmmac: fix MAC not working when system resume back with WoL active
+
+From: Joakim Zhang <qiangqing.zhang@nxp.com>
+
+commit 90702dcd19c093621b422ba16fcfd870afe2552f upstream.
+
+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 46f69ded988d
+("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/20210901090228.11308-1-qiangqing.zhang@nxp.com/
+
+Fixes: 46f69ded988d ("net: stmmac: Use resolved link config in mac_link_up()")
+Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c |   36 +++++++++++-----------
+ 1 file changed, 18 insertions(+), 18 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -7118,8 +7118,6 @@ int stmmac_suspend(struct device *dev)
+       if (!ndev || !netif_running(ndev))
+               return 0;
+-      phylink_mac_change(priv->phylink, false);
+-
+       mutex_lock(&priv->lock);
+       netif_device_detach(ndev);
+@@ -7145,14 +7143,6 @@ int stmmac_suspend(struct device *dev)
+               stmmac_pmt(priv, priv->hw, priv->wolopts);
+               priv->irq_wake = 1;
+       } else {
+-              mutex_unlock(&priv->lock);
+-              rtnl_lock();
+-              if (device_may_wakeup(priv->device))
+-                      phylink_speed_down(priv->phylink, false);
+-              phylink_stop(priv->phylink);
+-              rtnl_unlock();
+-              mutex_lock(&priv->lock);
+-
+               stmmac_mac_set(priv, priv->ioaddr, false);
+               pinctrl_pm_select_sleep_state(priv->device);
+               /* Disable clock in case of PWM is off */
+@@ -7166,6 +7156,16 @@ int stmmac_suspend(struct device *dev)
+       mutex_unlock(&priv->lock);
++      rtnl_lock();
++      if (device_may_wakeup(priv->device) && priv->plat->pmt) {
++              phylink_suspend(priv->phylink, true);
++      } else {
++              if (device_may_wakeup(priv->device))
++                      phylink_speed_down(priv->phylink, false);
++              phylink_suspend(priv->phylink, false);
++      }
++      rtnl_unlock();
++
+       if (priv->dma_cap.fpesel) {
+               /* Disable FPE */
+               stmmac_fpe_configure(priv, priv->ioaddr,
+@@ -7256,13 +7256,15 @@ int stmmac_resume(struct device *dev)
+                       return ret;
+       }
+-      if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+-              rtnl_lock();
+-              phylink_start(priv->phylink);
+-              /* We may have called phylink_speed_down before */
+-              phylink_speed_up(priv->phylink);
+-              rtnl_unlock();
++      rtnl_lock();
++      if (device_may_wakeup(priv->device) && priv->plat->pmt) {
++              phylink_resume(priv->phylink);
++      } else {
++              phylink_resume(priv->phylink);
++              if (device_may_wakeup(priv->device))
++                      phylink_speed_up(priv->phylink);
+       }
++      rtnl_unlock();
+       rtnl_lock();
+       mutex_lock(&priv->lock);
+@@ -7283,8 +7285,6 @@ int stmmac_resume(struct device *dev)
+       mutex_unlock(&priv->lock);
+       rtnl_unlock();
+-      phylink_mac_change(priv->phylink, true);
+-
+       netif_device_attach(ndev);
+       return 0;
index d8a6d307e46a56c71bb98eba2695eb88756db958..918e6a108e6cca0a3f9de62e2adaf8ba388d7d43 100644 (file)
@@ -1,3 +1,4 @@
+net-stmmac-fix-mac-not-working-when-system-resume-back-with-wol-active.patch
 io_uring-ensure-symmetry-in-handling-iter-types-in-loop_rw_iter.patch
 swiotlb-xen-avoid-double-free.patch
 swiotlb-xen-fix-late-init-retry.patch