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 af28ff7ae176..33984b737233 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c | |||
@@ -202,16 +202,21 @@ static int __devinit mdio_ofgpio_probe(struct of_device *ofdev, | |||
202 | { | 202 | { |
203 | struct device_node *np = NULL; | 203 | struct device_node *np = NULL; |
204 | struct mdio_gpio_platform_data *pdata; | 204 | struct mdio_gpio_platform_data *pdata; |
205 | int ret; | ||
205 | 206 | ||
206 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | 207 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); |
207 | if (!pdata) | 208 | if (!pdata) |
208 | return -ENOMEM; | 209 | return -ENOMEM; |
209 | 210 | ||
210 | pdata->mdc = of_get_gpio(ofdev->node, 0); | 211 | ret = of_get_gpio(ofdev->node, 0); |
211 | pdata->mdio = of_get_gpio(ofdev->node, 1); | 212 | if (ret < 0) |
212 | |||
213 | if (pdata->mdc < 0 || pdata->mdio < 0) | ||
214 | goto out_free; | 213 | goto out_free; |
214 | pdata->mdc = ret; | ||
215 | |||
216 | ret = of_get_gpio(ofdev->node, 1); | ||
217 | if (ret < 0) | ||
218 | goto out_free; | ||
219 | pdata->mdio = ret; | ||
215 | 220 | ||
216 | while ((np = of_get_next_child(ofdev->node, np))) | 221 | while ((np = of_get_next_child(ofdev->node, np))) |
217 | if (!strcmp(np->type, "ethernet-phy")) | 222 | if (!strcmp(np->type, "ethernet-phy")) |
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 | ||
290 | static 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 | */ |
292 | static int mdio_bus_suspend(struct device * dev, pm_message_t state) | 324 | static 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 | ||
305 | static int mdio_bus_resume(struct device * dev) | 334 | static 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 | ||
318 | struct bus_type mdio_bus_type = { | 344 | struct bus_type mdio_bus_type = { |