From 6fcc20ae2653b7be8dbd9d018c606e09905bfd3c Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Wed, 30 Apr 2008 17:39:08 -0300 Subject: [PATCH] Add patches accepted for 2.6.26-rc1 Signed-off-by: Henrique de Moraes Holschuh --- ...cpi-fix-possible-NULL-pointer-dereference.patch | 29 ++ ...inkpad-acpi-BIOS-backlight-mode-helper-v2.patch | 419 +++++++++++++++++++++ ...kpad-acpi-warn-once-about-weird-hotkey-ma.patch | 75 ++++ ...kpad-acpi-enhance-box-identification-outp.patch | 61 +++ ...kpad-acpi-rate-limit-CMOS-EC-unsynced-err.patch | 65 ++++ ...nkpad-acpi-fix-brightness-dimming-control.patch | 174 +++++++++ ...kpad-acpi-claim-tpacpi-as-an-official-sho.patch | 78 ++++ ...kpad-acpi-prepare-light-and-LED-for-sysfs.patch | 338 +++++++++++++++++ ...kpad-acpi-add-sysfs-led-class-support-for.patch | 148 ++++++++ ...nkpad-acpi-add-sysfs-led-class-support-to.patch | 285 ++++++++++++++ ...inkpad-acpi-use-uppercase-for-LED-on-user.patch | 89 +++++ ...ACPI-thinkpad-acpi-fluff-really-minor-fix.patch | 29 ++ ...CPI-thinkpad-acpi-use-a-private-workqueue.patch | 124 ++++++ ...CPI-thinkpad-acpi-bump-up-version-to-0.20.patch | 45 +++ 14 files changed, 1959 insertions(+) create mode 100644 releases/upstream/2.6.26-rc1/0001-thinkpad_acpi-fix-possible-NULL-pointer-dereference.patch create mode 100644 releases/upstream/2.6.26-rc1/0002-ACPI-thinkpad-acpi-BIOS-backlight-mode-helper-v2.patch create mode 100644 releases/upstream/2.6.26-rc1/0003-ACPI-thinkpad-acpi-warn-once-about-weird-hotkey-ma.patch create mode 100644 releases/upstream/2.6.26-rc1/0004-ACPI-thinkpad-acpi-enhance-box-identification-outp.patch create mode 100644 releases/upstream/2.6.26-rc1/0005-ACPI-thinkpad-acpi-rate-limit-CMOS-EC-unsynced-err.patch create mode 100644 releases/upstream/2.6.26-rc1/0006-ACPI-thinkpad-acpi-fix-brightness-dimming-control.patch create mode 100644 releases/upstream/2.6.26-rc1/0007-ACPI-thinkpad-acpi-claim-tpacpi-as-an-official-sho.patch create mode 100644 releases/upstream/2.6.26-rc1/0008-ACPI-thinkpad-acpi-prepare-light-and-LED-for-sysfs.patch create mode 100644 releases/upstream/2.6.26-rc1/0009-ACPI-thinkpad-acpi-add-sysfs-led-class-support-for.patch create mode 100644 releases/upstream/2.6.26-rc1/0010-ACPI-thinkpad-acpi-add-sysfs-led-class-support-to.patch create mode 100644 releases/upstream/2.6.26-rc1/0011-ACPI-thinkpad-acpi-use-uppercase-for-LED-on-user.patch create mode 100644 releases/upstream/2.6.26-rc1/0012-ACPI-thinkpad-acpi-fluff-really-minor-fix.patch create mode 100644 releases/upstream/2.6.26-rc1/0013-ACPI-thinkpad-acpi-use-a-private-workqueue.patch create mode 100644 releases/upstream/2.6.26-rc1/0014-ACPI-thinkpad-acpi-bump-up-version-to-0.20.patch diff --git a/releases/upstream/2.6.26-rc1/0001-thinkpad_acpi-fix-possible-NULL-pointer-dereference.patch b/releases/upstream/2.6.26-rc1/0001-thinkpad_acpi-fix-possible-NULL-pointer-dereference.patch new file mode 100644 index 00000000000..8e59a2dabfa --- /dev/null +++ b/releases/upstream/2.6.26-rc1/0001-thinkpad_acpi-fix-possible-NULL-pointer-dereference.patch @@ -0,0 +1,29 @@ +From 90fe17f4df2f830601ffd422b11d1f7f9a9d0355 Mon Sep 17 00:00:00 2001 +From: Cyrill Gorcunov +Date: Fri, 18 Apr 2008 13:27:29 -0700 +Subject: thinkpad_acpi: fix possible NULL pointer dereference if kstrdup failed + +Signed-off-by: Cyrill Gorcunov +Acked-by: Henrique de Moraes Holschuh +Signed-off-by: Andrew Morton +Signed-off-by: Len Brown +--- + drivers/misc/thinkpad_acpi.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c +index 6cb7812..31115c9 100644 +--- a/drivers/misc/thinkpad_acpi.c ++++ b/drivers/misc/thinkpad_acpi.c +@@ -5826,7 +5826,7 @@ static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp) + + tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION), + GFP_KERNEL); +- if (strnicmp(tp->model_str, "ThinkPad", 8) != 0) { ++ if (tp->model_str && strnicmp(tp->model_str, "ThinkPad", 8) != 0) { + kfree(tp->model_str); + tp->model_str = NULL; + } +-- +1.5.4.4 + diff --git a/releases/upstream/2.6.26-rc1/0002-ACPI-thinkpad-acpi-BIOS-backlight-mode-helper-v2.patch b/releases/upstream/2.6.26-rc1/0002-ACPI-thinkpad-acpi-BIOS-backlight-mode-helper-v2.patch new file mode 100644 index 00000000000..d3aeb9685f5 --- /dev/null +++ b/releases/upstream/2.6.26-rc1/0002-ACPI-thinkpad-acpi-BIOS-backlight-mode-helper-v2.patch @@ -0,0 +1,419 @@ +From b59727965d7f286489206c292e2788d4835a8a23 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Sat, 26 Apr 2008 01:02:17 -0300 +Subject: ACPI: thinkpad-acpi: BIOS backlight mode helper (v2.1) + +Lenovo ThinkPads with generic ACPI backlight level control can be easily +set to react to keyboard brightness key presses in a more predictable way +than what they do when in "DOS / bootloader" mode after Linux brings +up the ACPI interface. + +The switch to the ACPI backlight mode in the firmware is designed to be +safe to use only as an one way trapdoor. One is not to force the firmware +to switch back to "DOS/bootloader" mode except by rebooting. The mode +switch itself is performed by calling any of the ACPI _BCL methods at least +once. + +When in ACPI mode, the backlight firmware just issues (standard) events for +the brightness up/down hot key presses along with the non-standard HKEY +events which thinkpad-acpi traps, and doesn't touch the hardware. + +thinkpad-acpi will: + +1. Place the ThinkPad firmware in ACPI backlight control mode + if one is available +2. Suppress HKEY backlight change notifications by default + to avoid double-reporting when ACPI video is loaded when + the ThinkPad is in ACPI backlight control mode +3. Urge the user to load the ACPI video driver + +The user is free to use either the ACPI video driver to get the brightness +key events, or to override the thinkpad-acpi default hotkey mask to get +them from thinkpad-acpi as well (this will result in duplicate events if +ACPI video is loaded, so let's hope distros won't screw this up). + +Provided userspace is sane, all should work (and *keep* working), which is +more that can be said about the non-ACPI mode of the new Lenovo ThinkPad +BIOSes when coupled to current userspace and X.org drivers. + +Full guidelines for backlight hot key reporting and use of the +thinkpad-acpi backlight interface have been added to the documentation. + +Signed-off-by: Henrique de Moraes Holschuh +Cc: Matthew Garrett +Cc: Thomas Renninger +Signed-off-by: Len Brown +--- + Documentation/laptops/thinkpad-acpi.txt | 50 +++++++ + drivers/misc/thinkpad_acpi.c | 238 +++++++++++++++++-------------- + 2 files changed, 183 insertions(+), 105 deletions(-) + +diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt +index 76cb428..a77da28 100644 +--- a/Documentation/laptops/thinkpad-acpi.txt ++++ b/Documentation/laptops/thinkpad-acpi.txt +@@ -571,6 +571,47 @@ netlink interface and the input layer interface, and don't bother at all + with hotkey_report_mode. + + ++Brightness hotkey notes: ++ ++These are the current sane choices for brightness key mapping in ++thinkpad-acpi: ++ ++For IBM and Lenovo models *without* ACPI backlight control (the ones on ++which thinkpad-acpi will autoload its backlight interface by default, ++and on which ACPI video does not export a backlight interface): ++ ++1. Don't enable or map the brightness hotkeys in thinkpad-acpi, as ++ these older firmware versions unfortunately won't respect the hotkey ++ mask for brightness keys anyway, and always reacts to them. This ++ usually work fine, unless X.org drivers are doing something to block ++ the BIOS. In that case, use (3) below. This is the default mode of ++ operation. ++ ++2. Enable the hotkeys, but map them to something else that is NOT ++ KEY_BRIGHTNESS_UP/DOWN or any other keycode that would cause ++ userspace to try to change the backlight level, and use that as an ++ on-screen-display hint. ++ ++3. IF AND ONLY IF X.org drivers find a way to block the firmware from ++ automatically changing the brightness, enable the hotkeys and map ++ them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN, and feed that to ++ something that calls xbacklight. thinkpad-acpi will not be able to ++ change brightness in that case either, so you should disable its ++ backlight interface. ++ ++For Lenovo models *with* ACPI backlight control: ++ ++1. Load up ACPI video and use that. ACPI video will report ACPI ++ events for brightness change keys. Do not mess with thinkpad-acpi ++ defaults in this case. thinkpad-acpi should not have anything to do ++ with backlight events in a scenario where ACPI video is loaded: ++ brightness hotkeys must be disabled, and the backlight interface is ++ to be kept disabled as well. This is the default mode of operation. ++ ++2. Do *NOT* load up ACPI video, enable the hotkeys in thinkpad-acpi, ++ and map them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN. Process ++ these keys on userspace somehow (e.g. by calling xbacklight). ++ + Bluetooth + --------- + +@@ -1090,6 +1131,15 @@ it there will be the following attributes: + dim the display. + + ++WARNING: ++ ++ Whatever you do, do NOT ever call thinkpad-acpi backlight-level change ++ interface and the ACPI-based backlight level change interface ++ (available on newer BIOSes, and driven by the Linux ACPI video driver) ++ at the same time. The two will interact in bad ways, do funny things, ++ and maybe reduce the life of the backlight lamps by needlessly kicking ++ its level up and down at every change. ++ + Volume control -- /proc/acpi/ibm/volume + --------------------------------------- + +diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c +index 6cb7812..2c85a2e 100644 +--- a/drivers/misc/thinkpad_acpi.c ++++ b/drivers/misc/thinkpad_acpi.c +@@ -225,6 +225,7 @@ static struct { + u32 light:1; + u32 light_status:1; + u32 bright_16levels:1; ++ u32 bright_acpimode:1; + u32 wan:1; + u32 fan_ctrl_status_undef:1; + u32 input_device_registered:1; +@@ -807,6 +808,80 @@ static int parse_strtoul(const char *buf, + return 0; + } + ++static int __init tpacpi_query_bcl_levels(acpi_handle handle) ++{ ++ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; ++ union acpi_object *obj; ++ int rc; ++ ++ if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) { ++ obj = (union acpi_object *)buffer.pointer; ++ if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { ++ printk(TPACPI_ERR "Unknown _BCL data, " ++ "please report this to %s\n", TPACPI_MAIL); ++ rc = 0; ++ } else { ++ rc = obj->package.count; ++ } ++ } else { ++ return 0; ++ } ++ ++ kfree(buffer.pointer); ++ return rc; ++} ++ ++static acpi_status __init tpacpi_acpi_walk_find_bcl(acpi_handle handle, ++ u32 lvl, void *context, void **rv) ++{ ++ char name[ACPI_PATH_SEGMENT_LENGTH]; ++ struct acpi_buffer buffer = { sizeof(name), &name }; ++ ++ if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && ++ !strncmp("_BCL", name, sizeof(name) - 1)) { ++ BUG_ON(!rv || !*rv); ++ **(int **)rv = tpacpi_query_bcl_levels(handle); ++ return AE_CTRL_TERMINATE; ++ } else { ++ return AE_OK; ++ } ++} ++ ++/* ++ * Returns 0 (no ACPI _BCL or _BCL invalid), or size of brightness map ++ */ ++static int __init tpacpi_check_std_acpi_brightness_support(void) ++{ ++ int status; ++ int bcl_levels = 0; ++ void *bcl_ptr = &bcl_levels; ++ ++ if (!vid_handle) { ++ TPACPI_ACPIHANDLE_INIT(vid); ++ } ++ if (!vid_handle) ++ return 0; ++ ++ /* ++ * Search for a _BCL method, and execute it. This is safe on all ++ * ThinkPads, and as a side-effect, _BCL will place a Lenovo Vista ++ * BIOS in ACPI backlight control mode. We do NOT have to care ++ * about calling the _BCL method in an enabled video device, any ++ * will do for our purposes. ++ */ ++ ++ status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3, ++ tpacpi_acpi_walk_find_bcl, NULL, ++ &bcl_ptr); ++ ++ if (ACPI_SUCCESS(status) && bcl_levels > 2) { ++ tp_features.bright_acpimode = 1; ++ return (bcl_levels - 2); ++ } ++ ++ return 0; ++} ++ + /************************************************************************* + * thinkpad-acpi driver attributes + */ +@@ -1887,6 +1962,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) + KEY_UNKNOWN, /* 0x0D: FN+INSERT */ + KEY_UNKNOWN, /* 0x0E: FN+DELETE */ + ++ /* These either have to go through ACPI video, or ++ * act like in the IBM ThinkPads, so don't ever ++ * enable them by default */ + KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ + KEY_RESERVED, /* 0x10: FN+END (brightness down) */ + +@@ -2091,6 +2169,32 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) + set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); + } + ++ /* Do not issue duplicate brightness change events to ++ * userspace */ ++ if (!tp_features.bright_acpimode) ++ /* update bright_acpimode... */ ++ tpacpi_check_std_acpi_brightness_support(); ++ ++ if (tp_features.bright_acpimode) { ++ printk(TPACPI_INFO ++ "This ThinkPad has standard ACPI backlight " ++ "brightness control, supported by the ACPI " ++ "video driver\n"); ++ printk(TPACPI_NOTICE ++ "Disabling thinkpad-acpi brightness events " ++ "by default...\n"); ++ ++ /* The hotkey_reserved_mask change below is not ++ * necessary while the keys are at KEY_RESERVED in the ++ * default map, but better safe than sorry, leave it ++ * here as a marker of what we have to do, especially ++ * when we finally become able to set this at runtime ++ * on response to X.org requests */ ++ hotkey_reserved_mask |= ++ (1 << TP_ACPI_HOTKEYSCAN_FNHOME) ++ | (1 << TP_ACPI_HOTKEYSCAN_FNEND); ++ } ++ + dbg_printk(TPACPI_DBG_INIT, + "enabling hot key handling\n"); + res = hotkey_status_set(1); +@@ -4273,100 +4377,6 @@ static struct backlight_ops ibm_backlight_data = { + + /* --------------------------------------------------------------------- */ + +-static int __init tpacpi_query_bcll_levels(acpi_handle handle) +-{ +- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; +- union acpi_object *obj; +- int rc; +- +- if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) { +- obj = (union acpi_object *)buffer.pointer; +- if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { +- printk(TPACPI_ERR "Unknown BCLL data, " +- "please report this to %s\n", TPACPI_MAIL); +- rc = 0; +- } else { +- rc = obj->package.count; +- } +- } else { +- return 0; +- } +- +- kfree(buffer.pointer); +- return rc; +-} +- +-static acpi_status __init brightness_find_bcll(acpi_handle handle, u32 lvl, +- void *context, void **rv) +-{ +- char name[ACPI_PATH_SEGMENT_LENGTH]; +- struct acpi_buffer buffer = { sizeof(name), &name }; +- +- if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && +- !strncmp("BCLL", name, sizeof(name) - 1)) { +- if (tpacpi_query_bcll_levels(handle) == 16) { +- *rv = handle; +- return AE_CTRL_TERMINATE; +- } else { +- return AE_OK; +- } +- } else { +- return AE_OK; +- } +-} +- +-static int __init brightness_check_levels(void) +-{ +- int status; +- void *found_node = NULL; +- +- if (!vid_handle) { +- TPACPI_ACPIHANDLE_INIT(vid); +- } +- if (!vid_handle) +- return 0; +- +- /* Search for a BCLL package with 16 levels */ +- status = acpi_walk_namespace(ACPI_TYPE_PACKAGE, vid_handle, 3, +- brightness_find_bcll, NULL, +- &found_node); +- +- return (ACPI_SUCCESS(status) && found_node != NULL); +-} +- +-static acpi_status __init brightness_find_bcl(acpi_handle handle, u32 lvl, +- void *context, void **rv) +-{ +- char name[ACPI_PATH_SEGMENT_LENGTH]; +- struct acpi_buffer buffer = { sizeof(name), &name }; +- +- if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && +- !strncmp("_BCL", name, sizeof(name) - 1)) { +- *rv = handle; +- return AE_CTRL_TERMINATE; +- } else { +- return AE_OK; +- } +-} +- +-static int __init brightness_check_std_acpi_support(void) +-{ +- int status; +- void *found_node = NULL; +- +- if (!vid_handle) { +- TPACPI_ACPIHANDLE_INIT(vid); +- } +- if (!vid_handle) +- return 0; +- +- /* Search for a _BCL method, but don't execute it */ +- status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3, +- brightness_find_bcl, NULL, &found_node); +- +- return (ACPI_SUCCESS(status) && found_node != NULL); +-} +- + static int __init brightness_init(struct ibm_init_struct *iibm) + { + int b; +@@ -4375,13 +4385,19 @@ static int __init brightness_init(struct ibm_init_struct *iibm) + + mutex_init(&brightness_mutex); + +- if (!brightness_enable) { +- dbg_printk(TPACPI_DBG_INIT, +- "brightness support disabled by " +- "module parameter\n"); +- return 1; +- } else if (brightness_enable > 1) { +- if (brightness_check_std_acpi_support()) { ++ /* ++ * We always attempt to detect acpi support, so as to switch ++ * Lenovo Vista BIOS to ACPI brightness mode even if we are not ++ * going to publish a backlight interface ++ */ ++ b = tpacpi_check_std_acpi_brightness_support(); ++ if (b > 0) { ++ if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { ++ printk(TPACPI_NOTICE ++ "Lenovo BIOS switched to ACPI backlight " ++ "control mode\n"); ++ } ++ if (brightness_enable > 1) { + printk(TPACPI_NOTICE + "standard ACPI backlight interface " + "available, not loading native one...\n"); +@@ -4389,6 +4405,22 @@ static int __init brightness_init(struct ibm_init_struct *iibm) + } + } + ++ if (!brightness_enable) { ++ dbg_printk(TPACPI_DBG_INIT, ++ "brightness support disabled by " ++ "module parameter\n"); ++ return 1; ++ } ++ ++ if (b > 16) { ++ printk(TPACPI_ERR ++ "Unsupported brightness interface, " ++ "please contact %s\n", TPACPI_MAIL); ++ return 1; ++ } ++ if (b == 16) ++ tp_features.bright_16levels = 1; ++ + if (!brightness_mode) { + if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) + brightness_mode = 2; +@@ -4402,10 +4434,6 @@ static int __init brightness_init(struct ibm_init_struct *iibm) + if (brightness_mode > 3) + return -EINVAL; + +- tp_features.bright_16levels = +- thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO && +- brightness_check_levels(); +- + b = brightness_get(NULL); + if (b < 0) + return 1; +-- +1.5.4.4 + diff --git a/releases/upstream/2.6.26-rc1/0003-ACPI-thinkpad-acpi-warn-once-about-weird-hotkey-ma.patch b/releases/upstream/2.6.26-rc1/0003-ACPI-thinkpad-acpi-warn-once-about-weird-hotkey-ma.patch new file mode 100644 index 00000000000..fe52f1d7c46 --- /dev/null +++ b/releases/upstream/2.6.26-rc1/0003-ACPI-thinkpad-acpi-warn-once-about-weird-hotkey-ma.patch @@ -0,0 +1,75 @@ +From 92889022250d736e135ca92fbffd1ab0ea4780d1 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Sat, 26 Apr 2008 01:02:18 -0300 +Subject: ACPI: thinkpad-acpi: warn once about weird hotkey masks + +thinkpad-acpi knows for a while now how to best program the hotkeys by +default, and always enable them by default. Unfortunately, this +information has not filtered down everywhere it needs to, yet. Notably, +old ibm-acpi documentation and most "thinkpad setup guides" will have wrong +information on this area. + +Warn the local admin once whenever any of the following patterns are met: + +1. Attempts to set hotkey mask to 0xffff (artifact from docs and config + for the old ibm-acpi driver and behaviour). This mask makes no + real-world sense; + +2. Attempts to set hotkey mask to 0xffffffff, which means the user is + trying to just have "everything work" without even reading the + documentation, or that we need to get a bug report, because there + is a new thinkpad out there with new exciting hot keys :-) + +3. Attempts to set hotkey mask to 0xffffff, which is almost never the + correct way to set up volume and brightness event reporting (and with + the current state-of-the-art, it is known to never be right way to do + it). + +The driver will perform any and all requested operations, though, +regardless of any warnings. I hope these warnings can be removed one or +two years from now. + +Signed-off-by: Henrique de Moraes Holschuh +Signed-off-by: Len Brown +--- + drivers/misc/thinkpad_acpi.c | 17 +++++++++++++++++ + 1 files changed, 17 insertions(+), 0 deletions(-) + +diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c +index 2c85a2e..cd263c5 100644 +--- a/drivers/misc/thinkpad_acpi.c ++++ b/drivers/misc/thinkpad_acpi.c +@@ -237,6 +237,10 @@ static struct { + u32 hotkey_poll_active:1; + } tp_features; + ++static struct { ++ u16 hotkey_mask_ff:1; ++} tp_warned; ++ + struct thinkpad_id_data { + unsigned int vendor; /* ThinkPad vendor: + * PCI_VENDOR_ID_IBM/PCI_VENDOR_ID_LENOVO */ +@@ -1182,6 +1186,19 @@ static int hotkey_mask_set(u32 mask) + int rc = 0; + + if (tp_features.hotkey_mask) { ++ if (!tp_warned.hotkey_mask_ff && ++ (mask == 0xffff || mask == 0xffffff || ++ mask == 0xffffffff)) { ++ tp_warned.hotkey_mask_ff = 1; ++ printk(TPACPI_NOTICE ++ "setting the hotkey mask to 0x%08x is likely " ++ "not the best way to go about it\n", mask); ++ printk(TPACPI_NOTICE ++ "please consider using the driver defaults, " ++ "and refer to up-to-date thinkpad-acpi " ++ "documentation\n"); ++ } ++ + HOTKEY_CONFIG_CRITICAL_START + for (i = 0; i < 32; i++) { + u32 m = 1 << i; +-- +1.5.4.4 + diff --git a/releases/upstream/2.6.26-rc1/0004-ACPI-thinkpad-acpi-enhance-box-identification-outp.patch b/releases/upstream/2.6.26-rc1/0004-ACPI-thinkpad-acpi-enhance-box-identification-outp.patch new file mode 100644 index 00000000000..a11ad7a783b --- /dev/null +++ b/releases/upstream/2.6.26-rc1/0004-ACPI-thinkpad-acpi-enhance-box-identification-outp.patch @@ -0,0 +1,61 @@ +From 8c74adbc692a3cb040cc69d7ca3dfd86d75860a8 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Sat, 26 Apr 2008 01:02:19 -0300 +Subject: ACPI: thinkpad-acpi: enhance box identification output (v2) + +During initialization, thinkpad-acpi outputs some messages to make sure +releavant box identification information is easily available in-line with +the rest of the driver messages. + +Enhance those messages to output the alfanumeric model number as well. + +Signed-off-by: Henrique de Moraes Holschuh +Signed-off-by: Len Brown +--- + drivers/misc/thinkpad_acpi.c | 12 +++++++++--- + 1 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c +index cd263c5..601dbe8 100644 +--- a/drivers/misc/thinkpad_acpi.c ++++ b/drivers/misc/thinkpad_acpi.c +@@ -251,7 +251,8 @@ struct thinkpad_id_data { + u16 bios_model; /* Big Endian, TP-1Y = 0x5931, 0 = unknown */ + u16 ec_model; + +- char *model_str; ++ char *model_str; /* ThinkPad T43 */ ++ char *nummodel_str; /* 9384A9C for a 9384-A9C model */ + }; + static struct thinkpad_id_data thinkpad_id; + +@@ -988,12 +989,14 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm) + thinkpad_id.ec_version_str : "unknown"); + + if (thinkpad_id.vendor && thinkpad_id.model_str) +- printk(TPACPI_INFO "%s %s\n", ++ printk(TPACPI_INFO "%s %s, model %s\n", + (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ? + "IBM" : ((thinkpad_id.vendor == + PCI_VENDOR_ID_LENOVO) ? + "Lenovo" : "Unknown vendor"), +- thinkpad_id.model_str); ++ thinkpad_id.model_str, ++ (thinkpad_id.nummodel_str) ? ++ thinkpad_id.nummodel_str : "unknown"); + + return 0; + } +@@ -5875,6 +5878,9 @@ static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp) + kfree(tp->model_str); + tp->model_str = NULL; + } ++ ++ tp->nummodel_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_NAME), ++ GFP_KERNEL); + } + + static int __init probe_for_thinkpad(void) +-- +1.5.4.4 + diff --git a/releases/upstream/2.6.26-rc1/0005-ACPI-thinkpad-acpi-rate-limit-CMOS-EC-unsynced-err.patch b/releases/upstream/2.6.26-rc1/0005-ACPI-thinkpad-acpi-rate-limit-CMOS-EC-unsynced-err.patch new file mode 100644 index 00000000000..9c4cf5b1dc9 --- /dev/null +++ b/releases/upstream/2.6.26-rc1/0005-ACPI-thinkpad-acpi-rate-limit-CMOS-EC-unsynced-err.patch @@ -0,0 +1,65 @@ +From 2d5e94d7ca315f859a0eee1366838e8ad34dd7b2 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Sat, 26 Apr 2008 01:02:20 -0300 +Subject: ACPI: thinkpad-acpi: rate-limit CMOS/EC unsynced error messages + +If userspace applications mess with the CMOS NVRAM, or something causes +both the ACPI firmware and thinkpad-acpi to try to change the brightness at +the same time, it is possible to have the CMOS and EC registers for the +current brightness go out of sync. + +Should that happen, thinkpad-acpi could be really obnoxious when using a +brightness_mode of 3 (both EC and CMOS). Instead of complaining a massive +number of times, make sure to complain only once until EC and CMOS are back +in sync. + +Signed-off-by: Henrique de Moraes Holschuh +Cc: Joerg Platte +Signed-off-by: Len Brown +--- + drivers/misc/thinkpad_acpi.c | 22 +++++++++++++++------- + 1 files changed, 15 insertions(+), 7 deletions(-) + +diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c +index 601dbe8..7dc6b73 100644 +--- a/drivers/misc/thinkpad_acpi.c ++++ b/drivers/misc/thinkpad_acpi.c +@@ -239,6 +239,7 @@ static struct { + + static struct { + u16 hotkey_mask_ff:1; ++ u16 bright_cmos_ec_unsync:1; + } tp_warned; + + struct thinkpad_id_data { +@@ -4323,13 +4324,20 @@ static int brightness_get(struct backlight_device *bd) + level = lcmos; + } + +- if (brightness_mode == 3 && lec != lcmos) { +- printk(TPACPI_ERR +- "CMOS NVRAM (%u) and EC (%u) do not agree " +- "on display brightness level\n", +- (unsigned int) lcmos, +- (unsigned int) lec); +- return -EIO; ++ if (brightness_mode == 3) { ++ if (lec == lcmos) ++ tp_warned.bright_cmos_ec_unsync = 0; ++ else { ++ if (!tp_warned.bright_cmos_ec_unsync) { ++ printk(TPACPI_ERR ++ "CMOS NVRAM (%u) and EC (%u) do not " ++ "agree on display brightness level\n", ++ (unsigned int) lcmos, ++ (unsigned int) lec); ++ tp_warned.bright_cmos_ec_unsync = 1; ++ } ++ return -EIO; ++ } + } + + return level; +-- +1.5.4.4 + diff --git a/releases/upstream/2.6.26-rc1/0006-ACPI-thinkpad-acpi-fix-brightness-dimming-control.patch b/releases/upstream/2.6.26-rc1/0006-ACPI-thinkpad-acpi-fix-brightness-dimming-control.patch new file mode 100644 index 00000000000..b358376d128 --- /dev/null +++ b/releases/upstream/2.6.26-rc1/0006-ACPI-thinkpad-acpi-fix-brightness-dimming-control.patch @@ -0,0 +1,174 @@ +From e11aecf1379e7c4a0293182096e38e5a336696b2 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Sat, 26 Apr 2008 01:02:21 -0300 +Subject: ACPI: thinkpad-acpi: fix brightness dimming control bug + +ibm-acpi and thinkpad-acpi did not know about bit 5 of the EC backlight +level control register (EC 0x31), so it was always forced to zero on +any writes. + +This would disable the BIOS option to *not* use a dimmer backlight level +scale while on battery, and who knows what else (there are two other +control bits of unknown function). + +Bit 5 controls the "reduce backlight levels when on battery" optional +functionality (active low). Bits 6 and 7 are better left alone as well, +instead of being forced to zero. + +Signed-off-by: Henrique de Moraes Holschuh +Signed-off-by: Len Brown +--- + drivers/misc/thinkpad_acpi.c | 64 ++++++++++++++++++++++++++++++++---------- + 1 files changed, 49 insertions(+), 15 deletions(-) + +diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c +index 7dc6b73..5e25abc 100644 +--- a/drivers/misc/thinkpad_acpi.c ++++ b/drivers/misc/thinkpad_acpi.c +@@ -4295,8 +4295,16 @@ static struct ibm_struct ecdump_driver_data = { + + #define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen" + ++enum { ++ TP_EC_BACKLIGHT = 0x31, ++ ++ /* TP_EC_BACKLIGHT bitmasks */ ++ TP_EC_BACKLIGHT_LVLMSK = 0x1F, ++ TP_EC_BACKLIGHT_CMDMSK = 0xE0, ++ TP_EC_BACKLIGHT_MAPSW = 0x20, ++}; ++ + static struct backlight_device *ibm_backlight_device; +-static int brightness_offset = 0x31; + static int brightness_mode; + static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */ + +@@ -4305,16 +4313,24 @@ static struct mutex brightness_mutex; + /* + * ThinkPads can read brightness from two places: EC 0x31, or + * CMOS NVRAM byte 0x5E, bits 0-3. ++ * ++ * EC 0x31 has the following layout ++ * Bit 7: unknown function ++ * Bit 6: unknown function ++ * Bit 5: Z: honour scale changes, NZ: ignore scale changes ++ * Bit 4: must be set to zero to avoid problems ++ * Bit 3-0: backlight brightness level ++ * ++ * brightness_get_raw returns status data in the EC 0x31 layout + */ +-static int brightness_get(struct backlight_device *bd) ++static int brightness_get_raw(int *status) + { + u8 lec = 0, lcmos = 0, level = 0; + + if (brightness_mode & 1) { +- if (!acpi_ec_read(brightness_offset, &lec)) ++ if (!acpi_ec_read(TP_EC_BACKLIGHT, &lec)) + return -EIO; +- lec &= (tp_features.bright_16levels)? 0x0f : 0x07; +- level = lec; ++ level = lec & TP_EC_BACKLIGHT_LVLMSK; + }; + if (brightness_mode & 2) { + lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) +@@ -4325,6 +4341,8 @@ static int brightness_get(struct backlight_device *bd) + } + + if (brightness_mode == 3) { ++ *status = lec; /* Prefer EC, CMOS is just a backing store */ ++ lec &= TP_EC_BACKLIGHT_LVLMSK; + if (lec == lcmos) + tp_warned.bright_cmos_ec_unsync = 0; + else { +@@ -4338,9 +4356,11 @@ static int brightness_get(struct backlight_device *bd) + } + return -EIO; + } ++ } else { ++ *status = level; + } + +- return level; ++ return 0; + } + + /* May return EINTR which can always be mapped to ERESTARTSYS */ +@@ -4348,19 +4368,22 @@ static int brightness_set(int value) + { + int cmos_cmd, inc, i, res; + int current_value; ++ int command_bits; + +- if (value > ((tp_features.bright_16levels)? 15 : 7)) ++ if (value > ((tp_features.bright_16levels)? 15 : 7) || ++ value < 0) + return -EINVAL; + + res = mutex_lock_interruptible(&brightness_mutex); + if (res < 0) + return res; + +- current_value = brightness_get(NULL); +- if (current_value < 0) { +- res = current_value; ++ res = brightness_get_raw(¤t_value); ++ if (res < 0) + goto errout; +- } ++ ++ command_bits = current_value & TP_EC_BACKLIGHT_CMDMSK; ++ current_value &= TP_EC_BACKLIGHT_LVLMSK; + + cmos_cmd = value > current_value ? + TP_CMOS_BRIGHTNESS_UP : +@@ -4375,7 +4398,8 @@ static int brightness_set(int value) + goto errout; + } + if ((brightness_mode & 1) && +- !acpi_ec_write(brightness_offset, i + inc)) { ++ !acpi_ec_write(TP_EC_BACKLIGHT, ++ (i + inc) | command_bits)) { + res = -EIO; + goto errout;; + } +@@ -4398,6 +4422,17 @@ static int brightness_update_status(struct backlight_device *bd) + bd->props.brightness : 0); + } + ++static int brightness_get(struct backlight_device *bd) ++{ ++ int status, res; ++ ++ res = brightness_get_raw(&status); ++ if (res < 0) ++ return 0; /* FIXME: teach backlight about error handling */ ++ ++ return status & TP_EC_BACKLIGHT_LVLMSK; ++} ++ + static struct backlight_ops ibm_backlight_data = { + .get_brightness = brightness_get, + .update_status = brightness_update_status, +@@ -4462,8 +4497,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm) + if (brightness_mode > 3) + return -EINVAL; + +- b = brightness_get(NULL); +- if (b < 0) ++ if (brightness_get_raw(&b) < 0) + return 1; + + if (tp_features.bright_16levels) +@@ -4481,7 +4515,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm) + + ibm_backlight_device->props.max_brightness = + (tp_features.bright_16levels)? 15 : 7; +- ibm_backlight_device->props.brightness = b; ++ ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK; + backlight_update_status(ibm_backlight_device); + + return 0; +-- +1.5.4.4 + diff --git a/releases/upstream/2.6.26-rc1/0007-ACPI-thinkpad-acpi-claim-tpacpi-as-an-official-sho.patch b/releases/upstream/2.6.26-rc1/0007-ACPI-thinkpad-acpi-claim-tpacpi-as-an-official-sho.patch new file mode 100644 index 00000000000..c160de38241 --- /dev/null +++ b/releases/upstream/2.6.26-rc1/0007-ACPI-thinkpad-acpi-claim-tpacpi-as-an-official-sho.patch @@ -0,0 +1,78 @@ +From 95e57ab2cbd8b016327b23d76da8a96cbd26ac0c Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Sat, 26 Apr 2008 01:02:22 -0300 +Subject: ACPI: thinkpad-acpi: claim tpacpi as an official short handle (v1.1) + +Unfortunately, a lot of stuff in the kernel has size limitations, so +"thinkpad-acpi" ends up eating up too much real estate. We were using +"tpacpi" in symbols already, but this shorthand was not visible to +userland. + +Document that the driver will use tpacpi as a short hand where necessary, +and use it to name the kernel thread for NVRAM polling (now named +"ktpacpi_nvramd"). + +Also, register a module alias with the shorthand. One can refer to the +module using the shorthand name. + +Signed-off-by: Henrique de Moraes Holschuh +Signed-off-by: Len Brown +--- + Documentation/laptops/thinkpad-acpi.txt | 5 +++++ + drivers/misc/thinkpad_acpi.c | 8 ++++++-- + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt +index a77da28..a41bc89 100644 +--- a/Documentation/laptops/thinkpad-acpi.txt ++++ b/Documentation/laptops/thinkpad-acpi.txt +@@ -18,6 +18,11 @@ This driver used to be named ibm-acpi until kernel 2.6.21 and release + moved to the drivers/misc tree and renamed to thinkpad-acpi for kernel + 2.6.22, and release 0.14. + ++The driver is named "thinkpad-acpi". In some places, like module ++names, "thinkpad_acpi" is used because of userspace issues. ++ ++"tpacpi" is used as a shorthand where "thinkpad-acpi" would be too ++long due to length limitations on some Linux kernel versions. + + Status + ------ +diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c +index 5e25abc..2b73dfa 100644 +--- a/drivers/misc/thinkpad_acpi.c ++++ b/drivers/misc/thinkpad_acpi.c +@@ -133,8 +133,11 @@ enum { + #define TPACPI_PROC_DIR "ibm" + #define TPACPI_ACPI_EVENT_PREFIX "ibm" + #define TPACPI_DRVR_NAME TPACPI_FILE ++#define TPACPI_DRVR_SHORTNAME "tpacpi" + #define TPACPI_HWMON_DRVR_NAME TPACPI_NAME "_hwmon" + ++#define TPACPI_NVRAM_KTHREAD_NAME "ktpacpi_nvramd" ++ + #define TPACPI_MAX_ACPI_ARGS 3 + + /* Debugging */ +@@ -1523,8 +1526,7 @@ static void hotkey_poll_setup(int may_warn) + (tpacpi_inputdev->users > 0 || hotkey_report_mode < 2)) { + if (!tpacpi_hotkey_task) { + tpacpi_hotkey_task = kthread_run(hotkey_kthread, +- NULL, +- TPACPI_FILE "d"); ++ NULL, TPACPI_NVRAM_KTHREAD_NAME); + if (IS_ERR(tpacpi_hotkey_task)) { + tpacpi_hotkey_task = NULL; + printk(TPACPI_ERR +@@ -6316,6 +6318,8 @@ static int __init thinkpad_acpi_module_init(void) + /* Please remove this in year 2009 */ + MODULE_ALIAS("ibm_acpi"); + ++MODULE_ALIAS(TPACPI_DRVR_SHORTNAME); ++ + /* + * DMI matching for module autoloading + * +-- +1.5.4.4 + diff --git a/releases/upstream/2.6.26-rc1/0008-ACPI-thinkpad-acpi-prepare-light-and-LED-for-sysfs.patch b/releases/upstream/2.6.26-rc1/0008-ACPI-thinkpad-acpi-prepare-light-and-LED-for-sysfs.patch new file mode 100644 index 00000000000..b853d9a612d --- /dev/null +++ b/releases/upstream/2.6.26-rc1/0008-ACPI-thinkpad-acpi-prepare-light-and-LED-for-sysfs.patch @@ -0,0 +1,338 @@ +From 4fa6811b8ade1b7839342824939817a8fc751539 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Sat, 26 Apr 2008 01:02:23 -0300 +Subject: ACPI: thinkpad-acpi: prepare light and LED for sysfs support + +Do some preparatory work to add sysfs support to the thinklight and +thinkpad leds driver. + +Signed-off-by: Henrique de Moraes Holschuh +Signed-off-by: Len Brown +--- + drivers/misc/Kconfig | 2 + + drivers/misc/thinkpad_acpi.c | 191 ++++++++++++++++++++++++++++++------------ + 2 files changed, 138 insertions(+), 55 deletions(-) + +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig +index 297a48f..3a5d769 100644 +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -245,6 +245,8 @@ config THINKPAD_ACPI + select HWMON + select NVRAM + depends on INPUT ++ select NEW_LEDS ++ select LEDS_CLASS + ---help--- + This is a driver for the IBM and Lenovo ThinkPad laptops. It adds + support for Fn-Fx key combinations, Bluetooth control, video +diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c +index 2b73dfa..5a3fb09 100644 +--- a/drivers/misc/thinkpad_acpi.c ++++ b/drivers/misc/thinkpad_acpi.c +@@ -67,6 +67,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -85,6 +86,8 @@ + #define TP_CMOS_VOLUME_MUTE 2 + #define TP_CMOS_BRIGHTNESS_UP 4 + #define TP_CMOS_BRIGHTNESS_DOWN 5 ++#define TP_CMOS_THINKLIGHT_ON 12 ++#define TP_CMOS_THINKLIGHT_OFF 13 + + /* NVRAM Addresses */ + enum tp_nvram_addr { +@@ -269,6 +272,13 @@ static enum { + static int experimental; + static u32 dbg_level; + ++/* Special LED class that can defer work */ ++struct tpacpi_led_classdev { ++ struct led_classdev led_classdev; ++ struct work_struct work; ++ enum led_brightness new_brightness; ++}; ++ + /**************************************************************************** + **************************************************************************** + * +@@ -3237,6 +3247,39 @@ static struct ibm_struct video_driver_data = { + TPACPI_HANDLE(lght, root, "\\LGHT"); /* A21e, A2xm/p, T20-22, X20-21 */ + TPACPI_HANDLE(ledb, ec, "LEDB"); /* G4x */ + ++static int light_get_status(void) ++{ ++ int status = 0; ++ ++ if (tp_features.light_status) { ++ if (!acpi_evalf(ec_handle, &status, "KBLT", "d")) ++ return -EIO; ++ return (!!status); ++ } ++ ++ return -ENXIO; ++} ++ ++static int light_set_status(int status) ++{ ++ int rc; ++ ++ if (tp_features.light) { ++ if (cmos_handle) { ++ rc = acpi_evalf(cmos_handle, NULL, NULL, "vd", ++ (status)? ++ TP_CMOS_THINKLIGHT_ON : ++ TP_CMOS_THINKLIGHT_OFF); ++ } else { ++ rc = acpi_evalf(lght_handle, NULL, NULL, "vd", ++ (status)? 1 : 0); ++ } ++ return (rc)? 0 : -EIO; ++ } ++ ++ return -ENXIO; ++} ++ + static int __init light_init(struct ibm_init_struct *iibm) + { + vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n"); +@@ -3263,7 +3306,7 @@ static int __init light_init(struct ibm_init_struct *iibm) + static int light_read(char *p) + { + int len = 0; +- int status = 0; ++ int status; + + if (!tp_features.light) { + len += sprintf(p + len, "status:\t\tnot supported\n"); +@@ -3271,8 +3314,9 @@ static int light_read(char *p) + len += sprintf(p + len, "status:\t\tunknown\n"); + len += sprintf(p + len, "commands:\ton, off\n"); + } else { +- if (!acpi_evalf(ec_handle, &status, "KBLT", "d")) +- return -EIO; ++ status = light_get_status(); ++ if (status < 0) ++ return status; + len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0)); + len += sprintf(p + len, "commands:\ton, off\n"); + } +@@ -3282,31 +3326,22 @@ static int light_read(char *p) + + static int light_write(char *buf) + { +- int cmos_cmd, lght_cmd; + char *cmd; +- int success; ++ int newstatus = 0; + + if (!tp_features.light) + return -ENODEV; + + while ((cmd = next_cmd(&buf))) { + if (strlencmp(cmd, "on") == 0) { +- cmos_cmd = 0x0c; +- lght_cmd = 1; ++ newstatus = 1; + } else if (strlencmp(cmd, "off") == 0) { +- cmos_cmd = 0x0d; +- lght_cmd = 0; ++ newstatus = 0; + } else + return -EINVAL; +- +- success = cmos_handle ? +- acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd) : +- acpi_evalf(lght_handle, NULL, NULL, "vd", lght_cmd); +- if (!success) +- return -EIO; + } + +- return 0; ++ return light_set_status(newstatus); + } + + static struct ibm_struct light_driver_data = { +@@ -3710,6 +3745,12 @@ enum { /* For TPACPI_LED_OLD */ + TPACPI_LED_EC_HLMS = 0x0e, /* EC reg to select led to command */ + }; + ++enum led_status_t { ++ TPACPI_LED_OFF = 0, ++ TPACPI_LED_ON, ++ TPACPI_LED_BLINK, ++}; ++ + static enum led_access_mode led_supported; + + TPACPI_HANDLE(led, ec, "SLED", /* 570 */ +@@ -3718,6 +3759,69 @@ TPACPI_HANDLE(led, ec, "SLED", /* 570 */ + "LED", /* all others */ + ); /* R30, R31 */ + ++static int led_get_status(unsigned int led) ++{ ++ int status; ++ ++ switch (led_supported) { ++ case TPACPI_LED_570: ++ if (!acpi_evalf(ec_handle, ++ &status, "GLED", "dd", 1 << led)) ++ return -EIO; ++ return (status == 0)? ++ TPACPI_LED_OFF : ++ ((status == 1)? ++ TPACPI_LED_ON : ++ TPACPI_LED_BLINK); ++ default: ++ return -ENXIO; ++ } ++ ++ /* not reached */ ++} ++ ++static int led_set_status(unsigned int led, enum led_status_t ledstatus) ++{ ++ /* off, on, blink. Index is led_status_t */ ++ static const int const led_sled_arg1[] = { 0, 1, 3 }; ++ static const int const led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */ ++ static const int const led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */ ++ static const int const led_led_arg1[] = { 0, 0x80, 0xc0 }; ++ ++ int rc = 0; ++ ++ switch (led_supported) { ++ case TPACPI_LED_570: ++ /* 570 */ ++ led = 1 << led; ++ if (!acpi_evalf(led_handle, NULL, NULL, "vdd", ++ led, led_sled_arg1[ledstatus])) ++ rc = -EIO; ++ break; ++ case TPACPI_LED_OLD: ++ /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */ ++ led = 1 << led; ++ rc = ec_write(TPACPI_LED_EC_HLMS, led); ++ if (rc >= 0) ++ rc = ec_write(TPACPI_LED_EC_HLBL, ++ led * led_exp_hlbl[ledstatus]); ++ if (rc >= 0) ++ rc = ec_write(TPACPI_LED_EC_HLCL, ++ led * led_exp_hlcl[ledstatus]); ++ break; ++ case TPACPI_LED_NEW: ++ /* all others */ ++ if (!acpi_evalf(led_handle, NULL, NULL, "vdd", ++ led, led_led_arg1[ledstatus])) ++ rc = -EIO; ++ break; ++ default: ++ rc = -ENXIO; ++ } ++ ++ return rc; ++} ++ + static int __init led_init(struct ibm_init_struct *iibm) + { + vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n"); +@@ -3743,7 +3847,9 @@ static int __init led_init(struct ibm_init_struct *iibm) + return (led_supported != TPACPI_LED_NONE)? 0 : 1; + } + +-#define led_status(s) ((s) == 0 ? "off" : ((s) == 1 ? "on" : "blinking")) ++#define str_led_status(s) \ ++ ((s) == TPACPI_LED_OFF ? "off" : \ ++ ((s) == TPACPI_LED_ON ? "on" : "blinking")) + + static int led_read(char *p) + { +@@ -3759,11 +3865,11 @@ static int led_read(char *p) + /* 570 */ + int i, status; + for (i = 0; i < 8; i++) { +- if (!acpi_evalf(ec_handle, +- &status, "GLED", "dd", 1 << i)) ++ status = led_get_status(i); ++ if (status < 0) + return -EIO; + len += sprintf(p + len, "%d:\t\t%s\n", +- i, led_status(status)); ++ i, str_led_status(status)); + } + } + +@@ -3773,16 +3879,11 @@ static int led_read(char *p) + return len; + } + +-/* off, on, blink */ +-static const int led_sled_arg1[] = { 0, 1, 3 }; +-static const int led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */ +-static const int led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */ +-static const int led_led_arg1[] = { 0, 0x80, 0xc0 }; +- + static int led_write(char *buf) + { + char *cmd; +- int led, ind, ret; ++ int led, rc; ++ enum led_status_t s; + + if (!led_supported) + return -ENODEV; +@@ -3792,38 +3893,18 @@ static int led_write(char *buf) + return -EINVAL; + + if (strstr(cmd, "off")) { +- ind = 0; ++ s = TPACPI_LED_OFF; + } else if (strstr(cmd, "on")) { +- ind = 1; ++ s = TPACPI_LED_ON; + } else if (strstr(cmd, "blink")) { +- ind = 2; +- } else +- return -EINVAL; +- +- if (led_supported == TPACPI_LED_570) { +- /* 570 */ +- led = 1 << led; +- if (!acpi_evalf(led_handle, NULL, NULL, "vdd", +- led, led_sled_arg1[ind])) +- return -EIO; +- } else if (led_supported == TPACPI_LED_OLD) { +- /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */ +- led = 1 << led; +- ret = ec_write(TPACPI_LED_EC_HLMS, led); +- if (ret >= 0) +- ret = ec_write(TPACPI_LED_EC_HLBL, +- led * led_exp_hlbl[ind]); +- if (ret >= 0) +- ret = ec_write(TPACPI_LED_EC_HLCL, +- led * led_exp_hlcl[ind]); +- if (ret < 0) +- return ret; ++ s = TPACPI_LED_BLINK; + } else { +- /* all others */ +- if (!acpi_evalf(led_handle, NULL, NULL, "vdd", +- led, led_led_arg1[ind])) +- return -EIO; ++ return -EINVAL; + } ++ ++ rc = led_set_status(led, s); ++ if (rc < 0) ++ return rc; + } + + return 0; +-- +1.5.4.4 + diff --git a/releases/upstream/2.6.26-rc1/0009-ACPI-thinkpad-acpi-add-sysfs-led-class-support-for.patch b/releases/upstream/2.6.26-rc1/0009-ACPI-thinkpad-acpi-add-sysfs-led-class-support-for.patch new file mode 100644 index 00000000000..70815d32b62 --- /dev/null +++ b/releases/upstream/2.6.26-rc1/0009-ACPI-thinkpad-acpi-add-sysfs-led-class-support-for.patch @@ -0,0 +1,148 @@ +From e306501d1c4ff610feaba74ac35dd13e470480e6 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Sat, 26 Apr 2008 01:02:24 -0300 +Subject: ACPI: thinkpad-acpi: add sysfs led class support for thinklight (v3.1) + +Add a sysfs led class interface to the thinklight (light subdriver). + +Signed-off-by: Henrique de Moraes Holschuh +Cc: Richard Purdie +Signed-off-by: Len Brown +--- + Documentation/laptops/thinkpad-acpi.txt | 25 +++++++++++--- + drivers/misc/thinkpad_acpi.c | 57 ++++++++++++++++++++++++++++++- + 2 files changed, 76 insertions(+), 6 deletions(-) + +diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt +index a41bc89..af1f2bc 100644 +--- a/Documentation/laptops/thinkpad-acpi.txt ++++ b/Documentation/laptops/thinkpad-acpi.txt +@@ -693,16 +693,31 @@ while others are still having problems. For more information: + + https://bugs.freedesktop.org/show_bug.cgi?id=2000 + +-ThinkLight control -- /proc/acpi/ibm/light +------------------------------------------- ++ThinkLight control ++------------------ ++ ++procfs: /proc/acpi/ibm/light ++sysfs attributes: as per led class, for the "tpacpi::thinklight" led ++ ++procfs notes: + +-The current status of the ThinkLight can be found in this file. A few +-models which do not make the status available will show it as +-"unknown". The available commands are: ++The ThinkLight status can be read and set through the procfs interface. A ++few models which do not make the status available will show the ThinkLight ++status as "unknown". The available commands are: + + echo on > /proc/acpi/ibm/light + echo off > /proc/acpi/ibm/light + ++sysfs notes: ++ ++The ThinkLight sysfs interface is documented by the led class ++documentation, in Documentation/leds-class.txt. The ThinkLight led name ++is "tpacpi::thinklight". ++ ++Due to limitations in the sysfs led class, if the status of the thinklight ++cannot be read or if it is unknown, thinkpad-acpi will report it as "off". ++It is impossible to know if the status returned through sysfs is valid. ++ + Docking / undocking -- /proc/acpi/ibm/dock + ------------------------------------------ + +diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c +index 5a3fb09..38a119b 100644 +--- a/drivers/misc/thinkpad_acpi.c ++++ b/drivers/misc/thinkpad_acpi.c +@@ -3280,13 +3280,49 @@ static int light_set_status(int status) + return -ENXIO; + } + ++static void light_set_status_worker(struct work_struct *work) ++{ ++ struct tpacpi_led_classdev *data = ++ container_of(work, struct tpacpi_led_classdev, work); ++ ++ if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING)) ++ light_set_status((data->new_brightness != LED_OFF)); ++} ++ ++static void light_sysfs_set(struct led_classdev *led_cdev, ++ enum led_brightness brightness) ++{ ++ struct tpacpi_led_classdev *data = ++ container_of(led_cdev, ++ struct tpacpi_led_classdev, ++ led_classdev); ++ data->new_brightness = brightness; ++ schedule_work(&data->work); ++} ++ ++static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev) ++{ ++ return (light_get_status() == 1)? LED_FULL : LED_OFF; ++} ++ ++static struct tpacpi_led_classdev tpacpi_led_thinklight = { ++ .led_classdev = { ++ .name = "tpacpi::thinklight", ++ .brightness_set = &light_sysfs_set, ++ .brightness_get = &light_sysfs_get, ++ } ++}; ++ + static int __init light_init(struct ibm_init_struct *iibm) + { ++ int rc = 0; ++ + vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n"); + + TPACPI_ACPIHANDLE_INIT(ledb); + TPACPI_ACPIHANDLE_INIT(lght); + TPACPI_ACPIHANDLE_INIT(cmos); ++ INIT_WORK(&tpacpi_led_thinklight.work, light_set_status_worker); + + /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */ + tp_features.light = (cmos_handle || lght_handle) && !ledb_handle; +@@ -3300,7 +3336,25 @@ static int __init light_init(struct ibm_init_struct *iibm) + vdbg_printk(TPACPI_DBG_INIT, "light is %s\n", + str_supported(tp_features.light)); + +- return (tp_features.light)? 0 : 1; ++ if (tp_features.light) { ++ rc = led_classdev_register(&tpacpi_pdev->dev, ++ &tpacpi_led_thinklight.led_classdev); ++ } ++ ++ if (rc < 0) { ++ tp_features.light = 0; ++ tp_features.light_status = 0; ++ } else { ++ rc = (tp_features.light)? 0 : 1; ++ } ++ return rc; ++} ++ ++static void light_exit(void) ++{ ++ led_classdev_unregister(&tpacpi_led_thinklight.led_classdev); ++ if (work_pending(&tpacpi_led_thinklight.work)) ++ flush_scheduled_work(); + } + + static int light_read(char *p) +@@ -3348,6 +3402,7 @@ static struct ibm_struct light_driver_data = { + .name = "light", + .read = light_read, + .write = light_write, ++ .exit = light_exit, + }; + + /************************************************************************* +-- +1.5.4.4 + diff --git a/releases/upstream/2.6.26-rc1/0010-ACPI-thinkpad-acpi-add-sysfs-led-class-support-to.patch b/releases/upstream/2.6.26-rc1/0010-ACPI-thinkpad-acpi-add-sysfs-led-class-support-to.patch new file mode 100644 index 00000000000..f2df76b7b99 --- /dev/null +++ b/releases/upstream/2.6.26-rc1/0010-ACPI-thinkpad-acpi-add-sysfs-led-class-support-to.patch @@ -0,0 +1,285 @@ +From af116101924914a9655dfad108548d0db58c40f9 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Sat, 26 Apr 2008 01:02:25 -0300 +Subject: ACPI: thinkpad-acpi: add sysfs led class support to thinkpad leds (v3.2) + +Add a sysfs led class interface to the led subdriver. + +Signed-off-by: Henrique de Moraes Holschuh +Cc: Richard Purdie +Signed-off-by: Len Brown +--- + Documentation/laptops/thinkpad-acpi.txt | 47 +++++++++-- + drivers/misc/thinkpad_acpi.c | 136 ++++++++++++++++++++++++++++++- + 2 files changed, 176 insertions(+), 7 deletions(-) + +diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt +index af1f2bc..73b80a7 100644 +--- a/Documentation/laptops/thinkpad-acpi.txt ++++ b/Documentation/laptops/thinkpad-acpi.txt +@@ -876,28 +876,63 @@ The cmos command interface is prone to firmware split-brain problems, as + in newer ThinkPads it is just a compatibility layer. Do not use it, it is + exported just as a debug tool. + +-LED control -- /proc/acpi/ibm/led +---------------------------------- ++LED control ++----------- + +-Some of the LED indicators can be controlled through this feature. The +-available commands are: ++procfs: /proc/acpi/ibm/led ++sysfs attributes: as per led class, see below for names ++ ++Some of the LED indicators can be controlled through this feature. On ++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. ++ ++procfs notes: ++ ++The available commands are: + + echo ' on' >/proc/acpi/ibm/led + echo ' off' >/proc/acpi/ibm/led + echo ' blink' >/proc/acpi/ibm/led + + The range is 0 to 7. The set of LEDs that can be +-controlled varies from model to model. Here is the mapping on the X40: ++controlled varies from model to model. Here is the common ThinkPad ++mapping: + + 0 - power + 1 - battery (orange) + 2 - battery (green) +- 3 - UltraBase ++ 3 - UltraBase/dock + 4 - UltraBay ++ 5 - UltraBase battery slot ++ 6 - (unknown) + 7 - standby + + All of the above can be turned on and off and can be made to blink. + ++sysfs notes: ++ ++The ThinkPad LED sysfs interface is described in detail by the led class ++documentation, in Documentation/leds-class.txt. ++ ++The leds are named (in LED ID order, from 0 to 7): ++"tpacpi::power", "tpacpi:orange:batt", "tpacpi:green:batt", ++"tpacpi::dock_active", "tpacpi::bay_active", "tpacpi::dock_batt", ++"tpacpi::unknown_led", "tpacpi::standby". ++ ++Due to limitations in the sysfs led class, if the status of the LED ++indicators cannot be read due to an error, thinkpad-acpi will report it as ++a brightness of zero (same as LED off). ++ ++If the thinkpad firmware doesn't support reading the current status, ++trying to read the current LED brightness will just return whatever ++brightness was last written to that attribute. ++ ++These LEDs can blink using hardware acceleration. To request that a ++ThinkPad indicator LED should blink in hardware accelerated mode, use the ++"timer" trigger, and leave the delay_on and delay_off parameters set to ++zero (to request hardware acceleration autodetection). ++ + ACPI sounds -- /proc/acpi/ibm/beep + ---------------------------------- + +diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c +index 38a119b..2ab3633 100644 +--- a/drivers/misc/thinkpad_acpi.c ++++ b/drivers/misc/thinkpad_acpi.c +@@ -277,6 +277,7 @@ struct tpacpi_led_classdev { + struct led_classdev led_classdev; + struct work_struct work; + enum led_brightness new_brightness; ++ unsigned int led; + }; + + /**************************************************************************** +@@ -3814,20 +3815,38 @@ TPACPI_HANDLE(led, ec, "SLED", /* 570 */ + "LED", /* all others */ + ); /* R30, R31 */ + ++#define TPACPI_LED_NUMLEDS 8 ++static struct tpacpi_led_classdev *tpacpi_leds; ++static enum led_status_t tpacpi_led_state_cache[TPACPI_LED_NUMLEDS]; ++static const char const *tpacpi_led_names[TPACPI_LED_NUMLEDS] = { ++ /* there's a limit of 19 chars + NULL before 2.6.26 */ ++ "tpacpi::power", ++ "tpacpi:orange:batt", ++ "tpacpi:green:batt", ++ "tpacpi::dock_active", ++ "tpacpi::bay_active", ++ "tpacpi::dock_batt", ++ "tpacpi::unknown_led", ++ "tpacpi::standby", ++}; ++ + static int led_get_status(unsigned int led) + { + int status; ++ enum led_status_t led_s; + + switch (led_supported) { + case TPACPI_LED_570: + if (!acpi_evalf(ec_handle, + &status, "GLED", "dd", 1 << led)) + return -EIO; +- return (status == 0)? ++ led_s = (status == 0)? + TPACPI_LED_OFF : + ((status == 1)? + TPACPI_LED_ON : + TPACPI_LED_BLINK); ++ tpacpi_led_state_cache[led] = led_s; ++ return led_s; + default: + return -ENXIO; + } +@@ -3874,11 +3893,96 @@ static int led_set_status(unsigned int led, enum led_status_t ledstatus) + rc = -ENXIO; + } + ++ if (!rc) ++ tpacpi_led_state_cache[led] = ledstatus; ++ + return rc; + } + ++static void led_sysfs_set_status(unsigned int led, ++ enum led_brightness brightness) ++{ ++ led_set_status(led, ++ (brightness == LED_OFF) ? ++ TPACPI_LED_OFF : ++ (tpacpi_led_state_cache[led] == TPACPI_LED_BLINK) ? ++ TPACPI_LED_BLINK : TPACPI_LED_ON); ++} ++ ++static void led_set_status_worker(struct work_struct *work) ++{ ++ struct tpacpi_led_classdev *data = ++ container_of(work, struct tpacpi_led_classdev, work); ++ ++ if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING)) ++ led_sysfs_set_status(data->led, data->new_brightness); ++} ++ ++static void led_sysfs_set(struct led_classdev *led_cdev, ++ enum led_brightness brightness) ++{ ++ struct tpacpi_led_classdev *data = container_of(led_cdev, ++ struct tpacpi_led_classdev, led_classdev); ++ ++ data->new_brightness = brightness; ++ schedule_work(&data->work); ++} ++ ++static int led_sysfs_blink_set(struct led_classdev *led_cdev, ++ unsigned long *delay_on, unsigned long *delay_off) ++{ ++ struct tpacpi_led_classdev *data = container_of(led_cdev, ++ struct tpacpi_led_classdev, led_classdev); ++ ++ /* Can we choose the flash rate? */ ++ if (*delay_on == 0 && *delay_off == 0) { ++ /* yes. set them to the hardware blink rate (1 Hz) */ ++ *delay_on = 500; /* ms */ ++ *delay_off = 500; /* ms */ ++ } else if ((*delay_on != 500) || (*delay_off != 500)) ++ return -EINVAL; ++ ++ data->new_brightness = TPACPI_LED_BLINK; ++ schedule_work(&data->work); ++ ++ return 0; ++} ++ ++static enum led_brightness led_sysfs_get(struct led_classdev *led_cdev) ++{ ++ int rc; ++ ++ struct tpacpi_led_classdev *data = container_of(led_cdev, ++ struct tpacpi_led_classdev, led_classdev); ++ ++ rc = led_get_status(data->led); ++ ++ if (rc == TPACPI_LED_OFF || rc < 0) ++ rc = LED_OFF; /* no error handling in led class :( */ ++ else ++ rc = LED_FULL; ++ ++ return rc; ++} ++ ++static void led_exit(void) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < TPACPI_LED_NUMLEDS; i++) { ++ if (tpacpi_leds[i].led_classdev.name) ++ led_classdev_unregister(&tpacpi_leds[i].led_classdev); ++ } ++ ++ kfree(tpacpi_leds); ++ tpacpi_leds = NULL; ++} ++ + static int __init led_init(struct ibm_init_struct *iibm) + { ++ unsigned int i; ++ int rc; ++ + vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n"); + + TPACPI_ACPIHANDLE_INIT(led); +@@ -3899,6 +4003,35 @@ static int __init led_init(struct ibm_init_struct *iibm) + vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n", + str_supported(led_supported), led_supported); + ++ tpacpi_leds = kzalloc(sizeof(*tpacpi_leds) * TPACPI_LED_NUMLEDS, ++ GFP_KERNEL); ++ if (!tpacpi_leds) { ++ printk(TPACPI_ERR "Out of memory for LED data\n"); ++ return -ENOMEM; ++ } ++ ++ 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; ++ } ++ } ++ + return (led_supported != TPACPI_LED_NONE)? 0 : 1; + } + +@@ -3969,6 +4102,7 @@ static struct ibm_struct led_driver_data = { + .name = "led", + .read = led_read, + .write = led_write, ++ .exit = led_exit, + }; + + /************************************************************************* +-- +1.5.4.4 + diff --git a/releases/upstream/2.6.26-rc1/0011-ACPI-thinkpad-acpi-use-uppercase-for-LED-on-user.patch b/releases/upstream/2.6.26-rc1/0011-ACPI-thinkpad-acpi-use-uppercase-for-LED-on-user.patch new file mode 100644 index 00000000000..14f0fdfff0c --- /dev/null +++ b/releases/upstream/2.6.26-rc1/0011-ACPI-thinkpad-acpi-use-uppercase-for-LED-on-user.patch @@ -0,0 +1,89 @@ +From 65807cc284dd291b024dd6e55de88feb16b4230a Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Sat, 26 Apr 2008 01:02:26 -0300 +Subject: ACPI: thinkpad-acpi: use uppercase for "LED" on user documentation + +Change all occourences of the "led" word to full uppercase in user +documentation. + +Signed-off-by: Henrique de Moraes Holschuh +Acked-by: Randy Dunlap +Signed-off-by: Len Brown +--- + Documentation/laptops/thinkpad-acpi.txt | 22 +++++++++++----------- + 1 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt +index 73b80a7..947b726 100644 +--- a/Documentation/laptops/thinkpad-acpi.txt ++++ b/Documentation/laptops/thinkpad-acpi.txt +@@ -697,7 +697,7 @@ ThinkLight control + ------------------ + + procfs: /proc/acpi/ibm/light +-sysfs attributes: as per led class, for the "tpacpi::thinklight" led ++sysfs attributes: as per LED class, for the "tpacpi::thinklight" LED + + procfs notes: + +@@ -710,11 +710,11 @@ status as "unknown". The available commands are: + + sysfs notes: + +-The ThinkLight sysfs interface is documented by the led class +-documentation, in Documentation/leds-class.txt. The ThinkLight led name ++The ThinkLight sysfs interface is documented by the LED class ++documentation, in Documentation/leds-class.txt. The ThinkLight LED name + is "tpacpi::thinklight". + +-Due to limitations in the sysfs led class, if the status of the thinklight ++Due to limitations in the sysfs LED class, if the status of the thinklight + cannot be read or if it is unknown, thinkpad-acpi will report it as "off". + It is impossible to know if the status returned through sysfs is valid. + +@@ -880,7 +880,7 @@ LED control + ----------- + + procfs: /proc/acpi/ibm/led +-sysfs attributes: as per led class, see below for names ++sysfs attributes: as per LED class, see below for names + + Some of the LED indicators can be controlled through this feature. On + some older ThinkPad models, it is possible to query the status of the +@@ -891,11 +891,11 @@ procfs notes: + + The available commands are: + +- echo ' on' >/proc/acpi/ibm/led +- echo ' off' >/proc/acpi/ibm/led +- echo ' blink' >/proc/acpi/ibm/led ++ echo ' on' >/proc/acpi/ibm/led ++ echo ' off' >/proc/acpi/ibm/led ++ echo ' blink' >/proc/acpi/ibm/led + +-The range is 0 to 7. The set of LEDs that can be ++The range is 0 to 7. The set of LEDs that can be + controlled varies from model to model. Here is the common ThinkPad + mapping: + +@@ -912,7 +912,7 @@ All of the above can be turned on and off and can be made to blink. + + sysfs notes: + +-The ThinkPad LED sysfs interface is described in detail by the led class ++The ThinkPad LED sysfs interface is described in detail by the LED class + documentation, in Documentation/leds-class.txt. + + The leds are named (in LED ID order, from 0 to 7): +@@ -920,7 +920,7 @@ The leds are named (in LED ID order, from 0 to 7): + "tpacpi::dock_active", "tpacpi::bay_active", "tpacpi::dock_batt", + "tpacpi::unknown_led", "tpacpi::standby". + +-Due to limitations in the sysfs led class, if the status of the LED ++Due to limitations in the sysfs LED class, if the status of the LED + indicators cannot be read due to an error, thinkpad-acpi will report it as + a brightness of zero (same as LED off). + +-- +1.5.4.4 + diff --git a/releases/upstream/2.6.26-rc1/0012-ACPI-thinkpad-acpi-fluff-really-minor-fix.patch b/releases/upstream/2.6.26-rc1/0012-ACPI-thinkpad-acpi-fluff-really-minor-fix.patch new file mode 100644 index 00000000000..cb028018e54 --- /dev/null +++ b/releases/upstream/2.6.26-rc1/0012-ACPI-thinkpad-acpi-fluff-really-minor-fix.patch @@ -0,0 +1,29 @@ +From 10cc92759bb5d6031d308bdde96775f74082bb44 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Sat, 26 Apr 2008 01:02:27 -0300 +Subject: ACPI: thinkpad-acpi: fluff really minor fix + +Fix a minor (nano?) thing that bothered me at exactly at the wrong time. + +Signed-off-by: Henrique de Moraes Holschuh +Signed-off-by: Len Brown +--- + drivers/misc/thinkpad_acpi.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c +index 2ab3633..f471b46 100644 +--- a/drivers/misc/thinkpad_acpi.c ++++ b/drivers/misc/thinkpad_acpi.c +@@ -3881,7 +3881,7 @@ static int led_set_status(unsigned int led, enum led_status_t ledstatus) + led * led_exp_hlbl[ledstatus]); + if (rc >= 0) + rc = ec_write(TPACPI_LED_EC_HLCL, +- led * led_exp_hlcl[ledstatus]); ++ led * led_exp_hlcl[ledstatus]); + break; + case TPACPI_LED_NEW: + /* all others */ +-- +1.5.4.4 + diff --git a/releases/upstream/2.6.26-rc1/0013-ACPI-thinkpad-acpi-use-a-private-workqueue.patch b/releases/upstream/2.6.26-rc1/0013-ACPI-thinkpad-acpi-use-a-private-workqueue.patch new file mode 100644 index 00000000000..3b3cbe90813 --- /dev/null +++ b/releases/upstream/2.6.26-rc1/0013-ACPI-thinkpad-acpi-use-a-private-workqueue.patch @@ -0,0 +1,124 @@ +From e0e3c0615abdb1c3e28356595f7be87627288d5b Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Sat, 26 Apr 2008 01:02:28 -0300 +Subject: ACPI: thinkpad-acpi: use a private workqueue + +Switch all task workers to a private thinkpad-acpi workqueue. + +This way, we don't risk causing trouble for other tasks scheduled to the +default work queue, as our workers end up needing to access the ACPI EC, +run ACPI AML code, trigger SMI traps... and none of those are exactly known +to be fast, simple operations. + +Signed-off-by: Henrique de Moraes Holschuh +Signed-off-by: Len Brown +--- + drivers/misc/thinkpad_acpi.c | 26 +++++++++++++++++++------- + 1 files changed, 19 insertions(+), 7 deletions(-) + +diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c +index f471b46..d5c08c0 100644 +--- a/drivers/misc/thinkpad_acpi.c ++++ b/drivers/misc/thinkpad_acpi.c +@@ -140,6 +140,7 @@ enum { + #define TPACPI_HWMON_DRVR_NAME TPACPI_NAME "_hwmon" + + #define TPACPI_NVRAM_KTHREAD_NAME "ktpacpi_nvramd" ++#define TPACPI_WORKQUEUE_NAME "ktpacpid" + + #define TPACPI_MAX_ACPI_ARGS 3 + +@@ -272,6 +273,8 @@ static enum { + static int experimental; + static u32 dbg_level; + ++static struct workqueue_struct *tpacpi_wq; ++ + /* Special LED class that can defer work */ + struct tpacpi_led_classdev { + struct led_classdev led_classdev; +@@ -3298,7 +3301,7 @@ static void light_sysfs_set(struct led_classdev *led_cdev, + struct tpacpi_led_classdev, + led_classdev); + data->new_brightness = brightness; +- schedule_work(&data->work); ++ queue_work(tpacpi_wq, &data->work); + } + + static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev) +@@ -3355,7 +3358,7 @@ static void light_exit(void) + { + led_classdev_unregister(&tpacpi_led_thinklight.led_classdev); + if (work_pending(&tpacpi_led_thinklight.work)) +- flush_scheduled_work(); ++ flush_workqueue(tpacpi_wq); + } + + static int light_read(char *p) +@@ -3925,7 +3928,7 @@ static void led_sysfs_set(struct led_classdev *led_cdev, + struct tpacpi_led_classdev, led_classdev); + + data->new_brightness = brightness; +- schedule_work(&data->work); ++ queue_work(tpacpi_wq, &data->work); + } + + static int led_sysfs_blink_set(struct led_classdev *led_cdev, +@@ -3943,7 +3946,7 @@ static int led_sysfs_blink_set(struct led_classdev *led_cdev, + return -EINVAL; + + data->new_brightness = TPACPI_LED_BLINK; +- schedule_work(&data->work); ++ queue_work(tpacpi_wq, &data->work); + + return 0; + } +@@ -5408,11 +5411,11 @@ static void fan_watchdog_reset(void) + if (fan_watchdog_maxinterval > 0 && + tpacpi_lifecycle != TPACPI_LIFE_EXITING) { + fan_watchdog_active = 1; +- if (!schedule_delayed_work(&fan_watchdog_task, ++ if (!queue_delayed_work(tpacpi_wq, &fan_watchdog_task, + msecs_to_jiffies(fan_watchdog_maxinterval + * 1000))) { + printk(TPACPI_ERR +- "failed to schedule the fan watchdog, " ++ "failed to queue the fan watchdog, " + "watchdog will not trigger\n"); + } + } else +@@ -5782,7 +5785,7 @@ static void fan_exit(void) + &driver_attr_fan_watchdog); + + cancel_delayed_work(&fan_watchdog_task); +- flush_scheduled_work(); ++ flush_workqueue(tpacpi_wq); + } + + static int fan_read(char *p) +@@ -6436,6 +6439,9 @@ static void thinkpad_acpi_module_exit(void) + if (proc_dir) + remove_proc_entry(TPACPI_PROC_DIR, acpi_root_dir); + ++ if (tpacpi_wq) ++ destroy_workqueue(tpacpi_wq); ++ + kfree(thinkpad_id.bios_version_str); + kfree(thinkpad_id.ec_version_str); + kfree(thinkpad_id.model_str); +@@ -6466,6 +6472,12 @@ static int __init thinkpad_acpi_module_init(void) + TPACPI_ACPIHANDLE_INIT(ecrd); + TPACPI_ACPIHANDLE_INIT(ecwr); + ++ tpacpi_wq = create_singlethread_workqueue(TPACPI_WORKQUEUE_NAME); ++ if (!tpacpi_wq) { ++ thinkpad_acpi_module_exit(); ++ return -ENOMEM; ++ } ++ + proc_dir = proc_mkdir(TPACPI_PROC_DIR, acpi_root_dir); + if (!proc_dir) { + printk(TPACPI_ERR +-- +1.5.4.4 + diff --git a/releases/upstream/2.6.26-rc1/0014-ACPI-thinkpad-acpi-bump-up-version-to-0.20.patch b/releases/upstream/2.6.26-rc1/0014-ACPI-thinkpad-acpi-bump-up-version-to-0.20.patch new file mode 100644 index 00000000000..aff4a989089 --- /dev/null +++ b/releases/upstream/2.6.26-rc1/0014-ACPI-thinkpad-acpi-bump-up-version-to-0.20.patch @@ -0,0 +1,45 @@ +From 68f12ae5d778279e13e406d3913c74c592307770 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Sat, 26 Apr 2008 01:02:30 -0300 +Subject: ACPI: thinkpad-acpi: bump up version to 0.20 + +Full LED sysfs support, and the rest of the assorted minor fixes and +enhancements are a good reason to checkpoint a new version... + +Signed-off-by: Henrique de Moraes Holschuh +Signed-off-by: Len Brown +--- + Documentation/laptops/thinkpad-acpi.txt | 4 ++-- + drivers/misc/thinkpad_acpi.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt +index 947b726..01c6c3d 100644 +--- a/Documentation/laptops/thinkpad-acpi.txt ++++ b/Documentation/laptops/thinkpad-acpi.txt +@@ -1,7 +1,7 @@ + ThinkPad ACPI Extras Driver + +- Version 0.19 +- January 06th, 2008 ++ Version 0.20 ++ April 09th, 2008 + + Borislav Deianov + Henrique de Moraes Holschuh +diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c +index d5c08c0..d29ad2e 100644 +--- a/drivers/misc/thinkpad_acpi.c ++++ b/drivers/misc/thinkpad_acpi.c +@@ -21,7 +21,7 @@ + * 02110-1301, USA. + */ + +-#define TPACPI_VERSION "0.19" ++#define TPACPI_VERSION "0.20" + #define TPACPI_SYSFS_VERSION 0x020200 + + /* +-- +1.5.4.4 + -- 2.11.4.GIT