[PATCH net] net: phy: mdio_device: leave PHY reset deasserted on unregister

From: leo.moerlein@xxxxxxxxx

Date: Wed May 20 2026 - 11:29:16 EST


From: Leonardo Mörlein <leo.moerlein@xxxxxxxxx>

Some PHY devices are discovered again after the MDIO bus is torn down and
reprobed, for example when a parent driver first returns -EPROBE_DEFER and
is probed again later.

This breaks boards where external PHYs have per-device reset lines
described through reset-gpios. mdiobus_register_device() acquires the
reset GPIO and asserts reset, mdio_probe() later deasserts it for the
active device, but mdiobus_unregister_device() used to release the GPIO
descriptor without first driving the line back to the inactive state.
If that descriptor was the last owner, then the PHY could remain held
in reset across the next bus registration and disappear from the reprobe
scan.

On a Lantiq GSWIP based FRITZ!Box 7360 v2 this left PHYs 0 and 1 missing
after a deferred reprobe, while PHYs without external reset lines were
still found. DSA then failed to attach those ports with -ENODEV.

Before releasing optional reset resources, deassert reset again for
PHY devices so the hardware stays discoverable across a later reprobe.

Link: https://github.com/openwrt/openwrt/issues/20629
Fixes: 8ea25274ebaf2 ("net: mdiobus: release reset_gpio in mdiobus_unregister_device()")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Leonardo Mörlein <leo.moerlein@xxxxxxxxx>
Assisted-by: GitHubCopilot:GPT-5.4
---
drivers/net/phy/mdio_device.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c
index 56080d3d2d25..9caeb9ea5248 100644
--- a/drivers/net/phy/mdio_device.c
+++ b/drivers/net/phy/mdio_device.c
@@ -215,6 +215,12 @@ int mdiobus_unregister_device(struct mdio_device *mdiodev)
if (mdiodev->bus->mdio_map[mdiodev->addr] != mdiodev)
return -EINVAL;

+ /*
+ * Leave optional reset lines deasserted before releasing them so devices
+ * remain discoverable across a later bus reprobe.
+ */
+ mdio_device_reset(mdiodev, 0);
+
mdio_device_unregister_reset(mdiodev);

mdiodev->bus->mdio_map[mdiodev->addr] = NULL;
--
2.51.2