[PATCH v2] platform/x86: thinkpad_acpi: Add "unrestricted_leds" module parameter

From: Rong Zhang

Date: Tue Nov 10 2026 - 13:45:45 EST


Since commit a4d5effcc737 ("thinkpad-acpi: restrict access to some
firmware LEDs"), most LEDs are classified as unsafe and write access to
them is restricted by default.

To enable unrestricted access, users have to build the kernel (module)
on their own with CONFIG_THINKPAD_ACPI_UNSAFE_LEDS enabled, as it's
unsupported and no distribution enables it.

The Kconfig option, for sure, acts as a gatekeeper very well, but it may
be too harsh when a user really has some sensible reasons to enable
unrestricted access, e.g., disable LEDs for better sleep quality.

As a result, there have been several attempts to loosen the restriction.

Introduce a new module parameter "unrestricted_leds" to allow enabling
unrestricted access to LEDs without rebuilding the kernel (module).

The module parameter is a bitmask, as we expect that users will read the
source code to determine which LED to enable and understand the
consequence. By limiting the scope of access to what the user needs,
this also prevents accidentally touching other unsafe LEDs via sysfs.

The Kconfig option is kept, but solely changes the default value of the
module parameter now. The preexisting pr_notice() message now prints
whenever an extra bit not in TPACPI_SAFE_LEDS is set.

Link: https://lore.kernel.org/all/20181113174136.58198c3a@xxxxxxxxx/
Link: https://lore.kernel.org/all/20250403040846.7834-1-martin@xxxxxxxxxx/
Link: https://lore.kernel.org/all/a14640f58be48d4912ce5808faea1402ad7f7ad0.1793906572.git.josh@xxxxxxxxxxxxxxxx/
Signed-off-by: Rong Zhang <i@xxxxxxxx>
---
Changes in v2:
- Use a module parameter "unrestricted_leds" rather than debugfs nodes
(thanks Henrique de Moraes Holschuh, Mark Pearson, Josh Triplett)
- https://msgid.link/c70af6c5-3d95-44c5-8f3f-b014178234c9@xxxxxxxxxxxxxxxx
- Link to v1: https://patch.msgid.link/20261107-tpacpi-debugfs-unlock-unsafe-led-v1-1-69b1f1e10c2f@xxxxxxxx
---
.../admin-guide/laptops/thinkpad-acpi.rst | 9 ++++----
drivers/platform/x86/lenovo/Kconfig | 3 +++
drivers/platform/x86/lenovo/thinkpad_acpi.c | 25 +++++++++++++++-------
3 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/Documentation/admin-guide/laptops/thinkpad-acpi.rst b/Documentation/admin-guide/laptops/thinkpad-acpi.rst
index 60bf6868b849..6e8c8575f758 100644
--- a/Documentation/admin-guide/laptops/thinkpad-acpi.rst
+++ b/Documentation/admin-guide/laptops/thinkpad-acpi.rst
@@ -794,10 +794,11 @@ buses are still active), or mask an important alarm (such as a nearly
empty battery, or a broken battery), access to most LEDs is
restricted.

-Unrestricted access to all LEDs requires that thinkpad-acpi be
-compiled with the CONFIG_THINKPAD_ACPI_UNSAFE_LEDS option enabled.
-Distributions must never enable this option. Individual users that
-are aware of the consequences are welcome to enabling it.
+Individual users that are aware of the consequences may enable
+unrestricted access to desired LEDs with either the "unrestricted_leds"
+module parameter or the CONFIG_THINKPAD_ACPI_UNSAFE_LEDS option
+(distributions must never enable it). Please always be aware of the
+danger of unrestricted LED access.

Audio mute and microphone mute LEDs are supported, but currently not
visible to userspace. They are used by the snd-hda-intel audio driver.
diff --git a/drivers/platform/x86/lenovo/Kconfig b/drivers/platform/x86/lenovo/Kconfig
index 516594993073..0995f61266e7 100644
--- a/drivers/platform/x86/lenovo/Kconfig
+++ b/drivers/platform/x86/lenovo/Kconfig
@@ -161,6 +161,9 @@ config THINKPAD_ACPI_UNSAFE_LEDS
and the driver will allow control of every LED, including
the ones on the dock stations.

+ This is also configurable via the "unrestricted_leds" module
+ parameter.
+
Never enable this option on a distribution kernel.

Say N here, unless you are building a kernel for your own
diff --git a/drivers/platform/x86/lenovo/thinkpad_acpi.c b/drivers/platform/x86/lenovo/thinkpad_acpi.c
index 4f81855ad721..dc0e4cff72cd 100644
--- a/drivers/platform/x86/lenovo/thinkpad_acpi.c
+++ b/drivers/platform/x86/lenovo/thinkpad_acpi.c
@@ -5608,15 +5608,20 @@ static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = {
"tpacpi::unknown_led3",
"tpacpi::thinkvantage",
};
-#define TPACPI_SAFE_LEDS 0x1481U

-static inline bool tpacpi_is_led_restricted(const unsigned int led)
-{
+#define TPACPI_SAFE_LEDS 0x1481U
+
#ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS
- return false;
+#define TPACPI_UNRESTRICTED_LEDS 0xFFFFU
#else
- return (1U & (TPACPI_SAFE_LEDS >> led)) == 0;
+#define TPACPI_UNRESTRICTED_LEDS TPACPI_SAFE_LEDS
#endif
+
+static unsigned int unrestricted_leds = TPACPI_UNRESTRICTED_LEDS;
+
+static inline bool tpacpi_is_led_restricted(const unsigned int led)
+{
+ return !(unrestricted_leds & BIT(led));
}

static int led_get_status(const unsigned int led)
@@ -5892,9 +5897,9 @@ static int __init led_init(struct ibm_init_struct *iibm)
}
}

-#ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS
- pr_notice("warning: userspace override of important firmware LEDs is enabled\n");
-#endif
+ if (unrestricted_leds & ~TPACPI_SAFE_LEDS)
+ pr_notice("warning: userspace override of important firmware LEDs is enabled\n");
+
return 0;
}

@@ -12238,6 +12243,10 @@ MODULE_PARM_DESC(uwb_state,
module_param(profile_force, int, 0444);
MODULE_PARM_DESC(profile_force, "Force profile mode. -1=off, 1=MMC, 2=PSC");

+module_param(unrestricted_leds, uint, 0444);
+MODULE_PARM_DESC(unrestricted_leds,
+ "Bitmask. Set/clear a bit to enable/disable unrestricted access to an LED");
+
static void thinkpad_acpi_module_exit(void)
{
tpacpi_lifecycle = TPACPI_LIFE_EXITING;

---
base-commit: 7475ea8b58616b33c04afb976cf0fbaad9dd63fb
change-id: 9fa95cad-tpacpi-debugfs-unlock-unsafe-led-17ad492d8f5c

Thanks,
Rong