[PATCH net] net: phy: add device link between MAC device and MDIO device

Wei Fang posted 1 patch 1 week, 5 days ago
drivers/net/phy/phy_device.c | 24 ++++++++++++++----------
include/linux/phy.h          |  4 ----
2 files changed, 14 insertions(+), 14 deletions(-)
[PATCH net] net: phy: add device link between MAC device and MDIO device
Posted by Wei Fang 1 week, 5 days ago
For the shared MDIO bus use case, multiple MACs will share the same MDIO
bus. Therefore, these MACs all depend on this MDIO bus, however, current
PHY driver does not create this dependency relationship between the MACs
and the shared MDIO devices. If this shared MDIO bus is removed, it could
potentially cause a crash. For example, the i.MX6ULL platform has two FEC
ports (fec1 and fec2) and uses phylib interfaces to manage the external
PHY. And fec1 uses the MDIO bus shared by fec2. When the fec2 driver is
removed, users can see the following warning log.

$ echo 20b4000.ethernet > /sys/bus/platform/drivers/fec/unbind
WARNING: drivers/net/phy/phy.c:1352 at _phy_state_machine+0xe8/0x38c, CPU#0: kworker/0:6/35
phy_check_link_status+0x0/0xf8: returned: -13
Call trace:
 unwind_backtrace from show_stack+0x10/0x14
 show_stack from dump_stack_lvl+0x54/0x68
 dump_stack_lvl from __warn+0x84/0xf4
 __warn from warn_slowpath_fmt+0x1a8/0x1bc
 warn_slowpath_fmt from _phy_state_machine+0xe8/0x38c
 _phy_state_machine from phy_state_machine+0x20/0x50
 phy_state_machine from process_one_work+0x168/0x2f4

Another example is the i.MX95-15x15 platform which has two ENETC ports
and uses the phylink interfaces to manage the exteranl PHY. All the
external PHYs can be accessed the EMDIO, it is a different device from
ENETC. When the EMDIO driver is removed, users can see the below crash
log and the console is hanged.

$ echo 0002:01:00.0 > /sys/bus/pci/drivers/fsl_enetc_mdio/unbind
$ ifconfig eth0 down
Unable to handle kernel NULL pointer dereference at virtual address 00000000000001b8
pc : _phy_state_machine+0x230/0x36c
lr : _phy_state_machine+0x2b4/0x36c
Call trace:
 _phy_state_machine+0x230/0x36c (P)
 phy_stop+0x74/0x190
 phylink_stop+0x28/0xb8
 enetc_close+0x28/0x8c
 netif_change_flags+0x24/0x6c
 dev_change_flags+0x48/0x7c
 devinet_ioctl+0x328/0x604
 inet_ioctl+0x204/0x220

The commit bc66fa87d4fd ("net: phy: Add link between phy dev and mac
dev") has created a device link between the MAC and the PHY if the MAC
uses a shared MDIO bus (The MDIO and the MAC are two separate devices).
Sarosh Hasan tried to change the DL_FLAG_STATELESS flag to
DL_FLAG_AUTOREMOVE_SUPPLIER to fix the issue [1]. However, the solution
does not take into account the hot-swappable PHY devices (such as SFP).
so when the PHY device is unplugged, the MAC driver will automatically
be removed, which is not the expected behavior.

Therefore, to solve this issue of the shared MDIO bus, we create the
device link between the MAC device and the MDIO device, rather than
between the MAC device and the PHY device. And when the shared MDIO bus
is removed, all MAC drivers that depend on it will also be removed.

Reported-by: Abhishek Chauhan (ABC) <quic_abchauha@quicinc.com>
Closes: https://lore.kernel.org/all/d696a426-40bb-4c1a-b42d-990fb690de5e@quicinc.com/
Link: https://lore.kernel.org/imx/20250703090041.23137-1-quic_sarohasa@quicinc.com/ # [1]
Fixes: bc66fa87d4fd ("net: phy: Add link between phy dev and mac dev")
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
 drivers/net/phy/phy_device.c | 24 ++++++++++++++----------
 include/linux/phy.h          |  4 ----
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 81984d4ebb7c..d5ac7506fe39 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1768,12 +1768,21 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
 
 	/**
 	 * If the external phy used by current mac interface is managed by
-	 * another mac interface, so we should create a device link between
-	 * phy dev and mac dev.
+	 * another MDIO controller, which means that the MAC and MDIO are
+	 * separated devices, then we should create a device link between
+	 * the MAC device and the MDIO device.
 	 */
-	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) {
+		if (!device_link_add(dev->dev.parent, phydev->mdio.bus->parent,
+				     DL_FLAG_PM_RUNTIME |
+				     DL_FLAG_AUTOREMOVE_SUPPLIER)) {
+			phydev_err(phydev,
+				   "Failed to add devlink between MAC and MDIO\n");
+			err = -EINVAL;
+			goto error;
+		}
+	}
 
 	return err;
 
@@ -1845,11 +1854,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 fbbe028cc4b7..d6f2039a63d3 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -559,8 +559,6 @@ struct phy_oatc14_sqi_capability {
  *
  * @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.
@@ -666,8 +664,6 @@ struct phy_device {
 	/* And management functions */
 	const struct phy_driver *drv;
 
-	struct device_link *devlink;
-
 	u32 phyindex;
 	u32 phy_id;
 
-- 
2.34.1
Re: [PATCH net] net: phy: add device link between MAC device and MDIO device
Posted by Maxime Chevallier 1 week, 2 days ago
Hi

[...]
> 
> diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
> index 81984d4ebb7c..d5ac7506fe39 100644
> --- a/drivers/net/phy/phy_device.c
> +++ b/drivers/net/phy/phy_device.c
> @@ -1768,12 +1768,21 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
>  
>  	/**
>  	 * If the external phy used by current mac interface is managed by
> -	 * another mac interface, so we should create a device link between
> -	 * phy dev and mac dev.
> +	 * another MDIO controller, which means that the MAC and MDIO are
> +	 * separated devices, then we should create a device link between
> +	 * the MAC device and the MDIO device.
>  	 */

I was confused by the use of the "MDIO device" terminology here, which
refers to a device sitting on an mdio bus, such as a PHY. I think though
that what you actually refer to is the MDIO controller itself, right ?

> -	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) {
> +		if (!device_link_add(dev->dev.parent, phydev->mdio.bus->parent,
> +				     DL_FLAG_PM_RUNTIME |
> +				     DL_FLAG_AUTOREMOVE_SUPPLIER)) {

Don't we have the same problem with SFP ? The struct mii_bus for SFP
PHYs also completely disappears when you remove the module.

That being said, I ran some tests with SFP and this patch, and the
netdev actually didn't dissapear under my feet.

I'm a total noob with fw_devlink, but I can see there seems to already
be a link between MAC devices and the associated SFP bus :

on cyclone V :

# ls /sys/class/devlink
 [...]
platform:sfp--platform:ff702000.ethernet

on macchiatobin :

# ls /sys/class/devlink
 [...]
platform:sfp-eth3--platform:f4000000.ethernet

So I guess this is what's preventing the netdev from going away.

Now, these seems to be automagically populated based on DT, but I don't
know if it also works with non-DT platforms. If this is DT-specific,
then I guess we still can't use DL_FLAG_AUTOREMOVE_SUPPLIER.

Maxime
Re: [PATCH net] net: phy: add device link between MAC device and MDIO device
Posted by Jakub Kicinski 1 week, 2 days ago
On Mon, 26 Jan 2026 18:44:09 +0800 Wei Fang wrote:
> The commit bc66fa87d4fd ("net: phy: Add link between phy dev and mac
> dev") has created a device link between the MAC and the PHY if the MAC
> uses a shared MDIO bus (The MDIO and the MAC are two separate devices).
> Sarosh Hasan tried to change the DL_FLAG_STATELESS flag to
> DL_FLAG_AUTOREMOVE_SUPPLIER to fix the issue [1]. However, the solution
> does not take into account the hot-swappable PHY devices (such as SFP).
> so when the PHY device is unplugged, the MAC driver will automatically
> be removed, which is not the expected behavior.
> 
> Therefore, to solve this issue of the shared MDIO bus, we create the
> device link between the MAC device and the MDIO device, rather than
> between the MAC device and the PHY device. And when the shared MDIO bus
> is removed, all MAC drivers that depend on it will also be removed.

Anyone willing to venture a review tag?
Re: [PATCH net] net: phy: add device link between MAC device and MDIO device
Posted by Russell King (Oracle) 1 week, 2 days ago
On Wed, Jan 28, 2026 at 08:15:01PM -0800, Jakub Kicinski wrote:
> On Mon, 26 Jan 2026 18:44:09 +0800 Wei Fang wrote:
> > The commit bc66fa87d4fd ("net: phy: Add link between phy dev and mac
> > dev") has created a device link between the MAC and the PHY if the MAC
> > uses a shared MDIO bus (The MDIO and the MAC are two separate devices).
> > Sarosh Hasan tried to change the DL_FLAG_STATELESS flag to
> > DL_FLAG_AUTOREMOVE_SUPPLIER to fix the issue [1]. However, the solution
> > does not take into account the hot-swappable PHY devices (such as SFP).
> > so when the PHY device is unplugged, the MAC driver will automatically
> > be removed, which is not the expected behavior.
> > 
> > Therefore, to solve this issue of the shared MDIO bus, we create the
> > device link between the MAC device and the MDIO device, rather than
> > between the MAC device and the PHY device. And when the shared MDIO bus
> > is removed, all MAC drivers that depend on it will also be removed.
> 
> Anyone willing to venture a review tag?

No, I don't agrew with the patch.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
Re: [PATCH net] net: phy: add device link between MAC device and MDIO device
Posted by Andrew Lunn 1 week, 5 days ago
> The commit bc66fa87d4fd ("net: phy: Add link between phy dev and mac
> dev") has created a device link between the MAC and the PHY if the MAC
> uses a shared MDIO bus (The MDIO and the MAC are two separate devices).

> Sarosh Hasan tried to change the DL_FLAG_STATELESS flag to
> DL_FLAG_AUTOREMOVE_SUPPLIER to fix the issue [1]. However, the solution
> does not take into account the hot-swappable PHY devices (such as SFP).
> so when the PHY device is unplugged, the MAC driver will automatically
> be removed, which is not the expected behavior.
> 
> Therefore, to solve this issue of the shared MDIO bus, we create the
> device link between the MAC device and the MDIO device, rather than
> between the MAC device and the PHY device. And when the shared MDIO bus
> is removed, all MAC drivers that depend on it will also be removed.

Shouldn't there be a full chain here? MAC->MDIO->PHY?

For the case of the SFP, maybe it should be

MAC->SFP Cage and I2C MDIO->PHY

So if the PHY inside an SFP disappears, the I2C MDIO bus is
removed. But there is no link upwards from that, so the SFP cage and
the MAC are left alone?

    Andrew
Re: [PATCH net] net: phy: add device link between MAC device and MDIO device
Posted by Russell King (Oracle) 1 week, 5 days ago
On Mon, Jan 26, 2026 at 03:13:26PM +0100, Andrew Lunn wrote:
> > The commit bc66fa87d4fd ("net: phy: Add link between phy dev and mac
> > dev") has created a device link between the MAC and the PHY if the MAC
> > uses a shared MDIO bus (The MDIO and the MAC are two separate devices).
> 
> > Sarosh Hasan tried to change the DL_FLAG_STATELESS flag to
> > DL_FLAG_AUTOREMOVE_SUPPLIER to fix the issue [1]. However, the solution
> > does not take into account the hot-swappable PHY devices (such as SFP).
> > so when the PHY device is unplugged, the MAC driver will automatically
> > be removed, which is not the expected behavior.
> > 
> > Therefore, to solve this issue of the shared MDIO bus, we create the
> > device link between the MAC device and the MDIO device, rather than
> > between the MAC device and the PHY device. And when the shared MDIO bus
> > is removed, all MAC drivers that depend on it will also be removed.
> 
> Shouldn't there be a full chain here? MAC->MDIO->PHY?
> 
> For the case of the SFP, maybe it should be
> 
> MAC->SFP Cage and I2C MDIO->PHY
> 
> So if the PHY inside an SFP disappears, the I2C MDIO bus is
> removed.

That's a crazy idea. The SFP cage driver handles the presence of the
I2C-based MDIO bus, and has to because the type of bus created depends
on the module, and the lifetime of the bus is determined by the time
that the module is plugged in, not whether there's a PHY present.

If removing a PHY on a MDIO bus results in the bus to which it was
connected to being removed, that's utterly stupid, because that
means all other PHYs will end up being removed when the bus goes away.

Consider a MDIO bus that has some independent PHYs and a DSA switch
connected. Do we really want removal of the PHY to destroy the MDIO
bus, and thus also take out the DSA switch?

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!