diff options
| author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-03-31 16:06:50 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-03-31 16:06:50 -0800 |
| commit | f6ea76c0dc98f2a9219ee5327a2d3a00dfb7e89b (patch) | |
| tree | c7c6360b40213958ee55fff48cc16c506357ce5d /drivers | |
| parent | 54356933c64d5f26e15c040d6bb81e8d2d616555 (diff) | |
| parent | 63b61eadc2c4fd8ef6932e3a31370927b2e4951f (diff) | |
Merge bk://kernel.bkbits.net/davem/net-2.6
into ppc970.osdl.org:/home/torvalds/v2.6/linux
Diffstat (limited to 'drivers')
71 files changed, 2286 insertions, 712 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 894128bffc..0400a52d50 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -331,6 +331,26 @@ config ACPI_CONTAINER This is the ACPI generic container driver which supports ACPI0004, PNP0A05 and PNP0A06 devices +config ACPI_HOTPLUG_MEMORY + tristate "Memory Hotplug" + depends on ACPI + depends on MEMORY_HOTPLUG + default n + help + This driver adds supports for ACPI Memory Hotplug. This driver + provides support for fielding notifications on ACPI memory + devices (PNP0C80) which represent memory ranges that may be + onlined or offlined during runtime. + + Enabling this driver assumes that your platform hardware + and firmware have support for hot-plugging physical memory. If + your system does not support physically adding or ripping out + memory DIMMs at some platfrom defined granularity (individually + or as a bank) at runtime, then you need not enable this driver. + + If one selects "m," this driver can be loaded using the following + command: + $>modprobe acpi_memhotplug endif # ACPI endmenu diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 1ae0d89c2d..65c92e2056 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -55,3 +55,4 @@ obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o obj-$(CONFIG_ACPI_IBM) += ibm_acpi.o obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o obj-$(CONFIG_ACPI_BUS) += scan.o motherboard.o +obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index e0f498c7b3..23ab761dd7 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -51,8 +51,8 @@ MODULE_AUTHOR("Paul Diefenbaugh"); MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME); MODULE_LICENSE("GPL"); -int acpi_ac_add (struct acpi_device *device); -int acpi_ac_remove (struct acpi_device *device, int type); +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); static struct acpi_driver acpi_ac_driver = { @@ -108,9 +108,9 @@ acpi_ac_get_state ( FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_ac_dir; +static struct proc_dir_entry *acpi_ac_dir; -int acpi_ac_seq_show(struct seq_file *seq, void *offset) +static int acpi_ac_seq_show(struct seq_file *seq, void *offset) { struct acpi_ac *ac = (struct acpi_ac *) seq->private; @@ -200,7 +200,7 @@ acpi_ac_remove_fs ( Driver Model -------------------------------------------------------------------------- */ -void +static void acpi_ac_notify ( acpi_handle handle, u32 event, @@ -232,7 +232,7 @@ acpi_ac_notify ( } -int +static int acpi_ac_add ( struct acpi_device *device) { @@ -286,7 +286,7 @@ end: } -int +static int acpi_ac_remove ( struct acpi_device *device, int type) @@ -315,7 +315,7 @@ acpi_ac_remove ( } -int __init +static int __init acpi_ac_init (void) { int result = 0; @@ -337,7 +337,7 @@ acpi_ac_init (void) } -void __exit +static void __exit acpi_ac_exit (void) { ACPI_FUNCTION_TRACE("acpi_ac_exit"); diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c new file mode 100644 index 0000000000..77285ffe41 --- /dev/null +++ b/drivers/acpi/acpi_memhotplug.c @@ -0,0 +1,542 @@ +/* + * Copyright (C) 2004 Intel Corporation <naveen.b.s@intel.com> + * + * All rights reserved. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * ACPI based HotPlug driver that supports Memory Hotplug + * This driver fields notifications from firmare for memory add + * and remove operations and alerts the VM of the affected memory + * ranges. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/memory_hotplug.h> +#include <acpi/acpi_drivers.h> + + +#define ACPI_MEMORY_DEVICE_COMPONENT 0x08000000UL +#define ACPI_MEMORY_DEVICE_CLASS "memory" +#define ACPI_MEMORY_DEVICE_HID "PNP0C80" +#define ACPI_MEMORY_DEVICE_DRIVER_NAME "Hotplug Mem Driver" +#define ACPI_MEMORY_DEVICE_NAME "Hotplug Mem Device" + +#define _COMPONENT ACPI_MEMORY_DEVICE_COMPONENT + +ACPI_MODULE_NAME ("acpi_memory") +MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>"); +MODULE_DESCRIPTION(ACPI_MEMORY_DEVICE_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +/* ACPI _STA method values */ +#define ACPI_MEMORY_STA_PRESENT (0x00000001UL) +#define ACPI_MEMORY_STA_ENABLED (0x00000002UL) +#define ACPI_MEMORY_STA_FUNCTIONAL (0x00000008UL) + +/* Memory Device States */ +#define MEMORY_INVALID_STATE 0 +#define MEMORY_POWER_ON_STATE 1 +#define MEMORY_POWER_OFF_STATE 2 + +static int acpi_memory_device_add (struct acpi_device *device); +static int acpi_memory_device_remove (struct acpi_device *device, int type); + +static struct acpi_driver acpi_memory_device_driver = { + .name = ACPI_MEMORY_DEVICE_DRIVER_NAME, + .class = ACPI_MEMORY_DEVICE_CLASS, + .ids = ACPI_MEMORY_DEVICE_HID, + .ops = { + .add = acpi_memory_device_add, + .remove = acpi_memory_device_remove, + }, +}; + +struct acpi_memory_device { + acpi_handle handle; + unsigned int state; /* State of the memory device */ + unsigned short cache_attribute; /* memory cache attribute */ + unsigned short read_write_attribute;/* memory read/write attribute */ + u64 start_addr; /* Memory Range start physical addr */ + u64 end_addr; /* Memory Range end physical addr */ +}; + + +static int +acpi_memory_get_device_resources(struct acpi_memory_device *mem_device) +{ + acpi_status status; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + struct acpi_resource *resource = NULL; + struct acpi_resource_address64 address64; + + ACPI_FUNCTION_TRACE("acpi_memory_get_device_resources"); + + /* Get the range from the _CRS */ + status = acpi_get_current_resources(mem_device->handle, &buffer); + if (ACPI_FAILURE(status)) + return_VALUE(-EINVAL); + + resource = (struct acpi_resource *) buffer.pointer; + status = acpi_resource_to_address64(resource, &address64); + if (ACPI_SUCCESS(status)) { + if (address64.resource_type == ACPI_MEMORY_RANGE) { + /* Populate the structure */ + mem_device->cache_attribute = + address64.attribute.memory.cache_attribute; + mem_device->read_write_attribute = + address64.attribute.memory.read_write_attribute; + mem_device->start_addr = address64.min_address_range; + mem_device->end_addr = address64.max_address_range; + } + } + + acpi_os_free(buffer.pointer); + return_VALUE(0); +} + +static int +acpi_memory_get_device(acpi_handle handle, + struct acpi_memory_device **mem_device) +{ + acpi_status status; + acpi_handle phandle; + struct acpi_device *device = NULL; + struct acpi_device *pdevice = NULL; + + ACPI_FUNCTION_TRACE("acpi_memory_get_device"); + + if (!acpi_bus_get_device(handle, &device) && device) + goto end; + + status = acpi_get_parent(handle, &phandle); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error in acpi_get_parent\n")); + return_VALUE(-EINVAL); + } + + /* Get the parent device */ + status = acpi_bus_get_device(phandle, &pdevice); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error in acpi_bus_get_device\n")); + return_VALUE(-EINVAL); + } + + /* + * Now add the notified device. This creates the acpi_device + * and invokes .add function + */ + status = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error in acpi_bus_add\n")); + return_VALUE(-EINVAL); + } + +end: + *mem_device = acpi_driver_data(device); + if (!(*mem_device)) { + printk(KERN_ERR "\n driver data not found" ); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + +static int +acpi_memory_check_device(struct acpi_memory_device *mem_device) +{ + unsigned long current_status; + + ACPI_FUNCTION_TRACE("acpi_memory_check_device"); + + /* Get device present/absent information from the _STA */ + if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->handle, "_STA", + NULL, ¤t_status))) + return_VALUE(-ENODEV); + /* + * Check for device status. Device should be + * present/enabled/functioning. + */ + if (!((current_status & ACPI_MEMORY_STA_PRESENT) + && (current_status & ACPI_MEMORY_STA_ENABLED) + && (current_status & ACPI_MEMORY_STA_FUNCTIONAL))) + return_VALUE(-ENODEV); + + return_VALUE(0); +} + +static int +acpi_memory_enable_device(struct acpi_memory_device *mem_device) +{ + int result; + + ACPI_FUNCTION_TRACE("acpi_memory_enable_device"); + + /* Get the range from the _CRS */ + result = acpi_memory_get_device_resources(mem_device); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "\nget_device_resources failed\n")); + mem_device->state = MEMORY_INVALID_STATE; + return result; + } + + /* + * Tell the VM there is more memory here... + * Note: Assume that this function returns zero on success + */ + result = add_memory(mem_device->start_addr, + (mem_device->end_addr - mem_device->start_addr) + 1, + mem_device->read_write_attribute); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "\nadd_memory failed\n")); + mem_device->state = MEMORY_INVALID_STATE; + return result; + } + + return result; +} + +static int +acpi_memory_powerdown_device(struct acpi_memory_device *mem_device) +{ + acpi_status status; + struct acpi_object_list arg_list; + union acpi_object arg; + unsigned long current_status; + + ACPI_FUNCTION_TRACE("acpi_memory_powerdown_device"); + + /* Issue the _EJ0 command */ + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = 1; + status = acpi_evaluate_object(mem_device->handle, + "_EJ0", &arg_list, NULL); + /* Return on _EJ0 failure */ + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"_EJ0 failed.\n")); + return_VALUE(-ENODEV); + } + + /* Evalute _STA to check if the device is disabled */ + status = acpi_evaluate_integer(mem_device->handle, "_STA", + NULL, ¤t_status); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + /* Check for device status. Device should be disabled */ + if (current_status & ACPI_MEMORY_STA_ENABLED) + return_VALUE(-EINVAL); + + return_VALUE(0); +} + +static int +acpi_memory_disable_device(struct acpi_memory_device *mem_device) +{ + int result; + u64 start = mem_device->start_addr; + u64 len = mem_device->end_addr - start + 1; + unsigned long attr = mem_device->read_write_attribute; + + ACPI_FUNCTION_TRACE("acpi_memory_disable_device"); + + /* + * Ask the VM to offline this memory range. + * Note: Assume that this function returns zero on success + */ + result = remove_memory(start, len, attr); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hot-Remove failed.\n")); + return_VALUE(result); + } + + /* Power-off and eject the device */ + result = acpi_memory_powerdown_device(mem_device); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Device Power Down failed.\n")); + /* Set the status of the device to invalid */ + mem_device->state = MEMORY_INVALID_STATE; + return result; + } + + mem_device->state = MEMORY_POWER_OFF_STATE; + return result; +} + +static void +acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) +{ + struct acpi_memory_device *mem_device; + struct acpi_device *device; + + ACPI_FUNCTION_TRACE("acpi_memory_device_notify"); + + switch (event) { + case ACPI_NOTIFY_BUS_CHECK: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "\nReceived BUS CHECK notification for device\n")); + /* Fall Through */ + case ACPI_NOTIFY_DEVICE_CHECK: + if (event == ACPI_NOTIFY_DEVICE_CHECK) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "\nReceived DEVICE CHECK notification for device\n")); + if (acpi_memory_get_device(handle, &mem_device)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error in finding driver data\n")); + return_VOID; + } + + if (!acpi_memory_check_device(mem_device)) { + if (acpi_memory_enable_device(mem_device)) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error in acpi_memory_enable_device\n")); + } + break; + case ACPI_NOTIFY_EJECT_REQUEST: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "\nReceived EJECT REQUEST notification for device\n")); + + if (acpi_bus_get_device(handle, &device)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Device doesn't exist\n")); + break; + } + mem_device = acpi_driver_data(device); + if (!mem_device) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Driver Data is NULL\n")); + break; + } + + /* + * Currently disabling memory device from kernel mode + * TBD: Can also be disabled from user mode scripts + * TBD: Can also be disabled by Callback registration + * with generic sysfs driver + */ + if (acpi_memory_disable_device(mem_device)) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error in acpi_memory_disable_device\n")); + /* + * TBD: Invoke acpi_bus_remove to cleanup data structures + */ + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Unsupported event [0x%x]\n", event)); + break; + } + + return_VOID; +} + +static int +acpi_memory_device_add(struct acpi_device *device) +{ + int result; + struct acpi_memory_device *mem_device = NULL; + + ACPI_FUNCTION_TRACE("acpi_memory_device_add"); + + if (!device) + return_VALUE(-EINVAL); + + mem_device = kmalloc(sizeof(struct acpi_memory_device), GFP_KERNEL); + if (!mem_device) + return_VALUE(-ENOMEM); + memset(mem_device, 0, sizeof(struct acpi_memory_device)); + + mem_device->handle = device->handle; + 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; + + /* Get the range from the _CRS */ + result = acpi_memory_get_device_resources(mem_device); + if (result) { + kfree(mem_device); + return_VALUE(result); + } + + /* Set the device state */ + mem_device->state = MEMORY_POWER_ON_STATE; + + printk(KERN_INFO "%s \n", acpi_device_name(device)); + + return_VALUE(result); +} + +static int +acpi_memory_device_remove (struct acpi_device *device, int type) +{ + struct acpi_memory_device *mem_device = NULL; + + ACPI_FUNCTION_TRACE("acpi_memory_device_remove"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + mem_device = (struct acpi_memory_device *) acpi_driver_data(device); + kfree(mem_device); + + return_VALUE(0); +} + +/* + * Helper function to check for memory device + */ +static acpi_status +is_memory_device(acpi_handle handle) +{ + char *hardware_id; + acpi_status status; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + struct acpi_device_info *info; + + ACPI_FUNCTION_TRACE("is_memory_device"); + + status = acpi_get_object_info(handle, &buffer); + if (ACPI_FAILURE(status)) + return_ACPI_STATUS(AE_ERROR); + + info = buffer.pointer; + if (!(info->valid & ACPI_VALID_HID)) { + acpi_os_free(buffer.pointer); + return_ACPI_STATUS(AE_ERROR); + } + + hardware_id = info->hardware_id.value; + if ((hardware_id == NULL) || + (strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID))) + status = AE_ERROR; + + acpi_os_free(buffer.pointer); + return_ACPI_STATUS(status); +} + +static acpi_status +acpi_memory_register_notify_handler (acpi_handle handle, + u32 level, void *ctxt, void **retv) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE("acpi_memory_register_notify_handler"); + + status = is_memory_device(handle); + if (ACPI_FAILURE(status)) + return_ACPI_STATUS(AE_OK); /* continue */ + + status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + acpi_memory_device_notify, NULL); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error installing notify handler\n")); + return_ACPI_STATUS(AE_OK); /* continue */ + } + + return_ACPI_STATUS(status); +} + +static acpi_status +acpi_memory_deregister_notify_handler (acpi_handle handle, + u32 level, void *ctxt, void **retv) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE("acpi_memory_deregister_notify_handler"); + + status = is_memory_device(handle); + if (ACPI_FAILURE(status)) + return_ACPI_STATUS(AE_OK); /* continue */ + + status = acpi_remove_notify_handler(handle, + ACPI_SYSTEM_NOTIFY, acpi_memory_device_notify); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error removing notify handler\n")); + return_ACPI_STATUS(AE_OK); /* continue */ + } + + return_ACPI_STATUS(status); +} + +static int __init +acpi_memory_device_init (void) +{ + int result; + acpi_status status; + + ACPI_FUNCTION_TRACE("acpi_memory_device_init"); + + result = acpi_bus_register_driver(&acpi_memory_device_driver); + + if (result < 0) + return_VALUE(-ENODEV); + + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + acpi_memory_register_notify_handler, + NULL, NULL); + + if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed\n")); + acpi_bus_unregister_driver(&acpi_memory_device_driver); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + +static void __exit +acpi_memory_device_exit (void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE("acpi_memory_device_exit"); + + /* + * Adding this to un-install notification handlers for all the device + * handles. + */ + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + acpi_memory_deregister_notify_handler, + NULL, NULL); + + if (ACPI_FAILURE (status)) + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed\n")); + + acpi_bus_unregister_driver(&acpi_memory_device_driver); + + return_VOID; +} + +module_init(acpi_memory_device_init); +module_exit(acpi_memory_device_exit); + + diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index a10de067db..c55feca9b7 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -341,7 +341,7 @@ acpi_battery_check ( FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_battery_dir; +static struct proc_dir_entry *acpi_battery_dir; static int acpi_battery_read_info(struct seq_file *seq, void *offset) { int result = 0; diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 31aded126c..ec4430e305 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -275,7 +275,7 @@ acpi_button_remove_fs ( Driver Interface -------------------------------------------------------------------------- */ -void +static void acpi_button_notify ( acpi_handle handle, u32 event, @@ -302,7 +302,7 @@ acpi_button_notify ( } -acpi_status +static acpi_status acpi_button_notify_fixed ( void *data) { diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 060251b5e4..5a0adbf8bc 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -177,13 +177,18 @@ container_notify_cb(acpi_handle handle, u32 type, void *context) printk("Container driver received %s event\n", (type == ACPI_NOTIFY_BUS_CHECK)? "ACPI_NOTIFY_BUS_CHECK":"ACPI_NOTIFY_DEVICE_CHECK"); + status = acpi_bus_get_device(handle, &device); if (present) { - status = acpi_bus_get_device(handle, &device); if (ACPI_FAILURE(status) || !device) { result = container_device_add(&device, handle); if (!result) - kobject_hotplug(&device->kobj, KOBJ_ONLINE); - } else { + kobject_hotplug(&device->kobj, + KOBJ_ONLINE); + else + printk("Failed to add container\n"); + } + } else { + if (ACPI_SUCCESS(status)) { /* device exist and this is a remove request */ kobject_hotplug(&device->kobj, KOBJ_OFFLINE); } @@ -255,7 +260,7 @@ end: } -int __init +static int __init acpi_container_init(void) { int result = 0; @@ -276,7 +281,7 @@ acpi_container_init(void) return(0); } -void __exit +static void __exit acpi_container_exit(void) { int action = UNINSTALL_NOTIFY_HANDLER; diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index d947e2a0a4..2c0dac559f 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c @@ -35,7 +35,7 @@ struct acpi_dlevel { }; #define ACPI_DEBUG_INIT(v) { .name = #v, .value = v } -const struct acpi_dlayer acpi_debug_layers[] = +static const struct acpi_dlayer acpi_debug_layers[] = { ACPI_DEBUG_INIT(ACPI_UTILITIES), ACPI_DEBUG_INIT(ACPI_HARDWARE), @@ -53,7 +53,7 @@ const struct acpi_dlayer acpi_debug_layers[] = ACPI_DEBUG_INIT(ACPI_TOOLS), }; -const struct acpi_dlevel acpi_debug_levels[] = +static const struct acpi_dlevel acpi_debug_levels[] = { ACPI_DEBUG_INIT(ACPI_LV_ERROR), ACPI_DEBUG_INIT(ACPI_LV_WARN), diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index fac39ba4a7..9f0456cb9b 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -448,7 +448,16 @@ acpi_ds_restart_control_method ( */ walk_state->return_desc = return_desc; } - else { + + /* + * The following code is the + * optional support for a so-called "implicit return". Some AML code + * assumes that the last value of the method is "implicitly" returned + * to the caller. Just save the last result as the return value. + * NOTE: this is optional because the ASL language does not actually + * support this behavior. + */ + else if (!acpi_ds_do_implicit_return (return_desc, walk_state, FALSE)) { /* * Delete the return value if it will not be used by the * calling method diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index 66fc7549c6..5c987a0e7b 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c @@ -1010,6 +1010,10 @@ acpi_ds_exec_end_control_op ( * has been bubbled up the tree */ if (op->common.value.arg) { + /* Since we have a real Return(), delete any implicit return */ + + acpi_ds_clear_implicit_return (walk_state); + /* Return statement has an immediate operand */ status = acpi_ds_create_operands (walk_state, op->common.value.arg); @@ -1036,6 +1040,10 @@ acpi_ds_exec_end_control_op ( } else if ((walk_state->results) && (walk_state->results->results.num_results > 0)) { + /* Since we have a real Return(), delete any implicit return */ + + acpi_ds_clear_implicit_return (walk_state); + /* * The return value has come from a previous calculation. * diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c index df6b001867..462c5d83e7 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c @@ -54,10 +54,120 @@ ACPI_MODULE_NAME ("dsutils") +/******************************************************************************* + * + * FUNCTION: acpi_ds_clear_implicit_return + * + * PARAMETERS: walk_state - Current State + * + * RETURN: None. + * + * DESCRIPTION: Clear and remove a reference on an implicit return value. Used + * to delete "stale" return values (if enabled, the return value + * from every operator is saved at least momentarily, in case the + * parent method exits.) + * + ******************************************************************************/ + +void +acpi_ds_clear_implicit_return ( + struct acpi_walk_state *walk_state) +{ + ACPI_FUNCTION_NAME ("ds_clear_implicit_return"); + + + /* + * Slack must be enabled for this feature + */ + if (!acpi_gbl_enable_interpreter_slack) { + return; + } + + if (walk_state->implicit_return_obj) { + /* + * Delete any "stale" implicit return. However, in + * complex statements, the implicit return value can be + * bubbled up several levels. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Removing reference on stale implicit return obj %p\n", + walk_state->implicit_return_obj)); + + acpi_ut_remove_reference (walk_state->implicit_return_obj); + walk_state->implicit_return_obj = NULL; + } +} + + #ifndef ACPI_NO_METHOD_EXECUTION /******************************************************************************* * + * FUNCTION: acpi_ds_do_implicit_return + * + * PARAMETERS: return_desc - The return value + * walk_state - Current State + * add_reference - True if a reference should be added to the + * return object + * + * RETURN: TRUE if implicit return enabled, FALSE otherwise + * + * DESCRIPTION: Implements the optional "implicit return". We save the result + * of every ASL operator and control method invocation in case the + * parent method exit. Before storing a new return value, we + * delete the previous return value. + * + ******************************************************************************/ + +u8 +acpi_ds_do_implicit_return ( + union acpi_operand_object *return_desc, + struct acpi_walk_state *walk_state, + u8 add_reference) +{ + ACPI_FUNCTION_NAME ("ds_do_implicit_return"); + + + /* + * Slack must be enabled for this feature, and we must + * have a valid return object + */ + if ((!acpi_gbl_enable_interpreter_slack) || + (!return_desc)) { + return (FALSE); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Result %p will be implicitly returned; Prev=%p\n", + return_desc, + walk_state->implicit_return_obj)); + + /* + * Delete any "stale" implicit return value first. However, in + * complex statements, the implicit return value can be + * bubbled up several levels, so we don't clear the value if it + * is the same as the return_desc. + */ + if (walk_state->implicit_return_obj) { + if (walk_state->implicit_return_obj == return_desc) { + return (TRUE); + } + acpi_ds_clear_implicit_return (walk_state); + } + + /* Save the implicit return value, add a reference if requested */ + + walk_state->implicit_return_obj = return_desc; + if (add_reference) { + acpi_ut_add_reference (return_desc); + } + + return (TRUE); +} + + +/******************************************************************************* + * * FUNCTION: acpi_ds_is_result_used * * PARAMETERS: Op - Current Op @@ -76,7 +186,6 @@ acpi_ds_is_result_used ( { const struct acpi_opcode_info *parent_info; - ACPI_FUNCTION_TRACE_PTR ("ds_is_result_used", op); @@ -88,6 +197,19 @@ acpi_ds_is_result_used ( } /* + * We know that this operator is not a + * Return() operator (would not come here.) The following code is the + * optional support for a so-called "implicit return". Some AML code + * assumes that the last value of the method is "implicitly" returned + * to the caller. Just save the last result as the return value. + * NOTE: this is optional because the ASL language does not actually + * support this behavior. + */ + acpi_ds_do_implicit_return (walk_state->result_obj, walk_state, TRUE); + + /* + * Now determine if the parent will use the result + * * If there is no parent, or the parent is a scope_op, we are executing * at the method level. An executing method typically has no parent, * since each method is parsed separately. A method invoked externally @@ -95,29 +217,10 @@ acpi_ds_is_result_used ( */ if ((!op->common.parent) || (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) { - /* - * If this is the last statement in the method, we know it is not a - * Return() operator (would not come here.) The following code is the - * optional support for a so-called "implicit return". Some AML code - * assumes that the last value of the method is "implicitly" returned - * to the caller. Just save the last result as the return value. - * NOTE: this is optional because the ASL language does not actually - * support this behavior. - */ - if ((acpi_gbl_enable_interpreter_slack) && - (walk_state->parser_state.aml >= walk_state->parser_state.aml_end)) { - ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "Result of [%s] will be implicitly returned\n", - acpi_ps_get_opcode_name (op->common.aml_opcode))); - - /* Use the top of the result stack as the implicit return value */ - - walk_state->return_desc = walk_state->results->results.obj_desc[0]; - return_VALUE (TRUE); - } - /* No parent, the return value cannot possibly be used */ + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "At Method level, result of [%s] not used\n", + acpi_ps_get_opcode_name (op->common.aml_opcode))); return_VALUE (FALSE); } @@ -262,9 +365,8 @@ acpi_ds_delete_result_if_not_used ( } if (!acpi_ds_is_result_used (op, walk_state)) { - /* - * Must pop the result stack (obj_desc should be equal to result_obj) - */ + /* Must pop the result stack (obj_desc should be equal to result_obj) */ + status = acpi_ds_result_pop (&obj_desc, walk_state); if (ACPI_SUCCESS (status)) { acpi_ut_remove_reference (result_obj); @@ -338,9 +440,8 @@ acpi_ds_clear_operands ( ACPI_FUNCTION_TRACE_PTR ("ds_clear_operands", walk_state); - /* - * Remove a reference on each operand on the stack - */ + /* Remove a reference on each operand on the stack */ + for (i = 0; i < walk_state->num_operands; i++) { /* * Remove a reference to all operands, including both @@ -407,11 +508,7 @@ acpi_ds_create_operand ( return_ACPI_STATUS (status); } - /* - * All prefixes have been handled, and the name is - * in name_string - */ - + /* All prefixes have been handled, and the name is in name_string */ /* * Special handling for buffer_field declarations. This is a deferred @@ -586,7 +683,8 @@ acpi_ds_create_operand ( * * FUNCTION: acpi_ds_create_operands * - * PARAMETERS: first_arg - First argument of a parser argument tree + * PARAMETERS: walk_state - Current state + * first_arg - First argument of a parser argument tree * * RETURN: Status * diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index b02322e213..2071a0d2bb 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -91,6 +91,7 @@ acpi_ds_get_predicate_value ( union acpi_operand_object *result_obj) { acpi_status status = AE_OK; union acpi_operand_object *obj_desc; + union acpi_operand_object *local_obj_desc = NULL; ACPI_FUNCTION_TRACE_PTR ("ds_get_predicate_value", walk_state); @@ -130,12 +131,17 @@ acpi_ds_get_predicate_value ( } /* - * Result of predicate evaluation currently must - * be a number + * Result of predicate evaluation must be an Integer + * object. Implicitly convert the argument if necessary. */ - if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_INTEGER) { + status = acpi_ex_convert_to_integer (obj_desc, &local_obj_desc, 16); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + if (ACPI_GET_OBJECT_TYPE (local_obj_desc) != ACPI_TYPE_INTEGER) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Bad predicate (not a number) obj_desc=%p State=%p Type=%X\n", + "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X\n", obj_desc, walk_state, ACPI_GET_OBJECT_TYPE (obj_desc))); status = AE_AML_OPERAND_TYPE; @@ -144,13 +150,13 @@ acpi_ds_get_predicate_value ( /* Truncate the predicate to 32-bits if necessary */ - acpi_ex_truncate_for32bit_table (obj_desc); + acpi_ex_truncate_for32bit_table (local_obj_desc); /* * Save the result of the predicate evaluation on * the control stack */ - if (obj_desc->integer.value) { + if (local_obj_desc->integer.value) { walk_state->control_state->common.value = TRUE; } else { @@ -170,12 +176,15 @@ cleanup: /* Break to debugger to display result */ - ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (obj_desc, walk_state)); + ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (local_obj_desc, walk_state)); /* * Delete the predicate result object (we know that * we don't need it anymore) */ + if (local_obj_desc != obj_desc) { + acpi_ut_remove_reference (local_obj_desc); + } acpi_ut_remove_reference (obj_desc); walk_state->control_state->common.state = ACPI_CONTROL_NORMAL; @@ -306,9 +315,10 @@ acpi_ds_exec_begin_op ( case AML_CLASS_EXECUTE: case AML_CLASS_CREATE: - /* most operators with arguments */ - /* Start a new result/operand state */ - + /* + * Most operators with arguments. + * Start a new result/operand state + */ status = acpi_ds_result_stack_push (walk_state); break; @@ -471,20 +481,41 @@ acpi_ds_exec_end_op ( /* 1 Operand, 0 external_result, 0 internal_result */ status = acpi_ds_exec_end_control_op (walk_state, op); - if (ACPI_FAILURE (status)) { - break; - } - status = acpi_ds_result_stack_pop (walk_state); + /* Make sure to properly pop the result stack */ + + if (ACPI_SUCCESS (status)) { + status = acpi_ds_result_stack_pop (walk_state); + } + else if (status == AE_CTRL_PENDING) { + status = acpi_ds_result_stack_pop (walk_state); + if (ACPI_SUCCESS (status)) { + status = AE_CTRL_PENDING; + } + } break; case AML_TYPE_METHOD_CALL: + /* + * If the method is referenced from within a package + * declaration, it is not a invocation of the method, just + * a reference to it. + */ + if ((op->asl.parent) && + ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP) || + (op->asl.parent->asl.aml_opcode == AML_VAR_PACKAGE_OP))) { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method Reference in a Package, Op=%p\n", op)); + op->common.node = (struct acpi_namespace_node *) op->asl.value.arg->asl.node->object; + acpi_ut_add_reference (op->asl.value.arg->asl.node->object); + return_ACPI_STATUS (AE_OK); + } + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method invocation, Op=%p\n", op)); /* - * (AML_METHODCALL) Op->Value->Arg->Node contains + * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains * the method Node pointer */ /* next_op points to the op that holds the method name */ diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 8d4219388c..fdf143b405 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -514,7 +514,7 @@ out: FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_ec_dir; +static struct proc_dir_entry *acpi_ec_dir; static int diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index a48820152c..0bfec10a5f 100644 --- a/drivers/acpi/events/evxface.c +++ b/drivers/acpi/events/evxface.c @@ -149,7 +149,9 @@ acpi_install_fixed_event_handler ( acpi_gbl_fixed_event_handlers[event].handler = handler; acpi_gbl_fixed_event_handlers[event].context = context; - status = acpi_enable_event (event, 0); + status = acpi_clear_event (event); + if (ACPI_SUCCESS(status)) + status = acpi_enable_event (event, 0); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not enable fixed event.\n")); diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c index fc54d4d0cc..b542dcd58c 100644 --- a/drivers/acpi/executer/exmisc.c +++ b/drivers/acpi/executer/exmisc.c @@ -95,6 +95,7 @@ acpi_ex_get_object_reference ( switch (obj_desc->reference.opcode) { case AML_LOCAL_OP: case AML_ARG_OP: + case AML_DEBUG_OP: /* The referenced object is the pseudo-node for the local/arg */ @@ -103,7 +104,7 @@ acpi_ex_get_object_reference ( default: - ACPI_REPORT_ERROR (("Unknown Reference subtype in get ref %X\n", + ACPI_REPORT_ERROR (("Unknown Reference opcode in get_reference %X\n", obj_desc->reference.opcode)); return_ACPI_STATUS (AE_AML_INTERNAL); } @@ -121,7 +122,7 @@ acpi_ex_get_object_reference ( default: - ACPI_REPORT_ERROR (("Invalid descriptor type in get ref: %X\n", + ACPI_REPORT_ERROR (("Invalid descriptor type in get_reference: %X\n", ACPI_GET_DESCRIPTOR_TYPE (obj_desc))); return_ACPI_STATUS (AE_TYPE); } diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c index 23964e70a8..8be4d80cee 100644 --- a/drivers/acpi/executer/exoparg2.c +++ b/drivers/acpi/executer/exoparg2.c @@ -442,6 +442,12 @@ acpi_ex_opcode_2A_1T_1R ( return_desc->reference.object = operand[0]; } + /* + * Add a reference to the target package/buffer/string for the life + * of the index. + */ + acpi_ut_add_reference (operand[0]); + /* Complete the Index reference object */ return_desc->reference.opcode = AML_INDEX_OP; diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c index 9cccf8299d..7be6049111 100644 --- a/drivers/acpi/executer/exresolv.c +++ b/drivers/acpi/executer/exresolv.c @@ -422,6 +422,12 @@ acpi_ex_resolve_multiple ( * This could of course in turn be another reference object. */ obj_desc = *(obj_desc->reference.where); + if (!obj_desc) { + /* NULL package elements are allowed */ + + type = 0; /* Uninitialized */ + goto exit; + } break; diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c index e663a48f8a..d3677feb07 100644 --- a/drivers/acpi/executer/exstoren.c +++ b/drivers/acpi/executer/exstoren.c @@ -206,7 +206,6 @@ acpi_ex_store_object_to_object ( { union acpi_operand_object *actual_src_desc; acpi_status status = AE_OK; - acpi_object_type original_src_type; ACPI_FUNCTION_TRACE_PTR ("ex_store_object_to_object", source_desc); @@ -223,8 +222,7 @@ acpi_ex_store_object_to_object ( return_ACPI_STATUS (status); } - original_src_type = ACPI_GET_OBJECT_TYPE (source_desc); - if (original_src_type != ACPI_GET_OBJECT_TYPE (dest_desc)) { + if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_GET_OBJECT_TYPE (dest_desc)) { /* * The source type does not match the type of the destination. * Perform the "implicit conversion" of the source to the current type @@ -275,8 +273,7 @@ acpi_ex_store_object_to_object ( * Note: There is different store behavior depending on the original * source type */ - status = acpi_ex_store_buffer_to_buffer (original_src_type, actual_src_desc, - dest_desc); + status = acpi_ex_store_buffer_to_buffer (actual_src_desc, dest_desc); break; case ACPI_TYPE_PACKAGE: diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c index 4e2b442ee5..05e1ecae8d 100644 --- a/drivers/acpi/executer/exstorob.c +++ b/drivers/acpi/executer/exstorob.c @@ -66,7 +66,6 @@ acpi_status acpi_ex_store_buffer_to_buffer ( - acpi_object_type original_src_type, union acpi_operand_object *source_desc, union acpi_operand_object *target_desc) { @@ -77,9 +76,8 @@ acpi_ex_store_buffer_to_buffer ( ACPI_FUNCTION_TRACE_PTR ("ex_store_buffer_to_buffer", source_desc); - /* - * We know that source_desc is a buffer by now - */ + /* We know that source_desc is a buffer by now */ + buffer = (u8 *) source_desc->buffer.pointer; length = source_desc->buffer.length; @@ -105,7 +103,17 @@ acpi_ex_store_buffer_to_buffer ( ACPI_MEMSET (target_desc->buffer.pointer, 0, target_desc->buffer.length); ACPI_MEMCPY (target_desc->buffer.pointer, buffer, length); +#ifdef ACPI_OBSOLETE_BEHAVIOR + /* + * NOTE: ACPI versions up to 3.0 specified that the buffer must be + * truncated if the string is smaller than the buffer. However, "other" + * implementations of ACPI never did this and thus became the defacto + * standard. ACPi 3.0_a changes this behavior such that the buffer + * is no longer truncated. + */ + /* + * OBSOLETE BEHAVIOR: * If the original source was a string, we must truncate the buffer, * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer * copy must not truncate the original buffer. @@ -115,6 +123,7 @@ acpi_ex_store_buffer_to_buffer ( target_desc->buffer.length = length; } +#endif } else { /* Truncate the source, copy only what will fit */ @@ -159,9 +168,8 @@ acpi_ex_store_string_to_string ( ACPI_FUNCTION_TRACE_PTR ("ex_store_string_to_string", source_desc); - /* - * We know that source_desc is a string by now. - */ + /* We know that source_desc is a string by now */ + buffer = (u8 *) source_desc->string.pointer; length = source_desc->string.length; @@ -185,9 +193,8 @@ acpi_ex_store_string_to_string ( */ if (target_desc->string.pointer && (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) { - /* - * Only free if not a pointer into the DSDT - */ + /* Only free if not a pointer into the DSDT */ + ACPI_MEM_FREE (target_desc->string.pointer); } diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 2c5422dfec..14192ee55f 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -50,8 +50,8 @@ MODULE_AUTHOR("Paul Diefenbaugh"); MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME); MODULE_LICENSE("GPL"); -int acpi_fan_add (struct acpi_device *device); -int acpi_fan_remove (struct acpi_device *device, int type); +static int acpi_fan_add (struct acpi_device *device); +static int acpi_fan_remove (struct acpi_device *device, int type); static struct acpi_driver acpi_fan_driver = { .name = ACPI_FAN_DRIVER_NAME, @@ -72,27 +72,24 @@ struct acpi_fan { FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_fan_dir; +static struct proc_dir_entry *acpi_fan_dir; static int acpi_fan_read_state (struct seq_file *seq, void *offset) { - struct acpi_fan *fan = (struct acpi_fan *) seq->private; + struct acpi_fan *fan = seq->private; int state = 0; ACPI_FUNCTION_TRACE("acpi_fan_read_state"); - if (!fan) - goto end; - - if (acpi_bus_get_power(fan->handle, &state)) - goto end; - - seq_printf(seq, "status: %s\n", - !state?"on":"off"); - -end: + if (fan) { + if (acpi_bus_get_power(fan->handle, &state)) + seq_printf(seq, "status: ERROR\n"); + else + seq_printf(seq, "status: %s\n", + !state?"on":"off"); + } return_VALUE(0); } @@ -197,7 +194,7 @@ acpi_fan_remove_fs ( Driver Interface -------------------------------------------------------------------------- */ -int +static int acpi_fan_add ( struct acpi_device *device) { @@ -243,7 +240,7 @@ end: } -int +static int acpi_fan_remove ( struct acpi_device *device, int type) @@ -265,7 +262,7 @@ acpi_fan_remove ( } -int __init +static int __init acpi_fan_init (void) { int result = 0; @@ -287,7 +284,7 @@ acpi_fan_init (void) } -void __exit +static void __exit acpi_fan_exit (void) { ACPI_FUNCTION_TRACE("acpi_fan_exit"); diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 94a76e520e..0fb731a470 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -155,7 +155,7 @@ struct ibm_struct { int experimental; }; -struct proc_dir_entry *proc_dir = NULL; +static struct proc_dir_entry *proc_dir = NULL; #define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off") #define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") @@ -856,7 +856,7 @@ static int beep_write(struct ibm_struct *ibm, char *buf) return 0; } -struct ibm_struct ibms[] = { +static struct ibm_struct ibms[] = { { .name = "driver", .init = driver_init, diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 9bfce46cd4..a82834b327 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -170,7 +170,7 @@ acpi_table_parse_srat ( int __init -acpi_numa_init() +acpi_numa_init(void) { int result; diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 94a511315c..5a9128de62 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -563,7 +563,7 @@ acpi_os_write_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, acpi_integ } /* TODO: Change code to take advantage of driver model more */ -void +static void acpi_os_derive_pci_id_2 ( acpi_handle rhandle, /* upper bound */ acpi_handle chandle, /* current node */ @@ -1071,7 +1071,7 @@ acpi_os_signal ( } EXPORT_SYMBOL(acpi_os_signal); -int __init +static int __init acpi_os_name_setup(char *str) { char *p = acpi_os_name; @@ -1101,7 +1101,7 @@ __setup("acpi_os_name=", acpi_os_name_setup); * empty string disables _OSI * TBD additional string adds to _OSI */ -int __init +static int __init acpi_osi_setup(char *str) { if (str == NULL || *str == '\0') { @@ -1119,7 +1119,7 @@ acpi_osi_setup(char *str) __setup("acpi_osi=", acpi_osi_setup); /* enable serialization to combat AE_ALREADY_EXISTS errors */ -int __init +static int __init acpi_serialize_setup(char *str) { printk(KERN_INFO PREFIX "serialize enabled\n"); @@ -1140,7 +1140,7 @@ __setup("acpi_serialize", acpi_serialize_setup); * Run-time events on the same GPE this flag is available * to tell Linux to keep the wake-time GPEs enabled at run-time. */ -int __init +static int __init acpi_wake_gpes_always_on_setup(char *str) { printk(KERN_INFO PREFIX "wake GPEs not disabled\n"); diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c index c1360fc23c..03e33fedc1 100644 --- a/drivers/acpi/parser/psopcode.c +++ b/drivers/acpi/parser/psopcode.c @@ -522,7 +522,7 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = /* 2E */ ACPI_OP ("DerefOf", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R), /* 2F */ ACPI_OP ("Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R), /* 30 */ ACPI_OP ("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE), -/* 31 */ ACPI_OP ("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), +/* 31 */ ACPI_OP ("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R), /* 32 */ ACPI_OP ("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT), /* 33 */ ACPI_OP ("CreateDWordField", ARGP_CREATE_DWORD_FIELD_OP,ARGI_CREATE_DWORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE), /* 34 */ ACPI_OP ("CreateWordField", ARGP_CREATE_WORD_FIELD_OP, ARGI_CREATE_WORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE), diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index fd2751f512..e79edb53cb 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -1187,8 +1187,8 @@ acpi_ps_parse_aml ( previous_walk_state = walk_state; - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "return_value=%p, State=%p\n", - walk_state->return_desc, walk_state)); + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "return_value=%p, implicit_value=%p State=%p\n", + walk_state->return_desc, walk_state->implicit_return_obj, walk_state)); /* Check if we have restarted a preempted walk */ @@ -1200,8 +1200,20 @@ acpi_ps_parse_aml ( * If the method return value is not used by the parent, * The object is deleted */ - status = acpi_ds_restart_control_method (walk_state, - previous_walk_state->return_desc); + if (!previous_walk_state->return_desc) { + status = acpi_ds_restart_control_method (walk_state, + previous_walk_state->implicit_return_obj); + } + else { + /* + * We have a valid return value, delete any implicit + * return value. + */ + acpi_ds_clear_implicit_return (previous_walk_state); + + status = acpi_ds_restart_control_method (walk_state, + previous_walk_state->return_desc); + } if (ACPI_SUCCESS (status)) { walk_state->walk_type |= ACPI_WALK_METHOD_RESTART; } @@ -1218,12 +1230,26 @@ acpi_ps_parse_aml ( * value (if any) */ else if (previous_walk_state->caller_return_desc) { - *(previous_walk_state->caller_return_desc) = previous_walk_state->return_desc; /* NULL if no return value */ + if (previous_walk_state->implicit_return_obj) { + *(previous_walk_state->caller_return_desc) = previous_walk_state->implicit_return_obj; + } + else { + /* NULL if no return value */ + + *(previous_walk_state->caller_return_desc) = previous_walk_state->return_desc; + } } - else if (previous_walk_state->return_desc) { - /* Caller doesn't want it, must delete it */ + else { + if (previous_walk_state->return_desc) { + /* Caller doesn't want it, must delete it */ - acpi_ut_remove_reference (previous_walk_state->return_desc); + acpi_ut_remove_reference (previous_walk_state->return_desc); + } + if (previous_walk_state->implicit_return_obj) { + /* Caller doesn't want it, must delete it */ + + acpi_ut_remove_reference (previous_walk_state->implicit_return_obj); + } } acpi_ds_delete_walk_state (previous_walk_state); diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c index e04b1b7360..110d2ce917 100644 --- a/drivers/acpi/parser/pswalk.c +++ b/drivers/acpi/parser/pswalk.c @@ -44,7 +44,6 @@ #include <acpi/acpi.h> #include <acpi/acparser.h> -#include <acpi/acdispat.h> #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME ("pswalk") @@ -52,256 +51,65 @@ /******************************************************************************* * - * FUNCTION: acpi_ps_get_next_walk_op + * FUNCTION: acpi_ps_delete_parse_tree * - * PARAMETERS: walk_state - Current state of the walk - * Op - Current Op to be walked - * ascending_callback - Procedure called when Op is complete + * PARAMETERS: subtree_root - Root of tree (or subtree) to delete * - * RETURN: Status + * RETURN: None * - * DESCRIPTION: Get the next Op in a walk of the parse tree. + * DESCRIPTION: Delete a portion of or an entire parse tree. * ******************************************************************************/ -acpi_status -acpi_ps_get_next_walk_op ( - struct acpi_walk_state *walk_state, - union acpi_parse_object *op, - acpi_parse_upwards ascending_callback) +void +acpi_ps_delete_parse_tree ( + union acpi_parse_object *subtree_root) { - union acpi_parse_object *next; - union acpi_parse_object *parent; - union acpi_parse_object *grand_parent; - acpi_status status; + union acpi_parse_object *op = subtree_root; + union acpi_parse_object *next = NULL; + union acpi_parse_object *parent = NULL; - ACPI_FUNCTION_TRACE_PTR ("ps_get_next_walk_op", op); + ACPI_FUNCTION_TRACE_PTR ("ps_delete_parse_tree", subtree_root); - /* Check for a argument only if we are descending in the tree */ + /* Visit all nodes in the subtree */ - if (walk_state->next_op_info != ACPI_NEXT_OP_UPWARD) { - /* Look for an argument or child of the current op */ + while (op) { + /* Check if we are not ascending */ - next = acpi_ps_get_arg (op, 0); - if (next) { - /* Still going downward in tree (Op is not completed yet) */ + if (op != parent) { + /* Look for an argument or child of the current op */ - walk_state->prev_op = op; - walk_state->next_op = next; - walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD; + next = acpi_ps_get_arg (op, 0); + if (next) { + /* Still going downward in tree (Op is not completed yet) */ - return_ACPI_STATUS (AE_OK); + op = next; + continue; + } } /* - * No more children, this Op is complete. Save Next and Parent - * in case the Op object gets deleted by the callback routine + * No more children, this Op is complete. */ - next = op->common.next; - parent = op->common.parent; - - walk_state->op = op; - walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); - walk_state->opcode = op->common.aml_opcode; + next = op->common.next; + parent = op->common.parent; - status = ascending_callback (walk_state); + acpi_ps_free_op (op); /* * If we are back to the starting point, the walk is complete. */ - if (op == walk_state->origin) { - /* Reached the point of origin, the walk is complete */ - - walk_state->prev_op = op; - walk_state->next_op = NULL; - - return_ACPI_STATUS (status); + if (op == subtree_root) { + return_VOID; } - - /* - * Check for a sibling to the current op. A sibling means - * we are still going "downward" in the tree. - */ if (next) { - /* There is a sibling, it will be next */ - - walk_state->prev_op = op; - walk_state->next_op = next; - walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD; - - /* Continue downward */ - - return_ACPI_STATUS (status); + op = next; } - - /* - * Drop into the loop below because we are moving upwards in - * the tree - */ - } - else { - /* - * We are resuming a walk, and we were (are) going upward in the tree. - * So, we want to drop into the parent loop below. - */ - parent = op; - } - - /* - * Look for a sibling of the current Op's parent - * Continue moving up the tree until we find a node that has not been - * visited, or we get back to where we started. - */ - while (parent) { - /* We are moving up the tree, therefore this parent Op is complete */ - - grand_parent = parent->common.parent; - next = parent->common.next; - - walk_state->op = parent; - walk_state->op_info = acpi_ps_get_opcode_info (parent->common.aml_opcode); - walk_state->opcode = parent->common.aml_opcode; - - status = ascending_callback (walk_state); - - /* - * If we are back to the starting point, the walk is complete. - */ - if (parent == walk_state->origin) { - /* Reached the point of origin, the walk is complete */ - - walk_state->prev_op = parent; - walk_state->next_op = NULL; - - return_ACPI_STATUS (status); - } - - /* - * If there is a sibling to this parent (it is not the starting point - * Op), then we will visit it. - */ - if (next) { - /* found sibling of parent */ - - walk_state->prev_op = parent; - walk_state->next_op = next; - walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD; - - return_ACPI_STATUS (status); + else { + op = parent; } - - /* No siblings, no errors, just move up one more level in the tree */ - - op = parent; - parent = grand_parent; - walk_state->prev_op = op; } - - - /* - * Got all the way to the top of the tree, we must be done! - * However, the code should have terminated in the loop above - */ - walk_state->next_op = NULL; - - return_ACPI_STATUS (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: acpi_ps_delete_completed_op - * - * PARAMETERS: State - Walk state - * Op - Completed op - * - * RETURN: AE_OK - * - * DESCRIPTION: Callback function for acpi_ps_get_next_walk_op(). Used during - * acpi_ps_delete_parse tree to delete Op objects when all sub-objects - * have been visited (and deleted.) - * - ******************************************************************************/ - -acpi_status -acpi_ps_delete_completed_op ( - struct acpi_walk_state *walk_state) -{ - - acpi_ps_free_op (walk_state->op); - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: acpi_ps_delete_parse_tree - * - * PARAMETERS: subtree_root - Root of tree (or subtree) to delete - * - * RETURN: None - * - * DESCRIPTION: Delete a portion of or an entire parse tree. - * - ******************************************************************************/ - -void -acpi_ps_delete_parse_tree ( - union acpi_parse_object *subtree_root) -{ - struct acpi_walk_state *walk_state; - struct acpi_thread_state *thread; - acpi_status status; - - - ACPI_FUNCTION_TRACE_PTR ("ps_delete_parse_tree", subtree_root); - - - if (!subtree_root) { - return_VOID; - } - - /* Create and initialize a new walk list */ - - thread = acpi_ut_create_thread_state (); - if (!thread) { - return_VOID; - } - - walk_state = acpi_ds_create_walk_state (0, NULL, NULL, thread); - if (!walk_state) { - return_VOID; - } - - walk_state->parse_flags = 0; - walk_state->descending_callback = NULL; - walk_state->ascending_callback = NULL; - - walk_state->origin = subtree_root; - walk_state->next_op = subtree_root; - - /* Head downward in the tree */ - - walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD; - - /* Visit all nodes in the subtree */ - - while (walk_state->next_op) { - status = acpi_ps_get_next_walk_op (walk_state, walk_state->next_op, - acpi_ps_delete_completed_op); - if (ACPI_FAILURE (status)) { - break; - } - } - - /* We are done with this walk */ - - acpi_ut_delete_generic_state (ACPI_CAST_PTR (union acpi_generic_state, thread)); - acpi_ds_delete_walk_state (walk_state); - return_VOID; } - - diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index a4750192a3..12b0eea634 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -42,8 +42,8 @@ #define _COMPONENT ACPI_PCI_COMPONENT ACPI_MODULE_NAME ("pci_irq") -struct acpi_prt_list acpi_prt; -DEFINE_SPINLOCK(acpi_prt_lock); +static struct acpi_prt_list acpi_prt; +static DEFINE_SPINLOCK(acpi_prt_lock); /* -------------------------------------------------------------------------- PCI IRQ Routing Table (PRT) Support @@ -281,7 +281,8 @@ acpi_pci_irq_lookup ( int device, int pin, int *edge_level, - int *active_high_low) + int *active_high_low, + char **link) { struct acpi_prt_entry *entry = NULL; int segment = pci_domain_nr(bus); @@ -301,7 +302,8 @@ acpi_pci_irq_lookup ( } if (entry->link.handle) { - irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, edge_level, active_high_low); + irq = acpi_pci_link_get_irq(entry->link.handle, + entry->link.index, edge_level, active_high_low, link); if (irq < 0) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); return_VALUE(-1); @@ -327,7 +329,8 @@ acpi_pci_irq_derive ( struct pci_dev *dev, int pin, int *edge_level, - int *active_high_low) + int *active_high_low, + char **link) { struct pci_dev *bridge = dev; int irq = -1; @@ -360,7 +363,7 @@ acpi_pci_irq_derive ( } irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn), - pin, edge_level, active_high_low); + pin, edge_level, active_high_low, link); } if (irq < 0) { @@ -389,6 +392,7 @@ acpi_pci_irq_enable ( int edge_level = ACPI_LEVEL_SENSITIVE; int active_high_low = ACPI_ACTIVE_LOW; extern int via_interrupt_line_quirk; + char *link = NULL; ACPI_FUNCTION_TRACE("acpi_pci_irq_enable"); @@ -411,21 +415,23 @@ acpi_pci_irq_enable ( * First we check the PCI IRQ routing table (PRT) for an IRQ. PRT * values override any BIOS-assigned IRQs set during boot. */ - irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, &edge_level, &active_high_low); + irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, + &edge_level, &active_high_low, &link); /* * If no PRT entry was found, we'll try to derive an IRQ from the * device's parent bridge. */ if (irq < 0) - irq = acpi_pci_irq_derive(dev, pin, &edge_level, &active_high_low); + irq = acpi_pci_irq_derive(dev, pin, &edge_level, + &active_high_low, &link); /* * No IRQ known to the ACPI subsystem - maybe the BIOS / * driver reported one, then use it. Exit in any case. */ if (irq < 0) { - printk(KERN_WARNING PREFIX "PCI interrupt %s[%c]: no GSI", + printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: no GSI", pci_name(dev), ('A' + pin)); /* Interrupt Line values above 0xF are forbidden */ if (dev->irq >= 0 && (dev->irq <= 0xF)) { @@ -443,9 +449,13 @@ acpi_pci_irq_enable ( dev->irq = acpi_register_gsi(irq, edge_level, active_high_low); - printk(KERN_INFO PREFIX "PCI interrupt %s[%c] -> GSI %u " - "(%s, %s) -> IRQ %d\n", - pci_name(dev), 'A' + pin, irq, + printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ", + pci_name(dev), 'A' + pin); + + if (link) + printk("Link [%s] -> ", link); + + printk("GSI %u (%s, %s) -> IRQ %d\n", irq, (edge_level == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", (active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); @@ -482,14 +492,14 @@ acpi_pci_irq_disable ( * First we check the PCI IRQ routing table (PRT) for an IRQ. */ gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, - &edge_level, &active_high_low); + &edge_level, &active_high_low, NULL); /* * If no PRT entry was found, we'll try to derive an IRQ from the * device's parent bridge. */ if (gsi < 0) gsi = acpi_pci_irq_derive(dev, pin, - &edge_level, &active_high_low); + &edge_level, &active_high_low, NULL); if (gsi < 0) return_VOID; diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 3191b5ff10..520b28ad07 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -522,9 +522,11 @@ acpi_irq_penalty_init(void) static int acpi_irq_balance; /* 0: static, 1: balance */ -static int acpi_pci_link_allocate(struct acpi_pci_link* link) { - int irq; - int i; +static int acpi_pci_link_allocate( + struct acpi_pci_link *link) +{ + int irq; + int i; ACPI_FUNCTION_TRACE("acpi_pci_link_allocate"); @@ -597,8 +599,9 @@ int acpi_pci_link_get_irq ( acpi_handle handle, int index, - int* edge_level, - int* active_high_low) + int *edge_level, + int *active_high_low, + char **name) { int result = 0; struct acpi_device *device = NULL; @@ -634,6 +637,7 @@ acpi_pci_link_get_irq ( if (edge_level) *edge_level = link->irq.edge_level; if (active_high_low) *active_high_low = link->irq.active_high_low; + if (name) *name = acpi_device_bid(link->device); return_VALUE(link->irq.active); } diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 2adaba68b8..7e6b8e3b2e 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -258,7 +258,7 @@ acpi_pci_root_add ( /* TBD: Locking */ list_add_tail(&root->node, &acpi_pci_roots); - printk(KERN_INFO PREFIX "%s [%s] (%02x:%02x)\n", + printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n", acpi_device_name(device), acpi_device_bid(device), root->id.segment, root->id.bus); @@ -272,7 +272,7 @@ acpi_pci_root_add ( root->bus = pci_acpi_scan_root(device, root->id.segment, root->id.bus); if (!root->bus) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Bus %02x:%02x not present in PCI namespace\n", + "Bus %04x:%02x not present in PCI namespace\n", root->id.segment, root->id.bus)); result = -ENODEV; goto end; diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 419b371d95..373a3a95bb 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -58,8 +58,8 @@ ACPI_MODULE_NAME ("acpi_power") #define ACPI_POWER_RESOURCE_STATE_ON 0x01 #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF -int acpi_power_add (struct acpi_device *device); -int acpi_power_remove (struct acpi_device *device, int type); +static int acpi_power_add (struct acpi_device *device); +static int acpi_power_remove (struct acpi_device *device, int type); static int acpi_power_open_fs(struct inode *inode, struct file *file); static struct acpi_driver acpi_power_driver = { @@ -479,7 +479,7 @@ end: FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_power_dir; +static struct proc_dir_entry *acpi_power_dir; static int acpi_power_seq_show(struct seq_file *seq, void *offset) { @@ -576,7 +576,7 @@ acpi_power_remove_fs ( Driver Interface -------------------------------------------------------------------------- */ -int +static int acpi_power_add ( struct acpi_device *device) { @@ -642,7 +642,7 @@ end: } -int +static int acpi_power_remove ( struct acpi_device *device, int type) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index e517a11dc9..f4778747e8 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -105,7 +105,7 @@ static struct acpi_driver acpi_processor_driver = { #define UNINSTALL_NOTIFY_HANDLER 2 -struct file_operations acpi_processor_info_fops = { +static struct file_operations acpi_processor_info_fops = { .open = acpi_processor_info_open_fs, .read = seq_read, .llseek = seq_lseek, @@ -121,7 +121,7 @@ struct acpi_processor_errata errata; Errata Handling -------------------------------------------------------------------------- */ -int +static int acpi_processor_errata_piix4 ( struct pci_dev *dev) { @@ -259,7 +259,7 @@ acpi_processor_errata ( FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_processor_dir = NULL; +static struct proc_dir_entry *acpi_processor_dir = NULL; static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset) { diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 8711236d28..12bd980a12 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -345,7 +345,7 @@ end: return_VALUE(0); } -int acpi_processor_limit_open_fs(struct inode *inode, struct file *file) +static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file) { return single_open(file, acpi_processor_limit_seq_show, PDE(inode)->data); diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index db0b31d2b3..be9f569d39 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -308,7 +308,7 @@ end: return_VALUE(0); } -int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file) +static int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file) { return single_open(file, acpi_processor_throttling_seq_show, PDE(inode)->data); diff --git a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c index ec4ae9a15c..4788c07973 100644 --- a/drivers/acpi/resources/rsaddr.c +++ b/drivers/acpi/resources/rsaddr.c @@ -110,13 +110,13 @@ acpi_rs_address16_resource ( buffer += 2; temp8 = *buffer; - /* Values 0-2 are valid */ + /* Values 0-2 and 0xC0-0xFF are valid */ - if (temp8 > 2) { + if ((temp8 > 2) && (temp8 < 0xC0)) { return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); } - output_struct->data.address16.resource_type = temp8 & 0x03; + output_struct->data.address16.resource_type = temp8; /* * Get the General Flags (Byte4) @@ -496,12 +496,13 @@ acpi_rs_address32_resource ( buffer += 2; temp8 = *buffer; - /* Values 0-2 are valid */ - if(temp8 > 2) { + /* Values 0-2 and 0xC0-0xFF are valid */ + + if ((temp8 > 2) && (temp8 < 0xC0)) { return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); } - output_struct->data.address32.resource_type = temp8 & 0x03; + output_struct->data.address32.resource_type = temp8; /* * Get the General Flags (Byte4) @@ -850,6 +851,7 @@ acpi_rs_address64_resource ( struct acpi_resource *output_struct = (void *) *output_buffer; u16 temp16; u8 temp8; + u8 resource_type; u8 *temp_ptr; acpi_size struct_size; u32 index; @@ -860,6 +862,7 @@ acpi_rs_address64_resource ( buffer = byte_stream_buffer; struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64); + resource_type = *buffer; /* * Point past the Descriptor to get the number of bytes consumed @@ -882,13 +885,13 @@ acpi_rs_address64_resource ( buffer += 2; temp8 = *buffer; - /* Values 0-2 are valid */ + /* Values 0-2 and 0xC0-0xFF are valid */ - if(temp8 > 2) { + if ((temp8 > 2) && (temp8 < 0xC0)) { return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); } - output_struct->data.address64.resource_type = temp8 & 0x03; + output_struct->data.address64.resource_type = temp8; /* * Get the General Flags (Byte4) @@ -942,98 +945,113 @@ acpi_rs_address64_resource ( } } + if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) { + /* Move past revision_id and Reserved byte */ + + buffer += 2; + } + /* - * Get Granularity (Bytes 6-13) + * Get Granularity (Bytes 6-13) or (Bytes 8-15) */ buffer += 1; ACPI_MOVE_64_TO_64 (&output_struct->data.address64.granularity, buffer); /* - * Get min_address_range (Bytes 14-21) + * Get min_address_range (Bytes 14-21) or (Bytes 16-23) */ buffer += 8; ACPI_MOVE_64_TO_64 (&output_struct->data.address64.min_address_range, buffer); /* - * Get max_address_range (Bytes 22-29) + * Get max_address_range (Bytes 22-29) or (Bytes 24-31) */ buffer += 8; ACPI_MOVE_64_TO_64 (&output_struct->data.address64.max_address_range, buffer); /* - * Get address_translation_offset (Bytes 30-37) + * Get address_translation_offset (Bytes 30-37) or (Bytes 32-39) */ buffer += 8; ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_translation_offset, buffer); /* - * Get address_length (Bytes 38-45) + * Get address_length (Bytes 38-45) or (Bytes 40-47) */ buffer += 8; ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_length, buffer); - /* - * Resource Source Index (if present) - */ - buffer += 8; + output_struct->data.address64.resource_source.index = 0x00; + output_struct->data.address64.resource_source.string_length = 0; + output_struct->data.address64.resource_source.string_ptr = NULL; - /* - * This will leave us pointing to the Resource Source Index - * If it is present, then save it off and calculate the - * pointer to where the null terminated string goes: - * Each Interrupt takes 32-bits + the 5 bytes of the - * stream that are default. - * - * Note: Some resource descriptors will have an additional null, so - * we add 1 to the length. - */ - if (*bytes_consumed > (46 + 1)) { - /* Dereference the Index */ + if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) { + /* Get type_specific_attribute (Bytes 48-55) */ - temp8 = *buffer; - output_struct->data.address64.resource_source.index = - (u32) temp8; + buffer += 8; + ACPI_MOVE_64_TO_64 (&output_struct->data.address64.type_specific_attributes, buffer); + } + else { + output_struct->data.address64.type_specific_attributes = 0; - /* Point to the String */ + /* + * Resource Source Index (if present) + */ + buffer += 8; - buffer += 1; + /* + * This will leave us pointing to the Resource Source Index + * If it is present, then save it off and calculate the + * pointer to where the null terminated string goes: + * Each Interrupt takes 32-bits + the 5 bytes of the + * stream that are default. + * + * Note: Some resource descriptors will have an additional null, so + * we add 1 to the length. + */ + if (*bytes_consumed > (46 + 1)) { + /* Dereference the Index */ - /* Point the String pointer to the end of this structure */ + temp8 = *buffer; + output_struct->data.address64.resource_source.index = + (u32) temp8; - output_struct->data.address64.resource_source.string_ptr = - (char *)((u8 *)output_struct + struct_size); + /* Point to the String */ - temp_ptr = (u8 *) output_struct->data.address64.resource_source.string_ptr; + buffer += 1; - /* Copy the string into the buffer */ + /* Point the String pointer to the end of this structure */ - index = 0; - while (0x00 != *buffer) { - *temp_ptr = *buffer; + output_struct->data.address64.resource_source.string_ptr = + (char *)((u8 *)output_struct + struct_size); - temp_ptr += 1; - buffer += 1; - index += 1; - } + temp_ptr = (u8 *) output_struct->data.address64.resource_source.string_ptr; - /* - * Add the terminating null - */ - *temp_ptr = 0x00; - output_struct->data.address64.resource_source.string_length = index + 1; + /* Copy the string into the buffer */ - /* - * In order for the struct_size to fall on a 32-bit boundary, - * calculate the length of the string and expand the - * struct_size to the next 32-bit boundary. - */ - temp8 = (u8) (index + 1); - struct_size += ACPI_ROUND_UP_to_32_bITS (temp8); - } - else { - output_struct->data.address64.resource_source.index = 0x00; - output_struct->data.address64.resource_source.string_length = 0; - output_struct->data.address64.resource_source.string_ptr = NULL; + index = 0; + while (0x00 != *buffer) { + *temp_ptr = *buffer; + + temp_ptr += 1; + buffer += 1; + index += 1; + } + + /* + * Add the terminating null + */ + *temp_ptr = 0x00; + output_struct->data.address64.resource_source.string_length = index + 1; + + /* + * In order for the struct_size to fall on a 32-bit boundary, + * calculate the length of the string and expand the + * struct_size to the next 32-bit boundary. + */ + temp8 = (u8) (index + 1); + struct_size += ACPI_ROUND_UP_to_32_bITS (temp8); + } } /* diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index 1113af7469..8a5f0a5237 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c @@ -376,6 +376,20 @@ acpi_rs_get_list_length ( break; + case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE: + /* + * 64-Bit Address Resource + */ + buffer = byte_stream_buffer; + + ++buffer; + ACPI_MOVE_16_TO_16 (&temp16, buffer); + + bytes_consumed = temp16 + 3; + structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64); + break; + + case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE: /* * 64-Bit Address Resource diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c index a869980f7f..eef1b1f2c6 100644 --- a/drivers/acpi/resources/rsdump.c +++ b/drivers/acpi/resources/rsdump.c @@ -571,7 +571,7 @@ acpi_rs_dump_address16 ( break; } - acpi_os_printf (" Type Specific: %s Translation\n", + acpi_os_printf (" Type Specific: %s Translation\n", ACPI_SPARSE_TRANSLATION == address16_data->attribute.io.translation_attribute ? "Sparse" : "Dense"); @@ -584,8 +584,8 @@ acpi_rs_dump_address16 ( default: - acpi_os_printf ("Invalid resource type. Exiting.\n"); - return; + acpi_os_printf ("0x%2.2X\n", address16_data->resource_type); + break; } acpi_os_printf (" Resource %s\n", @@ -718,7 +718,7 @@ acpi_rs_dump_address32 ( break; } - acpi_os_printf (" Type Specific: %s Translation\n", + acpi_os_printf (" Type Specific: %s Translation\n", ACPI_SPARSE_TRANSLATION == address32_data->attribute.io.translation_attribute ? "Sparse" : "Dense"); @@ -731,8 +731,8 @@ acpi_rs_dump_address32 ( default: - acpi_os_printf (" Invalid Resource Type..exiting.\n"); - return; + acpi_os_printf (" Resource Type: 0x%2.2X\n", address32_data->resource_type); + break; } acpi_os_printf (" Resource %s\n", @@ -865,7 +865,7 @@ acpi_rs_dump_address64 ( break; } - acpi_os_printf (" Type Specific: %s Translation\n", + acpi_os_printf (" Type Specific: %s Translation\n", ACPI_SPARSE_TRANSLATION == address64_data->attribute.io.translation_attribute ? "Sparse" : "Dense"); @@ -878,8 +878,8 @@ acpi_rs_dump_address64 ( default: - acpi_os_printf (" Invalid Resource Type..exiting.\n"); - return; + acpi_os_printf (" Resource Type: 0x%2.2X\n", address64_data->resource_type); + break; } acpi_os_printf (" Resource %s\n", @@ -913,7 +913,10 @@ acpi_rs_dump_address64 ( acpi_os_printf (" Address Length: %8.8X%8.8X\n", ACPI_FORMAT_UINT64 (address64_data->address_length)); - if(0xFF != address64_data->resource_source.index) { + acpi_os_printf (" Type Specific Attributes: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (address64_data->type_specific_attributes)); + + if (0xFF != address64_data->resource_source.index) { acpi_os_printf (" Resource Source Index: %X\n", address64_data->resource_source.index); acpi_os_printf (" Resource Source: %s\n", diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c index 1297589d79..e49c1e030f 100644 --- a/drivers/acpi/resources/rslist.c +++ b/drivers/acpi/resources/rslist.c @@ -178,6 +178,7 @@ acpi_rs_byte_stream_to_list ( case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE: + case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE: /* * 64-Bit Address Resource */ diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f20d88d3c5..e7ca066265 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -27,6 +27,10 @@ static LIST_HEAD(acpi_device_list); DEFINE_SPINLOCK(acpi_device_lock); LIST_HEAD(acpi_wakeup_device_list); +static int +acpi_bus_trim(struct acpi_device *start, + int rmdevice); + static void acpi_device_release(struct kobject * kobj) { struct acpi_device * dev = container_of(kobj,struct acpi_device,kobj); @@ -81,12 +85,37 @@ static struct kobj_type ktype_acpi_ns = { .release = acpi_device_release, }; +static int namespace_hotplug(struct kset *kset, struct kobject *kobj, + char **envp, int num_envp, char *buffer, + int buffer_size) +{ + struct acpi_device *dev = to_acpi_device(kobj); + int i = 0; + int len = 0; + + if (!dev->driver) + return 0; + + if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len, + "PHYSDEVDRIVER=%s", dev->driver->name)) + return -ENOMEM; + + envp[i] = NULL; + + return 0; +} + +static struct kset_hotplug_ops namespace_hotplug_ops = { + .hotplug = &namespace_hotplug, +}; + static struct kset acpi_namespace_kset = { .kobj = { .name = "namespace", }, .subsys = &acpi_subsys, .ktype = &ktype_acpi_ns, + .hotplug_ops = &namespace_hotplug_ops, }; @@ -358,7 +387,15 @@ setup_sys_fs_device_files ( struct acpi_device *dev, acpi_device_sysfs_files *func) { - if (dev->flags.ejectable == 1) + acpi_status status; + acpi_handle temp = NULL; + + /* + * If device has _EJ0, 'eject' file is created that is used to trigger + * hot-removal function from userland. + */ + status = acpi_get_handle(dev->handle, "_EJ0", &temp); + if (ACPI_SUCCESS(status)) (*(func))(&dev->kobj,&acpi_device_attr_eject.attr); } @@ -857,7 +894,7 @@ static void acpi_device_set_id(struct acpi_device * device, struct acpi_device * acpi_os_free(buffer.pointer); } -int acpi_device_set_context(struct acpi_device * device, int type) +static int acpi_device_set_context(struct acpi_device * device, int type) { acpi_status status = AE_OK; int result = 0; @@ -882,7 +919,7 @@ int acpi_device_set_context(struct acpi_device * device, int type) return result; } -void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle handle, int type) +static void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle handle, int type) { #ifdef CONFIG_ACPI_DEBUG_OUTPUT char *type_string = NULL; @@ -925,7 +962,7 @@ void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle handle, } -int +static int acpi_bus_remove ( struct acpi_device *dev, int rmdevice) @@ -1223,7 +1260,7 @@ int acpi_bus_scan (struct acpi_device *start) EXPORT_SYMBOL(acpi_bus_scan); -int +static int acpi_bus_trim(struct acpi_device *start, int rmdevice) { diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index be97f28695..79c3a686bc 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -774,7 +774,7 @@ acpi_thermal_check ( FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_thermal_dir; +static struct proc_dir_entry *acpi_thermal_dir; static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset) { diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c index c0c9ea1084..c84997c9f9 100644 --- a/drivers/acpi/toshiba_acpi.c +++ b/drivers/acpi/toshiba_acpi.c @@ -481,7 +481,7 @@ read_version(char* p) #define PROC_TOSHIBA "toshiba" -ProcItem proc_items[] = +static ProcItem proc_items[] = { { "lcd" , read_lcd , write_lcd }, { "video" , read_video , write_video }, diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index 0b366d3b48..0fcd98bde0 100644 --- a/drivers/acpi/utilities/utcopy.c +++ b/drivers/acpi/utilities/utcopy.c @@ -659,15 +659,17 @@ acpi_ut_copy_simple_object ( /* Create an actual buffer only if length > 0 */ if (source_desc->buffer.length) { - dest_desc->buffer.pointer = ACPI_MEM_ALLOCATE (source_desc->buffer.length); + dest_desc->buffer.pointer = + ACPI_MEM_ALLOCATE (source_desc->buffer.length); if (!dest_desc->buffer.pointer) { return (AE_NO_MEMORY); } /* Copy the actual buffer data */ - ACPI_MEMCPY (dest_desc->buffer.pointer, source_desc->buffer.pointer, - source_desc->buffer.length); + ACPI_MEMCPY (dest_desc->buffer.pointer, + source_desc->buffer.pointer, + source_desc->buffer.length); } } break; @@ -682,7 +684,8 @@ acpi_ut_copy_simple_object ( */ if ((source_desc->string.pointer) && (!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) { - dest_desc->string.pointer = ACPI_MEM_ALLOCATE ((acpi_size) source_desc->string.length + 1); + dest_desc->string.pointer = + ACPI_MEM_ALLOCATE ((acpi_size) source_desc->string.length + 1); if (!dest_desc->string.pointer) { return (AE_NO_MEMORY); } @@ -692,6 +695,14 @@ acpi_ut_copy_simple_object ( } break; + case ACPI_TYPE_LOCAL_REFERENCE: + /* + * We copied the reference object, so we now must add a reference + * to the object pointed to by the reference + */ + acpi_ut_add_reference (source_desc->reference.object); + break; + default: /* Nothing to do for other simple objects */ break; diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index e8ee13280b..9a52ad52a2 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -46,6 +46,7 @@ #include <acpi/acinterp.h> #include <acpi/acnamesp.h> #include <acpi/acevents.h> +#include <acpi/amlcode.h> #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME ("utdelete") @@ -562,8 +563,23 @@ acpi_ut_update_object_reference ( break; - case ACPI_TYPE_REGION: case ACPI_TYPE_LOCAL_REFERENCE: + + /* + * The target of an Index (a package, string, or buffer) must track + * changes to the ref count of the index. + */ + if (object->reference.opcode == AML_INDEX_OP) { + status = acpi_ut_create_update_state_and_push ( + object->reference.object, action, &state_list); + if (ACPI_FAILURE (status)) { + goto error_exit; + } + } + break; + + + case ACPI_TYPE_REGION: default: /* No subobjects */ diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index d3eb4db38f..25b0f8ae1b 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -194,6 +194,8 @@ const char *acpi_gbl_highest_dstate_names[4] = */ const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = { + /* Operating System Vendor Strings */ + "Linux", "Windows 2000", "Windows 2001", @@ -202,7 +204,11 @@ const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STR "Windows 2001 SP1", "Windows 2001 SP2", "Windows 2001 SP3", - "Windows 2001 SP4" + "Windows 2001 SP4", + + /* Feature Group Strings */ + + "Extended Address Space Descriptor" }; @@ -355,6 +361,7 @@ struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG] /* ACPI_BITREG_SLEEP_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_SLEEP_BUTTON_STATUS, ACPI_BITMASK_SLEEP_BUTTON_STATUS}, /* ACPI_BITREG_RT_CLOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_RT_CLOCK_STATUS, ACPI_BITMASK_RT_CLOCK_STATUS}, /* ACPI_BITREG_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_WAKE_STATUS, ACPI_BITMASK_WAKE_STATUS}, + /* ACPI_BITREG_PCIEXP_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_PCIEXP_WAKE_STATUS, ACPI_BITMASK_PCIEXP_WAKE_STATUS}, /* ACPI_BITREG_TIMER_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_TIMER_ENABLE, ACPI_BITMASK_TIMER_ENABLE}, /* ACPI_BITREG_GLOBAL_LOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_GLOBAL_LOCK_ENABLE, ACPI_BITMASK_GLOBAL_LOCK_ENABLE}, @@ -362,6 +369,7 @@ struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG] /* ACPI_BITREG_SLEEP_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE, ACPI_BITMASK_SLEEP_BUTTON_ENABLE}, /* ACPI_BITREG_RT_CLOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_ENABLE}, /* ACPI_BITREG_WAKE_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, 0, 0}, + /* ACPI_BITREG_PCIEXP_WAKE_DISABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE, ACPI_BITMASK_PCIEXP_WAKE_DISABLE}, /* ACPI_BITREG_SCI_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SCI_ENABLE, ACPI_BITMASK_SCI_ENABLE}, /* ACPI_BITREG_BUS_MASTER_RLD */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_BUS_MASTER_RLD, ACPI_BITMASK_BUS_MASTER_RLD}, diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index 4d32f6d18f..f659854738 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -372,7 +372,7 @@ acpi_ut_strtoul64 ( u32 base, acpi_integer *ret_integer) { - u32 this_digit; + u32 this_digit = 0; acpi_integer return_value = 0; acpi_integer quotient; @@ -380,6 +380,10 @@ acpi_ut_strtoul64 ( ACPI_FUNCTION_TRACE ("ut_stroul64"); + if ((!string) || !(*string)) { + goto error_exit; + } + switch (base) { case ACPI_ANY_BASE: case 10: @@ -394,7 +398,7 @@ acpi_ut_strtoul64 ( /* Skip over any white space in the buffer */ while (ACPI_IS_SPACE (*string) || *string == '\t') { - ++string; + string++; } /* @@ -403,9 +407,9 @@ acpi_ut_strtoul64 ( */ if (base == 0) { if ((*string == '0') && - (ACPI_TOLOWER (*(++string)) == 'x')) { + (ACPI_TOLOWER (*(string + 1)) == 'x')) { base = 16; - ++string; + string += 2; } else { base = 10; @@ -416,10 +420,10 @@ acpi_ut_strtoul64 ( * For hexadecimal base, skip over the leading * 0 or 0x, if they are present. */ - if (base == 16 && - *string == '0' && - ACPI_TOLOWER (*(++string)) == 'x') { - string++; + if ((base == 16) && + (*string == '0') && + (ACPI_TOLOWER (*(string + 1)) == 'x')) { + string += 2; } /* Any string left? */ @@ -437,23 +441,27 @@ acpi_ut_strtoul64 ( this_digit = ((u8) *string) - '0'; } else { + if (base == 10) { + /* Digit is out of range */ + + goto error_exit; + } + this_digit = (u8) ACPI_TOUPPER (*string); - if (ACPI_IS_UPPER ((char) this_digit)) { + if (ACPI_IS_XDIGIT ((char) this_digit)) { /* Convert ASCII Hex char to value */ this_digit = this_digit - 'A' + 10; } else { - goto error_exit; + /* + * We allow non-hex chars, just stop now, same as end-of-string. + * See ACPI spec, string-to-integer conversion. + */ + break; } } - /* Check to see if digit is out of range */ - - if (this_digit >= base) { - goto error_exit; - } - /* Divide the digit into the correct position */ (void) acpi_ut_short_divide ((ACPI_INTEGER_MAX - (acpi_integer) this_digit), @@ -464,9 +472,11 @@ acpi_ut_strtoul64 ( return_value *= base; return_value += this_digit; - ++string; + string++; } + /* All done, normal exit */ + *ret_integer = return_value; return_ACPI_STATUS (AE_OK); diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bd311c2076..71fa101171 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -683,7 +683,7 @@ acpi_video_bus_check ( FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_video_dir; +static struct proc_dir_entry *acpi_video_dir; /* video devices */ diff --git a/drivers/i2c/algos/i2c-algo-ite.c b/drivers/i2c/algos/i2c-algo-ite.c index ffd87404b0..68e9e6832c 100644 --- a/drivers/i2c/algos/i2c-algo-ite.c +++ b/drivers/i2c/algos/i2c-algo-ite.c @@ -713,14 +713,11 @@ static u32 iic_func(struct i2c_adapter *adap) /* -----exported algorithm data: ------------------------------------- */ static struct i2c_algorithm iic_algo = { - "ITE IIC algorithm", - I2C_ALGO_IIC, - iic_xfer, /* master_xfer */ - NULL, /* smbus_xfer */ - NULL, /* slave_xmit */ - NULL, /* slave_recv */ - algo_control, /* ioctl */ - iic_func, /* functionality */ + .name = "ITE IIC algorithm", + .id = I2C_ALGO_IIC, + .master_xfer = iic_xfer, + .algo_control = algo_control, /* ioctl */ + .functionality = iic_func, }; diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c index 66e681cb33..8d087dac32 100644 --- a/drivers/i2c/algos/i2c-algo-pcf.c +++ b/drivers/i2c/algos/i2c-algo-pcf.c @@ -78,7 +78,6 @@ static void i2c_stop(struct i2c_algo_pcf_data *adap) set_pcf(adap, 1, I2C_PCF_STOP); } - static int wait_for_bb(struct i2c_algo_pcf_data *adap) { int timeout = DEF_TIMEOUT; @@ -109,6 +108,26 @@ static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) { adap->waitforpin(); *status = get_pcf(adap, 1); } + if (*status & I2C_PCF_LAB) { + DEB2(printk(KERN_INFO + "i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n", + *status)); + /* Cleanup from LAB-- reset and enable ESO. + * This resets the PCF8584; since we've lost the bus, no + * further attempts should be made by callers to clean up + * (no i2c_stop() etc.) + */ + set_pcf(adap, 1, I2C_PCF_PIN); + set_pcf(adap, 1, I2C_PCF_ESO); + /* TODO: we should pause for a time period sufficient for any + * running I2C transaction to complete-- the arbitration + * logic won't work properly until the next START is seen. + */ + DEB2(printk(KERN_INFO + "i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n", + get_pcf(adap,1))); + return(-EINTR); + } #endif if (timeout <= 0) return(-1); @@ -188,16 +207,22 @@ static inline int try_address(struct i2c_algo_pcf_data *adap, unsigned char addr, int retries) { int i, status, ret = -1; + int wfp; for (i=0;i<retries;i++) { i2c_outb(adap, addr); i2c_start(adap); status = get_pcf(adap, 1); - if (wait_for_pin(adap, &status) >= 0) { + if ((wfp = wait_for_pin(adap, &status)) >= 0) { if ((status & I2C_PCF_LRB) == 0) { i2c_stop(adap); break; /* success! */ } } + if (wfp == -EINTR) { + /* arbitration lost */ + udelay(adap->udelay); + return -EINTR; + } i2c_stop(adap); udelay(adap->udelay); } @@ -219,6 +244,10 @@ static int pcf_sendbytes(struct i2c_adapter *i2c_adap, const char *buf, i2c_outb(adap, buf[wrcount]); timeout = wait_for_pin(adap, &status); if (timeout) { + if (timeout == -EINTR) { + /* arbitration lost */ + return -EINTR; + } i2c_stop(adap); dev_err(&i2c_adap->dev, "i2c_write: error - timeout.\n"); return -EREMOTEIO; /* got a better one ?? */ @@ -247,11 +276,16 @@ static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf, { int i, status; struct i2c_algo_pcf_data *adap = i2c_adap->algo_data; + int wfp; /* increment number of bytes to read by one -- read dummy byte */ for (i = 0; i <= count; i++) { - if (wait_for_pin(adap, &status)) { + if ((wfp = wait_for_pin(adap, &status))) { + if (wfp == -EINTR) { + /* arbitration lost */ + return -EINTR; + } i2c_stop(adap); dev_err(&i2c_adap->dev, "pcf_readbytes timed out.\n"); return (-1); @@ -366,6 +400,10 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap, /* Wait for PIN (pending interrupt NOT) */ timeout = wait_for_pin(adap, &status); if (timeout) { + if (timeout == -EINTR) { + /* arbitration lost */ + return (-EINTR); + } i2c_stop(adap); DEB2(printk(KERN_ERR "i2c-algo-pcf.o: Timeout waiting " "for PIN(1) in pcf_xfer\n");) diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c index ea1a9047a3..35789bb712 100644 --- a/drivers/i2c/algos/i2c-algo-sibyte.c +++ b/drivers/i2c/algos/i2c-algo-sibyte.c @@ -136,14 +136,11 @@ static u32 bit_func(struct i2c_adapter *adap) /* -----exported algorithm data: ------------------------------------- */ static struct i2c_algorithm i2c_sibyte_algo = { - "SiByte algorithm", - I2C_ALGO_SIBYTE, - NULL, /* master_xfer */ - smbus_xfer, /* smbus_xfer */ - NULL, /* slave_xmit */ - NULL, /* slave_recv */ - algo_control, /* ioctl */ - bit_func, /* functionality */ + .name = "SiByte algorithm", + .id = I2C_ALGO_SIBYTE, + .smbus_xfer = smbus_xfer, + .algo_control = algo_control, /* ioctl */ + .functionality = bit_func, }; /* diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 34ff2ecad2..edf8051da3 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -108,7 +108,7 @@ config I2C_HYDRA will be called i2c-hydra. config I2C_I801 - tristate "Intel 801" + tristate "Intel 82801 (ICH)" depends on I2C && PCI && EXPERIMENTAL help If you say yes to this option, support will be included for the Intel @@ -119,7 +119,7 @@ config I2C_I801 82801BA 82801CA/CAM 82801DB - 82801EB + 82801EB/ER (ICH5/ICH5R) 6300ESB ICH6 ICH7 @@ -143,6 +143,23 @@ config I2C_I810 This driver can also be built as a module. If so, the module will be called i2c-i810. +config I2C_PIIX4 + tristate "Intel PIIX4" + depends on I2C && PCI + help + If you say yes to this option, support will be included for the Intel + PIIX4 family of mainboard I2C interfaces. Specifically, the following + versions of the chipset are supported: + Intel PIIX4 + Intel 440MX + Serverworks OSB4 + Serverworks CSB5 + Serverworks CSB6 + SMSC Victory66 + + This driver can also be built as a module. If so, the module + will be called i2c-piix4. + config I2C_IBM_IIC tristate "IBM PPC 4xx on-chip I2C interface" depends on IBM_OCP && I2C @@ -285,23 +302,6 @@ config I2C_PARPORT_LIGHT This support is also available as a module. If so, the module will be called i2c-parport-light. -config I2C_PIIX4 - tristate "Intel PIIX4" - depends on I2C && PCI && EXPERIMENTAL - help - If you say yes to this option, support will be included for the Intel - PIIX4 family of mainboard I2C interfaces. Specifically, the following - versions of the chipset are supported: - Intel PIIX4 - Intel 440MX - Serverworks OSB4 - Serverworks CSB5 - Serverworks CSB6 - SMSC Victory66 - - This driver can also be built as a module. If so, the module - will be called i2c-piix4. - config I2C_PROSAVAGE tristate "S3/VIA (Pro)Savage" depends on I2C && PCI && EXPERIMENTAL diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c index 96fc7d7290..0a7720000a 100644 --- a/drivers/i2c/busses/i2c-elektor.c +++ b/drivers/i2c/busses/i2c-elektor.c @@ -110,22 +110,23 @@ static int pcf_isa_getclock(void *data) } static void pcf_isa_waitforpin(void) { - + DEFINE_WAIT(wait); int timeout = 2; - long flags; + unsigned long flags; if (irq > 0) { spin_lock_irqsave(&lock, flags); if (pcf_pending == 0) { spin_unlock_irqrestore(&lock, flags); - if (interruptible_sleep_on_timeout(&pcf_wait, - timeout*HZ)) { + prepare_to_wait(&pcf_wait, &wait, TASK_INTERRUPTIBLE); + if (schedule_timeout(timeout*HZ)) { spin_lock_irqsave(&lock, flags); if (pcf_pending == 1) { pcf_pending = 0; } spin_unlock_irqrestore(&lock, flags); } + finish_wait(&pcf_wait, &wait); } else { pcf_pending = 0; spin_unlock_irqrestore(&lock, flags); diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 17326cdd68..bb885215c0 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -630,10 +630,6 @@ static struct i2c_algorithm iic_algo = { .name = "IBM IIC algorithm", .id = I2C_ALGO_OCP, .master_xfer = iic_xfer, - .smbus_xfer = NULL, - .slave_send = NULL, - .slave_recv = NULL, - .algo_control = NULL, .functionality = iic_func }; diff --git a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c index 62638115cf..702e3def1b 100644 --- a/drivers/i2c/busses/i2c-ite.c +++ b/drivers/i2c/busses/i2c-ite.c @@ -40,6 +40,7 @@ #include <linux/delay.h> #include <linux/slab.h> #include <linux/init.h> +#include <linux/wait.h> #include <asm/irq.h> #include <asm/io.h> @@ -107,7 +108,7 @@ static int iic_ite_getclock(void *data) * IIC controller interrupts. */ static void iic_ite_waitforpin(void) { - + DEFINE_WAIT(wait); int timeout = 2; long flags; @@ -121,13 +122,15 @@ static void iic_ite_waitforpin(void) { spin_lock_irqsave(&lock, flags); if (iic_pending == 0) { spin_unlock_irqrestore(&lock, flags); - if (interruptible_sleep_on_timeout(&iic_wait, timeout*HZ)) { + prepare_to_wait(&iic_wait, &wait, TASK_INTERRUPTIBLE); + if (schedule_timeout(timeout*HZ)) { spin_lock_irqsave(&lock, flags); if (iic_pending == 1) { iic_pending = 0; } spin_unlock_irqrestore(&lock, flags); } + finish_wait(&iic_wait, &wait); } else { iic_pending = 0; spin_unlock_irqrestore(&lock, flags); diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index db88a12439..5b852782d2 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -525,6 +525,8 @@ mv64xxx_i2c_probe(struct device *dev) drv_data->irq = platform_get_irq(pd, 0); drv_data->adapter.id = I2C_ALGO_MV64XXX | I2C_HW_MV64XXX; drv_data->adapter.algo = &mv64xxx_i2c_algo; + drv_data->adapter.owner = THIS_MODULE; + drv_data->adapter.class = I2C_CLASS_HWMON; drv_data->adapter.timeout = pdata->timeout; drv_data->adapter.retries = pdata->retries; dev_set_drvdata(dev, drv_data); diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 0ac72c935e..fcfa51c143 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -1,6 +1,6 @@ /* linux/drivers/i2c/busses/i2c-s3c2410.c * - * Copyright (C) 2004 Simtec Electronics + * Copyright (C) 2004,2005 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> * * S3C2410 I2C Controller @@ -188,6 +188,9 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, } else stat |= S3C2410_IICSTAT_MASTER_TX; + if (msg->flags & I2C_M_REV_DIR_ADDR) + addr ^= 1; + // todo - check for wether ack wanted or not s3c24xx_i2c_enable_ack(i2c); @@ -287,7 +290,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) !(i2c->msg->flags & I2C_M_IGNORE_NAK)) { /* ack was not received... */ - dev_err(i2c->dev, "ack was not received\n" ); + dev_dbg(i2c->dev, "ack was not received\n"); s3c24xx_i2c_stop(i2c, -EREMOTEIO); goto out_ack; } @@ -555,11 +558,18 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap, return -EREMOTEIO; } +/* declare our i2c functionality */ +static u32 s3c24xx_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING; +} + /* i2c bus registration info */ static struct i2c_algorithm s3c24xx_i2c_algorithm = { .name = "S3C2410-I2C-Algorithm", .master_xfer = s3c24xx_i2c_xfer, + .functionality = s3c24xx_i2c_func, }; static struct s3c24xx_i2c s3c24xx_i2c = { @@ -567,6 +577,7 @@ static struct s3c24xx_i2c s3c24xx_i2c = { .wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait), .adap = { .name = "s3c2410-i2c", + .owner = THIS_MODULE, .algo = &s3c24xx_i2c_algorithm, .retries = 2, .class = I2C_CLASS_HWMON, diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index c872c2849a..0bb60a636e 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c @@ -121,12 +121,12 @@ static int vt596_transaction(void) inb_p(SMBHSTDAT1)); /* Make sure the SMBus host is ready to start transmitting */ - if ((temp = inb_p(SMBHSTSTS)) != 0x00) { + if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). " "Resetting...\n", temp); outb_p(temp, SMBHSTSTS); - if ((temp = inb_p(SMBHSTSTS)) != 0x00) { + if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { dev_dbg(&vt596_adapter.dev, "Failed! (0x%02x)\n", temp); return -1; @@ -168,13 +168,14 @@ static int vt596_transaction(void) dev_dbg(&vt596_adapter.dev, "Error: no response!\n"); } - if (inb_p(SMBHSTSTS) != 0x00) - outb_p(inb(SMBHSTSTS), SMBHSTSTS); - - if ((temp = inb_p(SMBHSTSTS)) != 0x00) { - dev_dbg(&vt596_adapter.dev, "Failed reset at end of " - "transaction (%02x)\n", temp); + if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { + outb_p(temp, SMBHSTSTS); + if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { + dev_warn(&vt596_adapter.dev, "Failed reset at end " + "of transaction (%02x)\n", temp); + } } + dev_dbg(&vt596_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, " "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index 824c62d3a6..74d23cfce2 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig @@ -233,9 +233,23 @@ config SENSORS_LM90 LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657 and MAX6658 sensor chips. + The Analog Devices ADT7461 sensor chip is also supported, but only + if found in ADM1032 compatibility mode. + This driver can also be built as a module. If so, the module will be called lm90. +config SENSORS_LM92 + tristate "National Semiconductor LM92 and compatibles" + depends on I2C && EXPERIMENTAL + select I2C_SENSOR + help + If you say yes here you get support for National Semiconductor LM92 + and Maxim MAX6635 sensor chips. + + This driver can also be built as a module. If so, the module + will be called lm92. + config SENSORS_MAX1619 tristate "Maxim MAX1619 sensor chip" depends on I2C && EXPERIMENTAL @@ -351,6 +365,17 @@ endmenu menu "Other I2C Chip support" depends on I2C +config SENSORS_DS1337 + tristate "Dallas Semiconductor DS1337 Real Time Clock" + depends on I2C && EXPERIMENTAL + select I2C_SENSOR + help + If you say yes here you get support for Dallas Semiconductor + DS1337 real-time clock chips. + + This driver can also be built as a module. If so, the module + will be called ds1337. + config SENSORS_EEPROM tristate "EEPROM reader" depends on I2C && EXPERIMENTAL diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile index a6db6f3947..65599161a1 100644 --- a/drivers/i2c/chips/Makefile +++ b/drivers/i2c/chips/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o +obj-$(CONFIG_SENSORS_DS1337) += ds1337.o obj-$(CONFIG_SENSORS_DS1621) += ds1621.o obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o obj-$(CONFIG_SENSORS_FSCHER) += fscher.o @@ -27,6 +28,7 @@ obj-$(CONFIG_SENSORS_LM83) += lm83.o obj-$(CONFIG_SENSORS_LM85) += lm85.o obj-$(CONFIG_SENSORS_LM87) += lm87.o obj-$(CONFIG_SENSORS_LM90) += lm90.o +obj-$(CONFIG_SENSORS_LM92) += lm92.o obj-$(CONFIG_SENSORS_MAX1619) += max1619.o obj-$(CONFIG_SENSORS_M41T00) += m41t00.o obj-$(CONFIG_SENSORS_PC87360) += pc87360.o diff --git a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c index 5dd7f64fdd..b4e3ee5682 100644 --- a/drivers/i2c/chips/adm1021.c +++ b/drivers/i2c/chips/adm1021.c @@ -28,18 +28,6 @@ #include <linux/i2c-sensor.h> -/* Registers */ -#define ADM1021_SYSCTL_TEMP 1200 -#define ADM1021_SYSCTL_REMOTE_TEMP 1201 -#define ADM1021_SYSCTL_DIE_CODE 1202 -#define ADM1021_SYSCTL_ALARMS 1203 - -#define ADM1021_ALARM_TEMP_HIGH 0x40 -#define ADM1021_ALARM_TEMP_LOW 0x20 -#define ADM1021_ALARM_RTEMP_HIGH 0x10 -#define ADM1021_ALARM_RTEMP_LOW 0x08 -#define ADM1021_ALARM_RTEMP_NA 0x04 - /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, @@ -380,7 +368,7 @@ static struct adm1021_data *adm1021_update_device(struct device *dev) data->remote_temp_input = adm1021_read_value(client, ADM1021_REG_REMOTE_TEMP); data->remote_temp_max = adm1021_read_value(client, ADM1021_REG_REMOTE_TOS_R); data->remote_temp_hyst = adm1021_read_value(client, ADM1021_REG_REMOTE_THYST_R); - data->alarms = adm1021_read_value(client, ADM1021_REG_STATUS) & 0xec; + data->alarms = adm1021_read_value(client, ADM1021_REG_STATUS) & 0x7c; if (data->type == adm1021) data->die_code = adm1021_read_value(client, ADM1021_REG_DIE_CODE); if (data->type == adm1023) { diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c new file mode 100644 index 0000000000..07f16c3fb0 --- /dev/null +++ b/drivers/i2c/chips/ds1337.c @@ -0,0 +1,402 @@ +/* + * linux/drivers/i2c/chips/ds1337.c + * + * Copyright (C) 2005 James Chapman <jchapman@katalix.com> + * + * based on linux/drivers/acron/char/pcf8583.c + * Copyright (C) 2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Driver for Dallas Semiconductor DS1337 real time clock chip + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/i2c-sensor.h> +#include <linux/string.h> +#include <linux/rtc.h> /* get the user-level API */ +#include <linux/bcd.h> +#include <linux/list.h> + +/* Device registers */ +#define DS1337_REG_HOUR 2 +#define DS1337_REG_DAY 3 +#define DS1337_REG_DATE 4 +#define DS1337_REG_MONTH 5 +#define DS1337_REG_CONTROL 14 +#define DS1337_REG_STATUS 15 + +/* FIXME - how do we export these interface constants? */ +#define DS1337_GET_DATE 0 +#define DS1337_SET_DATE 1 + +/* + * Functions declaration + */ +static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END }; +static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; + +SENSORS_INSMOD_1(ds1337); + +static int ds1337_attach_adapter(struct i2c_adapter *adapter); +static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind); +static void ds1337_init_client(struct i2c_client *client); +static int ds1337_detach_client(struct i2c_client *client); +static int ds1337_command(struct i2c_client *client, unsigned int cmd, + void *arg); + +/* + * Driver data (common to all clients) + */ +static struct i2c_driver ds1337_driver = { + .owner = THIS_MODULE, + .name = "ds1337", + .flags = I2C_DF_NOTIFY, + .attach_adapter = ds1337_attach_adapter, + .detach_client = ds1337_detach_client, + .command = ds1337_command, +}; + +/* + * Client data (each client gets its own) + */ +struct ds1337_data { + struct i2c_client client; + struct list_head list; + int id; +}; + +/* + * Internal variables + */ +static int ds1337_id; +static LIST_HEAD(ds1337_clients); + +static inline int ds1337_read(struct i2c_client *client, u8 reg, u8 *value) +{ + s32 tmp = i2c_smbus_read_byte_data(client, reg); + + if (tmp < 0) + return -EIO; + + *value = tmp; + + return 0; +} + +/* + * Chip access functions + */ +static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt) +{ + struct ds1337_data *data = i2c_get_clientdata(client); + int result; + u8 buf[7]; + u8 val; + struct i2c_msg msg[2]; + u8 offs = 0; + + if (!dt) { + dev_dbg(&client->adapter->dev, "%s: EINVAL: dt=NULL\n", + __FUNCTION__); + + return -EINVAL; + } + + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].len = 1; + msg[0].buf = &offs; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].len = sizeof(buf); + msg[1].buf = &buf[0]; + + result = client->adapter->algo->master_xfer(client->adapter, + &msg[0], 2); + + dev_dbg(&client->adapter->dev, + "%s: [%d] %02x %02x %02x %02x %02x %02x %02x\n", + __FUNCTION__, result, buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6]); + + if (result >= 0) { + dt->tm_sec = BCD_TO_BIN(buf[0]); + dt->tm_min = BCD_TO_BIN(buf[1]); + val = buf[2] & 0x3f; + dt->tm_hour = BCD_TO_BIN(val); + dt->tm_wday = BCD_TO_BIN(buf[3]) - 1; + dt->tm_mday = BCD_TO_BIN(buf[4]); + val = buf[5] & 0x7f; + dt->tm_mon = BCD_TO_BIN(val); + dt->tm_year = 1900 + BCD_TO_BIN(buf[6]); + if (buf[5] & 0x80) + dt->tm_year += 100; + + dev_dbg(&client->adapter->dev, "%s: secs=%d, mins=%d, " + "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", + __FUNCTION__, dt->tm_sec, dt->tm_min, + dt->tm_hour, dt->tm_mday, + dt->tm_mon, dt->tm_year, dt->tm_wday); + } else { + dev_err(&client->adapter->dev, "ds1337[%d]: error reading " + "data! %d\n", data->id, result); + result = -EIO; + } + + return result; +} + +static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt) +{ + struct ds1337_data *data = i2c_get_clientdata(client); + int result; + u8 buf[8]; + u8 val; + struct i2c_msg msg[1]; + + if (!dt) { + dev_dbg(&client->adapter->dev, "%s: EINVAL: dt=NULL\n", + __FUNCTION__); + + return -EINVAL; + } + + dev_dbg(&client->adapter->dev, "%s: secs=%d, mins=%d, hours=%d, " + "mday=%d, mon=%d, year=%d, wday=%d\n", __FUNCTION__, + dt->tm_sec, dt->tm_min, dt->tm_hour, + dt->tm_mday, dt->tm_mon, dt->tm_year, dt->tm_wday); + + buf[0] = 0; /* reg offset */ + buf[1] = BIN_TO_BCD(dt->tm_sec); + buf[2] = BIN_TO_BCD(dt->tm_min); + buf[3] = BIN_TO_BCD(dt->tm_hour) | (1 << 6); + buf[4] = BIN_TO_BCD(dt->tm_wday) + 1; + buf[5] = BIN_TO_BCD(dt->tm_mday); + buf[6] = BIN_TO_BCD(dt->tm_mon); + if (dt->tm_year >= 2000) { + val = dt->tm_year - 2000; + buf[6] |= (1 << 7); + } else { + val = dt->tm_year - 1900; + } + buf[7] = BIN_TO_BCD(val); + + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].len = sizeof(buf); + msg[0].buf = &buf[0]; + + result = client->adapter->algo->master_xfer(client->adapter, + &msg[0], 1); + if (result < 0) { + dev_err(&client->adapter->dev, "ds1337[%d]: error " + "writing data! %d\n", data->id, result); + result = -EIO; + } else { + result = 0; + } + + return result; +} + +static int ds1337_command(struct i2c_client *client, unsigned int cmd, + void *arg) +{ + dev_dbg(&client->adapter->dev, "%s: cmd=%d\n", __FUNCTION__, cmd); + + switch (cmd) { + case DS1337_GET_DATE: + return ds1337_get_datetime(client, arg); + + case DS1337_SET_DATE: + return ds1337_set_datetime(client, arg); + + default: + return -EINVAL; + } +} + +/* + * Public API for access to specific device. Useful for low-level + * RTC access from kernel code. + */ +int ds1337_do_command(int id, int cmd, void *arg) +{ + struct list_head *walk; + struct list_head *tmp; + struct ds1337_data *data; + + list_for_each_safe(walk, tmp, &ds1337_clients) { + data = list_entry(walk, struct ds1337_data, list); + if (data->id == id) + return ds1337_command(&data->client, cmd, arg); + } + + return -ENODEV; +} + +static int ds1337_attach_adapter(struct i2c_adapter *adapter) +{ + return i2c_detect(adapter, &addr_data, ds1337_detect); +} + +/* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. + */ +static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *new_client; + struct ds1337_data *data; + int err = 0; + const char *name = ""; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_I2C)) + goto exit; + + if (!(data = kmalloc(sizeof(struct ds1337_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + memset(data, 0, sizeof(struct ds1337_data)); + INIT_LIST_HEAD(&data->list); + + /* The common I2C client data is placed right before the + * DS1337-specific data. + */ + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &ds1337_driver; + new_client->flags = 0; + + /* + * Now we do the remaining detection. A negative kind means that + * the driver was loaded with no force parameter (default), so we + * must both detect and identify the chip. A zero kind means that + * the driver was loaded with the force parameter, the detection + * step shall be skipped. A positive kind means that the driver + * was loaded with the force parameter and a given kind of chip is + * requested, so both the detection and the identification steps + * are skipped. + * + * For detection, we read registers that are most likely to cause + * detection failure, i.e. those that have more bits with fixed + * or reserved values. + */ + + /* Default to an DS1337 if forced */ + if (kind == 0) + kind = ds1337; + + if (kind < 0) { /* detection and identification */ + u8 data; + + /* Check that status register bits 6-2 are zero */ + if ((ds1337_read(new_client, DS1337_REG_STATUS, &data) < 0) || + (data & 0x7c)) + goto exit_free; + + /* Check for a valid day register value */ + if ((ds1337_read(new_client, DS1337_REG_DAY, &data) < 0) || + (data == 0) || (data & 0xf8)) + goto exit_free; + + /* Check for a valid date register value */ + if ((ds1337_read(new_client, DS1337_REG_DATE, &data) < 0) || + (data == 0) || (data & 0xc0) || ((data & 0x0f) > 9) || + (data >= 0x32)) + goto exit_free; + + /* Check for a valid month register value */ + if ((ds1337_read(new_client, DS1337_REG_MONTH, &data) < 0) || + (data == 0) || (data & 0x60) || ((data & 0x0f) > 9) || + ((data >= 0x13) && (data <= 0x19))) + goto exit_free; + + /* Check that control register bits 6-5 are zero */ + if ((ds1337_read(new_client, DS1337_REG_CONTROL, &data) < 0) || + (data & 0x60)) + goto exit_free; + + kind = ds1337; + } + + if (kind == ds1337) + name = "ds1337"; + + /* We can fill in the remaining client fields */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) + goto exit_free; + + /* Initialize the DS1337 chip */ + ds1337_init_client(new_client); + + /* Add client to local list */ + data->id = ds1337_id++; + list_add(&data->list, &ds1337_clients); + + return 0; + +exit_free: + kfree(data); +exit: + return err; +} + +static void ds1337_init_client(struct i2c_client *client) +{ + s32 val; + + /* Ensure that device is set in 24-hour mode */ + val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR); + if ((val >= 0) && (val & (1 << 6)) == 0) + i2c_smbus_write_byte_data(client, DS1337_REG_HOUR, + val | (1 << 6)); +} + +static int ds1337_detach_client(struct i2c_client *client) +{ + int err; + struct ds1337_data *data = i2c_get_clientdata(client); + + if ((err = i2c_detach_client(client))) { + dev_err(&client->dev, "Client deregistration failed, " + "client not detached.\n"); + return err; + } + + list_del(&data->list); + kfree(data); + return 0; +} + +static int __init ds1337_init(void) +{ + return i2c_add_driver(&ds1337_driver); +} + +static void __exit ds1337_exit(void) +{ + i2c_del_driver(&ds1337_driver); +} + +MODULE_AUTHOR("James Chapman <jchapman@katalix.com>"); +MODULE_DESCRIPTION("DS1337 RTC driver"); +MODULE_LICENSE("GPL"); + +module_init(ds1337_init); +module_exit(ds1337_exit); diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index f126d011cf..cbdfa2db6f 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c @@ -210,10 +210,11 @@ int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) if (i2c_smbus_read_byte_data(new_client, 0x80) == 'P' && i2c_smbus_read_byte(new_client) == 'C' && i2c_smbus_read_byte(new_client) == 'G' - && i2c_smbus_read_byte(new_client) == '-') + && i2c_smbus_read_byte(new_client) == '-') { dev_info(&new_client->dev, "Vaio EEPROM detected, " "enabling password protection\n"); data->nature = VAIO; + } } /* create the sysfs eeprom file */ diff --git a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c index e62c2e3900..bf02ba555a 100644 --- a/drivers/i2c/chips/it87.c +++ b/drivers/i2c/chips/it87.c @@ -734,10 +734,9 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind) goto ERROR0; /* Probe whether there is anything available on this address. Already - done for SMBus clients */ + done for SMBus and Super-I/O clients */ if (kind < 0) { - if (is_isa) { - + if (is_isa && !chip_type) { #define REALLY_SLOW_IO /* We need the timeouts for at least some IT87-like chips. But only if we read 'undefined' registers. */ @@ -890,9 +889,9 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind) } if (data->type == it8712) { + data->vrm = i2c_which_vrm(); device_create_file_vrm(new_client); device_create_file_vid(new_client); - data->vrm = i2c_which_vrm(); } return 0; @@ -1123,9 +1122,6 @@ static struct it87_data *it87_update_device(struct device *dev) it87_read_value(client, IT87_REG_TEMP_LOW(i)); } - /* The 8705 does not have VID capability */ - data->vid = 0x1f; - i = it87_read_value(client, IT87_REG_FAN_DIV); data->fan_div[0] = i & 0x07; data->fan_div[1] = (i >> 3) & 0x07; diff --git a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c index d17aba4e42..e08000b948 100644 --- a/drivers/i2c/chips/lm85.c +++ b/drivers/i2c/chips/lm85.c @@ -37,7 +37,7 @@ static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ -SENSORS_INSMOD_5(lm85b, lm85c, adm1027, adt7463, emc6d100); +SENSORS_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102); /* The LM85 registers */ @@ -74,8 +74,10 @@ SENSORS_INSMOD_5(lm85b, lm85c, adm1027, adt7463, emc6d100); #define LM85_VERSTEP_LM85B 0x62 #define LM85_VERSTEP_ADM1027 0x60 #define LM85_VERSTEP_ADT7463 0x62 +#define LM85_VERSTEP_ADT7463C 0x6A #define LM85_VERSTEP_EMC6D100_A0 0x60 #define LM85_VERSTEP_EMC6D100_A1 0x61 +#define LM85_VERSTEP_EMC6D102 0x65 #define LM85_REG_CONFIG 0x40 @@ -112,9 +114,13 @@ SENSORS_INSMOD_5(lm85b, lm85c, adm1027, adt7463, emc6d100); #define EMC6D100_REG_ALARM3 0x7d /* IN5, IN6 and IN7 */ -#define EMC6D100_REG_IN(nr) (0x70 + ((nr)-5)) -#define EMC6D100_REG_IN_MIN(nr) (0x73 + ((nr)-5) * 2) -#define EMC6D100_REG_IN_MAX(nr) (0x74 + ((nr)-5) * 2) +#define EMC6D100_REG_IN(nr) (0x70 + ((nr)-5)) +#define EMC6D100_REG_IN_MIN(nr) (0x73 + ((nr)-5) * 2) +#define EMC6D100_REG_IN_MAX(nr) (0x74 + ((nr)-5) * 2) +#define EMC6D102_REG_EXTEND_ADC1 0x85 +#define EMC6D102_REG_EXTEND_ADC2 0x86 +#define EMC6D102_REG_EXTEND_ADC3 0x87 +#define EMC6D102_REG_EXTEND_ADC4 0x88 #define LM85_ALARM_IN0 0x0001 #define LM85_ALARM_IN1 0x0002 @@ -139,35 +145,36 @@ SENSORS_INSMOD_5(lm85b, lm85c, adm1027, adt7463, emc6d100); these macros are called: arguments may be evaluated more than once. */ -/* IN are scaled 1.000 == 0xc0, mag = 3 */ -#define IN_TO_REG(val) (SENSORS_LIMIT((((val)*0xc0+500)/1000),0,255)) -#define INEXT_FROM_REG(val,ext) (((val)*1000 + (ext)*250 + 96)/0xc0) -#define IN_FROM_REG(val) (INEXT_FROM_REG(val,0)) - /* IN are scaled acording to built-in resistors */ static int lm85_scaling[] = { /* .001 Volts */ 2500, 2250, 3300, 5000, 12000, 3300, 1500, 1800 /*EMC6D100*/ }; #define SCALE(val,from,to) (((val)*(to) + ((from)/2))/(from)) -#define INS_TO_REG(n,val) (SENSORS_LIMIT(SCALE(val,lm85_scaling[n],192),0,255)) -#define INSEXT_FROM_REG(n,val,ext) (SCALE((val)*4 + (ext),192*4,lm85_scaling[n])) -#define INS_FROM_REG(n,val) (INSEXT_FROM_REG(n,val,0)) + +#define INS_TO_REG(n,val) \ + SENSORS_LIMIT(SCALE(val,lm85_scaling[n],192),0,255) + +#define INSEXT_FROM_REG(n,val,ext,scale) \ + SCALE((val)*(scale) + (ext),192*(scale),lm85_scaling[n]) + +#define INS_FROM_REG(n,val) INSEXT_FROM_REG(n,val,0,1) /* FAN speed is measured using 90kHz clock */ #define FAN_TO_REG(val) (SENSORS_LIMIT( (val)<=0?0: 5400000/(val),0,65534)) #define FAN_FROM_REG(val) ((val)==0?-1:(val)==0xffff?0:5400000/(val)) /* Temperature is reported in .001 degC increments */ -#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)+500)/1000,-127,127)) -#define TEMPEXT_FROM_REG(val,ext) ((val)*1000 + (ext)*250) -#define TEMP_FROM_REG(val) (TEMPEXT_FROM_REG(val,0)) -#define EXTTEMP_TO_REG(val) (SENSORS_LIMIT((val)/250,-127,127)) +#define TEMP_TO_REG(val) \ + SENSORS_LIMIT(SCALE(val,1000,1),-127,127) +#define TEMPEXT_FROM_REG(val,ext,scale) \ + SCALE((val)*scale + (ext),scale,1000) +#define TEMP_FROM_REG(val) \ + TEMPEXT_FROM_REG(val,0,1) #define PWM_TO_REG(val) (SENSORS_LIMIT(val,0,255)) #define PWM_FROM_REG(val) (val) -#define EXT_FROM_REG(val,sensor) (((val)>>(sensor * 2))&0x03) /* ZONEs have the following parameters: * Limit (low) temp, 1. degC @@ -355,7 +362,9 @@ struct lm85_data { u8 pwm[3]; /* Register value */ u8 spinup_ctl; /* Register encoding, combined */ u8 tach_mode; /* Register encoding, combined */ - u16 extend_adc; /* Register value */ + u8 temp_ext[3]; /* Decoded values */ + u8 in_ext[8]; /* Decoded values */ + u8 adc_scale; /* ADC Extended bits scaling factor */ u8 fan_ppr; /* Register value */ u8 smooth[3]; /* Register encoding */ u8 vid; /* Register value */ @@ -536,7 +545,10 @@ show_pwm_reg(3); static ssize_t show_in(struct device *dev, char *buf, int nr) { struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in[nr]) ); + return sprintf( buf, "%d\n", INSEXT_FROM_REG(nr, + data->in[nr], + data->in_ext[nr], + data->adc_scale) ); } static ssize_t show_in_min(struct device *dev, char *buf, int nr) { @@ -617,7 +629,9 @@ show_in_reg(4); static ssize_t show_temp(struct device *dev, char *buf, int nr) { struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp[nr]) ); + return sprintf(buf,"%d\n", TEMPEXT_FROM_REG(data->temp[nr], + data->temp_ext[nr], + data->adc_scale) ); } static ssize_t show_temp_min(struct device *dev, char *buf, int nr) { @@ -1089,7 +1103,8 @@ int lm85_detect(struct i2c_adapter *adapter, int address, && verstep == LM85_VERSTEP_ADM1027 ) { kind = adm1027 ; } else if( company == LM85_COMPANY_ANALOG_DEV - && verstep == LM85_VERSTEP_ADT7463 ) { + && (verstep == LM85_VERSTEP_ADT7463 + || verstep == LM85_VERSTEP_ADT7463C) ) { kind = adt7463 ; } else if( company == LM85_COMPANY_ANALOG_DEV && (verstep & LM85_VERSTEP_VMASK) == LM85_VERSTEP_GENERIC ) { @@ -1107,6 +1122,9 @@ int lm85_detect(struct i2c_adapter *adapter, int address, */ kind = emc6d100 ; } else if( company == LM85_COMPANY_SMSC + && verstep == LM85_VERSTEP_EMC6D102) { + kind = emc6d102 ; + } else if( company == LM85_COMPANY_SMSC && (verstep & LM85_VERSTEP_VMASK) == LM85_VERSTEP_GENERIC) { dev_err(&adapter->dev, "lm85: Detected SMSC chip\n"); dev_err(&adapter->dev, "lm85: Unrecognized version/stepping 0x%02x" @@ -1142,6 +1160,8 @@ int lm85_detect(struct i2c_adapter *adapter, int address, type_name = "adt7463"; } else if ( kind == emc6d100){ type_name = "emc6d100"; + } else if ( kind == emc6d102 ) { + type_name = "emc6d102"; } strlcpy(new_client->name, type_name, I2C_NAME_SIZE); @@ -1259,7 +1279,6 @@ int lm85_read_value(struct i2c_client *client, u8 reg) case LM85_REG_FAN_MIN(2) : case LM85_REG_FAN_MIN(3) : case LM85_REG_ALARM1 : /* Read both bytes at once */ - case ADM1027_REG_EXTEND_ADC1 : /* Read two bytes at once */ res = i2c_smbus_read_byte_data(client, reg) & 0xff ; res |= i2c_smbus_read_byte_data(client, reg+1) << 8 ; break ; @@ -1363,10 +1382,25 @@ static struct lm85_data *lm85_update_device(struct device *dev) * more significant bits that are read later. */ if ( (data->type == adm1027) || (data->type == adt7463) ) { - data->extend_adc = - lm85_read_value(client, ADM1027_REG_EXTEND_ADC1); + int ext1 = lm85_read_value(client, + ADM1027_REG_EXTEND_ADC1); + int ext2 = lm85_read_value(client, + ADM1027_REG_EXTEND_ADC2); + int val = (ext1 << 8) + ext2; + + for(i = 0; i <= 4; i++) + data->in_ext[i] = (val>>(i * 2))&0x03; + + for(i = 0; i <= 2; i++) + data->temp_ext[i] = (val>>((i + 5) * 2))&0x03; } + /* adc_scale is 2^(number of LSBs). There are 4 extra bits in + the emc6d102 and 2 in the adt7463 and adm1027. In all + other chips ext is always 0 and the value of scale is + irrelevant. So it is left in 4*/ + data->adc_scale = (data->type == emc6d102 ) ? 16 : 4; + for (i = 0; i <= 4; ++i) { data->in[i] = lm85_read_value(client, LM85_REG_IN(i)); @@ -1403,6 +1437,28 @@ static struct lm85_data *lm85_update_device(struct device *dev) /* More alarm bits */ data->alarms |= lm85_read_value(client, EMC6D100_REG_ALARM3) << 16; + } else if (data->type == emc6d102 ) { + /* Have to read LSB bits after the MSB ones because + the reading of the MSB bits has frozen the + LSBs (backward from the ADM1027). + */ + int ext1 = lm85_read_value(client, + EMC6D102_REG_EXTEND_ADC1); + int ext2 = lm85_read_value(client, + EMC6D102_REG_EXTEND_ADC2); + int ext3 = lm85_read_value(client, + EMC6D102_REG_EXTEND_ADC3); + int ext4 = lm85_read_value(client, + EMC6D102_REG_EXTEND_ADC4); + data->in_ext[0] = ext3 & 0x0f; + data->in_ext[1] = ext4 & 0x0f; + data->in_ext[2] = (ext4 >> 4) & 0x0f; + data->in_ext[3] = (ext3 >> 4) & 0x0f; + data->in_ext[4] = (ext2 >> 4) & 0x0f; + + data->temp_ext[0] = ext1 & 0x0f; + data->temp_ext[1] = ext2 & 0x0f; + data->temp_ext[2] = (ext1 >> 4) & 0x0f; } data->last_reading = jiffies ; diff --git a/drivers/i2c/chips/lm87.c b/drivers/i2c/chips/lm87.c index 8b9e2de21b..49d92326fa 100644 --- a/drivers/i2c/chips/lm87.c +++ b/drivers/i2c/chips/lm87.c @@ -317,20 +317,20 @@ show_temp(3); static void set_temp_low(struct device *dev, const char *buf, int nr) { - struct i2c_client *client = to_i2c_client(dev); - struct lm87_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - data->temp_low[nr] = TEMP_TO_REG(val); - lm87_write_value(client, LM87_REG_TEMP_LOW[nr], data->temp_low[nr]); + struct i2c_client *client = to_i2c_client(dev); + struct lm87_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + data->temp_low[nr] = TEMP_TO_REG(val); + lm87_write_value(client, LM87_REG_TEMP_LOW[nr], data->temp_low[nr]); } static void set_temp_high(struct device *dev, const char *buf, int nr) { - struct i2c_client *client = to_i2c_client(dev); - struct lm87_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - data->temp_high[nr] = TEMP_TO_REG(val); - lm87_write_value(client, LM87_REG_TEMP_HIGH[nr], data->temp_high[nr]); + struct i2c_client *client = to_i2c_client(dev); + struct lm87_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + data->temp_high[nr] = TEMP_TO_REG(val); + lm87_write_value(client, LM87_REG_TEMP_HIGH[nr], data->temp_high[nr]); } #define set_temp(offset) \ diff --git a/drivers/i2c/chips/lm90.c b/drivers/i2c/chips/lm90.c index 7540b23017..02e22b128b 100644 --- a/drivers/i2c/chips/lm90.c +++ b/drivers/i2c/chips/lm90.c @@ -43,6 +43,14 @@ * variants. The extra address and features of the MAX6659 are not * supported by this driver. * + * This driver also supports the ADT7461 chip from Analog Devices but + * only in its "compatability mode". If an ADT7461 chip is found but + * is configured in non-compatible mode (where its temperature + * register values are decoded differently) it is ignored by this + * driver. Complete datasheet can be obtained from Analog's website + * at: + * http://products.analog.com/products/info.asp?product=ADT7461 + * * Since the LM90 was the first chipset supported by this driver, most * comments will refer to this chipset, but are actually general and * concern all supported chipsets, unless mentioned otherwise. @@ -77,6 +85,7 @@ * LM86, LM89, LM90, LM99, ADM1032, MAX6657 and MAX6658 have address 0x4c. * LM89-1, and LM99-1 have address 0x4d. * MAX6659 can have address 0x4c, 0x4d or 0x4e (unsupported). + * ADT7461 always has address 0x4c. */ static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END }; @@ -86,7 +95,7 @@ static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; * Insmod parameters */ -SENSORS_INSMOD_5(lm90, adm1032, lm99, lm86, max6657); +SENSORS_INSMOD_6(lm90, adm1032, lm99, lm86, max6657, adt7461); /* * The LM90 registers @@ -148,6 +157,19 @@ SENSORS_INSMOD_5(lm90, adm1032, lm99, lm86, max6657); #define HYST_TO_REG(val) ((val) <= 0 ? 0 : (val) >= 30500 ? 31 : \ ((val) + 500) / 1000) +/* + * ADT7461 is almost identical to LM90 except that attempts to write + * values that are outside the range 0 < temp < 127 are treated as + * the boundary value. + */ + +#define TEMP1_TO_REG_ADT7461(val) ((val) <= 0 ? 0 : \ + (val) >= 127000 ? 127 : \ + ((val) + 500) / 1000) +#define TEMP2_TO_REG_ADT7461(val) ((val) <= 0 ? 0 : \ + (val) >= 127750 ? 0x7FC0 : \ + ((val) + 125) / 250 * 64) + /* * Functions declaration */ @@ -181,6 +203,7 @@ struct lm90_data { struct semaphore update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ + int kind; /* registers values */ s8 temp_input1, temp_low1, temp_high1; /* local */ @@ -216,7 +239,10 @@ static ssize_t set_##value(struct device *dev, const char *buf, \ struct i2c_client *client = to_i2c_client(dev); \ struct lm90_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ - data->value = TEMP1_TO_REG(val); \ + if (data->kind == adt7461) \ + data->value = TEMP1_TO_REG_ADT7461(val); \ + else \ + data->value = TEMP1_TO_REG(val); \ i2c_smbus_write_byte_data(client, reg, data->value); \ return count; \ } @@ -227,7 +253,10 @@ static ssize_t set_##value(struct device *dev, const char *buf, \ struct i2c_client *client = to_i2c_client(dev); \ struct lm90_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ - data->value = TEMP2_TO_REG(val); \ + if (data->kind == adt7461) \ + data->value = TEMP2_TO_REG_ADT7461(val); \ + else \ + data->value = TEMP2_TO_REG(val); \ i2c_smbus_write_byte_data(client, regh, data->value >> 8); \ i2c_smbus_write_byte_data(client, regl, data->value & 0xff); \ return count; \ @@ -381,6 +410,12 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) && (reg_config1 & 0x3F) == 0x00 && reg_convrate <= 0x0A) { kind = adm1032; + } else + if (address == 0x4c + && chip_id == 0x51 /* ADT7461 */ + && (reg_config1 & 0x1F) == 0x00 /* check compat mode */ + && reg_convrate <= 0x0A) { + kind = adt7461; } } else if (man_id == 0x4D) { /* Maxim */ @@ -418,11 +453,14 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) name = "lm86"; } else if (kind == max6657) { name = "max6657"; + } else if (kind == adt7461) { + name = "adt7461"; } /* We can fill in the remaining client fields */ strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; + data->kind = kind; init_MUTEX(&data->update_lock); /* Tell the I2C layer a new client has arrived */ diff --git a/drivers/i2c/chips/lm92.c b/drivers/i2c/chips/lm92.c new file mode 100644 index 0000000000..3c9d0ef8ec --- /dev/null +++ b/drivers/i2c/chips/lm92.c @@ -0,0 +1,423 @@ +/* + * lm92 - Hardware monitoring driver + * Copyright (C) 2005 Jean Delvare <khali@linux-fr.org> + * + * Based on the lm90 driver, with some ideas taken from the lm_sensors + * lm92 driver as well. + * + * The LM92 is a sensor chip made by National Semiconductor. It reports + * its own temperature with a 0.0625 deg resolution and a 0.33 deg + * accuracy. Complete datasheet can be obtained from National's website + * at: + * http://www.national.com/pf/LM/LM92.html + * + * This driver also supports the MAX6635 sensor chip made by Maxim. + * This chip is compatible with the LM92, but has a lesser accuracy + * (1.0 deg). Complete datasheet can be obtained from Maxim's website + * at: + * http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3074 + * + * Since the LM92 was the first chipset supported by this driver, most + * comments will refer to this chipset, but are actually general and + * concern all supported chipsets, unless mentioned otherwise. + * + * Support could easily be added for the National Semiconductor LM76 + * and Maxim MAX6633 and MAX6634 chips, which are mostly compatible + * with the LM92. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/i2c-sensor.h> + + +/* The LM92 and MAX6635 have 2 two-state pins for address selection, + resulting in 4 possible addresses. */ +static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, + I2C_CLIENT_END }; +static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; + +/* Insmod parameters */ +SENSORS_INSMOD_1(lm92); + +/* The LM92 registers */ +#define LM92_REG_CONFIG 0x01 /* 8-bit, RW */ +#define LM92_REG_TEMP 0x00 /* 16-bit, RO */ +#define LM92_REG_TEMP_HYST 0x02 /* 16-bit, RW */ +#define LM92_REG_TEMP_CRIT 0x03 /* 16-bit, RW */ +#define LM92_REG_TEMP_LOW 0x04 /* 16-bit, RW */ +#define LM92_REG_TEMP_HIGH 0x05 /* 16-bit, RW */ +#define LM92_REG_MAN_ID 0x07 /* 16-bit, RO, LM92 only */ + +/* The LM92 uses signed 13-bit values with LSB = 0.0625 degree Celsius, + left-justified in 16-bit registers. No rounding is done, with such + a resolution it's just not worth it. Note that the MAX6635 doesn't + make use of the 4 lower bits for limits (i.e. effective resolution + for limits is 1 degree Celsius). */ +static inline int TEMP_FROM_REG(s16 reg) +{ + return reg / 8 * 625 / 10; +} + +static inline s16 TEMP_TO_REG(int val) +{ + if (val <= -60000) + return -60000 * 10 / 625 * 8; + if (val >= 160000) + return 160000 * 10 / 625 * 8; + return val * 10 / 625 * 8; +} + +/* Alarm flags are stored in the 3 LSB of the temperature register */ +static inline u8 ALARMS_FROM_REG(s16 reg) +{ + return reg & 0x0007; +} + +/* Driver data (common to all clients) */ +static struct i2c_driver lm92_driver; + +/* Client data (each client gets its own) */ +struct lm92_data { + struct i2c_client client; + struct semaphore update_lock; + char valid; /* zero until following fields are valid */ + unsigned long last_updated; /* in jiffies */ + + /* registers values */ + s16 temp1_input, temp1_crit, temp1_min, temp1_max, temp1_hyst; +}; + + +/* + * Sysfs attributes and callback functions + */ + +static struct lm92_data *lm92_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm92_data *data = i2c_get_clientdata(client); + + down(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ) + || !data->valid) { + dev_dbg(&client->dev, "Updating lm92 data\n"); + data->temp1_input = swab16(i2c_smbus_read_word_data(client, + LM92_REG_TEMP)); + data->temp1_hyst = swab16(i2c_smbus_read_word_data(client, + LM92_REG_TEMP_HYST)); + data->temp1_crit = swab16(i2c_smbus_read_word_data(client, + LM92_REG_TEMP_CRIT)); + data->temp1_min = swab16(i2c_smbus_read_word_data(client, + LM92_REG_TEMP_LOW)); + data->temp1_max = swab16(i2c_smbus_read_word_data(client, + LM92_REG_TEMP_HIGH)); + + data->last_updated = jiffies; + data->valid = 1; + } + + up(&data->update_lock); + + return data; +} + +#define show_temp(value) \ +static ssize_t show_##value(struct device *dev, char *buf) \ +{ \ + struct lm92_data *data = lm92_update_device(dev); \ + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \ +} +show_temp(temp1_input); +show_temp(temp1_crit); +show_temp(temp1_min); +show_temp(temp1_max); + +#define set_temp(value, reg) \ +static ssize_t set_##value(struct device *dev, const char *buf, \ + size_t count) \ +{ \ + struct i2c_client *client = to_i2c_client(dev); \ + struct lm92_data *data = i2c_get_clientdata(client); \ + long val = simple_strtol(buf, NULL, 10); \ + data->value = TEMP_TO_REG(val); \ + i2c_smbus_write_word_data(client, reg, swab16(data->value)); \ + return count; \ +} +set_temp(temp1_crit, LM92_REG_TEMP_CRIT); +set_temp(temp1_min, LM92_REG_TEMP_LOW); +set_temp(temp1_max, LM92_REG_TEMP_HIGH); + +static ssize_t show_temp1_crit_hyst(struct device *dev, char *buf) +{ + struct lm92_data *data = lm92_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_crit) + - TEMP_FROM_REG(data->temp1_hyst)); +} +static ssize_t show_temp1_max_hyst(struct device *dev, char *buf) +{ + struct lm92_data *data = lm92_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_max) + - TEMP_FROM_REG(data->temp1_hyst)); +} +static ssize_t show_temp1_min_hyst(struct device *dev, char *buf) +{ + struct lm92_data *data = lm92_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_min) + + TEMP_FROM_REG(data->temp1_hyst)); +} + +static ssize_t set_temp1_crit_hyst(struct device *dev, const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm92_data *data = i2c_get_clientdata(client); + data->temp1_hyst = TEMP_FROM_REG(data->temp1_crit) - + simple_strtol(buf, NULL, 10); + i2c_smbus_write_word_data(client, LM92_REG_TEMP_HYST, + swab16(TEMP_TO_REG(data->temp1_hyst))); + return count; +} + +static ssize_t show_alarms(struct device *dev, char *buf) +{ + struct lm92_data *data = lm92_update_device(dev); + return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->temp1_input)); +} + +static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1_input, NULL); +static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp1_crit, + set_temp1_crit); +static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp1_crit_hyst, + set_temp1_crit_hyst); +static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp1_min, + set_temp1_min); +static DEVICE_ATTR(temp1_min_hyst, S_IRUGO, show_temp1_min_hyst, NULL); +static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp1_max, + set_temp1_max); +static DEVICE_ATTR(temp1_max_hyst, S_IRUGO, show_temp1_max_hyst, NULL); +static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); + + +/* + * Detection and registration + */ + +static void lm92_init_client(struct i2c_client *client) +{ + u8 config; + + /* Start the conversions if needed */ + config = i2c_smbus_read_byte_data(client, LM92_REG_CONFIG); + if (config & 0x01) + i2c_smbus_write_byte_data(client, LM92_REG_CONFIG, + config & 0xFE); +} + +/* The MAX6635 has no identification register, so we have to use tricks + to identify it reliably. This is somewhat slow. + Note that we do NOT rely on the 2 MSB of the configuration register + always reading 0, as suggested by the datasheet, because it was once + reported not to be true. */ +static int max6635_check(struct i2c_client *client) +{ + u16 temp_low, temp_high, temp_hyst, temp_crit; + u8 conf; + int i; + + /* No manufacturer ID register, so a read from this address will + always return the last read value. */ + temp_low = i2c_smbus_read_word_data(client, LM92_REG_TEMP_LOW); + if (i2c_smbus_read_word_data(client, LM92_REG_MAN_ID) != temp_low) + return 0; + temp_high = i2c_smbus_read_word_data(client, LM92_REG_TEMP_HIGH); + if (i2c_smbus_read_word_data(client, LM92_REG_MAN_ID) != temp_high) + return 0; + + /* Limits are stored as integer values (signed, 9-bit). */ + if ((temp_low & 0x7f00) || (temp_high & 0x7f00)) + return 0; + temp_hyst = i2c_smbus_read_word_data(client, LM92_REG_TEMP_HYST); + temp_crit = i2c_smbus_read_word_data(client, LM92_REG_TEMP_CRIT); + if ((temp_hyst & 0x7f00) || (temp_crit & 0x7f00)) + return 0; + + /* Registers addresses were found to cycle over 16-byte boundaries. + We don't test all registers with all offsets so as to save some + reads and time, but this should still be sufficient to dismiss + non-MAX6635 chips. */ + conf = i2c_smbus_read_byte_data(client, LM92_REG_CONFIG); + for (i=16; i<96; i*=2) { + if (temp_hyst != i2c_smbus_read_word_data(client, + LM92_REG_TEMP_HYST + i - 16) + || temp_crit != i2c_smbus_read_word_data(client, + LM92_REG_TEMP_CRIT + i) + || temp_low != i2c_smbus_read_word_data(client, + LM92_REG_TEMP_LOW + i + 16) + || temp_high != i2c_smbus_read_word_data(client, + LM92_REG_TEMP_HIGH + i + 32) + || conf != i2c_smbus_read_byte_data(client, + LM92_REG_CONFIG + i)) + return 0; + } + + return 1; +} + +/* The following function does more than just detection. If detection + succeeds, it also registers the new chip. */ +static int lm92_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *new_client; + struct lm92_data *data; + int err = 0; + char *name; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA + | I2C_FUNC_SMBUS_WORD_DATA)) + goto exit; + + if (!(data = kmalloc(sizeof(struct lm92_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + memset(data, 0, sizeof(struct lm92_data)); + + /* Fill in enough client fields so that we can read from the chip, + which is required for identication */ + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &lm92_driver; + new_client->flags = 0; + + /* A negative kind means that the driver was loaded with no force + parameter (default), so we must identify the chip. */ + if (kind < 0) { + u8 config = i2c_smbus_read_byte_data(new_client, + LM92_REG_CONFIG); + u16 man_id = i2c_smbus_read_word_data(new_client, + LM92_REG_MAN_ID); + + if ((config & 0xe0) == 0x00 + && man_id == 0x0180) { + pr_info("lm92: Found National Semiconductor LM92 chip\n"); + kind = lm92; + } else + if (max6635_check(new_client)) { + pr_info("lm92: Found Maxim MAX6635 chip\n"); + kind = lm92; /* No separate prefix */ + } + else + goto exit_free; + } else + if (kind == 0) /* Default to an LM92 if forced */ + kind = lm92; + + /* Give it the proper name */ + if (kind == lm92) { + name = "lm92"; + } else { /* Supposedly cannot happen */ + dev_dbg(&new_client->dev, "Kind out of range?\n"); + goto exit_free; + } + + /* Fill in the remaining client fields */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); + data->valid = 0; + init_MUTEX(&data->update_lock); + + /* Tell the i2c subsystem a new client has arrived */ + if ((err = i2c_attach_client(new_client))) + goto exit_free; + + /* Initialize the chipset */ + lm92_init_client(new_client); + + /* Register sysfs hooks */ + device_create_file(&new_client->dev, &dev_attr_temp1_input); + device_create_file(&new_client->dev, &dev_attr_temp1_crit); + device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst); + device_create_file(&new_client->dev, &dev_attr_temp1_min); + device_create_file(&new_client->dev, &dev_attr_temp1_min_hyst); + device_create_file(&new_client->dev, &dev_attr_temp1_max); + device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst); + device_create_file(&new_client->dev, &dev_attr_alarms); + + return 0; + +exit_free: + kfree(data); +exit: + return err; +} + +static int lm92_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_detect(adapter, &addr_data, lm92_detect); +} + +static int lm92_detach_client(struct i2c_client *client) +{ + int err; + + if ((err = i2c_detach_client(client))) { + dev_err(&client->dev, "Client deregistration failed, " + "client not detached.\n"); + return err; + } + + kfree(i2c_get_clientdata(client)); + return 0; +} + + +/* + * Module and driver stuff + */ + +static struct i2c_driver lm92_driver = { + .owner = THIS_MODULE, + .name = "lm92", + .id = I2C_DRIVERID_LM92, + .flags = I2C_DF_NOTIFY, + .attach_adapter = lm92_attach_adapter, + .detach_client = lm92_detach_client, +}; + +static int __init sensors_lm92_init(void) +{ + return i2c_add_driver(&lm92_driver); +} + +static void __exit sensors_lm92_exit(void) +{ + i2c_del_driver(&lm92_driver); +} + +MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); +MODULE_DESCRIPTION("LM92/MAX6635 driver"); +MODULE_LICENSE("GPL"); + +module_init(sensors_lm92_init); +module_exit(sensors_lm92_exit); diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c index de270e9202..e771566dff 100644 --- a/drivers/i2c/chips/m41t00.c +++ b/drivers/i2c/chips/m41t00.c @@ -184,7 +184,6 @@ m41t00_probe(struct i2c_adapter *adap, int addr, int kind) memset(client, 0, sizeof(struct i2c_client)); strncpy(client->name, M41T00_DRV_NAME, I2C_NAME_SIZE); - client->id = m41t00_driver.id; client->flags = I2C_DF_NOTIFY; client->addr = addr; client->adapter = adap; diff --git a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c index 986dba3f0a..133e449dc1 100644 --- a/drivers/i2c/chips/w83627hf.c +++ b/drivers/i2c/chips/w83627hf.c @@ -304,7 +304,6 @@ struct w83627hf_data { u32 beep_mask; /* Register encoding, combined */ u8 beep_enable; /* Boolean */ u8 pwm[3]; /* Register value */ - u8 pwmenable[3]; /* bool */ u16 sens[3]; /* 782D/783S only. 1 = pentium diode; 2 = 3904 diode; 3000-5000 = thermistor beta. @@ -1317,10 +1316,6 @@ static void w83627hf_init_client(struct i2c_client *client) break; } - data->pwmenable[0] = 1; - data->pwmenable[1] = 1; - data->pwmenable[2] = 1; - if(init) { /* Enable temp2 */ tmp = w83627hf_read_value(client, W83781D_REG_TEMP2_CONFIG); diff --git a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c index e893229239..628d769cf4 100644 --- a/drivers/i2c/chips/w83781d.c +++ b/drivers/i2c/chips/w83781d.c @@ -46,9 +46,6 @@ #include <asm/io.h> #include "lm75.h" -/* RT Table support #defined so we can take it out if it gets bothersome */ -#define W83781D_RT 1 - /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, @@ -258,9 +255,6 @@ struct w83781d_data { 3000-5000 = thermistor beta. Default = 3435. Other Betas unimplemented */ -#ifdef W83781D_RT - u8 rt[3][32]; /* Register value */ -#endif u8 vrm; }; @@ -834,66 +828,6 @@ do { \ device_create_file(&client->dev, &dev_attr_temp##offset##_type); \ } while (0) -#ifdef W83781D_RT -static ssize_t -show_rt_reg(struct device *dev, char *buf, int nr) -{ - struct w83781d_data *data = w83781d_update_device(dev); - int i, j = 0; - - for (i = 0; i < 32; i++) { - if (i > 0) - j += sprintf(buf, " %ld", (long) data->rt[nr - 1][i]); - else - j += sprintf(buf, "%ld", (long) data->rt[nr - 1][i]); - } - j += sprintf(buf, "\n"); - - return j; -} - -static ssize_t -store_rt_reg(struct device *dev, const char *buf, size_t count, int nr) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83781d_data *data = i2c_get_clientdata(client); - u32 val, i; - - for (i = 0; i < count; i++) { - val = simple_strtoul(buf + count, NULL, 10); - - /* fixme: no bounds checking 0-255 */ - data->rt[nr - 1][i] = val & 0xff; - w83781d_write_value(client, W83781D_REG_RT_IDX, i); - w83781d_write_value(client, W83781D_REG_RT_VAL, - data->rt[nr - 1][i]); - } - - return count; -} - -#define sysfs_rt(offset) \ -static ssize_t show_regs_rt_##offset (struct device *dev, char *buf) \ -{ \ - return show_rt_reg(dev, buf, offset); \ -} \ -static ssize_t store_regs_rt_##offset (struct device *dev, const char *buf, size_t count) \ -{ \ - return store_rt_reg(dev, buf, count, offset); \ -} \ -static DEVICE_ATTR(rt##offset, S_IRUGO | S_IWUSR, show_regs_rt_##offset, store_regs_rt_##offset); - -sysfs_rt(1); -sysfs_rt(2); -sysfs_rt(3); - -#define device_create_file_rt(client, offset) \ -do { \ -device_create_file(&client->dev, &dev_attr_rt##offset); \ -} while (0) - -#endif /* ifdef W83781D_RT */ - /* This function is called when: * w83781d_driver is inserted (when this module is loaded), for each available adapter @@ -1304,13 +1238,6 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) if (kind != w83783s && kind != w83697hf) device_create_file_sensor(new_client, 3); } -#ifdef W83781D_RT - if (kind == w83781d) { - device_create_file_rt(new_client, 1); - device_create_file_rt(new_client, 2); - device_create_file_rt(new_client, 3); - } -#endif return 0; @@ -1535,33 +1462,6 @@ w83781d_init_client(struct i2c_client *client) break; } } -#ifdef W83781D_RT -/* - Fill up the RT Tables. - We assume that they are 32 bytes long, in order for temp 1-3. - Data sheet documentation is sparse. - We also assume that it is only for the 781D although I suspect - that the others support it as well.... -*/ - - if (init && type == w83781d) { - u16 k = 0; -/* - Auto-indexing doesn't seem to work... - w83781d_write_value(client,W83781D_REG_RT_IDX,0); -*/ - for (i = 0; i < 3; i++) { - int j; - for (j = 0; j < 32; j++) { - w83781d_write_value(client, - W83781D_REG_RT_IDX, k++); - data->rt[i][j] = - w83781d_read_value(client, - W83781D_REG_RT_VAL); - } - } - } -#endif /* W83781D_RT */ if (init && type != as99127f) { /* Enable temp2 */ diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 56a6745734..e62a91a45a 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -587,7 +587,13 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) int ret; if (adap->algo->master_xfer) { - dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n", num); +#ifdef DEBUG + for (ret = 0; ret < num; ret++) { + dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, " + "len=%d\n", ret, msgs[ret].flags & I2C_M_RD ? + 'R' : 'W', msgs[ret].addr, msgs[ret].len); + } +#endif down(&adap->bus_lock); ret = adap->algo->master_xfer(adap,msgs,num); @@ -709,7 +715,7 @@ int i2c_probe(struct i2c_adapter *adapter, at all */ found = 0; - for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 3) { + for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 2) { if (((adap_id == address_data->force[i]) || (address_data->force[i] == ANY_I2C_BUS)) && (addr == address_data->force[i+1])) { diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 3f70e4926c..5425e0f77d 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -67,7 +67,7 @@ static void msi_set_mask_bit(unsigned int vector, int flag) int pos; u32 mask_bits; - pos = (int)entry->mask_base; + pos = (long)entry->mask_base; pci_read_config_dword(entry->dev, pos, &mask_bits); mask_bits &= ~(1); mask_bits |= flag; @@ -555,7 +555,7 @@ static int msi_capability_init(struct pci_dev *dev) dev->irq = vector; entry->dev = dev; if (is_mask_bit_support(control)) { - entry->mask_base = (void __iomem *)msi_mask_bits_reg(pos, + entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos, is_64bit_address(control)); } /* Replace with MSI handler */ diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index df102f9301..c0ddb1eb8c 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -219,9 +219,10 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, res->data.address64.min_address_range, res->data.address64.address_length); break; + case ACPI_RSTYPE_VENDOR: + break; default: - pnp_warn("PnPACPI: Alloc type : %d not handle", - res->id); + pnp_warn("PnPACPI: unknown resource type %d", res->id); return AE_ERROR; } @@ -508,7 +509,7 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res, case ACPI_RSTYPE_END_DPF: return AE_CTRL_TERMINATE; default: - pnp_warn("PnPACPI:Option type: %d not handle", res->id); + pnp_warn("PnPACPI: unknown resource type %d", res->id); return AE_ERROR; } @@ -810,7 +811,7 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table, mem ++; break; default: /* other type */ - pnp_warn("Invalid type"); + pnp_warn("unknown resource type %d", resource->id); return -EINVAL; } resource ++; |
