Add patches accepted for 2.6.26-rc1
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>
Wed, 30 Apr 2008 20:39:08 +0000 (30 17:39 -0300)
committerHenrique de Moraes Holschuh <hmh@hmh.eng.br>
Wed, 30 Apr 2008 20:39:08 +0000 (30 17:39 -0300)
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
14 files changed:
releases/upstream/2.6.26-rc1/0001-thinkpad_acpi-fix-possible-NULL-pointer-dereference.patch [new file with mode: 0644]
releases/upstream/2.6.26-rc1/0002-ACPI-thinkpad-acpi-BIOS-backlight-mode-helper-v2.patch [new file with mode: 0644]
releases/upstream/2.6.26-rc1/0003-ACPI-thinkpad-acpi-warn-once-about-weird-hotkey-ma.patch [new file with mode: 0644]
releases/upstream/2.6.26-rc1/0004-ACPI-thinkpad-acpi-enhance-box-identification-outp.patch [new file with mode: 0644]
releases/upstream/2.6.26-rc1/0005-ACPI-thinkpad-acpi-rate-limit-CMOS-EC-unsynced-err.patch [new file with mode: 0644]
releases/upstream/2.6.26-rc1/0006-ACPI-thinkpad-acpi-fix-brightness-dimming-control.patch [new file with mode: 0644]
releases/upstream/2.6.26-rc1/0007-ACPI-thinkpad-acpi-claim-tpacpi-as-an-official-sho.patch [new file with mode: 0644]
releases/upstream/2.6.26-rc1/0008-ACPI-thinkpad-acpi-prepare-light-and-LED-for-sysfs.patch [new file with mode: 0644]
releases/upstream/2.6.26-rc1/0009-ACPI-thinkpad-acpi-add-sysfs-led-class-support-for.patch [new file with mode: 0644]
releases/upstream/2.6.26-rc1/0010-ACPI-thinkpad-acpi-add-sysfs-led-class-support-to.patch [new file with mode: 0644]
releases/upstream/2.6.26-rc1/0011-ACPI-thinkpad-acpi-use-uppercase-for-LED-on-user.patch [new file with mode: 0644]
releases/upstream/2.6.26-rc1/0012-ACPI-thinkpad-acpi-fluff-really-minor-fix.patch [new file with mode: 0644]
releases/upstream/2.6.26-rc1/0013-ACPI-thinkpad-acpi-use-a-private-workqueue.patch [new file with mode: 0644]
releases/upstream/2.6.26-rc1/0014-ACPI-thinkpad-acpi-bump-up-version-to-0.20.patch [new file with mode: 0644]

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 (file)
index 0000000..8e59a2d
--- /dev/null
@@ -0,0 +1,29 @@
+From 90fe17f4df2f830601ffd422b11d1f7f9a9d0355 Mon Sep 17 00:00:00 2001
+From: Cyrill Gorcunov <gorcunov@gmail.com>
+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 <gorcunov@gmail.com>
+Acked-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ 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 (file)
index 0000000..d3aeb96
--- /dev/null
@@ -0,0 +1,419 @@
+From b59727965d7f286489206c292e2788d4835a8a23 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+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 <hmh@hmh.eng.br>
+Cc: Matthew Garrett <mjg59@srcf.ucam.org>
+Cc: Thomas Renninger <trenn@suse.de>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ 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 (file)
index 0000000..fe52f1d
--- /dev/null
@@ -0,0 +1,75 @@
+From 92889022250d736e135ca92fbffd1ab0ea4780d1 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+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 <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ 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 (file)
index 0000000..a11ad7a
--- /dev/null
@@ -0,0 +1,61 @@
+From 8c74adbc692a3cb040cc69d7ca3dfd86d75860a8 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+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 <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ 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 (file)
index 0000000..9c4cf5b
--- /dev/null
@@ -0,0 +1,65 @@
+From 2d5e94d7ca315f859a0eee1366838e8ad34dd7b2 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+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 <hmh@hmh.eng.br>
+Cc: Joerg Platte <lists@naasa.net>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ 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 (file)
index 0000000..b358376
--- /dev/null
@@ -0,0 +1,174 @@
+From e11aecf1379e7c4a0293182096e38e5a336696b2 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+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 <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ 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(&current_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 (file)
index 0000000..c160de3
--- /dev/null
@@ -0,0 +1,78 @@
+From 95e57ab2cbd8b016327b23d76da8a96cbd26ac0c Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+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 <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ 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 (file)
index 0000000..b853d9a
--- /dev/null
@@ -0,0 +1,338 @@
+From 4fa6811b8ade1b7839342824939817a8fc751539 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+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 <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ 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 <linux/hwmon.h>
+ #include <linux/hwmon-sysfs.h>
+ #include <linux/input.h>
++#include <linux/leds.h>
+ #include <asm/uaccess.h>
+ #include <linux/dmi.h>
+@@ -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 (file)
index 0000000..70815d3
--- /dev/null
@@ -0,0 +1,148 @@
+From e306501d1c4ff610feaba74ac35dd13e470480e6 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+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 <hmh@hmh.eng.br>
+Cc: Richard Purdie <rpurdie@rpsys.net>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ 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 (file)
index 0000000..f2df76b
--- /dev/null
@@ -0,0 +1,285 @@
+From af116101924914a9655dfad108548d0db58c40f9 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+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 <hmh@hmh.eng.br>
+Cc: Richard Purdie <rpurdie@rpsys.net>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ 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 '<led number> on' >/proc/acpi/ibm/led
+       echo '<led number> off' >/proc/acpi/ibm/led
+       echo '<led number> blink' >/proc/acpi/ibm/led
+ The <led number> 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 (file)
index 0000000..14f0fdf
--- /dev/null
@@ -0,0 +1,89 @@
+From 65807cc284dd291b024dd6e55de88feb16b4230a Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+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 <hmh@hmh.eng.br>
+Acked-by: Randy Dunlap <randy.dunlap@oracle.com>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ 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 '<led number> on' >/proc/acpi/ibm/led
+-      echo '<led number> off' >/proc/acpi/ibm/led
+-      echo '<led number> blink' >/proc/acpi/ibm/led
++      echo '<LED number> on' >/proc/acpi/ibm/led
++      echo '<LED number> off' >/proc/acpi/ibm/led
++      echo '<LED number> blink' >/proc/acpi/ibm/led
+-The <led number> range is 0 to 7. The set of LEDs that can be
++The <LED number> 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 (file)
index 0000000..cb02801
--- /dev/null
@@ -0,0 +1,29 @@
+From 10cc92759bb5d6031d308bdde96775f74082bb44 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+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 <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ 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 (file)
index 0000000..3b3cbe9
--- /dev/null
@@ -0,0 +1,124 @@
+From e0e3c0615abdb1c3e28356595f7be87627288d5b Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+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 <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ 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 (file)
index 0000000..aff4a98
--- /dev/null
@@ -0,0 +1,45 @@
+From 68f12ae5d778279e13e406d3913c74c592307770 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+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 <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ 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 <borislav@users.sf.net>
+              Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+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
+