[PATCH net v1] net: phy: Change flag to autoremove the consumer

From: Sarosh Hasan
Date: Thu Jul 03 2025 - 05:01:49 EST


phy_detach() is not called when the MDIO controller driver is
removed. So phydev->devlink is not cleared, but actually the device
link has been removed by phy_device_remove()--> device_del().Therefore,
it will cause the crash when the MAC controller driver is removed.
In such case delete link between phy dev and mac dev. Change the
DL_FLAG_STATELESS flag to DL_FLAG_AUTOREMOVE_SUPPLIER,so that the
consumer (MAC controller) driver will be automatically removed
when the link is removed.

Fixes: bc66fa87d4fd ("net: phy: Add link between phy dev and mac dev")
Link: https://lore.kernel.org/all/e6824f1a-c1a9-4c2e-9b46-6fe224877bfc@xxxxxxxxxxx/
Suggested-by: Wei Fang <wei.fang@xxxxxxx>
Signed-off-by: Abhishek Chauhan <quic_abchauha@xxxxxxxxxxx>
Signed-off-by: Sarosh Hasan <quic_sarohasa@xxxxxxxxxxx>
---
drivers/net/phy/phy_device.c | 17 +++++++++--------
include/linux/phy.h | 4 ----
2 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 90951681523c..f3db3dd93c74 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1630,6 +1630,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
struct mii_bus *bus = phydev->mdio.bus;
struct device *d = &phydev->mdio.dev;
struct module *ndev_owner = NULL;
+ struct device_link *devlink;
int err;

/* For Ethernet device drivers that register their own MDIO bus, we
@@ -1760,9 +1761,14 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
* another mac interface, so we should create a device link between
* phy dev and mac dev.
*/
- if (dev && phydev->mdio.bus->parent && dev->dev.parent != phydev->mdio.bus->parent)
- phydev->devlink = device_link_add(dev->dev.parent, &phydev->mdio.dev,
- DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
+ if (dev && phydev->mdio.bus->parent && dev->dev.parent != phydev->mdio.bus->parent) {
+ devlink = device_link_add(dev->dev.parent, &phydev->mdio.dev,
+ DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_SUPPLIER);
+ if (!devlink) {
+ err = -ENOMEM;
+ goto error;
+ }
+ }

return err;

@@ -1834,11 +1840,6 @@ void phy_detach(struct phy_device *phydev)
struct module *ndev_owner = NULL;
struct mii_bus *bus;

- if (phydev->devlink) {
- device_link_del(phydev->devlink);
- phydev->devlink = NULL;
- }
-
if (phydev->sysfs_links) {
if (dev)
sysfs_remove_link(&dev->dev.kobj, "phydev");
diff --git a/include/linux/phy.h b/include/linux/phy.h
index b037aab7b71d..e20643fb6f41 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -507,8 +507,6 @@ struct macsec_ops;
*
* @mdio: MDIO bus this PHY is on
* @drv: Pointer to the driver for this PHY instance
- * @devlink: Create a link between phy dev and mac dev, if the external phy
- * used by current mac interface is managed by another mac interface.
* @phyindex: Unique id across the phy's parent tree of phys to address the PHY
* from userspace, similar to ifindex. A zero index means the PHY
* wasn't assigned an id yet.
@@ -613,8 +611,6 @@ struct phy_device {
/* And management functions */
const struct phy_driver *drv;

- struct device_link *devlink;
-
u32 phyindex;
u32 phy_id;

--
2.17.1