Message ID | 20241003221006.4568-1-ansuelsmth@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [net,1/2] net: phy: Remove LED entry from LEDs list on unregister | expand |
On Fri, Oct 04, 2024 at 12:10:04AM +0200, Christian Marangi wrote: > Commit c938ab4da0eb ("net: phy: Manual remove LEDs to ensure correct > ordering") correctly fixed a problem with using devm_ but missed > removing the LED entry from the LEDs list. > > This cause kernel panic on specific scenario where the port for the PHY > is torn down and up and the kmod for the PHY is removed. > > On setting the port down the first time, the assosiacted LEDs are > correctly unregistered. The associated kmod for the PHY is now removed. > The kmod is now added again and the port is now put up, the associated LED > are registered again. > On putting the port down again for the second time after these step, the > LED list now have 4 elements. With the first 2 already unregistered > previously and the 2 new one registered again. > > This cause a kernel panic as the first 2 element should have been > removed. > > Fix this by correctly removing the element when LED is unregistered. > > Reported-by: Daniel Golle <daniel@makrotopia.org> > Tested-by: Daniel Golle <daniel@makrotopia.org> > Cc: stable@vger.kernel.org > Fixes: c938ab4da0eb ("net: phy: Manual remove LEDs to ensure correct ordering") > Signed-off-by: Christian Marangi <ansuelsmth@gmail.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Andrew
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 560e338b307a..499797646580 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -3326,10 +3326,11 @@ static __maybe_unused int phy_led_hw_is_supported(struct led_classdev *led_cdev, static void phy_leds_unregister(struct phy_device *phydev) { - struct phy_led *phyled; + struct phy_led *phyled, *tmp; - list_for_each_entry(phyled, &phydev->leds, list) { + list_for_each_entry_safe(phyled, tmp, &phydev->leds, list) { led_classdev_unregister(&phyled->led_cdev); + list_del(&phyled->list); } }