Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 141933
b: refs/heads/master
c: a4d5eff
h: refs/heads/master
i:
  141931: 9510154
v: v3
  • Loading branch information
Henrique de Moraes Holschuh authored and Len Brown committed Apr 4, 2009
1 parent 001144d commit 37883b3
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 21 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2586d5663d0a17d69383acf6110f16a979a07c4e
refs/heads/master: a4d5effcc73749ee3ebbf578d162905e6fa4e07d
11 changes: 11 additions & 0 deletions trunk/Documentation/laptops/thinkpad-acpi.txt
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,17 @@ some older ThinkPad models, it is possible to query the status of the
LED indicators as well. Newer ThinkPads cannot query the real status
of the LED indicators.

Because misuse of the LEDs could induce an unaware user to perform
dangerous actions (like undocking or ejecting a bay device while the
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.

procfs notes:

The available commands are:
Expand Down
24 changes: 24 additions & 0 deletions trunk/drivers/platform/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,30 @@ config THINKPAD_ACPI_DEBUG

If you are not sure, say N here.

config THINKPAD_ACPI_UNSAFE_LEDS
bool "Allow control of important LEDs (unsafe)"
depends on THINKPAD_ACPI
default n
---help---
Overriding LED state on ThinkPads can mask important
firmware alerts (like critical battery condition), or misled
the user into damaging the hardware (undocking or ejecting
the bay while buses are still active), etc.

LED control on the ThinkPad is write-only (with very few
exceptions on very ancient models), which makes it
impossible to know beforehand if important information will
be lost when one changes LED state.

Users that know what they are doing can enable this option
and the driver will allow control of every LED, including
the ones on the dock stations.

Never enable this option on a distribution kernel.

Say N here, unless you are building a kernel for your own
use, and need to control the important firmware LEDs.

config THINKPAD_ACPI_DOCK
bool "Legacy Docking Station Support"
depends on THINKPAD_ACPI
Expand Down
76 changes: 56 additions & 20 deletions trunk/drivers/platform/x86/thinkpad_acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -4657,6 +4657,16 @@ static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = {
"tpacpi::unknown_led",
"tpacpi::standby",
};
#define TPACPI_SAFE_LEDS 0x0081U

static inline bool tpacpi_is_led_restricted(const unsigned int led)
{
#ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS
return false;
#else
return (TPACPI_SAFE_LEDS & (1 << led)) == 0;
#endif
}

static int led_get_status(const unsigned int led)
{
Expand Down Expand Up @@ -4694,16 +4704,20 @@ static int led_set_status(const unsigned int led,
switch (led_supported) {
case TPACPI_LED_570:
/* 570 */
if (led > 7)
if (unlikely(led > 7))
return -EINVAL;
if (unlikely(tpacpi_is_led_restricted(led)))
return -EPERM;
if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
(1 << led), led_sled_arg1[ledstatus]))
rc = -EIO;
break;
case TPACPI_LED_OLD:
/* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
if (led > 7)
if (unlikely(led > 7))
return -EINVAL;
if (unlikely(tpacpi_is_led_restricted(led)))
return -EPERM;
rc = ec_write(TPACPI_LED_EC_HLMS, (1 << led));
if (rc >= 0)
rc = ec_write(TPACPI_LED_EC_HLBL,
Expand All @@ -4714,6 +4728,10 @@ static int led_set_status(const unsigned int led,
break;
case TPACPI_LED_NEW:
/* all others */
if (unlikely(led >= TPACPI_LED_NUMLEDS))
return -EINVAL;
if (unlikely(tpacpi_is_led_restricted(led)))
return -EPERM;
if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
led, led_led_arg1[ledstatus]))
rc = -EIO;
Expand Down Expand Up @@ -4806,6 +4824,30 @@ static void led_exit(void)
kfree(tpacpi_leds);
}

static int __init tpacpi_init_led(unsigned int led)
{
int rc;

tpacpi_leds[led].led = led;

tpacpi_leds[led].led_classdev.brightness_set = &led_sysfs_set;
tpacpi_leds[led].led_classdev.blink_set = &led_sysfs_blink_set;
if (led_supported == TPACPI_LED_570)
tpacpi_leds[led].led_classdev.brightness_get =
&led_sysfs_get;

tpacpi_leds[led].led_classdev.name = tpacpi_led_names[led];

INIT_WORK(&tpacpi_leds[led].work, led_set_status_worker);

rc = led_classdev_register(&tpacpi_pdev->dev,
&tpacpi_leds[led].led_classdev);
if (rc < 0)
tpacpi_leds[led].led_classdev.name = NULL;

return rc;
}

static int __init led_init(struct ibm_init_struct *iibm)
{
unsigned int i;
Expand Down Expand Up @@ -4839,27 +4881,21 @@ static int __init led_init(struct ibm_init_struct *iibm)
}

for (i = 0; i < TPACPI_LED_NUMLEDS; i++) {
tpacpi_leds[i].led = i;

tpacpi_leds[i].led_classdev.brightness_set = &led_sysfs_set;
tpacpi_leds[i].led_classdev.blink_set = &led_sysfs_blink_set;
if (led_supported == TPACPI_LED_570)
tpacpi_leds[i].led_classdev.brightness_get =
&led_sysfs_get;

tpacpi_leds[i].led_classdev.name = tpacpi_led_names[i];

INIT_WORK(&tpacpi_leds[i].work, led_set_status_worker);

rc = led_classdev_register(&tpacpi_pdev->dev,
&tpacpi_leds[i].led_classdev);
if (rc < 0) {
tpacpi_leds[i].led_classdev.name = NULL;
led_exit();
return rc;
if (!tpacpi_is_led_restricted(i)) {
rc = tpacpi_init_led(i);
if (rc < 0) {
led_exit();
return rc;
}
}
}

#ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS
if (led_supported != TPACPI_LED_NONE)
printk(TPACPI_NOTICE
"warning: userspace override of important "
"firmware LEDs is enabled\n");
#endif
return (led_supported != TPACPI_LED_NONE)? 0 : 1;
}

Expand Down

0 comments on commit 37883b3

Please sign in to comment.