net: phy: move phy_suspend() to end of phy_state_machine()
authorRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Thu, 14 Sep 2023 15:35:47 +0000 (16:35 +0100)
committerDavid S. Miller <davem@davemloft.net>
Sun, 17 Sep 2023 13:31:23 +0000 (14:31 +0100)
Move the call to phy_suspend() to the end of phy_state_machine() after
we release the lock so that we can combine the locked areas.
phy_suspend() can not be called while holding phydev->lock as it has
caused deadlocks in the past.

Tested-by: Jijie Shao <shaojijie@huawei.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/phy/phy.c

index 5bb33af2a4cbf5b4e76afb471470584126811bbf..756326f38b14ae66230c38c83a68cfe64224f0cb 100644 (file)
@@ -1494,15 +1494,11 @@ void phy_state_machine(struct work_struct *work)
                func = &_phy_start_aneg;
        }
 
-       mutex_unlock(&phydev->lock);
-
-       if (do_suspend)
-               phy_suspend(phydev);
-
-       if (err == -ENODEV)
+       if (err == -ENODEV) {
+               mutex_unlock(&phydev->lock);
                return;
+       }
 
-       mutex_lock(&phydev->lock);
        if (err < 0)
                phy_error_precise(phydev, func, err);
 
@@ -1519,6 +1515,9 @@ void phy_state_machine(struct work_struct *work)
        if (phy_polling_mode(phydev) && phy_is_started(phydev))
                phy_queue_state_machine(phydev, PHY_STATE_TIME);
        mutex_unlock(&phydev->lock);
+
+       if (do_suspend)
+               phy_suspend(phydev);
 }
 
 /**