]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branches 'release' and 'menlo' into release
authorLen Brown <len.brown@intel.com>
Thu, 7 Feb 2008 08:18:04 +0000 (03:18 -0500)
committerLen Brown <len.brown@intel.com>
Thu, 7 Feb 2008 08:18:04 +0000 (03:18 -0500)
Conflicts:

drivers/acpi/video.c

Signed-off-by: Len Brown <len.brown@intel.com>
1  2  3 
drivers/Kconfig
drivers/Makefile
drivers/acpi/processor_core.c
drivers/acpi/thermal.c
drivers/acpi/video.c
drivers/misc/Kconfig
include/acpi/processor.h

diff --combined drivers/Kconfig
index d74d9fbb9fd21177eca9f2096d8df82fc4f2b469,d74d9fbb9fd21177eca9f2096d8df82fc4f2b469,8e238cfc079559840cea1e3dcf441e71784b73e9..b86877bdc7ac50ede83ed0e311c52e692548ef3f
@@@@ -52,14 -52,14 -52,14 +52,16 @@@@ source "drivers/i2c/Kconfig
   
   source "drivers/spi/Kconfig"
   
  +source "drivers/gpio/Kconfig"
  +
   source "drivers/w1/Kconfig"
   
   source "drivers/power/Kconfig"
   
   source "drivers/hwmon/Kconfig"
   
++ source "drivers/thermal/Kconfig"
++ 
   source "drivers/watchdog/Kconfig"
   
   source "drivers/ssb/Kconfig"
@@@@ -93,4 -93,4 -93,6 +95,4 @@@@ source "drivers/dca/Kconfig
   source "drivers/auxdisplay/Kconfig"
   
   source "drivers/uio/Kconfig"
  -
  -source "drivers/virtio/Kconfig"
   endmenu
diff --combined drivers/Makefile
index f1c11db52a57e09b30b13380b1b000923dafcf3b,f1c11db52a57e09b30b13380b1b000923dafcf3b,a516b8b19127654cc426963dbdf303bf1397be60..30ba97ec5eb525eefd89807600490c7f0dac0854
@@@@ -5,7 -5,7 -5,6 +5,7 @@@@
   # Rewritten to use lists instead of if-statements.
   #
   
  +obj-$(CONFIG_HAVE_GPIO_LIB)  += gpio/
   obj-$(CONFIG_PCI)            += pci/
   obj-$(CONFIG_PARISC)         += parisc/
   obj-$(CONFIG_RAPIDIO)                += rapidio/
@@@@ -65,6 -65,6 -64,7 +65,7 @@@@ obj-y                         += i2c
   obj-$(CONFIG_W1)             += w1/
   obj-$(CONFIG_POWER_SUPPLY)   += power/
   obj-$(CONFIG_HWMON)          += hwmon/
++ obj-$(CONFIG_THERMAL)                += thermal/
   obj-$(CONFIG_WATCHDOG)               += watchdog/
   obj-$(CONFIG_PHONE)          += telephony/
   obj-$(CONFIG_MD)             += md/
index c53113e18004387be25282decb7c10bf23b3579c,c53113e18004387be25282decb7c10bf23b3579c,5668c5e8ae1929a3acfb329cd704f85a3be8a956..315fd8f7e8a125e88053b8d3a2b61197a1464255
@@@@ -668,6 -668,6 -668,24 +668,24 @@@@ static int __cpuinit acpi_processor_sta
   
        acpi_processor_power_init(pr, device);
   
++      pr->cdev = thermal_cooling_device_register("Processor", device,
++                                              &processor_cooling_ops);
++      if (pr->cdev)
++              printk(KERN_INFO PREFIX
++                      "%s is registered as cooling_device%d\n",
++                      device->dev.bus_id, pr->cdev->id);
++      else
++              goto end;
++ 
++      result = sysfs_create_link(&device->dev.kobj, &pr->cdev->device.kobj,
++                                      "thermal_cooling");
++      if (result)
++              return result;
++      result = sysfs_create_link(&pr->cdev->device.kobj, &device->dev.kobj,
++                                      "device");
++      if (result)
++              return result;
++ 
        if (pr->flags.throttling) {
                printk(KERN_INFO PREFIX "%s [%s] (supports",
                       acpi_device_name(device), acpi_device_bid(device));
@@@@ -791,6 -791,6 -809,11 +809,11 @@@@ static int acpi_processor_remove(struc
   
        acpi_processor_remove_fs(device);
   
++      sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
++      sysfs_remove_link(&pr->cdev->device.kobj, "device");
++      thermal_cooling_device_unregister(pr->cdev);
++      pr->cdev = NULL;
++ 
        processors[pr->id] = NULL;
   
        kfree(pr);
@@@@ -812,18 -812,18 -835,11 +835,18 @@@@ static int is_processor_present(acpi_ha
   
   
        status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
  -     if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT)) {
  -             ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present"));
  -             return 0;
  -     }
  -     return 1;
  +     /*
  +      * if a processor object does not have an _STA object,
  +      * OSPM assumes that the processor is present.
  +      */
  +     if (status == AE_NOT_FOUND)
  +             return 1;
  +
  +     if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT))
  +             return 1;
  +
  +     ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present"));
  +     return 0;
   }
   
   static
diff --combined drivers/acpi/thermal.c
index 3a0af9a8cd2712a208bd67e347d532a3059d0f71,3a0af9a8cd2712a208bd67e347d532a3059d0f71,73f276bc6e4f5a49e735b9bd08a50fb4fcbdf83c..8d4b79b4f933c631281e23ce8b602e3bcbbf3d9f
   #include <linux/seq_file.h>
   #include <linux/reboot.h>
   #include <asm/uaccess.h>
-- 
++ #include <linux/thermal.h>
   #include <acpi/acpi_bus.h>
   #include <acpi/acpi_drivers.h>
   
   #define ACPI_THERMAL_MAX_ACTIVE      10
   #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
   
-- #define KELVIN_TO_CELSIUS(t)    (long)(((long)t-2732>=0) ? ((long)t-2732+5)/10 : ((long)t-2732-5)/10)
-- #define CELSIUS_TO_KELVIN(t) ((t+273)*10)
-- 
   #define _COMPONENT           ACPI_THERMAL_COMPONENT
   ACPI_MODULE_NAME("thermal");
   
@@@@ -195,6 -195,6 -192,8 +192,8 @@@@ struct acpi_thermal 
        struct acpi_thermal_trips trips;
        struct acpi_handle_list devices;
        struct timer_list timer;
++      struct thermal_zone_device *thermal_zone;
++      int tz_enabled;
        struct mutex lock;
   };
   
@@@@ -321,178 -321,178 -320,226 +320,226 @@@@ static int acpi_thermal_set_cooling_mod
        return 0;
   }
   
-- static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
-- {
--      acpi_status status = AE_OK;
--      int i = 0;
++ #define ACPI_TRIPS_CRITICAL  0x01
++ #define ACPI_TRIPS_HOT               0x02
++ #define ACPI_TRIPS_PASSIVE   0x04
++ #define ACPI_TRIPS_ACTIVE    0x08
++ #define ACPI_TRIPS_DEVICES   0x10
   
++ #define ACPI_TRIPS_REFRESH_THRESHOLDS        (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE)
++ #define ACPI_TRIPS_REFRESH_DEVICES   ACPI_TRIPS_DEVICES
   
--      if (!tz)
--              return -EINVAL;
++ #define ACPI_TRIPS_INIT      (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT | \
++                            ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE |  \
++                            ACPI_TRIPS_DEVICES)
   
--      /* Critical Shutdown (required) */
-- 
--      status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL,
--                                     &tz->trips.critical.temperature);
--      if (ACPI_FAILURE(status)) {
--              tz->trips.critical.flags.valid = 0;
--              ACPI_EXCEPTION((AE_INFO, status, "No critical threshold"));
--              return -ENODEV;
--      } else {
--              tz->trips.critical.flags.valid = 1;
--              ACPI_DEBUG_PRINT((ACPI_DB_INFO,
--                                "Found critical threshold [%lu]\n",
--                                tz->trips.critical.temperature));
--      }
++ /*
++  * This exception is thrown out in two cases:
++  * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid
++  *   when re-evaluating the AML code.
++  * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change.
++  *   We need to re-bind the cooling devices of a thermal zone when this occurs.
++  */
++ #define ACPI_THERMAL_TRIPS_EXCEPTION(flags, str)     \
++ do { \
++      if (flags != ACPI_TRIPS_INIT)   \
++              ACPI_EXCEPTION((AE_INFO, AE_ERROR,      \
++              "ACPI thermal trip point %s changed\n"  \
++              "Please send acpidump to linux-acpi@vger.kernel.org\n", str)); \
++ } while (0)
++ 
++ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
++ {
++      acpi_status status = AE_OK;
++      struct acpi_handle_list devices;
++      int valid = 0;
++      int i;
   
--      if (tz->trips.critical.flags.valid == 1) {
--              if (crt == -1) {
++      /* Critical Shutdown (required) */
++      if (flag & ACPI_TRIPS_CRITICAL) {
++              status = acpi_evaluate_integer(tz->device->handle,
++                              "_CRT", NULL, &tz->trips.critical.temperature);
++              if (ACPI_FAILURE(status)) {
                        tz->trips.critical.flags.valid = 0;
--              } else if (crt > 0) {
--                      unsigned long crt_k = CELSIUS_TO_KELVIN(crt);
-- 
--                      /*
--                       * Allow override to lower critical threshold
--                       */
--                      if (crt_k < tz->trips.critical.temperature)
--                              tz->trips.critical.temperature = crt_k;
++                      ACPI_EXCEPTION((AE_INFO, status,
++                                      "No critical threshold"));
++                      return -ENODEV;
++              } else {
++                      tz->trips.critical.flags.valid = 1;
++                      ACPI_DEBUG_PRINT((ACPI_DB_INFO,
++                                      "Found critical threshold [%lu]\n",
++                                      tz->trips.critical.temperature));
++              }
++              if (tz->trips.critical.flags.valid == 1) {
++                      if (crt == -1) {
++                              tz->trips.critical.flags.valid = 0;
++                      } else if (crt > 0) {
++                              unsigned long crt_k = CELSIUS_TO_KELVIN(crt);
++                              /*
++                               * Allow override to lower critical threshold
++                               */
++                              if (crt_k < tz->trips.critical.temperature)
++                                      tz->trips.critical.temperature = crt_k;
++                      }
                }
        }
   
        /* Critical Sleep (optional) */
-- 
--      status =
--          acpi_evaluate_integer(tz->device->handle, "_HOT", NULL,
--                                &tz->trips.hot.temperature);
--      if (ACPI_FAILURE(status)) {
--              tz->trips.hot.flags.valid = 0;
--              ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No hot threshold\n"));
--      } else {
--              tz->trips.hot.flags.valid = 1;
--              ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%lu]\n",
--                                tz->trips.hot.temperature));
--      }
-- 
--      /* Passive: Processors (optional) */
-- 
--      if (psv == -1) {
--              status = AE_SUPPORT;
--      } else if (psv > 0) {
--              tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv);
--              status = AE_OK;
--      } else {
++      if (flag & ACPI_TRIPS_HOT) {
                status = acpi_evaluate_integer(tz->device->handle,
--                      "_PSV", NULL, &tz->trips.passive.temperature);
++                              "_HOT", NULL, &tz->trips.hot.temperature);
++              if (ACPI_FAILURE(status)) {
++                      tz->trips.hot.flags.valid = 0;
++                      ACPI_DEBUG_PRINT((ACPI_DB_INFO,
++                                      "No hot threshold\n"));
++              } else {
++                      tz->trips.hot.flags.valid = 1;
++                      ACPI_DEBUG_PRINT((ACPI_DB_INFO,
++                                      "Found hot threshold [%lu]\n",
++                                      tz->trips.critical.temperature));
++              }
        }
   
--      if (ACPI_FAILURE(status)) {
--              tz->trips.passive.flags.valid = 0;
--              ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n"));
--      } else {
--              tz->trips.passive.flags.valid = 1;
-- 
--              status =
--                  acpi_evaluate_integer(tz->device->handle, "_TC1", NULL,
--                                        &tz->trips.passive.tc1);
--              if (ACPI_FAILURE(status))
--                      tz->trips.passive.flags.valid = 0;
-- 
--              status =
--                  acpi_evaluate_integer(tz->device->handle, "_TC2", NULL,
--                                        &tz->trips.passive.tc2);
--              if (ACPI_FAILURE(status))
--                      tz->trips.passive.flags.valid = 0;
++      /* Passive (optional) */
++      if (flag & ACPI_TRIPS_PASSIVE) {
++              valid = tz->trips.passive.flags.valid;
++              if (psv == -1) {
++                      status = AE_SUPPORT;
++              } else if (psv > 0) {
++                      tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv);
++                      status = AE_OK;
++              } else {
++                      status = acpi_evaluate_integer(tz->device->handle,
++                              "_PSV", NULL, &tz->trips.passive.temperature);
++              }
   
--              status =
--                  acpi_evaluate_integer(tz->device->handle, "_TSP", NULL,
--                                        &tz->trips.passive.tsp);
                if (ACPI_FAILURE(status))
                        tz->trips.passive.flags.valid = 0;
-- 
--              status =
--                  acpi_evaluate_reference(tz->device->handle, "_PSL", NULL,
--                                          &tz->trips.passive.devices);
++              else {
++                      tz->trips.passive.flags.valid = 1;
++                      if (flag == ACPI_TRIPS_INIT) {
++                              status = acpi_evaluate_integer(
++                                              tz->device->handle, "_TC1",
++                                              NULL, &tz->trips.passive.tc1);
++                              if (ACPI_FAILURE(status))
++                                      tz->trips.passive.flags.valid = 0;
++                              status = acpi_evaluate_integer(
++                                              tz->device->handle, "_TC2",
++                                              NULL, &tz->trips.passive.tc2);
++                              if (ACPI_FAILURE(status))
++                                      tz->trips.passive.flags.valid = 0;
++                              status = acpi_evaluate_integer(
++                                              tz->device->handle, "_TSP",
++                                              NULL, &tz->trips.passive.tsp);
++                              if (ACPI_FAILURE(status))
++                                      tz->trips.passive.flags.valid = 0;
++                      }
++              }
++      }
++      if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.flags.valid) {
++              memset(&devices, 0, sizeof(struct acpi_handle_list));
++              status = acpi_evaluate_reference(tz->device->handle, "_PSL",
++                                                      NULL, &devices);
                if (ACPI_FAILURE(status))
                        tz->trips.passive.flags.valid = 0;
-- 
--              if (!tz->trips.passive.flags.valid)
--                      printk(KERN_WARNING PREFIX "Invalid passive threshold\n");
                else
--                      ACPI_DEBUG_PRINT((ACPI_DB_INFO,
--                                        "Found passive threshold [%lu]\n",
--                                        tz->trips.passive.temperature));
--      }
++                      tz->trips.passive.flags.valid = 1;
   
--      /* Active: Fans, etc. (optional) */
++              if (memcmp(&tz->trips.passive.devices, &devices,
++                              sizeof(struct acpi_handle_list))) {
++                      memcpy(&tz->trips.passive.devices, &devices,
++                              sizeof(struct acpi_handle_list));
++                      ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
++              }
++      }
++      if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) {
++              if (valid != tz->trips.passive.flags.valid)
++                              ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
++      }
   
++      /* Active (optional) */
        for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
-- 
                char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
++              valid = tz->trips.active[i].flags.valid;
   
                if (act == -1)
--                      break;  /* disable all active trip points */
-- 
--              status = acpi_evaluate_integer(tz->device->handle,
--                      name, NULL, &tz->trips.active[i].temperature);
-- 
--              if (ACPI_FAILURE(status)) {
--                      if (i == 0)     /* no active trip points */
--                              break;
--                      if (act <= 0)   /* no override requested */
++                      break; /* disable all active trip points */
++ 
++              if (flag & ACPI_TRIPS_ACTIVE) {
++                      status = acpi_evaluate_integer(tz->device->handle,
++                              name, NULL, &tz->trips.active[i].temperature);
++                      if (ACPI_FAILURE(status)) {
++                              tz->trips.active[i].flags.valid = 0;
++                              if (i == 0)
++                                      break;
++                              if (act <= 0)
++                                      break;
++                              if (i == 1)
++                                      tz->trips.active[0].temperature =
++                                              CELSIUS_TO_KELVIN(act);
++                              else
++                                      /*
++                                       * Don't allow override higher than
++                                       * the next higher trip point
++                                       */
++                                      tz->trips.active[i - 1].temperature =
++                                              (tz->trips.active[i - 2].temperature <
++                                              CELSIUS_TO_KELVIN(act) ?
++                                              tz->trips.active[i - 2].temperature :
++                                              CELSIUS_TO_KELVIN(act));
                                break;
--                      if (i == 1) {   /* 1 trip point */
--                              tz->trips.active[0].temperature =
--                                      CELSIUS_TO_KELVIN(act);
--                      } else {        /* multiple trips */
--                              /*
--                               * Don't allow override higher than
--                               * the next higher trip point
--                               */
--                              tz->trips.active[i - 1].temperature =
--                                  (tz->trips.active[i - 2].temperature <
--                                      CELSIUS_TO_KELVIN(act) ?
--                                      tz->trips.active[i - 2].temperature :
--                                      CELSIUS_TO_KELVIN(act));
--                      }
--                      break;
++                      } else
++                              tz->trips.active[i].flags.valid = 1;
                }
   
                name[2] = 'L';
--              status =
--                  acpi_evaluate_reference(tz->device->handle, name, NULL,
--                                          &tz->trips.active[i].devices);
--              if (ACPI_SUCCESS(status)) {
--                      tz->trips.active[i].flags.valid = 1;
--                      ACPI_DEBUG_PRINT((ACPI_DB_INFO,
--                                        "Found active threshold [%d]:[%lu]\n",
--                                        i, tz->trips.active[i].temperature));
--              } else
--                      ACPI_EXCEPTION((AE_INFO, status,
--                                      "Invalid active threshold [%d]", i));
++              if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].flags.valid ) {
++                      memset(&devices, 0, sizeof(struct acpi_handle_list));
++                      status = acpi_evaluate_reference(tz->device->handle,
++                                              name, NULL, &devices);
++                      if (ACPI_FAILURE(status))
++                              tz->trips.active[i].flags.valid = 0;
++                      else
++                              tz->trips.active[i].flags.valid = 1;
++ 
++                      if (memcmp(&tz->trips.active[i].devices, &devices,
++                                      sizeof(struct acpi_handle_list))) {
++                              memcpy(&tz->trips.active[i].devices, &devices,
++                                      sizeof(struct acpi_handle_list));
++                              ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
++                      }
++              }
++              if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES))
++                      if (valid != tz->trips.active[i].flags.valid)
++                              ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
++ 
++              if (!tz->trips.active[i].flags.valid)
++                      break;
++      }
++ 
++      if (flag & ACPI_TRIPS_DEVICES) {
++              memset(&devices, 0, sizeof(struct acpi_handle_list));
++              status = acpi_evaluate_reference(tz->device->handle, "_TZD",
++                                              NULL, &devices);
++              if (memcmp(&tz->devices, &devices,
++                              sizeof(struct acpi_handle_list))) {
++                      memcpy(&tz->devices, &devices,
++                              sizeof(struct acpi_handle_list));
++                      ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
++              }
        }
   
        return 0;
   }
   
-- static int acpi_thermal_get_devices(struct acpi_thermal *tz)
++ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
   {
--      acpi_status status = AE_OK;
-- 
-- 
--      if (!tz)
--              return -EINVAL;
-- 
--      status =
--          acpi_evaluate_reference(tz->device->handle, "_TZD", NULL, &tz->devices);
--      if (ACPI_FAILURE(status))
--              return -ENODEV;
-- 
--      return 0;
++      return acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
   }
   
   static int acpi_thermal_critical(struct acpi_thermal *tz)
   {
  -     if (!tz || !tz->trips.critical.flags.valid || nocrt)
  +     if (!tz || !tz->trips.critical.flags.valid)
                return -EINVAL;
   
        if (tz->temperature >= tz->trips.critical.temperature) {
        } else if (tz->trips.critical.flags.enabled)
                tz->trips.critical.flags.enabled = 0;
   
  -     printk(KERN_EMERG
  -            "Critical temperature reached (%ld C), shutting down.\n",
  -            KELVIN_TO_CELSIUS(tz->temperature));
        acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL,
                                tz->trips.critical.flags.enabled);
        acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
                                          ACPI_THERMAL_NOTIFY_CRITICAL,
                                          tz->trips.critical.flags.enabled);
   
  -     orderly_poweroff(true);
  +     /* take no action if nocrt is set */
  +     if(!nocrt) {
  +             printk(KERN_EMERG
  +                     "Critical temperature reached (%ld C), shutting down.\n",
  +                     KELVIN_TO_CELSIUS(tz->temperature));
  +             orderly_poweroff(true);
  +     }
   
        return 0;
   }
   
   static int acpi_thermal_hot(struct acpi_thermal *tz)
   {
  -     if (!tz || !tz->trips.hot.flags.valid || nocrt)
  +     if (!tz || !tz->trips.hot.flags.valid)
                return -EINVAL;
   
        if (tz->temperature >= tz->trips.hot.temperature) {
                                          ACPI_THERMAL_NOTIFY_HOT,
                                          tz->trips.hot.flags.enabled);
   
  -     /* TBD: Call user-mode "sleep(S4)" function */
  +     /* TBD: Call user-mode "sleep(S4)" function if nocrt is cleared */
   
        return 0;
   }
@@@@ -735,6 -735,6 -779,9 +782,9 @@@@ static void acpi_thermal_check(void *da
        if (result)
                goto unlock;
   
++      if (!tz->tz_enabled)
++              goto unlock;
++ 
        memset(&tz->state, 0, sizeof(tz->state));
   
        /*
        mutex_unlock(&tz->lock);
   }
   
++ /* sys I/F for generic thermal sysfs support */
++ static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf)
++ {
++      struct acpi_thermal *tz = thermal->devdata;
++ 
++      if (!tz)
++              return -EINVAL;
++ 
++      return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(tz->temperature));
++ }
++ 
++ static const char enabled[] = "kernel";
++ static const char disabled[] = "user";
++ static int thermal_get_mode(struct thermal_zone_device *thermal,
++                              char *buf)
++ {
++      struct acpi_thermal *tz = thermal->devdata;
++ 
++      if (!tz)
++              return -EINVAL;
++ 
++      return sprintf(buf, "%s\n", tz->tz_enabled ?
++                      enabled : disabled);
++ }
++ 
++ static int thermal_set_mode(struct thermal_zone_device *thermal,
++                              const char *buf)
++ {
++      struct acpi_thermal *tz = thermal->devdata;
++      int enable;
++ 
++      if (!tz)
++              return -EINVAL;
++ 
++      /*
++       * enable/disable thermal management from ACPI thermal driver
++       */
++      if (!strncmp(buf, enabled, sizeof enabled - 1))
++              enable = 1;
++      else if (!strncmp(buf, disabled, sizeof disabled - 1))
++              enable = 0;
++      else
++              return -EINVAL;
++ 
++      if (enable != tz->tz_enabled) {
++              tz->tz_enabled = enable;
++              ACPI_DEBUG_PRINT((ACPI_DB_INFO,
++                      "%s ACPI thermal control\n",
++                      tz->tz_enabled ? enabled : disabled));
++              acpi_thermal_check(tz);
++      }
++      return 0;
++ }
++ 
++ static int thermal_get_trip_type(struct thermal_zone_device *thermal,
++                               int trip, char *buf)
++ {
++      struct acpi_thermal *tz = thermal->devdata;
++      int i;
++ 
++      if (!tz || trip < 0)
++              return -EINVAL;
++ 
++      if (tz->trips.critical.flags.valid) {
++              if (!trip)
++                      return sprintf(buf, "critical\n");
++              trip--;
++      }
++ 
++      if (tz->trips.hot.flags.valid) {
++              if (!trip)
++                      return sprintf(buf, "hot\n");
++              trip--;
++      }
++ 
++      if (tz->trips.passive.flags.valid) {
++              if (!trip)
++                      return sprintf(buf, "passive\n");
++              trip--;
++      }
++ 
++      for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
++              tz->trips.active[i].flags.valid; i++) {
++              if (!trip)
++                      return sprintf(buf, "active%d\n", i);
++              trip--;
++      }
++ 
++      return -EINVAL;
++ }
++ 
++ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
++                               int trip, char *buf)
++ {
++      struct acpi_thermal *tz = thermal->devdata;
++      int i;
++ 
++      if (!tz || trip < 0)
++              return -EINVAL;
++ 
++      if (tz->trips.critical.flags.valid) {
++              if (!trip)
++                      return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
++                              tz->trips.critical.temperature));
++              trip--;
++      }
++ 
++      if (tz->trips.hot.flags.valid) {
++              if (!trip)
++                      return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
++                                      tz->trips.hot.temperature));
++              trip--;
++      }
++ 
++      if (tz->trips.passive.flags.valid) {
++              if (!trip)
++                      return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
++                                      tz->trips.passive.temperature));
++              trip--;
++      }
++ 
++      for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
++              tz->trips.active[i].flags.valid; i++) {
++              if (!trip)
++                      return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
++                                      tz->trips.active[i].temperature));
++              trip--;
++      }
++ 
++      return -EINVAL;
++ }
++ 
++ typedef int (*cb)(struct thermal_zone_device *, int,
++                struct thermal_cooling_device *);
++ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
++                                      struct thermal_cooling_device *cdev,
++                                      cb action)
++ {
++      struct acpi_device *device = cdev->devdata;
++      struct acpi_thermal *tz = thermal->devdata;
++      struct acpi_device *dev;
++      acpi_status status;
++      acpi_handle handle;
++      int i;
++      int j;
++      int trip = -1;
++      int result = 0;
++ 
++      if (tz->trips.critical.flags.valid)
++              trip++;
++ 
++      if (tz->trips.hot.flags.valid)
++              trip++;
++ 
++      if (tz->trips.passive.flags.valid) {
++              trip++;
++              for (i = 0; i < tz->trips.passive.devices.count;
++                  i++) {
++                      handle = tz->trips.passive.devices.handles[i];
++                      status = acpi_bus_get_device(handle, &dev);
++                      if (ACPI_SUCCESS(status) && (dev == device)) {
++                              result = action(thermal, trip, cdev);
++                              if (result)
++                                      goto failed;
++                      }
++              }
++      }
++ 
++      for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
++              if (!tz->trips.active[i].flags.valid)
++                      break;
++              trip++;
++              for (j = 0;
++                  j < tz->trips.active[i].devices.count;
++                  j++) {
++                      handle = tz->trips.active[i].devices.handles[j];
++                      status = acpi_bus_get_device(handle, &dev);
++                      if (ACPI_SUCCESS(status) && (dev == device)) {
++                              result = action(thermal, trip, cdev);
++                              if (result)
++                                      goto failed;
++                      }
++              }
++      }
++ 
++      for (i = 0; i < tz->devices.count; i++) {
++              handle = tz->devices.handles[i];
++              status = acpi_bus_get_device(handle, &dev);
++              if (ACPI_SUCCESS(status) && (dev == device)) {
++                      result = action(thermal, -1, cdev);
++                      if (result)
++                              goto failed;
++              }
++      }
++ 
++ failed:
++      return result;
++ }
++ 
++ static int
++ acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal,
++                                      struct thermal_cooling_device *cdev)
++ {
++      return acpi_thermal_cooling_device_cb(thermal, cdev,
++                              thermal_zone_bind_cooling_device);
++ }
++ 
++ static int
++ acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
++                                      struct thermal_cooling_device *cdev)
++ {
++      return acpi_thermal_cooling_device_cb(thermal, cdev,
++                              thermal_zone_unbind_cooling_device);
++ }
++ 
++ static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
++      .bind = acpi_thermal_bind_cooling_device,
++      .unbind = acpi_thermal_unbind_cooling_device,
++      .get_temp = thermal_get_temp,
++      .get_mode = thermal_get_mode,
++      .set_mode = thermal_set_mode,
++      .get_trip_type = thermal_get_trip_type,
++      .get_trip_temp = thermal_get_trip_temp,
++ };
++ 
++ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
++ {
++      int trips = 0;
++      int result;
++      acpi_status status;
++      int i;
++ 
++      if (tz->trips.critical.flags.valid)
++              trips++;
++ 
++      if (tz->trips.hot.flags.valid)
++              trips++;
++ 
++      if (tz->trips.passive.flags.valid)
++              trips++;
++ 
++      for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
++                      tz->trips.active[i].flags.valid; i++, trips++);
++      tz->thermal_zone = thermal_zone_device_register("ACPI thermal zone",
++                                      trips, tz, &acpi_thermal_zone_ops);
++      if (!tz->thermal_zone)
++              return -ENODEV;
++ 
++      result = sysfs_create_link(&tz->device->dev.kobj,
++                                 &tz->thermal_zone->device.kobj, "thermal_zone");
++      if (result)
++              return result;
++ 
++      result = sysfs_create_link(&tz->thermal_zone->device.kobj,
++                                 &tz->device->dev.kobj, "device");
++      if (result)
++              return result;
++ 
++      status = acpi_attach_data(tz->device->handle,
++                                acpi_bus_private_data_handler,
++                                tz->thermal_zone);
++      if (ACPI_FAILURE(status)) {
++              ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
++                              "Error attaching device data\n"));
++              return -ENODEV;
++      }
++ 
++      tz->tz_enabled = 1;
++ 
++      printk(KERN_INFO PREFIX "%s is registered as thermal_zone%d\n",
++                      tz->device->dev.bus_id, tz->thermal_zone->id);
++      return 0;
++ }
++ 
++ static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
++ {
++      sysfs_remove_link(&tz->device->dev.kobj, "thermal_zone");
++      sysfs_remove_link(&tz->thermal_zone->device.kobj, "device");
++      thermal_zone_device_unregister(tz->thermal_zone);
++      tz->thermal_zone = NULL;
++      acpi_detach_data(tz->device->handle, acpi_bus_private_data_handler);
++ }
++ 
++ 
   /* --------------------------------------------------------------------------
                                 FS Interface (/proc)
      -------------------------------------------------------------------------- */
@@@@ -1184,15 -1184,15 -1515,15 +1518,15 @@@@ static void acpi_thermal_notify(acpi_ha
                acpi_thermal_check(tz);
                break;
        case ACPI_THERMAL_NOTIFY_THRESHOLDS:
--              acpi_thermal_get_trip_points(tz);
++              acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS);
                acpi_thermal_check(tz);
                acpi_bus_generate_proc_event(device, event, 0);
                acpi_bus_generate_netlink_event(device->pnp.device_class,
                                                  device->dev.bus_id, event, 0);
                break;
        case ACPI_THERMAL_NOTIFY_DEVICES:
--              if (tz->flags.devices)
--                      acpi_thermal_get_devices(tz);
++              acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES);
++              acpi_thermal_check(tz);
                acpi_bus_generate_proc_event(device, event, 0);
                acpi_bus_generate_netlink_event(device->pnp.device_class,
                                                  device->dev.bus_id, event, 0);
@@@@ -1235,11 -1235,11 -1566,6 +1569,6 @@@@ static int acpi_thermal_get_info(struc
        else
                acpi_thermal_get_polling_frequency(tz);
   
--      /* Get devices in this thermal zone [_TZD] (optional) */
--      result = acpi_thermal_get_devices(tz);
--      if (!result)
--              tz->flags.devices = 1;
-- 
        return 0;
   }
   
@@@@ -1263,13 -1263,13 -1589,19 +1592,19 @@@@ static int acpi_thermal_add(struct acpi
        strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
        acpi_driver_data(device) = tz;
        mutex_init(&tz->lock);
++ 
++ 
        result = acpi_thermal_get_info(tz);
        if (result)
--              goto end;
++              goto free_memory;
++ 
++      result = acpi_thermal_register_thermal_zone(tz);
++      if (result)
++              goto free_memory;
   
        result = acpi_thermal_add_fs(device);
        if (result)
--              goto end;
++              goto unregister_thermal_zone;
   
        init_timer(&tz->timer);
   
                                             acpi_thermal_notify, tz);
        if (ACPI_FAILURE(status)) {
                result = -ENODEV;
--              goto end;
++              goto remove_fs;
        }
   
        printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
               acpi_device_name(device), acpi_device_bid(device),
               KELVIN_TO_CELSIUS(tz->temperature));
++      goto end;
   
--       end:
--      if (result) {
--              acpi_thermal_remove_fs(device);
--              kfree(tz);
--      }
-- 
++ remove_fs:
++      acpi_thermal_remove_fs(device);
++ unregister_thermal_zone:
++      thermal_zone_device_unregister(tz->thermal_zone);
++ free_memory:
++      kfree(tz);
++ end:
        return result;
   }
   
@@@@ -1332,6 -1332,6 -1666,7 +1669,7 @@@@ static int acpi_thermal_remove(struct a
        }
   
        acpi_thermal_remove_fs(device);
++      acpi_thermal_unregister_thermal_zone(tz);
        mutex_destroy(&tz->lock);
        kfree(tz);
        return 0;
diff --combined drivers/acpi/video.c
index a54ff6bce8fa3865cc2e78f7bc0ae2ffd0e6e0c3,a54ff6bce8fa3865cc2e78f7bc0ae2ffd0e6e0c3,eab9c4213b49625a800c42b581b0e6931cb9c39a..82815cff15a9085efcfac1c98cf654623f174f89
   #include <linux/seq_file.h>
   #include <linux/input.h>
   #include <linux/backlight.h>
++ #include <linux/thermal.h>
   #include <linux/video_output.h>
   #include <asm/uaccess.h>
   
@@@@ -179,6 -179,6 -180,7 +180,7 @@@@ struct acpi_video_device 
        struct acpi_device *dev;
        struct acpi_video_device_brightness *brightness;
        struct backlight_device *backlight;
++      struct thermal_cooling_device *cdev;
        struct output_device *output_dev;
   };
   
@@@@ -292,26 -292,26 -294,18 +294,26 @@@@ static int acpi_video_device_set_state(
   static int acpi_video_get_brightness(struct backlight_device *bd)
   {
        unsigned long cur_level;
  +     int i;
        struct acpi_video_device *vd =
                (struct acpi_video_device *)bl_get_data(bd);
        acpi_video_device_lcd_get_level_current(vd, &cur_level);
  -     return (int) cur_level;
  +     for (i = 2; i < vd->brightness->count; i++) {
  +             if (vd->brightness->levels[i] == cur_level)
  +                     /* The first two entries are special - see page 575
  +                        of the ACPI spec 3.0 */
  +                     return i-2;
  +     }
  +     return 0;
   }
   
   static int acpi_video_set_brightness(struct backlight_device *bd)
   {
  -     int request_level = bd->props.brightness;
  +     int request_level = bd->props.brightness+2;
        struct acpi_video_device *vd =
                (struct acpi_video_device *)bl_get_data(bd);
  -     acpi_video_device_lcd_set_level(vd, request_level);
  +     acpi_video_device_lcd_set_level(vd,
  +                                     vd->brightness->levels[request_level]);
        return 0;
   }
   
@@@@ -342,6 -342,6 -336,54 +344,54 @@@@ static struct output_properties acpi_ou
        .set_state = acpi_video_output_set,
        .get_status = acpi_video_output_get,
   };
++ 
++ 
++ /* thermal cooling device callbacks */
++ static int video_get_max_state(struct thermal_cooling_device *cdev, char *buf)
++ {
++      struct acpi_device *device = cdev->devdata;
++      struct acpi_video_device *video = acpi_driver_data(device);
++ 
++      return sprintf(buf, "%d\n", video->brightness->count - 3);
++ }
++ 
++ static int video_get_cur_state(struct thermal_cooling_device *cdev, char *buf)
++ {
++      struct acpi_device *device = cdev->devdata;
++      struct acpi_video_device *video = acpi_driver_data(device);
++      unsigned long level;
++      int state;
++ 
++      acpi_video_device_lcd_get_level_current(video, &level);
++      for (state = 2; state < video->brightness->count; state++)
++              if (level == video->brightness->levels[state])
++                      return sprintf(buf, "%d\n",
++                                     video->brightness->count - state - 1);
++ 
++      return -EINVAL;
++ }
++ 
++ static int
++ video_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state)
++ {
++      struct acpi_device *device = cdev->devdata;
++      struct acpi_video_device *video = acpi_driver_data(device);
++      int level;
++ 
++      if ( state >= video->brightness->count - 2)
++              return -EINVAL;
++ 
++      state = video->brightness->count - state;
++      level = video->brightness->levels[state -1];
++      return acpi_video_device_lcd_set_level(video, level);
++ }
++ 
++ static struct thermal_cooling_device_ops video_cooling_ops = {
++      .get_max_state = video_get_max_state,
++      .get_cur_state = video_get_cur_state,
++      .set_cur_state = video_set_cur_state,
++ };
++ 
   /* --------------------------------------------------------------------------
                                  Video Management
      -------------------------------------------------------------------------- */
@@@@ -660,6 -660,6 -702,8 +710,7 @@@@ static void acpi_video_device_find_cap(
        kfree(obj);
   
        if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){
  -             unsigned long tmp;
++              int result;
                static int count = 0;
                char *name;
                name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
                        return;
   
                sprintf(name, "acpi_video%d", count++);
  -             acpi_video_device_lcd_get_level_current(device, &tmp);
                device->backlight = backlight_device_register(name,
                        NULL, device, &acpi_backlight_ops);
  -             device->backlight->props.max_brightness = max_level;
  -             device->backlight->props.brightness = (int)tmp;
  +             device->backlight->props.max_brightness = device->brightness->count-3;
  +             device->backlight->props.brightness = acpi_video_get_brightness(device->backlight);
                backlight_update_status(device->backlight);
-- 
                kfree(name);
++ 
++              device->cdev = thermal_cooling_device_register("LCD",
++                                      device->dev, &video_cooling_ops);
++              if (device->cdev) {
++                      printk(KERN_INFO PREFIX
++                              "%s is registered as cooling_device%d\n",
++                              device->dev->dev.bus_id, device->cdev->id);
++                      result = sysfs_create_link(&device->dev->dev.kobj,
++                                        &device->cdev->device.kobj,
++                                        "thermal_cooling");
++                      if (result)
++                              printk(KERN_ERR PREFIX "Create sysfs link\n");
++                      result = sysfs_create_link(&device->cdev->device.kobj,
++                                        &device->dev->dev.kobj,
++                                        "device");
++                         if (result)
++                              printk(KERN_ERR PREFIX "Create sysfs link\n");
++              }
        }
        if (device->cap._DCS && device->cap._DSS){
                static int count = 0;
@@@@ -1262,37 -1262,37 -1324,8 +1330,37 @@@@ acpi_video_bus_write_DOS(struct file *f
   
   static int acpi_video_bus_add_fs(struct acpi_device *device)
   {
  +     long device_id;
  +     int status;
        struct proc_dir_entry *entry = NULL;
        struct acpi_video_bus *video;
  +     struct device *dev;
  +
  +     status =
  +         acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
  +
  +     if (!ACPI_SUCCESS(status))
  +             return -ENODEV;
  +
  +     /* We need to attempt to determine whether the _ADR refers to a
  +        PCI device or not. There's no terribly good way to do this,
  +        so the best we can hope for is to assume that there'll never
  +        be a video device in the host bridge */
  +     if (device_id >= 0x10000) {
  +             /* It looks like a PCI device. Does it exist? */
  +             dev = acpi_get_physical_device(device->handle);
  +     } else {
  +             /* It doesn't look like a PCI device. Does its parent
  +                exist? */
  +             acpi_handle phandle;
  +             if (acpi_get_parent(device->handle, &phandle))
  +                     return -ENODEV;
  +             dev = acpi_get_physical_device(phandle);
  +     }
  +     if (!dev)
  +             return -ENODEV;
  +     put_device(dev);
  +
   
   
        video = acpi_driver_data(device);
@@@@ -1764,6 -1764,6 -1797,14 +1832,14 @@@@ static int acpi_video_bus_put_one_devic
                                            ACPI_DEVICE_NOTIFY,
                                            acpi_video_device_notify);
        backlight_device_unregister(device->backlight);
++      if (device->cdev) {
++              sysfs_remove_link(&device->dev->dev.kobj,
++                                "thermal_cooling");
++              sysfs_remove_link(&device->cdev->device.kobj,
++                                "device");
++              thermal_cooling_device_unregister(device->cdev);
++              device->cdev = NULL;
++      }
        video_output_unregister(device->output_dev);
   
        return 0;
diff --combined drivers/misc/Kconfig
index b1f9a405c8228e7aba63dd098f52074ffe331a77,b1f9a405c8228e7aba63dd098f52074ffe331a77,d1380a5a0030c031638bff43e86d0244c50ed613..f20c30cf99e067addea43dab00ffa938a299b9d5
@@@@ -219,25 -219,25 -219,6 +219,25 @@@@ config THINKPAD_ACPI_BA
   
          If you are not sure, say Y here.
   
  +config THINKPAD_ACPI_HOTKEY_POLL
  +     bool "Suport NVRAM polling for hot keys"
  +     depends on THINKPAD_ACPI
  +     default y
  +     ---help---
  +       Some thinkpad models benefit from NVRAM polling to detect a few of
  +       the hot key press events.  If you know your ThinkPad model does not
  +       need to do NVRAM polling to support any of the hot keys you use,
  +       unselecting this option will save about 1kB of memory.
  +
  +       ThinkPads T40 and newer, R52 and newer, and X31 and newer are
  +       unlikely to need NVRAM polling in their latest BIOS versions.
  +
  +       NVRAM polling can detect at most the following keys: ThinkPad/Access
  +       IBM, Zoom, Switch Display (fn+F7), ThinkLight, Volume up/down/mute,
  +       Brightness up/down, Display Expand (fn+F8), Hibernate (fn+F12).
  +
  +       If you are not sure, say Y here.  The driver enables polling only if
  +       it is strictly necessary to do so.
   
   config ATMEL_SSC
        tristate "Device driver for Atmel SSC peripheral"
   
          If unsure, say N.
   
++ config INTEL_MENLOW
++      tristate "Thermal Management driver for Intel menlow platform"
++      depends on ACPI_THERMAL
++      ---help---
++        ACPI thermal management enhancement driver on
++        Intel Menlow platform.
++ 
++        If unsure, say N.
++ 
   endif # MISC_DEVICES
diff --combined include/acpi/processor.h
index f6d7c508917c340b801ea0b44b2b196bacd719ec,f6d7c508917c340b801ea0b44b2b196bacd719ec,0787635a11aa52ba473c162aa77ec36329d937d9..0c75a0b9c565f3e82d0125734d92a36710b79f97
@@@@ -4,7 -4,7 -4,7 +4,7 @@@@
   #include <linux/kernel.h>
   #include <linux/cpu.h>
   #include <linux/cpuidle.h>
-- 
++ #include <linux/thermal.h>
   #include <asm/acpi.h>
   
   #define ACPI_PROCESSOR_BUSY_METRIC   10
   
   #define ACPI_CSTATE_SYSTEMIO (0)
   #define ACPI_CSTATE_FFH              (1)
  +#define ACPI_CSTATE_HALT     (2)
   
   /* Power Management */
   
@@@@ -65,7 -65,7 -64,7 +65,7 @@@@ struct acpi_processor_cx 
        u8 valid;
        u8 type;
        u32 address;
  -     u8 space_id;
  +     u8 entry_method;
        u8 index;
        u32 latency;
        u32 latency_ticks;
@@@@ -183,7 -183,7 -182,7 +183,7 @@@@ struct acpi_processor_throttling 
   /* Limit Interface */
   
   struct acpi_processor_lx {
  -     int px;                 /* performace state */
  +     int px;                 /* performance state */
        int tx;                 /* throttle level */
   };
   
@@@@ -219,7 -219,7 -218,7 +219,7 @@@@ struct acpi_processor 
        struct acpi_processor_performance *performance;
        struct acpi_processor_throttling throttling;
        struct acpi_processor_limit limit;
-- 
++      struct thermal_cooling_device *cdev;
        /* the _PDC objects for this processor, if any */
        struct acpi_object_list *pdc;
   };
@@@@ -331,7 -331,7 -330,7 +331,7 @@@@ extern struct cpuidle_driver acpi_idle_
   /* in processor_thermal.c */
   int acpi_processor_get_limit_info(struct acpi_processor *pr);
   extern struct file_operations acpi_processor_limit_fops;
-- 
++ extern struct thermal_cooling_device_ops processor_cooling_ops;
   #ifdef CONFIG_CPU_FREQ
   void acpi_thermal_cpufreq_init(void);
   void acpi_thermal_cpufreq_exit(void);