diff --git a/arch/ia64/kernel/acpi-ext.c b/arch/ia64/kernel/acpi-ext.c
index 2a1ef742e2239a3ea9ad7054c09a6be33c203fc9..b7515bc808a8d815708c45124661e94cc4d63286 100644
--- a/arch/ia64/kernel/acpi-ext.c
+++ b/arch/ia64/kernel/acpi-ext.c
@@ -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;
 }
 
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index ccdef199d91553078fd5ceb5d65abc9042eb1f57..99761b81db4496a78c0ea1eb0cb1076c438c8c3c 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -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
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index bc2652d72fdc79dd97d1b2cd531e272e899caee4..fef7bab122447c5d18d437716eee3a61ce1f233e 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -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
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index f0a68ecf1e57d4eb60b45a69909ffdab2757d17d..bce7ca27b429e2874eb4e78a229dd65871070d6c 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -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
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 36ca365bcead4bca3baae6610ef83eb5dcd1aeec..24ccf81d135f9d1ccf440b426277b7d7a36ec71c 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -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;
 }
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index cd57372a672942cffc5b7cfb74731ac3682494c2..81e970adeab3b3cc6d5e47d32e69381693240943 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -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;
 }
 
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index 055cfd5c8766c3f217ee943e282557e7c3e7effb..e9ee4c52a5f6266a7edc5df20d80aad2647338ea 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -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
@@ -26,11 +26,8 @@
  *  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>
@@ -42,12 +39,14 @@
 #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"
@@ -67,9 +66,10 @@
 /*
  * 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;
 }
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 00b0728efe820a28ece8497b4fb3e819c566b5d8..24bf4dca88cc75936e275f2585a375eeec8b4722 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -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;
 }
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 02594639c4d96e7a0f21a13276d93ed619317021..fd1ba05eab688fb409d259d97848b88cec6c325c 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -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
index 0000000000000000000000000000000000000000..574a75a166c54730228e7bcef28f2db097cede3a
--- /dev/null
+++ b/drivers/acpi/cm_sbs.c
@@ -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);
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 7f7e41d40a3b77da042d6d414f3393ad13977968..871aa520ece78aaa50d94bbb90a29c3c9f4ef83b 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -236,7 +236,7 @@ container_walk_namespace_cb(acpi_handle handle,
 	}
 
       end:
-	acpi_os_free(buffer.pointer);
+	kfree(buffer.pointer);
 
 	return AE_OK;
 }
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 38acc69b21bcc5f929f5a042bddf4ef54b8810dc..daed2460924d8235552df6fc00882fa9c240af2a 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -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;
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 8daef57b994c4b264db47d4a050243812f5a0b8b..10f160dc75b1cb5370063bcf96a6c738745d028c 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -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
index 0000000000000000000000000000000000000000..84239d51dc0ca472bf4e01433dcc7498e037753b
--- /dev/null
+++ b/drivers/acpi/i2c_ec.c
@@ -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
index 0000000000000000000000000000000000000000..7c53fb732d610da5d5315c327a89f8d138c02a5f
--- /dev/null
+++ b/drivers/acpi/i2c_ec.h
@@ -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);
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
index 6d9bd45af30a6c95b997978d6d6d02e68b0fcc3c..dca6799ac678a978df124150cee591c832f5c5c4 100644
--- a/drivers/acpi/namespace/nsxfeval.c
+++ b/drivers/acpi/namespace/nsxfeval.c
@@ -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;
 	}
 
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 4d622981f61ae4c2707d1123c4217f3fbff89b51..e5e448edca41e14e5c2f9ce3265a8ffb1960c23f 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -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);
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 5a468e2779aecf5c167e7ee4c8e433a965f43fb3..eedb05c6dc7b6d14e901f0c68abb021c4426b097 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -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;
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 1badce27a83fcc243529aa0a7878e9b3b0e22489..8197c0e40769f68785559c58ce0002058ed6aa25 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -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)
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 8f10442119f01d84772946d5de06cb252a3e7e7f..0984a1ee24edceecbd9593b8da72b139f1fc4201 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -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;
 		}
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 224f729f700e2e6b75f307de2b02c1af76ba70f2..5d3447f4582ce797b2439b5a347e1ede7041066c 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -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;
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index e439eb77d283e98f011de2707dfbef70f75545a4..8e9c26aae8fed13b69875c211612c7d2cb01b820 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -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;
 }
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 14a00e5a8f6a14f002413d16369c46c99571257d..7ba5e49ab302c523848930773d474c351fed30a1 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -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
index 0000000000000000000000000000000000000000..db7b350a50356417f49bf660a1a9e1e74ccbfaa7
--- /dev/null
+++ b/drivers/acpi/sbs.c
@@ -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);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 861ac378ce42c34eeddb2125e52682c9960bf0f0..5fcb50c7b77802d135cbbe1368f96e8fabd6877e 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -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)
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index c90bd2f70b3fa0b9df9297ec5293f21533fd2351..c3bb7faad75ee59e613c2d93bf2280051c64b344 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -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;
 }
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index c855f4446b5fc45263166051829166e7f1b1a0c4..503c0b99db122814e9c30767e5358ab226d9cdac 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -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);
 
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c
index 7940fc1bd69ef88a1900ea903647f26531c49264..5cff17dc78b331855b143ebffa7d95b749dcab68 100644
--- a/drivers/acpi/utilities/utalloc.c
+++ b/drivers/acpi/utilities/utalloc.c
@@ -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
 
diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c
index 56270a30718ae8b968430a527a20efc3b4087676..1a1f8109159cec3d9d988d1513a75cdb1638ecf4 100644
--- a/drivers/acpi/utilities/utcache.c
+++ b/drivers/acpi/utilities/utcache.c
@@ -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);
 }
 
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 1930e1a75b22589838d46b8cb66779f131d0a069..f48227f4c8c9183f03e224852af6fa2f1c14c129 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -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;
 }
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 9feb633087a9b5f0e56cbd089c80f41a7f2e6095..56666a9824760bc0fbf569aba85518a38ce995cb 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -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);
 
diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h
index 4bb38068f40dc0ebc1238d6e2c093d7cd7f1f3fb..f1ac6109556e8d69fa53d3157bfbff877dbafb37 100644
--- a/include/acpi/acmacros.h
+++ b/include/acpi/acmacros.h
@@ -726,7 +726,7 @@
 
 #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
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 89bc4a16c2e89d8741669e93e4ee185b231f262c..0cd63bce0ae423d1905d37448879df7c802d79ac 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -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);