ath9k: Store the correct max TX power level
[deliverable/linux.git] / drivers / net / phy / mdio_bus.c
index 811a637695caf4270247cbace802bca469bc03e0..bb29ae3ff17dc6765fac1db21c532c1c5660b93c 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/device.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
@@ -286,33 +287,58 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv)
                (phydev->phy_id & phydrv->phy_id_mask));
 }
 
+static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
+{
+       struct device_driver *drv = phydev->dev.driver;
+       struct phy_driver *phydrv = to_phy_driver(drv);
+       struct net_device *netdev = phydev->attached_dev;
+
+       if (!drv || !phydrv->suspend)
+               return false;
+
+       /* PHY not attached? May suspend. */
+       if (!netdev)
+               return true;
+
+       /*
+        * Don't suspend PHY if the attched netdev parent may wakeup.
+        * The parent may point to a PCI device, as in tg3 driver.
+        */
+       if (netdev->dev.parent && device_may_wakeup(netdev->dev.parent))
+               return false;
+
+       /*
+        * Also don't suspend PHY if the netdev itself may wakeup. This
+        * is the case for devices w/o underlaying pwr. mgmt. aware bus,
+        * e.g. SoC devices.
+        */
+       if (device_may_wakeup(&netdev->dev))
+               return false;
+
+       return true;
+}
+
 /* Suspend and resume.  Copied from platform_suspend and
  * platform_resume
  */
 static int mdio_bus_suspend(struct device * dev, pm_message_t state)
 {
-       int ret = 0;
-       struct device_driver *drv = dev->driver;
-       struct phy_driver *phydrv = to_phy_driver(drv);
+       struct phy_driver *phydrv = to_phy_driver(dev->driver);
        struct phy_device *phydev = to_phy_device(dev);
 
-       if (drv && phydrv->suspend && !device_may_wakeup(phydev->dev.parent))
-               ret = phydrv->suspend(phydev);
-
-       return ret;
+       if (!mdio_bus_phy_may_suspend(phydev))
+               return 0;
+       return phydrv->suspend(phydev);
 }
 
 static int mdio_bus_resume(struct device * dev)
 {
-       int ret = 0;
-       struct device_driver *drv = dev->driver;
-       struct phy_driver *phydrv = to_phy_driver(drv);
+       struct phy_driver *phydrv = to_phy_driver(dev->driver);
        struct phy_device *phydev = to_phy_device(dev);
 
-       if (drv && phydrv->resume && !device_may_wakeup(phydev->dev.parent))
-               ret = phydrv->resume(phydev);
-
-       return ret;
+       if (!mdio_bus_phy_may_suspend(phydev))
+               return 0;
+       return phydrv->resume(phydev);
 }
 
 struct bus_type mdio_bus_type = {
This page took 0.025983 seconds and 5 git commands to generate.