Merge branch 'net-make-phy-pm-ops-a-no-op-if-mac-driver-manages-phy-pm'
Heiner Kallweit says: ==================== net: 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. ==================== Link: https://lore.kernel.org/r/9e695411-ab1d-34fe-8b90-3e8192ab84f6@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
6597b5c21c
@ -2048,6 +2048,8 @@ static int fec_enet_mii_probe(struct net_device *ndev)
|
||||
fep->link = 0;
|
||||
fep->full_duplex = 0;
|
||||
|
||||
phy_dev->mac_managed_pm = 1;
|
||||
|
||||
phy_attached_info(phy_dev);
|
||||
|
||||
return 0;
|
||||
@ -3864,6 +3866,7 @@ static int __maybe_unused fec_resume(struct device *dev)
|
||||
netif_device_attach(ndev);
|
||||
netif_tx_unlock_bh(ndev);
|
||||
napi_enable(&fep->napi);
|
||||
phy_init_hw(ndev->phydev);
|
||||
phy_start(ndev->phydev);
|
||||
}
|
||||
rtnl_unlock();
|
||||
|
@ -4660,6 +4660,7 @@ static void rtl8169_down(struct rtl8169_private *tp)
|
||||
static void rtl8169_up(struct rtl8169_private *tp)
|
||||
{
|
||||
pci_set_master(tp->pci_dev);
|
||||
phy_init_hw(tp->phydev);
|
||||
phy_resume(tp->phydev);
|
||||
rtl8169_init_phy(tp);
|
||||
napi_enable(&tp->napi);
|
||||
@ -5085,6 +5086,8 @@ static int r8169_mdio_register(struct rtl8169_private *tp)
|
||||
return -EUNATCH;
|
||||
}
|
||||
|
||||
tp->phydev->mac_managed_pm = 1;
|
||||
|
||||
/* PHY will be woken up in rtl_open() */
|
||||
phy_suspend(tp->phydev);
|
||||
|
||||
|
@ -273,6 +273,9 @@ static __maybe_unused int mdio_bus_phy_suspend(struct 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
|
||||
* control, possibly with the phydev->lock held. Upon resume, netdev
|
||||
* 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)
|
||||
struct phy_device *phydev = to_phy_device(dev);
|
||||
int ret;
|
||||
|
||||
if (phydev->mac_managed_pm)
|
||||
return 0;
|
||||
|
||||
if (!phydev->suspended_by_mdio_bus)
|
||||
goto no_resume;
|
||||
|
||||
|
@ -493,6 +493,7 @@ struct macsec_ops;
|
||||
* @loopback_enabled: Set true if this PHY has been loopbacked successfully.
|
||||
* @downshifted_rate: Set true if link speed has been downshifted.
|
||||
* @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
|
||||
* @dev_flags: Device-specific flags used by the PHY driver.
|
||||
* @irq: IRQ number of the PHY's interrupt (-1 if none)
|
||||
@ -567,6 +568,7 @@ struct phy_device {
|
||||
unsigned loopback_enabled:1;
|
||||
unsigned downshifted_rate:1;
|
||||
unsigned is_on_sfp_module:1;
|
||||
unsigned mac_managed_pm:1;
|
||||
|
||||
unsigned autoneg:1;
|
||||
/* The most recently read link state */
|
||||
|
Loading…
Reference in New Issue
Block a user