Commit 6597b5c2 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

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: default avatarJakub Kicinski <kuba@kernel.org>
parents a7150e38 5c2280fc
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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();
+3 −0
Original line number Diff line number Diff line
@@ -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);

+6 −0
Original line number Diff line number Diff line
@@ -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;

+2 −0
Original line number Diff line number Diff line
@@ -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 */