Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
authorLinus Torvalds <torvalds@g5.osdl.org>
Tue, 4 Jul 2006 04:32:50 +0000 (21:32 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Tue, 4 Jul 2006 04:32:50 +0000 (21:32 -0700)
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (44 commits)
  ACPI: remove function tracing macros from drivers/acpi/*.c
  ACPI: add support for Smart Battery
  ACPI: handle battery notify event on broken BIOS
  ACPI: handle AC notify event on broken BIOS
  ACPI: asus_acpi: add S1N WLED control
  ACPI: asus_acpi: correct M6N/M6R display nodes
  ACPI: asus_acpi: add S1N WLED control
  ACPI: asus_acpi: rework model detection
  ACPI: asus_acpi: support L5D
  ACPI: asus_acpi: handle internal Bluetooth / support W5A
  ACPI: asus_acpi: support A4G
  ACPI: asus_acpi: support W3400N
  ACPI: asus_acpi: LED display support
  ACPI: asus_acpi: support A3G
  ACPI: asus_acpi: misc cleanups
  ACPI: video: Remove unneeded acpi_handle from driver.
  ACPI: thermal: Remove unneeded acpi_handle from driver.
  ACPI: power: Remove unneeded acpi_handle from driver.
  ACPI: pci_root: Remove unneeded acpi_handle from driver.
  ACPI: pci_link: Remove unneeded acpi_handle from driver.
  ...

33 files changed:
arch/ia64/kernel/acpi-ext.c
arch/ia64/kernel/acpi.c
drivers/acpi/Kconfig
drivers/acpi/Makefile
drivers/acpi/ac.c
drivers/acpi/acpi_memhotplug.c
drivers/acpi/asus_acpi.c
drivers/acpi/battery.c
drivers/acpi/button.c
drivers/acpi/cm_sbs.c [new file with mode: 0644]
drivers/acpi/container.c
drivers/acpi/fan.c
drivers/acpi/glue.c
drivers/acpi/i2c_ec.c [new file with mode: 0644]
drivers/acpi/i2c_ec.h [new file with mode: 0644]
drivers/acpi/namespace/nsxfeval.c
drivers/acpi/numa.c
drivers/acpi/osl.c
drivers/acpi/pci_link.c
drivers/acpi/pci_root.c
drivers/acpi/power.c
drivers/acpi/processor_idle.c
drivers/acpi/processor_perflib.c
drivers/acpi/sbs.c [new file with mode: 0644]
drivers/acpi/scan.c
drivers/acpi/system.c
drivers/acpi/thermal.c
drivers/acpi/utilities/utalloc.c
drivers/acpi/utilities/utcache.c
drivers/acpi/utils.c
drivers/acpi/video.c
include/acpi/acmacros.h
include/acpi/acpiosxf.h

index 2a1ef74..b7515bc 100644 (file)
@@ -50,7 +50,7 @@ static acpi_status hp_ccsr_locate(acpi_handle obj, u64 *base, u64 *length)
        memcpy(length, vendor->byte_data + 8, sizeof(*length));
 
   exit:
-       acpi_os_free(buffer.pointer);
+       kfree(buffer.pointer);
        return status;
 }
 
index ccdef19..99761b8 100644 (file)
@@ -856,7 +856,7 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu)
        obj = buffer.pointer;
        if (obj->type != ACPI_TYPE_BUFFER ||
            obj->buffer.length < sizeof(*lsapic)) {
-               acpi_os_free(buffer.pointer);
+               kfree(buffer.pointer);
                return -EINVAL;
        }
 
@@ -864,13 +864,13 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu)
 
        if ((lsapic->header.type != ACPI_MADT_LSAPIC) ||
            (!lsapic->flags.enabled)) {
-               acpi_os_free(buffer.pointer);
+               kfree(buffer.pointer);
                return -EINVAL;
        }
 
        physid = ((lsapic->id << 8) | (lsapic->eid));
 
-       acpi_os_free(buffer.pointer);
+       kfree(buffer.pointer);
        buffer.length = ACPI_ALLOCATE_BUFFER;
        buffer.pointer = NULL;
 
@@ -934,20 +934,20 @@ acpi_map_iosapic(acpi_handle handle, u32 depth, void *context, void **ret)
        obj = buffer.pointer;
        if (obj->type != ACPI_TYPE_BUFFER ||
            obj->buffer.length < sizeof(*iosapic)) {
-               acpi_os_free(buffer.pointer);
+               kfree(buffer.pointer);
                return AE_OK;
        }
 
        iosapic = (struct acpi_table_iosapic *)obj->buffer.pointer;
 
        if (iosapic->header.type != ACPI_MADT_IOSAPIC) {
-               acpi_os_free(buffer.pointer);
+               kfree(buffer.pointer);
                return AE_OK;
        }
 
        gsi_base = iosapic->global_irq_base;
 
-       acpi_os_free(buffer.pointer);
+       kfree(buffer.pointer);
 
        /*
         * OK, it's an IOSAPIC MADT entry, look for a _PXM value to tell
index bc2652d..fef7bab 100644 (file)
@@ -352,6 +352,18 @@ config ACPI_HOTPLUG_MEMORY
          If one selects "m," this driver can be loaded using the following
          command: 
                $>modprobe acpi_memhotplug 
+
+config ACPI_SBS
+       tristate "Smart Battery System (EXPERIMENTAL)"
+       depends on X86 && I2C
+       depends on EXPERIMENTAL
+       default y
+       help
+         This driver adds support for the Smart Battery System.
+         Depends on I2C (Device Drivers ---> I2C support)
+         A "Smart Battery" is quite old and quite rare compared
+         to today's ACPI "Control Method" battery.
+
 endif  # ACPI
 
 endmenu
index f0a68ec..bce7ca2 100644 (file)
@@ -58,3 +58,5 @@ obj-$(CONFIG_ACPI_IBM)                += ibm_acpi.o
 obj-$(CONFIG_ACPI_TOSHIBA)     += toshiba_acpi.o
 obj-y                          += scan.o motherboard.o
 obj-$(CONFIG_ACPI_HOTPLUG_MEMORY)      += acpi_memhotplug.o
+obj-y                          += cm_sbs.o
+obj-$(CONFIG_ACPI_SBS)         += i2c_ec.o sbs.o
index 36ca365..24ccf81 100644 (file)
@@ -50,6 +50,9 @@ ACPI_MODULE_NAME("acpi_ac")
 MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME);
 MODULE_LICENSE("GPL");
 
+extern struct proc_dir_entry *acpi_lock_ac_dir(void);
+extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
+
 static int acpi_ac_add(struct acpi_device *device);
 static int acpi_ac_remove(struct acpi_device *device, int type);
 static int acpi_ac_open_fs(struct inode *inode, struct file *file);
@@ -65,7 +68,7 @@ static struct acpi_driver acpi_ac_driver = {
 };
 
 struct acpi_ac {
-       acpi_handle handle;
+       struct acpi_device * device;
        unsigned long state;
 };
 
@@ -88,7 +91,7 @@ static int acpi_ac_get_state(struct acpi_ac *ac)
        if (!ac)
                return -EINVAL;
 
-       status = acpi_evaluate_integer(ac->handle, "_PSR", NULL, &ac->state);
+       status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, &ac->state);
        if (ACPI_FAILURE(status)) {
                ACPI_EXCEPTION((AE_INFO, status, "Error reading AC Adapter state"));
                ac->state = ACPI_AC_STATUS_UNKNOWN;
@@ -191,11 +194,11 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
        if (!ac)
                return;
 
-       if (acpi_bus_get_device(ac->handle, &device))
-               return;
-
+       device = ac->device;
        switch (event) {
        case ACPI_AC_NOTIFY_STATUS:
+       case ACPI_NOTIFY_BUS_CHECK:
+       case ACPI_NOTIFY_DEVICE_CHECK:
                acpi_ac_get_state(ac);
                acpi_bus_generate_event(device, event, (u32) ac->state);
                break;
@@ -223,7 +226,7 @@ static int acpi_ac_add(struct acpi_device *device)
                return -ENOMEM;
        memset(ac, 0, sizeof(struct acpi_ac));
 
-       ac->handle = device->handle;
+       ac->device = device;
        strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_AC_CLASS);
        acpi_driver_data(device) = ac;
@@ -236,8 +239,8 @@ static int acpi_ac_add(struct acpi_device *device)
        if (result)
                goto end;
 
-       status = acpi_install_notify_handler(ac->handle,
-                                            ACPI_DEVICE_NOTIFY, acpi_ac_notify,
+       status = acpi_install_notify_handler(device->handle,
+                                            ACPI_ALL_NOTIFY, acpi_ac_notify,
                                             ac);
        if (ACPI_FAILURE(status)) {
                result = -ENODEV;
@@ -268,8 +271,8 @@ static int acpi_ac_remove(struct acpi_device *device, int type)
 
        ac = (struct acpi_ac *)acpi_driver_data(device);
 
-       status = acpi_remove_notify_handler(ac->handle,
-                                           ACPI_DEVICE_NOTIFY, acpi_ac_notify);
+       status = acpi_remove_notify_handler(device->handle,
+                                           ACPI_ALL_NOTIFY, acpi_ac_notify);
 
        acpi_ac_remove_fs(device);
 
@@ -280,17 +283,16 @@ static int acpi_ac_remove(struct acpi_device *device, int type)
 
 static int __init acpi_ac_init(void)
 {
-       int result = 0;
+       int result;
 
 
-       acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir);
+       acpi_ac_dir = acpi_lock_ac_dir();
        if (!acpi_ac_dir)
                return -ENODEV;
-       acpi_ac_dir->owner = THIS_MODULE;
 
        result = acpi_bus_register_driver(&acpi_ac_driver);
        if (result < 0) {
-               remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
+               acpi_unlock_ac_dir(acpi_ac_dir);
                return -ENODEV;
        }
 
@@ -302,7 +304,7 @@ static void __exit acpi_ac_exit(void)
 
        acpi_bus_unregister_driver(&acpi_ac_driver);
 
-       remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
+       acpi_unlock_ac_dir(acpi_ac_dir);
 
        return;
 }
index cd57372..81e970a 100644 (file)
@@ -80,7 +80,7 @@ struct acpi_memory_info {
 };
 
 struct acpi_memory_device {
-       acpi_handle handle;
+       struct acpi_device * device;
        unsigned int state;     /* State of the memory device */
        struct list_head res_list;
 };
@@ -129,7 +129,7 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
        struct acpi_memory_info *info, *n;
 
 
-       status = acpi_walk_resources(mem_device->handle, METHOD_NAME__CRS,
+       status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS,
                                     acpi_memory_get_resource, mem_device);
        if (ACPI_FAILURE(status)) {
                list_for_each_entry_safe(info, n, &mem_device->res_list, list)
@@ -192,7 +192,7 @@ static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
 
 
        /* Get device present/absent information from the _STA */
-       if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->handle, "_STA",
+       if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle, "_STA",
                                               NULL, &current_status)))
                return -ENODEV;
        /*
@@ -222,7 +222,7 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
                return result;
        }
 
-       node = acpi_get_node(mem_device->handle);
+       node = acpi_get_node(mem_device->device->handle);
        /*
         * Tell the VM there is more memory here...
         * Note: Assume that this function returns zero on success
@@ -269,7 +269,7 @@ static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
        arg_list.pointer = &arg;
        arg.type = ACPI_TYPE_INTEGER;
        arg.integer.value = 1;
-       status = acpi_evaluate_object(mem_device->handle,
+       status = acpi_evaluate_object(mem_device->device->handle,
                                      "_EJ0", &arg_list, NULL);
        /* Return on _EJ0 failure */
        if (ACPI_FAILURE(status)) {
@@ -278,7 +278,7 @@ static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
        }
 
        /* Evalute _STA to check if the device is disabled */
-       status = acpi_evaluate_integer(mem_device->handle, "_STA",
+       status = acpi_evaluate_integer(mem_device->device->handle, "_STA",
                                       NULL, &current_status);
        if (ACPI_FAILURE(status))
                return -ENODEV;
@@ -398,7 +398,7 @@ static int acpi_memory_device_add(struct acpi_device *device)
        memset(mem_device, 0, sizeof(struct acpi_memory_device));
 
        INIT_LIST_HEAD(&mem_device->res_list);
-       mem_device->handle = device->handle;
+       mem_device->device = device;
        sprintf(acpi_device_name(device), "%s", ACPI_MEMORY_DEVICE_NAME);
        sprintf(acpi_device_class(device), "%s", ACPI_MEMORY_DEVICE_CLASS);
        acpi_driver_data(device) = mem_device;
@@ -466,7 +466,7 @@ static acpi_status is_memory_device(acpi_handle handle)
 
        info = buffer.pointer;
        if (!(info->valid & ACPI_VALID_HID)) {
-               acpi_os_free(buffer.pointer);
+               kfree(buffer.pointer);
                return AE_ERROR;
        }
 
@@ -475,7 +475,7 @@ static acpi_status is_memory_device(acpi_handle handle)
            (strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID)))
                status = AE_ERROR;
 
-       acpi_os_free(buffer.pointer);
+       kfree(buffer.pointer);
        return status;
 }
 
index 055cfd5..e9ee4c5 100644 (file)
@@ -2,7 +2,7 @@
  *  asus_acpi.c - Asus Laptop ACPI Extras
  *
  *
- *  Copyright (C) 2002, 2003, 2004 Julien Lerouge, Karol Kozimor
+ *  Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor
  *
  *  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
  *  Pontus Fuchs   - Helper functions, cleanup
  *  Johann Wiesner - Small compile fixes
  *  John Belmonte  - ACPI code for Toshiba laptop was a good starting point.
+ *  Ã‰ric Burghard  - LED display support for W1N
  *
- *  TODO:
- *  add Fn key status
- *  Add mode selection on module loading (parameter) -> still necessary?
- *  Complete display switching -- may require dirty hacks or calling _DOS?
  */
 
 #include <linux/kernel.h>
 #include <acpi/acpi_bus.h>
 #include <asm/uaccess.h>
 
-#define ASUS_ACPI_VERSION "0.29"
+#define ASUS_ACPI_VERSION "0.30"
 
 #define PROC_ASUS       "asus" //the directory
 #define PROC_MLED       "mled"
 #define PROC_WLED       "wled"
 #define PROC_TLED       "tled"
+#define PROC_BT         "bluetooth"
+#define PROC_LEDD       "ledd"
 #define PROC_INFO       "info"
 #define PROC_LCD        "lcd"
 #define PROC_BRN        "brn"
 /*
  * Flags for hotk status
  */
-#define MLED_ON     0x01       //is MLED ON ?
-#define WLED_ON     0x02
-#define TLED_ON     0x04
+#define MLED_ON     0x01       //mail LED
+#define WLED_ON     0x02       //wireless LED
+#define TLED_ON     0x04       //touchpad LED
+#define BT_ON       0x08       //internal Bluetooth
 
 MODULE_AUTHOR("Julien Lerouge, Karol Kozimor");
 MODULE_DESCRIPTION(ACPI_HOTK_NAME);
@@ -92,7 +92,10 @@ struct model_data {
        char *wled_status;      //node to handle wled reading_______A
        char *mt_tled;          //method to handle tled_____________R
        char *tled_status;      //node to handle tled reading_______A
-       char *mt_lcd_switch;    //method to turn LCD ON/OFF_________A
+       char *mt_ledd;          //method to handle LED display______R
+       char *mt_bt_switch;     //method to switch Bluetooth on/off_R
+       char *bt_status;        //no model currently supports this__?
+       char *mt_lcd_switch;    //method to turn LCD on/off_________A
        char *lcd_status;       //node to read LCD panel state______A
        char *brightness_up;    //method to set brightness up_______A
        char *brightness_down;  //guess what ?______________________A
@@ -111,27 +114,31 @@ struct asus_hotk {
        struct acpi_device *device;     //the device we are in
        acpi_handle handle;     //the handle of the hotk device
        char status;            //status of the hotk, for LEDs, ...
+       u32 ledd_status;        //status of the LED display
        struct model_data *methods;     //methods available on the laptop
        u8 brightness;          //brightness level
        enum {
                A1x = 0,        //A1340D, A1300F
                A2x,            //A2500H
+               A4G,            //A4700G
                D1x,            //D1
                L2D,            //L2000D
                L3C,            //L3800C
                L3D,            //L3400D
-               L3H,            //L3H, but also L2000E
+               L3H,            //L3H, L2000E, L5D
                L4R,            //L4500R
                L5x,            //L5800C 
                L8L,            //L8400L
                M1A,            //M1300A
                M2E,            //M2400E, L4400L
-               M6N,            //M6800N
-               M6R,            //M6700R
+               M6N,            //M6800N, W3400N
+               M6R,            //M6700R, A3000G
                P30,            //Samsung P30
                S1x,            //S1300A, but also L1400B and M2400A (L84F)
                S2x,            //S200 (J1 reported), Victor MP-XP7210
-               xxN,            //M2400N, M3700N, M5200N, S1300N, S5200N, W1OOON
+               W1N,            //W1000N
+               W5A,            //W5A
+               xxN,            //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N
                //(Centrino)
                END_MODEL
        } model;                //Models currently supported
@@ -149,17 +156,8 @@ struct asus_hotk {
 
 static struct model_data model_conf[END_MODEL] = {
        /*
-        * Those pathnames are relative to the HOTK / ATKD device :
-        *       - mt_mled
-        *       - mt_wled
-        *       - brightness_set
-        *       - brightness_get
-        *       - display_set
-        *       - display_get
-        *
         * TODO I have seen a SWBX and AIBX method on some models, like L1400B,
         * it seems to be a kind of switch, but what for ?
-        *
         */
 
        {
@@ -183,6 +181,16 @@ static struct model_data model_conf[END_MODEL] = {
         .display_set = "SDSP",
         .display_get = "\\INFB"},
 
+       {
+        .name = "A4G",
+        .mt_mled = "MLED",
+/* WLED present, but not controlled by ACPI */
+        .mt_lcd_switch = xxN_PREFIX "_Q10",
+        .brightness_set = "SPLV",
+        .brightness_get = "GPLV",
+        .display_set = "SDSP",
+        .display_get = "\\ADVG"},
+
        {
         .name = "D1x",
         .mt_mled = "MLED",
@@ -302,7 +310,8 @@ static struct model_data model_conf[END_MODEL] = {
         .brightness_set = "SPLV",
         .brightness_get = "GPLV",
         .display_set = "SDSP",
-        .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"},
+        .display_get = "\\SSTE"},
+
        {
         .name = "M6R",
         .mt_mled = "MLED",
@@ -312,7 +321,7 @@ static struct model_data model_conf[END_MODEL] = {
         .brightness_set = "SPLV",
         .brightness_get = "GPLV",
         .display_set = "SDSP",
-        .display_get = "\\SSTE"},
+        .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"},
 
        {
         .name = "P30",
@@ -344,6 +353,28 @@ static struct model_data model_conf[END_MODEL] = {
         .brightness_up = S2x_PREFIX "_Q0B",
         .brightness_down = S2x_PREFIX "_Q0A"},
 
+       {
+        .name = "W1N",
+        .mt_mled = "MLED",
+        .mt_wled = "WLED",
+        .mt_ledd = "SLCM",
+        .mt_lcd_switch = xxN_PREFIX "_Q10",
+        .lcd_status = "\\BKLT",
+        .brightness_set = "SPLV",
+        .brightness_get = "GPLV",
+        .display_set = "SDSP",
+        .display_get = "\\ADVG"},
+
+       {
+        .name = "W5A",
+        .mt_bt_switch = "BLED",
+        .mt_wled = "WLED",
+        .mt_lcd_switch = xxN_PREFIX "_Q10",
+        .brightness_set = "SPLV",
+        .brightness_get = "GPLV",
+        .display_set = "SDSP",
+        .display_get = "\\ADVG"},
+
        {
         .name = "xxN",
         .mt_mled = "MLED",
@@ -562,6 +593,36 @@ proc_write_mled(struct file *file, const char __user * buffer,
        return write_led(buffer, count, hotk->methods->mt_mled, MLED_ON, 1);
 }
 
+/*
+ * Proc handlers for LED display
+ */
+static int
+proc_read_ledd(char *page, char **start, off_t off, int count, int *eof,
+              void *data)
+{
+       return sprintf(page, "0x%08x\n", hotk->ledd_status);
+}
+
+static int
+proc_write_ledd(struct file *file, const char __user * buffer,
+               unsigned long count, void *data)
+{
+       int value;
+
+       count = parse_arg(buffer, count, &value);
+       if (count > 0) {
+               if (!write_acpi_int
+                   (hotk->handle, hotk->methods->mt_ledd, value, NULL))
+                       printk(KERN_WARNING
+                              "Asus ACPI: LED display write failed\n");
+               else
+                       hotk->ledd_status = (u32) value;
+       } else if (count < 0)
+               printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
+
+       return count;
+}
+
 /*
  * Proc handlers for WLED
  */
@@ -580,6 +641,25 @@ proc_write_wled(struct file *file, const char __user * buffer,
        return write_led(buffer, count, hotk->methods->mt_wled, WLED_ON, 0);
 }
 
+/*
+ * Proc handlers for Bluetooth
+ */
+static int
+proc_read_bluetooth(char *page, char **start, off_t off, int count, int *eof,
+                   void *data)
+{
+       return sprintf(page, "%d\n", read_led(hotk->methods->bt_status, BT_ON));
+}
+
+static int
+proc_write_bluetooth(struct file *file, const char __user * buffer,
+                    unsigned long count, void *data)
+{
+       /* Note: mt_bt_switch controls both internal Bluetooth adapter's 
+          presence and its LED */
+       return write_led(buffer, count, hotk->methods->mt_bt_switch, BT_ON, 0);
+}
+
 /*
  * Proc handlers for TLED
  */
@@ -876,6 +956,11 @@ static int asus_hotk_add_fs(struct acpi_device *device)
                              mode, device);
        }
 
+       if (hotk->methods->mt_ledd) {
+               asus_proc_add(PROC_LEDD, &proc_write_ledd, &proc_read_ledd,
+                             mode, device);
+       }
+
        if (hotk->methods->mt_mled) {
                asus_proc_add(PROC_MLED, &proc_write_mled, &proc_read_mled,
                              mode, device);
@@ -886,6 +971,11 @@ static int asus_hotk_add_fs(struct acpi_device *device)
                              mode, device);
        }
 
+       if (hotk->methods->mt_bt_switch) {
+               asus_proc_add(PROC_BT, &proc_write_bluetooth,
+                             &proc_read_bluetooth, mode, device);
+       }
+
        /* 
         * We need both read node and write method as LCD switch is also accessible
         * from keyboard 
@@ -919,6 +1009,10 @@ static int asus_hotk_remove_fs(struct acpi_device *device)
                        remove_proc_entry(PROC_MLED, acpi_device_dir(device));
                if (hotk->methods->mt_tled)
                        remove_proc_entry(PROC_TLED, acpi_device_dir(device));
+               if (hotk->methods->mt_ledd)
+                       remove_proc_entry(PROC_LEDD, acpi_device_dir(device));
+               if (hotk->methods->mt_bt_switch)
+                       remove_proc_entry(PROC_BT, acpi_device_dir(device));
                if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status)
                        remove_proc_entry(PROC_LCD, acpi_device_dir(device));
                if ((hotk->methods->brightness_up
@@ -950,6 +1044,65 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
        return;
 }
 
+/*
+ * Match the model string to the list of supported models. Return END_MODEL if
+ * no match or model is NULL.
+ */
+static int asus_model_match(char *model)
+{
+       if (model == NULL)
+               return END_MODEL;
+
+       if (strncmp(model, "L3D", 3) == 0)
+               return L3D;
+       else if (strncmp(model, "L2E", 3) == 0 ||
+                strncmp(model, "L3H", 3) == 0 || strncmp(model, "L5D", 3) == 0)
+               return L3H;
+       else if (strncmp(model, "L3", 2) == 0 || strncmp(model, "L2B", 3) == 0)
+               return L3C;
+       else if (strncmp(model, "L8L", 3) == 0)
+               return L8L;
+       else if (strncmp(model, "L4R", 3) == 0)
+               return L4R;
+       else if (strncmp(model, "M6N", 3) == 0 || strncmp(model, "W3N", 3) == 0)
+               return M6N;
+       else if (strncmp(model, "M6R", 3) == 0 || strncmp(model, "A3G", 3) == 0)
+               return M6R;
+       else if (strncmp(model, "M2N", 3) == 0 ||
+                strncmp(model, "M3N", 3) == 0 ||
+                strncmp(model, "M5N", 3) == 0 ||
+                strncmp(model, "M6N", 3) == 0 ||
+                strncmp(model, "S1N", 3) == 0 ||
+                strncmp(model, "S5N", 3) == 0 || strncmp(model, "W1N", 3) == 0)
+               return xxN;
+       else if (strncmp(model, "M1", 2) == 0)
+               return M1A;
+       else if (strncmp(model, "M2", 2) == 0 || strncmp(model, "L4E", 3) == 0)
+               return M2E;
+       else if (strncmp(model, "L2", 2) == 0)
+               return L2D;
+       else if (strncmp(model, "L8", 2) == 0)
+               return S1x;
+       else if (strncmp(model, "D1", 2) == 0)
+               return D1x;
+       else if (strncmp(model, "A1", 2) == 0)
+               return A1x;
+       else if (strncmp(model, "A2", 2) == 0)
+               return A2x;
+       else if (strncmp(model, "J1", 2) == 0)
+               return S2x;
+       else if (strncmp(model, "L5", 2) == 0)
+               return L5x;
+       else if (strncmp(model, "A4G", 3) == 0)
+               return A4G;
+       else if (strncmp(model, "W1N", 3) == 0)
+               return W1N;
+       else if (strncmp(model, "W5A", 3) == 0)
+               return W5A;
+       else
+               return END_MODEL;
+}
+
 /*
  * This function is used to initialize the hotk with right values. In this
  * method, we can make all the detection we want, and modify the hotk struct
@@ -960,6 +1113,7 @@ static int asus_hotk_get_info(void)
        struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL };
        union acpi_object *model = NULL;
        int bsts_result;
+       char *string = NULL;
        acpi_status status;
 
        /*
@@ -989,114 +1143,73 @@ static int asus_hotk_get_info(void)
                printk(KERN_NOTICE "  BSTS called, 0x%02x returned\n",
                       bsts_result);
 
-       /* This is unlikely with implicit return */
-       if (buffer.pointer == NULL)
-               return -EINVAL;
-
-       model = (union acpi_object *) buffer.pointer;
        /*
-        * Samsung P30 has a device with a valid _HID whose INIT does not 
-        * return anything. It used to be possible to catch this exception,
-        * but the implicit return code will now happily confuse the 
-        * driver. We assume that every ACPI_TYPE_STRING is a valid model
-        * identifier but it's still possible to get completely bogus data.
+        * Try to match the object returned by INIT to the specific model.
+        * Handle every possible object (or the lack of thereof) the DSDT 
+        * writers might throw at us. When in trouble, we pass NULL to 
+        * asus_model_match() and try something completely different.
         */
-       if (model->type == ACPI_TYPE_STRING) {
-               printk(KERN_NOTICE "  %s model detected, ", model->string.pointer);
-       } else {
-               if (asus_info &&        /* Samsung P30 */
+       if (buffer.pointer) {
+               model = (union acpi_object *)buffer.pointer;
+               switch (model->type) {
+               case ACPI_TYPE_STRING:
+                       string = model->string.pointer;
+                       break;
+               case ACPI_TYPE_BUFFER:
+                       string = model->buffer.pointer;
+                       break;
+               default:
+                       kfree(model);
+                       break;
+               }
+       }
+       hotk->model = asus_model_match(string);
+       if (hotk->model == END_MODEL) { /* match failed */
+               if (asus_info &&
                    strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) {
                        hotk->model = P30;
                        printk(KERN_NOTICE
                               "  Samsung P30 detected, supported\n");
                } else {
                        hotk->model = M2E;
-                       printk(KERN_WARNING "  no string returned by INIT\n");
-                       printk(KERN_WARNING "  trying default values, supply "
-                              "the developers with your DSDT\n");
+                       printk(KERN_NOTICE "  unsupported model %s, trying "
+                              "default values\n", string);
+                       printk(KERN_NOTICE
+                              "  send /proc/acpi/dsdt to the developers\n");
                }
                hotk->methods = &model_conf[hotk->model];
-               
-               acpi_os_free(model);
-
                return AE_OK;
        }
-
-       hotk->model = END_MODEL;
-       if (strncmp(model->string.pointer, "L3D", 3) == 0)
-               hotk->model = L3D;
-       else if (strncmp(model->string.pointer, "L3H", 3) == 0 ||
-                strncmp(model->string.pointer, "L2E", 3) == 0)
-               hotk->model = L3H;
-       else if (strncmp(model->string.pointer, "L3", 2) == 0 ||
-                strncmp(model->string.pointer, "L2B", 3) == 0)
-               hotk->model = L3C;
-       else if (strncmp(model->string.pointer, "L8L", 3) == 0)
-               hotk->model = L8L;
-       else if (strncmp(model->string.pointer, "L4R", 3) == 0)
-               hotk->model = L4R;
-       else if (strncmp(model->string.pointer, "M6N", 3) == 0)
-               hotk->model = M6N;
-       else if (strncmp(model->string.pointer, "M6R", 3) == 0)
-               hotk->model = M6R;
-       else if (strncmp(model->string.pointer, "M2N", 3) == 0 ||
-                strncmp(model->string.pointer, "M3N", 3) == 0 ||
-                strncmp(model->string.pointer, "M5N", 3) == 0 ||
-                strncmp(model->string.pointer, "M6N", 3) == 0 ||
-                strncmp(model->string.pointer, "S1N", 3) == 0 ||
-                strncmp(model->string.pointer, "S5N", 3) == 0 ||
-                strncmp(model->string.pointer, "W1N", 3) == 0)
-               hotk->model = xxN;
-       else if (strncmp(model->string.pointer, "M1", 2) == 0)
-               hotk->model = M1A;
-       else if (strncmp(model->string.pointer, "M2", 2) == 0 ||
-                strncmp(model->string.pointer, "L4E", 3) == 0)
-               hotk->model = M2E;
-       else if (strncmp(model->string.pointer, "L2", 2) == 0)
-               hotk->model = L2D;
-       else if (strncmp(model->string.pointer, "L8", 2) == 0)
-               hotk->model = S1x;
-       else if (strncmp(model->string.pointer, "D1", 2) == 0)
-               hotk->model = D1x;
-       else if (strncmp(model->string.pointer, "A1", 2) == 0)
-               hotk->model = A1x;
-       else if (strncmp(model->string.pointer, "A2", 2) == 0)
-               hotk->model = A2x;
-       else if (strncmp(model->string.pointer, "J1", 2) == 0)
-               hotk->model = S2x;
-       else if (strncmp(model->string.pointer, "L5", 2) == 0)
-               hotk->model = L5x;
-
-       if (hotk->model == END_MODEL) {
-               printk("unsupported, trying default values, supply the "
-                      "developers with your DSDT\n");
-               hotk->model = M2E;
-       } else {
-               printk("supported\n");
-       }
-
        hotk->methods = &model_conf[hotk->model];
+       printk(KERN_NOTICE "  %s model detected, supported\n", string);
 
        /* Sort of per-model blacklist */
-       if (strncmp(model->string.pointer, "L2B", 3) == 0)
+       if (strncmp(string, "L2B", 3) == 0)
                hotk->methods->lcd_status = NULL;
        /* L2B is similar enough to L3C to use its settings, with this only 
           exception */
-       else if (strncmp(model->string.pointer, "S5N", 3) == 0 ||
-                strncmp(model->string.pointer, "M5N", 3) == 0)
+       else if (strncmp(string, "A3G", 3) == 0)
+               hotk->methods->lcd_status = "\\BLFG";
+       /* A3G is like M6R */
+       else if (strncmp(string, "S5N", 3) == 0 ||
+                strncmp(string, "M5N", 3) == 0 ||
+                strncmp(string, "W3N", 3) == 0)
                hotk->methods->mt_mled = NULL;
-       /* S5N and M5N have no MLED */
-       else if (strncmp(model->string.pointer, "M2N", 3) == 0 ||
-                strncmp(model->string.pointer, "W1N", 3) == 0)
+       /* S5N, M5N and W3N have no MLED */
+       else if (strncmp(string, "L5D", 3) == 0)
+               hotk->methods->mt_wled = NULL;
+       /* L5D's WLED is not controlled by ACPI */
+       else if (strncmp(string, "M2N", 3) == 0 ||
+                strncmp(string, "S1N", 3) == 0)
                hotk->methods->mt_wled = "WLED";
-       /* M2N and W1N have a usable WLED */
+       /* M2N and S1N have a usable WLED */
        else if (asus_info) {
                if (strncmp(asus_info->oem_table_id, "L1", 2) == 0)
                        hotk->methods->mled_status = NULL;
                /* S1300A reports L84F, but L1400B too, account for that */
        }
 
-       acpi_os_free(model);
+       kfree(model);
 
        return AE_OK;
 }
@@ -1164,8 +1277,7 @@ static int asus_hotk_add(struct acpi_device *device)
        /* For laptops without GPLV: init the hotk->brightness value */
        if ((!hotk->methods->brightness_get)
            && (!hotk->methods->brightness_status)
-           && (hotk->methods->brightness_up
-               && hotk->methods->brightness_down)) {
+           && (hotk->methods->brightness_up && hotk->methods->brightness_down)) {
                status =
                    acpi_evaluate_object(NULL, hotk->methods->brightness_down,
                                         NULL, NULL);
@@ -1184,6 +1296,9 @@ static int asus_hotk_add(struct acpi_device *device)
 
        asus_hotk_found = 1;
 
+       /* LED display is off by default */
+       hotk->ledd_status = 0xFFF;
+
       end:
        if (result) {
                kfree(hotk);
@@ -1256,7 +1371,7 @@ static void __exit asus_acpi_exit(void)
        acpi_bus_unregister_driver(&asus_hotk_driver);
        remove_proc_entry(PROC_ASUS, acpi_root_dir);
 
-       acpi_os_free(asus_info);
+       kfree(asus_info);
 
        return;
 }
index 00b0728..24bf4dc 100644 (file)
@@ -59,6 +59,9 @@ ACPI_MODULE_NAME("acpi_battery")
 MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME);
 MODULE_LICENSE("GPL");
 
+extern struct proc_dir_entry *acpi_lock_battery_dir(void);
+extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
+
 static int acpi_battery_add(struct acpi_device *device);
 static int acpi_battery_remove(struct acpi_device *device, int type);
 
@@ -108,7 +111,7 @@ struct acpi_battery_trips {
 };
 
 struct acpi_battery {
-       acpi_handle handle;
+       struct acpi_device * device;
        struct acpi_battery_flags flags;
        struct acpi_battery_trips trips;
        unsigned long alarm;
@@ -138,7 +141,7 @@ acpi_battery_get_info(struct acpi_battery *battery,
 
        /* Evalute _BIF */
 
-       status = acpi_evaluate_object(battery->handle, "_BIF", NULL, &buffer);
+       status = acpi_evaluate_object(battery->device->handle, "_BIF", NULL, &buffer);
        if (ACPI_FAILURE(status)) {
                ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF"));
                return -ENODEV;
@@ -171,7 +174,7 @@ acpi_battery_get_info(struct acpi_battery *battery,
        }
 
       end:
-       acpi_os_free(buffer.pointer);
+       kfree(buffer.pointer);
 
        if (!result)
                (*bif) = (struct acpi_battery_info *)data.pointer;
@@ -198,7 +201,7 @@ acpi_battery_get_status(struct acpi_battery *battery,
 
        /* Evalute _BST */
 
-       status = acpi_evaluate_object(battery->handle, "_BST", NULL, &buffer);
+       status = acpi_evaluate_object(battery->device->handle, "_BST", NULL, &buffer);
        if (ACPI_FAILURE(status)) {
                ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
                return -ENODEV;
@@ -231,7 +234,7 @@ acpi_battery_get_status(struct acpi_battery *battery,
        }
 
       end:
-       acpi_os_free(buffer.pointer);
+       kfree(buffer.pointer);
 
        if (!result)
                (*bst) = (struct acpi_battery_status *)data.pointer;
@@ -255,7 +258,7 @@ acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm)
 
        arg0.integer.value = alarm;
 
-       status = acpi_evaluate_object(battery->handle, "_BTP", &arg_list, NULL);
+       status = acpi_evaluate_object(battery->device->handle, "_BTP", &arg_list, NULL);
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
@@ -278,9 +281,7 @@ static int acpi_battery_check(struct acpi_battery *battery)
        if (!battery)
                return -EINVAL;
 
-       result = acpi_bus_get_device(battery->handle, &device);
-       if (result)
-               return result;
+       device = battery->device;
 
        result = acpi_bus_get_status(device);
        if (result)
@@ -305,7 +306,7 @@ static int acpi_battery_check(struct acpi_battery *battery)
 
                /* See if alarms are supported, and if so, set default */
 
-               status = acpi_get_handle(battery->handle, "_BTP", &handle);
+               status = acpi_get_handle(battery->device->handle, "_BTP", &handle);
                if (ACPI_SUCCESS(status)) {
                        battery->flags.alarm = 1;
                        acpi_battery_set_alarm(battery, battery->trips.warning);
@@ -662,12 +663,13 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
        if (!battery)
                return;
 
-       if (acpi_bus_get_device(handle, &device))
-               return;
+       device = battery->device;
 
        switch (event) {
        case ACPI_BATTERY_NOTIFY_STATUS:
        case ACPI_BATTERY_NOTIFY_INFO:
+       case ACPI_NOTIFY_BUS_CHECK:
+       case ACPI_NOTIFY_DEVICE_CHECK:
                acpi_battery_check(battery);
                acpi_bus_generate_event(device, event, battery->flags.present);
                break;
@@ -695,7 +697,7 @@ static int acpi_battery_add(struct acpi_device *device)
                return -ENOMEM;
        memset(battery, 0, sizeof(struct acpi_battery));
 
-       battery->handle = device->handle;
+       battery->device = device;
        strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
        acpi_driver_data(device) = battery;
@@ -708,8 +710,8 @@ static int acpi_battery_add(struct acpi_device *device)
        if (result)
                goto end;
 
-       status = acpi_install_notify_handler(battery->handle,
-                                            ACPI_DEVICE_NOTIFY,
+       status = acpi_install_notify_handler(device->handle,
+                                            ACPI_ALL_NOTIFY,
                                             acpi_battery_notify, battery);
        if (ACPI_FAILURE(status)) {
                result = -ENODEV;
@@ -740,8 +742,8 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
 
        battery = (struct acpi_battery *)acpi_driver_data(device);
 
-       status = acpi_remove_notify_handler(battery->handle,
-                                           ACPI_DEVICE_NOTIFY,
+       status = acpi_remove_notify_handler(device->handle,
+                                           ACPI_ALL_NOTIFY,
                                            acpi_battery_notify);
 
        acpi_battery_remove_fs(device);
@@ -753,17 +755,15 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
 
 static int __init acpi_battery_init(void)
 {
-       int result = 0;
-
+       int result;
 
-       acpi_battery_dir = proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir);
+       acpi_battery_dir = acpi_lock_battery_dir();
        if (!acpi_battery_dir)
                return -ENODEV;
-       acpi_battery_dir->owner = THIS_MODULE;
 
        result = acpi_bus_register_driver(&acpi_battery_driver);
        if (result < 0) {
-               remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
+               acpi_unlock_battery_dir(acpi_battery_dir);
                return -ENODEV;
        }
 
@@ -775,7 +775,7 @@ static void __exit acpi_battery_exit(void)
 
        acpi_bus_unregister_driver(&acpi_battery_driver);
 
-       remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
+       acpi_unlock_battery_dir(acpi_battery_dir);
 
        return;
 }
index 0259463..fd1ba05 100644 (file)
@@ -82,7 +82,6 @@ static struct acpi_driver acpi_button_driver = {
 };
 
 struct acpi_button {
-       acpi_handle handle;
        struct acpi_device *device;     /* Fixed button kludge */
        u8 type;
        unsigned long pushed;
@@ -137,7 +136,7 @@ static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
        if (!button || !button->device)
                return 0;
 
-       status = acpi_evaluate_integer(button->handle, "_LID", NULL, &state);
+       status = acpi_evaluate_integer(button->device->handle, "_LID", NULL, &state);
        if (ACPI_FAILURE(status)) {
                seq_printf(seq, "state:      unsupported\n");
        } else {
@@ -282,7 +281,7 @@ static acpi_status acpi_button_notify_fixed(void *data)
        if (!button)
                return AE_BAD_PARAMETER;
 
-       acpi_button_notify(button->handle, ACPI_BUTTON_NOTIFY_STATUS, button);
+       acpi_button_notify(button->device->handle, ACPI_BUTTON_NOTIFY_STATUS, button);
 
        return AE_OK;
 }
@@ -303,7 +302,6 @@ static int acpi_button_add(struct acpi_device *device)
        memset(button, 0, sizeof(struct acpi_button));
 
        button->device = device;
-       button->handle = device->handle;
        acpi_driver_data(device) = button;
 
        /*
@@ -362,7 +360,7 @@ static int acpi_button_add(struct acpi_device *device)
                                                     button);
                break;
        default:
-               status = acpi_install_notify_handler(button->handle,
+               status = acpi_install_notify_handler(device->handle,
                                                     ACPI_DEVICE_NOTIFY,
                                                     acpi_button_notify,
                                                     button);
@@ -420,7 +418,7 @@ static int acpi_button_remove(struct acpi_device *device, int type)
                                                    acpi_button_notify_fixed);
                break;
        default:
-               status = acpi_remove_notify_handler(button->handle,
+               status = acpi_remove_notify_handler(device->handle,
                                                    ACPI_DEVICE_NOTIFY,
                                                    acpi_button_notify);
                break;
diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c
new file mode 100644 (file)
index 0000000..574a75a
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  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
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+#include <acpi/acmacros.h>
+#include <acpi/actypes.h>
+#include <acpi/acutils.h>
+
+ACPI_MODULE_NAME("cm_sbs")
+#define ACPI_AC_CLASS          "ac_adapter"
+#define ACPI_BATTERY_CLASS     "battery"
+#define ACPI_SBS_COMPONENT     0x00080000
+#define _COMPONENT             ACPI_SBS_COMPONENT
+static struct proc_dir_entry *acpi_ac_dir;
+static struct proc_dir_entry *acpi_battery_dir;
+
+static struct semaphore cm_sbs_sem;
+
+static int lock_ac_dir_cnt = 0;
+static int lock_battery_dir_cnt = 0;
+
+struct proc_dir_entry *acpi_lock_ac_dir(void)
+{
+
+       down(&cm_sbs_sem);
+       if (!acpi_ac_dir) {
+               acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir);
+       }
+       if (acpi_ac_dir) {
+               lock_ac_dir_cnt++;
+       } else {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "Cannot create %s\n", ACPI_AC_CLASS));
+       }
+       up(&cm_sbs_sem);
+       return acpi_ac_dir;
+}
+
+EXPORT_SYMBOL(acpi_lock_ac_dir);
+
+void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir_param)
+{
+
+       down(&cm_sbs_sem);
+       if (acpi_ac_dir_param) {
+               lock_ac_dir_cnt--;
+       }
+       if (lock_ac_dir_cnt == 0 && acpi_ac_dir_param && acpi_ac_dir) {
+               remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
+               acpi_ac_dir = 0;
+       }
+       up(&cm_sbs_sem);
+}
+
+EXPORT_SYMBOL(acpi_unlock_ac_dir);
+
+struct proc_dir_entry *acpi_lock_battery_dir(void)
+{
+
+       down(&cm_sbs_sem);
+       if (!acpi_battery_dir) {
+               acpi_battery_dir =
+                   proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir);
+       }
+       if (acpi_battery_dir) {
+               lock_battery_dir_cnt++;
+       } else {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "Cannot create %s\n", ACPI_BATTERY_CLASS));
+       }
+       up(&cm_sbs_sem);
+       return acpi_battery_dir;
+}
+
+EXPORT_SYMBOL(acpi_lock_battery_dir);
+
+void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir_param)
+{
+
+       down(&cm_sbs_sem);
+       if (acpi_battery_dir_param) {
+               lock_battery_dir_cnt--;
+       }
+       if (lock_battery_dir_cnt == 0 && acpi_battery_dir_param
+           && acpi_battery_dir) {
+               remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
+               acpi_battery_dir = 0;
+       }
+       up(&cm_sbs_sem);
+       return;
+}
+
+EXPORT_SYMBOL(acpi_unlock_battery_dir);
+
+static int __init acpi_cm_sbs_init(void)
+{
+
+       if (acpi_disabled)
+               return 0;
+
+       init_MUTEX(&cm_sbs_sem);
+
+       return 0;
+}
+
+subsys_initcall(acpi_cm_sbs_init);
index 7f7e41d..871aa52 100644 (file)
@@ -236,7 +236,7 @@ container_walk_namespace_cb(acpi_handle handle,
        }
 
       end:
-       acpi_os_free(buffer.pointer);
+       kfree(buffer.pointer);
 
        return AE_OK;
 }
index 38acc69..daed246 100644 (file)
@@ -64,7 +64,7 @@ static struct acpi_driver acpi_fan_driver = {
 };
 
 struct acpi_fan {
-       acpi_handle handle;
+       struct acpi_device * device;
 };
 
 /* --------------------------------------------------------------------------
@@ -80,7 +80,7 @@ static int acpi_fan_read_state(struct seq_file *seq, void *offset)
 
 
        if (fan) {
-               if (acpi_bus_get_power(fan->handle, &state))
+               if (acpi_bus_get_power(fan->device->handle, &state))
                        seq_printf(seq, "status:                  ERROR\n");
                else
                        seq_printf(seq, "status:                  %s\n",
@@ -112,7 +112,7 @@ acpi_fan_write_state(struct file *file, const char __user * buffer,
 
        state_string[count] = '\0';
 
-       result = acpi_bus_set_power(fan->handle,
+       result = acpi_bus_set_power(fan->device->handle,
                                    simple_strtoul(state_string, NULL, 0));
        if (result)
                return result;
@@ -191,12 +191,12 @@ static int acpi_fan_add(struct acpi_device *device)
                return -ENOMEM;
        memset(fan, 0, sizeof(struct acpi_fan));
 
-       fan->handle = device->handle;
+       fan->device = device;
        strcpy(acpi_device_name(device), "Fan");
        strcpy(acpi_device_class(device), ACPI_FAN_CLASS);
        acpi_driver_data(device) = fan;
 
-       result = acpi_bus_get_power(fan->handle, &state);
+       result = acpi_bus_get_power(device->handle, &state);
        if (result) {
                printk(KERN_ERR PREFIX "Reading power state\n");
                goto end;
index 8daef57..10f160d 100644 (file)
@@ -152,7 +152,7 @@ static int get_root_bridge_busnr(acpi_handle handle)
                bbn = bus;
        }
       exit:
-       acpi_os_free(buffer.pointer);
+       kfree(buffer.pointer);
        return (int)bbn;
 }
 
@@ -192,7 +192,7 @@ find_pci_rootbridge(acpi_handle handle, u32 lvl, void *context, void **rv)
                find->handle = handle;
        status = AE_OK;
       exit:
-       acpi_os_free(buffer.pointer);
+       kfree(buffer.pointer);
        return status;
 }
 
@@ -224,7 +224,7 @@ do_acpi_find_child(acpi_handle handle, u32 lvl, void *context, void **rv)
                info = buffer.pointer;
                if (info->address == find->address)
                        find->handle = handle;
-               acpi_os_free(buffer.pointer);
+               kfree(buffer.pointer);
        }
        return AE_OK;
 }
@@ -330,7 +330,7 @@ static int acpi_platform_notify(struct device *dev)
 
                acpi_get_name(dev->firmware_data, ACPI_FULL_PATHNAME, &buffer);
                DBG("Device %s -> %s\n", dev->bus_id, (char *)buffer.pointer);
-               acpi_os_free(buffer.pointer);
+               kfree(buffer.pointer);
        } else
                DBG("Device %s -> No ACPI support\n", dev->bus_id);
 #endif
diff --git a/drivers/acpi/i2c_ec.c b/drivers/acpi/i2c_ec.c
new file mode 100644 (file)
index 0000000..84239d5
--- /dev/null
@@ -0,0 +1,406 @@
+/*
+ * SMBus driver for ACPI Embedded Controller ($Revision: 1.3 $)
+ *
+ * Copyright (c) 2002, 2005 Ducrot Bruno
+ * Copyright (c) 2005 Rich Townsend (tiny hacks & tweaks)
+ *
+ * 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
+ * the Free Software Foundation version 2.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+
+#include "i2c_ec.h"
+
+#define        xudelay(t)      udelay(t)
+#define        xmsleep(t)      msleep(t)
+
+#define ACPI_EC_HC_COMPONENT   0x00080000
+#define ACPI_EC_HC_CLASS       "ec_hc_smbus"
+#define ACPI_EC_HC_HID         "ACPI0001"
+#define ACPI_EC_HC_DRIVER_NAME "ACPI EC HC smbus driver"
+#define ACPI_EC_HC_DEVICE_NAME "EC HC smbus"
+
+#define _COMPONENT             ACPI_EC_HC_COMPONENT
+
+ACPI_MODULE_NAME("acpi_smbus")
+
+static int acpi_ec_hc_add(struct acpi_device *device);
+static int acpi_ec_hc_remove(struct acpi_device *device, int type);
+
+static struct acpi_driver acpi_ec_hc_driver = {
+       .name = ACPI_EC_HC_DRIVER_NAME,
+       .class = ACPI_EC_HC_CLASS,
+       .ids = ACPI_EC_HC_HID,
+       .ops = {
+               .add = acpi_ec_hc_add,
+               .remove = acpi_ec_hc_remove,
+               },
+};
+
+/* Various bit mask for EC_SC (R) */
+#define OBF            0x01
+#define IBF            0x02
+#define CMD            0x08
+#define BURST          0x10
+#define SCI_EVT                0x20
+#define SMI_EVT                0x40
+
+/* Commands for EC_SC (W) */
+#define RD_EC          0x80
+#define WR_EC          0x81
+#define BE_EC          0x82
+#define BD_EC          0x83
+#define QR_EC          0x84
+
+/*
+ * ACPI 2.0 chapter 13 SMBus 2.0 EC register model
+ */
+
+#define ACPI_EC_SMB_PRTCL      0x00    /* protocol, PEC */
+#define ACPI_EC_SMB_STS                0x01    /* status */
+#define ACPI_EC_SMB_ADDR       0x02    /* address */
+#define ACPI_EC_SMB_CMD                0x03    /* command */
+#define ACPI_EC_SMB_DATA       0x04    /* 32 data registers */
+#define ACPI_EC_SMB_BCNT       0x24    /* number of data bytes */
+#define ACPI_EC_SMB_ALRM_A     0x25    /* alarm address */
+#define ACPI_EC_SMB_ALRM_D     0x26    /* 2 bytes alarm data */
+
+#define ACPI_EC_SMB_STS_DONE   0x80
+#define ACPI_EC_SMB_STS_ALRM   0x40
+#define ACPI_EC_SMB_STS_RES    0x20
+#define ACPI_EC_SMB_STS_STATUS 0x1f
+
+#define ACPI_EC_SMB_STATUS_OK          0x00
+#define ACPI_EC_SMB_STATUS_FAIL                0x07
+#define ACPI_EC_SMB_STATUS_DNAK                0x10
+#define ACPI_EC_SMB_STATUS_DERR                0x11
+#define ACPI_EC_SMB_STATUS_CMD_DENY    0x12
+#define ACPI_EC_SMB_STATUS_UNKNOWN     0x13
+#define ACPI_EC_SMB_STATUS_ACC_DENY    0x17
+#define ACPI_EC_SMB_STATUS_TIMEOUT     0x18
+#define ACPI_EC_SMB_STATUS_NOTSUP      0x19
+#define ACPI_EC_SMB_STATUS_BUSY                0x1A
+#define ACPI_EC_SMB_STATUS_PEC         0x1F
+
+#define ACPI_EC_SMB_PRTCL_WRITE                        0x00
+#define ACPI_EC_SMB_PRTCL_READ                 0x01
+#define ACPI_EC_SMB_PRTCL_QUICK                        0x02
+#define ACPI_EC_SMB_PRTCL_BYTE                 0x04
+#define ACPI_EC_SMB_PRTCL_BYTE_DATA            0x06
+#define ACPI_EC_SMB_PRTCL_WORD_DATA            0x08
+#define ACPI_EC_SMB_PRTCL_BLOCK_DATA           0x0a
+#define ACPI_EC_SMB_PRTCL_PROC_CALL            0x0c
+#define ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL      0x0d
+#define ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA       0x4a
+#define ACPI_EC_SMB_PRTCL_PEC                  0x80
+
+/* Length of pre/post transaction sleep (msec) */
+#define ACPI_EC_SMB_TRANSACTION_SLEEP          1
+#define ACPI_EC_SMB_ACCESS_SLEEP1              1
+#define ACPI_EC_SMB_ACCESS_SLEEP2              10
+
+static int acpi_ec_smb_read(struct acpi_ec_smbus *smbus, u8 address, u8 * data)
+{
+       u8 val;
+       int err;
+
+       err = ec_read(smbus->base + address, &val);
+       if (!err) {
+               *data = val;
+       }
+       xmsleep(ACPI_EC_SMB_TRANSACTION_SLEEP);
+       return (err);
+}
+
+static int acpi_ec_smb_write(struct acpi_ec_smbus *smbus, u8 address, u8 data)
+{
+       int err;
+
+       err = ec_write(smbus->base + address, data);
+       return (err);
+}
+
+static int
+acpi_ec_smb_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
+                  char read_write, u8 command, int size,
+                  union i2c_smbus_data *data)
+{
+       struct acpi_ec_smbus *smbus = adap->algo_data;
+       unsigned char protocol, len = 0, pec, temp[2] = { 0, 0 };
+       int i;
+
+       if (read_write == I2C_SMBUS_READ) {
+               protocol = ACPI_EC_SMB_PRTCL_READ;
+       } else {
+               protocol = ACPI_EC_SMB_PRTCL_WRITE;
+       }
+       pec = (flags & I2C_CLIENT_PEC) ? ACPI_EC_SMB_PRTCL_PEC : 0;
+
+       switch (size) {
+
+       case I2C_SMBUS_QUICK:
+               protocol |= ACPI_EC_SMB_PRTCL_QUICK;
+               read_write = I2C_SMBUS_WRITE;
+               break;
+
+       case I2C_SMBUS_BYTE:
+               if (read_write == I2C_SMBUS_WRITE) {
+                       acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->byte);
+               }
+               protocol |= ACPI_EC_SMB_PRTCL_BYTE;
+               break;
+
+       case I2C_SMBUS_BYTE_DATA:
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
+               if (read_write == I2C_SMBUS_WRITE) {
+                       acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->byte);
+               }
+               protocol |= ACPI_EC_SMB_PRTCL_BYTE_DATA;
+               break;
+
+       case I2C_SMBUS_WORD_DATA:
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
+               if (read_write == I2C_SMBUS_WRITE) {
+                       acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->word);
+                       acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + 1,
+                                         data->word >> 8);
+               }
+               protocol |= ACPI_EC_SMB_PRTCL_WORD_DATA | pec;
+               break;
+
+       case I2C_SMBUS_BLOCK_DATA:
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
+               if (read_write == I2C_SMBUS_WRITE) {
+                       len = min_t(u8, data->block[0], 32);
+                       acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len);
+                       for (i = 0; i < len; i++)
+                               acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i,
+                                                 data->block[i + 1]);
+               }
+               protocol |= ACPI_EC_SMB_PRTCL_BLOCK_DATA | pec;
+               break;
+
+       case I2C_SMBUS_I2C_BLOCK_DATA:
+               len = min_t(u8, data->block[0], 32);
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len);
+               if (read_write == I2C_SMBUS_WRITE) {
+                       for (i = 0; i < len; i++) {
+                               acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i,
+                                                 data->block[i + 1]);
+                       }
+               }
+               protocol |= ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA;
+               break;
+
+       case I2C_SMBUS_PROC_CALL:
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->word);
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + 1, data->word >> 8);
+               protocol = ACPI_EC_SMB_PRTCL_PROC_CALL | pec;
+               read_write = I2C_SMBUS_READ;
+               break;
+
+       case I2C_SMBUS_BLOCK_PROC_CALL:
+               protocol |= pec;
+               len = min_t(u8, data->block[0], 31);
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len);
+               for (i = 0; i < len; i++)
+                       acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i,
+                                         data->block[i + 1]);
+               protocol = ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL | pec;
+               read_write = I2C_SMBUS_READ;
+               break;
+
+       default:
+               ACPI_DEBUG_PRINT((ACPI_DB_WARN, "EC SMBus adapter: "
+                                 "Unsupported transaction %d\n", size));
+               return (-1);
+       }
+
+       acpi_ec_smb_write(smbus, ACPI_EC_SMB_ADDR, addr << 1);
+       acpi_ec_smb_write(smbus, ACPI_EC_SMB_PRTCL, protocol);
+
+       acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0);
+
+       if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
+               xudelay(500);
+               acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0);
+       }
+       if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
+               xmsleep(ACPI_EC_SMB_ACCESS_SLEEP2);
+               acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0);
+       }
+       if ((~temp[0] & ACPI_EC_SMB_STS_DONE)
+           || (temp[0] & ACPI_EC_SMB_STS_STATUS)) {
+               return (-1);
+       }
+
+       if (read_write == I2C_SMBUS_WRITE) {
+               return (0);
+       }
+
+       switch (size) {
+
+       case I2C_SMBUS_BYTE:
+       case I2C_SMBUS_BYTE_DATA:
+               acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA, &data->byte);
+               break;
+
+       case I2C_SMBUS_WORD_DATA:
+       case I2C_SMBUS_PROC_CALL:
+               acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA, temp + 0);
+               acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA + 1, temp + 1);
+               data->word = (temp[1] << 8) | temp[0];
+               break;
+
+       case I2C_SMBUS_BLOCK_DATA:
+       case I2C_SMBUS_BLOCK_PROC_CALL:
+               len = 0;
+               acpi_ec_smb_read(smbus, ACPI_EC_SMB_BCNT, &len);
+               len = min_t(u8, len, 32);
+       case I2C_SMBUS_I2C_BLOCK_DATA:
+               for (i = 0; i < len; i++)
+                       acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA + i,
+                                        data->block + i + 1);
+               data->block[0] = len;
+               break;
+       }
+
+       return (0);
+}
+
+static u32 acpi_ec_smb_func(struct i2c_adapter *adapter)
+{
+
+       return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+               I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+               I2C_FUNC_SMBUS_BLOCK_DATA |
+               I2C_FUNC_SMBUS_PROC_CALL |
+               I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
+               I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC);
+}
+
+static struct i2c_algorithm acpi_ec_smbus_algorithm = {
+       .smbus_xfer = acpi_ec_smb_access,
+       .functionality = acpi_ec_smb_func,
+};
+
+static int acpi_ec_hc_add(struct acpi_device *device)
+{
+       int status;
+       unsigned long val;
+       struct acpi_ec_hc *ec_hc;
+       struct acpi_ec_smbus *smbus;
+
+       if (!device) {
+               return -EINVAL;
+       }
+
+       ec_hc = kmalloc(sizeof(struct acpi_ec_hc), GFP_KERNEL);
+       if (!ec_hc) {
+               return -ENOMEM;
+       }
+       memset(ec_hc, 0, sizeof(struct acpi_ec_hc));
+
+       smbus = kmalloc(sizeof(struct acpi_ec_smbus), GFP_KERNEL);
+       if (!smbus) {
+               kfree(ec_hc);
+               return -ENOMEM;
+       }
+       memset(smbus, 0, sizeof(struct acpi_ec_smbus));
+
+       ec_hc->handle = device->handle;
+       strcpy(acpi_device_name(device), ACPI_EC_HC_DEVICE_NAME);
+       strcpy(acpi_device_class(device), ACPI_EC_HC_CLASS);
+       acpi_driver_data(device) = ec_hc;
+
+       status = acpi_evaluate_integer(ec_hc->handle, "_EC", NULL, &val);
+       if (ACPI_FAILURE(status)) {
+               ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error obtaining _EC\n"));
+               kfree(ec_hc->smbus);
+               kfree(smbus);
+               return -EIO;
+       }
+
+       smbus->ec = acpi_driver_data(device->parent);
+       smbus->base = (val & 0xff00ull) >> 8;
+       smbus->alert = val & 0xffull;
+
+       smbus->adapter.owner = THIS_MODULE;
+       smbus->adapter.algo = &acpi_ec_smbus_algorithm;
+       smbus->adapter.algo_data = smbus;
+
+       if (i2c_add_adapter(&smbus->adapter)) {
+               ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+                                 "EC SMBus adapter: Failed to register adapter\n"));
+               kfree(smbus);
+               kfree(ec_hc);
+               return -EIO;
+       }
+
+       ec_hc->smbus = smbus;
+
+       printk(KERN_INFO PREFIX "%s [%s]\n",
+              acpi_device_name(device), acpi_device_bid(device));
+
+       return AE_OK;
+}
+
+static int acpi_ec_hc_remove(struct acpi_device *device, int type)
+{
+       struct acpi_ec_hc *ec_hc;
+
+       if (!device) {
+               return -EINVAL;
+       }
+       ec_hc = acpi_driver_data(device);
+
+       i2c_del_adapter(&ec_hc->smbus->adapter);
+       kfree(ec_hc->smbus);
+       kfree(ec_hc);
+
+       return AE_OK;
+}
+
+static int __init acpi_ec_hc_init(void)
+{
+       int result;
+
+       result = acpi_bus_register_driver(&acpi_ec_hc_driver);
+       if (result < 0) {
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static void __exit acpi_ec_hc_exit(void)
+{
+       acpi_bus_unregister_driver(&acpi_ec_hc_driver);
+}
+
+struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device)
+{
+       return ((struct acpi_ec_hc *)acpi_driver_data(device->parent));
+}
+
+EXPORT_SYMBOL(acpi_get_ec_hc);
+
+module_init(acpi_ec_hc_init);
+module_exit(acpi_ec_hc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ducrot Bruno");
+MODULE_DESCRIPTION("ACPI EC SMBus driver");
diff --git a/drivers/acpi/i2c_ec.h b/drivers/acpi/i2c_ec.h
new file mode 100644 (file)
index 0000000..7c53fb7
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * SMBus driver for ACPI Embedded Controller ($Revision: 1.2 $)
+ *
+ * Copyright (c) 2002, 2005 Ducrot Bruno
+ *
+ * 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
+ * the Free Software Foundation version 2.
+ */
+
+struct acpi_ec_smbus {
+       struct i2c_adapter adapter;
+       union acpi_ec *ec;
+       int base;
+       int alert;
+};
+
+struct acpi_ec_hc {
+       acpi_handle handle;
+       struct acpi_ec_smbus *smbus;
+};
+
+struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device);
index 6d9bd45..dca6799 100644 (file)
@@ -133,7 +133,7 @@ acpi_evaluate_object_typed(acpi_handle handle,
 
                /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
 
-               acpi_os_free(return_buffer->pointer);
+               ACPI_FREE(return_buffer->pointer);
                return_buffer->pointer = NULL;
        }
 
index 4d62298..e5e448e 100644 (file)
@@ -259,12 +259,10 @@ int acpi_get_node(acpi_handle *handle)
 {
        int pxm, node = -1;
 
-       ACPI_FUNCTION_TRACE("acpi_get_node");
-
        pxm = acpi_get_pxm(handle);
        if (pxm >= 0)
                node = acpi_map_pxm_to_node(pxm);
 
-       return_VALUE(node);
+       return node;
 }
 EXPORT_SYMBOL(acpi_get_node);
index 5a468e2..eedb05c 100644 (file)
@@ -146,13 +146,6 @@ void *acpi_os_allocate(acpi_size size)
                return kmalloc(size, GFP_KERNEL);
 }
 
-void acpi_os_free(void *ptr)
-{
-       kfree(ptr);
-}
-
-EXPORT_SYMBOL(acpi_os_free);
-
 acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr)
 {
        if (efi_enabled) {
@@ -742,7 +735,7 @@ acpi_status acpi_os_delete_semaphore(acpi_handle handle)
 
        ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle));
 
-       acpi_os_free(sem);
+       kfree(sem);
        sem = NULL;
 
        return AE_OK;
index 1badce2..8197c0e 100644 (file)
@@ -83,7 +83,6 @@ struct acpi_pci_link_irq {
 struct acpi_pci_link {
        struct list_head node;
        struct acpi_device *device;
-       acpi_handle handle;
        struct acpi_pci_link_irq irq;
        int refcnt;
 };
@@ -175,7 +174,7 @@ static int acpi_pci_link_get_possible(struct acpi_pci_link *link)
        if (!link)
                return -EINVAL;
 
-       status = acpi_walk_resources(link->handle, METHOD_NAME__PRS,
+       status = acpi_walk_resources(link->device->handle, METHOD_NAME__PRS,
                                     acpi_pci_link_check_possible, link);
        if (ACPI_FAILURE(status)) {
                ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRS"));
@@ -249,8 +248,7 @@ static int acpi_pci_link_get_current(struct acpi_pci_link *link)
        acpi_status status = AE_OK;
        int irq = 0;
 
-
-       if (!link || !link->handle)
+       if (!link)
                return -EINVAL;
 
        link->irq.active = 0;
@@ -274,7 +272,7 @@ static int acpi_pci_link_get_current(struct acpi_pci_link *link)
         * Query and parse _CRS to get the current IRQ assignment. 
         */
 
-       status = acpi_walk_resources(link->handle, METHOD_NAME__CRS,
+       status = acpi_walk_resources(link->device->handle, METHOD_NAME__CRS,
                                     acpi_pci_link_check_current, &irq);
        if (ACPI_FAILURE(status)) {
                ACPI_EXCEPTION((AE_INFO, status, "Evaluating _CRS"));
@@ -360,7 +358,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
        resource->end.type = ACPI_RESOURCE_TYPE_END_TAG;
 
        /* Attempt to set the resource */
-       status = acpi_set_current_resources(link->handle, &buffer);
+       status = acpi_set_current_resources(link->device->handle, &buffer);
 
        /* check for total failure */
        if (ACPI_FAILURE(status)) {
@@ -699,7 +697,7 @@ int acpi_pci_link_free_irq(acpi_handle handle)
                          acpi_device_bid(link->device)));
 
        if (link->refcnt == 0) {
-               acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL);
+               acpi_ut_evaluate_object(link->device->handle, "_DIS", 0, NULL);
        }
        mutex_unlock(&acpi_link_lock);
        return (link->irq.active);
@@ -726,7 +724,6 @@ static int acpi_pci_link_add(struct acpi_device *device)
        memset(link, 0, sizeof(struct acpi_pci_link));
 
        link->device = device;
-       link->handle = device->handle;
        strcpy(acpi_device_name(device), ACPI_PCI_LINK_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS);
        acpi_driver_data(device) = link;
@@ -765,7 +762,7 @@ static int acpi_pci_link_add(struct acpi_device *device)
 
       end:
        /* disable all links -- to be activated on use */
-       acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL);
+       acpi_ut_evaluate_object(device->handle, "_DIS", 0, NULL);
        mutex_unlock(&acpi_link_lock);
 
        if (result)
index 8f10442..0984a1e 100644 (file)
@@ -58,7 +58,7 @@ static struct acpi_driver acpi_pci_root_driver = {
 
 struct acpi_pci_root {
        struct list_head node;
-       acpi_handle handle;
+       struct acpi_device * device;
        struct acpi_pci_id id;
        struct pci_bus *bus;
 };
@@ -83,7 +83,7 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver)
        list_for_each(entry, &acpi_pci_roots) {
                struct acpi_pci_root *root;
                root = list_entry(entry, struct acpi_pci_root, node);
-               driver->add(root->handle);
+               driver->add(root->device->handle);
                n++;
        }
 
@@ -110,7 +110,7 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
        list_for_each(entry, &acpi_pci_roots) {
                struct acpi_pci_root *root;
                root = list_entry(entry, struct acpi_pci_root, node);
-               driver->remove(root->handle);
+               driver->remove(root->device->handle);
        }
 }
 
@@ -170,7 +170,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
        memset(root, 0, sizeof(struct acpi_pci_root));
        INIT_LIST_HEAD(&root->node);
 
-       root->handle = device->handle;
+       root->device = device;
        strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
        acpi_driver_data(device) = root;
@@ -185,7 +185,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
         * -------
         * Obtained via _SEG, if exists, otherwise assumed to be zero (0).
         */
-       status = acpi_evaluate_integer(root->handle, METHOD_NAME__SEG, NULL,
+       status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL,
                                       &value);
        switch (status) {
        case AE_OK:
@@ -207,7 +207,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
         * ---
         * Obtained via _BBN, if exists, otherwise assumed to be zero (0).
         */
-       status = acpi_evaluate_integer(root->handle, METHOD_NAME__BBN, NULL,
+       status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL,
                                       &value);
        switch (status) {
        case AE_OK:
@@ -234,7 +234,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
                                    "Wrong _BBN value, reboot"
                                    " and use option 'pci=noacpi'\n");
 
-                       status = try_get_root_bridge_busnr(root->handle, &bus);
+                       status = try_get_root_bridge_busnr(device->handle, &bus);
                        if (ACPI_FAILURE(status))
                                break;
                        if (bus != root->id.bus) {
@@ -294,9 +294,9 @@ static int acpi_pci_root_add(struct acpi_device *device)
         * -----------------
         * Evaluate and parse _PRT, if exists.
         */
-       status = acpi_get_handle(root->handle, METHOD_NAME__PRT, &handle);
+       status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
        if (ACPI_SUCCESS(status))
-               result = acpi_pci_irq_add_prt(root->handle, root->id.segment,
+               result = acpi_pci_irq_add_prt(device->handle, root->id.segment,
                                              root->id.bus);
 
       end:
@@ -315,7 +315,7 @@ static int acpi_pci_root_start(struct acpi_device *device)
 
 
        list_for_each_entry(root, &acpi_pci_roots, node) {
-               if (root->handle == device->handle) {
+               if (root->device == device) {
                        pci_bus_add_devices(root->bus);
                        return 0;
                }
index 224f729..5d3447f 100644 (file)
@@ -70,7 +70,7 @@ static struct acpi_driver acpi_power_driver = {
 };
 
 struct acpi_power_resource {
-       acpi_handle handle;
+       struct acpi_device * device;
        acpi_bus_id name;
        u32 system_level;
        u32 order;
@@ -124,7 +124,7 @@ static int acpi_power_get_state(struct acpi_power_resource *resource)
        if (!resource)
                return -EINVAL;
 
-       status = acpi_evaluate_integer(resource->handle, "_STA", NULL, &sta);
+       status = acpi_evaluate_integer(resource->device->handle, "_STA", NULL, &sta);
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
@@ -192,7 +192,7 @@ static int acpi_power_on(acpi_handle handle)
                return 0;
        }
 
-       status = acpi_evaluate_object(resource->handle, "_ON", NULL, NULL);
+       status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL);
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
@@ -203,10 +203,8 @@ static int acpi_power_on(acpi_handle handle)
                return -ENOEXEC;
 
        /* Update the power resource's _device_ power state */
-       result = acpi_bus_get_device(resource->handle, &device);
-       if (result)
-               return result;
-       device->power.state = ACPI_STATE_D0;
+       device = resource->device;
+       resource->device->power.state = ACPI_STATE_D0;
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned on\n",
                          resource->name));
@@ -242,7 +240,7 @@ static int acpi_power_off_device(acpi_handle handle)
                return 0;
        }
 
-       status = acpi_evaluate_object(resource->handle, "_OFF", NULL, NULL);
+       status = acpi_evaluate_object(resource->device->handle, "_OFF", NULL, NULL);
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
@@ -253,9 +251,7 @@ static int acpi_power_off_device(acpi_handle handle)
                return -ENOEXEC;
 
        /* Update the power resource's _device_ power state */
-       result = acpi_bus_get_device(resource->handle, &device);
-       if (result)
-               return result;
+       device = resource->device;
        device->power.state = ACPI_STATE_D3;
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned off\n",
@@ -544,14 +540,14 @@ static int acpi_power_add(struct acpi_device *device)
                return -ENOMEM;
        memset(resource, 0, sizeof(struct acpi_power_resource));
 
-       resource->handle = device->handle;
+       resource->device = device;
        strcpy(resource->name, device->pnp.bus_id);
        strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
        acpi_driver_data(device) = resource;
 
        /* Evalute the object to get the system level and resource order. */
-       status = acpi_evaluate_object(resource->handle, NULL, NULL, &buffer);
+       status = acpi_evaluate_object(device->handle, NULL, NULL, &buffer);
        if (ACPI_FAILURE(status)) {
                result = -ENODEV;
                goto end;
index e439eb7..8e9c26a 100644 (file)
@@ -768,7 +768,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
                status = -EFAULT;
 
       end:
-       acpi_os_free(buffer.pointer);
+       kfree(buffer.pointer);
 
        return status;
 }
index 14a00e5..7ba5e49 100644 (file)
@@ -216,7 +216,7 @@ static int acpi_processor_get_performance_control(struct acpi_processor *pr)
               sizeof(struct acpi_pct_register));
 
       end:
-       acpi_os_free(buffer.pointer);
+       kfree(buffer.pointer);
 
        return result;
 }
@@ -294,7 +294,7 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr)
        }
 
       end:
-       acpi_os_free(buffer.pointer);
+       kfree(buffer.pointer);
 
        return result;
 }
@@ -592,7 +592,7 @@ static int acpi_processor_get_psd(struct acpi_processor     *pr)
        }
 
 end:
-       acpi_os_free(buffer.pointer);
+       kfree(buffer.pointer);
        return result;
 }
 
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
new file mode 100644 (file)
index 0000000..db7b350
--- /dev/null
@@ -0,0 +1,1766 @@
+/*
+ *  acpi_sbs.c - ACPI Smart Battery System Driver ($Revision: 1.16 $)
+ *
+ *  Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  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
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <asm/uaccess.h>
+#include <linux/acpi.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+
+#include "i2c_ec.h"
+
+#define        DEF_CAPACITY_UNIT       3
+#define        MAH_CAPACITY_UNIT       1
+#define        MWH_CAPACITY_UNIT       2
+#define        CAPACITY_UNIT           DEF_CAPACITY_UNIT
+
+#define        REQUEST_UPDATE_MODE     1
+#define        QUEUE_UPDATE_MODE       2
+
+#define        DATA_TYPE_COMMON        0
+#define        DATA_TYPE_INFO          1
+#define        DATA_TYPE_STATE         2
+#define        DATA_TYPE_ALARM         3
+#define        DATA_TYPE_AC_STATE      4
+
+extern struct proc_dir_entry *acpi_lock_ac_dir(void);
+extern struct proc_dir_entry *acpi_lock_battery_dir(void);
+extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
+extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
+
+#define ACPI_SBS_COMPONENT             0x00080000
+#define ACPI_SBS_CLASS                 "sbs"
+#define ACPI_AC_CLASS                  "ac_adapter"
+#define ACPI_BATTERY_CLASS             "battery"
+#define ACPI_SBS_HID                   "ACPI0002"
+#define ACPI_SBS_DRIVER_NAME           "ACPI Smart Battery System Driver"
+#define ACPI_SBS_DEVICE_NAME           "Smart Battery System"
+#define ACPI_SBS_FILE_INFO             "info"
+#define ACPI_SBS_FILE_STATE            "state"
+#define ACPI_SBS_FILE_ALARM            "alarm"
+#define ACPI_BATTERY_DIR_NAME          "BAT%i"
+#define ACPI_AC_DIR_NAME               "AC0"
+#define ACPI_SBC_SMBUS_ADDR            0x9
+#define ACPI_SBSM_SMBUS_ADDR           0xa
+#define ACPI_SB_SMBUS_ADDR             0xb
+#define ACPI_SBS_AC_NOTIFY_STATUS      0x80
+#define ACPI_SBS_BATTERY_NOTIFY_STATUS 0x80
+#define ACPI_SBS_BATTERY_NOTIFY_INFO   0x81
+
+#define _COMPONENT                     ACPI_SBS_COMPONENT
+
+#define        MAX_SBS_BAT                     4
+#define        MAX_SMBUS_ERR                   1
+
+ACPI_MODULE_NAME("acpi_sbs");
+
+MODULE_AUTHOR("Rich Townsend");
+MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
+MODULE_LICENSE("GPL");
+
+static struct semaphore sbs_sem;
+
+#define        UPDATE_MODE             QUEUE_UPDATE_MODE
+/* REQUEST_UPDATE_MODE  QUEUE_UPDATE_MODE */
+#define        UPDATE_INFO_MODE        0
+#define        UPDATE_TIME             60
+#define        UPDATE_TIME2            0
+
+static int capacity_mode = CAPACITY_UNIT;
+static int update_mode = UPDATE_MODE;
+static int update_info_mode = UPDATE_INFO_MODE;
+static int update_time = UPDATE_TIME;
+static int update_time2 = UPDATE_TIME2;
+
+module_param(capacity_mode, int, CAPACITY_UNIT);
+module_param(update_mode, int, UPDATE_MODE);
+module_param(update_info_mode, int, UPDATE_INFO_MODE);
+module_param(update_time, int, UPDATE_TIME);
+module_param(update_time2, int, UPDATE_TIME2);
+
+static int acpi_sbs_add(struct acpi_device *device);
+static int acpi_sbs_remove(struct acpi_device *device, int type);
+static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus);
+static void acpi_sbs_update_queue(void *data);
+
+static struct acpi_driver acpi_sbs_driver = {
+       .name = ACPI_SBS_DRIVER_NAME,
+       .class = ACPI_SBS_CLASS,
+       .ids = ACPI_SBS_HID,
+       .ops = {
+               .add = acpi_sbs_add,
+               .remove = acpi_sbs_remove,
+               },
+};
+
+struct acpi_battery_info {
+       int capacity_mode;
+       s16 full_charge_capacity;
+       s16 design_capacity;
+       s16 design_voltage;
+       int vscale;
+       int ipscale;
+       s16 serial_number;
+       char manufacturer_name[I2C_SMBUS_BLOCK_MAX + 3];
+       char device_name[I2C_SMBUS_BLOCK_MAX + 3];
+       char device_chemistry[I2C_SMBUS_BLOCK_MAX + 3];
+};
+
+struct acpi_battery_state {
+       s16 voltage;
+       s16 amperage;
+       s16 remaining_capacity;
+       s16 average_time_to_empty;
+       s16 average_time_to_full;
+       s16 battery_status;
+};
+
+struct acpi_battery_alarm {
+       s16 remaining_capacity;
+};
+
+struct acpi_battery {
+       int alive;
+       int battery_present;
+       int id;
+       int init_state;
+       struct acpi_sbs *sbs;
+       struct acpi_battery_info info;
+       struct acpi_battery_state state;
+       struct acpi_battery_alarm alarm;
+       struct proc_dir_entry *battery_entry;
+};
+
+struct acpi_sbs {
+       acpi_handle handle;
+       struct acpi_device *device;
+       struct acpi_ec_smbus *smbus;
+       int sbsm_present;
+       int sbsm_batteries_supported;
+       int ac_present;
+       struct proc_dir_entry *ac_entry;
+       struct acpi_battery battery[MAX_SBS_BAT];
+       int update_info_mode;
+       int zombie;
+       int update_time;
+       int update_time2;
+       struct timer_list update_timer;
+};
+
+static void acpi_update_delay(struct acpi_sbs *sbs);
+static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type);
+
+/* --------------------------------------------------------------------------
+                               SMBus Communication
+   -------------------------------------------------------------------------- */
+
+static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus)
+{
+       union i2c_smbus_data data;
+       int result = 0;
+       char *err_str;
+       int err_number;
+
+       data.word = 0;
+
+       result = smbus->adapter.algo->
+           smbus_xfer(&smbus->adapter,
+                      ACPI_SB_SMBUS_ADDR,
+                      0, I2C_SMBUS_READ, 0x16, I2C_SMBUS_BLOCK_DATA, &data);
+
+       err_number = (data.word & 0x000f);
+
+       switch (data.word & 0x000f) {
+       case 0x0000:
+               err_str = "unexpected bus error";
+               break;
+       case 0x0001:
+               err_str = "busy";
+               break;
+       case 0x0002:
+               err_str = "reserved command";
+               break;
+       case 0x0003:
+               err_str = "unsupported command";
+               break;
+       case 0x0004:
+               err_str = "access denied";
+               break;
+       case 0x0005:
+               err_str = "overflow/underflow";
+               break;
+       case 0x0006:
+               err_str = "bad size";
+               break;
+       case 0x0007:
+               err_str = "unknown error";
+               break;
+       default:
+               err_str = "unrecognized error";
+       }
+       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                         "%s: ret %i, err %i\n", err_str, result, err_number));
+}
+
+static int
+acpi_sbs_smbus_read_word(struct acpi_ec_smbus *smbus, int addr, int func,
+                        u16 * word,
+                        void (*err_handler) (struct acpi_ec_smbus * smbus))
+{
+       union i2c_smbus_data data;
+       int result = 0;
+       int i;
+
+       if (err_handler == NULL) {
+               err_handler = acpi_battery_smbus_err_handler;
+       }
+
+       for (i = 0; i < MAX_SMBUS_ERR; i++) {
+               result =
+                   smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0,
+                                                   I2C_SMBUS_READ, func,
+                                                   I2C_SMBUS_WORD_DATA, &data);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "try %i: smbus->adapter.algo->smbus_xfer() failed\n",
+                                         i));
+                       if (err_handler) {
+                               err_handler(smbus);
+                       }
+               } else {
+                       *word = data.word;
+                       break;
+               }
+       }
+
+       return result;
+}
+
+static int
+acpi_sbs_smbus_read_str(struct acpi_ec_smbus *smbus, int addr, int func,
+                       char *str,
+                       void (*err_handler) (struct acpi_ec_smbus * smbus))
+{
+       union i2c_smbus_data data;
+       int result = 0;
+       int i;
+
+       if (err_handler == NULL) {
+               err_handler = acpi_battery_smbus_err_handler;
+       }
+
+       for (i = 0; i < MAX_SMBUS_ERR; i++) {
+               result =
+                   smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0,
+                                                   I2C_SMBUS_READ, func,
+                                                   I2C_SMBUS_BLOCK_DATA,
+                                                   &data);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "try %i: smbus->adapter.algo->smbus_xfer() failed\n",
+                                         i));
+                       if (err_handler) {
+                               err_handler(smbus);
+                       }
+               } else {
+                       strncpy(str, (const char *)data.block + 1,
+                               data.block[0]);
+                       str[data.block[0]] = 0;
+                       break;
+               }
+       }
+
+       return result;
+}
+
+static int
+acpi_sbs_smbus_write_word(struct acpi_ec_smbus *smbus, int addr, int func,
+                         int word,
+                         void (*err_handler) (struct acpi_ec_smbus * smbus))
+{
+       union i2c_smbus_data data;
+       int result = 0;
+       int i;
+
+       if (err_handler == NULL) {
+               err_handler = acpi_battery_smbus_err_handler;
+       }
+
+       data.word = word;
+
+       for (i = 0; i < MAX_SMBUS_ERR; i++) {
+               result =
+                   smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0,
+                                                   I2C_SMBUS_WRITE, func,
+                                                   I2C_SMBUS_WORD_DATA, &data);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "try %i: smbus->adapter.algo"
+                                         "->smbus_xfer() failed\n", i));
+                       if (err_handler) {
+                               err_handler(smbus);
+                       }
+               } else {
+                       break;
+               }
+       }
+
+       return result;
+}
+
+/* --------------------------------------------------------------------------
+                            Smart Battery System Management
+   -------------------------------------------------------------------------- */
+
+/* Smart Battery */
+
+static int acpi_sbs_generate_event(struct acpi_device *device,
+                                  int event, int state, char *bid, char *class)
+{
+       char bid_saved[5];
+       char class_saved[20];
+       int result = 0;
+
+       strcpy(bid_saved, acpi_device_bid(device));
+       strcpy(class_saved, acpi_device_class(device));
+
+       strcpy(acpi_device_bid(device), bid);
+       strcpy(acpi_device_class(device), class);
+
+       result = acpi_bus_generate_event(device, event, state);
+
+       strcpy(acpi_device_bid(device), bid_saved);
+       strcpy(acpi_device_class(device), class_saved);
+
+       return result;
+}
+
+static int acpi_battery_get_present(struct acpi_battery *battery)
+{
+       s16 state;
+       int result = 0;
+       int is_present = 0;
+
+       result = acpi_sbs_smbus_read_word(battery->sbs->smbus,
+                                         ACPI_SBSM_SMBUS_ADDR, 0x01,
+                                         &state, NULL);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed"));
+       }
+       if (!result) {
+               is_present = (state & 0x000f) & (1 << battery->id);
+       }
+       battery->battery_present = is_present;
+
+       return result;
+}
+
+static int acpi_battery_is_present(struct acpi_battery *battery)
+{
+       return (battery->battery_present);
+}
+
+static int acpi_ac_is_present(struct acpi_sbs *sbs)
+{
+       return (sbs->ac_present);
+}
+
+static int acpi_battery_select(struct acpi_battery *battery)
+{
+       struct acpi_ec_smbus *smbus = battery->sbs->smbus;
+       int result = 0;
+       s16 state;
+       int foo;
+
+       if (battery->sbs->sbsm_present) {
+
+               /* Take special care not to knobble other nibbles of
+                * state (aka selector_state), since
+                * it causes charging to halt on SBSELs */
+
+               result =
+                   acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01,
+                                            &state, NULL);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_smbus_read_word() failed\n"));
+                       goto end;
+               }
+
+               foo = (state & 0x0fff) | (1 << (battery->id + 12));
+               result =
+                   acpi_sbs_smbus_write_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01,
+                                             foo, NULL);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_smbus_write_word() failed\n"));
+                       goto end;
+               }
+       }
+
+      end:
+       return result;
+}
+
+static int acpi_sbsm_get_info(struct acpi_sbs *sbs)
+{
+       struct acpi_ec_smbus *smbus = sbs->smbus;
+       int result = 0;
+       s16 battery_system_info;
+
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x04,
+                                         &battery_system_info, NULL);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       sbs->sbsm_batteries_supported = battery_system_info & 0x000f;
+
+      end:
+
+       return result;
+}
+
+static int acpi_battery_get_info(struct acpi_battery *battery)
+{
+       struct acpi_ec_smbus *smbus = battery->sbs->smbus;
+       int result = 0;
+       s16 battery_mode;
+       s16 specification_info;
+
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03,
+                                         &battery_mode,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+       battery->info.capacity_mode = (battery_mode & 0x8000) >> 15;
+
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x10,
+                                         &battery->info.full_charge_capacity,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x18,
+                                         &battery->info.design_capacity,
+                                         &acpi_battery_smbus_err_handler);
+
+       if (result) {
+               goto end;
+       }
+
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x19,
+                                         &battery->info.design_voltage,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1a,
+                                         &specification_info,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       switch ((specification_info & 0x0f00) >> 8) {
+       case 1:
+               battery->info.vscale = 10;
+               break;
+       case 2:
+               battery->info.vscale = 100;
+               break;
+       case 3:
+               battery->info.vscale = 1000;
+               break;
+       default:
+               battery->info.vscale = 1;
+       }
+
+       switch ((specification_info & 0xf000) >> 12) {
+       case 1:
+               battery->info.ipscale = 10;
+               break;
+       case 2:
+               battery->info.ipscale = 100;
+               break;
+       case 3:
+               battery->info.ipscale = 1000;
+               break;
+       default:
+               battery->info.ipscale = 1;
+       }
+
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1c,
+                                         &battery->info.serial_number,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               goto end;
+       }
+
+       result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x20,
+                                        battery->info.manufacturer_name,
+                                        &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_str() failed\n"));
+               goto end;
+       }
+
+       result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x21,
+                                        battery->info.device_name,
+                                        &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_str() failed\n"));
+               goto end;
+       }
+
+       result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x22,
+                                        battery->info.device_chemistry,
+                                        &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_str() failed\n"));
+               goto end;
+       }
+
+      end:
+       return result;
+}
+
+static void acpi_update_delay(struct acpi_sbs *sbs)
+{
+       if (sbs->zombie) {
+               return;
+       }
+       if (sbs->update_time2 > 0) {
+               msleep(sbs->update_time2 * 1000);
+       }
+}
+
+static int acpi_battery_get_state(struct acpi_battery *battery)
+{
+       struct acpi_ec_smbus *smbus = battery->sbs->smbus;
+       int result = 0;
+
+       acpi_update_delay(battery->sbs);
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x09,
+                                         &battery->state.voltage,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       acpi_update_delay(battery->sbs);
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0a,
+                                         &battery->state.amperage,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       acpi_update_delay(battery->sbs);
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0f,
+                                         &battery->state.remaining_capacity,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       acpi_update_delay(battery->sbs);
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x12,
+                                         &battery->state.average_time_to_empty,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       acpi_update_delay(battery->sbs);
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x13,
+                                         &battery->state.average_time_to_full,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       acpi_update_delay(battery->sbs);
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x16,
+                                         &battery->state.battery_status,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       acpi_update_delay(battery->sbs);
+
+      end:
+       return result;
+}
+
+static int acpi_battery_get_alarm(struct acpi_battery *battery)
+{
+       struct acpi_ec_smbus *smbus = battery->sbs->smbus;
+       int result = 0;
+
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01,
+                                         &battery->alarm.remaining_capacity,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       acpi_update_delay(battery->sbs);
+
+      end:
+
+       return result;
+}
+
+static int acpi_battery_set_alarm(struct acpi_battery *battery,
+                                 unsigned long alarm)
+{
+       struct acpi_ec_smbus *smbus = battery->sbs->smbus;
+       int result = 0;
+       s16 battery_mode;
+       int foo;
+
+       result = acpi_battery_select(battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_select() failed\n"));
+               goto end;
+       }
+
+       /* If necessary, enable the alarm */
+
+       if (alarm > 0) {
+               result =
+                   acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03,
+                                            &battery_mode,
+                                            &acpi_battery_smbus_err_handler);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_smbus_read_word() failed\n"));
+                       goto end;
+               }
+
+               result =
+                   acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01,
+                                             battery_mode & 0xbfff,
+                                             &acpi_battery_smbus_err_handler);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_smbus_write_word() failed\n"));
+                       goto end;
+               }
+       }
+
+       foo = alarm / (battery->info.capacity_mode ? 10 : 1);
+       result = acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01,
+                                          foo,
+                                          &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_write_word() failed\n"));
+               goto end;
+       }
+
+      end:
+
+       return result;
+}
+
+static int acpi_battery_set_mode(struct acpi_battery *battery)
+{
+       int result = 0;
+       s16 battery_mode;
+
+       if (capacity_mode == DEF_CAPACITY_UNIT) {
+               goto end;
+       }
+
+       result = acpi_sbs_smbus_read_word(battery->sbs->smbus,
+                                         ACPI_SB_SMBUS_ADDR, 0x03,
+                                         &battery_mode, NULL);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       if (capacity_mode == MAH_CAPACITY_UNIT) {
+               battery_mode &= 0x7fff;
+       } else {
+               battery_mode |= 0x8000;
+       }
+       result = acpi_sbs_smbus_write_word(battery->sbs->smbus,
+                                          ACPI_SB_SMBUS_ADDR, 0x03,
+                                          battery_mode, NULL);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_write_word() failed\n"));
+               goto end;
+       }
+
+       result = acpi_sbs_smbus_read_word(battery->sbs->smbus,
+                                         ACPI_SB_SMBUS_ADDR, 0x03,
+                                         &battery_mode, NULL);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+      end:
+       return result;
+}
+
+static int acpi_battery_init(struct acpi_battery *battery)
+{
+       int result = 0;
+
+       result = acpi_battery_select(battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_init() failed\n"));
+               goto end;
+       }
+
+       result = acpi_battery_set_mode(battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_set_mode() failed\n"));
+               goto end;
+       }
+
+       result = acpi_battery_get_info(battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_get_info() failed\n"));
+               goto end;
+       }
+
+       result = acpi_battery_get_state(battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_get_state() failed\n"));
+               goto end;
+       }
+
+       result = acpi_battery_get_alarm(battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_get_alarm() failed\n"));
+               goto end;
+       }
+
+      end:
+       return result;
+}
+
+static int acpi_ac_get_present(struct acpi_sbs *sbs)
+{
+       struct acpi_ec_smbus *smbus = sbs->smbus;
+       int result = 0;
+       s16 charger_status;
+
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SBC_SMBUS_ADDR, 0x13,
+                                         &charger_status, NULL);
+
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       sbs->ac_present = (charger_status & 0x8000) >> 15;
+
+      end:
+
+       return result;
+}
+
+/* --------------------------------------------------------------------------
+                              FS Interface (/proc/acpi)
+   -------------------------------------------------------------------------- */
+
+/* Generic Routines */
+
+static int
+acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
+                       struct proc_dir_entry *parent_dir,
+                       char *dir_name,
+                       struct file_operations *info_fops,
+                       struct file_operations *state_fops,
+                       struct file_operations *alarm_fops, void *data)
+{
+       struct proc_dir_entry *entry = NULL;
+
+       if (!*dir) {
+               *dir = proc_mkdir(dir_name, parent_dir);
+               if (!*dir) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "proc_mkdir() failed\n"));
+                       return -ENODEV;
+               }
+               (*dir)->owner = THIS_MODULE;
+       }
+
+       /* 'info' [R] */
+       if (info_fops) {
+               entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir);
+               if (!entry) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "create_proc_entry() failed\n"));
+               } else {
+                       entry->proc_fops = info_fops;
+                       entry->data = data;
+                       entry->owner = THIS_MODULE;
+               }
+       }
+
+       /* 'state' [R] */
+       if (state_fops) {
+               entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir);
+               if (!entry) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "create_proc_entry() failed\n"));
+               } else {
+                       entry->proc_fops = state_fops;
+                       entry->data = data;
+                       entry->owner = THIS_MODULE;
+               }
+       }
+
+       /* 'alarm' [R/W] */
+       if (alarm_fops) {
+               entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir);
+               if (!entry) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "create_proc_entry() failed\n"));
+               } else {
+                       entry->proc_fops = alarm_fops;
+                       entry->data = data;
+                       entry->owner = THIS_MODULE;
+               }
+       }
+
+       return 0;
+}
+
+static void
+acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir,
+                          struct proc_dir_entry *parent_dir)
+{
+
+       if (*dir) {
+               remove_proc_entry(ACPI_SBS_FILE_INFO, *dir);
+               remove_proc_entry(ACPI_SBS_FILE_STATE, *dir);
+               remove_proc_entry(ACPI_SBS_FILE_ALARM, *dir);
+               remove_proc_entry((*dir)->name, parent_dir);
+               *dir = NULL;
+       }
+
+}
+
+/* Smart Battery Interface */
+
+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;
+       int cscale;
+       int result = 0;
+
+       if (battery->sbs->zombie) {
+               return -ENODEV;
+       }
+
+       down(&sbs_sem);
+
+       if (update_mode == REQUEST_UPDATE_MODE) {
+               result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_INFO);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_update_run() failed\n"));
+               }
+       }
+
+       if (acpi_battery_is_present(battery)) {
+               seq_printf(seq, "present:                 yes\n");
+       } else {
+               seq_printf(seq, "present:                 no\n");
+               goto end;
+       }
+
+       if (battery->info.capacity_mode) {
+               cscale = battery->info.vscale * battery->info.ipscale;
+       } else {
+               cscale = battery->info.ipscale;
+       }
+       seq_printf(seq, "design capacity:         %i%s",
+                  battery->info.design_capacity * cscale,
+                  battery->info.capacity_mode ? "0 mWh\n" : " mAh\n");
+
+       seq_printf(seq, "last full capacity:      %i%s",
+                  battery->info.full_charge_capacity * cscale,
+                  battery->info.capacity_mode ? "0 mWh\n" : " mAh\n");
+
+       seq_printf(seq, "battery technology:      rechargeable\n");
+
+       seq_printf(seq, "design voltage:          %i mV\n",
+                  battery->info.design_voltage * battery->info.vscale);
+
+       seq_printf(seq, "design capacity warning: unknown\n");
+       seq_printf(seq, "design capacity low:     unknown\n");
+       seq_printf(seq, "capacity granularity 1:  unknown\n");
+       seq_printf(seq, "capacity granularity 2:  unknown\n");
+
+       seq_printf(seq, "model number:            %s\n",
+                  battery->info.device_name);
+
+       seq_printf(seq, "serial number:           %i\n",
+                  battery->info.serial_number);
+
+       seq_printf(seq, "battery type:            %s\n",
+                  battery->info.device_chemistry);
+
+       seq_printf(seq, "OEM info:                %s\n",
+                  battery->info.manufacturer_name);
+
+      end:
+
+       up(&sbs_sem);
+
+       return result;
+}
+
+static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
+{
+       return single_open(file, acpi_battery_read_info, PDE(inode)->data);
+}
+
+static int acpi_battery_read_state(struct seq_file *seq, void *offset)
+{
+       struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+       int result = 0;
+       int cscale;
+       int foo;
+
+       if (battery->sbs->zombie) {
+               return -ENODEV;
+       }
+
+       down(&sbs_sem);
+
+       if (update_mode == REQUEST_UPDATE_MODE) {
+               result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_STATE);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_update_run() failed\n"));
+               }
+       }
+
+       if (acpi_battery_is_present(battery)) {
+               seq_printf(seq, "present:                 yes\n");
+       } else {
+               seq_printf(seq, "present:                 no\n");
+               goto end;
+       }
+
+       if (battery->info.capacity_mode) {
+               cscale = battery->info.vscale * battery->info.ipscale;
+       } else {
+               cscale = battery->info.ipscale;
+       }
+
+       if (battery->state.battery_status & 0x0010) {
+               seq_printf(seq, "capacity state:          critical\n");
+       } else {
+               seq_printf(seq, "capacity state:          ok\n");
+       }
+       if (battery->state.amperage < 0) {
+               seq_printf(seq, "charging state:          discharging\n");
+               foo = battery->state.remaining_capacity * cscale * 60 /
+                   (battery->state.average_time_to_empty == 0 ? 1 :
+                    battery->state.average_time_to_empty);
+               seq_printf(seq, "present rate:            %i%s\n",
+                          foo, battery->info.capacity_mode ? "0 mW" : " mA");
+       } else if (battery->state.amperage > 0) {
+               seq_printf(seq, "charging state:          charging\n");
+               foo = (battery->info.full_charge_capacity -
+                      battery->state.remaining_capacity) * cscale * 60 /
+                   (battery->state.average_time_to_full == 0 ? 1 :
+                    battery->state.average_time_to_full);
+               seq_printf(seq, "present rate:            %i%s\n",
+                          foo, battery->info.capacity_mode ? "0 mW" : " mA");
+       } else {
+               seq_printf(seq, "charging state:          charged\n");
+               seq_printf(seq, "present rate:            0 %s\n",
+                          battery->info.capacity_mode ? "mW" : "mA");
+       }
+
+       seq_printf(seq, "remaining capacity:      %i%s",
+                  battery->state.remaining_capacity * cscale,
+                  battery->info.capacity_mode ? "0 mWh\n" : " mAh\n");
+
+       seq_printf(seq, "present voltage:         %i mV\n",
+                  battery->state.voltage * battery->info.vscale);
+
+      end:
+
+       up(&sbs_sem);
+
+       return result;
+}
+
+static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
+{
+       return single_open(file, acpi_battery_read_state, PDE(inode)->data);
+}
+
+static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
+{
+       struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+       int result = 0;
+       int cscale;
+
+       if (battery->sbs->zombie) {
+               return -ENODEV;
+       }
+
+       down(&sbs_sem);
+
+       if (update_mode == REQUEST_UPDATE_MODE) {
+               result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_ALARM);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_update_run() failed\n"));
+               }
+       }
+
+       if (!acpi_battery_is_present(battery)) {
+               seq_printf(seq, "present:                 no\n");
+               goto end;
+       }
+
+       if (battery->info.capacity_mode) {
+               cscale = battery->info.vscale * battery->info.ipscale;
+       } else {
+               cscale = battery->info.ipscale;
+       }
+
+       seq_printf(seq, "alarm:                   ");
+       if (battery->alarm.remaining_capacity) {
+               seq_printf(seq, "%i%s",
+                          battery->alarm.remaining_capacity * cscale,
+                          battery->info.capacity_mode ? "0 mWh\n" : " mAh\n");
+       } else {
+               seq_printf(seq, "disabled\n");
+       }
+
+      end:
+
+       up(&sbs_sem);
+
+       return result;
+}
+
+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;
+       char alarm_string[12] = { '\0' };
+       int result, old_alarm, new_alarm;
+
+       if (battery->sbs->zombie) {
+               return -ENODEV;
+       }
+
+       down(&sbs_sem);
+
+       if (!acpi_battery_is_present(battery)) {
+               result = -ENODEV;
+               goto end;
+       }
+
+       if (count > sizeof(alarm_string) - 1) {
+               result = -EINVAL;
+               goto end;
+       }
+
+       if (copy_from_user(alarm_string, buffer, count)) {
+               result = -EFAULT;
+               goto end;
+       }
+
+       alarm_string[count] = 0;
+
+       old_alarm = battery->alarm.remaining_capacity;
+       new_alarm = simple_strtoul(alarm_string, NULL, 0);
+
+       result = acpi_battery_set_alarm(battery, new_alarm);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_set_alarm() failed\n"));
+               (void)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);
+               goto end;
+       }
+
+      end:
+       up(&sbs_sem);
+
+       if (result) {
+               return result;
+       } else {
+               return count;
+       }
+}
+
+static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
+{
+       return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
+}
+
+static struct file_operations acpi_battery_info_fops = {
+       .open = acpi_battery_info_open_fs,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .owner = THIS_MODULE,
+};
+
+static struct file_operations acpi_battery_state_fops = {
+       .open = acpi_battery_state_open_fs,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .owner = THIS_MODULE,
+};
+
+static struct file_operations acpi_battery_alarm_fops = {
+       .open = acpi_battery_alarm_open_fs,
+       .read = seq_read,
+       .write = acpi_battery_write_alarm,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .owner = THIS_MODULE,
+};
+
+/* Legacy AC Adapter Interface */
+
+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;
+       int result;
+
+       if (sbs->zombie) {
+               return -ENODEV;
+       }
+
+       down(&sbs_sem);
+
+       if (update_mode == REQUEST_UPDATE_MODE) {
+               result = acpi_sbs_update_run(sbs, DATA_TYPE_AC_STATE);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_update_run() failed\n"));
+               }
+       }
+
+       seq_printf(seq, "state:                   %s\n",
+                  sbs->ac_present ? "on-line" : "off-line");
+
+       up(&sbs_sem);
+
+       return 0;
+}
+
+static int acpi_ac_state_open_fs(struct inode *inode, struct file *file)
+{
+       return single_open(file, acpi_ac_read_state, PDE(inode)->data);
+}
+
+static struct file_operations acpi_ac_state_fops = {
+       .open = acpi_ac_state_open_fs,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .owner = THIS_MODULE,
+};
+
+/* --------------------------------------------------------------------------
+                                 Driver Interface
+   -------------------------------------------------------------------------- */
+
+/* Smart Battery */
+
+static int acpi_battery_add(struct acpi_sbs *sbs, int id)
+{
+       int is_present;
+       int result;
+       char dir_name[32];
+       struct acpi_battery *battery;
+
+       battery = &sbs->battery[id];
+
+       battery->alive = 0;
+
+       battery->init_state = 0;
+       battery->id = id;
+       battery->sbs = sbs;
+
+       result = acpi_battery_select(battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_select() failed\n"));
+               goto end;
+       }
+
+       result = acpi_battery_get_present(battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_get_present() failed\n"));
+               goto end;
+       }
+
+       is_present = acpi_battery_is_present(battery);
+
+       if (is_present) {
+               result = acpi_battery_init(battery);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_battery_init() failed\n"));
+                       goto end;
+               }
+               battery->init_state = 1;
+       }
+
+       (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
+
+       result = acpi_sbs_generic_add_fs(&battery->battery_entry,
+                                        acpi_battery_dir,
+                                        dir_name,
+                                        &acpi_battery_info_fops,
+                                        &acpi_battery_state_fops,
+                                        &acpi_battery_alarm_fops, battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_generic_add_fs() failed\n"));
+               goto end;
+       }
+       battery->alive = 1;
+
+      end:
+       return result;
+}
+
+static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
+{
+
+       if (sbs->battery[id].battery_entry) {
+               acpi_sbs_generic_remove_fs(&(sbs->battery[id].battery_entry),
+                                          acpi_battery_dir);
+       }
+}
+
+static int acpi_ac_add(struct acpi_sbs *sbs)
+{
+       int result;
+
+       result = acpi_ac_get_present(sbs);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_ac_get_present() failed\n"));
+               goto end;
+       }
+
+       result = acpi_sbs_generic_add_fs(&sbs->ac_entry,
+                                        acpi_ac_dir,
+                                        ACPI_AC_DIR_NAME,
+                                        NULL, &acpi_ac_state_fops, NULL, sbs);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_generic_add_fs() failed\n"));
+               goto end;
+       }
+
+      end:
+
+       return result;
+}
+
+static void acpi_ac_remove(struct acpi_sbs *sbs)
+{
+
+       if (sbs->ac_entry) {
+               acpi_sbs_generic_remove_fs(&sbs->ac_entry, acpi_ac_dir);
+       }
+}
+
+static void acpi_sbs_update_queue_run(unsigned long data)
+{
+       acpi_os_execute(OSL_GPE_HANDLER, acpi_sbs_update_queue, (void *)data);
+}
+
+static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type)
+{
+       struct acpi_battery *battery;
+       int result = 0;
+       int old_ac_present;
+       int old_battery_present;
+       int new_ac_present;
+       int new_battery_present;
+       int id;
+       char dir_name[32];
+       int do_battery_init, do_ac_init;
+       s16 old_remaining_capacity;
+
+       if (sbs->zombie) {
+               goto end;
+       }
+
+       old_ac_present = acpi_ac_is_present(sbs);
+
+       result = acpi_ac_get_present(sbs);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_ac_get_present() failed\n"));
+       }
+
+       new_ac_present = acpi_ac_is_present(sbs);
+
+       do_ac_init = (old_ac_present != new_ac_present);
+
+       if (data_type == DATA_TYPE_AC_STATE) {
+               goto end;
+       }
+
+       for (id = 0; id < MAX_SBS_BAT; id++) {
+               battery = &sbs->battery[id];
+               if (battery->alive == 0) {
+                       continue;
+               }
+
+               old_remaining_capacity = battery->state.remaining_capacity;
+
+               old_battery_present = acpi_battery_is_present(battery);
+
+               result = acpi_battery_select(battery);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_battery_select() failed\n"));
+               }
+               if (sbs->zombie) {
+                       goto end;
+               }
+
+               result = acpi_battery_get_present(battery);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_battery_get_present() failed\n"));
+               }
+               if (sbs->zombie) {
+                       goto end;
+               }
+
+               new_battery_present = acpi_battery_is_present(battery);
+
+               do_battery_init = ((old_battery_present != new_battery_present)
+                                  && new_battery_present);
+
+               if (sbs->zombie) {
+                       goto end;
+               }
+               if (do_ac_init || do_battery_init ||
+                   update_info_mode || sbs->update_info_mode) {
+                       if (sbs->update_info_mode) {
+                               sbs->update_info_mode = 0;
+                       } else {
+                               sbs->update_info_mode = 1;
+                       }
+                       result = acpi_battery_init(battery);
+                       if (result) {
+                               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                                 "acpi_battery_init() "
+                                                 "failed\n"));
+                       }
+               }
+               if (data_type == DATA_TYPE_INFO) {
+                       continue;
+               }
+
+               if (sbs->zombie) {
+                       goto end;
+               }
+               if (new_battery_present) {
+                       result = acpi_battery_get_alarm(battery);
+                       if (result) {
+                               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                                 "acpi_battery_get_alarm() "
+                                                 "failed\n"));
+                       }
+                       if (data_type == DATA_TYPE_ALARM) {
+                               continue;
+                       }
+
+                       result = acpi_battery_get_state(battery);
+                       if (result) {
+                               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                                 "acpi_battery_get_state() "
+                                                 "failed\n"));
+                       }
+               }
+               if (sbs->zombie) {
+                       goto end;
+               }
+               if (data_type != DATA_TYPE_COMMON) {
+                       continue;
+               }
+
+               if (old_battery_present != new_battery_present) {
+                       (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
+                       result = acpi_sbs_generate_event(sbs->device,
+                                                        ACPI_SBS_BATTERY_NOTIFY_STATUS,
+                                                        new_battery_present,
+                                                        dir_name,
+                                                        ACPI_BATTERY_CLASS);
+                       if (result) {
+                               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                                 "acpi_sbs_generate_event() "
+                                                 "failed\n"));
+                       }
+               }
+               if (old_remaining_capacity != battery->state.remaining_capacity) {
+                       (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
+                       result = acpi_sbs_generate_event(sbs->device,
+                                                        ACPI_SBS_BATTERY_NOTIFY_STATUS,
+                                                        new_battery_present,
+                                                        dir_name,
+                                                        ACPI_BATTERY_CLASS);
+                       if (result) {
+                               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                                 "acpi_sbs_generate_event() failed\n"));
+                       }
+               }
+
+       }
+       if (sbs->zombie) {
+               goto end;
+       }
+       if (data_type != DATA_TYPE_COMMON) {
+               goto end;
+       }
+
+       if (old_ac_present != new_ac_present) {
+               result = acpi_sbs_generate_event(sbs->device,
+                                                ACPI_SBS_AC_NOTIFY_STATUS,
+                                                new_ac_present,
+                                                ACPI_AC_DIR_NAME,
+                                                ACPI_AC_CLASS);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_generate_event() failed\n"));
+               }
+       }
+
+      end:
+       return result;
+}
+
+static void acpi_sbs_update_queue(void *data)
+{
+       struct acpi_sbs *sbs = data;
+       unsigned long delay = -1;
+       int result;
+
+       if (sbs->zombie) {
+               goto end;
+       }
+
+       result = acpi_sbs_update_run(sbs, DATA_TYPE_COMMON);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_update_run() failed\n"));
+       }
+
+       if (sbs->zombie) {
+               goto end;
+       }
+
+       if (update_mode == REQUEST_UPDATE_MODE) {
+               goto end;
+       }
+
+       delay = jiffies + HZ * update_time;
+       sbs->update_timer.data = (unsigned long)data;
+       sbs->update_timer.function = acpi_sbs_update_queue_run;
+       sbs->update_timer.expires = delay;
+       add_timer(&sbs->update_timer);
+      end:
+       ;
+}
+
+static int acpi_sbs_add(struct acpi_device *device)
+{
+       struct acpi_sbs *sbs = NULL;
+       struct acpi_ec_hc *ec_hc = NULL;
+       int result, remove_result = 0;
+       unsigned long sbs_obj;
+       int id, cnt;
+       acpi_status status = AE_OK;
+
+       sbs = kmalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
+       if (!sbs) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "kmalloc() failed\n"));
+               return -ENOMEM;
+       }
+       memset(sbs, 0, sizeof(struct acpi_sbs));
+
+       cnt = 0;
+       while (cnt < 10) {
+               cnt++;
+               ec_hc = acpi_get_ec_hc(device);
+               if (ec_hc) {
+                       break;
+               }
+               msleep(1000);
+       }
+
+       if (!ec_hc) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_get_ec_hc() failed: "
+                                 "NO driver found for EC HC SMBus\n"));
+               result = -ENODEV;
+               goto end;
+       }
+
+       sbs->device = device;
+       sbs->smbus = ec_hc->smbus;
+
+       strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
+       strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
+       acpi_driver_data(device) = sbs;
+
+       sbs->update_time = 0;
+       sbs->update_time2 = 0;
+
+       result = acpi_ac_add(sbs);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "acpi_ac_add() failed\n"));
+               goto end;
+       }
+       result = acpi_evaluate_integer(device->handle, "_SBS", NULL, &sbs_obj);
+       if (ACPI_FAILURE(result)) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_evaluate_integer() failed\n"));
+               result = -EIO;
+               goto end;
+       }
+
+       if (sbs_obj > 0) {
+               result = acpi_sbsm_get_info(sbs);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbsm_get_info() failed\n"));
+                       goto end;
+               }
+               sbs->sbsm_present = 1;
+       }
+       if (sbs->sbsm_present == 0) {
+               result = acpi_battery_add(sbs, 0);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_battery_add() failed\n"));
+                       goto end;
+               }
+       } else {
+               for (id = 0; id < MAX_SBS_BAT; id++) {
+                       if ((sbs->sbsm_batteries_supported & (1 << id))) {
+                               result = acpi_battery_add(sbs, id);
+                               if (result) {
+                                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                                         "acpi_battery_add() "
+                                                         "failed\n"));
+                                       goto end;
+                               }
+                       }
+               }
+       }
+
+       sbs->handle = device->handle;
+
+       init_timer(&sbs->update_timer);
+       if (update_mode == QUEUE_UPDATE_MODE) {
+               status = acpi_os_execute(OSL_GPE_HANDLER,
+                                        acpi_sbs_update_queue, (void *)sbs);
+               if (status != AE_OK) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_os_execute() failed\n"));
+               }
+       }
+       sbs->update_time = update_time;
+       sbs->update_time2 = update_time2;
+
+       printk(KERN_INFO PREFIX "%s [%s]\n",
+              acpi_device_name(device), acpi_device_bid(device));
+
+      end:
+       if (result) {
+               remove_result = acpi_sbs_remove(device, 0);
+               if (remove_result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_remove() failed\n"));
+               }
+       }
+
+       return result;
+}
+
+int acpi_sbs_remove(struct acpi_device *device, int type)
+{
+       struct acpi_sbs *sbs = (struct acpi_sbs *)acpi_driver_data(device);
+       int id;
+
+       if (!device || !sbs) {
+               return -EINVAL;
+       }
+
+       sbs->zombie = 1;
+       sbs->update_time = 0;
+       sbs->update_time2 = 0;
+       del_timer_sync(&sbs->update_timer);
+       acpi_os_wait_events_complete(NULL);
+       del_timer_sync(&sbs->update_timer);
+
+       for (id = 0; id < MAX_SBS_BAT; id++) {
+               acpi_battery_remove(sbs, id);
+       }
+
+       acpi_ac_remove(sbs);
+
+       kfree(sbs);
+
+       return 0;
+}
+
+static int __init acpi_sbs_init(void)
+{
+       int result = 0;
+
+       init_MUTEX(&sbs_sem);
+
+       if (capacity_mode != DEF_CAPACITY_UNIT
+           && capacity_mode != MAH_CAPACITY_UNIT
+           && capacity_mode != MWH_CAPACITY_UNIT) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "acpi_sbs_init: "
+                                 "invalid capacity_mode = %d\n",
+                                 capacity_mode));
+               return -EINVAL;
+       }
+
+       acpi_ac_dir = acpi_lock_ac_dir();
+       if (!acpi_ac_dir) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_lock_ac_dir() failed\n"));
+               return -ENODEV;
+       }
+
+       acpi_battery_dir = acpi_lock_battery_dir();
+       if (!acpi_battery_dir) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_lock_battery_dir() failed\n"));
+               return -ENODEV;
+       }
+
+       result = acpi_bus_register_driver(&acpi_sbs_driver);
+       if (result < 0) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_bus_register_driver() failed\n"));
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static void __exit acpi_sbs_exit(void)
+{
+
+       acpi_bus_unregister_driver(&acpi_sbs_driver);
+
+       acpi_unlock_ac_dir(acpi_ac_dir);
+       acpi_ac_dir = NULL;
+       acpi_unlock_battery_dir(acpi_battery_dir);
+       acpi_battery_dir = NULL;
+
+       return;
+}
+
+module_init(acpi_sbs_init);
+module_exit(acpi_sbs_exit);
index 861ac37..5fcb50c 100644 (file)
@@ -319,7 +319,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
                goto end;
        }
 
-       acpi_os_free(buffer.pointer);
+       kfree(buffer.pointer);
 
        device->wakeup.flags.valid = 1;
        /* Power button, Lid switch always enable wakeup */
@@ -854,7 +854,7 @@ static void acpi_device_set_id(struct acpi_device *device,
                        printk(KERN_ERR "Memory allocation error\n");
        }
 
-       acpi_os_free(buffer.pointer);
+       kfree(buffer.pointer);
 }
 
 static int acpi_device_set_context(struct acpi_device *device, int type)
index c90bd2f..c3bb7fa 100644 (file)
@@ -86,7 +86,7 @@ acpi_system_read_dsdt(struct file *file,
 
        res = simple_read_from_buffer(buffer, count, ppos,
                                      dsdt.pointer, dsdt.length);
-       acpi_os_free(dsdt.pointer);
+       kfree(dsdt.pointer);
 
        return res;
 }
@@ -113,7 +113,7 @@ acpi_system_read_fadt(struct file *file,
 
        res = simple_read_from_buffer(buffer, count, ppos,
                                      fadt.pointer, fadt.length);
-       acpi_os_free(fadt.pointer);
+       kfree(fadt.pointer);
 
        return res;
 }
index c855f44..503c0b9 100644 (file)
@@ -162,7 +162,7 @@ struct acpi_thermal_flags {
 };
 
 struct acpi_thermal {
-       acpi_handle handle;
+       struct acpi_device * device;
        acpi_bus_id name;
        unsigned long temperature;
        unsigned long last_temperature;
@@ -229,7 +229,7 @@ static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
        tz->last_temperature = tz->temperature;
 
        status =
-           acpi_evaluate_integer(tz->handle, "_TMP", NULL, &tz->temperature);
+           acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tz->temperature);
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
@@ -248,7 +248,7 @@ static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
                return -EINVAL;
 
        status =
-           acpi_evaluate_integer(tz->handle, "_TZP", NULL,
+           acpi_evaluate_integer(tz->device->handle, "_TZP", NULL,
                                  &tz->polling_frequency);
        if (ACPI_FAILURE(status))
                return -ENODEV;
@@ -285,7 +285,7 @@ static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode)
        if (!tz)
                return -EINVAL;
 
-       status = acpi_get_handle(tz->handle, "_SCP", &handle);
+       status = acpi_get_handle(tz->device->handle, "_SCP", &handle);
        if (ACPI_FAILURE(status)) {
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n"));
                return -ENODEV;
@@ -316,7 +316,7 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
 
        /* Critical Shutdown (required) */
 
-       status = acpi_evaluate_integer(tz->handle, "_CRT", NULL,
+       status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL,
                                       &tz->trips.critical.temperature);
        if (ACPI_FAILURE(status)) {
                tz->trips.critical.flags.valid = 0;
@@ -332,7 +332,7 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
        /* Critical Sleep (optional) */
 
        status =
-           acpi_evaluate_integer(tz->handle, "_HOT", NULL,
+           acpi_evaluate_integer(tz->device->handle, "_HOT", NULL,
                                  &tz->trips.hot.temperature);
        if (ACPI_FAILURE(status)) {
                tz->trips.hot.flags.valid = 0;
@@ -346,7 +346,7 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
        /* Passive: Processors (optional) */
 
        status =
-           acpi_evaluate_integer(tz->handle, "_PSV", NULL,
+           acpi_evaluate_integer(tz->device->handle, "_PSV", NULL,
                                  &tz->trips.passive.temperature);
        if (ACPI_FAILURE(status)) {
                tz->trips.passive.flags.valid = 0;
@@ -355,25 +355,25 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
                tz->trips.passive.flags.valid = 1;
 
                status =
-                   acpi_evaluate_integer(tz->handle, "_TC1", NULL,
+                   acpi_evaluate_integer(tz->device->handle, "_TC1", NULL,
                                          &tz->trips.passive.tc1);
                if (ACPI_FAILURE(status))
                        tz->trips.passive.flags.valid = 0;
 
                status =
-                   acpi_evaluate_integer(tz->handle, "_TC2", NULL,
+                   acpi_evaluate_integer(tz->device->handle, "_TC2", NULL,
                                          &tz->trips.passive.tc2);
                if (ACPI_FAILURE(status))
                        tz->trips.passive.flags.valid = 0;
 
                status =
-                   acpi_evaluate_integer(tz->handle, "_TSP", NULL,
+                   acpi_evaluate_integer(tz->device->handle, "_TSP", NULL,
                                          &tz->trips.passive.tsp);
                if (ACPI_FAILURE(status))
                        tz->trips.passive.flags.valid = 0;
 
                status =
-                   acpi_evaluate_reference(tz->handle, "_PSL", NULL,
+                   acpi_evaluate_reference(tz->device->handle, "_PSL", NULL,
                                            &tz->trips.passive.devices);
                if (ACPI_FAILURE(status))
                        tz->trips.passive.flags.valid = 0;
@@ -393,14 +393,14 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
                char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
 
                status =
-                   acpi_evaluate_integer(tz->handle, name, NULL,
+                   acpi_evaluate_integer(tz->device->handle, name, NULL,
                                          &tz->trips.active[i].temperature);
                if (ACPI_FAILURE(status))
                        break;
 
                name[2] = 'L';
                status =
-                   acpi_evaluate_reference(tz->handle, name, NULL,
+                   acpi_evaluate_reference(tz->device->handle, name, NULL,
                                            &tz->trips.active[i].devices);
                if (ACPI_SUCCESS(status)) {
                        tz->trips.active[i].flags.valid = 1;
@@ -424,7 +424,7 @@ static int acpi_thermal_get_devices(struct acpi_thermal *tz)
                return -EINVAL;
 
        status =
-           acpi_evaluate_reference(tz->handle, "_TZD", NULL, &tz->devices);
+           acpi_evaluate_reference(tz->device->handle, "_TZD", NULL, &tz->devices);
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
@@ -453,10 +453,6 @@ static int acpi_thermal_call_usermode(char *path)
 
 static int acpi_thermal_critical(struct acpi_thermal *tz)
 {
-       int result = 0;
-       struct acpi_device *device = NULL;
-
-
        if (!tz || !tz->trips.critical.flags.valid)
                return -EINVAL;
 
@@ -466,14 +462,10 @@ static int acpi_thermal_critical(struct acpi_thermal *tz)
        } else if (tz->trips.critical.flags.enabled)
                tz->trips.critical.flags.enabled = 0;
 
-       result = acpi_bus_get_device(tz->handle, &device);
-       if (result)
-               return result;
-
        printk(KERN_EMERG
               "Critical temperature reached (%ld C), shutting down.\n",
               KELVIN_TO_CELSIUS(tz->temperature));
-       acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_CRITICAL,
+       acpi_bus_generate_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL,
                                tz->trips.critical.flags.enabled);
 
        acpi_thermal_call_usermode(ACPI_THERMAL_PATH_POWEROFF);
@@ -483,10 +475,6 @@ static int acpi_thermal_critical(struct acpi_thermal *tz)
 
 static int acpi_thermal_hot(struct acpi_thermal *tz)
 {
-       int result = 0;
-       struct acpi_device *device = NULL;
-
-
        if (!tz || !tz->trips.hot.flags.valid)
                return -EINVAL;
 
@@ -496,11 +484,7 @@ static int acpi_thermal_hot(struct acpi_thermal *tz)
        } else if (tz->trips.hot.flags.enabled)
                tz->trips.hot.flags.enabled = 0;
 
-       result = acpi_bus_get_device(tz->handle, &device);
-       if (result)
-               return result;
-
-       acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_HOT,
+       acpi_bus_generate_event(tz->device, ACPI_THERMAL_NOTIFY_HOT,
                                tz->trips.hot.flags.enabled);
 
        /* TBD: Call user-mode "sleep(S4)" function */
@@ -1193,8 +1177,7 @@ static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
        if (!tz)
                return;
 
-       if (acpi_bus_get_device(tz->handle, &device))
-               return;
+       device = tz->device;
 
        switch (event) {
        case ACPI_THERMAL_NOTIFY_TEMPERATURE:
@@ -1293,7 +1276,7 @@ static int acpi_thermal_add(struct acpi_device *device)
                return -ENOMEM;
        memset(tz, 0, sizeof(struct acpi_thermal));
 
-       tz->handle = device->handle;
+       tz->device = device;
        strcpy(tz->name, device->pnp.bus_id);
        strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
@@ -1311,7 +1294,7 @@ static int acpi_thermal_add(struct acpi_device *device)
 
        acpi_thermal_check(tz);
 
-       status = acpi_install_notify_handler(tz->handle,
+       status = acpi_install_notify_handler(device->handle,
                                             ACPI_DEVICE_NOTIFY,
                                             acpi_thermal_notify, tz);
        if (ACPI_FAILURE(status)) {
@@ -1352,7 +1335,7 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
        /* deferred task may reinsert timer */
        del_timer_sync(&(tz->timer));
 
-       status = acpi_remove_notify_handler(tz->handle,
+       status = acpi_remove_notify_handler(device->handle,
                                            ACPI_DEVICE_NOTIFY,
                                            acpi_thermal_notify);
 
index 7940fc1..5cff17d 100644 (file)
@@ -166,10 +166,10 @@ acpi_status acpi_ut_delete_caches(void)
 
        /* Free memory lists */
 
-       acpi_os_free(acpi_gbl_global_list);
+       ACPI_FREE(acpi_gbl_global_list);
        acpi_gbl_global_list = NULL;
 
-       acpi_os_free(acpi_gbl_ns_node_list);
+       ACPI_FREE(acpi_gbl_ns_node_list);
        acpi_gbl_ns_node_list = NULL;
 #endif
 
index 56270a3..1a1f810 100644 (file)
@@ -162,7 +162,7 @@ acpi_status acpi_os_delete_cache(struct acpi_memory_list * cache)
 
        /* Now we can delete the cache object */
 
-       acpi_os_free(cache);
+       ACPI_FREE(cache);
        return (AE_OK);
 }
 
index 1930e1a..f48227f 100644 (file)
@@ -332,7 +332,7 @@ acpi_evaluate_string(acpi_handle handle,
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%s]\n", *data));
 
-       acpi_os_free(buffer.pointer);
+       kfree(buffer.pointer);
 
        return AE_OK;
 }
@@ -418,7 +418,7 @@ acpi_evaluate_reference(acpi_handle handle,
                //kfree(list->handles);
        }
 
-       acpi_os_free(buffer.pointer);
+       kfree(buffer.pointer);
 
        return status;
 }
index 9feb633..56666a9 100644 (file)
@@ -117,7 +117,7 @@ struct acpi_video_enumerated_device {
 };
 
 struct acpi_video_bus {
-       acpi_handle handle;
+       struct acpi_device *device;
        u8 dos_setting;
        struct acpi_video_enumerated_device *attached_array;
        u8 attached_count;
@@ -155,7 +155,6 @@ struct acpi_video_device_brightness {
 };
 
 struct acpi_video_device {
-       acpi_handle handle;
        unsigned long device_id;
        struct acpi_video_device_flags flags;
        struct acpi_video_device_cap cap;
@@ -272,7 +271,8 @@ static int
 acpi_video_device_query(struct acpi_video_device *device, unsigned long *state)
 {
        int status;
-       status = acpi_evaluate_integer(device->handle, "_DGS", NULL, state);
+
+       status = acpi_evaluate_integer(device->dev->handle, "_DGS", NULL, state);
 
        return status;
 }
@@ -283,8 +283,7 @@ acpi_video_device_get_state(struct acpi_video_device *device,
 {
        int status;
 
-
-       status = acpi_evaluate_integer(device->handle, "_DCS", NULL, state);
+       status = acpi_evaluate_integer(device->dev->handle, "_DCS", NULL, state);
 
        return status;
 }
@@ -299,7 +298,7 @@ acpi_video_device_set_state(struct acpi_video_device *device, int state)
 
 
        arg0.integer.value = state;
-       status = acpi_evaluate_integer(device->handle, "_DSS", &args, &ret);
+       status = acpi_evaluate_integer(device->dev->handle, "_DSS", &args, &ret);
 
        return status;
 }
@@ -315,7 +314,7 @@ acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
 
        *levels = NULL;
 
-       status = acpi_evaluate_object(device->handle, "_BCL", NULL, &buffer);
+       status = acpi_evaluate_object(device->dev->handle, "_BCL", NULL, &buffer);
        if (!ACPI_SUCCESS(status))
                return status;
        obj = (union acpi_object *)buffer.pointer;
@@ -344,7 +343,7 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
 
 
        arg0.integer.value = level;
-       status = acpi_evaluate_object(device->handle, "_BCM", &args, NULL);
+       status = acpi_evaluate_object(device->dev->handle, "_BCM", &args, NULL);
 
        printk(KERN_DEBUG "set_level status: %x\n", status);
        return status;
@@ -356,7 +355,7 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
 {
        int status;
 
-       status = acpi_evaluate_integer(device->handle, "_BQC", NULL, level);
+       status = acpi_evaluate_integer(device->dev->handle, "_BQC", NULL, level);
 
        return status;
 }
@@ -383,7 +382,7 @@ acpi_video_device_EDID(struct acpi_video_device *device,
        else
                return -EINVAL;
 
-       status = acpi_evaluate_object(device->handle, "_DDC", &args, &buffer);
+       status = acpi_evaluate_object(device->dev->handle, "_DDC", &args, &buffer);
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
@@ -413,7 +412,7 @@ acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option)
 
        arg0.integer.value = option;
 
-       status = acpi_evaluate_integer(video->handle, "_SPD", &args, &tmp);
+       status = acpi_evaluate_integer(video->device->handle, "_SPD", &args, &tmp);
        if (ACPI_SUCCESS(status))
                status = tmp ? (-EINVAL) : (AE_OK);
 
@@ -425,8 +424,7 @@ acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id)
 {
        int status;
 
-
-       status = acpi_evaluate_integer(video->handle, "_GPD", NULL, id);
+       status = acpi_evaluate_integer(video->device->handle, "_GPD", NULL, id);
 
        return status;
 }
@@ -437,7 +435,7 @@ acpi_video_bus_POST_options(struct acpi_video_bus *video,
 {
        int status;
 
-       status = acpi_evaluate_integer(video->handle, "_VPO", NULL, options);
+       status = acpi_evaluate_integer(video->device->handle, "_VPO", NULL, options);
        *options &= 3;
 
        return status;
@@ -478,7 +476,7 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
        }
        arg0.integer.value = (lcd_flag << 2) | bios_flag;
        video->dos_setting = arg0.integer.value;
-       acpi_evaluate_object(video->handle, "_DOS", &args, NULL);
+       acpi_evaluate_object(video->device->handle, "_DOS", &args, NULL);
 
       Failed:
        return status;
@@ -506,25 +504,25 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 
        memset(&device->cap, 0, 4);
 
-       if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ADR", &h_dummy1))) {
+       if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) {
                device->cap._ADR = 1;
        }
-       if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_BCL", &h_dummy1))) {
+       if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCL", &h_dummy1))) {
                device->cap._BCL = 1;
        }
-       if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_BCM", &h_dummy1))) {
+       if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCM", &h_dummy1))) {
                device->cap._BCM = 1;
        }
-       if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DDC", &h_dummy1))) {
+       if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) {
                device->cap._DDC = 1;
        }
-       if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DCS", &h_dummy1))) {
+       if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DCS", &h_dummy1))) {
                device->cap._DCS = 1;
        }
-       if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DGS", &h_dummy1))) {
+       if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DGS", &h_dummy1))) {
                device->cap._DGS = 1;
        }
-       if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DSS", &h_dummy1))) {
+       if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DSS", &h_dummy1))) {
                device->cap._DSS = 1;
        }
 
@@ -588,22 +586,22 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
        acpi_handle h_dummy1;
 
        memset(&video->cap, 0, 4);
-       if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_DOS", &h_dummy1))) {
+       if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) {
                video->cap._DOS = 1;
        }
-       if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_DOD", &h_dummy1))) {
+       if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOD", &h_dummy1))) {
                video->cap._DOD = 1;
        }
-       if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_ROM", &h_dummy1))) {
+       if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_ROM", &h_dummy1))) {
                video->cap._ROM = 1;
        }
-       if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_GPD", &h_dummy1))) {
+       if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_GPD", &h_dummy1))) {
                video->cap._GPD = 1;
        }
-       if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_SPD", &h_dummy1))) {
+       if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_SPD", &h_dummy1))) {
                video->cap._SPD = 1;
        }
-       if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_VPO", &h_dummy1))) {
+       if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_VPO", &h_dummy1))) {
                video->cap._VPO = 1;
        }
 }
@@ -1271,7 +1269,6 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
 
                memset(data, 0, sizeof(struct acpi_video_device));
 
-               data->handle = device->handle;
                strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME);
                strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
                acpi_driver_data(device) = data;
@@ -1298,7 +1295,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
                acpi_video_device_bind(video, data);
                acpi_video_device_find_cap(data);
 
-               status = acpi_install_notify_handler(data->handle,
+               status = acpi_install_notify_handler(device->handle,
                                                     ACPI_DEVICE_NOTIFY,
                                                     acpi_video_device_notify,
                                                     data);
@@ -1400,8 +1397,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
        union acpi_object *dod = NULL;
        union acpi_object *obj;
 
-
-       status = acpi_evaluate_object(video->handle, "_DOD", NULL, &buffer);
+       status = acpi_evaluate_object(video->device->handle, "_DOD", NULL, &buffer);
        if (!ACPI_SUCCESS(status)) {
                ACPI_EXCEPTION((AE_INFO, status, "Evaluating _DOD"));
                return status;
@@ -1450,7 +1446,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
        video->attached_array = active_device_list;
        video->attached_count = count;
       out:
-       acpi_os_free(buffer.pointer);
+       kfree(buffer.pointer);
        return status;
 }
 
@@ -1569,7 +1565,7 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
        up(&video->sem);
        acpi_video_device_remove_fs(device->dev);
 
-       status = acpi_remove_notify_handler(device->handle,
+       status = acpi_remove_notify_handler(device->dev->handle,
                                            ACPI_DEVICE_NOTIFY,
                                            acpi_video_device_notify);
 
@@ -1624,8 +1620,7 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
        if (!video)
                return;
 
-       if (acpi_bus_get_device(handle, &device))
-               return;
+       device = video->device;
 
        switch (event) {
        case ACPI_VIDEO_NOTIFY_SWITCH:  /* User request that a switch occur,
@@ -1668,8 +1663,7 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
        if (!video_device)
                return;
 
-       if (acpi_bus_get_device(handle, &device))
-               return;
+       device = video_device->dev;
 
        switch (event) {
        case ACPI_VIDEO_NOTIFY_SWITCH:  /* change in status (cycle output device) */
@@ -1707,7 +1701,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
                return -ENOMEM;
        memset(video, 0, sizeof(struct acpi_video_bus));
 
-       video->handle = device->handle;
+       video->device = device;
        strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
        strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
        acpi_driver_data(device) = video;
@@ -1727,7 +1721,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
        acpi_video_bus_get_devices(video, device);
        acpi_video_bus_start_devices(video);
 
-       status = acpi_install_notify_handler(video->handle,
+       status = acpi_install_notify_handler(device->handle,
                                             ACPI_DEVICE_NOTIFY,
                                             acpi_video_bus_notify, video);
        if (ACPI_FAILURE(status)) {
@@ -1767,7 +1761,7 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type)
 
        acpi_video_bus_stop_devices(video);
 
-       status = acpi_remove_notify_handler(video->handle,
+       status = acpi_remove_notify_handler(video->device->handle,
                                            ACPI_DEVICE_NOTIFY,
                                            acpi_video_bus_notify);
 
index 4bb3806..f1ac610 100644 (file)
 
 #define ACPI_ALLOCATE(a)            acpi_ut_allocate((acpi_size)(a),_COMPONENT,_acpi_module_name,__LINE__)
 #define ACPI_ALLOCATE_ZEROED(a)     acpi_ut_allocate_zeroed((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__)
-#define ACPI_FREE(a)                acpi_os_free(a)
+#define ACPI_FREE(a)                kfree(a)
 #define ACPI_MEM_TRACKING(a)
 
 #else
index 89bc4a1..0cd63bc 100644 (file)
@@ -143,8 +143,6 @@ void acpi_os_release_mutex(acpi_mutex handle);
  */
 void *acpi_os_allocate(acpi_size size);
 
-void acpi_os_free(void *memory);
-
 acpi_status
 acpi_os_map_memory(acpi_physical_address physical_address,
                   acpi_size size, void __iomem ** logical_address);