Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: phy: Don't register LEDs for genphy

If a PHY has no driver, the genphy driver is probed/removed directly in
phy_attach/detach. If the PHY's ofnode has an "leds" subnode, then the
LEDs will be (un)registered when probing/removing the genphy driver.
This could occur if the leds are for a non-generic driver that isn't
loaded for whatever reason. Synchronously removing the PHY device in
phy_detach leads to the following deadlock:

rtnl_lock()
ndo_close()
...
phy_detach()
phy_remove()
phy_leds_unregister()
led_classdev_unregister()
led_trigger_set()
netdev_trigger_deactivate()
unregister_netdevice_notifier()
rtnl_lock()

There is a corresponding deadlock on the open/register side of things
(and that one is reported by lockdep), but it requires a race while this
one is deterministic.

Generic PHYs do not support LEDs anyway, so don't bother registering
them.

Fixes: 01e5b728e9e4 ("net: phy: Add a binding for PHY LEDs")
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
Link: https://patch.msgid.link/20250707195803.666097-1-sean.anderson@linux.dev
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Sean Anderson and committed by
Jakub Kicinski
f0f2b992 e18f3486

+4 -2
+4 -2
drivers/net/phy/phy_device.c
··· 3416 3416 /* Get the LEDs from the device tree, and instantiate standard 3417 3417 * LEDs for them. 3418 3418 */ 3419 - if (IS_ENABLED(CONFIG_PHYLIB_LEDS)) 3419 + if (IS_ENABLED(CONFIG_PHYLIB_LEDS) && !phy_driver_is_genphy(phydev) && 3420 + !phy_driver_is_genphy_10g(phydev)) 3420 3421 err = of_phy_leds(phydev); 3421 3422 3422 3423 out: ··· 3434 3433 3435 3434 cancel_delayed_work_sync(&phydev->state_queue); 3436 3435 3437 - if (IS_ENABLED(CONFIG_PHYLIB_LEDS)) 3436 + if (IS_ENABLED(CONFIG_PHYLIB_LEDS) && !phy_driver_is_genphy(phydev) && 3437 + !phy_driver_is_genphy_10g(phydev)) 3438 3438 phy_leds_unregister(phydev); 3439 3439 3440 3440 phydev->state = PHY_DOWN;