mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	net: phy: Manual remove LEDs to ensure correct ordering
If the core is left to remove the LEDs via devm_, it is performed too
late, after the PHY driver is removed from the PHY. This results in
dereferencing a NULL pointer when the LED core tries to turn the LED
off before destroying the LED.
Manually unregister the LEDs at a safe point in phy_remove.
Cc: stable@vger.kernel.org
Reported-by: Florian Fainelli <f.fainelli@gmail.com>
Suggested-by: Florian Fainelli <f.fainelli@gmail.com>
Fixes: 01e5b728e9 ("net: phy: Add a binding for PHY LEDs")
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									eb09fc2d14
								
							
						
					
					
						commit
						c938ab4da0
					
				
					 1 changed files with 14 additions and 1 deletions
				
			
		| 
						 | 
				
			
			@ -3021,6 +3021,15 @@ static int phy_led_blink_set(struct led_classdev *led_cdev,
 | 
			
		|||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void phy_leds_unregister(struct phy_device *phydev)
 | 
			
		||||
{
 | 
			
		||||
	struct phy_led *phyled;
 | 
			
		||||
 | 
			
		||||
	list_for_each_entry(phyled, &phydev->leds, list) {
 | 
			
		||||
		led_classdev_unregister(&phyled->led_cdev);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int of_phy_led(struct phy_device *phydev,
 | 
			
		||||
		      struct device_node *led)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -3054,7 +3063,7 @@ static int of_phy_led(struct phy_device *phydev,
 | 
			
		|||
	init_data.fwnode = of_fwnode_handle(led);
 | 
			
		||||
	init_data.devname_mandatory = true;
 | 
			
		||||
 | 
			
		||||
	err = devm_led_classdev_register_ext(dev, cdev, &init_data);
 | 
			
		||||
	err = led_classdev_register_ext(dev, cdev, &init_data);
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3083,6 +3092,7 @@ static int of_phy_leds(struct phy_device *phydev)
 | 
			
		|||
		err = of_phy_led(phydev, led);
 | 
			
		||||
		if (err) {
 | 
			
		||||
			of_node_put(led);
 | 
			
		||||
			phy_leds_unregister(phydev);
 | 
			
		||||
			return err;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3305,6 +3315,9 @@ static int phy_remove(struct device *dev)
 | 
			
		|||
 | 
			
		||||
	cancel_delayed_work_sync(&phydev->state_queue);
 | 
			
		||||
 | 
			
		||||
	if (IS_ENABLED(CONFIG_PHYLIB_LEDS))
 | 
			
		||||
		phy_leds_unregister(phydev);
 | 
			
		||||
 | 
			
		||||
	phydev->state = PHY_DOWN;
 | 
			
		||||
 | 
			
		||||
	sfp_bus_del_upstream(phydev->sfp_bus);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue