]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 16 Mar 2018 12:38:04 +0000 (13:38 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 16 Mar 2018 12:38:04 +0000 (13:38 +0100)
added patches:
net-phy-fix-resume-handling.patch
net-phy-restore-phy_resume-locking-assumption.patch

queue-4.14/net-phy-fix-resume-handling.patch [new file with mode: 0644]
queue-4.14/net-phy-restore-phy_resume-locking-assumption.patch [new file with mode: 0644]
queue-4.14/series [new file with mode: 0644]
queue-4.15/series [new file with mode: 0644]

diff --git a/queue-4.14/net-phy-fix-resume-handling.patch b/queue-4.14/net-phy-fix-resume-handling.patch
new file mode 100644 (file)
index 0000000..6020dfc
--- /dev/null
@@ -0,0 +1,134 @@
+From 6aae7a6232c6444941de8e5a1e0cc42442ab9bce Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@armlinux.org.uk>
+Date: Tue, 12 Dec 2017 10:45:36 +0000
+Subject: [PATCH] net: phy: fix resume handling
+
+From: Russell King <rmk+kernel@armlinux.org.uk>
+
+[ Upstream commit f5e64032a799d4f54decc7eb6aafcdffb67f9ad9 ]
+
+When a PHY has the BMCR_PDOWN bit set, it may decide to ignore writes
+to other registers, or reset the registers to power-on defaults.
+Micrel PHYs do this for their interrupt registers.
+
+The current structure of phylib tries to enable interrupts before
+resuming (and releasing) the BMCR_PDOWN bit.  This fails, causing
+Micrel PHYs to stop working after a suspend/resume sequence if they
+are using interrupts.
+
+Fix this by ensuring that the PHY driver resume methods do not take
+the phydev->lock mutex themselves, but the callers of phy_resume()
+take that lock.  This then allows us to move the call to phy_resume()
+before we enable interrupts in phy_start().
+
+Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/phy/at803x.c     |    4 ----
+ drivers/net/phy/phy.c        |    9 +++------
+ drivers/net/phy/phy_device.c |   10 ++++++----
+ 3 files changed, 9 insertions(+), 14 deletions(-)
+
+--- a/drivers/net/phy/at803x.c
++++ b/drivers/net/phy/at803x.c
+@@ -239,14 +239,10 @@ static int at803x_resume(struct phy_devi
+ {
+       int value;
+-      mutex_lock(&phydev->lock);
+-
+       value = phy_read(phydev, MII_BMCR);
+       value &= ~(BMCR_PDOWN | BMCR_ISOLATE);
+       phy_write(phydev, MII_BMCR, value);
+-      mutex_unlock(&phydev->lock);
+-
+       return 0;
+ }
+--- a/drivers/net/phy/phy.c
++++ b/drivers/net/phy/phy.c
+@@ -828,7 +828,6 @@ EXPORT_SYMBOL(phy_stop);
+  */
+ void phy_start(struct phy_device *phydev)
+ {
+-      bool do_resume = false;
+       int err = 0;
+       mutex_lock(&phydev->lock);
+@@ -841,6 +840,9 @@ void phy_start(struct phy_device *phydev
+               phydev->state = PHY_UP;
+               break;
+       case PHY_HALTED:
++              /* if phy was suspended, bring the physical link up again */
++              phy_resume(phydev);
++
+               /* make sure interrupts are re-enabled for the PHY */
+               if (phy_interrupt_is_valid(phydev)) {
+                       err = phy_enable_interrupts(phydev);
+@@ -849,17 +851,12 @@ void phy_start(struct phy_device *phydev
+               }
+               phydev->state = PHY_RESUMING;
+-              do_resume = true;
+               break;
+       default:
+               break;
+       }
+       mutex_unlock(&phydev->lock);
+-      /* if phy was suspended, bring the physical link up again */
+-      if (do_resume)
+-              phy_resume(phydev);
+-
+       phy_trigger_machine(phydev, true);
+ }
+ EXPORT_SYMBOL(phy_start);
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -135,7 +135,9 @@ static int mdio_bus_phy_resume(struct de
+       if (!mdio_bus_phy_may_suspend(phydev))
+               goto no_resume;
++      mutex_lock(&phydev->lock);
+       ret = phy_resume(phydev);
++      mutex_unlock(&phydev->lock);
+       if (ret < 0)
+               return ret;
+@@ -1026,7 +1028,9 @@ int phy_attach_direct(struct net_device
+       if (err)
+               goto error;
++      mutex_lock(&phydev->lock);
+       phy_resume(phydev);
++      mutex_unlock(&phydev->lock);
+       phy_led_triggers_register(phydev);
+       return err;
+@@ -1157,6 +1161,8 @@ int phy_resume(struct phy_device *phydev
+       struct phy_driver *phydrv = to_phy_driver(phydev->mdio.dev.driver);
+       int ret = 0;
++      WARN_ON(!mutex_is_locked(&phydev->lock));
++
+       if (phydev->drv && phydrv->resume)
+               ret = phydrv->resume(phydev);
+@@ -1639,13 +1645,9 @@ int genphy_resume(struct phy_device *phy
+ {
+       int value;
+-      mutex_lock(&phydev->lock);
+-
+       value = phy_read(phydev, MII_BMCR);
+       phy_write(phydev, MII_BMCR, value & ~BMCR_PDOWN);
+-      mutex_unlock(&phydev->lock);
+-
+       return 0;
+ }
+ EXPORT_SYMBOL(genphy_resume);
diff --git a/queue-4.14/net-phy-restore-phy_resume-locking-assumption.patch b/queue-4.14/net-phy-restore-phy_resume-locking-assumption.patch
new file mode 100644 (file)
index 0000000..b1c8fce
--- /dev/null
@@ -0,0 +1,101 @@
+From 9c2c2e62df3fa30fb13fbeb7512a4eede729383b Mon Sep 17 00:00:00 2001
+From: Andrew Lunn <andrew@lunn.ch>
+Date: Tue, 27 Feb 2018 01:56:06 +0100
+Subject: net: phy: Restore phy_resume() locking assumption
+
+From: Andrew Lunn <andrew@lunn.ch>
+
+commit 9c2c2e62df3fa30fb13fbeb7512a4eede729383b upstream.
+
+commit f5e64032a799 ("net: phy: fix resume handling") changes the
+locking semantics for phy_resume() such that the caller now needs to
+hold the phy mutex. Not all call sites were adopted to this new
+semantic, resulting in warnings from the added
+WARN_ON(!mutex_is_locked(&phydev->lock)).  Rather than change the
+semantics, add a __phy_resume() and restore the old behavior of
+phy_resume().
+
+Reported-by: Heiner Kallweit <hkallweit1@gmail.com>
+Fixes: f5e64032a799 ("net: phy: fix resume handling")
+Signed-off-by: Andrew Lunn <andrew@lunn.ch>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/phy/phy.c        |    2 +-
+ drivers/net/phy/phy_device.c |   18 +++++++++++++-----
+ include/linux/phy.h          |    1 +
+ 3 files changed, 15 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/phy/phy.c
++++ b/drivers/net/phy/phy.c
+@@ -841,7 +841,7 @@ void phy_start(struct phy_device *phydev
+               break;
+       case PHY_HALTED:
+               /* if phy was suspended, bring the physical link up again */
+-              phy_resume(phydev);
++              __phy_resume(phydev);
+               /* make sure interrupts are re-enabled for the PHY */
+               if (phy_interrupt_is_valid(phydev)) {
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -135,9 +135,7 @@ static int mdio_bus_phy_resume(struct de
+       if (!mdio_bus_phy_may_suspend(phydev))
+               goto no_resume;
+-      mutex_lock(&phydev->lock);
+       ret = phy_resume(phydev);
+-      mutex_unlock(&phydev->lock);
+       if (ret < 0)
+               return ret;
+@@ -1028,9 +1026,7 @@ int phy_attach_direct(struct net_device
+       if (err)
+               goto error;
+-      mutex_lock(&phydev->lock);
+       phy_resume(phydev);
+-      mutex_unlock(&phydev->lock);
+       phy_led_triggers_register(phydev);
+       return err;
+@@ -1156,7 +1152,7 @@ int phy_suspend(struct phy_device *phyde
+ }
+ EXPORT_SYMBOL(phy_suspend);
+-int phy_resume(struct phy_device *phydev)
++int __phy_resume(struct phy_device *phydev)
+ {
+       struct phy_driver *phydrv = to_phy_driver(phydev->mdio.dev.driver);
+       int ret = 0;
+@@ -1173,6 +1169,18 @@ int phy_resume(struct phy_device *phydev
+       return ret;
+ }
++EXPORT_SYMBOL(__phy_resume);
++
++int phy_resume(struct phy_device *phydev)
++{
++      int ret;
++
++      mutex_lock(&phydev->lock);
++      ret = __phy_resume(phydev);
++      mutex_unlock(&phydev->lock);
++
++      return ret;
++}
+ EXPORT_SYMBOL(phy_resume);
+ int phy_loopback(struct phy_device *phydev, bool enable)
+--- a/include/linux/phy.h
++++ b/include/linux/phy.h
+@@ -817,6 +817,7 @@ void phy_device_remove(struct phy_device
+ int phy_init_hw(struct phy_device *phydev);
+ int phy_suspend(struct phy_device *phydev);
+ int phy_resume(struct phy_device *phydev);
++int __phy_resume(struct phy_device *phydev);
+ int phy_loopback(struct phy_device *phydev, bool enable);
+ struct phy_device *phy_attach(struct net_device *dev, const char *bus_id,
+                             phy_interface_t interface);
diff --git a/queue-4.14/series b/queue-4.14/series
new file mode 100644 (file)
index 0000000..5ccb0ea
--- /dev/null
@@ -0,0 +1,2 @@
+net-phy-fix-resume-handling.patch
+net-phy-restore-phy_resume-locking-assumption.patch
diff --git a/queue-4.15/series b/queue-4.15/series
new file mode 100644 (file)
index 0000000..e69de29