merge linus into test branch
authorLen Brown <len.brown@intel.com>
Wed, 20 Dec 2006 07:53:13 +0000 (02:53 -0500)
committerLen Brown <len.brown@intel.com>
Wed, 20 Dec 2006 07:53:13 +0000 (02:53 -0500)
53 files changed:
Documentation/ibm-acpi.txt
MAINTAINERS
arch/i386/kernel/acpi/boot.c
drivers/acpi/Kconfig
drivers/acpi/ac.c
drivers/acpi/acpi_memhotplug.c
drivers/acpi/asus_acpi.c
drivers/acpi/battery.c
drivers/acpi/button.c
drivers/acpi/container.c
drivers/acpi/dock.c
drivers/acpi/ec.c
drivers/acpi/events/evmisc.c
drivers/acpi/executer/exmutex.c
drivers/acpi/fan.c
drivers/acpi/glue.c
drivers/acpi/hotkey.c
drivers/acpi/i2c_ec.c
drivers/acpi/ibm_acpi.c
drivers/acpi/numa.c
drivers/acpi/osl.c
drivers/acpi/pci_bind.c
drivers/acpi/pci_irq.c
drivers/acpi/pci_link.c
drivers/acpi/pci_root.c
drivers/acpi/power.c
drivers/acpi/processor_core.c
drivers/acpi/processor_idle.c
drivers/acpi/processor_perflib.c
drivers/acpi/processor_thermal.c
drivers/acpi/processor_throttling.c
drivers/acpi/sbs.c
drivers/acpi/sleep/wakeup.c
drivers/acpi/tables.c
drivers/acpi/thermal.c
drivers/acpi/toshiba_acpi.c
drivers/acpi/utilities/utdebug.c
drivers/acpi/utilities/utmutex.c
drivers/acpi/utils.c
drivers/acpi/video.c
drivers/misc/msi-laptop.c
drivers/usb/misc/appledisplay.c
drivers/video/aty/aty128fb.c
drivers/video/aty/atyfb_base.c
drivers/video/aty/radeon_backlight.c
drivers/video/backlight/backlight.c
drivers/video/nvidia/nv_backlight.c
drivers/video/riva/fbdev.c
include/asm-i386/acpi.h
include/asm-x86_64/acpi.h
include/linux/backlight.h
kernel/power/disk.c
kernel/power/main.c

index e50595bfd8ea63e0cfc15c0c4cadd94e01ea1224..0132d363feb564b0af0c3544226887df9f474aec 100644 (file)
@@ -398,25 +398,67 @@ Temperature sensors -- /proc/acpi/ibm/thermal
 
 Most ThinkPads include six or more separate temperature sensors but
 only expose the CPU temperature through the standard ACPI methods.
-This feature shows readings from up to eight different sensors. Some
-readings may not be valid, e.g. may show large negative values. For
-example, on the X40, a typical output may be:
+This feature shows readings from up to eight different sensors on older
+ThinkPads, and it has experimental support for up to sixteen different
+sensors on newer ThinkPads.  Readings from sensors that are not available
+return -128.
 
+No commands can be written to this file.
+
+EXPERIMENTAL: The 16-sensors feature is marked EXPERIMENTAL because the
+implementation directly accesses hardware registers and may not work as
+expected. USE WITH CAUTION! To use this feature, you need to supply the
+experimental=1 parameter when loading the module.  When EXPERIMENTAL
+mode is enabled, reading the first 8 sensors on newer ThinkPads will
+also use an new experimental thermal sensor access mode.
+
+For example, on the X40, a typical output may be:
 temperatures:   42 42 45 41 36 -128 33 -128
 
-Thomas Gruber took his R51 apart and traced all six active sensors in
-his laptop (the location of sensors may vary on other models):
+EXPERIMENTAL: On the T43/p, a typical output may be:
+temperatures:   48 48 36 52 38 -128 31 -128 48 52 48 -128 -128 -128 -128 -128
+
+The mapping of thermal sensors to physical locations varies depending on
+system-board model (and thus, on ThinkPad model).
+
+http://thinkwiki.org/wiki/Thermal_Sensors is a public wiki page that
+tries to track down these locations for various models.
+
+Most (newer?) models seem to follow this pattern:
 
 1:  CPU
-2:  Mini PCI Module
-3:  HDD
+2:  (depends on model)
+3:  (depends on model)
 4:  GPU
-5:  Battery
-6:  N/A
-7:  Battery
-8:  N/A
+5:  Main battery: main sensor
+6:  Bay battery: main sensor
+7:  Main battery: secondary sensor
+8:  Bay battery: secondary sensor
+9-15: (depends on model)
+
+For the R51 (source: Thomas Gruber):
+2:  Mini-PCI
+3:  Internal HDD
+
+For the T43, T43/p (source: Shmidoax/Thinkwiki.org)
+http://thinkwiki.org/wiki/Thermal_Sensors#ThinkPad_T43.2C_T43p
+2:  System board, left side (near PCMCIA slot), reported as HDAPS temp
+3:  PCMCIA slot
+9:  MCH (northbridge) to DRAM Bus
+10: ICH (southbridge), under Mini-PCI card, under touchpad
+11: Power regulator, underside of system board, below F2 key
+
+The A31 has a very atypical layout for the thermal sensors
+(source: Milos Popovic, http://thinkwiki.org/wiki/Thermal_Sensors#ThinkPad_A31)
+1:  CPU
+2:  Main Battery: main sensor
+3:  Power Converter
+4:  Bay Battery: main sensor
+5:  MCH (northbridge)
+6:  PCMCIA/ambient
+7:  Main Battery: secondary sensor
+8:  Bay Battery: secondary sensor
 
-No commands can be written to this file.
 
 EXPERIMENTAL: Embedded controller register dump -- /proc/acpi/ibm/ecdump
 ------------------------------------------------------------------------
@@ -529,27 +571,57 @@ directly accesses hardware registers and may not work as expected. USE
 WITH CAUTION! To use this feature, you need to supply the
 experimental=1 parameter when loading the module.
 
-This feature attempts to show the current fan speed. The speed is read
-directly from the hardware registers of the embedded controller. This
-is known to work on later R, T and X series ThinkPads but may show a
-bogus value on other models.
+This feature attempts to show the current fan speed, control mode and
+other fan data that might be available.  The speed is read directly
+from the hardware registers of the embedded controller.  This is known
+to work on later R, T and X series ThinkPads but may show a bogus
+value on other models.
+
+Most ThinkPad fans work in "levels".  Level 0 stops the fan.  The higher
+the level, the higher the fan speed, although adjacent levels often map
+to the same fan speed.  7 is the highest level, where the fan reaches
+the maximum recommended speed.  Level "auto" means the EC changes the
+fan level according to some internal algorithm, usually based on
+readings from the thermal sensors.  Level "disengaged" means the EC
+disables the speed-locked closed-loop fan control, and drives the fan as
+fast as it can go, which might exceed hardware limits, so use this level
+with caution.
+
+The fan usually ramps up or down slowly from one speed to another,
+and it is normal for the EC to take several seconds to react to fan
+commands.
 
 The fan may be enabled or disabled with the following commands:
 
        echo enable  >/proc/acpi/ibm/fan
        echo disable >/proc/acpi/ibm/fan
 
+Placing a fan on level 0 is the same as disabling it.  Enabling a fan
+will try to place it in a safe level if it is too slow or disabled.
+
 WARNING WARNING WARNING: do not leave the fan disabled unless you are
-monitoring the temperature sensor readings and you are ready to enable
-it if necessary to avoid overheating.
+monitoring all of the temperature sensor readings and you are ready to
+enable it if necessary to avoid overheating.
 
-The fan only runs if it's enabled *and* the various temperature
-sensors which control it read high enough. On the X40, this seems to
-depend on the CPU and HDD temperatures. Specifically, the fan is
-turned on when either the CPU temperature climbs to 56 degrees or the
-HDD temperature climbs to 46 degrees. The fan is turned off when the
-CPU temperature drops to 49 degrees and the HDD temperature drops to
-41 degrees. These thresholds cannot currently be controlled.
+An enabled fan in level "auto" may stop spinning if the EC decides the
+ThinkPad is cool enough and doesn't need the extra airflow.  This is
+normal, and the EC will spin the fan up if the varios thermal readings
+rise too much.
+
+On the X40, this seems to depend on the CPU and HDD temperatures.
+Specifically, the fan is turned on when either the CPU temperature
+climbs to 56 degrees or the HDD temperature climbs to 46 degrees.  The
+fan is turned off when the CPU temperature drops to 49 degrees and the
+HDD temperature drops to 41 degrees.  These thresholds cannot
+currently be controlled.
+
+The fan level can be controlled with the command:
+
+       echo 'level <level>' > /proc/acpi/ibm/thermal
+
+Where <level> is an integer from 0 to 7, or one of the words "auto"
+or "disengaged" (without the quotes).  Not all ThinkPads support the
+"auto" and "disengaged" levels.
 
 On the X31 and X40 (and ONLY on those models), the fan speed can be
 controlled to a certain degree. Once the fan is running, it can be
@@ -562,12 +634,9 @@ about 3700 to about 7350. Values outside this range either do not have
 any effect or the fan speed eventually settles somewhere in that
 range. The fan cannot be stopped or started with this command.
 
-On the 570, temperature readings are not available through this
-feature and the fan control works a little differently. The fan speed
-is reported in levels from 0 (off) to 7 (max) and can be controlled
-with the following command:
-
-       echo 'level <level>' > /proc/acpi/ibm/thermal
+The ThinkPad's ACPI DSDT code will reprogram the fan on its own when
+certain conditions are met.  It will override any fan programming done
+through ibm-acpi.
 
 EXPERIMENTAL: WAN -- /proc/acpi/ibm/wan
 ---------------------------------------
@@ -601,6 +670,26 @@ example:
 
        modprobe ibm_acpi hotkey=enable,0xffff video=auto_disable
 
+The ibm-acpi kernel driver can be programmed to revert the fan level
+to a safe setting if userspace does not issue one of the fan commands:
+"enable", "disable", "level" or "watchdog" within a configurable
+ammount of time.  To do this, use the "watchdog" command.
+
+       echo 'watchdog <interval>' > /proc/acpi/ibm/fan
+
+Interval is the ammount of time in seconds to wait for one of the
+above mentioned fan commands before reseting the fan level to a safe
+one.  If set to zero, the watchdog is disabled (default).  When the
+watchdog timer runs out, it does the exact equivalent of the "enable"
+fan command.
+
+Note that the watchdog timer stops after it enables the fan.  It will
+be rearmed again automatically (using the same interval) when one of
+the above mentioned fan commands is received.  The fan watchdog is,
+therefore, not suitable to protect against fan mode changes made
+through means other than the "enable", "disable", and "level" fan
+commands.
+
 
 Example Configuration
 ---------------------
index 3e926e73387862c4c334b013605fe0c8e16d1d95..db38a4d28039bc59f881ce88ee12638d908f3893 100644 (file)
@@ -1403,6 +1403,15 @@ W:       http://www.ia64-linux.org/
 T:     git kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
 S:     Maintained
 
+IBM ACPI EXTRAS DRIVER
+P:     Henrique de Moraes Holschuh
+M:     ibm-acpi@hmh.eng.br
+L:     ibm-acpi-devel@lists.sourceforge.net
+W:     http://ibm-acpi.sourceforge.net
+W:     http://thinkwiki.org/wiki/Ibm-acpi
+T:     git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
+S:     Maintained
+
 SN-IA64 (Itanium) SUB-PLATFORM
 P:     Jes Sorensen
 M:     jes@sgi.com
index c8f96cff07c61fd4560659da01dc2740f6bb6ee0..094300b3a81fad123f347403434ff20f645cb5cc 100644 (file)
@@ -1327,3 +1327,25 @@ static int __init setup_acpi_sci(char *s)
        return 0;
 }
 early_param("acpi_sci", setup_acpi_sci);
+
+int __acpi_acquire_global_lock(unsigned int *lock)
+{
+       unsigned int old, new, val;
+       do {
+               old = *lock;
+               new = (((old & ~0x3) + 2) + ((old >> 1) & 0x1));
+               val = cmpxchg(lock, old, new);
+       } while (unlikely (val != old));
+       return (new < 3) ? -1 : 0;
+}
+
+int __acpi_release_global_lock(unsigned int *lock)
+{
+       unsigned int old, new, val;
+       do {
+               old = *lock;
+               new = old & ~0x3;
+               val = cmpxchg(lock, old, new);
+       } while (unlikely (val != old));
+       return old & 0x1;
+}
index 0f9d4be7ed758814ba7c9a3e63d8620998609e04..1639998e4d2754ea0819b2f946585b98efb6f429 100644 (file)
@@ -11,7 +11,7 @@ config ACPI
        bool "ACPI Support"
        depends on IA64 || X86
        depends on PCI
-       select PM
+       depends on PM
        default y
        ---help---
          Advanced Configuration and Power Interface (ACPI) support for 
@@ -97,6 +97,7 @@ config ACPI_BATTERY
 
 config ACPI_BUTTON
        tristate "Button"
+       depends on INPUT
        default y
        help
          This driver handles events on the power, sleep and lid buttons.
@@ -172,6 +173,7 @@ config ACPI_NUMA
 config ACPI_ASUS
         tristate "ASUS/Medion Laptop Extras"
        depends on X86
+       select BACKLIGHT_CLASS_DEVICE
         ---help---
           This driver provides support for extra features of ACPI-compatible
           ASUS laptops. As some of Medion laptops are made by ASUS, it may also
@@ -200,6 +202,7 @@ config ACPI_ASUS
 config ACPI_IBM
        tristate "IBM ThinkPad Laptop Extras"
        depends on X86
+       select BACKLIGHT_CLASS_DEVICE
        ---help---
          This is a Linux ACPI driver for the IBM ThinkPad laptops. It adds
          support for Fn-Fx key combinations, Bluetooth control, video
@@ -222,9 +225,21 @@ config ACPI_IBM_DOCK
 
          If you are not sure, say N here.
 
+config ACPI_IBM_BAY
+       bool "Legacy Removable Bay Support"
+       depends on ACPI_IBM
+       depends on ACPI_BAY=n
+       default n
+       ---help---
+         Allows the ibm_acpi driver to handle removable bays.
+         This support is obsoleted by CONFIG_ACPI_BAY.
+
+         If you are not sure, say N here.
+
 config ACPI_TOSHIBA
        tristate "Toshiba Laptop Extras"
        depends on X86
+       select BACKLIGHT_CLASS_DEVICE
        ---help---
          This driver adds support for access to certain system settings
          on "legacy free" Toshiba laptops.  These laptops can be recognized by
index 11abc7bf777ef90626eac53d0aec8e32f0228bde..46e58663dcb5dd75936894c5d4389a7dcb985ffc 100644 (file)
@@ -109,7 +109,7 @@ static struct proc_dir_entry *acpi_ac_dir;
 
 static int acpi_ac_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_ac *ac = (struct acpi_ac *)seq->private;
+       struct acpi_ac *ac = seq->private;
 
 
        if (!ac)
@@ -187,7 +187,7 @@ static int acpi_ac_remove_fs(struct acpi_device *device)
 
 static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
 {
-       struct acpi_ac *ac = (struct acpi_ac *)data;
+       struct acpi_ac *ac = data;
        struct acpi_device *device = NULL;
 
 
@@ -269,7 +269,7 @@ static int acpi_ac_remove(struct acpi_device *device, int type)
        if (!device || !acpi_driver_data(device))
                return -EINVAL;
 
-       ac = (struct acpi_ac *)acpi_driver_data(device);
+       ac = acpi_driver_data(device);
 
        status = acpi_remove_notify_handler(device->handle,
                                            ACPI_ALL_NOTIFY, acpi_ac_notify);
index 6bcd9e8e7bcb2b081df4262a20489f9fd7ec0779..150112ae48ed7e6bfdd4afefa7d17b7bd244845d 100644 (file)
@@ -429,7 +429,7 @@ static int acpi_memory_device_remove(struct acpi_device *device, int type)
        if (!device || !acpi_driver_data(device))
                return -EINVAL;
 
-       mem_device = (struct acpi_memory_device *)acpi_driver_data(device);
+       mem_device = acpi_driver_data(device);
        kfree(mem_device);
 
        return 0;
index c7ac9297a20499893da15a4f2c766285310d6f1b..7cc54aacd4c082f8623eb5a90a382f99ddda499b 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
+#include <linux/backlight.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/acpi_bus.h>
 #include <asm/uaccess.h>
@@ -402,6 +403,8 @@ static struct model_data model_conf[END_MODEL] = {
 /* procdir we use */
 static struct proc_dir_entry *asus_proc_dir;
 
+static struct backlight_device *asus_backlight_device;
+
 /*
  * This header is made available to allow proper configuration given model,
  * revision number , ... this info cannot go in struct asus_hotk because it is
@@ -779,7 +782,7 @@ proc_write_lcd(struct file *file, const char __user * buffer,
        return rv;
 }
 
-static int read_brightness(void)
+static int read_brightness(struct backlight_device *bd)
 {
        int value;
 
@@ -801,9 +804,10 @@ static int read_brightness(void)
 /*
  * Change the brightness level
  */
-static void set_brightness(int value)
+static int set_brightness(int value)
 {
        acpi_status status = 0;
+       int ret = 0;
 
        /* SPLV laptop */
        if (hotk->methods->brightness_set) {
@@ -811,11 +815,12 @@ static void set_brightness(int value)
                                    value, NULL))
                        printk(KERN_WARNING
                               "Asus ACPI: Error changing brightness\n");
-               return;
+                       ret = -EIO;
+               goto out;
        }
 
        /* No SPLV method if we are here, act as appropriate */
-       value -= read_brightness();
+       value -= read_brightness(NULL);
        while (value != 0) {
                status = acpi_evaluate_object(NULL, (value > 0) ?
                                              hotk->methods->brightness_up :
@@ -825,15 +830,22 @@ static void set_brightness(int value)
                if (ACPI_FAILURE(status))
                        printk(KERN_WARNING
                               "Asus ACPI: Error changing brightness\n");
+                       ret = -EIO;
        }
-       return;
+out:
+       return ret;
+}
+
+static int set_brightness_status(struct backlight_device *bd)
+{
+       return set_brightness(bd->props->brightness);
 }
 
 static int
 proc_read_brn(char *page, char **start, off_t off, int count, int *eof,
              void *data)
 {
-       return sprintf(page, "%d\n", read_brightness());
+       return sprintf(page, "%d\n", read_brightness(NULL));
 }
 
 static int
@@ -1134,7 +1146,7 @@ static int asus_hotk_get_info(void)
        if (ACPI_FAILURE(status))
                printk(KERN_WARNING "  Couldn't get the DSDT table header\n");
        else
-               asus_info = (struct acpi_table_header *)dsdt.pointer;
+               asus_info = dsdt.pointer;
 
        /* We have to write 0 on init this far for all ASUS models */
        if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {
@@ -1156,7 +1168,7 @@ static int asus_hotk_get_info(void)
         * asus_model_match() and try something completely different.
         */
        if (buffer.pointer) {
-               model = (union acpi_object *)buffer.pointer;
+               model = buffer.pointer;
                switch (model->type) {
                case ACPI_TYPE_STRING:
                        string = model->string.pointer;
@@ -1252,8 +1264,7 @@ static int asus_hotk_add(struct acpi_device *device)
        printk(KERN_NOTICE "Asus Laptop ACPI Extras version %s\n",
               ASUS_ACPI_VERSION);
 
-       hotk =
-           (struct asus_hotk *)kmalloc(sizeof(struct asus_hotk), GFP_KERNEL);
+       hotk = kmalloc(sizeof(struct asus_hotk), GFP_KERNEL);
        if (!hotk)
                return -ENOMEM;
        memset(hotk, 0, sizeof(struct asus_hotk));
@@ -1333,6 +1344,26 @@ static int asus_hotk_remove(struct acpi_device *device, int type)
        return 0;
 }
 
+static struct backlight_properties asus_backlight_data = {
+        .owner          = THIS_MODULE,
+        .get_brightness = read_brightness,
+        .update_status  = set_brightness_status,
+        .max_brightness = 15,
+};
+
+static void __exit asus_acpi_exit(void)
+{
+       if (asus_backlight_device)
+               backlight_device_unregister(asus_backlight_device);
+
+       acpi_bus_unregister_driver(&asus_hotk_driver);
+       remove_proc_entry(PROC_ASUS, acpi_root_dir);
+
+       kfree(asus_info);
+
+       return;
+}
+
 static int __init asus_acpi_init(void)
 {
        int result;
@@ -1370,17 +1401,15 @@ static int __init asus_acpi_init(void)
                return result;
        }
 
-       return 0;
-}
-
-static void __exit asus_acpi_exit(void)
-{
-       acpi_bus_unregister_driver(&asus_hotk_driver);
-       remove_proc_entry(PROC_ASUS, acpi_root_dir);
-
-       kfree(asus_info);
+       asus_backlight_device = backlight_device_register("asus",NULL,NULL,
+                                                         &asus_backlight_data);
+        if (IS_ERR(asus_backlight_device)) {
+               printk(KERN_ERR "Could not register asus backlight device\n");
+               asus_backlight_device = NULL;
+               asus_acpi_exit();
+       }
 
-       return;
+       return 0;
 }
 
 module_init(asus_acpi_init);
index 026e40755cdd7b0780c4832aade6a9601fb9db83..f47c78a106561e23f3d179a3055fec3372c27734 100644 (file)
@@ -149,7 +149,7 @@ acpi_battery_get_info(struct acpi_battery *battery,
                return -ENODEV;
        }
 
-       package = (union acpi_object *)buffer.pointer;
+       package = buffer.pointer;
 
        /* Extract Package Data */
 
@@ -179,7 +179,7 @@ acpi_battery_get_info(struct acpi_battery *battery,
        kfree(buffer.pointer);
 
        if (!result)
-               (*bif) = (struct acpi_battery_info *)data.pointer;
+               (*bif) = data.pointer;
 
        return result;
 }
@@ -209,7 +209,7 @@ acpi_battery_get_status(struct acpi_battery *battery,
                return -ENODEV;
        }
 
-       package = (union acpi_object *)buffer.pointer;
+       package = buffer.pointer;
 
        /* Extract Package Data */
 
@@ -239,7 +239,7 @@ acpi_battery_get_status(struct acpi_battery *battery,
        kfree(buffer.pointer);
 
        if (!result)
-               (*bst) = (struct acpi_battery_status *)data.pointer;
+               (*bst) = data.pointer;
 
        return result;
 }
@@ -334,7 +334,7 @@ static struct proc_dir_entry *acpi_battery_dir;
 static int acpi_battery_read_info(struct seq_file *seq, void *offset)
 {
        int result = 0;
-       struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+       struct acpi_battery *battery = seq->private;
        struct acpi_battery_info *bif = NULL;
        char *units = "?";
 
@@ -418,7 +418,7 @@ static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
 static int acpi_battery_read_state(struct seq_file *seq, void *offset)
 {
        int result = 0;
-       struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+       struct acpi_battery *battery = seq->private;
        struct acpi_battery_status *bst = NULL;
        char *units = "?";
 
@@ -494,7 +494,7 @@ static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
 
 static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
 {
-       struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+       struct acpi_battery *battery = seq->private;
        char *units = "?";
 
 
@@ -531,8 +531,8 @@ acpi_battery_write_alarm(struct file *file,
 {
        int result = 0;
        char alarm_string[12] = { '\0' };
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       struct acpi_battery *battery = (struct acpi_battery *)m->private;
+       struct seq_file *m = file->private_data;
+       struct acpi_battery *battery = m->private;
 
 
        if (!battery || (count > sizeof(alarm_string) - 1))
@@ -658,7 +658,7 @@ static int acpi_battery_remove_fs(struct acpi_device *device)
 
 static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
 {
-       struct acpi_battery *battery = (struct acpi_battery *)data;
+       struct acpi_battery *battery = data;
        struct acpi_device *device = NULL;
 
 
@@ -742,7 +742,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
        if (!device || !acpi_driver_data(device))
                return -EINVAL;
 
-       battery = (struct acpi_battery *)acpi_driver_data(device);
+       battery = acpi_driver_data(device);
 
        status = acpi_remove_notify_handler(device->handle,
                                            ACPI_ALL_NOTIFY,
index 5ef885e82c78a94b7352307307ac4b5e35e0b08f..ac860583c2034a1fa7a8febbdd91cae0e279debd 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/types.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/input.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
@@ -62,7 +63,7 @@
 #define _COMPONENT             ACPI_BUTTON_COMPONENT
 ACPI_MODULE_NAME("acpi_button")
 
-    MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_AUTHOR("Paul Diefenbaugh");
 MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME);
 MODULE_LICENSE("GPL");
 
@@ -78,12 +79,14 @@ static struct acpi_driver acpi_button_driver = {
        .ops = {
                .add = acpi_button_add,
                .remove = acpi_button_remove,
-               },
+       },
 };
 
 struct acpi_button {
        struct acpi_device *device;     /* Fixed button kludge */
-       u8 type;
+       unsigned int type;
+       struct input_dev *input;
+       char phys[32];                  /* for input device */
        unsigned long pushed;
 };
 
@@ -109,8 +112,7 @@ static struct proc_dir_entry *acpi_button_dir;
 
 static int acpi_button_info_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_button *button = (struct acpi_button *)seq->private;
-
+       struct acpi_button *button = seq->private;
 
        if (!button || !button->device)
                return 0;
@@ -128,22 +130,17 @@ static int acpi_button_info_open_fs(struct inode *inode, struct file *file)
 
 static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_button *button = (struct acpi_button *)seq->private;
+       struct acpi_button *button = seq->private;
        acpi_status status;
        unsigned long state;
 
-
        if (!button || !button->device)
                return 0;
 
        status = acpi_evaluate_integer(button->device->handle, "_LID", NULL, &state);
-       if (ACPI_FAILURE(status)) {
-               seq_printf(seq, "state:      unsupported\n");
-       } else {
-               seq_printf(seq, "state:      %s\n",
-                          (state ? "open" : "closed"));
-       }
-
+       seq_printf(seq, "state:      %s\n",
+                  ACPI_FAILURE(status) ? "unsupported" :
+                       (state ? "open" : "closed"));
        return 0;
 }
 
@@ -159,8 +156,7 @@ static struct proc_dir_entry *acpi_lid_dir;
 static int acpi_button_add_fs(struct acpi_device *device)
 {
        struct proc_dir_entry *entry = NULL;
-       struct acpi_button *button = NULL;
-
+       struct acpi_button *button;
 
        if (!device || !acpi_driver_data(device))
                return -EINVAL;
@@ -228,10 +224,8 @@ static int acpi_button_add_fs(struct acpi_device *device)
 
 static int acpi_button_remove_fs(struct acpi_device *device)
 {
-       struct acpi_button *button = NULL;
-
+       struct acpi_button *button = acpi_driver_data(device);
 
-       button = acpi_driver_data(device);
        if (acpi_device_dir(device)) {
                if (button->type == ACPI_BUTTON_TYPE_LID)
                        remove_proc_entry(ACPI_BUTTON_FILE_STATE,
@@ -253,14 +247,34 @@ static int acpi_button_remove_fs(struct acpi_device *device)
 
 static void acpi_button_notify(acpi_handle handle, u32 event, void *data)
 {
-       struct acpi_button *button = (struct acpi_button *)data;
-
+       struct acpi_button *button = data;
+       struct input_dev *input;
 
        if (!button || !button->device)
                return;
 
        switch (event) {
        case ACPI_BUTTON_NOTIFY_STATUS:
+               input = button->input;
+
+               if (button->type == ACPI_BUTTON_TYPE_LID) {
+                       struct acpi_handle *handle = button->device->handle;
+                       unsigned long state;
+
+                       if (!ACPI_FAILURE(acpi_evaluate_integer(handle, "_LID",
+                                                               NULL, &state)))
+                               input_report_switch(input, SW_LID, !state);
+
+               } else {
+                       int keycode = test_bit(KEY_SLEEP, input->keybit) ?
+                                               KEY_SLEEP : KEY_POWER;
+
+                       input_report_key(input, keycode, 1);
+                       input_sync(input);
+                       input_report_key(input, keycode, 0);
+               }
+               input_sync(input);
+
                acpi_bus_generate_event(button->device, event,
                                        ++button->pushed);
                break;
@@ -275,8 +289,7 @@ static void acpi_button_notify(acpi_handle handle, u32 event, void *data)
 
 static acpi_status acpi_button_notify_fixed(void *data)
 {
-       struct acpi_button *button = (struct acpi_button *)data;
-
+       struct acpi_button *button = data;
 
        if (!button)
                return AE_BAD_PARAMETER;
@@ -286,24 +299,75 @@ static acpi_status acpi_button_notify_fixed(void *data)
        return AE_OK;
 }
 
-static int acpi_button_add(struct acpi_device *device)
+static int acpi_button_install_notify_handlers(struct acpi_button *button)
 {
-       int result = 0;
-       acpi_status status = AE_OK;
-       struct acpi_button *button = NULL;
+       acpi_status status;
 
+       switch (button->type) {
+       case ACPI_BUTTON_TYPE_POWERF:
+               status =
+                   acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
+                                                    acpi_button_notify_fixed,
+                                                    button);
+               break;
+       case ACPI_BUTTON_TYPE_SLEEPF:
+               status =
+                   acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
+                                                    acpi_button_notify_fixed,
+                                                    button);
+               break;
+       default:
+               status = acpi_install_notify_handler(button->device->handle,
+                                                    ACPI_DEVICE_NOTIFY,
+                                                    acpi_button_notify,
+                                                    button);
+               break;
+       }
+
+       return ACPI_FAILURE(status) ? -ENODEV : 0;
+}
+
+static void acpi_button_remove_notify_handlers(struct acpi_button *button)
+{
+       switch (button->type) {
+       case ACPI_BUTTON_TYPE_POWERF:
+               acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
+                                               acpi_button_notify_fixed);
+               break;
+       case ACPI_BUTTON_TYPE_SLEEPF:
+               acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
+                                               acpi_button_notify_fixed);
+               break;
+       default:
+               acpi_remove_notify_handler(button->device->handle,
+                                          ACPI_DEVICE_NOTIFY,
+                                          acpi_button_notify);
+               break;
+       }
+}
+
+static int acpi_button_add(struct acpi_device *device)
+{
+       int error;
+       struct acpi_button *button;
+       struct input_dev *input;
 
        if (!device)
                return -EINVAL;
 
-       button = kmalloc(sizeof(struct acpi_button), GFP_KERNEL);
+       button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL);
        if (!button)
                return -ENOMEM;
-       memset(button, 0, sizeof(struct acpi_button));
 
        button->device = device;
        acpi_driver_data(device) = button;
 
+       button->input = input = input_allocate_device();
+       if (!input) {
+               error = -ENOMEM;
+               goto err_free_button;
+       }
+
        /*
         * Determine the button type (via hid), as fixed-feature buttons
         * need to be handled a bit differently than generic-space.
@@ -338,39 +402,48 @@ static int acpi_button_add(struct acpi_device *device)
        } else {
                printk(KERN_ERR PREFIX "Unsupported hid [%s]\n",
                            acpi_device_hid(device));
-               result = -ENODEV;
-               goto end;
+               error = -ENODEV;
+               goto err_free_input;
        }
 
-       result = acpi_button_add_fs(device);
-       if (result)
-               goto end;
+       error = acpi_button_add_fs(device);
+       if (error)
+               goto err_free_input;
+
+       error = acpi_button_install_notify_handlers(button);
+       if (error)
+               goto err_remove_fs;
+
+       snprintf(button->phys, sizeof(button->phys),
+                "%s/button/input0", acpi_device_hid(device));
+
+       input->name = acpi_device_name(device);
+       input->phys = button->phys;
+       input->id.bustype = BUS_HOST;
+       input->id.product = button->type;
 
        switch (button->type) {
+       case ACPI_BUTTON_TYPE_POWER:
        case ACPI_BUTTON_TYPE_POWERF:
-               status =
-                   acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
-                                                    acpi_button_notify_fixed,
-                                                    button);
+               input->evbit[0] = BIT(EV_KEY);
+               set_bit(KEY_POWER, input->keybit);
                break;
+
+       case ACPI_BUTTON_TYPE_SLEEP:
        case ACPI_BUTTON_TYPE_SLEEPF:
-               status =
-                   acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
-                                                    acpi_button_notify_fixed,
-                                                    button);
+               input->evbit[0] = BIT(EV_KEY);
+               set_bit(KEY_SLEEP, input->keybit);
                break;
-       default:
-               status = acpi_install_notify_handler(device->handle,
-                                                    ACPI_DEVICE_NOTIFY,
-                                                    acpi_button_notify,
-                                                    button);
+
+       case ACPI_BUTTON_TYPE_LID:
+               input->evbit[0] = BIT(EV_SW);
+               set_bit(SW_LID, input->swbit);
                break;
        }
 
-       if (ACPI_FAILURE(status)) {
-               result = -ENODEV;
-               goto end;
-       }
+       error = input_register_device(input);
+       if (error)
+               goto err_remove_handlers;
 
        if (device->wakeup.flags.valid) {
                /* Button's GPE is run-wake GPE */
@@ -385,47 +458,31 @@ static int acpi_button_add(struct acpi_device *device)
        printk(KERN_INFO PREFIX "%s [%s]\n",
               acpi_device_name(device), acpi_device_bid(device));
 
-      end:
-       if (result) {
-               acpi_button_remove_fs(device);
-               kfree(button);
-       }
+       return 0;
 
-       return result;
+ err_remove_handlers:
+       acpi_button_remove_notify_handlers(button);
+ err_remove_fs:
+       acpi_button_remove_fs(device);
+ err_free_input:
+       input_free_device(input);
+ err_free_button:
+       kfree(button);
+       return error;
 }
 
 static int acpi_button_remove(struct acpi_device *device, int type)
 {
-       acpi_status status = 0;
-       struct acpi_button *button = NULL;
-
+       struct acpi_button *button;
 
        if (!device || !acpi_driver_data(device))
                return -EINVAL;
 
        button = acpi_driver_data(device);
 
-       /* Unregister for device notifications. */
-       switch (button->type) {
-       case ACPI_BUTTON_TYPE_POWERF:
-               status =
-                   acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
-                                                   acpi_button_notify_fixed);
-               break;
-       case ACPI_BUTTON_TYPE_SLEEPF:
-               status =
-                   acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
-                                                   acpi_button_notify_fixed);
-               break;
-       default:
-               status = acpi_remove_notify_handler(device->handle,
-                                                   ACPI_DEVICE_NOTIFY,
-                                                   acpi_button_notify);
-               break;
-       }
-
+       acpi_button_remove_notify_handlers(button);
        acpi_button_remove_fs(device);
-
+       input_unregister_device(button->input);
        kfree(button);
 
        return 0;
@@ -433,8 +490,7 @@ static int acpi_button_remove(struct acpi_device *device, int type)
 
 static int __init acpi_button_init(void)
 {
-       int result = 0;
-
+       int result;
 
        acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
        if (!acpi_button_dir)
@@ -451,7 +507,6 @@ static int __init acpi_button_init(void)
 
 static void __exit acpi_button_exit(void)
 {
-
        acpi_bus_unregister_driver(&acpi_button_driver);
 
        if (acpi_power_dir)
@@ -461,8 +516,6 @@ static void __exit acpi_button_exit(void)
        if (acpi_lid_dir)
                remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
        remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
-
-       return;
 }
 
 module_init(acpi_button_init);
index 871aa520ece78aaa50d94bbb90a29c3c9f4ef83b..a15381789462d21bbcdcf0b7ccdc94508695acc2 100644 (file)
@@ -117,7 +117,7 @@ static int acpi_container_remove(struct acpi_device *device, int type)
        acpi_status status = AE_OK;
        struct acpi_container *pc = NULL;
 
-       pc = (struct acpi_container *)acpi_driver_data(device);
+       pc = acpi_driver_data(device);
        kfree(pc);
        return status;
 }
index bf5b79ed36131111b59527223e71a5a930b55e07..90990a4b65264aa0522bf54017b433df357df4d2 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/notifier.h>
+#include <linux/platform_device.h>
 #include <linux/jiffies.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
@@ -39,13 +40,15 @@ MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_NAME);
 MODULE_LICENSE("GPL");
 
 static struct atomic_notifier_head dock_notifier_list;
+static struct platform_device dock_device;
+static char dock_device_name[] = "dock";
 
 struct dock_station {
        acpi_handle handle;
        unsigned long last_dock_time;
        u32 flags;
        spinlock_t dd_lock;
-       spinlock_t hp_lock;
+       struct mutex hp_lock;
        struct list_head dependent_devices;
        struct list_head hotplug_devices;
 };
@@ -115,9 +118,9 @@ static void
 dock_add_hotplug_device(struct dock_station *ds,
                        struct dock_dependent_device *dd)
 {
-       spin_lock(&ds->hp_lock);
+       mutex_lock(&ds->hp_lock);
        list_add_tail(&dd->hotplug_list, &ds->hotplug_devices);
-       spin_unlock(&ds->hp_lock);
+       mutex_unlock(&ds->hp_lock);
 }
 
 /**
@@ -131,9 +134,9 @@ static void
 dock_del_hotplug_device(struct dock_station *ds,
                        struct dock_dependent_device *dd)
 {
-       spin_lock(&ds->hp_lock);
+       mutex_lock(&ds->hp_lock);
        list_del(&dd->hotplug_list);
-       spin_unlock(&ds->hp_lock);
+       mutex_unlock(&ds->hp_lock);
 }
 
 /**
@@ -296,7 +299,7 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
 {
        struct dock_dependent_device *dd;
 
-       spin_lock(&ds->hp_lock);
+       mutex_lock(&ds->hp_lock);
 
        /*
         * First call driver specific hotplug functions
@@ -318,15 +321,17 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
                else
                        dock_create_acpi_device(dd->handle);
        }
-       spin_unlock(&ds->hp_lock);
+       mutex_unlock(&ds->hp_lock);
 }
 
 static void dock_event(struct dock_station *ds, u32 event, int num)
 {
+       struct device *dev = &dock_device.dev;
        /*
-        * we don't do events until someone tells me that
-        * they would like to have them.
+        * Indicate that the status of the dock station has
+        * changed.
         */
+       kobject_uevent(&dev->kobj, KOBJ_CHANGE);
 }
 
 /**
@@ -441,6 +446,9 @@ static int dock_in_progress(struct dock_station *ds)
  */
 int register_dock_notifier(struct notifier_block *nb)
 {
+       if (!dock_station)
+               return -ENODEV;
+
        return atomic_notifier_chain_register(&dock_notifier_list, nb);
 }
 
@@ -452,6 +460,9 @@ EXPORT_SYMBOL_GPL(register_dock_notifier);
  */
 void unregister_dock_notifier(struct notifier_block *nb)
 {
+       if (!dock_station)
+               return;
+
        atomic_notifier_chain_unregister(&dock_notifier_list, nb);
 }
 
@@ -511,6 +522,37 @@ void unregister_hotplug_dock_device(acpi_handle handle)
 
 EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
 
+/**
+ * handle_eject_request - handle an undock request checking for error conditions
+ *
+ * Check to make sure the dock device is still present, then undock and
+ * hotremove all the devices that may need removing.
+ */
+static int handle_eject_request(struct dock_station *ds, u32 event)
+{
+       if (!dock_present(ds))
+               return -ENODEV;
+
+       if (dock_in_progress(ds))
+               return -EBUSY;
+
+       /*
+        * here we need to generate the undock
+        * event prior to actually doing the undock
+        * so that the device struct still exists.
+        */
+       dock_event(ds, event, UNDOCK_EVENT);
+       hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
+       undock(ds);
+       eject_dock(ds);
+       if (dock_present(ds)) {
+               printk(KERN_ERR PREFIX "Unable to undock!\n");
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
 /**
  * dock_notify - act upon an acpi dock notification
  * @handle: the dock station handle
@@ -519,13 +561,11 @@ EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
  *
  * If we are notified to dock, then check to see if the dock is
  * present and then dock.  Notify all drivers of the dock event,
- * and then hotplug and devices that may need hotplugging.  For undock
- * check to make sure the dock device is still present, then undock
- * and hotremove all the devices that may need removing.
+ * and then hotplug and devices that may need hotplugging.
  */
 static void dock_notify(acpi_handle handle, u32 event, void *data)
 {
-       struct dock_station *ds = (struct dock_station *)data;
+       struct dock_station *ds = data;
 
        switch (event) {
        case ACPI_NOTIFY_BUS_CHECK:
@@ -553,19 +593,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
         * to the driver who wish to hotplug.
          */
        case ACPI_NOTIFY_EJECT_REQUEST:
-               if (!dock_in_progress(ds) && dock_present(ds)) {
-                       /*
-                        * here we need to generate the undock
-                        * event prior to actually doing the undock
-                        * so that the device struct still exists.
-                        */
-                       dock_event(ds, event, UNDOCK_EVENT);
-                       hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
-                       undock(ds);
-                       eject_dock(ds);
-                       if (dock_present(ds))
-                               printk(KERN_ERR PREFIX "Unable to undock!\n");
-               }
+               handle_eject_request(ds, event);
                break;
        default:
                printk(KERN_ERR PREFIX "Unknown dock event %d\n", event);
@@ -588,7 +616,7 @@ find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
        acpi_status status;
        acpi_handle tmp;
-       struct dock_station *ds = (struct dock_station *)context;
+       struct dock_station *ds = context;
        struct dock_dependent_device *dd;
 
        status = acpi_bus_get_ejd(handle, &tmp);
@@ -604,6 +632,33 @@ find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv)
        return AE_OK;
 }
 
+/*
+ * show_docked - read method for "docked" file in sysfs
+ */
+static ssize_t show_docked(struct device *dev,
+                          struct device_attribute *attr, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station));
+
+}
+DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
+
+/*
+ * write_undock - write method for "undock" file in sysfs
+ */
+static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       int ret;
+
+       if (!count)
+               return -EINVAL;
+
+       ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST);
+       return ret ? ret: count;
+}
+DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
+
 /**
  * dock_add - add a new dock station
  * @handle: the dock station handle
@@ -626,9 +681,33 @@ static int dock_add(acpi_handle handle)
        INIT_LIST_HEAD(&dock_station->dependent_devices);
        INIT_LIST_HEAD(&dock_station->hotplug_devices);
        spin_lock_init(&dock_station->dd_lock);
-       spin_lock_init(&dock_station->hp_lock);
+       mutex_init(&dock_station->hp_lock);
        ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
 
+       /* initialize platform device stuff */
+       dock_device.name = dock_device_name;
+       ret = platform_device_register(&dock_device);
+       if (ret) {
+               printk(KERN_ERR PREFIX "Error %d registering dock device\n", ret);
+               kfree(dock_station);
+               return ret;
+       }
+       ret = device_create_file(&dock_device.dev, &dev_attr_docked);
+       if (ret) {
+               printk("Error %d adding sysfs file\n", ret);
+               platform_device_unregister(&dock_device);
+               kfree(dock_station);
+               return ret;
+       }
+       ret = device_create_file(&dock_device.dev, &dev_attr_undock);
+       if (ret) {
+               printk("Error %d adding sysfs file\n", ret);
+               device_remove_file(&dock_device.dev, &dev_attr_docked);
+               platform_device_unregister(&dock_device);
+               kfree(dock_station);
+               return ret;
+       }
+
        /* Find dependent devices */
        acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
                            ACPI_UINT32_MAX, find_dock_devices, dock_station,
@@ -638,7 +717,8 @@ static int dock_add(acpi_handle handle)
        dd = alloc_dock_dependent_device(handle);
        if (!dd) {
                kfree(dock_station);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto dock_add_err_unregister;
        }
        add_dock_dependent_device(dock_station, dd);
 
@@ -658,8 +738,12 @@ static int dock_add(acpi_handle handle)
        return 0;
 
 dock_add_err:
-       kfree(dock_station);
        kfree(dd);
+dock_add_err_unregister:
+       device_remove_file(&dock_device.dev, &dev_attr_docked);
+       device_remove_file(&dock_device.dev, &dev_attr_undock);
+       platform_device_unregister(&dock_device);
+       kfree(dock_station);
        return ret;
 }
 
@@ -686,6 +770,11 @@ static int dock_remove(void)
        if (ACPI_FAILURE(status))
                printk(KERN_ERR "Error removing notify handler\n");
 
+       /* cleanup sysfs */
+       device_remove_file(&dock_device.dev, &dev_attr_docked);
+       device_remove_file(&dock_device.dev, &dev_attr_undock);
+       platform_device_unregister(&dock_device);
+
        /* free dock station memory */
        kfree(dock_station);
        return 0;
@@ -703,7 +792,7 @@ static int dock_remove(void)
 static acpi_status
 find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
-       int *count = (int *)context;
+       int *count = context;
        acpi_status status = AE_OK;
 
        if (is_dock(handle)) {
@@ -726,7 +815,7 @@ static int __init dock_init(void)
                            ACPI_UINT32_MAX, find_dock, &num, NULL);
 
        if (!num)
-               return -ENODEV;
+               printk(KERN_INFO "No dock devices found.\n");
 
        return 0;
 }
index e6d4b084dca2eeb40213074998ccdfde52278260..08c12588af6910cf98d236823463dc8fb105eb01 100644 (file)
@@ -45,35 +45,34 @@ ACPI_MODULE_NAME("acpi_ec")
 #define ACPI_EC_DRIVER_NAME            "ACPI Embedded Controller Driver"
 #define ACPI_EC_DEVICE_NAME            "Embedded Controller"
 #define ACPI_EC_FILE_INFO              "info"
-
+#undef PREFIX
+#define PREFIX                         "ACPI: EC: "
 /* EC status register */
 #define ACPI_EC_FLAG_OBF       0x01    /* Output buffer full */
 #define ACPI_EC_FLAG_IBF       0x02    /* Input buffer full */
 #define ACPI_EC_FLAG_BURST     0x10    /* burst mode */
 #define ACPI_EC_FLAG_SCI       0x20    /* EC-SCI occurred */
-
 /* EC commands */
-#define ACPI_EC_COMMAND_READ   0x80
-#define ACPI_EC_COMMAND_WRITE  0x81
-#define ACPI_EC_BURST_ENABLE   0x82
-#define ACPI_EC_BURST_DISABLE  0x83
-#define ACPI_EC_COMMAND_QUERY  0x84
-
+enum ec_command {
+       ACPI_EC_COMMAND_READ = 0x80,
+       ACPI_EC_COMMAND_WRITE = 0x81,
+       ACPI_EC_BURST_ENABLE = 0x82,
+       ACPI_EC_BURST_DISABLE = 0x83,
+       ACPI_EC_COMMAND_QUERY = 0x84,
+};
 /* EC events */
-enum {
+enum ec_event {
        ACPI_EC_EVENT_OBF_1 = 1,        /* Output buffer full */
-       ACPI_EC_EVENT_IBF_0,            /* Input buffer empty */
+       ACPI_EC_EVENT_IBF_0,    /* Input buffer empty */
 };
 
-#define ACPI_EC_DELAY          50      /* Wait 50ms max. during EC ops */
+#define ACPI_EC_DELAY          500     /* Wait 500ms max. during EC ops */
 #define ACPI_EC_UDELAY_GLK     1000    /* Wait 1ms max. to get global lock */
-#define ACPI_EC_UDELAY         100     /* Poll @ 100us increments */
-#define ACPI_EC_UDELAY_COUNT   1000    /* Wait 10ms max. during EC ops */
 
-enum {
-       EC_INTR = 1,    /* Output buffer full */
-       EC_POLL,        /* Input buffer empty */
-};
+static enum ec_mode {
+       EC_INTR = 1,            /* Output buffer full */
+       EC_POLL,                /* Input buffer empty */
+} acpi_ec_mode = EC_INTR;
 
 static int acpi_ec_remove(struct acpi_device *device, int type);
 static int acpi_ec_start(struct acpi_device *device);
@@ -93,22 +92,21 @@ static struct acpi_driver acpi_ec_driver = {
 };
 
 /* If we find an EC via the ECDT, we need to keep a ptr to its context */
-struct acpi_ec {
+static struct acpi_ec {
        acpi_handle handle;
        unsigned long uid;
-       unsigned long gpe_bit;
+       unsigned long gpe;
        unsigned long command_addr;
        unsigned long data_addr;
        unsigned long global_lock;
-       struct semaphore sem;
-       unsigned int expect_event;
+       struct mutex lock;
+       atomic_t query_pending;
        atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */
        wait_queue_head_t wait;
 } *ec_ecdt;
 
 /* External interfaces use first EC only, so remember */
 static struct acpi_device *first_ec;
-static int acpi_ec_mode = EC_INTR;
 
 /* --------------------------------------------------------------------------
                              Transaction Management
@@ -134,54 +132,41 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
        outb(data, ec->data_addr);
 }
 
-static int acpi_ec_check_status(u8 status, u8 event)
+static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
 {
-       switch (event) {
-       case ACPI_EC_EVENT_OBF_1:
+       u8 status = acpi_ec_read_status(ec);
+
+       if (event == ACPI_EC_EVENT_OBF_1) {
                if (status & ACPI_EC_FLAG_OBF)
                        return 1;
-               break;
-       case ACPI_EC_EVENT_IBF_0:
+       } else if (event == ACPI_EC_EVENT_IBF_0) {
                if (!(status & ACPI_EC_FLAG_IBF))
                        return 1;
-               break;
-       default:
-               break;
        }
 
        return 0;
 }
 
-static int acpi_ec_wait(struct acpi_ec *ec, u8 event)
+static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event)
 {
-       int i = (acpi_ec_mode == EC_POLL) ? ACPI_EC_UDELAY_COUNT : 0;
-       long time_left;
-
-       ec->expect_event = event;
-       if (acpi_ec_check_status(acpi_ec_read_status(ec), event)) {
-               ec->expect_event = 0;
-               return 0;
-       }
-
-       do {
-               if (acpi_ec_mode == EC_POLL) {
-                       udelay(ACPI_EC_UDELAY);
-               } else {
-                       time_left = wait_event_timeout(ec->wait,
-                                   !ec->expect_event,
-                                   msecs_to_jiffies(ACPI_EC_DELAY));
-                       if (time_left > 0) {
-                               ec->expect_event = 0;
+       if (acpi_ec_mode == EC_POLL) {
+               unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
+               while (time_before(jiffies, delay)) {
+                       if (acpi_ec_check_status(ec, event))
                                return 0;
-                       }
                }
-               if (acpi_ec_check_status(acpi_ec_read_status(ec), event)) {
-                       ec->expect_event = 0;
+       } else {
+               if (wait_event_timeout(ec->wait,
+                                      acpi_ec_check_status(ec, event),
+                                      msecs_to_jiffies(ACPI_EC_DELAY)) ||
+                   acpi_ec_check_status(ec, event)) {
                        return 0;
+               } else {
+                       printk(KERN_ERR PREFIX "acpi_ec_wait timeout,"
+                              " status = %d, expect_event = %d\n",
+                              acpi_ec_read_status(ec), event);
                }
-       } while (--i > 0);
-
-       ec->expect_event = 0;
+       }
 
        return -ETIME;
 }
@@ -196,7 +181,6 @@ int acpi_ec_enter_burst_mode(struct acpi_ec *ec)
        u8 tmp = 0;
        u8 status = 0;
 
-
        status = acpi_ec_read_status(ec);
        if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) {
                status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
@@ -212,7 +196,7 @@ int acpi_ec_enter_burst_mode(struct acpi_ec *ec)
 
        atomic_set(&ec->leaving_burst, 0);
        return 0;
-  end:
+      end:
        ACPI_EXCEPTION((AE_INFO, status, "EC wait, burst mode"));
        return -1;
 }
@@ -221,58 +205,68 @@ int acpi_ec_leave_burst_mode(struct acpi_ec *ec)
 {
        u8 status = 0;
 
-
        status = acpi_ec_read_status(ec);
-       if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)){
+       if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)) {
                status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
-               if(status)
+               if (status)
                        goto end;
                acpi_ec_write_cmd(ec, ACPI_EC_BURST_DISABLE);
                acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
        }
        atomic_set(&ec->leaving_burst, 1);
        return 0;
-  end:
+      end:
        ACPI_EXCEPTION((AE_INFO, status, "EC leave burst mode"));
        return -1;
 }
-#endif /* ACPI_FUTURE_USAGE */
+#endif                         /* ACPI_FUTURE_USAGE */
 
 static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
-                                       const u8 *wdata, unsigned wdata_len,
-                                       u8 *rdata, unsigned rdata_len)
+                                       const u8 * wdata, unsigned wdata_len,
+                                       u8 * rdata, unsigned rdata_len)
 {
-       int result;
+       int result = 0;
 
        acpi_ec_write_cmd(ec, command);
 
-       for (; wdata_len > 0; wdata_len --) {
+       for (; wdata_len > 0; --wdata_len) {
                result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
-               if (result)
-                       return result;
+               if (result) {
+                       printk(KERN_ERR PREFIX
+                              "write_cmd timeout, command = %d\n", command);
+                       goto end;
+               }
                acpi_ec_write_data(ec, *(wdata++));
        }
 
-       if (command == ACPI_EC_COMMAND_WRITE) {
+       if (!rdata_len) {
                result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
-               if (result)
-                       return result;
+               if (result) {
+                       printk(KERN_ERR PREFIX
+                              "finish-write timeout, command = %d\n", command);
+                       goto end;
+               }
+       } else if (command == ACPI_EC_COMMAND_QUERY) {
+               atomic_set(&ec->query_pending, 0);
        }
 
-       for (; rdata_len > 0; rdata_len --) {
+       for (; rdata_len > 0; --rdata_len) {
                result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1);
-               if (result)
-                       return result;
+               if (result) {
+                       printk(KERN_ERR PREFIX "read timeout, command = %d\n",
+                              command);
+                       goto end;
+               }
 
                *(rdata++) = acpi_ec_read_data(ec);
        }
-
-       return 0;
+      end:
+       return result;
 }
 
 static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
-                               const u8 *wdata, unsigned wdata_len,
-                               u8 *rdata, unsigned rdata_len)
+                              const u8 * wdata, unsigned wdata_len,
+                              u8 * rdata, unsigned rdata_len)
 {
        int status;
        u32 glk;
@@ -280,36 +274,40 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
        if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata))
                return -EINVAL;
 
-        if (rdata)
-                memset(rdata, 0, rdata_len);
+       if (rdata)
+               memset(rdata, 0, rdata_len);
 
+       mutex_lock(&ec->lock);
        if (ec->global_lock) {
                status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
                if (ACPI_FAILURE(status))
                        return -ENODEV;
        }
-       down(&ec->sem);
+
+       /* Make sure GPE is enabled before doing transaction */
+       acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
 
        status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
        if (status) {
-               printk(KERN_DEBUG PREFIX "read EC, IB not empty\n");
+               printk(KERN_DEBUG PREFIX
+                      "input buffer is not empty, aborting transaction\n");
                goto end;
        }
 
-        status = acpi_ec_transaction_unlocked(ec, command,
-                                              wdata, wdata_len,
-                                              rdata, rdata_len);
+       status = acpi_ec_transaction_unlocked(ec, command,
+                                             wdata, wdata_len,
+                                             rdata, rdata_len);
 
-end:
-       up(&ec->sem);
+      end:
 
        if (ec->global_lock)
                acpi_release_global_lock(glk);
+       mutex_unlock(&ec->lock);
 
        return status;
 }
 
-static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data)
+static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
 {
        int result;
        u8 d;
@@ -322,15 +320,15 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data)
 
 static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
 {
-        u8 wdata[2] = { address, data };
-        return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE,
+       u8 wdata[2] = { address, data };
+       return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE,
                                   wdata, 2, NULL, 0);
 }
 
 /*
  * Externally callable EC access functions. For now, assume 1 EC only
  */
-int ec_read(u8 addr, u8 *val)
+int ec_read(u8 addr, u8 * val)
 {
        struct acpi_ec *ec;
        int err;
@@ -369,9 +367,9 @@ int ec_write(u8 addr, u8 val)
 
 EXPORT_SYMBOL(ec_write);
 
-extern int ec_transaction(u8 command,
-                          const u8 *wdata, unsigned wdata_len,
-                          u8 *rdata, unsigned rdata_len)
+int ec_transaction(u8 command,
+                         const u8 * wdata, unsigned wdata_len,
+                         u8 * rdata, unsigned rdata_len)
 {
        struct acpi_ec *ec;
 
@@ -386,65 +384,49 @@ extern int ec_transaction(u8 command,
 
 EXPORT_SYMBOL(ec_transaction);
 
-static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
+static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
 {
        int result;
-        u8 d;
+       u8 d;
 
-        if (!ec || !data)
-                return -EINVAL;
+       if (!ec || !data)
+               return -EINVAL;
 
-        /*
-         * Query the EC to find out which _Qxx method we need to evaluate.
-         * Note that successful completion of the query causes the ACPI_EC_SCI
-         * bit to be cleared (and thus clearing the interrupt source).
-         */
+       /*
+        * Query the EC to find out which _Qxx method we need to evaluate.
+        * Note that successful completion of the query causes the ACPI_EC_SCI
+        * bit to be cleared (and thus clearing the interrupt source).
+        */
 
-        result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1);
-        if (result)
-                return result;
+       result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1);
+       if (result)
+               return result;
 
-        if (!d)
-                return -ENODATA;
+       if (!d)
+               return -ENODATA;
 
-        *data = d;
-        return 0;
+       *data = d;
+       return 0;
 }
 
 /* --------------------------------------------------------------------------
                                 Event Management
    -------------------------------------------------------------------------- */
 
-struct acpi_ec_query_data {
-       acpi_handle handle;
-       u8 data;
-};
-
 static void acpi_ec_gpe_query(void *ec_cxt)
 {
        struct acpi_ec *ec = (struct acpi_ec *)ec_cxt;
        u8 value = 0;
-       static char object_name[8];
+       char object_name[8];
 
-       if (!ec)
-               goto end;
-
-       value = acpi_ec_read_status(ec);
-
-       if (!(value & ACPI_EC_FLAG_SCI))
-               goto end;
-
-       if (acpi_ec_query(ec, &value))
-               goto end;
+       if (!ec || acpi_ec_query(ec, &value))
+               return;
 
        snprintf(object_name, 8, "_Q%2.2X", value);
 
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name));
+       printk(KERN_INFO PREFIX "evaluating %s\n", object_name);
 
        acpi_evaluate_object(ec->handle, object_name, NULL, NULL);
-
-      end:
-       acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
 }
 
 static u32 acpi_ec_gpe_handler(void *data)
@@ -453,22 +435,18 @@ static u32 acpi_ec_gpe_handler(void *data)
        u8 value;
        struct acpi_ec *ec = (struct acpi_ec *)data;
 
-       acpi_clear_gpe(NULL, ec->gpe_bit, ACPI_ISR);
-       value = acpi_ec_read_status(ec);
-
        if (acpi_ec_mode == EC_INTR) {
-               if (acpi_ec_check_status(value, ec->expect_event)) {
-                       ec->expect_event = 0;
-                       wake_up(&ec->wait);
-               }
+               wake_up(&ec->wait);
        }
 
-       if (value & ACPI_EC_FLAG_SCI) {
-               status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec);
-               return status == AE_OK ?
-                   ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
+       value = acpi_ec_read_status(ec);
+       if ((value & ACPI_EC_FLAG_SCI) && !atomic_read(&ec->query_pending)) {
+               atomic_set(&ec->query_pending, 1);
+               status =
+                   acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query,
+                                   ec);
        }
-       acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_ISR);
+
        return status == AE_OK ?
            ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
 }
@@ -504,7 +482,6 @@ acpi_ec_space_handler(u32 function,
        acpi_integer f_v = 0;
        int i = 0;
 
-
        if ((address > 0xFF) || !value || !handler_context)
                return AE_BAD_PARAMETER;
 
@@ -518,7 +495,7 @@ acpi_ec_space_handler(u32 function,
        switch (function) {
        case ACPI_READ:
                temp = 0;
-               result = acpi_ec_read(ec, (u8) address, (u8 *) &temp);
+               result = acpi_ec_read(ec, (u8) address, (u8 *) & temp);
                break;
        case ACPI_WRITE:
                result = acpi_ec_write(ec, (u8) address, (u8) temp);
@@ -571,18 +548,15 @@ static int acpi_ec_read_info(struct seq_file *seq, void *offset)
 {
        struct acpi_ec *ec = (struct acpi_ec *)seq->private;
 
-
        if (!ec)
                goto end;
 
-       seq_printf(seq, "gpe bit:                 0x%02x\n",
-                  (u32) ec->gpe_bit);
+       seq_printf(seq, "gpe:                 0x%02x\n", (u32) ec->gpe);
        seq_printf(seq, "ports:                   0x%02x, 0x%02x\n",
-                  (u32) ec->command_addr,
-                  (u32) ec->data_addr);
+                  (u32) ec->command_addr, (u32) ec->data_addr);
        seq_printf(seq, "use global lock:         %s\n",
                   ec->global_lock ? "yes" : "no");
-       acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+       acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
 
       end:
        return 0;
@@ -605,7 +579,6 @@ static int acpi_ec_add_fs(struct acpi_device *device)
 {
        struct proc_dir_entry *entry = NULL;
 
-
        if (!acpi_device_dir(device)) {
                acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
                                                     acpi_ec_dir);
@@ -648,7 +621,6 @@ static int acpi_ec_add(struct acpi_device *device)
        acpi_status status = AE_OK;
        struct acpi_ec *ec = NULL;
 
-
        if (!device)
                return -EINVAL;
 
@@ -659,7 +631,8 @@ static int acpi_ec_add(struct acpi_device *device)
 
        ec->handle = device->handle;
        ec->uid = -1;
-       init_MUTEX(&ec->sem);
+       mutex_init(&ec->lock);
+       atomic_set(&ec->query_pending, 0);
        if (acpi_ec_mode == EC_INTR) {
                atomic_set(&ec->leaving_burst, 1);
                init_waitqueue_head(&ec->wait);
@@ -669,8 +642,7 @@ static int acpi_ec_add(struct acpi_device *device)
        acpi_driver_data(device) = ec;
 
        /* Use the global lock for all EC transactions? */
-       acpi_evaluate_integer(ec->handle, "_GLK", NULL,
-                             &ec->global_lock);
+       acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock);
 
        /* XXX we don't test uids, because on some boxes ecdt uid = 0, see:
           http://bugzilla.kernel.org/show_bug.cgi?id=6111 */
@@ -679,7 +651,7 @@ static int acpi_ec_add(struct acpi_device *device)
                                                  ACPI_ADR_SPACE_EC,
                                                  &acpi_ec_space_handler);
 
-               acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit,
+               acpi_remove_gpe_handler(NULL, ec_ecdt->gpe,
                                        &acpi_ec_gpe_handler);
 
                kfree(ec_ecdt);
@@ -687,11 +659,10 @@ static int acpi_ec_add(struct acpi_device *device)
 
        /* Get GPE bit assignment (EC events). */
        /* TODO: Add support for _GPE returning a package */
-       status =
-           acpi_evaluate_integer(ec->handle, "_GPE", NULL,
-                                 &ec->gpe_bit);
+       status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe);
        if (ACPI_FAILURE(status)) {
-               ACPI_EXCEPTION((AE_INFO, status, "Obtaining GPE bit assignment"));
+               ACPI_EXCEPTION((AE_INFO, status,
+                               "Obtaining GPE bit assignment"));
                result = -ENODEV;
                goto end;
        }
@@ -701,13 +672,13 @@ static int acpi_ec_add(struct acpi_device *device)
                goto end;
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s [%s] (gpe %d) interrupt mode.",
-              acpi_device_name(device), acpi_device_bid(device),
-              (u32) ec->gpe_bit));
+                         acpi_device_name(device), acpi_device_bid(device),
+                         (u32) ec->gpe));
 
        if (!first_ec)
                first_ec = device;
 
-  end:
+      end:
        if (result)
                kfree(ec);
 
@@ -718,7 +689,6 @@ static int acpi_ec_remove(struct acpi_device *device, int type)
 {
        struct acpi_ec *ec = NULL;
 
-
        if (!device)
                return -EINVAL;
 
@@ -761,7 +731,6 @@ static int acpi_ec_start(struct acpi_device *device)
        acpi_status status = AE_OK;
        struct acpi_ec *ec = NULL;
 
-
        if (!device)
                return -EINVAL;
 
@@ -782,27 +751,26 @@ static int acpi_ec_start(struct acpi_device *device)
        }
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx",
-                         ec->gpe_bit, ec->command_addr, ec->data_addr));
+                         ec->gpe, ec->command_addr, ec->data_addr));
 
        /*
         * Install GPE handler
         */
-       status = acpi_install_gpe_handler(NULL, ec->gpe_bit,
+       status = acpi_install_gpe_handler(NULL, ec->gpe,
                                          ACPI_GPE_EDGE_TRIGGERED,
                                          &acpi_ec_gpe_handler, ec);
        if (ACPI_FAILURE(status)) {
                return -ENODEV;
        }
-       acpi_set_gpe_type(NULL, ec->gpe_bit, ACPI_GPE_TYPE_RUNTIME);
-       acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+       acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
+       acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
 
        status = acpi_install_address_space_handler(ec->handle,
                                                    ACPI_ADR_SPACE_EC,
                                                    &acpi_ec_space_handler,
                                                    &acpi_ec_space_setup, ec);
        if (ACPI_FAILURE(status)) {
-               acpi_remove_gpe_handler(NULL, ec->gpe_bit,
-                                       &acpi_ec_gpe_handler);
+               acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler);
                return -ENODEV;
        }
 
@@ -814,7 +782,6 @@ static int acpi_ec_stop(struct acpi_device *device, int type)
        acpi_status status = AE_OK;
        struct acpi_ec *ec = NULL;
 
-
        if (!device)
                return -EINVAL;
 
@@ -826,9 +793,7 @@ static int acpi_ec_stop(struct acpi_device *device, int type)
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
-       status =
-           acpi_remove_gpe_handler(NULL, ec->gpe_bit,
-                                   &acpi_ec_gpe_handler);
+       status = acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler);
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
@@ -841,7 +806,7 @@ acpi_fake_ecdt_callback(acpi_handle handle,
 {
        acpi_status status;
 
-       init_MUTEX(&ec_ecdt->sem);
+       mutex_init(&ec_ecdt->lock);
        if (acpi_ec_mode == EC_INTR) {
                init_waitqueue_head(&ec_ecdt->wait);
        }
@@ -853,16 +818,15 @@ acpi_fake_ecdt_callback(acpi_handle handle,
        ec_ecdt->uid = -1;
        acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid);
 
-       status =
-           acpi_evaluate_integer(handle, "_GPE", NULL,
-                                 &ec_ecdt->gpe_bit);
+       status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->gpe);
        if (ACPI_FAILURE(status))
                return status;
        ec_ecdt->global_lock = TRUE;
        ec_ecdt->handle = handle;
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx",
-              ec_ecdt->gpe_bit, ec_ecdt->command_addr, ec_ecdt->data_addr));
+                         ec_ecdt->gpe, ec_ecdt->command_addr,
+                         ec_ecdt->data_addr));
 
        return AE_CTRL_TERMINATE;
 }
@@ -901,7 +865,7 @@ static int __init acpi_ec_fake_ecdt(void)
                goto error;
        }
        return 0;
-  error:
+      error:
        return ret;
 }
 
@@ -926,25 +890,24 @@ static int __init acpi_ec_get_real_ecdt(void)
                return -ENOMEM;
        memset(ec_ecdt, 0, sizeof(struct acpi_ec));
 
-       init_MUTEX(&ec_ecdt->sem);
+       mutex_init(&ec_ecdt->lock);
        if (acpi_ec_mode == EC_INTR) {
                init_waitqueue_head(&ec_ecdt->wait);
        }
        ec_ecdt->command_addr = ecdt_ptr->ec_control.address;
        ec_ecdt->data_addr = ecdt_ptr->ec_data.address;
-       ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit;
+       ec_ecdt->gpe = ecdt_ptr->gpe_bit;
        /* use the GL just to be safe */
        ec_ecdt->global_lock = TRUE;
        ec_ecdt->uid = ecdt_ptr->uid;
 
-       status =
-           acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle);
+       status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle);
        if (ACPI_FAILURE(status)) {
                goto error;
        }
 
        return 0;
-  error:
+      error:
        ACPI_EXCEPTION((AE_INFO, status, "Could not use ECDT"));
        kfree(ec_ecdt);
        ec_ecdt = NULL;
@@ -970,14 +933,14 @@ int __init acpi_ec_ecdt_probe(void)
        /*
         * Install GPE handler
         */
-       status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe_bit,
+       status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe,
                                          ACPI_GPE_EDGE_TRIGGERED,
                                          &acpi_ec_gpe_handler, ec_ecdt);
        if (ACPI_FAILURE(status)) {
                goto error;
        }
-       acpi_set_gpe_type(NULL, ec_ecdt->gpe_bit, ACPI_GPE_TYPE_RUNTIME);
-       acpi_enable_gpe(NULL, ec_ecdt->gpe_bit, ACPI_NOT_ISR);
+       acpi_set_gpe_type(NULL, ec_ecdt->gpe, ACPI_GPE_TYPE_RUNTIME);
+       acpi_enable_gpe(NULL, ec_ecdt->gpe, ACPI_NOT_ISR);
 
        status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
                                                    ACPI_ADR_SPACE_EC,
@@ -985,7 +948,7 @@ int __init acpi_ec_ecdt_probe(void)
                                                    &acpi_ec_space_setup,
                                                    ec_ecdt);
        if (ACPI_FAILURE(status)) {
-               acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit,
+               acpi_remove_gpe_handler(NULL, ec_ecdt->gpe,
                                        &acpi_ec_gpe_handler);
                goto error;
        }
@@ -1004,7 +967,6 @@ static int __init acpi_ec_init(void)
 {
        int result = 0;
 
-
        if (acpi_disabled)
                return 0;
 
@@ -1057,7 +1019,8 @@ static int __init acpi_ec_set_intr_mode(char *str)
                acpi_ec_mode = EC_POLL;
        }
        acpi_ec_driver.ops.add = acpi_ec_add;
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "EC %s mode.\n", intr ? "interrupt" : "polling"));
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "EC %s mode.\n",
+                         intr ? "interrupt" : "polling"));
 
        return 1;
 }
index ee2a10bf907745ceef823a5d9a2ecd637ae51b2c..bf63edc6608d7732cdec84a92868a71a5277be81 100644 (file)
@@ -331,7 +331,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context)
 static u32 acpi_ev_global_lock_handler(void *context)
 {
        u8 acquired = FALSE;
-       acpi_status status;
 
        /*
         * Attempt to get the lock
index 3a39c2e8e104a001c22f3cc18adab681b598497d..bf90f04f2c605218effa13adf83273d056903e37 100644 (file)
@@ -266,10 +266,10 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
             walk_state->thread->thread_id)
            && (obj_desc->mutex.os_mutex != ACPI_GLOBAL_LOCK)) {
                ACPI_ERROR((AE_INFO,
-                           "Thread %X cannot release Mutex [%4.4s] acquired by thread %X",
-                           (u32) walk_state->thread->thread_id,
+                           "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX",
+                           (unsigned long)walk_state->thread->thread_id,
                            acpi_ut_get_node_name(obj_desc->mutex.node),
-                           (u32) obj_desc->mutex.owner_thread->thread_id));
+                           (unsigned long)obj_desc->mutex.owner_thread->thread_id));
                return_ACPI_STATUS(AE_AML_NOT_OWNER);
        }
 
index 045c89477e59b2929f125ac536226928e949a73a..c413e69fea8eb25633d4754ce69b9cd3dd9cf041 100644 (file)
@@ -99,8 +99,8 @@ acpi_fan_write_state(struct file *file, const char __user * buffer,
                     size_t count, loff_t * ppos)
 {
        int result = 0;
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       struct acpi_fan *fan = (struct acpi_fan *)m->private;
+       struct seq_file *m = file->private_data;
+       struct acpi_fan *fan = m->private;
        char state_string[12] = { '\0' };
 
 
@@ -229,7 +229,7 @@ static int acpi_fan_remove(struct acpi_device *device, int type)
        if (!device || !acpi_driver_data(device))
                return -EINVAL;
 
-       fan = (struct acpi_fan *)acpi_driver_data(device);
+       fan = acpi_driver_data(device);
 
        acpi_fan_remove_fs(device);
 
index a2f46d587d55d77310c96694b706a7d6b18b4643..8a0324b43e53869adcf9f98a29c513a38b1c2d15 100644 (file)
@@ -96,7 +96,7 @@ struct acpi_find_pci_root {
 static acpi_status
 do_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
 {
-       unsigned long *busnr = (unsigned long *)data;
+       unsigned long *busnr = data;
        struct acpi_resource_address64 address;
 
        if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 &&
@@ -189,8 +189,12 @@ find_pci_rootbridge(acpi_handle handle, u32 lvl, void *context, void **rv)
        bus = tmp;
 
        if (seg == find->seg && bus == find->bus)
+       {
                find->handle = handle;
-       status = AE_OK;
+               status = AE_CTRL_TERMINATE;
+       }
+       else
+               status = AE_OK;
       exit:
        kfree(buffer.pointer);
        return status;
@@ -217,7 +221,7 @@ do_acpi_find_child(acpi_handle handle, u32 lvl, void *context, void **rv)
        acpi_status status;
        struct acpi_device_info *info;
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-       struct acpi_find_child *find = (struct acpi_find_child *)context;
+       struct acpi_find_child *find = context;
 
        status = acpi_get_object_info(handle, &buffer);
        if (ACPI_SUCCESS(status)) {
index 1ba2db6718652aae3874c9bdf8ceae167fc990e4..8edfb92f7ede258ef665aa7dabfc1aeea73b87ab 100644 (file)
@@ -265,8 +265,7 @@ static char *format_result(union acpi_object *object)
 
 static int hotkey_polling_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_polling_hotkey *poll_hotkey =
-           (struct acpi_polling_hotkey *)seq->private;
+       struct acpi_polling_hotkey *poll_hotkey = seq->private;
        char *buf;
 
 
@@ -577,7 +576,7 @@ init_poll_hotkey_device(union acpi_hotkey *key, char **config_entry,
        if (ACPI_FAILURE(status))
                goto do_fail_zero;
        key->poll_hotkey.poll_result =
-           (union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL);
+           kmalloc(sizeof(union acpi_object), GFP_KERNEL);
        if (!key->poll_hotkey.poll_result)
                goto do_fail_zero;
        return AE_OK;
index 6342e612c203726514be32d5ab4e97ecf579f552..82e3e64483fbe8caff40d2590fc1235f09df78ba 100644 (file)
@@ -393,7 +393,7 @@ static void __exit acpi_ec_hc_exit(void)
 
 struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device)
 {
-       return ((struct acpi_ec_hc *)acpi_driver_data(device->parent));
+       return acpi_driver_data(device->parent);
 }
 
 EXPORT_SYMBOL(acpi_get_ec_hc);
index 003a9876c9683bee7de662e5959f06ec42ed91f9..130cc8c37e226a227d1182cb77efe2678207f752 100644 (file)
@@ -3,6 +3,7 @@
  *
  *
  *  Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.net>
+ *  Copyright (C) 2006 Henrique de Moraes Holschuh <hmh@hmh.eng.br>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#define IBM_VERSION "0.12a"
+#define IBM_VERSION "0.13"
 
 /*
  *  Changelog:
+ *
+ *  2006-11-22 0.13    new maintainer
+ *                     changelog now lives in git commit history, and will
+ *                     not be updated further in-file.
  *  
  *  2005-08-17  0.12   fix compilation on 2.6.13-rc kernels
  *  2005-03-17 0.11    support for 600e, 770x
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
+#include <linux/string.h>
+
 #include <linux/proc_fs.h>
+#include <linux/backlight.h>
 #include <asm/uaccess.h>
 
+#include <linux/dmi.h>
+#include <linux/jiffies.h>
+#include <linux/workqueue.h>
+
 #include <acpi/acpi_drivers.h>
 #include <acpi/acnamesp.h>
 
 #define IBM_FILE "ibm_acpi"
 #define IBM_URL "http://ibm-acpi.sf.net/"
 
-MODULE_AUTHOR("Borislav Deianov");
+MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh");
 MODULE_DESCRIPTION(IBM_DESC);
 MODULE_VERSION(IBM_VERSION);
 MODULE_LICENSE("GPL");
@@ -116,28 +128,6 @@ static acpi_handle root_handle = NULL;
        static char        *object##_path;                      \
        static char        *object##_paths[] = { paths }
 
-/*
- * The following models are supported to various degrees:
- *
- * 570, 600e, 600x, 770e, 770x
- * A20m, A21e, A21m, A21p, A22p, A30, A30p, A31, A31p
- * G40, G41
- * R30, R31, R32, R40, R40e, R50, R50e, R50p, R51
- * T20, T21, T22, T23, T30, T40, T40p, T41, T41p, T42, T42p, T43
- * X20, X21, X22, X23, X24, X30, X31, X40
- *
- * The following models have no supported features:
- *
- * 240, 240x, i1400
- *
- * Still missing DSDTs for the following models:
- *
- * A20p, A22e, A22m
- * R52
- * S31
- * T43p
- */
-
 IBM_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0",     /* 240, 240x */
           "\\_SB.PCI.ISA.EC",  /* 570 */
           "\\_SB.PCI0.ISA0.EC0",       /* 600e/x, 770e, 770x */
@@ -167,8 +157,10 @@ IBM_HANDLE(dock, root, "\\_SB.GDCK",       /* X30, X31, X40 */
           "\\_SB.PCI.ISA.SLCE",        /* 570 */
     );                         /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */
 #endif
+#ifdef CONFIG_ACPI_IBM_BAY
 IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST",       /* 570 */
           "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */
+          "\\_SB.PCI0.SATA.SCND.MSTR", /* T60, X60, Z60 */ 
           "\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */
     );                         /* A21e, R30, R31 */
 
@@ -183,6 +175,7 @@ IBM_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV", /* A3x, R32 */
 IBM_HANDLE(bay2_ej, bay2, "_EJ3",      /* 600e/x, 770e, A3x */
           "_EJ0",              /* 770x */
     );                         /* all others */
+#endif
 
 /* don't list other alternatives as we install a notify handler on the 570 */
 IBM_HANDLE(pci, root, "\\_SB.PCI");    /* 570 */
@@ -203,7 +196,7 @@ IBM_HANDLE(led, ec, "SLED", /* 570 */
 IBM_HANDLE(beep, ec, "BEEP");  /* all except R30, R31 */
 IBM_HANDLE(ecrd, ec, "ECRD");  /* 570 */
 IBM_HANDLE(ecwr, ec, "ECWR");  /* 570 */
-IBM_HANDLE(fans, ec, "FANS");  /* X31, X40 */
+IBM_HANDLE(fans, ec, "FANS");  /* X31, X40, X41 */
 
 IBM_HANDLE(gfan, ec, "GFAN",   /* 570 */
           "\\FSPD",            /* 600e/x, 770e, 770x */
@@ -216,6 +209,152 @@ IBM_HANDLE(sfan, ec, "SFAN",      /* 570 */
 #define IBM_HKEY_HID   "IBM0068"
 #define IBM_PCI_HID    "PNP0A03"
 
+enum thermal_access_mode {
+       IBMACPI_THERMAL_NONE = 0,       /* No thermal support */
+       IBMACPI_THERMAL_ACPI_TMP07,     /* Use ACPI TMP0-7 */
+       IBMACPI_THERMAL_ACPI_UPDT,      /* Use ACPI TMP0-7 with UPDT */
+       IBMACPI_THERMAL_TPEC_8,         /* Use ACPI EC regs, 8 sensors */
+       IBMACPI_THERMAL_TPEC_16,        /* Use ACPI EC regs, 16 sensors */
+};
+
+#define IBMACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */
+struct ibm_thermal_sensors_struct {
+       s32 temp[IBMACPI_MAX_THERMAL_SENSORS];
+};
+
+/*
+ * FAN ACCESS MODES
+ *
+ * IBMACPI_FAN_RD_ACPI_GFAN:
+ *     ACPI GFAN method: returns fan level
+ *
+ *     see IBMACPI_FAN_WR_ACPI_SFAN
+ *     EC 0x2f not available if GFAN exists
+ *
+ * IBMACPI_FAN_WR_ACPI_SFAN:
+ *     ACPI SFAN method: sets fan level, 0 (stop) to 7 (max)
+ *
+ *     EC 0x2f might be available *for reading*, but never for writing.
+ *
+ * IBMACPI_FAN_WR_TPEC:
+ *     ThinkPad EC register 0x2f (HFSP): fan control loop mode Supported
+ *     on almost all ThinkPads
+ *
+ *     Fan speed changes of any sort (including those caused by the
+ *     disengaged mode) are usually done slowly by the firmware as the
+ *     maximum ammount of fan duty cycle change per second seems to be
+ *     limited.
+ *
+ *     Reading is not available if GFAN exists.
+ *     Writing is not available if SFAN exists.
+ *
+ *     Bits
+ *      7      automatic mode engaged;
+ *             (default operation mode of the ThinkPad)
+ *             fan level is ignored in this mode.
+ *      6      disengage mode (takes precedence over bit 7);
+ *             not available on all thinkpads.  May disable
+ *             the tachometer, and speeds up fan to 100% duty-cycle,
+ *             which speeds it up far above the standard RPM
+ *             levels.  It is not impossible that it could cause
+ *             hardware damage.
+ *     5-3     unused in some models.  Extra bits for fan level
+ *             in others, but still useless as all values above
+ *             7 map to the same speed as level 7 in these models.
+ *     2-0     fan level (0..7 usually)
+ *                     0x00 = stop
+ *                     0x07 = max (set when temperatures critical)
+ *             Some ThinkPads may have other levels, see
+ *             IBMACPI_FAN_WR_ACPI_FANS (X31/X40/X41)
+ *
+ *     FIRMWARE BUG: on some models, EC 0x2f might not be initialized at
+ *     boot. Apparently the EC does not intialize it, so unless ACPI DSDT
+ *     does so, its initial value is meaningless (0x07).
+ *
+ *     For firmware bugs, refer to:
+ *     http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
+ *
+ *     ----
+ *
+ *     ThinkPad EC register 0x84 (LSB), 0x85 (MSB):
+ *     Main fan tachometer reading (in RPM)
+ *
+ *     This register is present on all ThinkPads with a new-style EC, and
+ *     it is known not to be present on the A21m/e, and T22, as there is
+ *     something else in offset 0x84 according to the ACPI DSDT.  Other
+ *     ThinkPads from this same time period (and earlier) probably lack the
+ *     tachometer as well.
+ *
+ *     Unfortunately a lot of ThinkPads with new-style ECs but whose firwmare
+ *     was never fixed by IBM to report the EC firmware version string
+ *     probably support the tachometer (like the early X models), so
+ *     detecting it is quite hard.  We need more data to know for sure.
+ *
+ *     FIRMWARE BUG: always read 0x84 first, otherwise incorrect readings
+ *     might result.
+ *
+ *     FIRMWARE BUG: when EC 0x2f bit 6 is set (disengaged mode), this
+ *     register is not invalidated in ThinkPads that disable tachometer
+ *     readings.  Thus, the tachometer readings go stale.
+ *
+ *     For firmware bugs, refer to:
+ *     http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
+ *
+ * IBMACPI_FAN_WR_ACPI_FANS:
+ *     ThinkPad X31, X40, X41.  Not available in the X60.
+ *
+ *     FANS ACPI handle: takes three arguments: low speed, medium speed,
+ *     high speed.  ACPI DSDT seems to map these three speeds to levels
+ *     as follows: STOP LOW LOW MED MED HIGH HIGH HIGH HIGH
+ *     (this map is stored on FAN0..FAN8 as "0,1,1,2,2,3,3,3,3")
+ *
+ *     The speeds are stored on handles
+ *     (FANA:FAN9), (FANC:FANB), (FANE:FAND).
+ *
+ *     There are three default speed sets, acessible as handles:
+ *     FS1L,FS1M,FS1H; FS2L,FS2M,FS2H; FS3L,FS3M,FS3H
+ *
+ *     ACPI DSDT switches which set is in use depending on various
+ *     factors.
+ *
+ *     IBMACPI_FAN_WR_TPEC is also available and should be used to
+ *     command the fan.  The X31/X40/X41 seems to have 8 fan levels,
+ *     but the ACPI tables just mention level 7.
+ */
+
+enum fan_status_access_mode {
+       IBMACPI_FAN_NONE = 0,           /* No fan status or control */
+       IBMACPI_FAN_RD_ACPI_GFAN,       /* Use ACPI GFAN */
+       IBMACPI_FAN_RD_TPEC,            /* Use ACPI EC regs 0x2f, 0x84-0x85 */
+};
+
+enum fan_control_access_mode {
+       IBMACPI_FAN_WR_NONE = 0,        /* No fan control */
+       IBMACPI_FAN_WR_ACPI_SFAN,       /* Use ACPI SFAN */
+       IBMACPI_FAN_WR_TPEC,            /* Use ACPI EC reg 0x2f */
+       IBMACPI_FAN_WR_ACPI_FANS,       /* Use ACPI FANS and EC reg 0x2f */
+};
+
+enum fan_control_commands {
+       IBMACPI_FAN_CMD_SPEED   = 0x0001,       /* speed command */
+       IBMACPI_FAN_CMD_LEVEL   = 0x0002,       /* level command  */
+       IBMACPI_FAN_CMD_ENABLE  = 0x0004,       /* enable/disable cmd,
+                                                * and also watchdog cmd */
+};
+
+enum {                                 /* Fan control constants */
+       fan_status_offset = 0x2f,       /* EC register 0x2f */
+       fan_rpm_offset = 0x84,          /* EC register 0x84: LSB, 0x85 MSB (RPM)
+                                        * 0x84 must be read before 0x85 */
+
+       IBMACPI_FAN_EC_DISENGAGED       = 0x40, /* EC mode: tachometer
+                                                * disengaged */
+       IBMACPI_FAN_EC_AUTO             = 0x80, /* EC mode: auto fan
+                                                * control */
+};
+
+static char *ibm_thinkpad_ec_found = NULL;
+
 struct ibm_struct {
        char *name;
        char param[32];
@@ -243,6 +382,8 @@ struct ibm_struct {
 
 static struct proc_dir_entry *proc_dir = NULL;
 
+static struct backlight_device *ibm_backlight_device = NULL;
+
 #define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off")
 #define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
 #define strlencmp(a,b) (strncmp((a), (b), strlen(b)))
@@ -581,8 +722,7 @@ static int wan_status(void)
 {
        int status;
 
-       if (!wan_supported ||
-           !acpi_evalf(hkey_handle, &status, "GWAN", "d"))
+       if (!wan_supported || !acpi_evalf(hkey_handle, &status, "GWAN", "d"))
                status = 0;
 
        return status;
@@ -630,12 +770,15 @@ static int wan_write(char *buf)
        return 0;
 }
 
-static int video_supported;
-static int video_orig_autosw;
+enum video_access_mode {
+       IBMACPI_VIDEO_NONE = 0,
+       IBMACPI_VIDEO_570,      /* 570 */
+       IBMACPI_VIDEO_770,      /* 600e/x, 770e, 770x */
+       IBMACPI_VIDEO_NEW,      /* all others */
+};
 
-#define VIDEO_570 1
-#define VIDEO_770 2
-#define VIDEO_NEW 3
+static enum video_access_mode video_supported;
+static int video_orig_autosw;
 
 static int video_init(void)
 {
@@ -647,16 +790,16 @@ static int video_init(void)
 
        if (!vid_handle)
                /* video switching not supported on R30, R31 */
-               video_supported = 0;
+               video_supported = IBMACPI_VIDEO_NONE;
        else if (acpi_evalf(vid_handle, &video_orig_autosw, "SWIT", "qd"))
                /* 570 */
-               video_supported = VIDEO_570;
+               video_supported = IBMACPI_VIDEO_570;
        else if (acpi_evalf(vid_handle, &video_orig_autosw, "^VADL", "qd"))
                /* 600e/x, 770e, 770x */
-               video_supported = VIDEO_770;
+               video_supported = IBMACPI_VIDEO_770;
        else
                /* all others */
-               video_supported = VIDEO_NEW;
+               video_supported = IBMACPI_VIDEO_NEW;
 
        return 0;
 }
@@ -666,15 +809,15 @@ static int video_status(void)
        int status = 0;
        int i;
 
-       if (video_supported == VIDEO_570) {
+       if (video_supported == IBMACPI_VIDEO_570) {
                if (acpi_evalf(NULL, &i, "\\_SB.PHS", "dd", 0x87))
                        status = i & 3;
-       } else if (video_supported == VIDEO_770) {
+       } else if (video_supported == IBMACPI_VIDEO_770) {
                if (acpi_evalf(NULL, &i, "\\VCDL", "d"))
                        status |= 0x01 * i;
                if (acpi_evalf(NULL, &i, "\\VCDC", "d"))
                        status |= 0x02 * i;
-       } else if (video_supported == VIDEO_NEW) {
+       } else if (video_supported == IBMACPI_VIDEO_NEW) {
                acpi_evalf(NULL, NULL, "\\VUPS", "vd", 1);
                if (acpi_evalf(NULL, &i, "\\VCDC", "d"))
                        status |= 0x02 * i;
@@ -693,9 +836,10 @@ static int video_autosw(void)
 {
        int autosw = 0;
 
-       if (video_supported == VIDEO_570)
+       if (video_supported == IBMACPI_VIDEO_570)
                acpi_evalf(vid_handle, &autosw, "SWIT", "d");
-       else if (video_supported == VIDEO_770 || video_supported == VIDEO_NEW)
+       else if (video_supported == IBMACPI_VIDEO_770 ||
+                video_supported == IBMACPI_VIDEO_NEW)
                acpi_evalf(vid_handle, &autosw, "^VDEE", "d");
 
        return autosw & 1;
@@ -715,12 +859,12 @@ static int video_read(char *p)
        len += sprintf(p + len, "status:\t\tsupported\n");
        len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0));
        len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1));
-       if (video_supported == VIDEO_NEW)
+       if (video_supported == IBMACPI_VIDEO_NEW)
                len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3));
        len += sprintf(p + len, "auto:\t\t%s\n", enabled(autosw, 0));
        len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable\n");
        len += sprintf(p + len, "commands:\tcrt_enable, crt_disable\n");
-       if (video_supported == VIDEO_NEW)
+       if (video_supported == IBMACPI_VIDEO_NEW)
                len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable\n");
        len += sprintf(p + len, "commands:\tauto_enable, auto_disable\n");
        len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n");
@@ -735,7 +879,7 @@ static int video_switch(void)
 
        if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
                return -EIO;
-       ret = video_supported == VIDEO_570 ?
+       ret = video_supported == IBMACPI_VIDEO_570 ?
            acpi_evalf(ec_handle, NULL, "_Q16", "v") :
            acpi_evalf(vid_handle, NULL, "VSWT", "v");
        acpi_evalf(vid_handle, NULL, "_DOS", "vd", autosw);
@@ -745,9 +889,9 @@ static int video_switch(void)
 
 static int video_expand(void)
 {
-       if (video_supported == VIDEO_570)
+       if (video_supported == IBMACPI_VIDEO_570)
                return acpi_evalf(ec_handle, NULL, "_Q17", "v");
-       else if (video_supported == VIDEO_770)
+       else if (video_supported == IBMACPI_VIDEO_770)
                return acpi_evalf(vid_handle, NULL, "VEXP", "v");
        else
                return acpi_evalf(NULL, NULL, "\\VEXP", "v");
@@ -757,10 +901,10 @@ static int video_switch2(int status)
 {
        int ret;
 
-       if (video_supported == VIDEO_570) {
+       if (video_supported == IBMACPI_VIDEO_570) {
                ret = acpi_evalf(NULL, NULL,
                                 "\\_SB.PHS2", "vdd", 0x8b, status | 0x80);
-       } else if (video_supported == VIDEO_770) {
+       } else if (video_supported == IBMACPI_VIDEO_770) {
                int autosw = video_autosw();
                if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
                        return -EIO;
@@ -796,10 +940,10 @@ static int video_write(char *buf)
                        enable |= 0x02;
                } else if (strlencmp(cmd, "crt_disable") == 0) {
                        disable |= 0x02;
-               } else if (video_supported == VIDEO_NEW &&
+               } else if (video_supported == IBMACPI_VIDEO_NEW &&
                           strlencmp(cmd, "dvi_enable") == 0) {
                        enable |= 0x08;
-               } else if (video_supported == VIDEO_NEW &&
+               } else if (video_supported == IBMACPI_VIDEO_NEW &&
                           strlencmp(cmd, "dvi_disable") == 0) {
                        disable |= 0x08;
                } else if (strlencmp(cmd, "auto_enable") == 0) {
@@ -898,6 +1042,7 @@ static int light_write(char *buf)
        return 0;
 }
 
+#if defined(CONFIG_ACPI_IBM_DOCK) || defined(CONFIG_ACPI_IBM_BAY)
 static int _sta(acpi_handle handle)
 {
        int status;
@@ -907,6 +1052,7 @@ static int _sta(acpi_handle handle)
 
        return status;
 }
+#endif
 #ifdef CONFIG_ACPI_IBM_DOCK
 #define dock_docked() (_sta(dock_handle) & 1)
 
@@ -972,6 +1118,7 @@ static void dock_notify(struct ibm_struct *ibm, u32 event)
 }
 #endif
 
+#ifdef CONFIG_ACPI_IBM_BAY
 static int bay_status_supported;
 static int bay_status2_supported;
 static int bay_eject_supported;
@@ -1047,6 +1194,7 @@ static void bay_notify(struct ibm_struct *ibm, u32 event)
 {
        acpi_bus_generate_event(ibm->device, event, 0);
 }
+#endif
 
 static int cmos_read(char *p)
 {
@@ -1094,26 +1242,28 @@ static int cmos_write(char *buf)
        return 0;
 }
 
-static int led_supported;
-
-#define LED_570 1
-#define LED_OLD 2
-#define LED_NEW 3
+enum led_access_mode {
+       IBMACPI_LED_NONE = 0,
+       IBMACPI_LED_570,        /* 570 */
+       IBMACPI_LED_OLD,        /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
+       IBMACPI_LED_NEW,        /* all others */
+};
+static enum led_access_mode led_supported;
 
 static int led_init(void)
 {
        if (!led_handle)
                /* led not supported on R30, R31 */
-               led_supported = 0;
+               led_supported = IBMACPI_LED_NONE;
        else if (strlencmp(led_path, "SLED") == 0)
                /* 570 */
-               led_supported = LED_570;
+               led_supported = IBMACPI_LED_570;
        else if (strlencmp(led_path, "SYSL") == 0)
                /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
-               led_supported = LED_OLD;
+               led_supported = IBMACPI_LED_OLD;
        else
                /* all others */
-               led_supported = LED_NEW;
+               led_supported = IBMACPI_LED_NEW;
 
        return 0;
 }
@@ -1130,7 +1280,7 @@ static int led_read(char *p)
        }
        len += sprintf(p + len, "status:\t\tsupported\n");
 
-       if (led_supported == LED_570) {
+       if (led_supported == IBMACPI_LED_570) {
                /* 570 */
                int i, status;
                for (i = 0; i < 8; i++) {
@@ -1179,13 +1329,13 @@ static int led_write(char *buf)
                } else
                        return -EINVAL;
 
-               if (led_supported == LED_570) {
+               if (led_supported == IBMACPI_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 == LED_OLD) {
+               } else if (led_supported == IBMACPI_LED_OLD) {
                        /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
                        led = 1 << led;
                        ret = ec_write(EC_HLMS, led);
@@ -1272,50 +1422,142 @@ static int acpi_ec_write(int i, u8 v)
        return 1;
 }
 
-static int thermal_tmp_supported;
-static int thermal_updt_supported;
+static enum thermal_access_mode thermal_read_mode;
 
 static int thermal_init(void)
 {
-       /* temperatures not supported on 570, G4x, R30, R31, R32 */
-       thermal_tmp_supported = acpi_evalf(ec_handle, NULL, "TMP7", "qv");
+       u8 t, ta1, ta2;
+       int i;
+       int acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv");
+
+       if (ibm_thinkpad_ec_found && experimental) {
+               /*
+                * Direct EC access mode: sensors at registers
+                * 0x78-0x7F, 0xC0-0xC7.  Registers return 0x00 for
+                * non-implemented, thermal sensors return 0x80 when
+                * not available
+                */
 
-       /* 600e/x, 770e, 770x */
-       thermal_updt_supported = acpi_evalf(ec_handle, NULL, "UPDT", "qv");
+               ta1 = ta2 = 0;
+               for (i = 0; i < 8; i++) {
+                       if (likely(acpi_ec_read(0x78 + i, &t))) {
+                               ta1 |= t;
+                       } else {
+                               ta1 = 0;
+                               break;
+                       }
+                       if (likely(acpi_ec_read(0xC0 + i, &t))) {
+                               ta2 |= t;
+                       } else {
+                               ta1 = 0;
+                               break;
+                       }
+               }
+               if (ta1 == 0) {
+                       /* This is sheer paranoia, but we handle it anyway */
+                       if (acpi_tmp7) {
+                               printk(IBM_ERR
+                                      "ThinkPad ACPI EC access misbehaving, "
+                                      "falling back to ACPI TMPx access mode\n");
+                               thermal_read_mode = IBMACPI_THERMAL_ACPI_TMP07;
+                       } else {
+                               printk(IBM_ERR
+                                      "ThinkPad ACPI EC access misbehaving, "
+                                      "disabling thermal sensors access\n");
+                               thermal_read_mode = IBMACPI_THERMAL_NONE;
+                       }
+               } else {
+                       thermal_read_mode =
+                           (ta2 != 0) ?
+                           IBMACPI_THERMAL_TPEC_16 : IBMACPI_THERMAL_TPEC_8;
+               }
+       } else if (acpi_tmp7) {
+               if (acpi_evalf(ec_handle, NULL, "UPDT", "qv")) {
+                       /* 600e/x, 770e, 770x */
+                       thermal_read_mode = IBMACPI_THERMAL_ACPI_UPDT;
+               } else {
+                       /* Standard ACPI TMPx access, max 8 sensors */
+                       thermal_read_mode = IBMACPI_THERMAL_ACPI_TMP07;
+               }
+       } else {
+               /* temperatures not supported on 570, G4x, R30, R31, R32 */
+               thermal_read_mode = IBMACPI_THERMAL_NONE;
+       }
 
        return 0;
 }
 
-static int thermal_read(char *p)
+static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s)
 {
-       int len = 0;
+       int i, t;
+       s8 tmp;
+       char tmpi[] = "TMPi";
 
-       if (!thermal_tmp_supported)
-               len += sprintf(p + len, "temperatures:\tnot supported\n");
-       else {
-               int i, t;
-               char tmpi[] = "TMPi";
-               s8 tmp[8];
+       if (!s)
+               return -EINVAL;
 
-               if (thermal_updt_supported)
-                       if (!acpi_evalf(ec_handle, NULL, "UPDT", "v"))
+       switch (thermal_read_mode) {
+#if IBMACPI_MAX_THERMAL_SENSORS >= 16
+       case IBMACPI_THERMAL_TPEC_16:
+               for (i = 0; i < 8; i++) {
+                       if (!acpi_ec_read(0xC0 + i, &tmp))
+                               return -EIO;
+                       s->temp[i + 8] = tmp * 1000;
+               }
+               /* fallthrough */
+#endif
+       case IBMACPI_THERMAL_TPEC_8:
+               for (i = 0; i < 8; i++) {
+                       if (!acpi_ec_read(0x78 + i, &tmp))
                                return -EIO;
+                       s->temp[i] = tmp * 1000;
+               }
+               return (thermal_read_mode == IBMACPI_THERMAL_TPEC_16) ? 16 : 8;
 
+       case IBMACPI_THERMAL_ACPI_UPDT:
+               if (!acpi_evalf(ec_handle, NULL, "UPDT", "v"))
+                       return -EIO;
                for (i = 0; i < 8; i++) {
                        tmpi[3] = '0' + i;
                        if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
                                return -EIO;
-                       if (thermal_updt_supported)
-                               tmp[i] = (t - 2732 + 5) / 10;
-                       else
-                               tmp[i] = t;
+                       s->temp[i] = (t - 2732) * 100;
                }
+               return 8;
 
-               len += sprintf(p + len,
-                              "temperatures:\t%d %d %d %d %d %d %d %d\n",
-                              tmp[0], tmp[1], tmp[2], tmp[3],
-                              tmp[4], tmp[5], tmp[6], tmp[7]);
+       case IBMACPI_THERMAL_ACPI_TMP07:
+               for (i = 0; i < 8; i++) {
+                       tmpi[3] = '0' + i;
+                       if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
+                               return -EIO;
+                       s->temp[i] = t * 1000;
+               }
+               return 8;
+
+       case IBMACPI_THERMAL_NONE:
+       default:
+               return 0;
        }
+}
+
+static int thermal_read(char *p)
+{
+       int len = 0;
+       int n, i;
+       struct ibm_thermal_sensors_struct t;
+
+       n = thermal_get_sensors(&t);
+       if (unlikely(n < 0))
+               return n;
+
+       len += sprintf(p + len, "temperatures:\t");
+
+       if (n > 0) {
+               for (i = 0; i < (n - 1); i++)
+                       len += sprintf(p + len, "%d ", t.temp[i] / 1000);
+               len += sprintf(p + len, "%d\n", t.temp[i] / 1000);
+       } else
+               len += sprintf(p + len, "not supported\n");
 
        return len;
 }
@@ -1381,12 +1623,23 @@ static int ecdump_write(char *buf)
 
 static int brightness_offset = 0x31;
 
+static int brightness_get(struct backlight_device *bd)
+{
+       u8 level;
+       if (!acpi_ec_read(brightness_offset, &level))
+               return -EIO;
+
+       level &= 0x7;
+
+       return level;
+}
+
 static int brightness_read(char *p)
 {
        int len = 0;
-       u8 level;
+       int level;
 
-       if (!acpi_ec_read(brightness_offset, &level)) {
+       if ((level = brightness_get(NULL)) < 0) {
                len += sprintf(p + len, "level:\t\tunreadable\n");
        } else {
                len += sprintf(p + len, "level:\t\t%d\n", level & 0x7);
@@ -1401,16 +1654,34 @@ static int brightness_read(char *p)
 #define BRIGHTNESS_UP  4
 #define BRIGHTNESS_DOWN        5
 
-static int brightness_write(char *buf)
+static int brightness_set(int value)
 {
        int cmos_cmd, inc, i;
-       u8 level;
+       int current_value = brightness_get(NULL);
+
+       value &= 7;
+
+       cmos_cmd = value > current_value ? BRIGHTNESS_UP : BRIGHTNESS_DOWN;
+       inc = value > current_value ? 1 : -1;
+       for (i = current_value; i != value; i += inc) {
+               if (!cmos_eval(cmos_cmd))
+                       return -EIO;
+               if (!acpi_ec_write(brightness_offset, i + inc))
+                       return -EIO;
+       }
+
+       return 0;
+}
+
+static int brightness_write(char *buf)
+{
+       int level;
        int new_level;
        char *cmd;
 
        while ((cmd = next_cmd(&buf))) {
-               if (!acpi_ec_read(brightness_offset, &level))
-                       return -EIO;
+               if ((level = brightness_get(NULL)) < 0)
+                       return level;
                level &= 7;
 
                if (strlencmp(cmd, "up") == 0) {
@@ -1423,19 +1694,44 @@ static int brightness_write(char *buf)
                } else
                        return -EINVAL;
 
-               cmos_cmd = new_level > level ? BRIGHTNESS_UP : BRIGHTNESS_DOWN;
-               inc = new_level > level ? 1 : -1;
-               for (i = level; i != new_level; i += inc) {
-                       if (!cmos_eval(cmos_cmd))
-                               return -EIO;
-                       if (!acpi_ec_write(brightness_offset, i + inc))
-                               return -EIO;
-               }
+               brightness_set(new_level);
        }
 
        return 0;
 }
 
+static int brightness_update_status(struct backlight_device *bd)
+{
+       return brightness_set(bd->props->brightness);
+}
+
+static struct backlight_properties ibm_backlight_data = {
+        .owner          = THIS_MODULE,
+        .get_brightness = brightness_get,
+        .update_status  = brightness_update_status,
+        .max_brightness = 7,
+};
+
+static int brightness_init(void)
+{
+       ibm_backlight_device = backlight_device_register("ibm", NULL, NULL,
+                                                        &ibm_backlight_data);
+       if (IS_ERR(ibm_backlight_device)) {
+               printk(IBM_ERR "Could not register backlight device\n");
+               return PTR_ERR(ibm_backlight_device);
+       }
+
+       return 0;
+}
+
+static void brightness_exit(void)
+{
+       if (ibm_backlight_device) {
+               backlight_device_unregister(ibm_backlight_device);
+               ibm_backlight_device = NULL;
+       }
+}
+
 static int volume_offset = 0x30;
 
 static int volume_read(char *p)
@@ -1522,86 +1818,482 @@ static int volume_write(char *buf)
        return 0;
 }
 
-static int fan_status_offset = 0x2f;
-static int fan_rpm_offset = 0x84;
+static enum fan_status_access_mode fan_status_access_mode;
+static enum fan_control_access_mode fan_control_access_mode;
+static enum fan_control_commands fan_control_commands;
 
-static int fan_read(char *p)
+static int fan_control_status_known;
+static u8 fan_control_initial_status;
+
+static void fan_watchdog_fire(struct work_struct *ignored);
+static int fan_watchdog_maxinterval;
+static DECLARE_DELAYED_WORK(fan_watchdog_task, fan_watchdog_fire);
+
+static int fan_init(void)
 {
-       int len = 0;
-       int s;
-       u8 lo, hi, status;
+       fan_status_access_mode = IBMACPI_FAN_NONE;
+       fan_control_access_mode = IBMACPI_FAN_WR_NONE;
+       fan_control_commands = 0;
+       fan_control_status_known = 1;
+       fan_watchdog_maxinterval = 0;
 
        if (gfan_handle) {
                /* 570, 600e/x, 770e, 770x */
-               if (!acpi_evalf(gfan_handle, &s, NULL, "d"))
-                       return -EIO;
+               fan_status_access_mode = IBMACPI_FAN_RD_ACPI_GFAN;
+       } else {
+               /* all other ThinkPads: note that even old-style
+                * ThinkPad ECs supports the fan control register */
+               if (likely(acpi_ec_read(fan_status_offset,
+                                       &fan_control_initial_status))) {
+                       fan_status_access_mode = IBMACPI_FAN_RD_TPEC;
+
+                       /* In some ThinkPads, neither the EC nor the ACPI
+                        * DSDT initialize the fan status, and it ends up
+                        * being set to 0x07 when it *could* be either
+                        * 0x07 or 0x80.
+                        *
+                        * Enable for TP-1Y (T43), TP-78 (R51e),
+                        * TP-76 (R52), TP-70 (T43, R52), which are known
+                        * to be buggy. */
+                       if (fan_control_initial_status == 0x07 &&
+                           ibm_thinkpad_ec_found &&
+                           ((ibm_thinkpad_ec_found[0] == '1' &&
+                             ibm_thinkpad_ec_found[1] == 'Y') ||
+                            (ibm_thinkpad_ec_found[0] == '7' &&
+                             (ibm_thinkpad_ec_found[1] == '6' ||
+                              ibm_thinkpad_ec_found[1] == '8' ||
+                              ibm_thinkpad_ec_found[1] == '0'))
+                           )) {
+                               printk(IBM_NOTICE
+                                      "fan_init: initial fan status is "
+                                      "unknown, assuming it is in auto "
+                                      "mode\n");
+                               fan_control_status_known = 0;
+                       }
+               } else {
+                       printk(IBM_ERR
+                              "ThinkPad ACPI EC access misbehaving, "
+                              "fan status and control unavailable\n");
+                       return 0;
+               }
+       }
 
-               len += sprintf(p + len, "level:\t\t%d\n", s);
+       if (sfan_handle) {
+               /* 570, 770x-JL */
+               fan_control_access_mode = IBMACPI_FAN_WR_ACPI_SFAN;
+               fan_control_commands |=
+                   IBMACPI_FAN_CMD_LEVEL | IBMACPI_FAN_CMD_ENABLE;
        } else {
+               if (!gfan_handle) {
+                       /* gfan without sfan means no fan control */
+                       /* all other models implement TP EC 0x2f control */
+
+                       if (fans_handle) {
+                               /* X31, X40, X41 */
+                               fan_control_access_mode =
+                                   IBMACPI_FAN_WR_ACPI_FANS;
+                               fan_control_commands |=
+                                   IBMACPI_FAN_CMD_SPEED |
+                                   IBMACPI_FAN_CMD_LEVEL |
+                                   IBMACPI_FAN_CMD_ENABLE;
+                       } else {
+                               fan_control_access_mode = IBMACPI_FAN_WR_TPEC;
+                               fan_control_commands |=
+                                   IBMACPI_FAN_CMD_LEVEL |
+                                   IBMACPI_FAN_CMD_ENABLE;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int fan_get_status(u8 *status)
+{
+       u8 s;
+
+       /* TODO:
+        * Add IBMACPI_FAN_RD_ACPI_FANS ? */
+
+       switch (fan_status_access_mode) {
+       case IBMACPI_FAN_RD_ACPI_GFAN:
+               /* 570, 600e/x, 770e, 770x */
+
+               if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d")))
+                       return -EIO;
+
+               if (likely(status))
+                       *status = s & 0x07;
+
+               break;
+
+       case IBMACPI_FAN_RD_TPEC:
                /* all except 570, 600e/x, 770e, 770x */
-               if (!acpi_ec_read(fan_status_offset, &status))
-                       len += sprintf(p + len, "status:\t\tunreadable\n");
-               else
-                       len += sprintf(p + len, "status:\t\t%s\n",
-                                      enabled(status, 7));
+               if (unlikely(!acpi_ec_read(fan_status_offset, &s)))
+                       return -EIO;
 
-               if (!acpi_ec_read(fan_rpm_offset, &lo) ||
-                   !acpi_ec_read(fan_rpm_offset + 1, &hi))
-                       len += sprintf(p + len, "speed:\t\tunreadable\n");
-               else
-                       len += sprintf(p + len, "speed:\t\t%d\n",
-                                      (hi << 8) + lo);
+               if (likely(status))
+                       *status = s;
+
+               break;
+
+       default:
+               return -ENXIO;
        }
 
-       if (sfan_handle)
-               /* 570, 770x-JL */
-               len += sprintf(p + len, "commands:\tlevel <level>"
-                              " (<level> is 0-7)\n");
-       if (!gfan_handle)
+       return 0;
+}
+
+static int fan_get_speed(unsigned int *speed)
+{
+       u8 hi, lo;
+
+       switch (fan_status_access_mode) {
+       case IBMACPI_FAN_RD_TPEC:
                /* all except 570, 600e/x, 770e, 770x */
-               len += sprintf(p + len, "commands:\tenable, disable\n");
-       if (fans_handle)
-               /* X31, X40 */
+               if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) ||
+                            !acpi_ec_read(fan_rpm_offset + 1, &hi)))
+                       return -EIO;
+
+               if (likely(speed))
+                       *speed = (hi << 8) | lo;
+
+               break;
+
+       default:
+               return -ENXIO;
+       }
+
+       return 0;
+}
+
+static void fan_exit(void)
+{
+       cancel_delayed_work(&fan_watchdog_task);
+       flush_scheduled_work();
+}
+
+static void fan_watchdog_reset(void)
+{
+       static int fan_watchdog_active = 0;
+
+       if (fan_watchdog_active)
+               cancel_delayed_work(&fan_watchdog_task);
+
+       if (fan_watchdog_maxinterval > 0) {
+               fan_watchdog_active = 1;
+               if (!schedule_delayed_work(&fan_watchdog_task,
+                               msecs_to_jiffies(fan_watchdog_maxinterval
+                                                * 1000))) {
+                       printk(IBM_ERR "failed to schedule the fan watchdog, "
+                              "watchdog will not trigger\n");
+               }
+       } else
+               fan_watchdog_active = 0;
+}
+
+static int fan_read(char *p)
+{
+       int len = 0;
+       int rc;
+       u8 status;
+       unsigned int speed = 0;
+
+       switch (fan_status_access_mode) {
+       case IBMACPI_FAN_RD_ACPI_GFAN:
+               /* 570, 600e/x, 770e, 770x */
+               if ((rc = fan_get_status(&status)) < 0)
+                       return rc;
+
+               len += sprintf(p + len, "status:\t\t%s\n"
+                              "level:\t\t%d\n",
+                              (status != 0) ? "enabled" : "disabled", status);
+               break;
+
+       case IBMACPI_FAN_RD_TPEC:
+               /* all except 570, 600e/x, 770e, 770x */
+               if ((rc = fan_get_status(&status)) < 0)
+                       return rc;
+
+               if (unlikely(!fan_control_status_known)) {
+                       if (status != fan_control_initial_status)
+                               fan_control_status_known = 1;
+                       else
+                               /* Return most likely status. In fact, it
+                                * might be the only possible status */
+                               status = IBMACPI_FAN_EC_AUTO;
+               }
+
+               len += sprintf(p + len, "status:\t\t%s\n",
+                              (status != 0) ? "enabled" : "disabled");
+
+               /* No ThinkPad boots on disengaged mode, we can safely
+                * assume the tachometer is online if fan control status
+                * was unknown */
+               if ((rc = fan_get_speed(&speed)) < 0)
+                       return rc;
+
+               len += sprintf(p + len, "speed:\t\t%d\n", speed);
+
+               if (status & IBMACPI_FAN_EC_DISENGAGED)
+                       /* Disengaged mode takes precedence */
+                       len += sprintf(p + len, "level:\t\tdisengaged\n");
+               else if (status & IBMACPI_FAN_EC_AUTO)
+                       len += sprintf(p + len, "level:\t\tauto\n");
+               else
+                       len += sprintf(p + len, "level:\t\t%d\n", status);
+               break;
+
+       case IBMACPI_FAN_NONE:
+       default:
+               len += sprintf(p + len, "status:\t\tnot supported\n");
+       }
+
+       if (fan_control_commands & IBMACPI_FAN_CMD_LEVEL) {
+               len += sprintf(p + len, "commands:\tlevel <level>");
+
+               switch (fan_control_access_mode) {
+               case IBMACPI_FAN_WR_ACPI_SFAN:
+                       len += sprintf(p + len, " (<level> is 0-7)\n");
+                       break;
+
+               default:
+                       len += sprintf(p + len, " (<level> is 0-7, "
+                                      "auto, disengaged)\n");
+                       break;
+               }
+       }
+
+       if (fan_control_commands & IBMACPI_FAN_CMD_ENABLE)
+               len += sprintf(p + len, "commands:\tenable, disable\n"
+                              "commands:\twatchdog <timeout> (<timeout> is 0 (off), "
+                              "1-120 (seconds))\n");
+
+       if (fan_control_commands & IBMACPI_FAN_CMD_SPEED)
                len += sprintf(p + len, "commands:\tspeed <speed>"
                               " (<speed> is 0-65535)\n");
 
        return len;
 }
 
-static int fan_write(char *buf)
+static int fan_set_level(int level)
 {
-       char *cmd;
-       int level, speed;
-
-       while ((cmd = next_cmd(&buf))) {
-               if (sfan_handle &&
-                   sscanf(cmd, "level %d", &level) == 1 &&
-                   level >= 0 && level <= 7) {
-                       /* 570, 770x-JL */
+       switch (fan_control_access_mode) {
+       case IBMACPI_FAN_WR_ACPI_SFAN:
+               if (level >= 0 && level <= 7) {
                        if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
                                return -EIO;
-               } else if (!gfan_handle && strlencmp(cmd, "enable") == 0) {
-                       /* all except 570, 600e/x, 770e, 770x */
-                       if (!acpi_ec_write(fan_status_offset, 0x80))
-                               return -EIO;
-               } else if (!gfan_handle && strlencmp(cmd, "disable") == 0) {
-                       /* all except 570, 600e/x, 770e, 770x */
-                       if (!acpi_ec_write(fan_status_offset, 0x00))
-                               return -EIO;
-               } else if (fans_handle &&
-                          sscanf(cmd, "speed %d", &speed) == 1 &&
-                          speed >= 0 && speed <= 65535) {
-                       /* X31, X40 */
+               } else
+                       return -EINVAL;
+               break;
+
+       case IBMACPI_FAN_WR_ACPI_FANS:
+       case IBMACPI_FAN_WR_TPEC:
+               if ((level != IBMACPI_FAN_EC_AUTO) &&
+                   (level != IBMACPI_FAN_EC_DISENGAGED) &&
+                   ((level < 0) || (level > 7)))
+                       return -EINVAL;
+
+               if (!acpi_ec_write(fan_status_offset, level))
+                       return -EIO;
+               else
+                       fan_control_status_known = 1;
+               break;
+
+       default:
+               return -ENXIO;
+       }
+       return 0;
+}
+
+static int fan_set_enable(void)
+{
+       u8 s;
+       int rc;
+
+       switch (fan_control_access_mode) {
+       case IBMACPI_FAN_WR_ACPI_FANS:
+       case IBMACPI_FAN_WR_TPEC:
+               if ((rc = fan_get_status(&s)) < 0)
+                       return rc;
+
+               /* Don't go out of emergency fan mode */
+               if (s != 7)
+                       s = IBMACPI_FAN_EC_AUTO;
+
+               if (!acpi_ec_write(fan_status_offset, s))
+                       return -EIO;
+               else
+                       fan_control_status_known = 1;
+               break;
+
+       case IBMACPI_FAN_WR_ACPI_SFAN:
+               if ((rc = fan_get_status(&s)) < 0)
+                       return rc;
+
+               s &= 0x07;
+
+               /* Set fan to at least level 4 */
+               if (s < 4)
+                       s = 4;
+
+               if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", s))
+                       return -EIO;
+               break;
+
+       default:
+               return -ENXIO;
+       }
+       return 0;
+}
+
+static int fan_set_disable(void)
+{
+       switch (fan_control_access_mode) {
+       case IBMACPI_FAN_WR_ACPI_FANS:
+       case IBMACPI_FAN_WR_TPEC:
+               if (!acpi_ec_write(fan_status_offset, 0x00))
+                       return -EIO;
+               else
+                       fan_control_status_known = 1;
+               break;
+
+       case IBMACPI_FAN_WR_ACPI_SFAN:
+               if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", 0x00))
+                       return -EIO;
+               break;
+
+       default:
+               return -ENXIO;
+       }
+       return 0;
+}
+
+static int fan_set_speed(int speed)
+{
+       switch (fan_control_access_mode) {
+       case IBMACPI_FAN_WR_ACPI_FANS:
+               if (speed >= 0 && speed <= 65535) {
                        if (!acpi_evalf(fans_handle, NULL, NULL, "vddd",
                                        speed, speed, speed))
                                return -EIO;
                } else
                        return -EINVAL;
-       }
+               break;
 
+       default:
+               return -ENXIO;
+       }
        return 0;
 }
 
+static int fan_write_cmd_level(const char *cmd, int *rc)
+{
+       int level;
+
+       if (strlencmp(cmd, "level auto") == 0)
+               level = IBMACPI_FAN_EC_AUTO;
+       else if (strlencmp(cmd, "level disengaged") == 0)
+               level = IBMACPI_FAN_EC_DISENGAGED;
+       else if (sscanf(cmd, "level %d", &level) != 1)
+               return 0;
+
+       if ((*rc = fan_set_level(level)) == -ENXIO)
+               printk(IBM_ERR "level command accepted for unsupported "
+                      "access mode %d", fan_control_access_mode);
+
+       return 1;
+}
+
+static int fan_write_cmd_enable(const char *cmd, int *rc)
+{
+       if (strlencmp(cmd, "enable") != 0)
+               return 0;
+
+       if ((*rc = fan_set_enable()) == -ENXIO)
+               printk(IBM_ERR "enable command accepted for unsupported "
+                      "access mode %d", fan_control_access_mode);
+
+       return 1;
+}
+
+static int fan_write_cmd_disable(const char *cmd, int *rc)
+{
+       if (strlencmp(cmd, "disable") != 0)
+               return 0;
+
+       if ((*rc = fan_set_disable()) == -ENXIO)
+               printk(IBM_ERR "disable command accepted for unsupported "
+                      "access mode %d", fan_control_access_mode);
+
+       return 1;
+}
+
+static int fan_write_cmd_speed(const char *cmd, int *rc)
+{
+       int speed;
+
+       /* TODO:
+        * Support speed <low> <medium> <high> ? */
+
+       if (sscanf(cmd, "speed %d", &speed) != 1)
+               return 0;
+
+       if ((*rc = fan_set_speed(speed)) == -ENXIO)
+               printk(IBM_ERR "speed command accepted for unsupported "
+                      "access mode %d", fan_control_access_mode);
+
+       return 1;
+}
+
+static int fan_write_cmd_watchdog(const char *cmd, int *rc)
+{
+       int interval;
+
+       if (sscanf(cmd, "watchdog %d", &interval) != 1)
+               return 0;
+
+       if (interval < 0 || interval > 120)
+               *rc = -EINVAL;
+       else
+               fan_watchdog_maxinterval = interval;
+
+       return 1;
+}
+
+static int fan_write(char *buf)
+{
+       char *cmd;
+       int rc = 0;
+
+       while (!rc && (cmd = next_cmd(&buf))) {
+               if (!((fan_control_commands & IBMACPI_FAN_CMD_LEVEL) &&
+                     fan_write_cmd_level(cmd, &rc)) &&
+                   !((fan_control_commands & IBMACPI_FAN_CMD_ENABLE) &&
+                     (fan_write_cmd_enable(cmd, &rc) ||
+                      fan_write_cmd_disable(cmd, &rc) ||
+                      fan_write_cmd_watchdog(cmd, &rc))) &&
+                   !((fan_control_commands & IBMACPI_FAN_CMD_SPEED) &&
+                     fan_write_cmd_speed(cmd, &rc))
+                   )
+                       rc = -EINVAL;
+               else if (!rc)
+                       fan_watchdog_reset();
+       }
+
+       return rc;
+}
+
+static void fan_watchdog_fire(struct work_struct *ignored)
+{
+       printk(IBM_NOTICE "fan watchdog: enabling fan\n");
+       if (fan_set_enable()) {
+               printk(IBM_ERR "fan watchdog: error while enabling fan\n");
+               /* reschedule for later */
+               fan_watchdog_reset();
+       }
+}
+
 static struct ibm_struct ibms[] = {
        {
         .name = "driver",
@@ -1662,6 +2354,7 @@ static struct ibm_struct ibms[] = {
         .type = ACPI_SYSTEM_NOTIFY,
         },
 #endif
+#ifdef CONFIG_ACPI_IBM_BAY
        {
         .name = "bay",
         .init = bay_init,
@@ -1671,6 +2364,7 @@ static struct ibm_struct ibms[] = {
         .handle = &bay_handle,
         .type = ACPI_SYSTEM_NOTIFY,
         },
+#endif
        {
         .name = "cmos",
         .read = cmos_read,
@@ -1702,6 +2396,8 @@ static struct ibm_struct ibms[] = {
         .name = "brightness",
         .read = brightness_read,
         .write = brightness_write,
+        .init = brightness_init,
+        .exit = brightness_exit,
         },
        {
         .name = "volume",
@@ -1712,6 +2408,8 @@ static struct ibm_struct ibms[] = {
         .name = "fan",
         .read = fan_read,
         .write = fan_write,
+        .init = fan_init,
+        .exit = fan_exit,
         .experimental = 1,
         },
 };
@@ -1719,7 +2417,7 @@ static struct ibm_struct ibms[] = {
 static int dispatch_read(char *page, char **start, off_t off, int count,
                         int *eof, void *data)
 {
-       struct ibm_struct *ibm = (struct ibm_struct *)data;
+       struct ibm_struct *ibm = data;
        int len;
 
        if (!ibm || !ibm->read)
@@ -1744,7 +2442,7 @@ static int dispatch_read(char *page, char **start, off_t off, int count,
 static int dispatch_write(struct file *file, const char __user * userbuf,
                          unsigned long count, void *data)
 {
-       struct ibm_struct *ibm = (struct ibm_struct *)data;
+       struct ibm_struct *ibm = data;
        char *kernbuf;
        int ret;
 
@@ -1773,7 +2471,7 @@ static int dispatch_write(struct file *file, const char __user * userbuf,
 
 static void dispatch_notify(acpi_handle handle, u32 event, void *data)
 {
-       struct ibm_struct *ibm = (struct ibm_struct *)data;
+       struct ibm_struct *ibm = data;
 
        if (!ibm || !ibm->notify)
                return;
@@ -1805,7 +2503,7 @@ static int __init setup_notify(struct ibm_struct *ibm)
                       ibm->name, status);
                return -ENODEV;
        }
-
+       ibm->notify_installed = 1;
        return 0;
 }
 
@@ -1825,7 +2523,7 @@ static int __init register_driver(struct ibm_struct *ibm)
        }
 
        memset(ibm->driver, 0, sizeof(struct acpi_driver));
-       sprintf(ibm->driver->name, "%s/%s", IBM_NAME, ibm->name);
+       sprintf(ibm->driver->name, "%s_%s", IBM_NAME, ibm->name);
        ibm->driver->ids = ibm->hid;
        ibm->driver->ops.add = &ibm_device_add;
 
@@ -1882,7 +2580,6 @@ static int __init ibm_init(struct ibm_struct *ibm)
                ret = setup_notify(ibm);
                if (ret < 0)
                        return ret;
-               ibm->notify_installed = 1;
        }
 
        return 0;
@@ -1954,7 +2651,9 @@ IBM_PARAM(light);
 #ifdef CONFIG_ACPI_IBM_DOCK
 IBM_PARAM(dock);
 #endif
+#ifdef CONFIG_ACPI_IBM_BAY
 IBM_PARAM(bay);
+#endif
 IBM_PARAM(cmos);
 IBM_PARAM(led);
 IBM_PARAM(beep);
@@ -1971,6 +2670,33 @@ static void acpi_ibm_exit(void)
                ibm_exit(&ibms[i]);
 
        remove_proc_entry(IBM_DIR, acpi_root_dir);
+
+       if (ibm_thinkpad_ec_found)
+               kfree(ibm_thinkpad_ec_found);
+}
+
+static char* __init check_dmi_for_ec(void)
+{
+       struct dmi_device *dev = NULL;
+       char ec_fw_string[18];
+
+       /*
+        * ThinkPad T23 or newer, A31 or newer, R50e or newer,
+        * X32 or newer, all Z series;  Some models must have an
+        * up-to-date BIOS or they will not be detected.
+        *
+        * See http://thinkwiki.org/wiki/List_of_DMI_IDs
+        */
+       while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
+               if (sscanf(dev->name,
+                          "IBM ThinkPad Embedded Controller -[%17c",
+                          ec_fw_string) == 1) {
+                       ec_fw_string[sizeof(ec_fw_string) - 1] = 0;
+                       ec_fw_string[strcspn(ec_fw_string, " ]")] = 0;
+                       return kstrdup(ec_fw_string, GFP_KERNEL);
+               }
+       }
+       return NULL;
 }
 
 static int __init acpi_ibm_init(void)
@@ -1992,6 +2718,12 @@ static int __init acpi_ibm_init(void)
                return -ENODEV;
        }
 
+       /* Models with newer firmware report the EC in DMI */
+       ibm_thinkpad_ec_found = check_dmi_for_ec();
+       if (ibm_thinkpad_ec_found)
+               printk(IBM_INFO "ThinkPad EC firmware %s\n",
+                      ibm_thinkpad_ec_found);
+
        /* these handles are not required */
        IBM_HANDLE_INIT(vid);
        IBM_HANDLE_INIT(vid2);
@@ -2004,12 +2736,14 @@ static int __init acpi_ibm_init(void)
        IBM_HANDLE_INIT(dock);
 #endif
        IBM_HANDLE_INIT(pci);
+#ifdef CONFIG_ACPI_IBM_BAY
        IBM_HANDLE_INIT(bay);
        if (bay_handle)
                IBM_HANDLE_INIT(bay_ej);
        IBM_HANDLE_INIT(bay2);
        if (bay2_handle)
                IBM_HANDLE_INIT(bay2_ej);
+#endif
        IBM_HANDLE_INIT(beep);
        IBM_HANDLE_INIT(ecrd);
        IBM_HANDLE_INIT(ecwr);
index e5e448edca41e14e5c2f9ce3265a8ffb1960c23f..bd96a70459256953e405fd58b9a561828528641a 100644 (file)
@@ -248,7 +248,7 @@ int acpi_get_pxm(acpi_handle h)
                handle = phandle;
                status = acpi_evaluate_integer(handle, "_PXM", NULL, &pxm);
                if (ACPI_SUCCESS(status))
-                       return (int)pxm;
+                       return pxm;
                status = acpi_get_parent(handle, &phandle);
        } while (ACPI_SUCCESS(status));
        return -1;
index 02b30ae6a68edf4b8e433e6c0f3f19674d2e6159..57ae1e5cde0a2400f8f060d88d7024dd89ba6ba1 100644 (file)
@@ -568,6 +568,7 @@ void acpi_os_derive_pci_id(acpi_handle rhandle,     /* upper bound  */
 static void acpi_os_execute_deferred(struct work_struct *work)
 {
        struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
+
        if (!dpc) {
                printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
                return;
@@ -1031,7 +1032,7 @@ acpi_status
 acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache)
 {
        *cache = kmem_cache_create(name, size, 0, 0, NULL, NULL);
-       if (cache == NULL)
+       if (*cache == NULL)
                return AE_ERROR;
        else
                return AE_OK;
@@ -1051,7 +1052,7 @@ acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache)
 
 acpi_status acpi_os_purge_cache(acpi_cache_t * cache)
 {
-       (void)kmem_cache_shrink(cache);
+       kmem_cache_shrink(cache);
        return (AE_OK);
 }
 
index 1e2ae6e7a7e47d4e24e1e9af051d447d32178e39..70b440f3f262546e1598ff4c0d943152014f6d1b 100644 (file)
@@ -281,7 +281,7 @@ int acpi_pci_unbind(struct acpi_device *device)
        if (!device || !device->parent)
                return -EINVAL;
 
-       pathname = (char *)kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
+       pathname = kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
        if (!pathname)
                return -ENOMEM;
        memset(pathname, 0, ACPI_PATHNAME_MAX);
@@ -332,7 +332,7 @@ acpi_pci_bind_root(struct acpi_device *device,
        struct acpi_buffer buffer = { 0, NULL };
 
 
-       pathname = (char *)kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
+       pathname = kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
        if (!pathname)
                return -ENOMEM;
        memset(pathname, 0, ACPI_PATHNAME_MAX);
index feda0341f5a73b5a921c6d858de94bf9babfbc4b..226892eaf987f192805571cddc6a567621b2cf6f 100644 (file)
@@ -161,7 +161,7 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
        static int first_time = 1;
 
 
-       pathname = (char *)kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
+       pathname = kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
        if (!pathname)
                return -ENOMEM;
        memset(pathname, 0, ACPI_PATHNAME_MAX);
index d53bd9878ca2ccddcee6cde058d8781c74b698ba..812d733fe8167eeaf539f7a12094bf66c69dd2e1 100644 (file)
@@ -103,7 +103,7 @@ DEFINE_MUTEX(acpi_link_lock);
 static acpi_status
 acpi_pci_link_check_possible(struct acpi_resource *resource, void *context)
 {
-       struct acpi_pci_link *link = (struct acpi_pci_link *)context;
+       struct acpi_pci_link *link = context;
        u32 i = 0;
 
 
@@ -613,7 +613,7 @@ acpi_pci_link_allocate_irq(acpi_handle handle,
                return -1;
        }
 
-       link = (struct acpi_pci_link *)acpi_driver_data(device);
+       link = acpi_driver_data(device);
        if (!link) {
                printk(KERN_ERR PREFIX "Invalid link context\n");
                return -1;
@@ -668,7 +668,7 @@ int acpi_pci_link_free_irq(acpi_handle handle)
                return -1;
        }
 
-       link = (struct acpi_pci_link *)acpi_driver_data(device);
+       link = acpi_driver_data(device);
        if (!link) {
                printk(KERN_ERR PREFIX "Invalid link context\n");
                return -1;
@@ -808,7 +808,7 @@ static int acpi_pci_link_remove(struct acpi_device *device, int type)
        if (!device || !acpi_driver_data(device))
                return -EINVAL;
 
-       link = (struct acpi_pci_link *)acpi_driver_data(device);
+       link = acpi_driver_data(device);
 
        mutex_lock(&acpi_link_lock);
        list_del(&link->node);
index 0984a1ee24edceecbd9593b8da72b139f1fc4201..b9c52cdbf6587bc641026b123cb0d82625b42493 100644 (file)
@@ -98,11 +98,12 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
 
        struct acpi_pci_driver **pptr = &sub_driver;
        while (*pptr) {
-               if (*pptr != driver)
-                       continue;
-               *pptr = (*pptr)->next;
-               break;
+               if (*pptr == driver)
+                       break;
+               pptr = &(*pptr)->next;
        }
+       BUG_ON(!*pptr);
+       *pptr = (*pptr)->next;
 
        if (!driver->remove)
                return;
@@ -119,7 +120,7 @@ EXPORT_SYMBOL(acpi_pci_unregister_driver);
 static acpi_status
 get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
 {
-       int *busnr = (int *)data;
+       int *busnr = data;
        struct acpi_resource_address64 address;
 
        if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 &&
@@ -331,7 +332,7 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type)
        if (!device || !acpi_driver_data(device))
                return -EINVAL;
 
-       root = (struct acpi_pci_root *)acpi_driver_data(device);
+       root = acpi_driver_data(device);
 
        kfree(root);
 
index fe67a8af520ecdb715e020511b028c3b6d7f865c..23a8a9295578e9d408f0c238b56ff2f338b94f54 100644 (file)
@@ -108,7 +108,7 @@ acpi_power_get_context(acpi_handle handle,
                return result;
        }
 
-       *resource = (struct acpi_power_resource *)acpi_driver_data(device);
+       *resource = acpi_driver_data(device);
        if (!resource)
                return -ENODEV;
 
@@ -442,7 +442,7 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
        struct acpi_power_resource *resource = NULL;
 
 
-       resource = (struct acpi_power_resource *)seq->private;
+       resource = seq->private;
 
        if (!resource)
                goto end;
@@ -590,7 +590,7 @@ static int acpi_power_remove(struct acpi_device *device, int type)
        if (!device || !acpi_driver_data(device))
                return -EINVAL;
 
-       resource = (struct acpi_power_resource *)acpi_driver_data(device);
+       resource = acpi_driver_data(device);
 
        acpi_power_remove_fs(device);
 
index 1908e0d202226a47b0f839439a84f599d91649b1..89b3610feb47b6ea3f9317926cc6921b477b3440 100644 (file)
@@ -277,7 +277,7 @@ static struct proc_dir_entry *acpi_processor_dir = NULL;
 
 static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+       struct acpi_processor *pr = seq->private;
 
 
        if (!pr)
@@ -542,12 +542,12 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
         * Don't trust it blindly
         */
        if (processor_device_array[pr->id] != NULL &&
-           processor_device_array[pr->id] != (void *)device) {
+           processor_device_array[pr->id] != device) {
                printk(KERN_WARNING "BIOS reported wrong ACPI id"
                        "for the processor\n");
                return -ENODEV;
        }
-       processor_device_array[pr->id] = (void *)device;
+       processor_device_array[pr->id] = device;
 
        processors[pr->id] = pr;
 
@@ -578,7 +578,7 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
 
 static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
 {
-       struct acpi_processor *pr = (struct acpi_processor *)data;
+       struct acpi_processor *pr = data;
        struct acpi_device *device = NULL;
 
 
@@ -637,7 +637,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
        if (!device || !acpi_driver_data(device))
                return -EINVAL;
 
-       pr = (struct acpi_processor *)acpi_driver_data(device);
+       pr = acpi_driver_data(device);
 
        if (pr->id >= NR_CPUS) {
                kfree(pr);
@@ -901,13 +901,13 @@ static int __init acpi_processor_init(void)
 
        acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
        if (!acpi_processor_dir)
-               return 0;
+               return -ENOMEM;
        acpi_processor_dir->owner = THIS_MODULE;
 
        result = acpi_bus_register_driver(&acpi_processor_driver);
        if (result < 0) {
                remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
-               return 0;
+               return result;
        }
 
        acpi_processor_install_hotplug_notify();
index 65b3f056ad895a7d0f524f7412ff861ce9298649..4f2982cc54782c156dfddda43d0a7a4fd582a86a 100644 (file)
@@ -673,7 +673,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
                return -ENODEV;
        }
 
-       cst = (union acpi_object *)buffer.pointer;
+       cst = buffer.pointer;
 
        /* There must be at least 2 elements */
        if (!cst || (cst->type != ACPI_TYPE_PACKAGE) || cst->package.count < 2) {
@@ -702,14 +702,14 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
 
                memset(&cx, 0, sizeof(cx));
 
-               element = (union acpi_object *)&(cst->package.elements[i]);
+               element = &(cst->package.elements[i]);
                if (element->type != ACPI_TYPE_PACKAGE)
                        continue;
 
                if (element->package.count != 4)
                        continue;
 
-               obj = (union acpi_object *)&(element->package.elements[0]);
+               obj = &(element->package.elements[0]);
 
                if (obj->type != ACPI_TYPE_BUFFER)
                        continue;
@@ -721,7 +721,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
                        continue;
 
                /* There should be an easy way to extract an integer... */
-               obj = (union acpi_object *)&(element->package.elements[1]);
+               obj = &(element->package.elements[1]);
                if (obj->type != ACPI_TYPE_INTEGER)
                        continue;
 
@@ -754,13 +754,13 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
                        }
                }
 
-               obj = (union acpi_object *)&(element->package.elements[2]);
+               obj = &(element->package.elements[2]);
                if (obj->type != ACPI_TYPE_INTEGER)
                        continue;
 
                cx.latency = obj->integer.value;
 
-               obj = (union acpi_object *)&(element->package.elements[3]);
+               obj = &(element->package.elements[3]);
                if (obj->type != ACPI_TYPE_INTEGER)
                        continue;
 
@@ -1029,7 +1029,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
 
 static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+       struct acpi_processor *pr = seq->private;
        unsigned int i;
 
 
index 6fd174a3714958946be4f4b54377c434694824e2..0e60382714bbbacb6d63219b4ba51ff84c3612a0 100644 (file)
@@ -236,7 +236,7 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr)
                return -ENODEV;
        }
 
-       pss = (union acpi_object *)buffer.pointer;
+       pss = buffer.pointer;
        if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
                printk(KERN_ERR PREFIX "Invalid _PSS data\n");
                result = -EFAULT;
@@ -410,7 +410,7 @@ static struct file_operations acpi_processor_perf_fops = {
 
 static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+       struct acpi_processor *pr = seq->private;
        int i;
 
 
@@ -451,8 +451,8 @@ acpi_processor_write_performance(struct file *file,
                                 size_t count, loff_t * data)
 {
        int result = 0;
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       struct acpi_processor *pr = (struct acpi_processor *)m->private;
+       struct seq_file *m = file->private_data;
+       struct acpi_processor *pr = m->private;
        struct acpi_processor_performance *perf;
        char state_string[12] = { '\0' };
        unsigned int new_state = 0;
@@ -551,7 +551,7 @@ static int acpi_processor_get_psd(struct acpi_processor     *pr)
                return -ENODEV;
        }
 
-       psd = (union acpi_object *) buffer.pointer;
+       psd = buffer.pointer;
        if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) {
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
                result = -EFAULT;
index ef5e0f6efdba80922feb73ad7befc79f4f23cd61..40fecd67ad8371674372a77c73e9e3b0fb991cdd 100644 (file)
@@ -208,7 +208,7 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type)
        if (result)
                return result;
 
-       pr = (struct acpi_processor *)acpi_driver_data(device);
+       pr = acpi_driver_data(device);
        if (!pr)
                return -ENODEV;
 
@@ -348,8 +348,8 @@ static ssize_t acpi_processor_write_limit(struct file * file,
                                          size_t count, loff_t * data)
 {
        int result = 0;
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       struct acpi_processor *pr = (struct acpi_processor *)m->private;
+       struct seq_file *m = file->private_data;
+       struct acpi_processor *pr = m->private;
        char limit_string[25] = { '\0' };
        int px = 0;
        int tx = 0;
index d044ec519db0a226404653da9a20cbb079a2f293..0ec7dcde00632945668cbcc1d6383f8c979b6cf0 100644 (file)
@@ -259,7 +259,7 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
 static int acpi_processor_throttling_seq_show(struct seq_file *seq,
                                              void *offset)
 {
-       struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+       struct acpi_processor *pr = seq->private;
        int i = 0;
        int result = 0;
 
@@ -307,8 +307,8 @@ static ssize_t acpi_processor_write_throttling(struct file * file,
                                               size_t count, loff_t * data)
 {
        int result = 0;
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       struct acpi_processor *pr = (struct acpi_processor *)m->private;
+       struct seq_file *m = file->private_data;
+       struct acpi_processor *pr = m->private;
        char state_string[12] = { '\0' };
 
 
index 8908a975e5753ca028179298e008502b774eb3f2..2fb7533314cdfb57cc11b0ba89192766ddf06f7f 100644 (file)
@@ -923,7 +923,7 @@ static struct proc_dir_entry *acpi_battery_dir = NULL;
 
 static int acpi_battery_read_info(struct seq_file *seq, void *offset)
 {
-       struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+       struct acpi_battery *battery = seq->private;
        int cscale;
        int result = 0;
 
@@ -1076,7 +1076,7 @@ static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
 
 static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
 {
-       struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+       struct acpi_battery *battery = seq->private;
        int result = 0;
        int cscale;
 
@@ -1125,8 +1125,8 @@ static ssize_t
 acpi_battery_write_alarm(struct file *file, const char __user * buffer,
                         size_t count, loff_t * ppos)
 {
-       struct seq_file *seq = (struct seq_file *)file->private_data;
-       struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+       struct seq_file *seq = file->private_data;
+       struct acpi_battery *battery = seq->private;
        char alarm_string[12] = { '\0' };
        int result, old_alarm, new_alarm;
 
@@ -1160,14 +1160,14 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer,
        if (result) {
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                                  "acpi_battery_set_alarm() failed\n"));
-               (void)acpi_battery_set_alarm(battery, old_alarm);
+               acpi_battery_set_alarm(battery, old_alarm);
                goto end;
        }
        result = acpi_battery_get_alarm(battery);
        if (result) {
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                                  "acpi_battery_get_alarm() failed\n"));
-               (void)acpi_battery_set_alarm(battery, old_alarm);
+               acpi_battery_set_alarm(battery, old_alarm);
                goto end;
        }
 
@@ -1217,7 +1217,7 @@ static struct proc_dir_entry *acpi_ac_dir = NULL;
 
 static int acpi_ac_read_state(struct seq_file *seq, void *offset)
 {
-       struct acpi_sbs *sbs = (struct acpi_sbs *)seq->private;
+       struct acpi_sbs *sbs = seq->private;
        int result;
 
        if (sbs->zombie) {
@@ -1302,7 +1302,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
                battery->init_state = 1;
        }
 
-       (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
+       sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
 
        result = acpi_sbs_generic_add_fs(&battery->battery_entry,
                                         acpi_battery_dir,
@@ -1485,7 +1485,7 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type)
                }
 
                if (old_battery_present != new_battery_present) {
-                       (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
+                       sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
                        result = acpi_sbs_generate_event(sbs->device,
                                                         ACPI_SBS_BATTERY_NOTIFY_STATUS,
                                                         new_battery_present,
@@ -1498,7 +1498,7 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type)
                        }
                }
                if (old_remaining_capacity != battery->state.remaining_capacity) {
-                       (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
+                       sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
                        result = acpi_sbs_generate_event(sbs->device,
                                                         ACPI_SBS_BATTERY_NOTIFY_STATUS,
                                                         new_battery_present,
@@ -1659,7 +1659,7 @@ static int acpi_sbs_add(struct acpi_device *device)
        init_timer(&sbs->update_timer);
        if (update_mode == QUEUE_UPDATE_MODE) {
                status = acpi_os_execute(OSL_GPE_HANDLER,
-                                        acpi_sbs_update_queue, (void *)sbs);
+                                        acpi_sbs_update_queue, sbs);
                if (status != AE_OK) {
                        ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                                          "acpi_os_execute() failed\n"));
@@ -1685,7 +1685,7 @@ static int acpi_sbs_add(struct acpi_device *device)
 
 int acpi_sbs_remove(struct acpi_device *device, int type)
 {
-       struct acpi_sbs *sbs = NULL;
+       struct acpi_sbs *sbs;
        int id;
 
        if (!device) {
index af1dbabaf0b1d299277fe65727eed95778751c1d..fab8f2694f03284bf23f3dd256cd1a811ae6727f 100644 (file)
@@ -183,11 +183,11 @@ late_initcall(acpi_wakeup_device_init);
 #endif
 
 /*
- * Disable all wakeup GPEs before power off.
- * 
+ * Disable all wakeup GPEs before entering requested sleep state.
+ *     @sleep_state:   ACPI state
  * Since acpi_enter_sleep_state() will disable all
  * RUNTIME GPEs, we simply mark all GPES that
- * are not enabled for wakeup from S5 as RUNTIME.
+ * are not enabled for wakeup from requested state as RUNTIME.
  */
 void acpi_gpe_sleep_prepare(u32 sleep_state)
 {
index bfb3bfcf9e91017a4d35ec51b073076c7f724829..ffa30c9fccbfbfd7e5a9c069edab2ee0aa9d3ae0 100644 (file)
@@ -228,7 +228,7 @@ void acpi_table_print_madt_entry(acpi_table_entry_header * header)
 static int
 acpi_table_compute_checksum(void *table_pointer, unsigned long length)
 {
-       u8 *p = (u8 *) table_pointer;
+       u8 *p = table_pointer;
        unsigned long remains = length;
        unsigned long sum = 0;
 
index 5753d06b786021e0434a221cd79b6c46875c8b36..4d75085ca2d2e13ec89c2d6a131ec01c1d4c2310 100644 (file)
@@ -663,7 +663,7 @@ static void acpi_thermal_run(unsigned long data)
 static void acpi_thermal_check(void *data)
 {
        int result = 0;
-       struct acpi_thermal *tz = (struct acpi_thermal *)data;
+       struct acpi_thermal *tz = data;
        unsigned long sleep_time = 0;
        int i = 0;
        struct acpi_thermal_state state;
@@ -778,7 +778,7 @@ static struct proc_dir_entry *acpi_thermal_dir;
 
 static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+       struct acpi_thermal *tz = seq->private;
 
 
        if (!tz)
@@ -813,7 +813,7 @@ static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file)
 static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset)
 {
        int result = 0;
-       struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+       struct acpi_thermal *tz = seq->private;
 
 
        if (!tz)
@@ -837,7 +837,7 @@ static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file)
 
 static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+       struct acpi_thermal *tz = seq->private;
        int i = 0;
        int j = 0;
 
@@ -893,8 +893,8 @@ acpi_thermal_write_trip_points(struct file *file,
                               const char __user * buffer,
                               size_t count, loff_t * ppos)
 {
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
+       struct seq_file *m = file->private_data;
+       struct acpi_thermal *tz = m->private;
 
        char *limit_string;
        int num, critical, hot, passive;
@@ -953,7 +953,7 @@ acpi_thermal_write_trip_points(struct file *file,
 
 static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+       struct acpi_thermal *tz = seq->private;
 
 
        if (!tz)
@@ -984,8 +984,8 @@ acpi_thermal_write_cooling_mode(struct file *file,
                                const char __user * buffer,
                                size_t count, loff_t * ppos)
 {
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
+       struct seq_file *m = file->private_data;
+       struct acpi_thermal *tz = m->private;
        int result = 0;
        char mode_string[12] = { '\0' };
 
@@ -1014,7 +1014,7 @@ acpi_thermal_write_cooling_mode(struct file *file,
 
 static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+       struct acpi_thermal *tz = seq->private;
 
 
        if (!tz)
@@ -1043,8 +1043,8 @@ acpi_thermal_write_polling(struct file *file,
                           const char __user * buffer,
                           size_t count, loff_t * ppos)
 {
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
+       struct seq_file *m = file->private_data;
+       struct acpi_thermal *tz = m->private;
        int result = 0;
        char polling_string[12] = { '\0' };
        int seconds = 0;
@@ -1170,7 +1170,7 @@ static int acpi_thermal_remove_fs(struct acpi_device *device)
 
 static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
 {
-       struct acpi_thermal *tz = (struct acpi_thermal *)data;
+       struct acpi_thermal *tz = data;
        struct acpi_device *device = NULL;
 
 
@@ -1324,7 +1324,7 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
        if (!device || !acpi_driver_data(device))
                return -EINVAL;
 
-       tz = (struct acpi_thermal *)acpi_driver_data(device);
+       tz = acpi_driver_data(device);
 
        /* avoid timer adding new defer task */
        tz->zombie = 1;
@@ -1364,7 +1364,7 @@ static int acpi_thermal_resume(struct acpi_device *device, int state)
        if (!device || !acpi_driver_data(device))
                return -EINVAL;
 
-       tz = (struct acpi_thermal *)acpi_driver_data(device);
+       tz = acpi_driver_data(device);
 
        acpi_thermal_get_temperature(tz);
 
index 7fe0b7ae973397b8920b624887dce1462f7e6b4b..88aeccbafaaf9e46ed4678b573e0f28cc6a6f5f2 100644 (file)
@@ -41,6 +41,8 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
+#include <linux/backlight.h>
+
 #include <asm/uaccess.h>
 
 #include <acpi/acpi_drivers.h>
@@ -210,6 +212,7 @@ static acpi_status hci_read1(u32 reg, u32 * out1, u32 * result)
 }
 
 static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ;
+static struct backlight_device *toshiba_backlight_device;
 static int force_fan;
 static int last_key_event;
 static int key_event_valid;
@@ -271,14 +274,23 @@ dispatch_write(struct file *file, const char __user * buffer,
        return result;
 }
 
-static char *read_lcd(char *p)
+static int get_lcd(struct backlight_device *bd)
 {
        u32 hci_result;
        u32 value;
 
        hci_read1(HCI_LCD_BRIGHTNESS, &value, &hci_result);
        if (hci_result == HCI_SUCCESS) {
-               value = value >> HCI_LCD_BRIGHTNESS_SHIFT;
+               return (value >> HCI_LCD_BRIGHTNESS_SHIFT);
+       } else
+               return -EFAULT;
+}
+
+static char *read_lcd(char *p)
+{
+       int value = get_lcd(NULL);
+
+       if (value >= 0) {
                p += sprintf(p, "brightness:              %d\n", value);
                p += sprintf(p, "brightness_levels:       %d\n",
                             HCI_LCD_BRIGHTNESS_LEVELS);
@@ -289,22 +301,34 @@ static char *read_lcd(char *p)
        return p;
 }
 
+static int set_lcd(int value)
+{
+       u32 hci_result;
+
+       value = value << HCI_LCD_BRIGHTNESS_SHIFT;
+       hci_write1(HCI_LCD_BRIGHTNESS, value, &hci_result);
+       if (hci_result != HCI_SUCCESS)
+               return -EFAULT;
+
+       return 0;
+}
+
+static int set_lcd_status(struct backlight_device *bd)
+{
+       return set_lcd(bd->props->brightness);
+}
+
 static unsigned long write_lcd(const char *buffer, unsigned long count)
 {
        int value;
-       u32 hci_result;
+       int ret = count;
 
        if (sscanf(buffer, " brightness : %i", &value) == 1 &&
-           value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
-               value = value << HCI_LCD_BRIGHTNESS_SHIFT;
-               hci_write1(HCI_LCD_BRIGHTNESS, value, &hci_result);
-               if (hci_result != HCI_SUCCESS)
-                       return -EFAULT;
-       } else {
-               return -EINVAL;
-       }
-
-       return count;
+           value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS)
+               ret = set_lcd(value);
+       else
+               ret = -EINVAL;
+       return ret;
 }
 
 static char *read_video(char *p)
@@ -506,6 +530,26 @@ static acpi_status __exit remove_device(void)
        return AE_OK;
 }
 
+static struct backlight_properties toshiba_backlight_data = {
+        .owner          = THIS_MODULE,
+        .get_brightness = get_lcd,
+        .update_status  = set_lcd_status,
+        .max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1,
+};
+
+static void __exit toshiba_acpi_exit(void)
+{
+       if (toshiba_backlight_device)
+               backlight_device_unregister(toshiba_backlight_device);
+
+       remove_device();
+
+       if (toshiba_proc_dir)
+               remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
+
+       return;
+}
+
 static int __init toshiba_acpi_init(void)
 {
        acpi_status status = AE_OK;
@@ -546,17 +590,16 @@ static int __init toshiba_acpi_init(void)
                        remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
        }
 
-       return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;
-}
-
-static void __exit toshiba_acpi_exit(void)
-{
-       remove_device();
-
-       if (toshiba_proc_dir)
-               remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
+       toshiba_backlight_device = backlight_device_register("toshiba",NULL,
+                                               NULL,
+                                               &toshiba_backlight_data);
+        if (IS_ERR(toshiba_backlight_device)) {
+               printk(KERN_ERR "Could not register toshiba backlight device\n");
+               toshiba_backlight_device = NULL;
+               toshiba_acpi_exit();
+       }
 
-       return;
+       return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;
 }
 
 module_init(toshiba_acpi_init);
index bb1eaf9aa65370e4b30889159178713ad2fa346e..9e9054e155c17837549049dfe4a4dfd186402e4a 100644 (file)
@@ -180,8 +180,9 @@ acpi_ut_debug_print(u32 requested_debug_level,
        if (thread_id != acpi_gbl_prev_thread_id) {
                if (ACPI_LV_THREADS & acpi_dbg_level) {
                        acpi_os_printf
-                           ("\n**** Context Switch from TID %X to TID %X ****\n\n",
-                            (u32) acpi_gbl_prev_thread_id, (u32) thread_id);
+                           ("\n**** Context Switch from TID %lX to TID %lX ****\n\n",
+                            (unsigned long) acpi_gbl_prev_thread_id,
+                            (unsigned long) thread_id);
                }
 
                acpi_gbl_prev_thread_id = thread_id;
index c39062a047cd5c65b86aef83b9a11174e9e93a4e..180e73ceb6e2cc6566c7855563adc09e48bac8af 100644 (file)
@@ -243,23 +243,24 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
 #endif
 
        ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
-                         "Thread %X attempting to acquire Mutex [%s]\n",
-                         (u32) this_thread_id, acpi_ut_get_mutex_name(mutex_id)));
+                         "Thread %lX attempting to acquire Mutex [%s]\n",
+                         (unsigned long) this_thread_id,
+                         acpi_ut_get_mutex_name(mutex_id)));
 
        status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex,
                                       ACPI_WAIT_FOREVER);
        if (ACPI_SUCCESS(status)) {
                ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
-                                 "Thread %X acquired Mutex [%s]\n",
-                                 (u32) this_thread_id,
+                                 "Thread %lX acquired Mutex [%s]\n",
+                                 (unsigned long) this_thread_id,
                                  acpi_ut_get_mutex_name(mutex_id)));
 
                acpi_gbl_mutex_info[mutex_id].use_count++;
                acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id;
        } else {
                ACPI_EXCEPTION((AE_INFO, status,
-                               "Thread %X could not acquire Mutex [%X]",
-                               (u32) this_thread_id, mutex_id));
+                               "Thread %lX could not acquire Mutex [%X]",
+                               (unsigned long) this_thread_id, mutex_id));
        }
 
        return (status);
@@ -285,7 +286,8 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
 
        this_thread_id = acpi_os_get_thread_id();
        ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
-                         "Thread %X releasing Mutex [%s]\n", (u32) this_thread_id,
+                         "Thread %lX releasing Mutex [%s]\n",
+                         (unsigned long) this_thread_id,
                          acpi_ut_get_mutex_name(mutex_id)));
 
        if (mutex_id > ACPI_MAX_MUTEX) {
index d0d84c43a9d4c547591a6e43ffb8b8857dc90a63..91fed70a65a6dbe946e2b3370bd40d9223600b90 100644 (file)
@@ -83,7 +83,7 @@ acpi_extract_package(union acpi_object *package,
                return AE_BAD_DATA;
        }
 
-       format_string = (char *)format->pointer;
+       format_string = format->pointer;
 
        /*
         * Calculate size_required.
@@ -361,7 +361,7 @@ acpi_evaluate_reference(acpi_handle handle,
        if (ACPI_FAILURE(status))
                goto end;
 
-       package = (union acpi_object *)buffer.pointer;
+       package = buffer.pointer;
 
        if ((buffer.length == 0) || !package) {
                printk(KERN_ERR PREFIX "No return object (len %X ptr %p)\n",
index 56666a9824760bc0fbf569aba85518a38ce995cb..eb5141f9ef8f80a51e1ba1012e504bc7ff7ad9ae 100644 (file)
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
  *  Copyright (C) 2004 Bruno Ducrot <ducrot@poupinou.org>
+ *  Copyright (C) 2006 Thomas Tuttle <linux-kernel@ttuttle.net>
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
 #define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT  0x83
 #define ACPI_VIDEO_NOTIFY_PREV_OUTPUT  0x84
 
-#define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS     0x82
-#define        ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS        0x83
-#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS       0x84
-#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS      0x85
-#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF          0x86
+#define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS     0x85
+#define        ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS        0x86
+#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS       0x87
+#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS      0x88
+#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF          0x89
 
 #define ACPI_VIDEO_HEAD_INVALID                (~0u - 1)
 #define ACPI_VIDEO_HEAD_END            (~0u)
@@ -386,7 +387,7 @@ acpi_video_device_EDID(struct acpi_video_device *device,
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
-       obj = (union acpi_object *)buffer.pointer;
+       obj = buffer.pointer;
 
        if (obj && obj->type == ACPI_TYPE_BUFFER)
                *edid = obj;
@@ -654,8 +655,7 @@ static struct proc_dir_entry *acpi_video_dir;
 
 static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_video_device *dev =
-           (struct acpi_video_device *)seq->private;
+       struct acpi_video_device *dev = seq->private;
 
 
        if (!dev)
@@ -688,8 +688,7 @@ acpi_video_device_info_open_fs(struct inode *inode, struct file *file)
 static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset)
 {
        int status;
-       struct acpi_video_device *dev =
-           (struct acpi_video_device *)seq->private;
+       struct acpi_video_device *dev = seq->private;
        unsigned long state;
 
 
@@ -727,8 +726,8 @@ acpi_video_device_write_state(struct file *file,
                              size_t count, loff_t * data)
 {
        int status;
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       struct acpi_video_device *dev = (struct acpi_video_device *)m->private;
+       struct seq_file *m = file->private_data;
+       struct acpi_video_device *dev = m->private;
        char str[12] = { 0 };
        u32 state = 0;
 
@@ -754,8 +753,7 @@ acpi_video_device_write_state(struct file *file,
 static int
 acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_video_device *dev =
-           (struct acpi_video_device *)seq->private;
+       struct acpi_video_device *dev = seq->private;
        int i;
 
 
@@ -784,8 +782,8 @@ acpi_video_device_write_brightness(struct file *file,
                                   const char __user * buffer,
                                   size_t count, loff_t * data)
 {
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       struct acpi_video_device *dev = (struct acpi_video_device *)m->private;
+       struct seq_file *m = file->private_data;
+       struct acpi_video_device *dev = m->private;
        char str[4] = { 0 };
        unsigned int level = 0;
        int i;
@@ -817,8 +815,7 @@ acpi_video_device_write_brightness(struct file *file,
 
 static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_video_device *dev =
-           (struct acpi_video_device *)seq->private;
+       struct acpi_video_device *dev = seq->private;
        int status;
        int i;
        union acpi_object *edid = NULL;
@@ -866,7 +863,7 @@ static int acpi_video_device_add_fs(struct acpi_device *device)
        if (!device)
                return -ENODEV;
 
-       vid_dev = (struct acpi_video_device *)acpi_driver_data(device);
+       vid_dev = acpi_driver_data(device);
        if (!vid_dev)
                return -ENODEV;
 
@@ -931,7 +928,7 @@ static int acpi_video_device_remove_fs(struct acpi_device *device)
 {
        struct acpi_video_device *vid_dev;
 
-       vid_dev = (struct acpi_video_device *)acpi_driver_data(device);
+       vid_dev = acpi_driver_data(device);
        if (!vid_dev || !vid_dev->video || !vid_dev->video->dir)
                return -ENODEV;
 
@@ -950,7 +947,7 @@ static int acpi_video_device_remove_fs(struct acpi_device *device)
 /* video bus */
 static int acpi_video_bus_info_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
+       struct acpi_video_bus *video = seq->private;
 
 
        if (!video)
@@ -975,7 +972,7 @@ static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file)
 
 static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
+       struct acpi_video_bus *video = seq->private;
 
 
        if (!video)
@@ -995,7 +992,7 @@ static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file)
 
 static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
+       struct acpi_video_bus *video = seq->private;
        unsigned long options;
        int status;
 
@@ -1033,7 +1030,7 @@ acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file)
 
 static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
+       struct acpi_video_bus *video = seq->private;
        int status;
        unsigned long id;
 
@@ -1054,7 +1051,7 @@ static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
 
 static int acpi_video_bus_DOS_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
+       struct acpi_video_bus *video = seq->private;
 
 
        seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting);
@@ -1079,8 +1076,8 @@ acpi_video_bus_write_POST(struct file *file,
                          size_t count, loff_t * data)
 {
        int status;
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       struct acpi_video_bus *video = (struct acpi_video_bus *)m->private;
+       struct seq_file *m = file->private_data;
+       struct acpi_video_bus *video = m->private;
        char str[12] = { 0 };
        unsigned long opt, options;
 
@@ -1119,8 +1116,8 @@ acpi_video_bus_write_DOS(struct file *file,
                         size_t count, loff_t * data)
 {
        int status;
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       struct acpi_video_bus *video = (struct acpi_video_bus *)m->private;
+       struct seq_file *m = file->private_data;
+       struct acpi_video_bus *video = m->private;
        char str[12] = { 0 };
        unsigned long opt;
 
@@ -1150,7 +1147,7 @@ static int acpi_video_bus_add_fs(struct acpi_device *device)
        struct acpi_video_bus *video;
 
 
-       video = (struct acpi_video_bus *)acpi_driver_data(device);
+       video = acpi_driver_data(device);
 
        if (!acpi_device_dir(device)) {
                acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
@@ -1226,7 +1223,7 @@ static int acpi_video_bus_remove_fs(struct acpi_device *device)
        struct acpi_video_bus *video;
 
 
-       video = (struct acpi_video_bus *)acpi_driver_data(device);
+       video = acpi_driver_data(device);
 
        if (acpi_device_dir(device)) {
                remove_proc_entry("info", acpi_device_dir(device));
@@ -1403,7 +1400,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
                return status;
        }
 
-       dod = (union acpi_object *)buffer.pointer;
+       dod = buffer.pointer;
        if (!dod || (dod->type != ACPI_TYPE_PACKAGE)) {
                ACPI_EXCEPTION((AE_INFO, status, "Invalid _DOD data"));
                status = -EFAULT;
@@ -1426,7 +1423,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
 
        count = 0;
        for (i = 0; i < dod->package.count; i++) {
-               obj = (union acpi_object *)&dod->package.elements[i];
+               obj = &dod->package.elements[i];
 
                if (obj->type != ACPI_TYPE_INTEGER) {
                        printk(KERN_ERR PREFIX "Invalid _DOD data\n");
@@ -1509,8 +1506,34 @@ static int
 acpi_video_get_next_level(struct acpi_video_device *device,
                          u32 level_current, u32 event)
 {
-       /*Fix me */
-       return level_current;
+       int min, max, min_above, max_below, i, l;
+       max = max_below = 0;
+       min = min_above = 255;
+       for (i = 0; i < device->brightness->count; i++) {
+               l = device->brightness->levels[i];
+               if (l < min)
+                       min = l;
+               if (l > max)
+                       max = l;
+               if (l < min_above && l > level_current)
+                       min_above = l;
+               if (l > max_below && l < level_current)
+                       max_below = l;
+       }
+
+       switch (event) {
+       case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS:
+               return (level_current < max) ? min_above : min;
+       case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS:
+               return (level_current < max) ? min_above : max;
+       case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS:
+               return (level_current > min) ? max_below : min;
+       case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS:
+       case ACPI_VIDEO_NOTIFY_DISPLAY_OFF:
+               return 0;
+       default:
+               return level_current;
+       }
 }
 
 static void
@@ -1612,7 +1635,7 @@ static int acpi_video_bus_stop_devices(struct acpi_video_bus *video)
 
 static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
 {
-       struct acpi_video_bus *video = (struct acpi_video_bus *)data;
+       struct acpi_video_bus *video = data;
        struct acpi_device *device = NULL;
 
        printk("video bus notify\n");
@@ -1654,8 +1677,7 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
 
 static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
 {
-       struct acpi_video_device *video_device =
-           (struct acpi_video_device *)data;
+       struct acpi_video_device *video_device = data;
        struct acpi_device *device = NULL;
 
 
@@ -1757,7 +1779,7 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type)
        if (!device || !acpi_driver_data(device))
                return -EINVAL;
 
-       video = (struct acpi_video_bus *)acpi_driver_data(device);
+       video = acpi_driver_data(device);
 
        acpi_video_bus_stop_devices(video);
 
index fdb7153f4426c42b35be5e1206424c984f4de5ea..8e5e07e4c1cf6b91219148ad82bf10f1469fe3e6 100644 (file)
@@ -317,7 +317,8 @@ static int __init msi_init(void)
 
        /* Register backlight stuff */
 
-       msibl_device = backlight_device_register("msi-laptop-bl", NULL, &msibl_props);
+       msibl_device = backlight_device_register("msi-laptop-bl", NULL, NULL,
+                                               &msibl_props);
        if (IS_ERR(msibl_device))
                return PTR_ERR(msibl_device);
 
index 02cbb7fff24f0c5e812450fc476b4ea2bc5f804b..a7932a72d2988425de04921eba702eabe85e9121 100644 (file)
@@ -281,7 +281,7 @@ static int appledisplay_probe(struct usb_interface *iface,
        /* Register backlight device */
        snprintf(bl_name, sizeof(bl_name), "appledisplay%d",
                atomic_inc_return(&count_displays) - 1);
-       pdata->bd = backlight_device_register(bl_name, pdata,
+       pdata->bd = backlight_device_register(bl_name, NULL, NULL,
                                                &appledisplay_bl_data);
        if (IS_ERR(pdata->bd)) {
                err("appledisplay: Backlight registration failed");
index 3feddf89d100b881bf75aa69aa2be55fa8bc42be..2e976ffcde0fa53a3977da6e05ed1f61884f99c3 100644 (file)
@@ -1834,7 +1834,7 @@ static void aty128_bl_init(struct aty128fb_par *par)
 
        snprintf(name, sizeof(name), "aty128bl%d", info->node);
 
-       bd = backlight_device_register(name, par, &aty128_bl_data);
+       bd = backlight_device_register(name, info->dev, par, &aty128_bl_data);
        if (IS_ERR(bd)) {
                info->bl_dev = NULL;
                printk(KERN_WARNING "aty128: Backlight registration failed\n");
index 09684d7a7ce942c8458d23fcad35f3cfa161958c..f2ebdd880085a6f69183160fa667062e3c499148 100644 (file)
@@ -2211,7 +2211,7 @@ static void aty_bl_init(struct atyfb_par *par)
 
        snprintf(name, sizeof(name), "atybl%d", info->node);
 
-       bd = backlight_device_register(name, par, &aty_bl_data);
+       bd = backlight_device_register(name, info->dev, par, &aty_bl_data);
        if (IS_ERR(bd)) {
                info->bl_dev = NULL;
                printk(KERN_WARNING "aty: Backlight registration failed\n");
index 585eb7b9e63610f43b523cde48a3414c3d6b5e5f..3abfd4a380cc22c229520d3eaba7d728c0330001 100644 (file)
@@ -163,7 +163,7 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo)
 
        snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node);
 
-       bd = backlight_device_register(name, pdata, &radeon_bl_data);
+       bd = backlight_device_register(name, rinfo->info->dev, pdata, &radeon_bl_data);
        if (IS_ERR(bd)) {
                rinfo->info->bl_dev = NULL;
                printk("radeonfb: Backlight registration failed\n");
index db8c191b12013e941c1ab61cea7db7101763bdc0..9601bfe309ac2744c922a1f612eb4b6188e12aa0 100644 (file)
@@ -216,8 +216,10 @@ static const struct class_device_attribute bl_class_device_attributes[] = {
  * Creates and registers new backlight class_device. Returns either an
  * ERR_PTR() or a pointer to the newly allocated device.
  */
-struct backlight_device *backlight_device_register(const char *name, void *devdata,
-                                                  struct backlight_properties *bp)
+struct backlight_device *backlight_device_register(const char *name,
+       struct device *dev,
+       void *devdata,
+       struct backlight_properties *bp)
 {
        int i, rc;
        struct backlight_device *new_bd;
@@ -232,6 +234,7 @@ struct backlight_device *backlight_device_register(const char *name, void *devda
        new_bd->props = bp;
        memset(&new_bd->class_dev, 0, sizeof(new_bd->class_dev));
        new_bd->class_dev.class = &backlight_class;
+       new_bd->class_dev.dev = dev;
        strlcpy(new_bd->class_dev.class_id, name, KOBJ_NAME_LEN);
        class_set_devdata(&new_bd->class_dev, devdata);
 
index 5b75ae4e945704b8fca10b84befbea176374012a..df934bd218994882e9dda27457ef8575890e274d 100644 (file)
@@ -141,7 +141,7 @@ void nvidia_bl_init(struct nvidia_par *par)
 
        snprintf(name, sizeof(name), "nvidiabl%d", info->node);
 
-       bd = backlight_device_register(name, par, &nvidia_bl_data);
+       bd = backlight_device_register(name, info->dev, par, &nvidia_bl_data);
        if (IS_ERR(bd)) {
                info->bl_dev = NULL;
                printk(KERN_WARNING "nvidia: Backlight registration failed\n");
index 345e8b1c1af86cbc89378ca988dd28ca40d89224..1a13966b7d5b04d5aaa3a45a0b72e68638982806 100644 (file)
@@ -384,7 +384,7 @@ static void riva_bl_init(struct riva_par *par)
 
        snprintf(name, sizeof(name), "rivabl%d", info->node);
 
-       bd = backlight_device_register(name, par, &riva_bl_data);
+       bd = backlight_device_register(name, info->dev, par, &riva_bl_data);
        if (IS_ERR(bd)) {
                info->bl_dev = NULL;
                printk(KERN_WARNING "riva: Backlight registration failed\n");
index c80b3a94511a32c1799d020b02b9f0b428996192..7cfad93edf10085ae2b84e1a9700e1fcdba41ba1 100644 (file)
 #define ACPI_ENABLE_IRQS()  local_irq_enable()
 #define ACPI_FLUSH_CPU_CACHE() wbinvd()
 
-
-static inline int
-__acpi_acquire_global_lock (unsigned int *lock)
-{
-       unsigned int old, new, val;
-       do {
-               old = *lock;
-               new = (((old & ~0x3) + 2) + ((old >> 1) & 0x1));
-               val = cmpxchg(lock, old, new);
-       } while (unlikely (val != old));
-       return (new < 3) ? -1 : 0;
-}
-
-static inline int
-__acpi_release_global_lock (unsigned int *lock)
-{
-       unsigned int old, new, val;
-       do {
-               old = *lock;
-               new = old & ~0x3;
-               val = cmpxchg(lock, old, new);
-       } while (unlikely (val != old));
-       return old & 0x1;
-}
+int __acpi_acquire_global_lock(unsigned int *lock);
+int __acpi_release_global_lock(unsigned int *lock);
 
 #define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \
        ((Acq) = __acpi_acquire_global_lock((unsigned int *) GLptr))
index 9d1916e59c04f22eeff10646d39ca4b879bd9117..6b6fc6f8be7edb75e7f761bd43180a2a603eeadc 100644 (file)
 #define ACPI_ENABLE_IRQS()  local_irq_enable()
 #define ACPI_FLUSH_CPU_CACHE() wbinvd()
 
-
-static inline int
-__acpi_acquire_global_lock (unsigned int *lock)
-{
-       unsigned int old, new, val;
-       do {
-               old = *lock;
-               new = (((old & ~0x3) + 2) + ((old >> 1) & 0x1));
-               val = cmpxchg(lock, old, new);
-       } while (unlikely (val != old));
-       return (new < 3) ? -1 : 0;
-}
-
-static inline int
-__acpi_release_global_lock (unsigned int *lock)
-{
-       unsigned int old, new, val;
-       do {
-               old = *lock;
-               new = old & ~0x3;
-               val = cmpxchg(lock, old, new);
-       } while (unlikely (val != old));
-       return old & 0x1;
-}
+int __acpi_acquire_global_lock(unsigned int *lock);
+int __acpi_release_global_lock(unsigned int *lock);
 
 #define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \
        ((Acq) = __acpi_acquire_global_lock((unsigned int *) GLptr))
index 75e91f5b6a04ce7dc0626599d9d21ac08f8b3059..a5cf1beacb443a18edbfcd1767e2866a24dc6299 100644 (file)
@@ -54,7 +54,7 @@ struct backlight_device {
 };
 
 extern struct backlight_device *backlight_device_register(const char *name,
-       void *devdata, struct backlight_properties *bp);
+       struct device *dev,void *devdata,struct backlight_properties *bp);
 extern void backlight_device_unregister(struct backlight_device *bd);
 
 #define to_backlight_device(obj) container_of(obj, struct backlight_device, class_dev)
index 0b00f56c2ad0ad369fdaa42d40e24c6f56720881..88fc5d7ac737402c18db0306049b5873effeed55 100644 (file)
@@ -60,9 +60,11 @@ static void power_down(suspend_disk_method_t mode)
 {
        switch(mode) {
        case PM_DISK_PLATFORM:
-               kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
-               pm_ops->enter(PM_SUSPEND_DISK);
-               break;
+               if (pm_ops && pm_ops->enter) {
+                       kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
+                       pm_ops->enter(PM_SUSPEND_DISK);
+                       break;
+               }
        case PM_DISK_SHUTDOWN:
                kernel_power_off();
                break;
index 500eb87f643dd9ff56d08079a29c506e7140b777..ff3a6182f5f0df3fb479cbd56092dd0ee8e1ff2e 100644 (file)
@@ -29,7 +29,7 @@
 DEFINE_MUTEX(pm_mutex);
 
 struct pm_ops *pm_ops;
-suspend_disk_method_t pm_disk_mode = PM_DISK_SHUTDOWN;
+suspend_disk_method_t pm_disk_mode = PM_DISK_PLATFORM;
 
 /**
  *     pm_set_ops - Set the global power method table.