From 300d31b9613e71217758f105bad3ff71755a223b Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 16 Feb 2005 15:50:15 -0500 Subject: [ACPI] Add ACPI-based memory hot plug driver. The ACPI based memory hot plug driver patch supports physical hotplug operations on memory. This driver fields notifications for memory add and remove operations from firmware and notifies the VM of the affected memory ranges. Accordingly, this driver also maintains and updates the states of all the memory ranges. This driver is useful on hardware which helps firmware generating ACPI events for every physical hotplug operation of memory boards on the system during runtime. Signed-off-by: Dave Hansen Signed-off-by: Naveen B S Signed-off-by: Matt Tolentino Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 21 ++ drivers/acpi/Makefile | 1 + drivers/acpi/acpi_memhotplug.c | 542 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 564 insertions(+) create mode 100644 drivers/acpi/acpi_memhotplug.c diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 76d3f2b141929..a2a3dc6039ffc 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -343,4 +343,25 @@ 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 + endmenu diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 1ae0d89c2d3fb..65c92e20566d5 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/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c new file mode 100644 index 0000000000000..77285ffe41c5c --- /dev/null +++ b/drivers/acpi/acpi_memhotplug.c @@ -0,0 +1,542 @@ +/* + * Copyright (C) 2004 Intel Corporation + * + * 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 +#include +#include +#include +#include +#include + + +#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 "); +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); + + -- cgit 1.2.3-korg From 3d5e39cfe35cfd43174c3e74849ac17ddd34a38c Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 22 Feb 2005 22:40:01 -0800 Subject: [IA64] fix IOSAPIC destinations when CONFIG_SMP=n Always use cpu_physical_id() (which is really the ID/EID of a processor's Local SAPIC) when programming IOSAPIC entries. Previously we sometimes used hard_smp_processor_id(), which is correct when CONFIG_SMP=y but wrong otherwise. Signed-off-by: Bjorn Helgaas Signed-off-by: Tony Luck --- arch/ia64/kernel/iosapic.c | 9 ++++----- include/asm-ia64/smp.h | 45 ++++++++++++++++++++++++--------------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 111dad9175ba1..c15be5c38f560 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -91,7 +91,6 @@ #undef DEBUG_INTERRUPT_ROUTING -#undef OVERRIDE_DEBUG #ifdef DEBUG_INTERRUPT_ROUTING #define DBG(fmt...) printk(fmt) @@ -499,14 +498,14 @@ get_target_cpu (unsigned int gsi, int vector) * distribute interrupts. */ if (smp_int_redirect & SMP_IRQ_REDIRECTION) - return hard_smp_processor_id(); + return cpu_physical_id(smp_processor_id()); /* * Some interrupts (ACPI SCI, for instance) are registered * before the BSP is marked as online. */ if (!cpu_online(smp_processor_id())) - return hard_smp_processor_id(); + return cpu_physical_id(smp_processor_id()); #ifdef CONFIG_NUMA { @@ -553,7 +552,7 @@ skip_numa_setup: return cpu_physical_id(cpu); #else - return hard_smp_processor_id(); + return cpu_physical_id(smp_processor_id()); #endif } @@ -740,7 +739,7 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, unsigned long trigger) { int vector; - unsigned int dest = hard_smp_processor_id(); + unsigned int dest = cpu_physical_id(smp_processor_id()); vector = isa_irq_to_vector(isa_irq); diff --git a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h index d6838c9b7bb4e..c4a227acfeb0a 100644 --- a/include/asm-ia64/smp.h +++ b/include/asm-ia64/smp.h @@ -3,16 +3,14 @@ * * Copyright (C) 1999 VA Linux Systems * Copyright (C) 1999 Walt Drummond - * Copyright (C) 2001-2003 Hewlett-Packard Co + * (c) Copyright 2001-2003, 2005 Hewlett-Packard Development Company, L.P. * David Mosberger-Tang + * Bjorn Helgaas */ #ifndef _ASM_IA64_SMP_H #define _ASM_IA64_SMP_H #include - -#ifdef CONFIG_SMP - #include #include #include @@ -24,6 +22,25 @@ #include #include +static inline unsigned int +ia64_get_lid (void) +{ + union { + struct { + unsigned long reserved : 16; + unsigned long eid : 8; + unsigned long id : 8; + unsigned long ignored : 32; + } f; + unsigned long bits; + } lid; + + lid.bits = ia64_getreg(_IA64_REG_CR_LID); + return lid.f.id << 8 | lid.f.eid; +} + +#ifdef CONFIG_SMP + #define XTP_OFFSET 0x1e0008 #define SMP_IRQ_REDIRECTION (1 << 0) @@ -90,22 +107,7 @@ max_xtp (void) writeb(0x0f, ipi_base_addr + XTP_OFFSET); /* Set XTP to max */ } -static inline unsigned int -hard_smp_processor_id (void) -{ - union { - struct { - unsigned long reserved : 16; - unsigned long eid : 8; - unsigned long id : 8; - unsigned long ignored : 32; - } f; - unsigned long bits; - } lid; - - lid.bits = ia64_getreg(_IA64_REG_CR_LID); - return lid.f.id << 8 | lid.f.eid; -} +#define hard_smp_processor_id() ia64_get_lid() /* Upping and downing of CPUs */ extern int __cpu_disable (void); @@ -125,7 +127,8 @@ extern void unlock_ipi_calllock(void); #else -#define cpu_logical_id(cpuid) 0 +#define cpu_logical_id(i) 0 +#define cpu_physical_id(i) ia64_get_lid() #endif /* CONFIG_SMP */ #endif /* _ASM_IA64_SMP_H */ -- cgit 1.2.3-korg From d62164f6f78c3095234e55e6356ce2b9c0a8f3e4 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 1 Mar 2005 05:26:20 -0500 Subject: [ACPI] ACPICA 20050228 from Bob Moore Fixed a problem where the result of an Index() operator (an object reference) must increment the reference count on the target object for the life of the object reference. Implemented AML Interpreter and Debugger support for the new ACPI 3.0 Extended Address (IO, Memory, Space), QwordSpace, DwordSpace, and WordSpace resource descriptors. Implemented support in the _OSI method for the ACPI 3.0 "Extended Address Space Descriptor" string, indicating interpreter support for the descriptors above. Implemented header support for the new ACPI 3.0 FADT flag bits. Implemented header support for the new ACPI 3.0 PCI Express bits for the PM1 status/enable registers. Updated header support for the MADT processor local Apic struct and MADT platform interrupt source struct for new ACPI 3.0 fields. Implemented header support for the SRAT and SLIT ACPI tables. Signed-off-by: Len Brown --- drivers/acpi/executer/exoparg2.c | 6 ++ drivers/acpi/parser/psopcode.c | 2 +- drivers/acpi/resources/rsaddr.c | 146 +++++++++++++++++++++----------------- drivers/acpi/resources/rscalc.c | 14 ++++ drivers/acpi/resources/rsdump.c | 23 +++--- drivers/acpi/resources/rslist.c | 1 + drivers/acpi/utilities/utdelete.c | 18 ++++- drivers/acpi/utilities/utglobal.c | 10 ++- drivers/acpi/utilities/utmisc.c | 20 +++--- include/acpi/acconfig.h | 4 +- include/acpi/acdisasm.h | 5 ++ include/acpi/aclocal.h | 4 ++ include/acpi/actbl.h | 4 +- include/acpi/actbl2.h | 79 ++++++++++++++++++--- include/acpi/actypes.h | 39 +++++----- include/acpi/platform/acenv.h | 2 + 16 files changed, 260 insertions(+), 117 deletions(-) diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c index 23964e70a89bf..8be4d80ceed59 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/parser/psopcode.c b/drivers/acpi/parser/psopcode.c index c1360fc23cee1..03e33fedc11a2 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/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c index ec4ae9a15cb0c..4788c079735d8 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 1113af7469395..8a5f0a52371d4 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 a869980f7fe45..eef1b1f2c6859 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 1297589d792f5..e49c1e030f99f 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/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index e8ee13280bbf1..9a52ad52a23ae 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -46,6 +46,7 @@ #include #include #include +#include #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 d3eb4db38f75c..25b0f8ae1bc6f 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 4d32f6d18f648..bbaa918826694 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -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? */ @@ -464,7 +468,7 @@ acpi_ut_strtoul64 ( return_value *= base; return_value += this_digit; - ++string; + string++; } *ret_integer = return_value; diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 6701c11b406b3..d49803ea48989 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -64,7 +64,7 @@ /* Version string */ -#define ACPI_CA_VERSION 0x20050211 +#define ACPI_CA_VERSION 0x20050228 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, @@ -198,7 +198,7 @@ /* Number of strings associated with the _OSI reserved method */ -#define ACPI_NUM_OSI_STRINGS 9 +#define ACPI_NUM_OSI_STRINGS 10 /****************************************************************************** diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h index 6a5da01e46fcd..26d907eae6fe3 100644 --- a/include/acpi/acdisasm.h +++ b/include/acpi/acdisasm.h @@ -75,6 +75,11 @@ extern const char *acpi_gbl_SHRdecode[2]; extern const char *acpi_gbl_TYPdecode[4]; extern const char *acpi_gbl_BMdecode[2]; extern const char *acpi_gbl_SIZdecode[4]; +extern const char *acpi_gbl_TTPdecode[2]; +extern const char *acpi_gbl_MTPdecode[4]; +extern const char *acpi_gbl_TRSdecode[2]; + + extern const char *acpi_gbl_lock_rule[ACPI_NUM_LOCK_RULES]; extern const char *acpi_gbl_access_types[ACPI_NUM_ACCESS_TYPES]; extern const char *acpi_gbl_update_rules[ACPI_NUM_UPDATE_RULES]; diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h index f2b96f6be45b5..01d3b4bc0c857 100644 --- a/include/acpi/aclocal.h +++ b/include/acpi/aclocal.h @@ -774,6 +774,7 @@ struct acpi_bit_register_info #define ACPI_BITMASK_POWER_BUTTON_STATUS 0x0100 #define ACPI_BITMASK_SLEEP_BUTTON_STATUS 0x0200 #define ACPI_BITMASK_RT_CLOCK_STATUS 0x0400 +#define ACPI_BITMASK_PCIEXP_WAKE_STATUS 0x4000 /* ACPI 3.0 */ #define ACPI_BITMASK_WAKE_STATUS 0x8000 #define ACPI_BITMASK_ALL_FIXED_STATUS (ACPI_BITMASK_TIMER_STATUS | \ @@ -789,6 +790,7 @@ struct acpi_bit_register_info #define ACPI_BITMASK_POWER_BUTTON_ENABLE 0x0100 #define ACPI_BITMASK_SLEEP_BUTTON_ENABLE 0x0200 #define ACPI_BITMASK_RT_CLOCK_ENABLE 0x0400 +#define ACPI_BITMASK_PCIEXP_WAKE_DISABLE 0x4000 /* ACPI 3.0 */ #define ACPI_BITMASK_SCI_ENABLE 0x0001 #define ACPI_BITMASK_BUS_MASTER_RLD 0x0002 @@ -807,6 +809,7 @@ struct acpi_bit_register_info #define ACPI_BITPOSITION_POWER_BUTTON_STATUS 0x08 #define ACPI_BITPOSITION_SLEEP_BUTTON_STATUS 0x09 #define ACPI_BITPOSITION_RT_CLOCK_STATUS 0x0A +#define ACPI_BITPOSITION_PCIEXP_WAKE_STATUS 0x0E /* ACPI 3.0 */ #define ACPI_BITPOSITION_WAKE_STATUS 0x0F #define ACPI_BITPOSITION_TIMER_ENABLE 0x00 @@ -814,6 +817,7 @@ struct acpi_bit_register_info #define ACPI_BITPOSITION_POWER_BUTTON_ENABLE 0x08 #define ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE 0x09 #define ACPI_BITPOSITION_RT_CLOCK_ENABLE 0x0A +#define ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE 0x0E /* ACPI 3.0 */ #define ACPI_BITPOSITION_SCI_ENABLE 0x00 #define ACPI_BITPOSITION_BUS_MASTER_RLD 0x01 diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h index f39ed91b5bc88..7eee731112b18 100644 --- a/include/acpi/actbl.h +++ b/include/acpi/actbl.h @@ -261,6 +261,8 @@ struct madt_local_sapic u8 local_sapic_eid; /* SAPIC EID */ u8 reserved [3]; /* Reserved - must be zero */ LOCAL_APIC_FLAGS + u32 processor_uID; /* Numeric UID - ACPI 3.0 */ + char processor_uIDstring[1]; /* String UID - ACPI 3.0 */ }; struct madt_interrupt_source @@ -272,7 +274,7 @@ struct madt_interrupt_source u8 processor_eid; /* Processor EID */ u8 io_sapic_vector; /* Vector value for PMI interrupts */ u32 interrupt; /* Global system interrupt */ - u32 reserved; /* Reserved - must be zero */ + u32 flags; /* Interrupt Source Flags */ }; diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index ea3ca08d88aa8..e1729c967e052 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -108,7 +108,7 @@ struct facs_descriptor_rev2 /* - * ACPI 2.0 Generic Address Structure (GAS) + * ACPI 2.0+ Generic Address Structure (GAS) */ struct acpi_generic_address { @@ -159,7 +159,7 @@ struct acpi_generic_address u16 iapc_boot_arch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/ /* - * ACPI 2.0 Fixed ACPI Description Table (FADT) + * ACPI 2.0+ Fixed ACPI Description Table (FADT) */ struct fadt_descriptor_rev2 { @@ -174,17 +174,25 @@ struct fadt_descriptor_rev2 u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */ u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */ u32 rtcs4 : 1; /* RTC wakeup stat not possible from S4 */ - u32 tmr_val_ext : 1; /* Indicates tmr_val is 32 bits 0=24-bits*/ + u32 tmr_val_ext : 1; /* Indicates tmr_val is 32 bits 0=24-bits */ u32 dock_cap : 1; /* Supports Docking */ - u32 reset_reg_sup : 1; /* Indicates system supports system reset via the FADT RESET_REG*/ - u32 sealed_case : 1; /* Indicates system has no internal expansion capabilities and case is sealed. */ - u32 headless : 1; /* Indicates system does not have local video capabilities or local input devices.*/ + u32 reset_reg_sup : 1; /* Indicates system supports system reset via the FADT RESET_REG */ + u32 sealed_case : 1; /* Indicates system has no internal expansion capabilities and case is sealed */ + u32 headless : 1; /* Indicates system does not have local video capabilities or local input devices */ u32 cpu_sw_sleep : 1; /* Indicates to OSPM that a processor native instruction */ - /* Must be executed after writing the SLP_TYPx register. */ - u32 reserved6 : 18; /* Reserved - must be zero */ + /* must be executed after writing the SLP_TYPx register */ + /* ACPI 3.0 flag bits */ + + u32 pci_exp_wak : 1; /* System supports PCIEXP_WAKE (STS/EN) bits */ + u32 use_platform_clock : 1; /* OSPM should use platform-provided timer */ + u32 S4rtc_sts_valid : 1; /* Contents of RTC_STS valid after S4 wake */ + u32 remote_power_on_capable : 1; /* System is compatible with remote power on */ + u32 force_apic_cluster_model : 1; /* All local APICs must use cluster model */ + u32 force_apic_physical_destination_mode : 1; /* all local x_aPICs must use physical dest mode */ + u32 reserved6 : 12;/* Reserved - must be zero */ struct acpi_generic_address reset_register; /* Reset register address in GAS format */ - u8 reset_value; /* Value to write to the reset_register port to reset the system. */ + u8 reset_value; /* Value to write to the reset_register port to reset the system */ u8 reserved7[3]; /* These three bytes must be zero */ u64 xfirmware_ctrl; /* 64-bit physical address of FACS */ u64 Xdsdt; /* 64-bit physical address of DSDT */ @@ -199,7 +207,7 @@ struct fadt_descriptor_rev2 }; -/* "Downrevved" ACPI 2.0 FADT descriptor */ +/* "Down-revved" ACPI 2.0 FADT descriptor */ struct fadt_descriptor_rev2_minus { @@ -213,7 +221,7 @@ struct fadt_descriptor_rev2_minus }; -/* Embedded Controller */ +/* ECDT - Embedded Controller Boot Resources Table */ struct ec_boot_resources { @@ -226,6 +234,55 @@ struct ec_boot_resources }; +/* SRAT - System Resource Affinity Table */ + +struct static_resource_alloc +{ + u8 type; + u8 length; + u8 proximity_domain_lo; + u8 apic_id; + u32 enabled :1; + u32 reserved3 :31; + u8 local_sapic_eid; + u8 proximity_domain_hi[3]; + u32 reserved4; +}; + +struct memory_affinity +{ + u8 type; + u8 length; + u32 proximity_domain; + u16 reserved3; + u64 base_address; + u64 address_length; + u32 reserved4; + u32 enabled :1; + u32 hot_pluggable :1; + u32 non_volatile :1; + u32 reserved5 :29; + u64 reserved6; +}; + +struct system_resource_affinity +{ + ACPI_TABLE_HEADER_DEF + u32 reserved1; /* Must be value '1' */ + u64 reserved2; +}; + + +/* SLIT - System Locality Distance Information Table */ + +struct system_locality_info +{ + ACPI_TABLE_HEADER_DEF + u64 locality_count; + u8 entry[1][1]; +}; + + #pragma pack() #endif /* __ACTBL2_H__ */ diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 51cb780c241e9..7acb550af3eb9 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -653,24 +653,26 @@ typedef u8 acpi_adr_space_type; #define ACPI_BITREG_SLEEP_BUTTON_STATUS 0x04 #define ACPI_BITREG_RT_CLOCK_STATUS 0x05 #define ACPI_BITREG_WAKE_STATUS 0x06 - -#define ACPI_BITREG_TIMER_ENABLE 0x07 -#define ACPI_BITREG_GLOBAL_LOCK_ENABLE 0x08 -#define ACPI_BITREG_POWER_BUTTON_ENABLE 0x09 -#define ACPI_BITREG_SLEEP_BUTTON_ENABLE 0x0A -#define ACPI_BITREG_RT_CLOCK_ENABLE 0x0B -#define ACPI_BITREG_WAKE_ENABLE 0x0C - -#define ACPI_BITREG_SCI_ENABLE 0x0D -#define ACPI_BITREG_BUS_MASTER_RLD 0x0E -#define ACPI_BITREG_GLOBAL_LOCK_RELEASE 0x0F -#define ACPI_BITREG_SLEEP_TYPE_A 0x10 -#define ACPI_BITREG_SLEEP_TYPE_B 0x11 -#define ACPI_BITREG_SLEEP_ENABLE 0x12 - -#define ACPI_BITREG_ARB_DISABLE 0x13 - -#define ACPI_BITREG_MAX 0x13 +#define ACPI_BITREG_PCIEXP_WAKE_STATUS 0x07 + +#define ACPI_BITREG_TIMER_ENABLE 0x08 +#define ACPI_BITREG_GLOBAL_LOCK_ENABLE 0x09 +#define ACPI_BITREG_POWER_BUTTON_ENABLE 0x0A +#define ACPI_BITREG_SLEEP_BUTTON_ENABLE 0x0B +#define ACPI_BITREG_RT_CLOCK_ENABLE 0x0C +#define ACPI_BITREG_WAKE_ENABLE 0x0D +#define ACPI_BITREG_PCIEXP_WAKE_DISABLE 0x0E + +#define ACPI_BITREG_SCI_ENABLE 0x0F +#define ACPI_BITREG_BUS_MASTER_RLD 0x10 +#define ACPI_BITREG_GLOBAL_LOCK_RELEASE 0x11 +#define ACPI_BITREG_SLEEP_TYPE_A 0x12 +#define ACPI_BITREG_SLEEP_TYPE_B 0x13 +#define ACPI_BITREG_SLEEP_ENABLE 0x14 + +#define ACPI_BITREG_ARB_DISABLE 0x15 + +#define ACPI_BITREG_MAX 0x15 #define ACPI_NUM_BITREG ACPI_BITREG_MAX + 1 @@ -1206,6 +1208,7 @@ struct acpi_resource_address64 u64 max_address_range; u64 address_translation_offset; u64 address_length; + u64 type_specific_attributes; struct acpi_resource_source resource_source; }; diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h index 5a956b549b1e5..57bf9362335dc 100644 --- a/include/acpi/platform/acenv.h +++ b/include/acpi/platform/acenv.h @@ -226,6 +226,7 @@ */ #define ACPI_STRSTR(s1,s2) strstr((s1), (s2)) +#define ACPI_STRCHR(s1,c) strchr((s1), (c)) #ifdef ACPI_FUTURE_USAGE #define ACPI_STRUPR(s) (void) acpi_ut_strupr ((s)) @@ -294,6 +295,7 @@ typedef char *va_list; #define ACPI_STRSTR(s1,s2) acpi_ut_strstr ((s1), (s2)) +#define ACPI_STRCHR(s1,c) acpi_ut_strchr ((s1), (c)) #ifdef ACPI_FUTURE_USAGE #define ACPI_STRUPR(s) (void) acpi_ut_strupr ((s)) -- cgit 1.2.3-korg From b0303cb3c7376b9e39f3a55da00ed583319d7f0b Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 2 Mar 2005 03:36:53 -0500 Subject: [ACPI] CONFIG_ACPI_NUMA build fix Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- arch/ia64/kernel/acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 43a4492f221a2..a5fde4eedc999 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -756,7 +756,7 @@ EXPORT_SYMBOL(acpi_unmap_lsapic); #endif /* CONFIG_ACPI_HOTPLUG_CPU */ -#ifdef CONFIG_NUMA +#ifdef CONFIG_ACPI_NUMA acpi_status __init acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret) { -- cgit 1.2.3-korg From b95379dce1a5208ddf57a671d663152462f0a231 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 2 Mar 2005 03:54:47 -0500 Subject: [ACPI] enhance fan output in error path Currently, fan.c ignores errors from acpi_bus_get_power. On compaq evo notebook that leads to very confusing empty output. From: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/fan.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 2c5422dfecb5a..4c6e3a92b3642 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -78,21 +78,18 @@ 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); } -- cgit 1.2.3-korg From d08af00eaf6a7615b49b5473b33c8b092c648ed2 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 2 Mar 2005 03:57:35 -0500 Subject: [ACPI] flush TLB in init_low_mappings() From: Li Shaohua Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- arch/i386/kernel/acpi/sleep.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c index be4df5548111f..d30cf2c2bd9f9 100644 --- a/arch/i386/kernel/acpi/sleep.c +++ b/arch/i386/kernel/acpi/sleep.c @@ -8,7 +8,7 @@ #include #include #include - +#include /* address in low memory of the wakeup routine. */ unsigned long acpi_wakeup_address = 0; @@ -27,6 +27,7 @@ static void init_low_mapping(pgd_t *pgd, int pgd_limit) set_pgd(pgd, *(pgd+USER_PTRS_PER_PGD)); pgd_ofs++, pgd++; } + flush_tlb_all(); } /** -- cgit 1.2.3-korg From 913ad613751aa04d8584f9e99dbe86b0a91126c6 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 2 Mar 2005 04:02:55 -0500 Subject: [ACPI] fix kobject_hotplug() use by ACPI processor and container drivers A while ago, the drivers used their own function 'processor_run_sbin_hotplug() and container_run_sbin_hotplug()' to notify the agent script using /sbin/hotplug mechanism. But, they were changed to use kobject_hotplug() instead and this has caused a side effect. The container driver was supposed to invoke a container.agent (user mode agent script) using /sbin/hotplug mechanism, but after the changes, it is not able to call the agent any more and kobject_hotplug() in the container.c became to invoke a namespace.agent instead if exists. So, I would like to use the namespace.agent to handle container hotplug event (or something else) and let the agent to call proper agent (e.g. container.agent). But, there is an issue we need to solve. When the namespace.agent is called, a path name of associated kobject is passed as a DEVPATH (e.g./sys/firmware/ acpi/namespace/ACPI/_SB/DEV0). However, the agent would not know what device is associated with the DEVPATH nor which agents to call since the DEVPATH name depends on platform. The attached patch is to add .hotplug_ops member to acpi_namespace_kset structure and let it to set a driver name attached to the target kobject into the envp[] variable as a DRV_NAME element. With this, the namespace.agent can call proper agents (e.g. container.agent) by refering the DRV_NAME. Signed-off-by: Keiichiro Tokunaga Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/scan.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 9ff6ccfdc4bf9..7ed00fac346fe 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -81,12 +81,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, }; -- cgit 1.2.3-korg From 682327941ae1a6f3150f4895e7c256996d2a903a Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 2 Mar 2005 04:06:18 -0500 Subject: [ACPI] fix ACPI container driver's notify handler. Previously, the handler tried to make a container device be offline if an ACPI_NOTIFY_BUS/DEVICE_CHECK notification is performed on the device was present and has its acpi_device. But, the condition is weird. Whenever the notification is performed, there should be only the following two conditions: 1. the device is present, but does not have its acpi_device. 2. the device is not present, but has its acpi_device. #1 is a hot-addition case, which was handled properly also in previous handler. #2 is a surprising hot-removal case, which was not handled in previous handler. Signed-off-by: Keiichiro Tokunaga Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/container.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 060251b5e49c8..0c1a9d6965033 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); } -- cgit 1.2.3-korg From 3cc24cb10c0fca1b697f9c17136f02d9422376aa Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 2 Mar 2005 04:13:39 -0500 Subject: [ACPI] fix sysfs "eject" file This fixes a if-statement in setup_sys_fs_device_files(). It seems to assume that 'struct acpi_device_flags.ejectable' indicates whether a device has _EJ0 or not. But this is not a right assumption. It indicates whether a device has _EJ0|_EJD (See acpi_bus_get_flags() function). setup_sys_fs_device_files() creates 'eject' file for devices that have _EJ0 control method under a corresponding directory in /sys/firmware/acpi/namespace/ACPI/. 'eject' file is used to trigger hot-removal function from userland. Signed-off-by: Keiichiro Tokunaga Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/scan.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 7ed00fac346fe..5c7a3d8a38c2f 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -383,7 +383,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); } -- cgit 1.2.3-korg From 1bd4f4d03d6c5cef0e451cf304f87cd3573e170b Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 3 Mar 2005 09:55:50 -0500 Subject: [ACPI] ACPICA 20050303 from Bob Moore for AE_AML_BUFFER_LIMIT issue. It turns out that tightening up the interpreter to truncate buffers per the ACPI spec was a bad idea -- BIOS' in the field depended on old behaviour. Instead, we'll endeavor to update the ACPI spec to reflect industry practice in this area. http://bugme.osdl.org/show_bug.cgi?id=4263 Signed-off-by: Len Brown --- drivers/acpi/executer/exstorob.c | 2 ++ include/acpi/acconfig.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c index 4e2b442ee5a39..b8b83331e3458 100644 --- a/drivers/acpi/executer/exstorob.c +++ b/drivers/acpi/executer/exstorob.c @@ -105,6 +105,7 @@ 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); +#if ACPI_STRICT_CONFORMANCE /* * If the original source was a string, we must truncate the buffer, * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer @@ -115,6 +116,7 @@ acpi_ex_store_buffer_to_buffer ( target_desc->buffer.length = length; } +#endif } else { /* Truncate the source, copy only what will fit */ diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index d49803ea48989..9a98d99a7932c 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -64,7 +64,7 @@ /* Version string */ -#define ACPI_CA_VERSION 0x20050228 +#define ACPI_CA_VERSION 0x20050303 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, -- cgit 1.2.3-korg From 07f8d68bd46d33d5ddb3d178de0eb42937c7f3b9 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 3 Mar 2005 13:21:29 -0500 Subject: [ACPI] fix [ACPI_MTX_Hardware] AE_TIME warning which resulted from enabling the wake-on-RTC feature http://bugme.osdl.org/show_bug.cgi?id=3967 Signed-off-by: David Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/events/evxface.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index a48820152ccdc..0bfec10a5f1e9 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")); -- cgit 1.2.3-korg From 5e2bd00949f386b2e0758f2491b0b7253ea8c941 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Mon, 7 Mar 2005 19:57:10 -0800 Subject: [IA64] pci.c: PCI root busses need resources Using the generic setup-bus.c code currently fails on HP's Integrity servers because the root busses have their resources set to the whole of ioport space and the whole of iomem space, instead of just the ranges that are routed to that particular bus. This patch uses the resources in the pci_windows to provide the ranges to each PCI root bus. In order to do that, I had to change them from being bus addresses to system addresses. Signed-off-by: Matthew Wilcox Signed-off-by: Tony Luck --- arch/ia64/pci/pci.c | 134 ++++++++++++++++++++++++++++------------------------ 1 file changed, 71 insertions(+), 63 deletions(-) diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 2a0dcf6083d62..33068bd1bba44 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -197,30 +197,6 @@ alloc_pci_controller (int seg) return controller; } -static int __devinit -alloc_resource (char *name, struct resource *root, unsigned long start, unsigned long end, - unsigned long flags) -{ - struct resource *res; - - res = kmalloc(sizeof(*res), GFP_KERNEL); - if (!res) - return -ENOMEM; - - memset(res, 0, sizeof(*res)); - res->name = name; - res->start = start; - res->end = end; - res->flags = flags; - - if (insert_resource(root, res)) { - kfree(res); - return -EBUSY; - } - - return 0; -} - static u64 __devinit add_io_space (struct acpi_resource_address64 *addr) { @@ -273,10 +249,9 @@ struct pci_root_info { char *name; }; -static acpi_status __devinit -add_window (struct acpi_resource *res, void *data) +static __devinit acpi_status add_window(struct acpi_resource *res, void *data) { - struct pci_root_info *info = (struct pci_root_info *) data; + struct pci_root_info *info = data; struct pci_window *window; struct acpi_resource_address64 addr; acpi_status status; @@ -284,45 +259,71 @@ add_window (struct acpi_resource *res, void *data) struct resource *root; status = acpi_resource_to_address64(res, &addr); - if (ACPI_SUCCESS(status)) { - if (!addr.address_length) + if (!ACPI_SUCCESS(status)) + return AE_OK; + + if (!addr.address_length) + return AE_OK; + + if (addr.resource_type == ACPI_MEMORY_RANGE) { + flags = IORESOURCE_MEM; + root = &iomem_resource; + offset = addr.address_translation_offset; + } else if (addr.resource_type == ACPI_IO_RANGE) { + flags = IORESOURCE_IO; + root = &ioport_resource; + offset = add_io_space(&addr); + if (offset == ~0) return AE_OK; - - if (addr.resource_type == ACPI_MEMORY_RANGE) { - flags = IORESOURCE_MEM; - root = &iomem_resource; - offset = addr.address_translation_offset; - } else if (addr.resource_type == ACPI_IO_RANGE) { - flags = IORESOURCE_IO; - root = &ioport_resource; - offset = add_io_space(&addr); - if (offset == ~0) - return AE_OK; - } else - return AE_OK; - - window = &info->controller->window[info->controller->windows++]; - window->resource.flags = flags; - window->resource.start = addr.min_address_range; - window->resource.end = addr.max_address_range; - window->offset = offset; - - if (alloc_resource(info->name, root, addr.min_address_range + offset, - addr.max_address_range + offset, flags)) - printk(KERN_ERR "alloc 0x%lx-0x%lx from %s for %s failed\n", - addr.min_address_range + offset, addr.max_address_range + offset, - root->name, info->name); + } else + return AE_OK; + + window = &info->controller->window[info->controller->windows++]; + window->resource.name = info->name; + window->resource.flags = flags; + window->resource.start = addr.min_address_range + offset; + window->resource.end = addr.max_address_range + offset; + window->resource.child = NULL; + window->offset = offset; + + if (insert_resource(root, &window->resource)) { + printk(KERN_ERR "alloc 0x%lx-0x%lx from %s for %s failed\n", + window->resource.start, window->resource.end, + root->name, info->name); } return AE_OK; } +static void __devinit +pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl) +{ + int i, j; + + j = 0; + for (i = 0; i < ctrl->windows; i++) { + struct resource *res = &ctrl->window[i].resource; + /* HP's firmware has a hack to work around a Windows bug. + * Ignore these tiny memory ranges */ + if ((res->flags & IORESOURCE_MEM) && + (res->end - res->start < 16)) + continue; + if (j >= PCI_BUS_NUM_RESOURCES) { + printk("Ignoring range [%lx-%lx] (%lx)\n", res->start, + res->end, res->flags); + continue; + } + bus->resource[j++] = res; + } +} + struct pci_bus * __devinit -pci_acpi_scan_root (struct acpi_device *device, int domain, int bus) +pci_acpi_scan_root(struct acpi_device *device, int domain, int bus) { struct pci_root_info info; struct pci_controller *controller; unsigned int windows = 0; + struct pci_bus *pbus; char *name; controller = alloc_pci_controller(domain); @@ -331,8 +332,10 @@ pci_acpi_scan_root (struct acpi_device *device, int domain, int bus) controller->acpi_handle = device->handle; - acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, &windows); - controller->window = kmalloc(sizeof(*controller->window) * windows, GFP_KERNEL); + acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, + &windows); + controller->window = kmalloc(sizeof(*controller->window) * windows, + GFP_KERNEL); if (!controller->window) goto out2; @@ -343,9 +346,14 @@ pci_acpi_scan_root (struct acpi_device *device, int domain, int bus) sprintf(name, "PCI Bus %04x:%02x", domain, bus); info.controller = controller; info.name = name; - acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window, &info); + acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window, + &info); + + pbus = pci_scan_bus(bus, &pci_root_ops, controller); + if (pbus) + pcibios_setup_root_windows(pbus, controller); - return pci_scan_bus(bus, &pci_root_ops, controller); + return pbus; out3: kfree(controller->window); @@ -366,9 +374,9 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_window *window = &controller->window[i]; if (!(window->resource.flags & res->flags)) continue; - if (window->resource.start > res->start - window->offset) + if (window->resource.start > res->start) continue; - if (window->resource.end < res->end - window->offset) + if (window->resource.end < res->end) continue; offset = window->offset; break; @@ -390,9 +398,9 @@ void pcibios_bus_to_resource(struct pci_dev *dev, struct pci_window *window = &controller->window[i]; if (!(window->resource.flags & res->flags)) continue; - if (window->resource.start > region->start) + if (window->resource.start - window->offset > region->start) continue; - if (window->resource.end < region->end) + if (window->resource.end - window->offset < region->end) continue; offset = window->offset; break; -- cgit 1.2.3-korg From 8223648fd1f8e9d49649728d427fcbeac591c274 Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Mon, 7 Mar 2005 22:45:52 -0800 Subject: [IA64-SGI] [PATCH 1/2] - New chipset support for SN platform - add new parameters to a platform-specific SAL call to retrieve addition chipset specific info. - change partition_coherence_id() so that it works on platforms using the new chipset. Signed-off-by: Jack Steiner Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/setup.c | 18 ++++++++++----- include/asm-ia64/sn/sn_cpuid.h | 5 +++-- include/asm-ia64/sn/sn_sal.h | 50 +++++++++++++++++++++++++++++++----------- 3 files changed, 53 insertions(+), 20 deletions(-) diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index a852077940fe0..a78197af95a50 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -76,6 +76,16 @@ char sn_system_serial_number_string[128]; EXPORT_SYMBOL(sn_system_serial_number_string); u64 sn_partition_serial_number; EXPORT_SYMBOL(sn_partition_serial_number); +u8 sn_partition_id; +EXPORT_SYMBOL(sn_partition_id); +u8 sn_system_size; +EXPORT_SYMBOL(sn_system_size); +u8 sn_sharing_domain_size; +EXPORT_SYMBOL(sn_sharing_domain_size); +u8 sn_coherency_id; +EXPORT_SYMBOL(sn_coherency_id); +u8 sn_region_size; +EXPORT_SYMBOL(sn_region_size); short physical_node_map[MAX_PHYSNODE_ID]; @@ -424,15 +434,13 @@ void __init sn_cpu_init(void) int slice; int cnode; int i; - u64 shubtype, nasid_bitmask, nasid_shift; static int wars_have_been_checked; memset(pda, 0, sizeof(pda)); - if (ia64_sn_get_hub_info(0, &shubtype, &nasid_bitmask, &nasid_shift)) + if (ia64_sn_get_sn_info(0, &pda->shub2, &pda->nasid_bitmask, &pda->nasid_shift, + &sn_system_size, &sn_sharing_domain_size, &sn_partition_id, + &sn_coherency_id, &sn_region_size)) BUG(); - pda->shub2 = (u8)shubtype; - pda->nasid_bitmask = (u16)nasid_bitmask; - pda->nasid_shift = (u8)nasid_shift; pda->as_shift = pda->nasid_shift - 2; /* diff --git a/include/asm-ia64/sn/sn_cpuid.h b/include/asm-ia64/sn/sn_cpuid.h index 749f45042cdcc..685435af170d8 100644 --- a/include/asm-ia64/sn/sn_cpuid.h +++ b/include/asm-ia64/sn/sn_cpuid.h @@ -135,9 +135,10 @@ extern int nasid_slice_to_cpuid(int, int); #define nasid_to_cnodeid(nasid) (physical_node_map[nasid]) /* - * partition_coherence_id - cget the coherence ID of the current partition + * partition_coherence_id - get the coherence ID of the current partition */ -#define partition_coherence_id() (get_nasid() >> 9) +extern u8 sn_coherency_id; +#define partition_coherence_id() (sn_coherency_id) #endif /* _ASM_IA64_SN_SN_CPUID_H */ diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 4ecc05e8ad577..88c31b53dc097 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -18,6 +18,7 @@ #include #include #include +#include // SGI Specific Calls #define SN_SAL_POD_MODE 0x02000001 @@ -34,7 +35,7 @@ #define SN_SAL_PRINT_ERROR 0x02000012 #define SN_SAL_SET_ERROR_HANDLING_FEATURES 0x0200001a // reentrant #define SN_SAL_GET_FIT_COMPT 0x0200001b // reentrant -#define SN_SAL_GET_HUB_INFO 0x0200001c +#define SN_SAL_GET_SN_INFO 0x0200001c #define SN_SAL_GET_SAPIC_INFO 0x0200001d #define SN_SAL_CONSOLE_PUTC 0x02000021 #define SN_SAL_CONSOLE_GETC 0x02000022 @@ -935,15 +936,24 @@ ia64_sn_get_sapic_info(int sapicid, int *nasid, int *subnode, int *slice) /* * Returns information about the HUB/SHUB. * In: - * arg0 - SN_SAL_GET_HUB_INFO + * arg0 - SN_SAL_GET_SN_INFO * arg1 - 0 (other values reserved for future use) * Out: - * v0 - shub type (0=shub1, 1=shub2) - * v1 - masid mask (ex., 0x7ff for 11 bit nasid) - * v2 - bit position of low nasid bit + * v0 + * [7:0] - shub type (0=shub1, 1=shub2) + * [15:8] - Log2 max number of nodes in entire system (includes + * C-bricks, I-bricks, etc) + * [23:16] - Log2 of nodes per sharing domain + * [31:24] - partition ID + * [39:32] - coherency_id + * [47:40] - regionsize + * v1 + * [15:0] - nasid mask (ex., 0x7ff for 11 bit nasid) + * [23:15] - bit position of low nasid bit */ static inline u64 -ia64_sn_get_hub_info(int fc, u64 *arg1, u64 *arg2, u64 *arg3) +ia64_sn_get_sn_info(int fc, u8 *shubtype, u16 *nasid_bitmask, u8 *nasid_shift, + u8 *systemsize, u8 *sharing_domain_size, u8 *partid, u8 *coher, u8 *reg) { struct ia64_sal_retval ret_stuff; @@ -951,13 +961,22 @@ ia64_sn_get_hub_info(int fc, u64 *arg1, u64 *arg2, u64 *arg3) ret_stuff.v0 = 0; ret_stuff.v1 = 0; ret_stuff.v2 = 0; - SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_HUB_INFO, fc, 0, 0, 0, 0, 0, 0); + SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_SN_INFO, fc, 0, 0, 0, 0, 0, 0); /***** BEGIN HACK - temp til old proms no longer supported ********/ if (ret_stuff.status == SALRET_NOT_IMPLEMENTED) { - if (arg1) *arg1 = 0; - if (arg2) *arg2 = 0x7ff; - if (arg3) *arg3 = 38; + int nasid = get_sapicid() & 0xfff;; +#define SH_SHUB_ID_NODES_PER_BIT_MASK 0x001f000000000000UL +#define SH_SHUB_ID_NODES_PER_BIT_SHFT 48 + if (shubtype) *shubtype = 0; + if (nasid_bitmask) *nasid_bitmask = 0x7ff; + if (nasid_shift) *nasid_shift = 38; + if (systemsize) *systemsize = 11; + if (sharing_domain_size) *sharing_domain_size = 9; + if (partid) *partid = ia64_sn_sysctl_partition_get(nasid); + if (coher) *coher = nasid >> 9; + if (reg) *reg = (HUB_L((u64 *) LOCAL_MMR_ADDR(SH1_SHUB_ID)) & SH_SHUB_ID_NODES_PER_BIT_MASK) >> + SH_SHUB_ID_NODES_PER_BIT_SHFT; return 0; } /***** END HACK *******/ @@ -965,9 +984,14 @@ ia64_sn_get_hub_info(int fc, u64 *arg1, u64 *arg2, u64 *arg3) if (ret_stuff.status < 0) return ret_stuff.status; - if (arg1) *arg1 = ret_stuff.v0; - if (arg2) *arg2 = ret_stuff.v1; - if (arg3) *arg3 = ret_stuff.v2; + if (shubtype) *shubtype = ret_stuff.v0 & 0xff; + if (systemsize) *systemsize = (ret_stuff.v0 >> 8) & 0xff; + if (sharing_domain_size) *sharing_domain_size = (ret_stuff.v0 >> 16) & 0xff; + if (partid) *partid = (ret_stuff.v0 >> 24) & 0xff; + if (coher) *coher = (ret_stuff.v0 >> 32) & 0xff; + if (reg) *reg = (ret_stuff.v0 >> 40) & 0xff; + if (nasid_bitmask) *nasid_bitmask = (ret_stuff.v1 & 0xffff); + if (nasid_shift) *nasid_shift = (ret_stuff.v1 >> 16) & 0xff; return 0; } -- cgit 1.2.3-korg From 217907ba12bb5dfb7a05d8f0559556abdf1667ee Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Mon, 7 Mar 2005 23:02:27 -0800 Subject: [IA64-SGI] [PATCH 2/2] - New chipset support for SN platform - move a number of fields out of the SN pda & into per-cpu data. The pda is ugly & will be deleted. This is a first step. Additional patches will follow. Signed-off-by: Jack Steiner Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/setup.c | 12 +++++++----- include/asm-ia64/sn/addrs.h | 7 ++++--- include/asm-ia64/sn/arch.h | 24 ++++++++++++++++++++++++ include/asm-ia64/sn/pda.h | 13 ------------- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index a78197af95a50..f0306b516afba 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -67,9 +67,11 @@ extern void snidle(int); extern unsigned char acpi_kbd_controller_present; unsigned long sn_rtc_cycles_per_second; - EXPORT_SYMBOL(sn_rtc_cycles_per_second); +DEFINE_PER_CPU(struct sn_hub_info_s, __sn_hub_info); +EXPORT_PER_CPU_SYMBOL(__sn_hub_info); + partid_t sn_partid = -1; EXPORT_SYMBOL(sn_partid); char sn_system_serial_number_string[128]; @@ -242,7 +244,7 @@ static void __init sn_check_for_wars(void) } else { for_each_online_node(cnode) { if (is_shub_1_1(cnodeid_to_nasid(cnode))) - shub_1_1_found = 1; + sn_hub_info->shub_1_1_found = 1; } } } @@ -437,11 +439,11 @@ void __init sn_cpu_init(void) static int wars_have_been_checked; memset(pda, 0, sizeof(pda)); - if (ia64_sn_get_sn_info(0, &pda->shub2, &pda->nasid_bitmask, &pda->nasid_shift, + if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2, &sn_hub_info->nasid_bitmask, &sn_hub_info->nasid_shift, &sn_system_size, &sn_sharing_domain_size, &sn_partition_id, &sn_coherency_id, &sn_region_size)) BUG(); - pda->as_shift = pda->nasid_shift - 2; + sn_hub_info->as_shift = sn_hub_info->nasid_shift - 2; /* * The boot cpu makes this call again after platform initialization is @@ -490,7 +492,7 @@ void __init sn_cpu_init(void) sn_check_for_wars(); wars_have_been_checked = 1; } - pda->shub_1_1_found = shub_1_1_found; + sn_hub_info->shub_1_1_found = shub_1_1_found; /* * Set up addresses of PIO/MEM write status registers. diff --git a/include/asm-ia64/sn/addrs.h b/include/asm-ia64/sn/addrs.h index 3ce60976d474b..c916bd22767a1 100644 --- a/include/asm-ia64/sn/addrs.h +++ b/include/asm-ia64/sn/addrs.h @@ -11,6 +11,7 @@ #include #include +#include #include /* @@ -57,9 +58,9 @@ /* * Define basic shift & mask constants for manipulating NASIDs and AS values. */ -#define NASID_BITMASK (pda->nasid_bitmask) -#define NASID_SHIFT (pda->nasid_shift) -#define AS_SHIFT (pda->as_shift) +#define NASID_BITMASK (sn_hub_info->nasid_bitmask) +#define NASID_SHIFT (sn_hub_info->nasid_shift) +#define AS_SHIFT (sn_hub_info->as_shift) #define AS_BITMASK 0x3UL #define NASID_MASK ((u64)NASID_BITMASK << NASID_SHIFT) diff --git a/include/asm-ia64/sn/arch.h b/include/asm-ia64/sn/arch.h index bfc922a0ab717..7c349f07916a1 100644 --- a/include/asm-ia64/sn/arch.h +++ b/include/asm-ia64/sn/arch.h @@ -12,9 +12,33 @@ #define _ASM_IA64_SN_ARCH_H #include +#include #include #include +/* + * The following defines attributes of the HUB chip. These attributes are + * frequently referenced. They are kept in the per-cpu data areas of each cpu. + * They are kept together in a struct to minimize cache misses. + */ +struct sn_hub_info_s { + u8 shub2; + u8 nasid_shift; + u8 as_shift; + u8 shub_1_1_found; + u16 nasid_bitmask; +}; +DECLARE_PER_CPU(struct sn_hub_info_s, __sn_hub_info); +#define sn_hub_info (&__get_cpu_var(__sn_hub_info)) +#define is_shub2() (sn_hub_info->shub2) +#define is_shub1() (sn_hub_info->shub2 == 0) + +/* + * Use this macro to test if shub 1.1 wars should be enabled + */ +#define enable_shub_wars_1_1() (sn_hub_info->shub_1_1_found) + + /* * This is the maximum number of nodes that can be part of a kernel. * Effectively, it's the maximum number of compact node ids (cnodeid_t). diff --git a/include/asm-ia64/sn/pda.h b/include/asm-ia64/sn/pda.h index 6465e8ab2bccd..d18f96f0dc62b 100644 --- a/include/asm-ia64/sn/pda.h +++ b/include/asm-ia64/sn/pda.h @@ -37,11 +37,6 @@ typedef struct pda_s { * Support for SN LEDs */ volatile short *led_address; - u16 nasid_bitmask; - u8 shub2; - u8 nasid_shift; - u8 as_shift; - u8 shub_1_1_found; u8 led_state; u8 hb_state; /* supports blinking heartbeat leds */ unsigned int hb_count; @@ -84,12 +79,4 @@ DECLARE_PER_CPU(struct pda_s, pda_percpu); #define pdacpu(cpu) (&per_cpu(pda_percpu, cpu)) -/* - * Use this macro to test if shub 1.1 wars should be enabled - */ -#define enable_shub_wars_1_1() (pda->shub_1_1_found) - -#define is_shub2() (pda->shub2) -#define is_shub1() (pda->shub2 == 0) - #endif /* _ASM_IA64_SN_PDA_H */ -- cgit 1.2.3-korg From 8b46eae95b9d8a182ac434d38eb0c638567f939b Mon Sep 17 00:00:00 2001 From: Russ Anderson Date: Mon, 7 Mar 2005 23:04:50 -0800 Subject: [IA64-SGI] Remove unused cpu_bte_if from pda_s Signed-off-by: Russ Anderson Signed-off-by: Tony Luck --- include/asm-ia64/sn/pda.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/asm-ia64/sn/pda.h b/include/asm-ia64/sn/pda.h index d18f96f0dc62b..e940d3647c804 100644 --- a/include/asm-ia64/sn/pda.h +++ b/include/asm-ia64/sn/pda.h @@ -48,8 +48,6 @@ typedef struct pda_s { unsigned long pio_write_status_val; volatile unsigned long *pio_shub_war_cam_addr; - struct bteinfo_s *cpu_bte_if[BTES_PER_NODE]; /* cpu interface order */ - unsigned long sn_soft_irr[4]; unsigned long sn_in_service_ivecs[4]; short cnodeid_to_nasid_table[MAX_NUMNODES]; -- cgit 1.2.3-korg From 8d7c763253b85b5598e5975a5c88b896fefe2110 Mon Sep 17 00:00:00 2001 From: Bob Montgomery Date: Tue, 8 Mar 2005 00:44:21 -0800 Subject: [IA64] fix bad emulation of unaligned semaphore opcodes The method used to categorize the load/store instructions in arch/ia64/kernel/unaligned.c is masking the entire set of instructions described in Table 4-33 of the 2002 Intel Itanium Volume 3: Instruction Set Reference. It's the set of instructions for opcode 4, mbit 0, x bit 1, described as Semaphore/Get FR/16-Byte Opcode Instructions. Because the IA64_OPCODE_SHIFT and IA64_OPCODE_MASK operations ignore the x bit, this set of instructions (including cmpxchg, xchg, and fetchadd among others) are processed like the corresponding opcode 4, mbit 0, x bit 0 instructions. This means that a cmpxchg.acq with a misaligned pointer will return the old value without setting the new one (rendering spin locks as No-ops) and that the other instructions also appear not to update memory. A cmpxchg.rel will be treated like a ld.s and just retry forever. The correct behavior for this class of instructions is documented in the file as producing failures for user code and kernel oops in kernel mode, but the code as implemented does not behave this way. I have user test code to demonstrate the problem if you would like a copy. The simple fix in this patch has been discussed with Stephane Eranian and David Mosberger. It has the advantage of not requiring the redesign of the opcode discrimination in unaligned.c. Signed-off-by: Bob Montgomery Signed-off-by: Tony Luck --- arch/ia64/kernel/unaligned.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index 46dad0d215a3d..43b45b65ee5a9 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c @@ -1380,6 +1380,10 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) * - ldX.spill * - stX.spill * Reason: RNATs are based on addresses + * - ld16 + * - st16 + * Reason: ld16 and st16 are supposed to occur in a single + * memory op * * synchronization: * - cmpxchg @@ -1401,6 +1405,10 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) switch (opcode) { case LDS_OP: case LDSA_OP: + if (u.insn.x) + /* oops, really a semaphore op (cmpxchg, etc) */ + goto failure; + /* no break */ case LDS_IMM_OP: case LDSA_IMM_OP: case LDFS_OP: @@ -1425,6 +1433,10 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) case LDCCLR_OP: case LDCNC_OP: case LDCCLRACQ_OP: + if (u.insn.x) + /* oops, really a semaphore op (cmpxchg, etc) */ + goto failure; + /* no break */ case LD_IMM_OP: case LDA_IMM_OP: case LDBIAS_IMM_OP: @@ -1437,6 +1449,10 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) case ST_OP: case STREL_OP: + if (u.insn.x) + /* oops, really a semaphore op (cmpxchg, etc) */ + goto failure; + /* no break */ case ST_IMM_OP: case STREL_IMM_OP: ret = emulate_store_int(ifa, u.insn, regs); -- cgit 1.2.3-korg From 8a022b292383bba7e2c3e8735a5b0ff97f49777c Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 8 Mar 2005 13:56:24 -0500 Subject: [ACPI] PNPACPI should ignore vendor-defined resources Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/pnp/pnpacpi/rsparser.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index df102f9301e71..c0ddb1eb8c4d6 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 ++; -- cgit 1.2.3-korg From e7452b6fcf9d37c284c23b61cb6db69d88cae3f8 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 8 Mar 2005 13:59:02 -0500 Subject: [ACPI] Make PCI device -> interrupt link associations explicit, ACPI: PCI Interrupt 0000:00:0f.2[A] -> Link [IUSB] -> GSI 10 (level, low) -> IRQ 10 Previously, you could sometimes infer an association based on the output when an interrupt link is enabled, but when interrupt links are shared among several PCI devices, you could only make the inference for the first device to be enabled. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 30 ++++++++++++++++++++---------- drivers/acpi/pci_link.c | 14 +++++++++----- include/acpi/acpi_drivers.h | 3 ++- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 640a3d86c58f7..a3d8fc44a0368 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -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); diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 3191b5ff105e1..520b28ad0740e 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/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index 0c964592a2c34..c62e92ec43b28 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h @@ -56,7 +56,8 @@ /* ACPI PCI Interrupt Link (pci_link.c) */ int acpi_irq_penalty_init (void); -int acpi_pci_link_get_irq (acpi_handle handle, int index, int* edge_level, int* active_high_low); +int acpi_pci_link_get_irq (acpi_handle handle, int index, int *edge_level, + int *active_high_low, char **name); /* ACPI PCI Interrupt Routing (pci_irq.c) */ -- cgit 1.2.3-korg From dfc9bcb4570dd86709eda1bd611300fd930a2d6c Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 8 Mar 2005 14:02:51 -0500 Subject: [ACPI] Allow 4 digits when printing PCI segments to be consistent with the rest of the kernel. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_root.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 2adaba68b85b7..7e6b8e3b2ed41 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; -- cgit 1.2.3-korg From d1833bdaf4b380966686ba201640c6df139179e3 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 8 Mar 2005 15:29:06 -0500 Subject: [ACPI] fix acpi_numa_init() build warning Signed-off-by: Randy Dunlap Signed-off-by: Len Brown --- drivers/acpi/numa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 3a305b07c2543..ebd17be6c293d 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; -- cgit 1.2.3-korg From fcc545dc266d335b42b96df15d12c23f03f3b5ea Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 8 Mar 2005 15:38:15 -0500 Subject: [ACPI] limit scope of various globals to static Signed-off-by: Adrian Bunk Signed-off-by: Len Brown --- drivers/acpi/ac.c | 18 +++++++++--------- drivers/acpi/battery.c | 2 +- drivers/acpi/button.c | 4 ++-- drivers/acpi/container.c | 4 ++-- drivers/acpi/debug.c | 4 ++-- drivers/acpi/ec.c | 2 +- drivers/acpi/fan.c | 14 +++++++------- drivers/acpi/ibm_acpi.c | 4 ++-- drivers/acpi/osl.c | 10 +++++----- drivers/acpi/pci_irq.c | 4 ++-- drivers/acpi/power.c | 10 +++++----- drivers/acpi/processor_core.c | 6 +++--- drivers/acpi/processor_thermal.c | 2 +- drivers/acpi/processor_throttling.c | 2 +- drivers/acpi/scan.c | 12 ++++++++---- drivers/acpi/thermal.c | 2 +- drivers/acpi/toshiba_acpi.c | 2 +- drivers/acpi/video.c | 2 +- include/acpi/acpi_bus.h | 1 - include/acpi/processor.h | 2 -- include/linux/acpi.h | 2 -- 21 files changed, 54 insertions(+), 55 deletions(-) diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index e0f498c7b343c..23ab761dd7217 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/battery.c b/drivers/acpi/battery.c index a10de067dbb63..c55feca9b7d5e 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 31aded126ce88..ec4430e3053ff 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 0c1a9d6965033..5a0adbf8bc045 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -260,7 +260,7 @@ end: } -int __init +static int __init acpi_container_init(void) { int result = 0; @@ -281,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 d947e2a0a4629..2c0dac559f163 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/ec.c b/drivers/acpi/ec.c index 8d4219388c9a8..fdf143b405be7 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/fan.c b/drivers/acpi/fan.c index 4c6e3a92b3642..14192ee55f8f1 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,7 +72,7 @@ struct acpi_fan { FS Interface (/proc) -------------------------------------------------------------------------- */ -struct proc_dir_entry *acpi_fan_dir; +static struct proc_dir_entry *acpi_fan_dir; static int @@ -194,7 +194,7 @@ acpi_fan_remove_fs ( Driver Interface -------------------------------------------------------------------------- */ -int +static int acpi_fan_add ( struct acpi_device *device) { @@ -240,7 +240,7 @@ end: } -int +static int acpi_fan_remove ( struct acpi_device *device, int type) @@ -262,7 +262,7 @@ acpi_fan_remove ( } -int __init +static int __init acpi_fan_init (void) { int result = 0; @@ -284,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 94a76e520e213..0fb731a470dce 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/osl.c b/drivers/acpi/osl.c index 94a511315c8ba..5a9128de62261 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/pci_irq.c b/drivers/acpi/pci_irq.c index b52075acc3e66..046b68e492e9a 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 diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 419b371d95ad8..373a3a95bb4e1 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 e517a11dc9c68..f4778747e889b 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 8711236d28b66..12bd980a12e94 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 db0b31d2b3eb3..be9f569d39d33 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/scan.c b/drivers/acpi/scan.c index 4c1fee1523cd1..e7ca06626566e 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); @@ -890,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; @@ -915,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; @@ -958,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) @@ -1256,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 be97f28695792..79c3a686bc442 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 c0c9ea1084aa3..c84997c9f9640 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/video.c b/drivers/acpi/video.c index bd311c2076acc..71fa1011715f3 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/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index b4479061b8f90..c627bc408a6b1 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -328,7 +328,6 @@ int acpi_bus_receive_event (struct acpi_bus_event *event); int acpi_bus_register_driver (struct acpi_driver *driver); int acpi_bus_unregister_driver (struct acpi_driver *driver); int acpi_bus_scan (struct acpi_device *start); -int acpi_bus_trim(struct acpi_device *start, int rmdevice); int acpi_bus_add (struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type); diff --git a/include/acpi/processor.h b/include/acpi/processor.h index d1c8a8b98f6a6..2f50a5bb0c781 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -201,7 +201,6 @@ static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr) { /* in processor_throttling.c */ int acpi_processor_get_throttling_info (struct acpi_processor *pr); int acpi_processor_set_throttling (struct acpi_processor *pr, int state); -int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file); ssize_t acpi_processor_write_throttling ( struct file *file, const char __user *buffer, @@ -217,7 +216,6 @@ int acpi_processor_power_exit(struct acpi_processor *pr, struct acpi_device *dev /* in processor_thermal.c */ int acpi_processor_get_limit_info (struct acpi_processor *pr); -int acpi_processor_limit_open_fs(struct inode *inode, struct file *file); ssize_t acpi_processor_write_limit ( struct file *file, const char __user *buffer, diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 5cbf3486926f5..aefe6d051ace1 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -455,8 +455,6 @@ struct acpi_prt_list { struct list_head entries; }; -extern struct acpi_prt_list acpi_prt; - struct pci_dev; int acpi_pci_irq_enable (struct pci_dev *dev); -- cgit 1.2.3-korg From 4ca5d141df1bf28ec3047f8ef08041bb407452a8 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 9 Mar 2005 13:46:24 -0500 Subject: [ACPI] ACPICA 20050309 from Bob Moore The string-to-buffer implicit conversion code has been modified again after a change to the ACPI specification. In order to match the behavior of the other major ACPI implementation, the target buffer is no longer truncated if the source string is smaller than an existing target buffer. This change requires an update to the ACPI spec, and should eliminate the recent AE_AML_BUFFER_LIMIT issues. The "implicit return" support was rewritten to a new algorithm that solves the general case. Rather than attempt to determine when a method is about to exit, the result of every ASL operator is saved momentarily until the very next ASL operator is executed. Therefore, no matter how the method exits, there will always be a saved implicit return value. This feature is only enabled with the acpi_gbl_enable_interpreter_slack flag which Linux enables unless "acpi=strict". This should eliminate AE_AML_NO_RETURN_VALUE errors. Implemented implicit conversion support for the predicate (operand) of the If, Else, and While operators. String and Buffer arguments are automatically converted to Integers. Changed the string-to-integer conversion behavior to match the new ACPI errata: "If no integer object exists, a new integer is created. The ASCII string is interpreted as a hexadecimal constant. Each string character is interpreted as a hexadecimal value ('0'-'9', 'A'-'F', 'a', 'f'), starting with the first character as the most significant digit, and ending with the first non-hexadecimal character or end-of-string." This means that the first non-hex character terminates the conversion and this is the code that was changed. Fixed a problem where the ObjectType operator would fail (fault) when used on an Index of a Package which pointed to a null package element. The operator now properly returns zero (Uninitialized) in this case. Fixed a problem where the While operator used excessive memory by not properly popping the result stack during execution. There was no memory leak after execution, however. (Code provided by Valery Podrezov.) Fixed a problem where references to control methods within Package objects caused the method to be invoked, instead of producing a reference object pointing to the method. Restructured and simplified the pswalk.c module (acpi_ps_delete_parse_tree) to improve performance and reduce code size. (Code provided by Alexey Starikovskiy.) Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dsmethod.c | 11 +- drivers/acpi/dispatcher/dsopcode.c | 8 ++ drivers/acpi/dispatcher/dsutils.c | 166 +++++++++++++++++++----- drivers/acpi/dispatcher/dswexec.c | 61 ++++++--- drivers/acpi/executer/exmisc.c | 5 +- drivers/acpi/executer/exresolv.c | 6 + drivers/acpi/executer/exstoren.c | 7 +- drivers/acpi/executer/exstorob.c | 27 ++-- drivers/acpi/parser/psparse.c | 42 ++++-- drivers/acpi/parser/pswalk.c | 254 +++++-------------------------------- drivers/acpi/utilities/utcopy.c | 19 ++- drivers/acpi/utilities/utmisc.c | 24 ++-- include/acpi/acconfig.h | 2 +- include/acpi/acdispat.h | 10 ++ include/acpi/acinterp.h | 1 - include/acpi/acstruct.h | 1 + 16 files changed, 330 insertions(+), 314 deletions(-) diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index fac39ba4a7b44..9f0456cb9bb55 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 66fc7549c6883..5c987a0e7b75e 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 df6b001867790..462c5d83e747f 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c @@ -54,8 +54,118 @@ 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 @@ -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 b02322e213de9..2071a0d2bbbb9 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/executer/exmisc.c b/drivers/acpi/executer/exmisc.c index fc54d4d0ccabe..b542dcd58c074 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/exresolv.c b/drivers/acpi/executer/exresolv.c index 9cccf8299dd83..7be6049111568 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 e663a48f8a1cb..d3677feb07fd9 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 b8b83331e3458..05e1ecae8d92b 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,8 +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); -#if ACPI_STRICT_CONFORMANCE +#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. @@ -161,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; @@ -187,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/parser/psparse.c b/drivers/acpi/parser/psparse.c index fd2751f512e37..e79edb53cb3b9 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 e04b1b73606b9..110d2ce917b64 100644 --- a/drivers/acpi/parser/pswalk.c +++ b/drivers/acpi/parser/pswalk.c @@ -44,7 +44,6 @@ #include #include -#include #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/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index 0b366d3b48667..0fcd98bde0d10 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/utmisc.c b/drivers/acpi/utilities/utmisc.c index bbaa918826694..f6598547389b8 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; @@ -441,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), @@ -471,6 +475,8 @@ acpi_ut_strtoul64 ( string++; } + /* All done, normal exit */ + *ret_integer = return_value; return_ACPI_STATUS (AE_OK); diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 9a98d99a7932c..2b41e47b7d809 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -64,7 +64,7 @@ /* Version string */ -#define ACPI_CA_VERSION 0x20050303 +#define ACPI_CA_VERSION 0x20050309 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h index 4efbb8d7e704b..237d63433581c 100644 --- a/include/acpi/acdispat.h +++ b/include/acpi/acdispat.h @@ -374,6 +374,16 @@ acpi_ds_create_node ( /* dsutils - Parser/Interpreter interface utility routines */ +void +acpi_ds_clear_implicit_return ( + struct acpi_walk_state *walk_state); + +u8 +acpi_ds_do_implicit_return ( + union acpi_operand_object *return_desc, + struct acpi_walk_state *walk_state, + u8 add_reference); + u8 acpi_ds_is_result_used ( union acpi_parse_object *op, diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h index 78395916e4cfb..c5301f5ffaf4f 100644 --- a/include/acpi/acinterp.h +++ b/include/acpi/acinterp.h @@ -617,7 +617,6 @@ acpi_ex_store_object_to_object ( 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); diff --git a/include/acpi/acstruct.h b/include/acpi/acstruct.h index 6b2284c9e8949..c97843f6bcbc2 100644 --- a/include/acpi/acstruct.h +++ b/include/acpi/acstruct.h @@ -94,6 +94,7 @@ struct acpi_walk_state union acpi_generic_state *control_state; /* List of control states (nested IFs) */ struct acpi_namespace_node *deferred_node; /* Used when executing deferred opcodes */ struct acpi_gpe_event_info *gpe_event_info; /* Info for GPE (_Lxx/_Exx methods only */ + union acpi_operand_object *implicit_return_obj; struct acpi_namespace_node local_variables[ACPI_METHOD_NUM_LOCALS]; /* Control method locals */ struct acpi_namespace_node *method_call_node; /* Called method Node*/ union acpi_parse_object *method_call_op; /* method_call Op if running a method */ -- cgit 1.2.3-korg From 6bd637d034744162dd553e855b4e86073df377e3 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 17 Mar 2005 13:26:54 -0500 Subject: [ACPI] build fix in acpi_pci_irq_disable() bk-acpi-acpi_pci_irq_disable-build-fix.patch Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 046b68e492e9a..12b0eea634073 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -492,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; -- cgit 1.2.3-korg From 056f267341d55d8ab47d5d79864a6386a3d69d81 Mon Sep 17 00:00:00 2001 From: David Mosberger Date: Fri, 25 Mar 2005 02:11:48 -0800 Subject: [IA64] minstate.h: fix stray backslash Trivial fix to drop a stray backslash in the MINSTATE_START_SAVE_MIN_VIRT macro. Signed-off-by: David Mosberger-Tang Signed-off-by: Tony Luck --- arch/ia64/kernel/minstate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h index a01c2cd060380..1dbc7b2497c90 100644 --- a/arch/ia64/kernel/minstate.h +++ b/arch/ia64/kernel/minstate.h @@ -26,7 +26,7 @@ (pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \ ;; \ (pUStk) mov r18=ar.bsp; \ -(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \ +(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ #define MINSTATE_END_SAVE_MIN_VIRT \ bsw.1; /* switch back to bank 1 (must be last in insn group) */ \ -- cgit 1.2.3-korg From 3a0798d0167d59768151953e3eb774b4303e7ddd Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 30 Mar 2005 19:27:34 -0800 Subject: [PATCH] Fix incorrect bluetooth socket zapping On Tue, 2005-03-15 at 22:50 +0000, Linux Kernel Mailing List wrote: > - parent->sk_zapped = 1; > + sock_set_flag(sk, SOCK_ZAPPED); Er, no. That zapped the wrong socket. Signed-off-by: David Woodhouse Signed-off-by: Linus Torvalds --- net/bluetooth/sco.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index d1361367d7495..4f19f58c9fc04 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -349,7 +349,7 @@ static void sco_sock_cleanup_listen(struct sock *parent) } parent->sk_state = BT_CLOSED; - sock_set_flag(sk, SOCK_ZAPPED); + sock_set_flag(parent, SOCK_ZAPPED); } /* Kill socket (only if zapped and orphan) -- cgit 1.2.3-korg From 587916e8047812ec4e672e738772818d00117713 Mon Sep 17 00:00:00 2001 From: Domen Puncer Date: Wed, 30 Mar 2005 22:05:14 -0800 Subject: [PATCH] i2c/i2c-ite: remove interruptible_sleep_on_timeout() usage Replace deprecated interruptible_sleep_on_timeout() with direct wait-queue usage. Patch is compile-tested, sort of; the driver does not build in vanilla kernel either, but I don't seem to add any warnings.. Signed-off-by: Nishanth Aravamudan Signed-off-by: Domen Puncer Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-ite.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c index 62638115cf119..702e3def1b81f 100644 --- a/drivers/i2c/busses/i2c-ite.c +++ b/drivers/i2c/busses/i2c-ite.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -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); -- cgit 1.2.3-korg From 739a3ab01723c3751465fbd65a5c647b9bcb5267 Mon Sep 17 00:00:00 2001 From: Domen Puncer Date: Wed, 30 Mar 2005 22:05:31 -0800 Subject: [PATCH] i2c/i2c-elektor: remove interruptible_sleep_on_timeout() usage Replace deprecated interruptible_sleep_on_timeout() with direct wait-queue usage. Patch is compile-tested. Signed-off-by: Nishanth Aravamudan Signed-off-by: Domen Puncer Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-elektor.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c index 96fc7d72904bc..23de73e37abd5 100644 --- a/drivers/i2c/busses/i2c-elektor.c +++ b/drivers/i2c/busses/i2c-elektor.c @@ -110,7 +110,7 @@ static int pcf_isa_getclock(void *data) } static void pcf_isa_waitforpin(void) { - + DEFINE_WAIT(wait); int timeout = 2; long flags; @@ -118,14 +118,15 @@ static void pcf_isa_waitforpin(void) { 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); -- cgit 1.2.3-korg From c32de391c35d5f6da1e61f2b3f1648b3dd6b77ae Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Mar 2005 22:05:50 -0800 Subject: [PATCH] I2C: New lm92 chip driver This is a new i2c chip driver named lm92. It supports the National Semiconductor LM92 and Maxim MAX6635 chips. This time I did not port the driver from the lm_sensors project but instead rewrote it. The reason is that the original driver has a different structure from the other i2c chip drivers, which would have made maintenance harder. I don't have a compatible chip myself but could test my code thanks to Mark Hoffman's i2c-stub fake bus driver. Later on, James Chapman tested it on a real chip, successfully. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/Kconfig | 11 ++ drivers/i2c/chips/Makefile | 1 + drivers/i2c/chips/lm92.c | 423 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 435 insertions(+) create mode 100644 drivers/i2c/chips/lm92.c diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index 824c62d3a66c5..e80b4c0eb8b5e 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig @@ -236,6 +236,17 @@ config SENSORS_LM90 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 diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile index a6db6f39476c2..244495867febe 100644 --- a/drivers/i2c/chips/Makefile +++ b/drivers/i2c/chips/Makefile @@ -27,6 +27,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/lm92.c b/drivers/i2c/chips/lm92.c new file mode 100644 index 0000000000000..3c9d0ef8eca79 --- /dev/null +++ b/drivers/i2c/chips/lm92.c @@ -0,0 +1,423 @@ +/* + * lm92 - Hardware monitoring driver + * Copyright (C) 2005 Jean Delvare + * + * 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 +#include +#include +#include +#include + + +/* 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 "); +MODULE_DESCRIPTION("LM92/MAX6635 driver"); +MODULE_LICENSE("GPL"); + +module_init(sensors_lm92_init); +module_exit(sensors_lm92_exit); -- cgit 1.2.3-korg From 2f8ccbc0bd0365c581be7819949120927501529e Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Mar 2005 22:06:09 -0800 Subject: [PATCH] I2C: Cleanup adm1021 unused defines While working on the adm1021 driver, I found that this driver has a number of unused (and useless) defines we could get rid of. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/adm1021.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c index 5dd7f64fdddd4..697ae07bc0089 100644 --- a/drivers/i2c/chips/adm1021.c +++ b/drivers/i2c/chips/adm1021.c @@ -28,18 +28,6 @@ #include -/* 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, -- cgit 1.2.3-korg From 74ba4335539bd1c2e8138d636619b580824892af Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Mar 2005 22:06:28 -0800 Subject: [PATCH] I2C: Fix adm1021 alarms mask This patch fixes an incorrect bitmasking on the status register in the adm1021 driver, which was causing high alarm on remote temperature to be hidden. This bug was found and reported by Jayakrishnan: http://bugzilla.kernel.org/show_bug.cgi?id=4285 Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/adm1021.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c index 697ae07bc0089..b4e3ee568265f 100644 --- a/drivers/i2c/chips/adm1021.c +++ b/drivers/i2c/chips/adm1021.c @@ -368,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) { -- cgit 1.2.3-korg From 08b49e0edf37d950c32329978d1c6f30021164ea Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Mar 2005 22:06:47 -0800 Subject: [PATCH] I2C: Kill unused struct members in w83627hf driver I just noticed that the pwmenable struct members in the w83627hf driver are not used anywhere (and quite rightly so, as PWM cannot be disabled in these chips as far as I know). Let's just get rid of them and save some bytes of memory. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/w83627hf.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c index 986dba3f0a727..133e449dc14ef 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); -- cgit 1.2.3-korg From e6f6019ad2a158520072f411f74599952147b8ec Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Mar 2005 22:07:05 -0800 Subject: [PATCH] I2C: Make master_xfer debug messages more useful While working on the recent saa7110 mess, I found that the debug message displayed when calling master_xfer wasn't as useful as it could be. Here is a patch improving this. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/i2c-core.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 56a67457341d4..474ddb6fe2523 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); -- cgit 1.2.3-korg From 4a7d66b47239c8f5ffdf03093ea9142600f81d21 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Mar 2005 22:07:24 -0800 Subject: [PATCH] I2C: Skip broken detection step in it87 One of the detection steps in the it87 chip driver was reported to be broken for some revisions of the IT8712F chip [1] [2]. This detection step is a legacy from the lm78 driver and the documentation available for the IT8705F and IT8712F chips does not mention it at all. For this reason, I propose to skip this detection step for Super-I/O chips. Super-I/O chips have already been identified when we reach this step, so it is redundant (additionally do being broken). This closes bug #4335. [1] http://bugzilla.kernel.org/show_bug.cgi?id=4335 [2] http://archives.andrew.net.au/lm-sensors/msg29962.html Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/it87.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c index e62c2e390076b..686fb756407c0 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. */ -- cgit 1.2.3-korg From 723b671797aa735903e11c240e014beb50487481 Mon Sep 17 00:00:00 2001 From: "grant_nospam@dodo.com.au" Date: Wed, 30 Mar 2005 22:07:43 -0800 Subject: [PATCH] I2C: group Intel on I2C Hardware Bus support From an end-user perspective it is easy to miss the third Intel PIIX entry on the menuconfig "I2C Hardware Bus support" screen. Also the Intel 801 menu item does not mention ICH. This trivial patch groups three Intel entries together, adds ICH to menu item, and ICH5/ICH5R to the help section. Includes suggestions from Jean Delvare. Signed-off-by: Grant Coady Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/Kconfig | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 34ff2ecad216f..edf8051da3b4c 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 -- cgit 1.2.3-korg From 9b3cc645c34014149c3c66bf38e6b6f715d345b2 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Wed, 30 Mar 2005 22:08:02 -0800 Subject: [PATCH] i2c: new driver for ds1337 RTC Signed-off-by: James Chapman Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/Kconfig | 11 ++ drivers/i2c/chips/Makefile | 1 + drivers/i2c/chips/ds1337.c | 402 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 414 insertions(+) create mode 100644 drivers/i2c/chips/ds1337.c diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index e80b4c0eb8b5e..86aafca0db2cd 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig @@ -362,6 +362,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 244495867febe..65599161a172d 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 diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c new file mode 100644 index 0000000000000..07f16c3fb084d --- /dev/null +++ b/drivers/i2c/chips/ds1337.c @@ -0,0 +1,402 @@ +/* + * linux/drivers/i2c/chips/ds1337.c + * + * Copyright (C) 2005 James Chapman + * + * 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 +#include +#include +#include +#include +#include +#include +#include /* get the user-level API */ +#include +#include + +/* 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 "); +MODULE_DESCRIPTION("DS1337 RTC driver"); +MODULE_LICENSE("GPL"); + +module_init(ds1337_init); +module_exit(ds1337_exit); -- cgit 1.2.3-korg From 9800e965a4fbe190a8b5bdb1b52b415564d67757 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Wed, 30 Mar 2005 22:08:21 -0800 Subject: [PATCH] i2c: add adt7461 chip support to lm90 driver i2c: add adt7461 chip support The Analog Devices ADT7461 temperature sensor chip is compatible with the lm90 device provided its extended temperature range is not enabled. The chip will be ignored if the boot firmware enables extended temperature range. Also, since the adt7461 treats temp values <0 as 0 and >127 as 127, the driver prevents temperature values outside the supported range from being set. Signed-off-by: James Chapman Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/lm90.c | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/chips/lm90.c b/drivers/i2c/chips/lm90.c index 7540b230173e8..02e22b128b045 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 */ -- cgit 1.2.3-korg From ac2093ee725623caaf34ebaa36709e10e38cfa31 Mon Sep 17 00:00:00 2001 From: Frank Beesley Date: Wed, 30 Mar 2005 22:08:41 -0800 Subject: [PATCH] I2C: Clean up of i2c-elektor.c build This patch changes the flags variable type from long to unsigned long in one function. This removes a couple of warnings from the compile messages for elektor i2c bus driver. Signed-off-by: Frank Beesley Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-elektor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c index 23de73e37abd5..0a7720000a0c5 100644 --- a/drivers/i2c/busses/i2c-elektor.c +++ b/drivers/i2c/busses/i2c-elektor.c @@ -112,7 +112,7 @@ 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); -- cgit 1.2.3-korg From 97bb8b5a4da985dd64205ac587c5f53203a31bd2 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Wed, 30 Mar 2005 22:09:00 -0800 Subject: [PATCH] I2C: Fix breakage in m41t00 i2c rtc driver Remove setting of deleted i2c_client structure member. The latest include/linux/i2c.h:i2c_client structure no longer has an 'id' member. This patch removes the setting of that no longer existing member. Signed-off-by: Mark A. Greer Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/m41t00.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c index de270e920207a..e771566dffa8d 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; -- cgit 1.2.3-korg From 83be2048777eef368cf016ff54c31ba39f474a5b Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Mar 2005 22:09:20 -0800 Subject: [PATCH] I2C: Fix some i2c algorithm initialization While searching for i2c_algorithm declarations missing their .functionality member, I found three of them which were not properly initialized. i2c-algo-ite and i2c_sibyte_algo do not use the C99 initialization syntax, and i2c-ibm_iic.c explicitely initializes NULL members. Following patch puts some order in there. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/algos/i2c-algo-ite.c | 13 +++++-------- drivers/i2c/algos/i2c-algo-sibyte.c | 13 +++++-------- drivers/i2c/busses/i2c-ibm_iic.c | 4 ---- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/drivers/i2c/algos/i2c-algo-ite.c b/drivers/i2c/algos/i2c-algo-ite.c index ffd87404b0a0e..68e9e6832ca0c 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-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c index ea1a9047a3b25..35789bb7126a3 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/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 17326cdd68d74..bb885215c08d6 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 }; -- cgit 1.2.3-korg From cce0115c7b01dc9ed2b7be85eb9940db384de65f Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Mar 2005 22:09:38 -0800 Subject: [PATCH] I2C: Kill outdated defines in i2c.h Some defines in i2c.h (I2C_CLIENT_MODPARM and friends) are now useless. They should have been removed when the i2c client parameters were converted from MODULE_PARAM to module_parm_array, but where not. This patch removes them now. Additionally, it moves the definition of I2C_CLIENT_MAX_OPTS next to where it is used rather than 220 lines before, which is preferable IMHO. As a side note, I think that there is a bug in the way these options are handled. The i2c code looks for I2C_CLIENT_END as a list terminator, but if the maximum number of parameters are actually provided, no terminator will be left. It's rather unlikely to happen because nobody will probably ever provide that many parameters, but this should probably be fixed. I'll address this issue later, since I plan to completely rewrite the way these parameters are handled anyway. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- include/linux/i2c.h | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/include/linux/i2c.h b/include/linux/i2c.h index da901fd6b5908..9f2ae600683c6 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -306,9 +306,6 @@ struct i2c_client_address_data { #define ANY_I2C_BUS 0xffff #define ANY_I2C_ISA_BUS 9191 -/* The length of the option lists */ -#define I2C_CLIENT_MAX_OPTS 48 - /* ----- functions exported by i2c.o */ @@ -526,6 +523,9 @@ union i2c_smbus_data { #define I2C_MAJOR 89 /* Device major number */ /* These defines are used for probing i2c client addresses */ +/* The length of the option lists */ +#define I2C_CLIENT_MAX_OPTS 48 + /* Default fill of many variables */ #define I2C_CLIENT_DEFAULTS {I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ @@ -544,19 +544,12 @@ union i2c_smbus_data { I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END} -/* This is ugly. We need to evaluate I2C_CLIENT_MAX_OPTS before it is - stringified */ -#define I2C_CLIENT_MODPARM_AUX1(x) "1-" #x "h" -#define I2C_CLIENT_MODPARM_AUX(x) I2C_CLIENT_MODPARM_AUX1(x) -#define I2C_CLIENT_MODPARM I2C_CLIENT_MODPARM_AUX(I2C_CLIENT_MAX_OPTS) - /* I2C_CLIENT_MODULE_PARM creates a module parameter, and puts it in the module header */ #define I2C_CLIENT_MODULE_PARM(var,desc) \ static unsigned short var[I2C_CLIENT_MAX_OPTS] = I2C_CLIENT_DEFAULTS; \ static unsigned int var##_num; \ - /*MODULE_PARM(var,I2C_CLIENT_MODPARM);*/ \ module_param_array(var, short, &var##_num, 0); \ MODULE_PARM_DESC(var,desc) -- cgit 1.2.3-korg From 79e63ffa339d60d47cdc4c5711009e2ef26e54fb Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Mar 2005 22:28:46 -0800 Subject: [PATCH] I2C: Avoid repeated resets of i2c-viapro It was reported that the i2c-viapro SMBus driver sometimes has trouble on recent systems (VT8237 south bridge). The "Host Status" register has at least one additional bit used when compared with older south bridges of this family. The driver currently considers this additional bit as an error condition when it's set, causing repeated bus resets and sometimes read failures. This patch makes the driver ignore the bits of the "Host Status" register for which no definition is known. I wish I had a datasheet for the VIA VT8237, so that I could check what the additional bit is supposed to mean, but I don't. If someone has a datasheet or good contacts at VIA, please let me know. The patch was reported to fix the problem on a system with the VT8237, and was also tested not to break the driver on older VIA south bridges, so it seems to be safe. Thanks to Aurelien Jarno for the tests. Additionally, the patch makes the post-transaction bus reset slightly more efficient by sparing a few unneeded I/O operations. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-viapro.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index c872c2849a0bf..0bb60a636e166 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), -- cgit 1.2.3-korg From 939836f95cd1e78089f92c471c20b8d915a35a7f Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Mar 2005 22:29:05 -0800 Subject: [PATCH] I2C: Recognize new revision of the ADT7463 chip This simple patch to the lm85 driver adds recognition of a new revision of the ADT7463 chip. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/lm85.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c index d17aba4e42fcd..e96ad5ba5c9d0 100644 --- a/drivers/i2c/chips/lm85.c +++ b/drivers/i2c/chips/lm85.c @@ -74,6 +74,7 @@ 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 @@ -1089,7 +1090,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 ) { -- cgit 1.2.3-korg From fe198b354feb31463c396376359bfd684f2910dd Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Mar 2005 22:29:23 -0800 Subject: [PATCH] I2C: Fix Vaio EEPROM detection This fixes a bug in the eeprom driver, which made all EEPROMs at location 0x57 be erroneously treated as Vaio EEPROMs. I have to say I'm quite ashamed that I introduced the bug in the first place, as this was a really stupid one. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/eeprom.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index f126d011cfee2..cbdfa2db6f7c9 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 */ -- cgit 1.2.3-korg From 5efe36c305f7927d9e06ba12465efba2e6dbeb73 Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Wed, 30 Mar 2005 22:29:46 -0800 Subject: [PATCH] I2C: busses documentation update 1 of 2 This patch just moves i2c-parport file to busses directory. Patch for other busses documentation will follow. Signed-off-by: Rudolf Marek Signed-off-by: Greg Kroah-Hartman --- Documentation/i2c/busses/i2c-parport | 156 +++++++++++++++++++++++++++++++++++ Documentation/i2c/i2c-parport | 156 ----------------------------------- 2 files changed, 156 insertions(+), 156 deletions(-) create mode 100644 Documentation/i2c/busses/i2c-parport delete mode 100644 Documentation/i2c/i2c-parport diff --git a/Documentation/i2c/busses/i2c-parport b/Documentation/i2c/busses/i2c-parport new file mode 100644 index 0000000000000..d359461ce9b23 --- /dev/null +++ b/Documentation/i2c/busses/i2c-parport @@ -0,0 +1,156 @@ +================== +i2c-parport driver +================== + +2004-07-06, Jean Delvare + +This is a unified driver for several i2c-over-parallel-port adapters, +such as the ones made by Philips, Velleman or ELV. This driver is +meant as a replacement for the older, individual drivers: + * i2c-philips-par + * i2c-elv + * i2c-velleman + * video/i2c-parport (NOT the same as this one, dedicated to home brew + teletext adapters) + +It currently supports the following devices: + * Philips adapter + * home brew teletext adapter + * Velleman K8000 adapter + * ELV adapter + * Analog Devices evaluation boards (ADM1025, ADM1030, ADM1031, ADM1032) + +These devices use different pinout configurations, so you have to tell +the driver what you have, using the type module parameter. There is no +way to autodetect the devices. Support for different pinout configurations +can be easily added when needed. + + +Building your own adapter +------------------------- + +If you want to build you own i2c-over-parallel-port adapter, here is +a sample electronics schema (credits go to Sylvain Munaut): + +Device PC +Side ___________________Vdd (+) Side + | | | + --- --- --- + | | | | | | + |R| |R| |R| + | | | | | | + --- --- --- + | | | + | | /| | +SCL ----------x--------o |-----------x------------------- pin 2 + | \| | | + | | | + | |\ | | +SDA ----------x----x---| o---x--------------------------- pin 13 + | |/ | + | | + | /| | + ---------o |----------------x-------------- pin 3 + \| | | + | | + --- --- + | | | | + |R| |R| + | | | | + --- --- + | | + ### ### + GND GND + +Remarks: + - This is the exact pinout and electronics used on the Analog Devices + evaluation boards. + /| + - All inverters -o |- must be 74HC05, they must be open collector output. + \| + - All resitors are 10k. + - Pins 18-25 of the parallel port connected to GND. + - Pins 4-9 (D2-D7) could be used as VDD is the driver drives them high. + The ADM1032 evaluation board uses D4-D7. Beware that the amount of + current you can draw from the parallel port is limited. Also note that + all connected lines MUST BE driven at the same state, else you'll short + circuit the output buffers! So plugging the I2C adapter after loading + the i2c-parport module might be a good safety since data line state + prior to init may be unknown. + - This is 5V! + - Obviously you cannot read SCL (so it's not really standard-compliant). + Pretty easy to add, just copy the SDA part and use another input pin. + That would give (ELV compatible pinout): + + +Device PC +Side ______________________________Vdd (+) Side + | | | | + --- --- --- --- + | | | | | | | | + |R| |R| |R| |R| + | | | | | | | | + --- --- --- --- + | | | | + | | |\ | | +SCL ----------x--------x--| o---x------------------------ pin 15 + | | |/ | + | | | + | | /| | + | ---o |-------------x-------------- pin 2 + | \| | | + | | | + | | | + | |\ | | +SDA ---------------x---x--| o--------x------------------- pin 10 + | |/ | + | | + | /| | + ---o |------------------x--------- pin 3 + \| | | + | | + --- --- + | | | | + |R| |R| + | | | | + --- --- + | | + ### ### + GND GND + + +If possible, you should use the same pinout configuration as existing +adapters do, so you won't even have to change the code. + + +Similar (but different) drivers +------------------------------- + +This driver is NOT the same as the i2c-pport driver found in the i2c package. +The i2c-pport driver makes use of modern parallel port features so that +you don't need additional electronics. It has other restrictions however, and +was not ported to Linux 2.6 (yet). + +This driver is also NOT the same as the i2c-pcf-epp driver found in the +lm_sensors package. The i2c-pcf-epp driver doesn't use the parallel port +as an I2C bus directly. Instead, it uses it to control an external I2C bus +master. That driver was not ported to Linux 2.6 (yet) either. + + +Legacy documentation for Velleman adapter +----------------------------------------- + +Useful links: +Velleman http://www.velleman.be/ +Velleman K8000 Howto http://howto.htlw16.ac.at/k8000-howto.html + +The project has lead to new libs for the Velleman K8000 and K8005: + LIBK8000 v1.99.1 and LIBK8005 v0.21 +With these libs, you can control the K8000 interface card and the K8005 +stepper motor card with the simple commands which are in the original +Velleman software, like SetIOchannel, ReadADchannel, SendStepCCWFull and +many more, using /dev/velleman. + http://home.wanadoo.nl/hihihi/libk8000.htm + http://home.wanadoo.nl/hihihi/libk8005.htm + http://struyve.mine.nu:8080/index.php?block=k8000 + http://sourceforge.net/projects/libk8005/ diff --git a/Documentation/i2c/i2c-parport b/Documentation/i2c/i2c-parport deleted file mode 100644 index d359461ce9b23..0000000000000 --- a/Documentation/i2c/i2c-parport +++ /dev/null @@ -1,156 +0,0 @@ -================== -i2c-parport driver -================== - -2004-07-06, Jean Delvare - -This is a unified driver for several i2c-over-parallel-port adapters, -such as the ones made by Philips, Velleman or ELV. This driver is -meant as a replacement for the older, individual drivers: - * i2c-philips-par - * i2c-elv - * i2c-velleman - * video/i2c-parport (NOT the same as this one, dedicated to home brew - teletext adapters) - -It currently supports the following devices: - * Philips adapter - * home brew teletext adapter - * Velleman K8000 adapter - * ELV adapter - * Analog Devices evaluation boards (ADM1025, ADM1030, ADM1031, ADM1032) - -These devices use different pinout configurations, so you have to tell -the driver what you have, using the type module parameter. There is no -way to autodetect the devices. Support for different pinout configurations -can be easily added when needed. - - -Building your own adapter -------------------------- - -If you want to build you own i2c-over-parallel-port adapter, here is -a sample electronics schema (credits go to Sylvain Munaut): - -Device PC -Side ___________________Vdd (+) Side - | | | - --- --- --- - | | | | | | - |R| |R| |R| - | | | | | | - --- --- --- - | | | - | | /| | -SCL ----------x--------o |-----------x------------------- pin 2 - | \| | | - | | | - | |\ | | -SDA ----------x----x---| o---x--------------------------- pin 13 - | |/ | - | | - | /| | - ---------o |----------------x-------------- pin 3 - \| | | - | | - --- --- - | | | | - |R| |R| - | | | | - --- --- - | | - ### ### - GND GND - -Remarks: - - This is the exact pinout and electronics used on the Analog Devices - evaluation boards. - /| - - All inverters -o |- must be 74HC05, they must be open collector output. - \| - - All resitors are 10k. - - Pins 18-25 of the parallel port connected to GND. - - Pins 4-9 (D2-D7) could be used as VDD is the driver drives them high. - The ADM1032 evaluation board uses D4-D7. Beware that the amount of - current you can draw from the parallel port is limited. Also note that - all connected lines MUST BE driven at the same state, else you'll short - circuit the output buffers! So plugging the I2C adapter after loading - the i2c-parport module might be a good safety since data line state - prior to init may be unknown. - - This is 5V! - - Obviously you cannot read SCL (so it's not really standard-compliant). - Pretty easy to add, just copy the SDA part and use another input pin. - That would give (ELV compatible pinout): - - -Device PC -Side ______________________________Vdd (+) Side - | | | | - --- --- --- --- - | | | | | | | | - |R| |R| |R| |R| - | | | | | | | | - --- --- --- --- - | | | | - | | |\ | | -SCL ----------x--------x--| o---x------------------------ pin 15 - | | |/ | - | | | - | | /| | - | ---o |-------------x-------------- pin 2 - | \| | | - | | | - | | | - | |\ | | -SDA ---------------x---x--| o--------x------------------- pin 10 - | |/ | - | | - | /| | - ---o |------------------x--------- pin 3 - \| | | - | | - --- --- - | | | | - |R| |R| - | | | | - --- --- - | | - ### ### - GND GND - - -If possible, you should use the same pinout configuration as existing -adapters do, so you won't even have to change the code. - - -Similar (but different) drivers -------------------------------- - -This driver is NOT the same as the i2c-pport driver found in the i2c package. -The i2c-pport driver makes use of modern parallel port features so that -you don't need additional electronics. It has other restrictions however, and -was not ported to Linux 2.6 (yet). - -This driver is also NOT the same as the i2c-pcf-epp driver found in the -lm_sensors package. The i2c-pcf-epp driver doesn't use the parallel port -as an I2C bus directly. Instead, it uses it to control an external I2C bus -master. That driver was not ported to Linux 2.6 (yet) either. - - -Legacy documentation for Velleman adapter ------------------------------------------ - -Useful links: -Velleman http://www.velleman.be/ -Velleman K8000 Howto http://howto.htlw16.ac.at/k8000-howto.html - -The project has lead to new libs for the Velleman K8000 and K8005: - LIBK8000 v1.99.1 and LIBK8005 v0.21 -With these libs, you can control the K8000 interface card and the K8005 -stepper motor card with the simple commands which are in the original -Velleman software, like SetIOchannel, ReadADchannel, SendStepCCWFull and -many more, using /dev/velleman. - http://home.wanadoo.nl/hihihi/libk8000.htm - http://home.wanadoo.nl/hihihi/libk8005.htm - http://struyve.mine.nu:8080/index.php?block=k8000 - http://sourceforge.net/projects/libk8005/ -- cgit 1.2.3-korg From c10d3e4b15da22c193d40c7ade107509af11e7d0 Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Wed, 30 Mar 2005 22:30:05 -0800 Subject: [PATCH] I2C: busses documentation update 2 of 2 Patch contains promised documentation update for i2c bus drivers. I would like to thank Jean Delvare and Aurelien Jarno for their comments. Signed-off-by: Rudolf Marek Signed-off-by: Greg Kroah-Hartman --- Documentation/i2c/busses/i2c-ali1535 | 42 +++++++++++ Documentation/i2c/busses/i2c-ali1563 | 27 +++++++ Documentation/i2c/busses/i2c-ali15x3 | 112 +++++++++++++++++++++++++++++ Documentation/i2c/busses/i2c-amd756 | 25 +++++++ Documentation/i2c/busses/i2c-amd8111 | 41 +++++++++++ Documentation/i2c/busses/i2c-i801 | 80 +++++++++++++++++++++ Documentation/i2c/busses/i2c-i810 | 46 ++++++++++++ Documentation/i2c/busses/i2c-nforce2 | 41 +++++++++++ Documentation/i2c/busses/i2c-parport | 18 +++-- Documentation/i2c/busses/i2c-parport-light | 11 +++ Documentation/i2c/busses/i2c-pca-isa | 23 ++++++ Documentation/i2c/busses/i2c-piix4 | 72 +++++++++++++++++++ Documentation/i2c/busses/i2c-prosavage | 23 ++++++ Documentation/i2c/busses/i2c-savage4 | 26 +++++++ Documentation/i2c/busses/i2c-sis5595 | 59 +++++++++++++++ Documentation/i2c/busses/i2c-sis630 | 49 +++++++++++++ Documentation/i2c/busses/i2c-sis69x | 73 +++++++++++++++++++ Documentation/i2c/busses/i2c-via | 34 +++++++++ Documentation/i2c/busses/i2c-viapro | 47 ++++++++++++ Documentation/i2c/busses/i2c-voodoo3 | 62 ++++++++++++++++ Documentation/i2c/busses/scx200_acb | 14 ++++ 21 files changed, 915 insertions(+), 10 deletions(-) create mode 100644 Documentation/i2c/busses/i2c-ali1535 create mode 100644 Documentation/i2c/busses/i2c-ali1563 create mode 100644 Documentation/i2c/busses/i2c-ali15x3 create mode 100644 Documentation/i2c/busses/i2c-amd756 create mode 100644 Documentation/i2c/busses/i2c-amd8111 create mode 100644 Documentation/i2c/busses/i2c-i801 create mode 100644 Documentation/i2c/busses/i2c-i810 create mode 100644 Documentation/i2c/busses/i2c-nforce2 create mode 100644 Documentation/i2c/busses/i2c-parport-light create mode 100644 Documentation/i2c/busses/i2c-pca-isa create mode 100644 Documentation/i2c/busses/i2c-piix4 create mode 100644 Documentation/i2c/busses/i2c-prosavage create mode 100644 Documentation/i2c/busses/i2c-savage4 create mode 100644 Documentation/i2c/busses/i2c-sis5595 create mode 100644 Documentation/i2c/busses/i2c-sis630 create mode 100644 Documentation/i2c/busses/i2c-sis69x create mode 100644 Documentation/i2c/busses/i2c-via create mode 100644 Documentation/i2c/busses/i2c-viapro create mode 100644 Documentation/i2c/busses/i2c-voodoo3 create mode 100644 Documentation/i2c/busses/scx200_acb diff --git a/Documentation/i2c/busses/i2c-ali1535 b/Documentation/i2c/busses/i2c-ali1535 new file mode 100644 index 0000000000000..0db3b4c74ad11 --- /dev/null +++ b/Documentation/i2c/busses/i2c-ali1535 @@ -0,0 +1,42 @@ +Kernel driver i2c-ali1535 + +Supported adapters: + * Acer Labs, Inc. ALI 1535 (south bridge) + Datasheet: Now under NDA + http://www.ali.com.tw/eng/support/datasheet_request.php + +Authors: + Frodo Looijaard , + Philip Edelbrock , + Mark D. Studebaker , + Dan Eaton , + Stephen Rousset + +Description +----------- + +This is the driver for the SMB Host controller on Acer Labs Inc. (ALI) +M1535 South Bridge. + +The M1535 is a South bridge for portable systems. It is very similar to the +M15x3 South bridges also produced by Acer Labs Inc. Some of the registers +within the part have moved and some have been redefined slightly. +Additionally, the sequencing of the SMBus transactions has been modified to +be more consistent with the sequencing recommended by the manufacturer and +observed through testing. These changes are reflected in this driver and +can be identified by comparing this driver to the i2c-ali15x3 driver. For +an overview of these chips see http://www.acerlabs.com + +The SMB controller is part of the M7101 device, which is an ACPI-compliant +Power Management Unit (PMU). + +The whole M7101 device has to be enabled for the SMB to work. You can't +just enable the SMB alone. The SMB and the ACPI have separate I/O spaces. +We make sure that the SMB is enabled. We leave the ACPI alone. + + +Features +-------- + +This driver controls the SMB Host only. This driver does not use +interrupts. diff --git a/Documentation/i2c/busses/i2c-ali1563 b/Documentation/i2c/busses/i2c-ali1563 new file mode 100644 index 0000000000000..99ad4b9bcc32e --- /dev/null +++ b/Documentation/i2c/busses/i2c-ali1563 @@ -0,0 +1,27 @@ +Kernel driver i2c-ali1563 + +Supported adapters: + * Acer Labs, Inc. ALI 1563 (south bridge) + Datasheet: Now under NDA + http://www.ali.com.tw/eng/support/datasheet_request.php + +Author: Patrick Mochel + +Description +----------- + +This is the driver for the SMB Host controller on Acer Labs Inc. (ALI) +M1563 South Bridge. + +For an overview of these chips see http://www.acerlabs.com + +The M1563 southbridge is deceptively similar to the M1533, with a few +notable exceptions. One of those happens to be the fact they upgraded the +i2c core to be SMBus 2.0 compliant, and happens to be almost identical to +the i2c controller found in the Intel 801 south bridges. + +Features +-------- + +This driver controls the SMB Host only. This driver does not use +interrupts. diff --git a/Documentation/i2c/busses/i2c-ali15x3 b/Documentation/i2c/busses/i2c-ali15x3 new file mode 100644 index 0000000000000..ff28d381bebe8 --- /dev/null +++ b/Documentation/i2c/busses/i2c-ali15x3 @@ -0,0 +1,112 @@ +Kernel driver i2c-ali15x3 + +Supported adapters: + * Acer Labs, Inc. ALI 1533 and 1543C (south bridge) + Datasheet: Now under NDA + http://www.ali.com.tw/eng/support/datasheet_request.php + +Authors: + Frodo Looijaard , + Philip Edelbrock , + Mark D. Studebaker + +Module Parameters +----------------- + +* force_addr: int + Initialize the base address of the i2c controller + + +Notes +----- + +The force_addr parameter is useful for boards that don't set the address in +the BIOS. Does not do a PCI force; the device must still be present in +lspci. Don't use this unless the driver complains that the base address is +not set. + +Example: 'modprobe i2c-ali15x3 force_addr=0xe800' + +SMBus periodically hangs on ASUS P5A motherboards and can only be cleared +by a power cycle. Cause unknown (see Issues below). + + +Description +----------- + +This is the driver for the SMB Host controller on Acer Labs Inc. (ALI) +M1541 and M1543C South Bridges. + +The M1543C is a South bridge for desktop systems. +The M1541 is a South bridge for portable systems. +They are part of the following ALI chipsets: + + * "Aladdin Pro 2" includes the M1621 Slot 1 North bridge with AGP and + 100MHz CPU Front Side bus + * "Aladdin V" includes the M1541 Socket 7 North bridge with AGP and 100MHz + CPU Front Side bus + Some Aladdin V motherboards: + Asus P5A + Atrend ATC-5220 + BCM/GVC VP1541 + Biostar M5ALA + Gigabyte GA-5AX (** Generally doesn't work because the BIOS doesn't + enable the 7101 device! **) + Iwill XA100 Plus + Micronics C200 + Microstar (MSI) MS-5169 + + * "Aladdin IV" includes the M1541 Socket 7 North bridge + with host bus up to 83.3 MHz. + +For an overview of these chips see http://www.acerlabs.com. At this time the +full data sheets on the web site are password protected, however if you +contact the ALI office in San Jose they may give you the password. + +The M1533/M1543C devices appear as FOUR separate devices on the PCI bus. An +output of lspci will show something similar to the following: + + 00:02.0 USB Controller: Acer Laboratories Inc. M5237 (rev 03) + 00:03.0 Bridge: Acer Laboratories Inc. M7101 <= THIS IS THE ONE WE NEED + 00:07.0 ISA bridge: Acer Laboratories Inc. M1533 (rev c3) + 00:0f.0 IDE interface: Acer Laboratories Inc. M5229 (rev c1) + +** IMPORTANT ** +** If you have a M1533 or M1543C on the board and you get +** "ali15x3: Error: Can't detect ali15x3!" +** then run lspci. +** If you see the 1533 and 5229 devices but NOT the 7101 device, +** then you must enable ACPI, the PMU, SMB, or something similar +** in the BIOS. +** The driver won't work if it can't find the M7101 device. + +The SMB controller is part of the M7101 device, which is an ACPI-compliant +Power Management Unit (PMU). + +The whole M7101 device has to be enabled for the SMB to work. You can't +just enable the SMB alone. The SMB and the ACPI have separate I/O spaces. +We make sure that the SMB is enabled. We leave the ACPI alone. + +Features +-------- + +This driver controls the SMB Host only. The SMB Slave +controller on the M15X3 is not enabled. This driver does not use +interrupts. + + +Issues +------ + +This driver requests the I/O space for only the SMB +registers. It doesn't use the ACPI region. + +On the ASUS P5A motherboard, there are several reports that +the SMBus will hang and this can only be resolved by +powering off the computer. It appears to be worse when the board +gets hot, for example under heavy CPU load, or in the summer. +There may be electrical problems on this board. +On the P5A, the W83781D sensor chip is on both the ISA and +SMBus. Therefore the SMBus hangs can generally be avoided +by accessing the W83781D on the ISA bus only. + diff --git a/Documentation/i2c/busses/i2c-amd756 b/Documentation/i2c/busses/i2c-amd756 new file mode 100644 index 0000000000000..67f30874d0bfb --- /dev/null +++ b/Documentation/i2c/busses/i2c-amd756 @@ -0,0 +1,25 @@ +Kernel driver i2c-amd756 + +Supported adapters: + * AMD 756 + * AMD 766 + * AMD 768 + * AMD 8111 + Datasheets: Publicly available on AMD website + + * nVidia nForce + Datasheet: Unavailable + +Authors: + Frodo Looijaard , + Philip Edelbrock + +Description +----------- + +This driver supports the AMD 756, 766, 768 and 8111 Peripheral Bus +Controllers, and the nVidia nForce. + +Note that for the 8111, there are two SMBus adapters. The SMBus 1.0 adapter +is supported by this driver, and the SMBus 2.0 adapter is supported by the +i2c-amd8111 driver. diff --git a/Documentation/i2c/busses/i2c-amd8111 b/Documentation/i2c/busses/i2c-amd8111 new file mode 100644 index 0000000000000..db294ee7455a4 --- /dev/null +++ b/Documentation/i2c/busses/i2c-amd8111 @@ -0,0 +1,41 @@ +Kernel driver i2c-adm8111 + +Supported adapters: + * AMD-8111 SMBus 2.0 PCI interface + +Datasheets: + AMD datasheet not yet available, but almost everything can be found + in publically available ACPI 2.0 specification, which the adapter + follows. + +Author: Vojtech Pavlik + +Description +----------- + +If you see something like this: + +00:07.2 SMBus: Advanced Micro Devices [AMD] AMD-8111 SMBus 2.0 (rev 02) + Subsystem: Advanced Micro Devices [AMD] AMD-8111 SMBus 2.0 + Flags: medium devsel, IRQ 19 + I/O ports at d400 [size=32] + +in your 'lspci -v', then this driver is for your chipset. + +Process Call Support +-------------------- + +Supported. + +SMBus 2.0 Support +----------------- + +Supported. Both PEC and block process call support is implemented. Slave +mode or host notification are not yet implemented. + +Notes +----- + +Note that for the 8111, there are two SMBus adapters. The SMBus 2.0 adapter +is supported by this driver, and the SMBus 1.0 adapter is supported by the +i2c-amd756 driver. diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801 new file mode 100644 index 0000000000000..fd4b2712d570a --- /dev/null +++ b/Documentation/i2c/busses/i2c-i801 @@ -0,0 +1,80 @@ +Kernel driver i2c-i801 + +Supported adapters: + * Intel 82801AA and 82801AB (ICH and ICH0 - part of the + '810' and '810E' chipsets) + * Intel 82801BA (ICH2 - part of the '815E' chipset) + * Intel 82801CA/CAM (ICH3) + * Intel 82801DB (ICH4) (HW PEC supported, 32 byte buffer not supported) + * Intel 82801EB/ER (ICH5) (HW PEC supported, 32 byte buffer not supported) + * Intel 6300ESB + * Intel 82801FB/FR/FW/FRW (ICH6) + * Intel ICH7 + Datasheets: Publicly available at the Intel website + +Authors: + Frodo Looijaard , + Philip Edelbrock , + Mark Studebaker + + +Module Parameters +----------------- + +* force_addr: int + Forcibly enable the ICH at the given address. EXTREMELY DANGEROUS! + + +Description +----------- + +The ICH (properly known as the 82801AA), ICH0 (82801AB), ICH2 (82801BA), +ICH3 (82801CA/CAM) and later devices are Intel chips that are a part of +Intel's '810' chipset for Celeron-based PCs, '810E' chipset for +Pentium-based PCs, '815E' chipset, and others. + +The ICH chips contain at least SEVEN separate PCI functions in TWO logical +PCI devices. An output of lspci will show something similar to the +following: + + 00:1e.0 PCI bridge: Intel Corporation: Unknown device 2418 (rev 01) + 00:1f.0 ISA bridge: Intel Corporation: Unknown device 2410 (rev 01) + 00:1f.1 IDE interface: Intel Corporation: Unknown device 2411 (rev 01) + 00:1f.2 USB Controller: Intel Corporation: Unknown device 2412 (rev 01) + 00:1f.3 Unknown class [0c05]: Intel Corporation: Unknown device 2413 (rev 01) + +The SMBus controller is function 3 in device 1f. Class 0c05 is SMBus Serial +Controller. + +If you do NOT see the 24x3 device at function 3, and you can't figure out +any way in the BIOS to enable it, + +The ICH chips are quite similar to Intel's PIIX4 chip, at least in the +SMBus controller. + +See the file i2c-piix4 for some additional information. + + +Process Call Support +-------------------- + +Not supported. + + +I2C Block Read Support +---------------------- + +Not supported at the moment. + + +SMBus 2.0 Support +----------------- + +The 82801DB (ICH4) and later chips support several SMBus 2.0 features. + +********************** +The lm_sensors project gratefully acknowledges the support of Texas +Instruments in the initial development of this driver. + +The lm_sensors project gratefully acknowledges the support of Intel in the +development of SMBus 2.0 / ICH4 features of this driver. diff --git a/Documentation/i2c/busses/i2c-i810 b/Documentation/i2c/busses/i2c-i810 new file mode 100644 index 0000000000000..0544eb3328879 --- /dev/null +++ b/Documentation/i2c/busses/i2c-i810 @@ -0,0 +1,46 @@ +Kernel driver i2c-i810 + +Supported adapters: + * Intel 82810, 82810-DC100, 82810E, and 82815 (GMCH) + +Authors: + Frodo Looijaard , + Philip Edelbrock , + Kyösti Mälkki , + Ralph Metzler , + Mark D. Studebaker + +Main contact: Mark Studebaker + +Description +----------- + +WARNING: If you have an '810' or '815' motherboard, your standard I2C +temperature sensors are most likely on the 801's I2C bus. You want the +i2c-i801 driver for those, not this driver. + +Now for the i2c-i810... + +The GMCH chip contains two I2C interfaces. + +The first interface is used for DDC (Data Display Channel) which is a +serial channel through the VGA monitor connector to a DDC-compliant +monitor. This interface is defined by the Video Electronics Standards +Association (VESA). The standards are available for purchase at +http://www.vesa.org . + +The second interface is a general-purpose I2C bus. It may be connected to a +TV-out chip such as the BT869 or possibly to a digital flat-panel display. + +Features +-------- + +Both busses use the i2c-algo-bit driver for 'bit banging' +and support for specific transactions is provided by i2c-algo-bit. + +Issues +------ + +If you enable bus testing in i2c-algo-bit (insmod i2c-algo-bit bit_test=1), +the test may fail; if so, the i2c-i810 driver won't be inserted. However, +we think this has been fixed. diff --git a/Documentation/i2c/busses/i2c-nforce2 b/Documentation/i2c/busses/i2c-nforce2 new file mode 100644 index 0000000000000..e379e182e64f4 --- /dev/null +++ b/Documentation/i2c/busses/i2c-nforce2 @@ -0,0 +1,41 @@ +Kernel driver i2c-nforce2 + +Supported adapters: + * nForce2 MCP 10de:0064 + * nForce2 Ultra 400 MCP 10de:0084 + * nForce3 Pro150 MCP 10de:00D4 + * nForce3 250Gb MCP 10de:00E4 + * nForce4 MCP 10de:0052 + +Datasheet: not publically available, but seems to be similar to the + AMD-8111 SMBus 2.0 adapter. + +Authors: + Hans-Frieder Vogt , + Thomas Leibold , + Patrick Dreker + +Description +----------- + +i2c-nforce2 is a driver for the SMBuses included in the nVidia nForce2 MCP. + +If your 'lspci -v' listing shows something like the following, + +00:01.1 SMBus: nVidia Corporation: Unknown device 0064 (rev a2) + Subsystem: Asustek Computer, Inc.: Unknown device 0c11 + Flags: 66Mhz, fast devsel, IRQ 5 + I/O ports at c000 [size=32] + Capabilities: + +then this driver should support the SMBuses of your motherboard. + + +Notes +----- + +The SMBus adapter in the nForce2 chipset seems to be very similar to the +SMBus 2.0 adapter in the AMD-8111 southbridge. However, I could only get +the driver to work with direct I/O access, which is different to the EC +interface of the AMD-8111. Tested on Asus A7N8X. The ACPI DSDT table of the +Asus A7N8X lists two SMBuses, both of which are supported by this driver. diff --git a/Documentation/i2c/busses/i2c-parport b/Documentation/i2c/busses/i2c-parport index d359461ce9b23..9f1d0082da18b 100644 --- a/Documentation/i2c/busses/i2c-parport +++ b/Documentation/i2c/busses/i2c-parport @@ -1,8 +1,6 @@ -================== -i2c-parport driver -================== +Kernel driver i2c-parport -2004-07-06, Jean Delvare +Author: Jean Delvare This is a unified driver for several i2c-over-parallel-port adapters, such as the ones made by Philips, Velleman or ELV. This driver is @@ -126,14 +124,14 @@ adapters do, so you won't even have to change the code. Similar (but different) drivers ------------------------------- -This driver is NOT the same as the i2c-pport driver found in the i2c package. -The i2c-pport driver makes use of modern parallel port features so that -you don't need additional electronics. It has other restrictions however, and -was not ported to Linux 2.6 (yet). +This driver is NOT the same as the i2c-pport driver found in the i2c +package. The i2c-pport driver makes use of modern parallel port features so +that you don't need additional electronics. It has other restrictions +however, and was not ported to Linux 2.6 (yet). This driver is also NOT the same as the i2c-pcf-epp driver found in the -lm_sensors package. The i2c-pcf-epp driver doesn't use the parallel port -as an I2C bus directly. Instead, it uses it to control an external I2C bus +lm_sensors package. The i2c-pcf-epp driver doesn't use the parallel port as +an I2C bus directly. Instead, it uses it to control an external I2C bus master. That driver was not ported to Linux 2.6 (yet) either. diff --git a/Documentation/i2c/busses/i2c-parport-light b/Documentation/i2c/busses/i2c-parport-light new file mode 100644 index 0000000000000..287436478520a --- /dev/null +++ b/Documentation/i2c/busses/i2c-parport-light @@ -0,0 +1,11 @@ +Kernel driver i2c-parport-light + +Author: Jean Delvare + +This driver is a light version of i2c-parport. It doesn't depend +on the parport driver, and uses direct I/O access instead. This might be +prefered on embedded systems where wasting memory for the clean but heavy +parport handling is not an option. The drawback is a reduced portability +and the impossibility to daisy-chain other parallel port devices. + +Please see i2c-parport for documentation. diff --git a/Documentation/i2c/busses/i2c-pca-isa b/Documentation/i2c/busses/i2c-pca-isa new file mode 100644 index 0000000000000..6fc8f4c27c3ce --- /dev/null +++ b/Documentation/i2c/busses/i2c-pca-isa @@ -0,0 +1,23 @@ +Kernel driver i2c-pca-isa + +Supported adapters: +This driver supports ISA boards using the Philips PCA 9564 +Parallel bus to I2C bus controller + +Author: Ian Campbell , Arcom Control Systems + +Module Parameters +----------------- + +* base int + I/O base address +* irq int + IRQ interrupt +* clock int + Clock rate as described in table 1 of PCA9564 datasheet + +Description +----------- + +This driver supports ISA boards using the Philips PCA 9564 +Parallel bus to I2C bus controller diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4 new file mode 100644 index 0000000000000..856b4b8b962cc --- /dev/null +++ b/Documentation/i2c/busses/i2c-piix4 @@ -0,0 +1,72 @@ +Kernel driver i2c-piix4 + +Supported adapters: + * Intel 82371AB PIIX4 and PIIX4E + * Intel 82443MX (440MX) + Datasheet: Publicly available at the Intel website + * ServerWorks OSB4, CSB5 and CSB6 southbridges + Datasheet: Only available via NDA from ServerWorks + * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge + Datasheet: Publicly available at the SMSC website http://www.smsc.com + +Authors: + Frodo Looijaard + Philip Edelbrock + + +Module Parameters +----------------- + +* force: int + Forcibly enable the PIIX4. DANGEROUS! +* force_addr: int + Forcibly enable the PIIX4 at the given address. EXTREMELY DANGEROUS! +* fix_hstcfg: int + Fix config register. Needed on some boards (Force CPCI735). + + +Description +----------- + +The PIIX4 (properly known as the 82371AB) is an Intel chip with a lot of +functionality. Among other things, it implements the PCI bus. One of its +minor functions is implementing a System Management Bus. This is a true +SMBus - you can not access it on I2C levels. The good news is that it +natively understands SMBus commands and you do not have to worry about +timing problems. The bad news is that non-SMBus devices connected to it can +confuse it mightily. Yes, this is known to happen... + +Do 'lspci -v' and see whether it contains an entry like this: + +0000:00:02.3 Bridge: Intel Corp. 82371AB/EB/MB PIIX4 ACPI (rev 02) + Flags: medium devsel, IRQ 9 + +Bus and device numbers may differ, but the function number must be +identical (like many PCI devices, the PIIX4 incorporates a number of +different 'functions', which can be considered as separate devices). If you +find such an entry, you have a PIIX4 SMBus controller. + +On some computers (most notably, some Dells), the SMBus is disabled by +default. If you use the insmod parameter 'force=1', the kernel module will +try to enable it. THIS IS VERY DANGEROUS! If the BIOS did not set up a +correct address for this module, you could get in big trouble (read: +crashes, data corruption, etc.). Try this only as a last resort (try BIOS +updates first, for example), and backup first! An even more dangerous +option is 'force_addr='. This will not only enable the PIIX4 like +'force' foes, but it will also set a new base I/O port address. The SMBus +parts of the PIIX4 needs a range of 8 of these addresses to function +correctly. If these addresses are already reserved by some other device, +you will get into big trouble! DON'T USE THIS IF YOU ARE NOT VERY SURE +ABOUT WHAT YOU ARE DOING! + +The PIIX4E is just an new version of the PIIX4; it is supported as well. +The PIIX/PIIX3 does not implement an SMBus or I2C bus, so you can't use +this driver on those mainboards. + +The ServerWorks Southbridges, the Intel 440MX, and the Victory766 are +identical to the PIIX4 in I2C/SMBus support. + +A few OSB4 southbridges are known to be misconfigured by the BIOS. In this +case, you have you use the fix_hstcfg module parameter. Do not use it +unless you know you have to, because in some cases it also breaks +configuration on southbridges that don't need it. diff --git a/Documentation/i2c/busses/i2c-prosavage b/Documentation/i2c/busses/i2c-prosavage new file mode 100644 index 0000000000000..7036879025110 --- /dev/null +++ b/Documentation/i2c/busses/i2c-prosavage @@ -0,0 +1,23 @@ +Kernel driver i2c-prosavage + +Supported adapters: + + S3/VIA KM266/VT8375 aka ProSavage8 + S3/VIA KM133/VT8365 aka Savage4 + +Author: Henk Vergonet + +Description +----------- + +The Savage4 chips contain two I2C interfaces (aka a I2C 'master' or +'host'). + +The first interface is used for DDC (Data Display Channel) which is a +serial channel through the VGA monitor connector to a DDC-compliant +monitor. This interface is defined by the Video Electronics Standards +Association (VESA). The standards are available for purchase at +http://www.vesa.org . The second interface is a general-purpose I2C bus. + +Usefull for gaining access to the TV Encoder chips. + diff --git a/Documentation/i2c/busses/i2c-savage4 b/Documentation/i2c/busses/i2c-savage4 new file mode 100644 index 0000000000000..6ecceab618d39 --- /dev/null +++ b/Documentation/i2c/busses/i2c-savage4 @@ -0,0 +1,26 @@ +Kernel driver i2c-savage4 + +Supported adapters: + * Savage4 + * Savage2000 + +Authors: + Alexander Wold , + Mark D. Studebaker + +Description +----------- + +The Savage4 chips contain two I2C interfaces (aka a I2C 'master' +or 'host'). + +The first interface is used for DDC (Data Display Channel) which is a +serial channel through the VGA monitor connector to a DDC-compliant +monitor. This interface is defined by the Video Electronics Standards +Association (VESA). The standards are available for purchase at +http://www.vesa.org . The DDC bus is not yet supported because its register +is not directly memory-mapped. + +The second interface is a general-purpose I2C bus. This is the only +interface supported by the driver at the moment. + diff --git a/Documentation/i2c/busses/i2c-sis5595 b/Documentation/i2c/busses/i2c-sis5595 new file mode 100644 index 0000000000000..cc47db7d00a98 --- /dev/null +++ b/Documentation/i2c/busses/i2c-sis5595 @@ -0,0 +1,59 @@ +Kernel driver i2c-sis5595 + +Authors: + Frodo Looijaard , + Mark D. Studebaker , + Philip Edelbrock + +Supported adapters: + * Silicon Integrated Systems Corp. SiS5595 Southbridge + Datasheet: Publicly available at the Silicon Integrated Systems Corp. site. + +Note: all have mfr. ID 0x1039. + + SUPPORTED PCI ID + 5595 0008 + + Note: these chips contain a 0008 device which is incompatible with the + 5595. We recognize these by the presence of the listed + "blacklist" PCI ID and refuse to load. + + NOT SUPPORTED PCI ID BLACKLIST PCI ID + 540 0008 0540 + 550 0008 0550 + 5513 0008 5511 + 5581 0008 5597 + 5582 0008 5597 + 5597 0008 5597 + 5598 0008 5597/5598 + 630 0008 0630 + 645 0008 0645 + 646 0008 0646 + 648 0008 0648 + 650 0008 0650 + 651 0008 0651 + 730 0008 0730 + 735 0008 0735 + 745 0008 0745 + 746 0008 0746 + +Module Parameters +----------------- + +* force_addr=0xaddr Set the I/O base address. Useful for boards + that don't set the address in the BIOS. Does not do a + PCI force; the device must still be present in lspci. + Don't use this unless the driver complains that the + base address is not set. + +Description +----------- + +i2c-sis5595 is a true SMBus host driver for motherboards with the SiS5595 +southbridges. + +WARNING: If you are trying to access the integrated sensors on the SiS5595 +chip, you want the sis5595 driver for those, not this driver. This driver +is a BUS driver, not a CHIP driver. A BUS driver is used by other CHIP +drivers to access chips on the bus. + diff --git a/Documentation/i2c/busses/i2c-sis630 b/Documentation/i2c/busses/i2c-sis630 new file mode 100644 index 0000000000000..9aca6889f748e --- /dev/null +++ b/Documentation/i2c/busses/i2c-sis630 @@ -0,0 +1,49 @@ +Kernel driver i2c-sis630 + +Supported adapters: + * Silicon Integrated Systems Corp (SiS) + 630 chipset (Datasheet: available at http://amalysh.bei.t-online.de/docs/SIS/) + 730 chipset + * Possible other SiS chipsets ? + +Author: Alexander Malysh + +Module Parameters +----------------- + +* force = [1|0] Forcibly enable the SIS630. DANGEROUS! + This can be interesting for chipsets not named + above to check if it works for you chipset, but DANGEROUS! + +* high_clock = [1|0] Forcibly set Host Master Clock to 56KHz (default, + what your BIOS use). DANGEROUS! This should be a bit + faster, but freeze some systems (i.e. my Laptop). + + +Description +----------- + +This SMBus only driver is known to work on motherboards with the above +named chipsets. + +If you see something like this: + +00:00.0 Host bridge: Silicon Integrated Systems [SiS] 630 Host (rev 31) +00:01.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513 + +or like this: + +00:00.0 Host bridge: Silicon Integrated Systems [SiS] 730 Host (rev 02) +00:01.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513 + +in your 'lspci' output , then this driver is for your chipset. + +Thank You +--------- +Philip Edelbrock +- testing SiS730 support +Mark M. Hoffman +- bug fixes + +To anyone else which I forgot here ;), thanks! + diff --git a/Documentation/i2c/busses/i2c-sis69x b/Documentation/i2c/busses/i2c-sis69x new file mode 100644 index 0000000000000..5be48769f65bd --- /dev/null +++ b/Documentation/i2c/busses/i2c-sis69x @@ -0,0 +1,73 @@ +Kernel driver i2c-sis96x + +Replaces 2.4.x i2c-sis645 + +Supported adapters: + * Silicon Integrated Systems Corp (SiS) + Any combination of these host bridges: + 645, 645DX (aka 646), 648, 650, 651, 655, 735, 745, 746 + and these south bridges: + 961, 962, 963(L) + +Author: Mark M. Hoffman + +Description +----------- + +This SMBus only driver is known to work on motherboards with the above +named chipset combinations. The driver was developed without benefit of a +proper datasheet from SiS. The SMBus registers are assumed compatible with +those of the SiS630, although they are located in a completely different +place. Thanks to Alexander Malysh for providing the +SiS630 datasheet (and driver). + +The command "lspci" as root should produce something like these lines: + +00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645 +00:02.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513 +00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016 + +or perhaps this... + +00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645 +00:02.0 ISA bridge: Silicon Integrated Systems [SiS]: Unknown device 0961 +00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016 + +(kernel versions later than 2.4.18 may fill in the "Unknown"s) + +If you cant see it please look on quirk_sis_96x_smbus +(drivers/pci/quirks.c) (also if southbridge detection fails) + +I suspect that this driver could be made to work for the following SiS +chipsets as well: 635, and 635T. If anyone owns a board with those chips +AND is willing to risk crashing & burning an otherwise well-behaved kernel +in the name of progress... please contact me at or +via the project's mailing list: . Please +send bug reports and/or success stories as well. + + +TO DOs +------ + +* The driver does not support SMBus block reads/writes; I may add them if a +scenario is found where they're needed. + + +Thank You +--------- + +Mark D. Studebaker + - design hints and bug fixes +Alexander Maylsh + - ditto, plus an important datasheet... almost the one I really wanted +Hans-Günter Lütke Uphues + - patch for SiS735 +Robert Zwerus + - testing for SiS645DX +Kianusch Sayah Karadji + - patch for SiS645DX/962 +Ken Healy + - patch for SiS655 + +To anyone else who has written w/ feedback, thanks! + diff --git a/Documentation/i2c/busses/i2c-via b/Documentation/i2c/busses/i2c-via new file mode 100644 index 0000000000000..55edfe1a640be --- /dev/null +++ b/Documentation/i2c/busses/i2c-via @@ -0,0 +1,34 @@ +Kernel driver i2c-via + +Supported adapters: + * VIA Technologies, InC. VT82C586B + Datasheet: Publicly available at the VIA website + +Author: Kyösti Mälkki + +Description +----------- + +i2c-via is an i2c bus driver for motherboards with VIA chipset. + +The following VIA pci chipsets are supported: + - MVP3, VP3, VP2/97, VPX/97 + - others with South bridge VT82C586B + +Your lspci listing must show this : + + Bridge: VIA Technologies, Inc. VT82C586B ACPI (rev 10) + + Problems? + + Q: You have VT82C586B on the motherboard, but not in the listing. + + A: Go to your BIOS setup, section PCI devices or similar. + Turn USB support on, and try again. + + Q: No error messages, but still i2c doesn't seem to work. + + A: This can happen. This driver uses the pins VIA recommends in their + datasheets, but there are several ways the motherboard manufacturer + can actually wire the lines. + diff --git a/Documentation/i2c/busses/i2c-viapro b/Documentation/i2c/busses/i2c-viapro new file mode 100644 index 0000000000000..702f5ac68c09d --- /dev/null +++ b/Documentation/i2c/busses/i2c-viapro @@ -0,0 +1,47 @@ +Kernel driver i2c-viapro + +Supported adapters: + * VIA Technologies, Inc. VT82C596A/B + Datasheet: Sometimes available at the VIA website + + * VIA Technologies, Inc. VT82C686A/B + Datasheet: Sometimes available at the VIA website + + * VIA Technologies, Inc. VT8231, VT8233, VT8233A, VT8235, VT8237 + Datasheet: available on request from Via + +Authors: + Frodo Looijaard , + Philip Edelbrock , + Kyösti Mälkki , + Mark D. Studebaker + +Module Parameters +----------------- + +* force: int + Forcibly enable the SMBus controller. DANGEROUS! +* force_addr: int + Forcibly enable the SMBus at the given address. EXTREMELY DANGEROUS! + +Description +----------- + +i2c-viapro is a true SMBus host driver for motherboards with one of the +supported VIA southbridges. + +Your lspci -n listing must show one of these : + + device 1106:3050 (VT82C596 function 3) + device 1106:3051 (VT82C596 function 3) + device 1106:3057 (VT82C686 function 4) + device 1106:3074 (VT8233) + device 1106:3147 (VT8233A) + device 1106:8235 (VT8231) + devide 1106:3177 (VT8235) + devide 1106:3227 (VT8237) + +If none of these show up, you should look in the BIOS for settings like +enable ACPI / SMBus or even USB. + + diff --git a/Documentation/i2c/busses/i2c-voodoo3 b/Documentation/i2c/busses/i2c-voodoo3 new file mode 100644 index 0000000000000..62d90a454d399 --- /dev/null +++ b/Documentation/i2c/busses/i2c-voodoo3 @@ -0,0 +1,62 @@ +Kernel driver i2c-voodoo3 + +Supported adapters: + * 3dfx Voodoo3 based cards + * Voodoo Banshee based cards + +Authors: + Frodo Looijaard , + Philip Edelbrock , + Ralph Metzler , + Mark D. Studebaker + +Main contact: Philip Edelbrock + +The code is based upon Ralph's test code (he did the hard stuff ;') + +Description +----------- + +The 3dfx Voodoo3 chip contains two I2C interfaces (aka a I2C 'master' or +'host'). + +The first interface is used for DDC (Data Display Channel) which is a +serial channel through the VGA monitor connector to a DDC-compliant +monitor. This interface is defined by the Video Electronics Standards +Association (VESA). The standards are available for purchase at +http://www.vesa.org . + +The second interface is a general-purpose I2C bus. The intent by 3dfx was +to allow manufacturers to add extra chips to the video card such as a +TV-out chip such as the BT869 or possibly even I2C based temperature +sensors like the ADM1021 or LM75. + +Stability +--------- + +Seems to be stable on the test machine, but needs more testing on other +machines. Simultaneous accesses of the DDC and I2C busses may cause errors. + +Supported Devices +----------------- + +Specifically, this driver was written and tested on the '3dfx Voodoo3 AGP +3000' which has a tv-out feature (s-video or composite). According to the +docs and discussions, this code should work for any Voodoo3 based cards as +well as Voodoo Banshee based cards. The DDC interface has been tested on a +Voodoo Banshee card. + +Issues +------ + +Probably many, but it seems to work OK on my system. :') + + +External Device Connection +-------------------------- + +The digital video input jumpers give availability to the I2C bus. +Specifically, pins 13 and 25 (bottom row middle, and bottom right-end) are +the I2C clock and I2C data lines, respectively. +5V and GND are probably +also easily available making the addition of extra I2C/SMBus devices easy +to implement. diff --git a/Documentation/i2c/busses/scx200_acb b/Documentation/i2c/busses/scx200_acb new file mode 100644 index 0000000000000..08c8cd1df60c5 --- /dev/null +++ b/Documentation/i2c/busses/scx200_acb @@ -0,0 +1,14 @@ +Kernel driver scx200_acb + +Author: Christer Weinigel + +Module Parameters +----------------- + +* base: int + Base addresses for the ACCESS.bus controllers + +Description +----------- + +Enable the use of the ACCESS.bus controllers of a SCx200 processor. -- cgit 1.2.3-korg From 2f4ce18a3d9ce87b82c26ced004e7136d2ffce63 Mon Sep 17 00:00:00 2001 From: Eric Brower Date: Wed, 30 Mar 2005 22:30:24 -0800 Subject: [PATCH] I2C: lost arbitration detection for PCF8584 [PATCH] lost arbitration detection for PCF8584 algo driver Patch against a slightly-dated linux-2.6 BK tree This patch provides lost arbitration detection for the PCF8584 I2C algorithm driver. The PCF8584 LAB bit is set whenever lost arbitration is detected, so we check the bit in the wait_for_pin function and if LAB is detected we return -EINTR. The -EINTR value bubbles-up all the way to the master_xfer API call so callers may detect this condition explicitly. LAB could be checked more often, at the expense of code readability/maintainability. Signed-off-by: Eric Brower Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/algos/i2c-algo-pcf.c | 44 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c index 66e681cb33d1e..8d087dac32afc 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= 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");) -- cgit 1.2.3-korg From e229b0f7bf6d2c347240f8309435c43f6fd951e0 Mon Sep 17 00:00:00 2001 From: Rafael Ãvila de Espíndola Date: Wed, 30 Mar 2005 22:30:43 -0800 Subject: [PATCH] I2C: lsb in emc6d102 and adm1027 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The attached patches add support for reading the lsb from the emc6d102 and change how they are read from the adm1027. The lm85_update_device function decodes the LSBs to temp_ext and in_ext. This strategy was suggested by Philip Pokorny. The patch also changes some macros to use the SCALE macro. I think that they become more readable this way. Signed-off-by: Rafael Ãvila de Espíndola Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/lm85.c | 100 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 77 insertions(+), 23 deletions(-) diff --git a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c index e96ad5ba5c9d0..e08000b948b2f 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 */ @@ -77,6 +77,7 @@ SENSORS_INSMOD_5(lm85b, lm85c, adm1027, adt7463, emc6d100); #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 @@ -113,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 @@ -140,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 @@ -356,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 */ @@ -537,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) { @@ -618,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) { @@ -1108,6 +1121,9 @@ int lm85_detect(struct i2c_adapter *adapter, int address, * inputs read 0, then it's a '101. */ 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"); @@ -1144,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); @@ -1261,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 ; @@ -1365,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)); @@ -1405,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 ; -- cgit 1.2.3-korg From adcca21aa6af4df6d6e366434a5177a1f76d4355 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Mar 2005 22:31:02 -0800 Subject: [PATCH] I2C: Delete useless instruction in it87 The IT8705F doesn't support VID, so it's quite pointless to give a value to it (and an arbitrary one at that). I think that this instruction was there for compatibility reasons some times ago, but the reasons went away while the instruction was left in place. We can safely delete it now. Thanks to Rudolf Marek for testing the patch (you never know). Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/it87.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c index 686fb756407c0..fbb97e6aec6fb 100644 --- a/drivers/i2c/chips/it87.c +++ b/drivers/i2c/chips/it87.c @@ -1122,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; -- cgit 1.2.3-korg From 9d8eaff2367739d3b0c96a6c83343b8ea1456062 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Mar 2005 22:31:21 -0800 Subject: [PATCH] I2C: Fix race condition in it87 driver I noticed a race condition in the it87, affecting the IT8712F chip only. The VRM value is currently initialized *after* creating the vrm and vid sysfs files. This leaves a theorical room for reading from these files and get an invalid value. It's not critical, but let's still fix it. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/it87.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c index fbb97e6aec6fb..bf02ba555a851 100644 --- a/drivers/i2c/chips/it87.c +++ b/drivers/i2c/chips/it87.c @@ -889,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; -- cgit 1.2.3-korg From c54a6e6befadf7648f9a106505bb1bffa2f54e7d Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Mar 2005 22:31:40 -0800 Subject: [PATCH] I2C: i2c-s3c2410 functionality and fixes This patch does the following updates to the i2c-s3c2410 bus driver: * Properly report the i2c functionality by adding to the `.functionality` field of the adapter * Change the dev_err() call on no-ack to an dev_dbg() to make it less noisy when the bus is being probed by i2cdetect, etc. * Add I2C_M_REV_DIR_ADDR to fully implement the I2C_FUNC_PROTOCOLO_MANGLING. * Ensure that the adapter owner field is set to THIS_MODULE Please apply, thanks. (Once this is applied, all i2c bus drivers will be properly reporting their functionality so I'll be able to go on with the i2c functionality core cleanups.) Signed-off-by: Ben Dooks Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-s3c2410.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 0ac72c935e752..fcfa51c1436b5 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 * * 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, -- cgit 1.2.3-korg From 7343e7c77c30d385c0a4e0b4adfbd5bdbf647fdf Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Mar 2005 22:31:59 -0800 Subject: [PATCH] i2c: add adt7461 chip support to lm90 driver's Kconfig entry Hi Greg, James, all, > > > Attached is another version of my adt7461 patch, for inclusion in > > > the 2.6 tree. Reviewed by Jean. > > May we have an additional patch to Kconfig for this one? Here it finally comes. This simple patch adds a mention to the ADT7461 chip in Kconfig, now that the lm90 driver supports it. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index 86aafca0db2cd..74d23cfce2a34 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig @@ -233,6 +233,9 @@ 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. -- cgit 1.2.3-korg From 11543882368ecb38b880b4e3ae605be3d59371dd Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Mar 2005 22:32:17 -0800 Subject: [PATCH] I2C: Fix broken force parameter handling I just noticed a nasty bug in the way the "force" parameter is handled for non-sensors i2c chip drivers. The "force" parameter supposedy is a list of adapter, address *pairs* where supported chips are unquestionably assumed to be. However, after handling one pair, the i2c core code searches for the next one *three* values later, not two. So with the current code, the second and third pairs wouldn't be properly handled. The fourth one would be, and so on. As a side note, this questions the need of an array parameter handling up to 24 of such pairs, when obviously nobody ever required more than one for the past 6 years. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/i2c-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 474ddb6fe2523..e62a91a45a291 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -715,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])) { -- cgit 1.2.3-korg From 5249fba7239f98b15382e6e758ec9c32775ae507 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Mar 2005 22:32:36 -0800 Subject: [PATCH] I2C: Fix indentation of lm87 driver This trivial patch fixes indentation in the lm87 driver. I need this 'cause I'll soon post patches affecting these portions of code, and I'd like these patches to be easily readable. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/lm87.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/i2c/chips/lm87.c b/drivers/i2c/chips/lm87.c index 8b9e2de21bff7..49d92326faab5 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) \ -- cgit 1.2.3-korg From 12411eb0d191f7616b7eba560f7ddf88817741ab Mon Sep 17 00:00:00 2001 From: "grant_nospam@dodo.com.au" Date: Wed, 30 Mar 2005 22:32:55 -0800 Subject: [PATCH] I2C: Drop useless w83781d RT feature This patch removes useless RT feature from w83781d driver. Patch applies after the recent "I2C: Fix a common race condition in hardware monitoring" series. Signed-off-by: Grant Coady Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/w83781d.c | 100 -------------------------------------------- 1 file changed, 100 deletions(-) diff --git a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c index e893229239d07..628d769cf4751 100644 --- a/drivers/i2c/chips/w83781d.c +++ b/drivers/i2c/chips/w83781d.c @@ -46,9 +46,6 @@ #include #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 */ -- cgit 1.2.3-korg From ebbe7b61a562c8ff9c27c85091e81dcb7a64241d Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Wed, 30 Mar 2005 22:33:14 -0800 Subject: [PATCH] i2c: i2c-mv64xxx - set adapter owner and class fields This patch adds the correct values for the 'owner' and 'class' fields of the adapter structure in the mv64xxx i2c bus driver. The missing class field caused some i2c chip drivers to refuse to attempt a probe on the mv64xxx i2c bus. Signed-off-by: Chris Elston Signed-off-by: Mark A. Greer Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-mv64xxx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index db88a12439562..5b852782d2f59 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); -- cgit 1.2.3-korg From acaf240e91e52280da508b38a5d2da8a55583545 Mon Sep 17 00:00:00 2001 From: Bob Montgomery Date: Thu, 31 Mar 2005 00:10:45 -0800 Subject: [IA64] fix for unwind problem through dispatch_illegal_op_fault Here is the patch worked out with David Mosberger to fix the unwind info for dispatch_illegal_op_fault in ivt.S. Before adding this patch, an illegal op in the kernel would not show a complete stack trace in the oops message. Add PT_REGS_UNWIND_INFO to dispatch_illegal_op_fault to allow stack unwind to continue through that stack level when kernel code commits an illegal operation. Signed-off-by: Bob Montgomery Signed-off-by: Tony Luck --- arch/ia64/kernel/ivt.S | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S index b3ed949a4f860..d9c05d53435bd 100644 --- a/arch/ia64/kernel/ivt.S +++ b/arch/ia64/kernel/ivt.S @@ -957,6 +957,8 @@ END(ia64_syscall_setup) * element, followed by the arguments. */ ENTRY(dispatch_illegal_op_fault) + .prologue + .body SAVE_MIN_WITH_COVER ssm psr.ic | PSR_DEFAULT_BITS ;; @@ -969,6 +971,7 @@ ENTRY(dispatch_illegal_op_fault) mov out0=ar.ec ;; SAVE_REST + PT_REGS_UNWIND_INFO(0) ;; br.call.sptk.many rp=ia64_illegal_op_fault .ret0: ;; -- cgit 1.2.3-korg From 1f892e799c51bb4395f15c9b10e6d0355309e468 Mon Sep 17 00:00:00 2001 From: David Mosberger Date: Thu, 31 Mar 2005 00:15:46 -0800 Subject: [IA64] Initialize ar.k7 to empty_zero_page early on. Without this initialization, early TLB misses to any user-regions will cause the TLB miss handlers to go down in flames. Normally, no such early TLB misses occur, but aggressive use of lfetch.fault can trigger it easily (e.g., when using lfetch.fault for the prefetch()/prefetchw() macros we get an early miss for address 0 due to a prefetch in find_pid()). Signed-off-by: David Mosberger-Tang Signed-off-by: Tony Luck --- arch/ia64/kernel/setup.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 9891effcf4c3c..f05650c801d2a 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -645,6 +645,15 @@ cpu_init (void) ia64_set_kr(IA64_KR_FPU_OWNER, 0); + /* + * Initialize the page-table base register to a global + * directory with all zeroes. This ensure that we can handle + * TLB-misses to user address-space even before we created the + * first user address-space. This may happen, e.g., due to + * aggressive use of lfetch.fault. + */ + ia64_set_kr(IA64_KR_PT_BASE, __pa(ia64_imva(empty_zero_page))); + /* * Initialize default control register to defer all speculative faults. The * kernel MUST NOT depend on a particular setting of these bits (in other words, -- cgit 1.2.3-korg From de69281a2124509eb96a50a6b95e033e8e2af871 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 31 Mar 2005 00:21:27 -0800 Subject: [IA64] Andrew's fixes for warnings on ia64 build drivers/pci/msi.c: In function `msi_set_mask_bit': drivers/pci/msi.c:70: warning: cast from pointer to integer of different size drivers/pci/msi.c: In function `msi_capability_init': drivers/pci/msi.c:558: warning: cast to pointer from integer of different size Signed-off-by: Andrew Morton Signed-off-by: Tony Luck --- drivers/pci/msi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 3f70e4926cb61..5425e0f77d860 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 */ -- cgit 1.2.3-korg From 5227ffd37189ab2c6d442ab5b43c7a0636622e01 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 31 Mar 2005 00:24:49 -0800 Subject: [IA64] CONFIG_NUMA requires CONFIG_ACPI_NUMA arch/ia64/kernel/smpboot.c:511:17: #error Fixme: Dunno how to build CPU-to-node map. Seems that CONFIG_NUMA requires CONFIG_ACPI_NUMA. Signed-off-by: Andrew Morton Signed-off-by: Tony Luck --- arch/ia64/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index a337879e981da..33fcb205fcb7a 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -169,6 +169,7 @@ config NUMA bool "NUMA support" depends on !IA64_HP_SIM default y if IA64_SGI_SN2 + select ACPI_NUMA help Say Y to compile the kernel to support NUMA (Non-Uniform Memory Access). This option is for configuring high-end multiprocessor -- cgit 1.2.3-korg