aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/mdio_bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/mdio_bus.c')
-rw-r--r--drivers/net/phy/mdio_bus.c54
1 files changed, 40 insertions, 14 deletions
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 811a637695ca..bb29ae3ff17d 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -21,6 +21,7 @@
21#include <linux/interrupt.h> 21#include <linux/interrupt.h>
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/delay.h> 23#include <linux/delay.h>
24#include <linux/device.h>
24#include <linux/netdevice.h> 25#include <linux/netdevice.h>
25#include <linux/etherdevice.h> 26#include <linux/etherdevice.h>
26#include <linux/skbuff.h> 27#include <linux/skbuff.h>
@@ -286,33 +287,58 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv)
286 (phydev->phy_id & phydrv->phy_id_mask)); 287 (phydev->phy_id & phydrv->phy_id_mask));
287} 288}
288 289
290static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
291{
292 struct device_driver *drv = phydev->dev.driver;
293 struct phy_driver *phydrv = to_phy_driver(drv);
294 struct net_device *netdev = phydev->attached_dev;
295
296 if (!drv || !phydrv->suspend)
297 return false;
298
299 /* PHY not attached? May suspend. */
300 if (!netdev)
301 return true;
302
303 /*
304 * Don't suspend PHY if the attched netdev parent may wakeup.
305 * The parent may point to a PCI device, as in tg3 driver.
306 */
307 if (netdev->dev.parent && device_may_wakeup(netdev->dev.parent))
308 return false;
309
310 /*
311 * Also don't suspend PHY if the netdev itself may wakeup. This
312 * is the case for devices w/o underlaying pwr. mgmt. aware bus,
313 * e.g. SoC devices.
314 */
315 if (device_may_wakeup(&netdev->dev))
316 return false;
317
318 return true;
319}
320
289/* Suspend and resume. Copied from platform_suspend and 321/* Suspend and resume. Copied from platform_suspend and
290 * platform_resume 322 * platform_resume
291 */ 323 */
292static int mdio_bus_suspend(struct device * dev, pm_message_t state) 324static int mdio_bus_suspend(struct device * dev, pm_message_t state)
293{ 325{
294 int ret = 0; 326 struct phy_driver *phydrv = to_phy_driver(dev->driver);
295 struct device_driver *drv = dev->driver;
296 struct phy_driver *phydrv = to_phy_driver(drv);
297 struct phy_device *phydev = to_phy_device(dev); 327 struct phy_device *phydev = to_phy_device(dev);
298 328
299 if (drv && phydrv->suspend && !device_may_wakeup(phydev->dev.parent)) 329 if (!mdio_bus_phy_may_suspend(phydev))
300 ret = phydrv->suspend(phydev); 330 return 0;
301 331 return phydrv->suspend(phydev);
302 return ret;
303} 332}
304 333
305static int mdio_bus_resume(struct device * dev) 334static int mdio_bus_resume(struct device * dev)
306{ 335{
307 int ret = 0; 336 struct phy_driver *phydrv = to_phy_driver(dev->driver);
308 struct device_driver *drv = dev->driver;
309 struct phy_driver *phydrv = to_phy_driver(drv);
310 struct phy_device *phydev = to_phy_device(dev); 337 struct phy_device *phydev = to_phy_device(dev);
311 338
312 if (drv && phydrv->resume && !device_may_wakeup(phydev->dev.parent)) 339 if (!mdio_bus_phy_may_suspend(phydev))
313 ret = phydrv->resume(phydev); 340 return 0;
314 341 return phydrv->resume(phydev);
315 return ret;
316} 342}
317 343
318struct bus_type mdio_bus_type = { 344struct bus_type mdio_bus_type = {