[PATCH v2 08/13] leds: st1202: Take a reference on the LED firmware node

From: Manuel Fombuena

Date: Tue Sep 15 2026 - 10:39:09 EST


st1202_dt_init() stores each LED's firmware node while walking the
device tree with for_each_available_child_of_node_scoped(), which drops
its reference to the node at the end of every iteration. The LED class
stores the pointer with device_set_node() and does not take a reference
of its own, so nothing keeps the node alive for as long as the LED
device uses it. That has been the case since the driver was added, when
the LED class devices were registered inside that same loop.

Commit c72e455b89f2 ("leds: leds-st1202: Fix NULL pointer access on race
condition") moved the registration into a separate loop in
st1202_probe(), which also leaves the stored pointer unreferenced
between the two loops.

With CONFIG_OF_DYNAMIC the node can be freed while it is still in use,
leaving led->fwnode and the LED device's firmware node dangling.

Take a reference when the node is stored and release it through a devm
action. The action is registered before the LED class devices are, so it
runs after they have been unregistered.

Fixes: 259230378c65 ("leds: Add LED1202 I2C driver")
Signed-off-by: Manuel Fombuena <fombuena@xxxxxxxxxxx>
Assisted-by: LLM
---
drivers/leds/leds-st1202.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/leds/leds-st1202.c b/drivers/leds/leds-st1202.c
index 41eac6195659..ead7a3669312 100644
--- a/drivers/leds/leds-st1202.c
+++ b/drivers/leds/leds-st1202.c
@@ -12,6 +12,7 @@
#include <linux/i2c.h>
#include <linux/leds.h>
#include <linux/module.h>
+#include <linux/property.h>
#include <linux/slab.h>
#include <linux/string.h>

@@ -399,6 +400,11 @@ static int st1202_blink_set(struct led_classdev *led_cdev,
return 0;
}

+static void st1202_fwnode_put(void *data)
+{
+ fwnode_handle_put(data);
+}
+
static int st1202_dt_init(struct st1202_chip *chip)
{
struct device *dev = &chip->client->dev;
@@ -418,7 +424,11 @@ static int st1202_dt_init(struct st1202_chip *chip)

led = &chip->leds[reg];
led->is_active = true;
- led->fwnode = of_fwnode_handle(child);
+ led->fwnode = fwnode_handle_get(of_fwnode_handle(child));
+
+ err = devm_add_action_or_reset(dev, st1202_fwnode_put, led->fwnode);
+ if (err)
+ return err;

led->led_cdev.max_brightness = U8_MAX;
led->led_cdev.brightness_set_blocking = st1202_led_set;
--
2.55.0