Commit fba863b8 authored by Heiner Kallweit's avatar Heiner Kallweit Committed by Jakub Kicinski

net: phy: make PHY PM ops a no-op if MAC driver manages PHY PM

Resume callback of the PHY driver is called after the one for the MAC
driver. The PHY driver resume callback calls phy_init_hw(), and this is
potentially problematic if the MAC driver calls phy_start() in its resume
callback. One issue was reported with the fec driver and a KSZ8081 PHY
which seems to become unstable if a soft reset is triggered during aneg.

The new flag allows MAC drivers to indicate that they take care of
suspending/resuming the PHY. Then the MAC PM callbacks can handle
any dependency between MAC and PHY PM.
Signed-off-by: default avatarHeiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent a7150e38
...@@ -273,6 +273,9 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev) ...@@ -273,6 +273,9 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
{ {
struct phy_device *phydev = to_phy_device(dev); struct phy_device *phydev = to_phy_device(dev);
if (phydev->mac_managed_pm)
return 0;
/* We must stop the state machine manually, otherwise it stops out of /* We must stop the state machine manually, otherwise it stops out of
* control, possibly with the phydev->lock held. Upon resume, netdev * control, possibly with the phydev->lock held. Upon resume, netdev
* may call phy routines that try to grab the same lock, and that may * may call phy routines that try to grab the same lock, and that may
...@@ -294,6 +297,9 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev) ...@@ -294,6 +297,9 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
struct phy_device *phydev = to_phy_device(dev); struct phy_device *phydev = to_phy_device(dev);
int ret; int ret;
if (phydev->mac_managed_pm)
return 0;
if (!phydev->suspended_by_mdio_bus) if (!phydev->suspended_by_mdio_bus)
goto no_resume; goto no_resume;
......
...@@ -493,6 +493,7 @@ struct macsec_ops; ...@@ -493,6 +493,7 @@ struct macsec_ops;
* @loopback_enabled: Set true if this PHY has been loopbacked successfully. * @loopback_enabled: Set true if this PHY has been loopbacked successfully.
* @downshifted_rate: Set true if link speed has been downshifted. * @downshifted_rate: Set true if link speed has been downshifted.
* @is_on_sfp_module: Set true if PHY is located on an SFP module. * @is_on_sfp_module: Set true if PHY is located on an SFP module.
* @mac_managed_pm: Set true if MAC driver takes of suspending/resuming PHY
* @state: State of the PHY for management purposes * @state: State of the PHY for management purposes
* @dev_flags: Device-specific flags used by the PHY driver. * @dev_flags: Device-specific flags used by the PHY driver.
* @irq: IRQ number of the PHY's interrupt (-1 if none) * @irq: IRQ number of the PHY's interrupt (-1 if none)
...@@ -567,6 +568,7 @@ struct phy_device { ...@@ -567,6 +568,7 @@ struct phy_device {
unsigned loopback_enabled:1; unsigned loopback_enabled:1;
unsigned downshifted_rate:1; unsigned downshifted_rate:1;
unsigned is_on_sfp_module:1; unsigned is_on_sfp_module:1;
unsigned mac_managed_pm:1;
unsigned autoneg:1; unsigned autoneg:1;
/* The most recently read link state */ /* The most recently read link state */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment