aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/phy/mdio_bus.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index bd4e8d72dc08..49252d390903 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -303,8 +303,18 @@ static int mdio_bus_suspend(struct device * dev, pm_message_t state)
303 struct phy_driver *phydrv = to_phy_driver(dev->driver); 303 struct phy_driver *phydrv = to_phy_driver(dev->driver);
304 struct phy_device *phydev = to_phy_device(dev); 304 struct phy_device *phydev = to_phy_device(dev);
305 305
306 /*
307 * We must stop the state machine manually, otherwise it stops out of
308 * control, possibly with the phydev->lock held. Upon resume, netdev
309 * may call phy routines that try to grab the same lock, and that may
310 * lead to a deadlock.
311 */
312 if (phydev->attached_dev)
313 phy_stop_machine(phydev);
314
306 if (!mdio_bus_phy_may_suspend(phydev)) 315 if (!mdio_bus_phy_may_suspend(phydev))
307 return 0; 316 return 0;
317
308 return phydrv->suspend(phydev); 318 return phydrv->suspend(phydev);
309} 319}
310 320
@@ -312,10 +322,20 @@ static int mdio_bus_resume(struct device * dev)
312{ 322{
313 struct phy_driver *phydrv = to_phy_driver(dev->driver); 323 struct phy_driver *phydrv = to_phy_driver(dev->driver);
314 struct phy_device *phydev = to_phy_device(dev); 324 struct phy_device *phydev = to_phy_device(dev);
325 int ret;
315 326
316 if (!mdio_bus_phy_may_suspend(phydev)) 327 if (!mdio_bus_phy_may_suspend(phydev))
317 return 0; 328 goto no_resume;
318 return phydrv->resume(phydev); 329
330 ret = phydrv->resume(phydev);
331 if (ret < 0)
332 return ret;
333
334no_resume:
335 if (phydev->attached_dev)
336 phy_start_machine(phydev, NULL);
337
338 return 0;
319} 339}
320 340
321struct bus_type mdio_bus_type = { 341struct bus_type mdio_bus_type = {