diff options
| -rw-r--r-- | drivers/net/phy/mdio_bus.c | 14 | ||||
| -rw-r--r-- | drivers/net/phy/phy_device.c | 22 | ||||
| -rw-r--r-- | include/linux/phy.h | 3 |
3 files changed, 29 insertions, 10 deletions
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 50051f271b10..095ef3fe369a 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c | |||
| @@ -443,9 +443,13 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) | |||
| 443 | if (!drv || !phydrv->suspend) | 443 | if (!drv || !phydrv->suspend) |
| 444 | return false; | 444 | return false; |
| 445 | 445 | ||
| 446 | /* PHY not attached? May suspend. */ | 446 | /* PHY not attached? May suspend if the PHY has not already been |
| 447 | * suspended as part of a prior call to phy_disconnect() -> | ||
| 448 | * phy_detach() -> phy_suspend() because the parent netdev might be the | ||
| 449 | * MDIO bus driver and clock gated at this point. | ||
| 450 | */ | ||
| 447 | if (!netdev) | 451 | if (!netdev) |
| 448 | return true; | 452 | return !phydev->suspended; |
| 449 | 453 | ||
| 450 | /* Don't suspend PHY if the attched netdev parent may wakeup. | 454 | /* Don't suspend PHY if the attched netdev parent may wakeup. |
| 451 | * The parent may point to a PCI device, as in tg3 driver. | 455 | * The parent may point to a PCI device, as in tg3 driver. |
| @@ -465,7 +469,6 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) | |||
| 465 | 469 | ||
| 466 | static int mdio_bus_suspend(struct device *dev) | 470 | static int mdio_bus_suspend(struct device *dev) |
| 467 | { | 471 | { |
| 468 | struct phy_driver *phydrv = to_phy_driver(dev->driver); | ||
| 469 | struct phy_device *phydev = to_phy_device(dev); | 472 | struct phy_device *phydev = to_phy_device(dev); |
| 470 | 473 | ||
| 471 | /* We must stop the state machine manually, otherwise it stops out of | 474 | /* We must stop the state machine manually, otherwise it stops out of |
| @@ -479,19 +482,18 @@ static int mdio_bus_suspend(struct device *dev) | |||
| 479 | if (!mdio_bus_phy_may_suspend(phydev)) | 482 | if (!mdio_bus_phy_may_suspend(phydev)) |
| 480 | return 0; | 483 | return 0; |
| 481 | 484 | ||
| 482 | return phydrv->suspend(phydev); | 485 | return phy_suspend(phydev); |
| 483 | } | 486 | } |
| 484 | 487 | ||
| 485 | static int mdio_bus_resume(struct device *dev) | 488 | static int mdio_bus_resume(struct device *dev) |
| 486 | { | 489 | { |
| 487 | struct phy_driver *phydrv = to_phy_driver(dev->driver); | ||
| 488 | struct phy_device *phydev = to_phy_device(dev); | 490 | struct phy_device *phydev = to_phy_device(dev); |
| 489 | int ret; | 491 | int ret; |
| 490 | 492 | ||
| 491 | if (!mdio_bus_phy_may_suspend(phydev)) | 493 | if (!mdio_bus_phy_may_suspend(phydev)) |
| 492 | goto no_resume; | 494 | goto no_resume; |
| 493 | 495 | ||
| 494 | ret = phydrv->resume(phydev); | 496 | ret = phy_resume(phydev); |
| 495 | if (ret < 0) | 497 | if (ret < 0) |
| 496 | return ret; | 498 | return ret; |
| 497 | 499 | ||
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 3fc91e89f5a5..bdfe51fc3a65 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
| @@ -699,6 +699,7 @@ int phy_suspend(struct phy_device *phydev) | |||
| 699 | { | 699 | { |
| 700 | struct phy_driver *phydrv = to_phy_driver(phydev->dev.driver); | 700 | struct phy_driver *phydrv = to_phy_driver(phydev->dev.driver); |
| 701 | struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; | 701 | struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; |
| 702 | int ret = 0; | ||
| 702 | 703 | ||
| 703 | /* If the device has WOL enabled, we cannot suspend the PHY */ | 704 | /* If the device has WOL enabled, we cannot suspend the PHY */ |
| 704 | phy_ethtool_get_wol(phydev, &wol); | 705 | phy_ethtool_get_wol(phydev, &wol); |
| @@ -706,18 +707,31 @@ int phy_suspend(struct phy_device *phydev) | |||
| 706 | return -EBUSY; | 707 | return -EBUSY; |
| 707 | 708 | ||
| 708 | if (phydrv->suspend) | 709 | if (phydrv->suspend) |
| 709 | return phydrv->suspend(phydev); | 710 | ret = phydrv->suspend(phydev); |
| 710 | return 0; | 711 | |
| 712 | if (ret) | ||
| 713 | return ret; | ||
| 714 | |||
| 715 | phydev->suspended = true; | ||
| 716 | |||
| 717 | return ret; | ||
| 711 | } | 718 | } |
| 712 | EXPORT_SYMBOL(phy_suspend); | 719 | EXPORT_SYMBOL(phy_suspend); |
| 713 | 720 | ||
| 714 | int phy_resume(struct phy_device *phydev) | 721 | int phy_resume(struct phy_device *phydev) |
| 715 | { | 722 | { |
| 716 | struct phy_driver *phydrv = to_phy_driver(phydev->dev.driver); | 723 | struct phy_driver *phydrv = to_phy_driver(phydev->dev.driver); |
| 724 | int ret = 0; | ||
| 717 | 725 | ||
| 718 | if (phydrv->resume) | 726 | if (phydrv->resume) |
| 719 | return phydrv->resume(phydev); | 727 | ret = phydrv->resume(phydev); |
| 720 | return 0; | 728 | |
| 729 | if (ret) | ||
| 730 | return ret; | ||
| 731 | |||
| 732 | phydev->suspended = false; | ||
| 733 | |||
| 734 | return ret; | ||
| 721 | } | 735 | } |
| 722 | EXPORT_SYMBOL(phy_resume); | 736 | EXPORT_SYMBOL(phy_resume); |
| 723 | 737 | ||
diff --git a/include/linux/phy.h b/include/linux/phy.h index 9c189a1fa3a2..685809835b5c 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h | |||
| @@ -327,6 +327,8 @@ struct phy_c45_device_ids { | |||
| 327 | * c45_ids: 802.3-c45 Device Identifers if is_c45. | 327 | * c45_ids: 802.3-c45 Device Identifers if is_c45. |
| 328 | * is_c45: Set to true if this phy uses clause 45 addressing. | 328 | * is_c45: Set to true if this phy uses clause 45 addressing. |
| 329 | * is_internal: Set to true if this phy is internal to a MAC. | 329 | * is_internal: Set to true if this phy is internal to a MAC. |
| 330 | * has_fixups: Set to true if this phy has fixups/quirks. | ||
| 331 | * suspended: Set to true if this phy has been suspended successfully. | ||
| 330 | * state: state of the PHY for management purposes | 332 | * state: state of the PHY for management purposes |
| 331 | * dev_flags: Device-specific flags used by the PHY driver. | 333 | * dev_flags: Device-specific flags used by the PHY driver. |
| 332 | * addr: Bus address of PHY | 334 | * addr: Bus address of PHY |
| @@ -364,6 +366,7 @@ struct phy_device { | |||
| 364 | bool is_c45; | 366 | bool is_c45; |
| 365 | bool is_internal; | 367 | bool is_internal; |
| 366 | bool has_fixups; | 368 | bool has_fixups; |
| 369 | bool suspended; | ||
| 367 | 370 | ||
| 368 | enum phy_state state; | 371 | enum phy_state state; |
| 369 | 372 | ||
