Before this change the LED was added to leds_list before led_init_core()
gets called adding it the list before led_classdev.set_brightness_work gets
initialized.
This leaves a window where led_trigger_register() of a LED's default
trigger will call led_trigger_set() which calls led_set_brightness()
which in turn will end up queueing the *uninitialized*
led_classdev.set_brightness_work.
This race gets hit by the lenovo-thinkpad-t14s EC driver which registers
2 LEDs with a default trigger provided by snd_ctl_led.ko in quick
succession. The first led_classdev_register() causes an async modprobe of
snd_ctl_led to run and that async modprobe manages to exactly hit
the window where the second LED is on the leds_list without led_init_core()
being called for it, resulting in:
------------[ cut here ]------------
WARNING: CPU: 11 PID: 5608 at kernel/workqueue.c:4234 __flush_work+0x344/0x390
Hardware name: LENOVO 21N2S01F0B/21N2S01F0B, BIOS N42ET93W (2.23 ) 09/01/2025
...
Call trace:
__flush_work+0x344/0x390 (P)
flush_work+0x2c/0x50
led_trigger_set+0x1c8/0x340
led_trigger_register+0x17c/0x1c0
led_trigger_register_simple+0x84/0xe8
snd_ctl_led_init+0x40/0xf88 [snd_ctl_led]
do_one_initcall+0x5c/0x318
do_init_module+0x9c/0x2b8
load_module+0x7e0/0x998
Close the race window by moving the adding of the LED to leds_list to
after the led_init_core() call.
Cc: stable@vger.kernel.org
Fixes: d23a22a74f ("leds: delay led_set_brightness if stopping soft-blink")
Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Reviewed-by: Sebastian Reichel <sre@kernel.org>
Link: https://patch.msgid.link/20251211163727.366441-1-johannes.goede@oss.qualcomm.com
Signed-off-by: Lee Jones <lee@kernel.org>
Add 'name' argument to of_led_get() such that it can lookup LEDs in
devicetree by either name or index.
And use this modified function to add devicetree support to the generic
(non devicetree specific) [devm_]led_get() function.
This uses the standard devicetree pattern of adding a -names string array
to map names to the indexes for an array of resources.
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Hans de Goede <hansg@kernel.org>
Signed-off-by: Aleksandrs Vinarskis <alex@vinarskis.com>
Link: https://lore.kernel.org/r/20250910-leds-v5-3-bb90a0f897d5@vinarskis.com
Signed-off-by: Lee Jones <lee@kernel.org>
Pull LED updates from Lee Jones:
"Improvements & Fixes:
- A fix for QCOM Flash to prevent incorrect register access when the
driver is re-bound. This is solved by duplicating a static register
array during the probe function, which prevents register addresses
from being miscalculated after multiple binds
- The LP50xx driver now correctly handles the 'reg' property in
device tree child nodes to ensure the multi_index is set correctly.
This prevents issues where LEDs could be controlled incorrectly if
the device tree nodes were processed in a different order. An error
is returned if the reg property is missing or out of range
- Add a Kconfig dependency on between TPS6131x and
V4L2_FLASH_LED_CLASS to prevent a build failure when the driver is
built-in and the V4L2 flash infrastructure is a loadable module
- Fix a potential buffer overflow warning in PCA955x reported by
older GCC versions by using a more precise format specifier when
creating the default LED label.
Cleanups & Refactoring:
- Correct the MAINTAINERS file entry for the TPS6131X flash LED
driver to point to the correct device tree binding file name
- Fix a comment in the Flash Class for the flash_timeout setter to
"flash timeout" from "flash duration" for accuracy
- The of_led_get() function is no longer exported as it has no users
outside of its own module.
Removals:
- Revert the commit to configure LED blink intervals for hardware
offload in the Netdev Trigger. This change was found to break
existing PHY drivers by putting their LEDs into a permanent,
unconditional blinking state.
Device Tree Bindings Updates:
- Update the binding for LP50xx to document that the child reg
property is the index within the LED bank. The example was also
updated to use correct values
- Update the JNCP5623 binding to add 0x39 as a valid I2C address, as
it is used by the NCP5623C variant"
* tag 'leds-next-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/leds:
dt-bindings: leds: ncp5623: Add 0x39 as a valid I2C address
Revert "leds: trigger: netdev: Configure LED blink interval for HW offload"
leds: pca955x: Avoid potential overflow when filling default_label (take 2)
leds: Unexport of_led_get()
leds: tps6131x: Add V4L2_FLASH_LED_CLASS dependency
dt-bindings: leds: lp50xx: Document child reg, fix example
leds: leds-lp50xx: Handle reg to get correct multi_index
leds: led-class-flash:: Fix flash_timeout comment
MAINTAINERS: Adjust file entry in TPS6131X FLASH LED DRIVER
leds: flash: leds-qcom-flash: Fix registry access after re-bind
This allows to setup ordered workqueue for LEDs events. This may be
useful, because default 'system_wq' does not guarantee execution order
of each work_struct, thus for several brightness update requests (for
multiple LEDs), real brightness switch could be in random order.
Yes, for sysfs-based LEDs we have flush_work() call inside
brightness_store() operation, but it's blocking call, so userspace
caller can be blocked at a long time, which means LEDs animation stream
can be broken.
Ordered workqueue has the same behaviour as system_wq + flush_work(),
but all scheduled works are async and userspace caller is not blocked,
which it better for userspace animation scheduling.
Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
Signed-off-by: Dmitry Rokosov <ddrokosov@salutedevices.com>
Link: https://lore.kernel.org/r/20240903223936.21292-1-ddrokosov@salutedevices.com
[Lee: Couple of style fix-ups]
Signed-off-by: Lee Jones <lee@kernel.org>
Pull LED updates from Lee Jones:
"Core Frameworks:
- New trigger for Input Events
- New led_mc_set_brightness() call to adapt colour/brightness for
mutli-colour LEDs
- New lled_mc_trigger_event() call to call the above based on given
trigger conditions
- New led_get_color_name() call, a wrapper around the existing
led_colors[] array
- A new flag to avoid automatic renaming of LED devices
New Drivers:
- Silergy SY7802 Flash LED Controller
- Texas Instruments LP5569 LED Controller
- ChromeOS EC LED Controller
New Device Support:
- KTD202{6,7} support for Kinetic KTD2026/7 LEDs
Fix-ups:
- Replace ACPI/DT firmware helpers with agnostic variants
- Make use of resource managed devm_* API calls
- Device Tree binding adaptions/conversions/creation
- Constify/staticise applicable data structures
- Trivial; spelling, whitespace, coding-style adaptions
- Drop i2c_device_id::driver_data where the value is unused
- Utilise centrally provided helpers and macros to aid simplicity and
avoid duplication
- Use generic platform device properties instead of OF/ACPI specific
ones
- Consolidate/de-duplicate various functionality
- Remove superfluous/duplicated/unused sections
- Make use of the new *_scoped() guard APIs
- Improve/simplify error handling
Bug Fixes:
- Flush pending brightness changes before activating the trigger
- Repair incorrect device naming preventing matches
- Prevent memory leaks by correctly free resources during error
handling routines
- Repair locking issue causing circular dependency splats and
lock-ups
- Unregister sysfs entries before deactivating triggers to prevent
use-after issues
- Supply a bunch of MODULE_DESCRIPTIONs to silence modpost warnings
- Use correct return codes expected by the callers
- Omit set_brightness() error message for a LEDs that support only HW
triggers"
* tag 'leds-next-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/leds: (65 commits)
leds: leds-lp5569: Enable chip after chip configuration
leds: leds-lp5569: Better handle enabling clock internal setting
leds: leds-lp5569: Fix typo in driver name
leds: flash: leds-qcom-flash: Test the correct variable in init
leds: leds-lp55xx: Convert mutex lock/unlock to guard API
leds: leds-lp5523: Convert to sysfs_emit API
leds: leds-lp5569: Convert to sysfs_emit API
Revert "leds: led-core: Fix refcount leak in of_led_get()"
leds: leds-lp5569: Add support for Texas Instruments LP5569
leds: leds-lp55xx: Drop deprecated defines
leds: leds-lp55xx: Support ENGINE program up to 128 bytes
leds: leds-lp55xx: Generalize sysfs master_fader
leds: leds-lp55xx: Generalize sysfs engine_leds
leds: leds-lp55xx: Generalize sysfs engine_load and engine_mode
leds: leds-lp55xx: Generalize stop_engine function
leds: leds-lp55xx: Generalize turn_off_channels function
leds: leds-lp55xx: Generalize set_led_current function
leds: leds-lp55xx: Generalize multicolor_brightness function
leds: leds-lp55xx: Generalize led_brightness function
leds: leds-lp55xx: Generalize firmware_loaded function
...
Pull MFD updates from Lee Jones:
"New Drivers:
- ROHM BD96801 Power Management IC
- Cirrus Logic CS40L50 Haptic Driver with Waveform Memory
- Marvell 88PM886 Power Management IC
New Device Support:
- Keyboard Backlight to ChromeOS Embedded Controller
- LEDs to ChromeOS Embedded Controller
- Charge Control to ChromeOS Embedded Controller
- HW Monitoring Service to ChromeOS Embedded Controller
- AUXADCs to MediaTek MT635{7,8,9} Power Management ICs
New Functionality:
- Allow Syscon consumers to supply their own Regmaps on registration
Fix-ups:
- Constify/staticise applicable data structures
- Remove superfluous/duplicated/unused sections
- Device Tree binding adaptions/conversions/creation
- Trivial; spelling, whitespace, coding-style adaptions
- Utilise centrally provided helpers and macros to aid
simplicity/duplication
- Drop i2c_device_id::driver_data where the value is unused
- Replace ACPI/DT firmware helpers with agnostic variants
- Move over to GPIOD (descriptor-based) APIs
- Annotate a bunch of __counted_by() cases
- Straighten out some includes
Bug Fixes:
- Ensure potentially asserted recent lines are deasserted during
initialisation
- Avoid "<module>.ko is added to multiple modules" warnings
- Supply a bunch of MODULE_DESCRIPTIONs to silence modpost warnings
- Fix Wvoid-pointer-to-enum-cast warnings"
* tag 'mfd-next-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (87 commits)
mfd: timberdale: Attach device properties to TSC2007 board info
mfd: tmio: Move header to platform_data
mfd: tmio: Sanitize comments
mfd: tmio: Update include files
mmc: tmio/sdhi: Fix includes
mfd: tmio: Remove obsolete io accessors
mfd: tmio: Remove obsolete platform_data
watchdog: bd96801_wdt: Add missing include for FIELD_*()
dt-bindings: mfd: syscon: Add APM poweroff mailbox
dt-bindings: mfd: syscon: Split and enforce documenting MFD children
dt-bindings: mfd: rk817: Merge support for RK809
dt-bindings: mfd: rk817: Fixup clocks and reference dai-common
dt-bindings: mfd: syscon: Add TI's opp table compatible
mfd: omap-usb-tll: Use struct_size to allocate tll
dt-bindings: mfd: Explain lack of child dependency in simple-mfd
dt-bindings: mfd: Dual licensing for st,stpmic1 bindings
mfd: omap-usb-tll: Annotate struct usbtll_omap with __counted_by
mfd: tps6594-core: Remove unneeded semicolon in tps6594_check_crc_mode()
mfd: lm3533: Move to new GPIO descriptor-based APIs
mfd: tps65912: Use devm helper functions to simplify probe
...
This reverts commit da1afe8e60.
Commit 699a8c7c4b ("leds: Add of_led_get() and led_put()"), introduced in
5.5, added of_led_get() and led_put() but missed a put_device() in
led_put(), thus creating a leak in case the consumer device is removed.
Arguably device removal was not very popular, so this went apparently
unnoticed until 2022. In January 2023 two different patches got merged to
fix the same bug:
- commit da1afe8e60 ("leds: led-core: Fix refcount leak in of_led_get()")
- commit 445110941e ("leds: led-class: Add missing put_device() to led_put()")
They fix the bug in two different ways, which creates no patch conflicts,
and both were merged in v6.2. The result is that now there is one more
put_device() than get_device()s, instead of one less.
Arguably device removal is not very popular yet, so this apparently hasn't
been noticed as well up to now. But it blew up here while I'm working with
device tree overlay insertion and removal. The symptom is an apparently
unrelated list of oopses on device removal, with reasons:
kernfs: can not remove 'uevent', no directory
kernfs: can not remove 'brightness', no directory
kernfs: can not remove 'max_brightness', no directory
...
Here sysfs fails removing attribute files, which is because the device name
changed and so the sysfs path. This is because the device name string got
corrupted, which is because it got freed too early and its memory reused.
Different symptoms could appear in different use cases.
Fix by removing one of the two fixes.
The choice was to remove commit da1afe8e60 because:
* it is calling put_device() inside of_led_get() just after getting the
device, thus it is basically not refcounting the LED device at all
during its entire lifetime
* it does not add a corresponding put_device() in led_get(), so it fixes
only the OF case
The other fix (445110941e) is adding the put_device() in led_put() so it
covers the entire lifetime, and it works even in the non-DT case.
Fixes: da1afe8e60 ("leds: led-core: Fix refcount leak in of_led_get()")
Co-developed-by: Hervé Codina <herve.codina@bootlin.com>
Signed-off-by: Hervé Codina <herve.codina@bootlin.com>
Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
Link: https://lore.kernel.org/r/20240625-led-class-device-leak-v2-1-75fdccf47421@bootlin.com
Signed-off-by: Lee Jones <lee@kernel.org>
Commit 66601a29bb ("leds: class: If no default trigger is given, make
hw_control trigger the default trigger") causes ledtrig-netdev to get
set as default trigger on various network LEDs.
This causes users to hit a pre-existing AB-BA deadlock issue in
ledtrig-netdev between the LED-trigger locks and the rtnl mutex,
resulting in hung tasks in kernels >= 6.9.
Solving the deadlock is non trivial, so for now revert the change to
set the hw_control trigger as default trigger, so that ledtrig-netdev
no longer gets activated automatically for various network LEDs.
The netdev trigger is not needed because the network LEDs are usually under
hw-control and the netdev trigger tries to leave things that way so setting
it as the active trigger for the LED class device is a no-op.
Fixes: 66601a29bb ("leds: class: If no default trigger is given, make hw_control trigger the default trigger")
Reported-by: Genes Lists <lists@sapience.com>
Closes: https://lore.kernel.org/all/9d189ec329cfe68ed68699f314e191a10d4b5eda.camel@sapience.com/
Reported-by: Johannes Wüller <johanneswueller@gmail.com>
Closes: https://lore.kernel.org/lkml/e441605c-eaf2-4c2d-872b-d8e541f4cf60@gmail.com/
Cc: stable@vger.kernel.org
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Lee Jones <lee@kernel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Normally, the maximum brightness is determined by the hardware, and this
property is not required. This property is used to set a software limit.
It could happen that an LED is made so bright that it gets damaged or
causes damage due to restrictions in a specific system, such as mounting
conditions.
Note that this flag is mainly used for PWM-LEDs, where it is not possible
to map brightness to current. Drivers for other controllers should use
led-max-microamp.
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Astrid Rost <astrid.rost@axis.com>
Acked-by: Jacek Anaszewski <jacek.anaszewski@gmail.com>
Link: https://lore.kernel.org/r/20230703130313.548519-3-astrid.rost@axis.com
Signed-off-by: Lee Jones <lee@kernel.org>