[PATCH net v1 1/2] net: phy: split phy_probe() error paths
From: Xuanqiang Luo <hidden>
Date: 2026-08-12 12:52:04
Also in:
lkml
Subsystem:
ethernet phy library, networking drivers, the rest · Maintainers:
Andrew Lunn, Heiner Kallweit, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
From: Xuanqiang Luo <redacted> phy_probe() uses one cleanup path for failures at every initialization stage. This runs cleanup for resources that have not been initialized and leaves phy_setup_ports() relying on its caller to remove an SFP upstream after a partial failure. Make phy_setup_ports() unwind the SFP upstream before removing its ports. Then split the phy_probe() cleanup so each failure path unwinds only the resources that may have been initialized. Signed-off-by: Xuanqiang Luo <redacted> --- drivers/net/phy/phy_device.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 0615228459ef4..f8e434daab66e 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c@@ -3556,6 +3556,9 @@ static int phy_setup_ports(struct phy_device *phydev) return 0; out: + sfp_bus_del_upstream(phydev->sfp_bus); + phydev->sfp_bus = NULL; + phy_cleanup_ports(phydev); return ret; }
@@ -3681,7 +3684,7 @@ static int phy_probe(struct device *dev) if (phydev->drv->probe) { err = phydev->drv->probe(phydev); if (err) - goto out; + goto out_reset; } phy_disable_interrupts(phydev);
@@ -3702,7 +3705,7 @@ static int phy_probe(struct device *dev) err = genphy_read_abilities(phydev); if (err) - goto out; + goto out_reset; if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported))
@@ -3719,7 +3722,7 @@ static int phy_probe(struct device *dev) err = phy_setup_ports(phydev); if (err) - goto out; + goto out_reset; phy_advertise_supported(phydev);
@@ -3728,7 +3731,7 @@ static int phy_probe(struct device *dev) */ err = genphy_c45_read_eee_adv(phydev, phydev->advertising_eee); if (err) - goto out; + goto out_ports; /* Get the EEE modes we want to prohibit. */ of_set_phy_eee_broken(phydev);
@@ -3781,20 +3784,22 @@ static int phy_probe(struct device *dev) if (IS_ENABLED(CONFIG_PHYLIB_LEDS) && !phy_driver_is_genphy(phydev)) { err = of_phy_leds(phydev); if (err) - goto out; + goto out_led_triggers; } return 0; -out: +out_led_triggers: + if (!phydev->is_on_sfp_module) + phy_led_triggers_unregister(phydev); + +out_ports: sfp_bus_del_upstream(phydev->sfp_bus); phydev->sfp_bus = NULL; phy_cleanup_ports(phydev); - if (!phydev->is_on_sfp_module) - phy_led_triggers_unregister(phydev); - +out_reset: /* Re-assert the reset signal on error */ phy_device_reset(phydev, 1);
--
2.43.0