822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. From c938ab4da0eb1620ae3243b0b24c572ddfc318fc Mon Sep 17 00:00:00 2001
  2. From: Andrew Lunn <[email protected]>
  3. Date: Sat, 17 Jun 2023 17:55:00 +0200
  4. Subject: [PATCH] net: phy: Manual remove LEDs to ensure correct ordering
  5. If the core is left to remove the LEDs via devm_, it is performed too
  6. late, after the PHY driver is removed from the PHY. This results in
  7. dereferencing a NULL pointer when the LED core tries to turn the LED
  8. off before destroying the LED.
  9. Manually unregister the LEDs at a safe point in phy_remove.
  10. Cc: [email protected]
  11. Reported-by: Florian Fainelli <[email protected]>
  12. Suggested-by: Florian Fainelli <[email protected]>
  13. Fixes: 01e5b728e9e4 ("net: phy: Add a binding for PHY LEDs")
  14. Signed-off-by: Andrew Lunn <[email protected]>
  15. Signed-off-by: David S. Miller <[email protected]>
  16. ---
  17. drivers/net/phy/phy_device.c | 15 ++++++++++++++-
  18. 1 file changed, 14 insertions(+), 1 deletion(-)
  19. --- a/drivers/net/phy/phy_device.c
  20. +++ b/drivers/net/phy/phy_device.c
  21. @@ -3070,6 +3070,15 @@ static int phy_led_blink_set(struct led_
  22. return err;
  23. }
  24. +static void phy_leds_unregister(struct phy_device *phydev)
  25. +{
  26. + struct phy_led *phyled;
  27. +
  28. + list_for_each_entry(phyled, &phydev->leds, list) {
  29. + led_classdev_unregister(&phyled->led_cdev);
  30. + }
  31. +}
  32. +
  33. static int of_phy_led(struct phy_device *phydev,
  34. struct device_node *led)
  35. {
  36. @@ -3103,7 +3112,7 @@ static int of_phy_led(struct phy_device
  37. init_data.fwnode = of_fwnode_handle(led);
  38. init_data.devname_mandatory = true;
  39. - err = devm_led_classdev_register_ext(dev, cdev, &init_data);
  40. + err = led_classdev_register_ext(dev, cdev, &init_data);
  41. if (err)
  42. return err;
  43. @@ -3132,6 +3141,7 @@ static int of_phy_leds(struct phy_device
  44. err = of_phy_led(phydev, led);
  45. if (err) {
  46. of_node_put(led);
  47. + phy_leds_unregister(phydev);
  48. return err;
  49. }
  50. }
  51. @@ -3337,6 +3347,9 @@ static int phy_remove(struct device *dev
  52. cancel_delayed_work_sync(&phydev->state_queue);
  53. + if (IS_ENABLED(CONFIG_PHYLIB_LEDS))
  54. + phy_leds_unregister(phydev);
  55. +
  56. phydev->state = PHY_DOWN;
  57. sfp_bus_del_upstream(phydev->sfp_bus);