GIT 309b0f125a22ee34c8f6962677255f7bf6af5e3d git+ssh://master.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git#test commit 635227ee89929a6e2920fc8aa1cd48f7225d3d93 Author: Len Brown Date: Sat Jul 1 16:48:23 2006 -0400 ACPI: remove function tracing macros from drivers/acpi/*.c a few invocations appeared due to the SBS and other patches. Signed-off-by: Len Brown commit 3f86b83243d59bb50caf5938d284d22e10d082a4 Author: Rich Townsend Date: Sat Jul 1 11:36:54 2006 -0400 ACPI: add support for Smart Battery Most batteries today are ACPI "Control Method" batteries, but some models ship with the older "Smart Battery" that requires this code. Rich Townsend and Bruno Ducrot were the original authors. Vladimir Lebedev updated to run on latest kernel. http://bugzilla.kernel.org/show_bug.cgi?id=3734 Signed-off-by: Len Brown commit 9becf5b91ec7b600a3cfea12724165aaaf4d4527 Author: Karol Kozimor Date: Fri Jun 30 19:15:00 2006 -0400 ACPI: asus_acpi: correct M6N/M6R display nodes This patch switches back the display nodes for M6R and M6N -- this happened a while ago when a patch was misapplied (only the in-tree version was affected). Signed-off-by: Karol Kozimor Signed-off-by: Len Brown commit 9fdae727645215d4dbb88912b9a176ef87911a05 Author: Vladimir Lebedev Date: Tue Jun 27 04:49:00 2006 -0400 ACPI: handle battery notify event on broken BIOS http://bugzilla.kernel.org/show_bug.cgi?id=3241 Signed-off-by: Vladimir Lebedev Signed-off-by: Len Brown commit 03d782524e2d0511317769521c8d5daadbab8482 Author: Christian Lupien Date: Thu Aug 19 01:26:00 2004 -0400 ACPI: handle AC notify event on broken BIOS http://bugzilla.kernel.org/show_bug.cgi?id=3241 updated by Vladimir Lebedev Signed-off-by: Len Brown commit 2df8386cec47520b76822cb39d96709f5d353cf8 Author: Karol Kozimor Date: Fri Jun 30 19:15:00 2006 -0400 ACPI: asus_acpi: add S1N WLED control This patch switches back the display nodes for M6R and M6N -- this happened a while ago when a patch was misapplied (only the in-tree version was affected). Signed-off-by: Karol Kozimor Signed-off-by: Len Brown commit 96d1142084281ae4601fab02be061e1267e431a3 Author: Karol Kozimor Date: Fri Jun 30 19:13:00 2006 -0400 ACPI: asus_acpi: add S1N WLED control This small patch adds back WLED control for S1N models, this was accidentally removed a while ago. Signed-off-by: Karol Kozimor Signed-off-by: Len Brown commit ffab0d9507dc527ff6d704ec5e7e7ccfee119fb1 Author: Karol Kozimor Date: Fri Jun 30 19:11:00 2006 -0400 ACPI: asus_acpi: rework model detection This patch reworks laptop model detection. This addresses the Samsung P30 issue, where the INIT method would return no object, but the implicit return in the AML interpreter would confuse the driver. It also accounts for a newer batch of Asus models whose INIT returns ACPI_TYPE_BUFFER instead of STRING. The handling is now much leaner, if we get a buffer or a string, we check against known values, in every other case we use a different path (currently DSDT signatures). The bulk of this patch is separating the string matching from asus_hotk_get_info() into a separate function. This patch properly fixes http://bugme.osdl.org/show_bug.cgi?id=5067 and http://bugme.osdl.org/show_bug.cgi?id=5092 and makes the driver fully functional again with acpi=strict on all machines. Signed-off-by: Karol Kozimor Signed-off-by: Len Brown commit ebccb84810729f0e86a83a65681ba2de45ff84d8 Author: Karol Kozimor Date: Fri Jun 30 19:08:00 2006 -0400 ACPI: asus_acpi: support L5D This patch adds support for Asus L5D and thus fixes http://bugme.osdl.org/show_bug.cgi?id=4695 Signed-off-by: Karol Kozimor Signed-off-by: Len Brown commit e067aaa7612c273d4bfd70d1bd8d80313a57685c Author: Karol Kozimor Date: Fri Jun 30 19:07:00 2006 -0400 ACPI: asus_acpi: handle internal Bluetooth / support W5A This patch creates a new file named "bluetooth" under /proc/acpi/asus/. This file controls both the internal Bluetooth adapter's presence on the USB bus and the associated LED. echo 1 > /proc/acpi/asus/bluetooth to enable, 0 to disable. Additionally, the patch add support for Asus W5A, the first model that uses this feature. Patch originally by Fernando A. P. Gomes. Signed-off-by: Karol Kozimor Signed-off-by: Len Brown commit f78c589d108f4b06a012817536c9ced37f473eae Author: Karol Kozimor Date: Fri Jun 30 19:06:00 2006 -0400 ACPI: asus_acpi: support A4G This patch adds support for Asus A4G. Originally by Giuseppe Rota. Signed-off-by: Karol Kozimor Signed-off-by: Len Brown commit c067a7899790ed4c03b00ed186c6e3b6a3964379 Author: Karol Kozimor Date: Fri Jun 30 19:05:00 2006 -0400 ACPI: asus_acpi: support W3400N This patch adds support for Asus W3400N. Signed-off-by: Karol Kozimor Signed-off-by: Len Brown commit 42cb891295795ed9b3048c8922d93f7a71f63968 Author: Karol Kozimor Date: Fri Jun 30 19:04:00 2006 -0400 ACPI: asus_acpi: LED display support This patch adds handling for front LED displays found on W1N and the like. Additionally, W1N is given its own model_data instance. Patch originally by Éric Burghard. Signed-off-by: Karol Kozimor Signed-off-by: Len Brown commit ed2cb07b2bb04f14793cdeecb0b384374e979525 Author: Karol Kozimor Date: Fri Jun 30 19:03:00 2006 -0400 ACPI: asus_acpi: support A3G This patch adds support for Asus A3G. Signed-off-by: Karol Kozimor Signed-off-by: Len Brown commit a170a5317c0298538deb170028376ec1631acc2f Author: Karol Kozimor Date: Fri Jun 30 19:03:00 2006 -0400 ACPI: asus_acpi: misc cleanups This patch updates the version string, copyright notices and does whitespace cleanup (it looks weird, blame Lindent). Signed-off-by: Karol Kozimor Signed-off-by: Len Brown commit 02438d8771ae6a4b215938959827692026380bf9 Author: Len Brown Date: Fri Jun 30 03:19:10 2006 -0400 ACPI: delete acpi_os_free(), use kfree() directly Signed-off-by: Len Brown commit d07a8577f695c807977af003b6e75f996e01a15f Author: Patrick Mochel Date: Fri May 19 16:54:52 2006 -0400 ACPI: video: Remove unneeded acpi_handle from driver. Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 8a4444bf5a3fd890441e6cbd5022a3c24edbe69a Author: Patrick Mochel Date: Fri May 19 16:54:51 2006 -0400 ACPI: thermal: Remove unneeded acpi_handle from driver. Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 14747204055d4b8fb2f8517beca91985ac617c17 Author: Patrick Mochel Date: Fri May 19 16:54:51 2006 -0400 ACPI: power: Remove unneeded acpi_handle from driver. Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 432bfaba7d4e70483fc5af164e020066f4921bff Author: Patrick Mochel Date: Fri May 19 16:54:51 2006 -0400 ACPI: pci_root: Remove unneeded acpi_handle from driver. Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit e0e4e117d4c898b0df749d5b88c86955151abf53 Author: Patrick Mochel Date: Fri May 19 16:54:50 2006 -0400 ACPI: pci_link: Remove unneeded acpi_handle from driver. Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 579c896cc91434e4feb938f780eba580c93fa0da Author: Patrick Mochel Date: Fri May 19 16:54:50 2006 -0400 ACPI: fan: Remove unneeded acpi_handle from driver. Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 6c689537726ec665246d2f60c48475be2efac2d0 Author: Patrick Mochel Date: Fri May 19 16:54:50 2006 -0400 ACPI: button: Remove unneeded acpi_handle from driver. Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 39cb61e26771891f843cb433ee6febd9159bce73 Author: Patrick Mochel Date: Fri May 19 16:54:49 2006 -0400 ACPI: battery: Remove unneeded acpi_handle from driver. Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 9453ece92688fedd7755d2ea54b2efe88822a91b Author: Patrick Mochel Date: Fri May 19 16:54:49 2006 -0400 ACPI: acpi_memhotplug: Remove unneeded acpi_handle from driver. Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 1b5b8b81bddd1c5dcf690f43422e20b0e964c349 Author: Patrick Mochel Date: Fri May 19 16:54:49 2006 -0400 ACPI: ac: Remove unneeded acpi_handle from driver. Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 901302688cb85b49a9551ec1f6aa86fb081ae49e Author: Patrick Mochel Date: Fri May 19 16:54:48 2006 -0400 ACPI: video: Use acpi_device's handle instead of driver's Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 38ba7c9ed2e1a222103332031f76c28b726573f5 Author: Patrick Mochel Date: Fri May 19 16:54:48 2006 -0400 ACPI: thermal: Use acpi_device's handle instead of driver's Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 5fbc19efdbedf9c9125774f66f80d6a6ccce4566 Author: Patrick Mochel Date: Fri May 19 16:54:43 2006 -0400 ACPI: power: Use acpi_device's handle instead of driver's Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 2d1e0a02f16f84c2358843d91d6ca0131a0587ce Author: Patrick Mochel Date: Fri May 19 16:54:43 2006 -0400 ACPI: pci_root: Use acpi_device's handle instead of driver's Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 67a7136573b24a0d1f85a4aab131558a02910d25 Author: Patrick Mochel Date: Fri May 19 16:54:42 2006 -0400 ACPI: pci_link: Use acpi_device's handle instead of driver's Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit dc8c2b2744f8563aa5feb07488e4cc207a70ac70 Author: Patrick Mochel Date: Fri May 19 16:54:42 2006 -0400 ACPI: fan: Use acpi_device's handle instead of driver's Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 27b1d3e85b1dfd9037d3fbb98b2e2aacca01da39 Author: Patrick Mochel Date: Fri May 19 16:54:42 2006 -0400 ACPI: button: Use acpi_device's handle instead of driver's Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 3b073ec3667ee63e35b66752a30eeedef1e1e772 Author: Patrick Mochel Date: Fri May 19 16:54:41 2006 -0400 ACPI: battery: Use acpi_device's handle instead of driver's Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit b863278523f7adbacb9e34133f4b6397cdab9977 Author: Patrick Mochel Date: Fri May 19 16:54:41 2006 -0400 ACPI: acpi_memhotplug: Use acpi_device's handle instead of driver's Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit a6ba5ebef91a59fabd45962e576c02468dbcd33f Author: Patrick Mochel Date: Fri May 19 16:54:41 2006 -0400 ACPI: ac: Use acpi_device's handle instead of driver's Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit e6afa0de1476290a876dfd1237a97cce7735581c Author: Patrick Mochel Date: Fri May 19 16:54:40 2006 -0400 ACPI: video: add struct acpi_device to struct acpi_video_bus. - Use it instead of acpi_bus_get_device() in acpi_video_bus_notify() and use the one from struct acpi_video_device in acpi_video_device_notify(). Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 415985728895ba3127116bc4f999caf94420ed85 Author: Patrick Mochel Date: Fri May 19 16:54:40 2006 -0400 ACPI: power: add struct acpi_device to struct acpi_power_resource - Use it instead of acpi_bus_get_device() where we can.. Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 8348e1b19a06b1932f65e84e1d59be29e1626c2b Author: Patrick Mochel Date: Fri May 19 16:54:40 2006 -0400 ACPI: thermal: add struct acpi_device to struct acpi_thermal. - Use it instead of acpi_bus_get_device() where we can.. Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 32917e5b589d813c9dc0f2d140d8c52898ddb6fb Author: Patrick Mochel Date: Fri May 19 16:54:39 2006 -0400 ACPI: pci root: add struct acpi_device to struct acpi_pci_root. Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 74b142e0fe039fcde42030c064763577e11ca004 Author: Patrick Mochel Date: Fri May 19 16:54:39 2006 -0400 ACPI: fan: add struct acpi_device to struct acpi_fan. Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 145def84a177c01cf3cc6cfbb67a029f39a8ac35 Author: Patrick Mochel Date: Fri May 19 16:54:39 2006 -0400 ACPI: battery: add struct acpi_device to struct acpi_battery. - Use it instead of acpi_bus_get_device().. Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit 3b74863df5d46f794052b5ee010cfc8fd66819dd Author: Patrick Mochel Date: Fri May 19 16:54:38 2006 -0400 ACPI: acpi_memhotplug: add struct acpi_device to struct acpi_memory_device. Signed-off-by: Patrick Mochel Signed-off-by: Len Brown commit af96179a8298832cc58be212d0e4988d8a1e11bf Author: Patrick Mochel Date: Fri May 19 16:54:32 2006 -0400 ACPI: ac: Add struct acpi_device to struct acpi_ac. Signed-off-by: Patrick Mochel Signed-off-by: Len Brown --- diff --git a/arch/ia64/kernel/acpi-ext.c b/arch/ia64/kernel/acpi-ext.c index 2a1ef74..b7515bc 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_h 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 ccdef19..99761b8 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -856,7 +856,7 @@ int acpi_map_lsapic(acpi_handle handle, 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, 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 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 bc2652d..fef7bab 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 f0a68ec..bce7ca2 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 36ca365..24ccf81 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 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 h 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_devic 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_devic 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_de 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_de 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 cd57372..81e970a 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 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(stru /* 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, ¤t_status))) return -ENODEV; /* @@ -222,7 +222,7 @@ static int acpi_memory_enable_device(str 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( 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( } /* 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, ¤t_status); if (ACPI_FAILURE(status)) return -ENODEV; @@ -398,7 +398,7 @@ static int acpi_memory_device_add(struct 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 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 (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 055cfd5..e9ee4c5 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 @@ -42,12 +39,14 @@ #include #include #include -#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 @@ #define BR_DOWN 0x20 /* * 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 @@ #define xxN_PREFIX "\\_SB.PCI0.SBRG.EC0. 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 ? - * */ { @@ -184,6 +182,16 @@ static struct model_data model_conf[END_ .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", .mt_lcd_switch = "\\Q0D", @@ -302,7 +310,8 @@ static struct model_data model_conf[END_ .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_ .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", - .display_get = "\\SSTE"}, + .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"}, { .name = "P30", @@ -345,6 +354,28 @@ static struct model_data model_conf[END_ .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", /* WLED present, but not controlled by ACPI */ @@ -563,6 +594,36 @@ proc_write_mled(struct file *file, const } /* + * 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 */ static int @@ -581,6 +642,25 @@ proc_write_wled(struct file *file, const } /* + * 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 */ static int @@ -876,6 +956,11 @@ static int asus_hotk_add_fs(struct acpi_ 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_ 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 ac 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 @@ -951,6 +1045,65 @@ static void asus_hotk_notify(acpi_handle } /* + * 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_dev /* 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_dev 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 00b0728..24bf4dc 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_batter /* 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_batter } 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_batt /* 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_batt } 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_batte 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 acp 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 acp /* 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_han 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_ 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_ 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 ac 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 ac 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(voi 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 0259463..fd1ba05 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -82,7 +82,6 @@ static struct acpi_driver acpi_button_dr }; 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(st 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_fi 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_d 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_d 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 acp 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 0000000..574a75a --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 7f7e41d..871aa52 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -236,7 +236,7 @@ container_walk_namespace_cb(acpi_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 38acc69..daed246 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -64,7 +64,7 @@ static struct acpi_driver acpi_fan_drive }; struct acpi_fan { - acpi_handle handle; + struct acpi_device * device; }; /* -------------------------------------------------------------------------- @@ -80,7 +80,7 @@ static int acpi_fan_read_state(struct se 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, 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_devi 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 8daef57..10f160d 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -152,7 +152,7 @@ static int get_root_bridge_busnr(acpi_ha bbn = bus; } exit: - acpi_os_free(buffer.pointer); + kfree(buffer.pointer); return (int)bbn; } @@ -192,7 +192,7 @@ find_pci_rootbridge(acpi_handle handle, 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, u 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 @@ #if ACPI_GLUE_DEBUG 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 0000000..84239d5 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 0000000..7c53fb7 --- /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 6d9bd45..dca6799 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -133,7 +133,7 @@ acpi_evaluate_object_typed(acpi_handle h /* 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 4d62298..e5e448e 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 5dd2ed1..d4bd314 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(acp 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 1badce2..8197c0e 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(st 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(str 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(str * 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 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 @@ #endif 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 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 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 8f10442..0984a1e 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -58,7 +58,7 @@ static struct acpi_driver acpi_pci_root_ 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 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 a 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 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 * ------- * 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 * --- * 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 "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 * ----------------- * 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 ac 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 224f729..5d3447f 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -70,7 +70,7 @@ static struct acpi_driver acpi_power_dri }; 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 a 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 han 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 han 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_ha 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_ha 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_de 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 e439eb7..8e9c26a 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -768,7 +768,7 @@ static int acpi_processor_get_power_info 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 14a00e5..7ba5e49 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -216,7 +216,7 @@ static int acpi_processor_get_performanc 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_performanc } end: - acpi_os_free(buffer.pointer); + kfree(buffer.pointer); return result; } @@ -592,7 +592,7 @@ static int acpi_processor_get_psd(struct } 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 0000000..db7b350 --- /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 + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 861ac37..5fcb50c 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -319,7 +319,7 @@ static int acpi_bus_get_wakeup_device_fl 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 ac 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 c90bd2f..c3bb7fa 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 c855f44..503c0b9 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( 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_freq 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 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( /* 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( /* 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( /* 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( 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( 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(stru 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(ch 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 } 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 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_ } 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_han 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_ 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_ 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 ac /* 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 7940fc1..5cff17d 100644 --- a/drivers/acpi/utilities/utalloc.c +++ b/drivers/acpi/utilities/utalloc.c @@ -166,10 +166,10 @@ #ifdef ACPI_DBG_TRACK_ALLOCATIONS /* 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 56270a3..1a1f810 100644 --- a/drivers/acpi/utilities/utcache.c +++ b/drivers/acpi/utilities/utcache.c @@ -162,7 +162,7 @@ acpi_status acpi_os_delete_cache(struct /* 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 1930e1a..f48227f 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 hand //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 9feb633..56666a9 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_ { 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_ 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(struc *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 a 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( { 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 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_vide 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_vide { 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_ { 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 } 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(s 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(stru 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 acp 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 acp 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(s 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(s 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 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_h 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(acp 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 acp 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 acp 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_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 4bb3806..f1ac610 100644 --- a/include/acpi/acmacros.h +++ b/include/acpi/acmacros.h @@ -726,7 +726,7 @@ #ifndef ACPI_DBG_TRACK_ALLOCATIONS #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 89bc4a1..0cd63bc 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -143,8 +143,6 @@ #define acpi_os_release_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);