[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20260126104409.1070403-1-wei.fang@nxp.com>
Date: Mon, 26 Jan 2026 18:44:09 +0800
From: Wei Fang <wei.fang@....com>
To: andrew@...n.ch,
hkallweit1@...il.com,
linux@...linux.org.uk,
davem@...emloft.net,
edumazet@...gle.com,
kuba@...nel.org,
pabeni@...hat.com,
florian.fainelli@...adcom.com,
xiaolei.wang@...driver.com,
maxime.chevallier@...tlin.com,
quic_abchauha@...cinc.com,
quic_sarohasa@...cinc.com
Cc: imx@...ts.linux.dev,
netdev@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: [PATCH net] net: phy: add device link between MAC device and MDIO device
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@...cinc.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@....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
Powered by blists - more mailing lists