From: Greg Kroah-Hartman Date: Fri, 16 Mar 2018 12:38:04 +0000 (+0100) Subject: 4.14-stable patches X-Git-Tag: v3.18.100~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=12f8fda67c9aedef50b9cf0b468fdbfb62f47a42;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: net-phy-fix-resume-handling.patch net-phy-restore-phy_resume-locking-assumption.patch --- 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 index 00000000000..6020dfce2e3 --- /dev/null +++ b/queue-4.14/net-phy-fix-resume-handling.patch @@ -0,0 +1,134 @@ +From 6aae7a6232c6444941de8e5a1e0cc42442ab9bce Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Tue, 12 Dec 2017 10:45:36 +0000 +Subject: [PATCH] net: phy: fix resume handling + +From: Russell King + +[ 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 +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..b1c8fce048f --- /dev/null +++ b/queue-4.14/net-phy-restore-phy_resume-locking-assumption.patch @@ -0,0 +1,101 @@ +From 9c2c2e62df3fa30fb13fbeb7512a4eede729383b Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Tue, 27 Feb 2018 01:56:06 +0100 +Subject: net: phy: Restore phy_resume() locking assumption + +From: Andrew Lunn + +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 +Fixes: f5e64032a799 ("net: phy: fix resume handling") +Signed-off-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..5ccb0ea8f36 --- /dev/null +++ b/queue-4.14/series @@ -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 index 00000000000..e69de29bb2d