| From efac2dc7567b2bdf94153c79815120eb8c355fb3 Mon Sep 17 00:00:00 2001 |
| From: Heiner Kallweit <hkallweit1@gmail.com> |
| Date: Thu, 12 Mar 2020 22:25:20 +0100 |
| Subject: [PATCH] net: phy: fix MDIO bus PM PHY resuming |
| |
| commit 611d779af7cad2b87487ff58e4931a90c20b113c upstream. |
| |
| So far we have the unfortunate situation that mdio_bus_phy_may_suspend() |
| is called in suspend AND resume path, assuming that function result is |
| the same. After the original change this is no longer the case, |
| resulting in broken resume as reported by Geert. |
| |
| To fix this call mdio_bus_phy_may_suspend() in the suspend path only, |
| and let the phy_device store the info whether it was suspended by |
| MDIO bus PM. |
| |
| Fixes: 503ba7c69610 ("net: phy: Avoid multiple suspends") |
| Reported-by: Geert Uytterhoeven <geert@linux-m68k.org> |
| Tested-by: Geert Uytterhoeven <geert@linux-m68k.org> |
| Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> |
| Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c |
| index 9cf8284baf7e..862815495b20 100644 |
| --- a/drivers/net/phy/phy_device.c |
| +++ b/drivers/net/phy/phy_device.c |
| @@ -284,6 +284,8 @@ static int mdio_bus_phy_suspend(struct device *dev) |
| if (!mdio_bus_phy_may_suspend(phydev)) |
| return 0; |
| |
| + phydev->suspended_by_mdio_bus = 1; |
| + |
| return phy_suspend(phydev); |
| } |
| |
| @@ -292,9 +294,11 @@ static int mdio_bus_phy_resume(struct device *dev) |
| struct phy_device *phydev = to_phy_device(dev); |
| int ret; |
| |
| - if (!mdio_bus_phy_may_suspend(phydev)) |
| + if (!phydev->suspended_by_mdio_bus) |
| goto no_resume; |
| |
| + phydev->suspended_by_mdio_bus = 0; |
| + |
| ret = phy_resume(phydev); |
| if (ret < 0) |
| return ret; |
| diff --git a/include/linux/phy.h b/include/linux/phy.h |
| index 8e3c7d095944..9e13674fb566 100644 |
| --- a/include/linux/phy.h |
| +++ b/include/linux/phy.h |
| @@ -336,6 +336,7 @@ struct phy_c45_device_ids { |
| * is_gigabit_capable: Set to true if PHY supports 1000Mbps |
| * has_fixups: Set to true if this phy has fixups/quirks. |
| * suspended: Set to true if this phy has been suspended successfully. |
| + * suspended_by_mdio_bus: Set to true if this phy was suspended by MDIO bus. |
| * sysfs_links: Internal boolean tracking sysfs symbolic links setup/removal. |
| * loopback_enabled: Set true if this phy has been loopbacked successfully. |
| * state: state of the PHY for management purposes |
| @@ -374,6 +375,7 @@ struct phy_device { |
| unsigned is_gigabit_capable:1; |
| unsigned has_fixups:1; |
| unsigned suspended:1; |
| + unsigned suspended_by_mdio_bus:1; |
| unsigned sysfs_links:1; |
| unsigned loopback_enabled:1; |
| |
| -- |
| 2.7.4 |
| |