mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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: 01e5b728e9 ("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>
			
			
This commit is contained in:
		
							parent
							
								
									e18f348632
								
							
						
					
					
						commit
						f0f2b992d8
					
				
					 1 changed files with 4 additions and 2 deletions
				
			
		| 
						 | 
					@ -3416,7 +3416,8 @@ static int phy_probe(struct device *dev)
 | 
				
			||||||
	/* Get the LEDs from the device tree, and instantiate standard
 | 
						/* Get the LEDs from the device tree, and instantiate standard
 | 
				
			||||||
	 * LEDs for them.
 | 
						 * LEDs for them.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (IS_ENABLED(CONFIG_PHYLIB_LEDS))
 | 
						if (IS_ENABLED(CONFIG_PHYLIB_LEDS) && !phy_driver_is_genphy(phydev) &&
 | 
				
			||||||
 | 
						    !phy_driver_is_genphy_10g(phydev))
 | 
				
			||||||
		err = of_phy_leds(phydev);
 | 
							err = of_phy_leds(phydev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
| 
						 | 
					@ -3433,7 +3434,8 @@ static int phy_remove(struct device *dev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cancel_delayed_work_sync(&phydev->state_queue);
 | 
						cancel_delayed_work_sync(&phydev->state_queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (IS_ENABLED(CONFIG_PHYLIB_LEDS))
 | 
						if (IS_ENABLED(CONFIG_PHYLIB_LEDS) && !phy_driver_is_genphy(phydev) &&
 | 
				
			||||||
 | 
						    !phy_driver_is_genphy_10g(phydev))
 | 
				
			||||||
		phy_leds_unregister(phydev);
 | 
							phy_leds_unregister(phydev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	phydev->state = PHY_DOWN;
 | 
						phydev->state = PHY_DOWN;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue