diff options
Diffstat (limited to 'drivers/net/phy')
-rw-r--r-- | drivers/net/phy/mdio-gpio.c | 13 | ||||
-rw-r--r-- | drivers/net/phy/mdio_bus.c | 54 |
2 files changed, 49 insertions, 18 deletions
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index a439ebeb431..3f460c56492 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -200,16 +200,21 @@ static int __devinit mdio_ofgpio_probe(struct of_device *ofdev, { struct device_node *np = NULL; struct mdio_gpio_platform_data *pdata; + int ret; pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; - pdata->mdc = of_get_gpio(ofdev->node, 0); - pdata->mdio = of_get_gpio(ofdev->node, 1); - - if (pdata->mdc < 0 || pdata->mdio < 0) + ret = of_get_gpio(ofdev->node, 0); + if (ret < 0) goto out_free; + pdata->mdc = ret; + + ret = of_get_gpio(ofdev->node, 1); + if (ret < 0) + goto out_free; + pdata->mdio = ret; while ((np = of_get_next_child(ofdev->node, np))) if (!strcmp(np->type, "ethernet-phy")) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 811a637695c..bb29ae3ff17 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -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 = { |