From: Daniel Golle Some MDIO buses require to program PHY polling registers depending on the PHY type. RealTek switch SoCs are the most prominent example of a DSA switch which doesn't allow to program MAC speed, duplex and flow-control settings without using PHY polling to do so [1]. Avoid a half-baked solution in the MDIO bus driver because - it must reinvent the bus scanning to determine the PHYs and - it must anticipate the right point in time (e.g. deferred PHYs). Hence there is a need to inform the MDIO bus driver that a PHY is being attached or detached. Provide two simple hooks in struct mii_bus which are called - right after a PHY has been attached - just before the PHY is going to be detached Remark! A slightly different version of this patch was part of a former series [2]. The discussion already showed that an initialization hook should be placed somewhere late during the whole setup. This commit implants it right after phy_init_hw() as suggested. On top of this it adds the detach hook. [1] https://github.com/openwrt/openwrt/pull/21515#discussion_r2714069716 [2] https://lore.kernel.org/netdev/cover.1769053496.git.daniel@makrotopia.org/ Signed-off-by: Daniel Golle Signed-off-by: Markus Stockhausen --- drivers/net/phy/phy_device.c | 9 +++++++++ include/linux/phy.h | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 0615228459ef..676cbf183350 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1876,6 +1876,12 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, if (err) goto error; + if (phydev->mdio.bus->notify_phy_attach) { + err = phydev->mdio.bus->notify_phy_attach(phydev); + if (err) + goto error; + } + phy_resume(phydev); /** @@ -1919,6 +1925,9 @@ void phy_detach(struct phy_device *phydev) struct module *ndev_owner = NULL; struct mii_bus *bus; + if (phydev->mdio.bus->notify_phy_detach) + phydev->mdio.bus->notify_phy_detach(phydev); + if (phydev->devlink) { device_link_del(phydev->devlink); phydev->devlink = NULL; diff --git a/include/linux/phy.h b/include/linux/phy.h index 199a7aaa341b..3160ca99deab 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -376,6 +376,10 @@ struct mii_bus { int regnum, u16 val); /** @reset: Perform a reset of the bus */ int (*reset)(struct mii_bus *bus); + /** @notify_phy_attach: Perform post-attach handling */ + int (*notify_phy_attach)(struct phy_device *phydev); + /** @notify_phy_detach: Perform pre-detach handling */ + void (*notify_phy_detach)(struct phy_device *phydev); /** @stats: Statistic counters per device on the bus */ struct mdio_bus_stats stats[PHY_MAX_ADDR]; -- 2.54.0