aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy
diff options
context:
space:
mode:
authorAnton Vorontsov <avorontsov@ru.mvista.com>2009-02-01 03:53:34 -0500
committerDavid S. Miller <davem@davemloft.net>2009-02-01 03:53:34 -0500
commit3d1e4db2b0698785f4e4dd139d88257e855e53b8 (patch)
tree47ed84760a205d6977064682331bbb9a4fee9e73 /drivers/net/phy
parent2884e5cc9283d541977bdf5dc344849af94cd639 (diff)
phylib: Rework suspend/resume code to check netdev wakeup capability
In most cases (e.g. PCI drivers) MDIO and MAC controllers are represented by the same device. But for SOC ethernets we have separate devices. So, in SOC case, checking whether MDIO controller may wakeup is not only makes little sense, but also prevents us from doing per-netdevice wakeup management. This patch reworks suspend/resume code so that now it checks for net device's wakeup flags, not MDIO controller's ones. Each netdevice should manage its wakeup flags, and phylib will decide whether suspend an attached PHY or not. Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/phy')
-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 = {