# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/03/13 04:34:52-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/src/linux-acpi-test-2.4.22 # into intel.com:/home/lenb/src/linux-acpi-test-2.4.24 # # Documentation/kernel-parameters.txt # 2004/03/13 04:34:49-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2004/03/13 04:34:23-05:00 len.brown@intel.com # [ACPI] add boot parameters "acpi_osi=" and "acpi_serialize" # acpi_osi= will disable the _OSI method -- which by default # tells the BIOS to behave as if Windows is the OS. # acpi_serialize is for debugging AE_ALREADY_EXISTS failures # # # drivers/acpi/osl.c # 2004/03/13 04:33:00-05:00 len.brown@intel.com +36 -0 # [ACPI] add acpi_osi= and acpi_serialize # # Documentation/kernel-parameters.txt # 2004/03/13 04:32:36-05:00 len.brown@intel.com +4 -0 # [ACPI] add acpi_osi= and acpi_serialize # # ChangeSet # 2004/03/13 01:40:14-05:00 len.brown@intel.com # Merge # # drivers/acpi/system.c # 2004/03/13 01:40:14-05:00 len.brown@intel.com +0 -0 # SCCS merged # # ChangeSet # 2004/03/13 01:24:09-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/src/linux-acpi-test-2.4.22 # into intel.com:/home/lenb/src/linux-acpi-test-2.4.24 # # drivers/acpi/system.c # 2004/03/13 01:24:08-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2004/03/13 00:29:04-05:00 len.brown@intel.com # [ACPI] ACPICA 20040311 from Bob Moore # # Fixed a problem where errors occurring during the parse phase of control # method execution did not abort cleanly. For example, objects created # and installed in the namespace were not deleted. This caused all # subsequent invocations of the method to return the AE_ALREADY_EXISTS # exception. # # Implemented a mechanism to force a control method to "Serialized" # execution if the method attempts to create namespace objects. # (The root of the AE_ALREADY_EXISTS problem.) # # Implemented support for the predefined _OSI "internal" control method. # Initial supported strings are "Linux", "Windows 2000", "Windows 2001", # and "Windows 2001.1", and can be easily upgraded for new strings as # necessary. This feature allows Linux to execute # the fully tested, "Windows" code path through the ASL code # # Global Lock Support: Now allows multiple acquires and releases with any # internal thread. Removed concept of "owning thread" for this special # mutex. # # Fixed two functions that were inappropriately declaring large objects on # the CPU stack: ps_parse_loop() and ns_evaluate_relative(). # Reduces the stack usage during method execution considerably. # # Fixed a problem in the ACPI 2.0 FACS descriptor (actbl2.h) where the # S4Bios_f field was incorrectly defined as UINT32 instead of UINT32_BIT. # # Fixed a problem where acpi_ev_gpe_detect() would fault # if there were no GPEs defined on the machine. # # Implemented two runtime options: One to force all control method # execution to "Serialized" to mimic Windows behavior, another to disable # _OSI support if it causes problems on a given machine. # # include/acpi/amlcode.h # 2004/03/13 00:29:02-05:00 len.brown@intel.com +10 -4 # ACPICA 20040311 # # include/acpi/acutils.h # 2004/03/13 00:29:02-05:00 len.brown@intel.com +4 -2 # ACPICA 20040311 # # include/acpi/actypes.h # 2004/03/13 00:29:02-05:00 len.brown@intel.com +1 -4 # ACPICA 20040311 # # include/acpi/acobject.h # 2004/03/13 00:29:02-05:00 len.brown@intel.com +6 -1 # ACPICA 20040311 # # include/acpi/acmacros.h # 2004/03/13 00:29:02-05:00 len.brown@intel.com +0 -3 # ACPICA 20040311 # # include/acpi/acglobal.h # 2004/03/13 00:29:02-05:00 len.brown@intel.com +10 -1 # ACPICA 20040311 # # include/acpi/acconfig.h # 2004/03/13 00:29:02-05:00 len.brown@intel.com +5 -1 # ACPICA 20040311 # # drivers/acpi/utilities/utglobal.c # 2004/03/13 00:29:02-05:00 len.brown@intel.com +17 -11 # ACPICA 20040311 # # drivers/acpi/utilities/uteval.c # 2004/03/13 00:29:02-05:00 len.brown@intel.com +56 -0 # ACPICA 20040311 # # drivers/acpi/parser/psscope.c # 2004/03/13 00:29:02-05:00 len.brown@intel.com +2 -7 # ACPICA 20040311 # # drivers/acpi/parser/psparse.c # 2004/03/13 00:29:02-05:00 len.brown@intel.com +39 -5 # ACPICA 20040311 # # drivers/acpi/namespace/nseval.c # 2004/03/13 00:29:02-05:00 len.brown@intel.com +11 -4 # ACPICA 20040311 # # drivers/acpi/namespace/nsalloc.c # 2004/03/13 00:29:02-05:00 len.brown@intel.com +4 -3 # ACPICA 20040311 # # drivers/acpi/namespace/nsaccess.c # 2004/03/13 00:29:02-05:00 len.brown@intel.com +22 -8 # ACPICA 20040311 # # drivers/acpi/executer/exmutex.c # 2004/03/13 00:29:02-05:00 len.brown@intel.com +17 -11 # ACPICA 20040311 # # drivers/acpi/executer/excreate.c # 2004/03/13 00:29:02-05:00 len.brown@intel.com +13 -7 # ACPICA 20040311 # # drivers/acpi/events/evgpe.c # 2004/03/13 00:29:02-05:00 len.brown@intel.com +5 -0 # ACPICA 20040311 # # drivers/acpi/dispatcher/dsmethod.c # 2004/03/13 00:29:02-05:00 len.brown@intel.com +58 -27 # ACPICA 20040311 # # ChangeSet # 2004/03/13 00:02:05-05:00 len.brown@intel.com # [ACPI] SMP poweroff (David Shaohua Li) # http://bugzilla.kernel.org/show_bug.cgi?id=1141 # # drivers/acpi/system.c # 2004/03/12 23:59:21-05:00 len.brown@intel.com +3 -0 # poweroff from CPU0 -- David Shaohua Li # # ChangeSet # 2004/03/05 01:01:48-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/src/linux-acpi-test-2.4.25 # into intel.com:/home/lenb/src/linux-acpi-test-2.4.26 # # arch/i386/kernel/acpi.c # 2004/03/05 01:01:47-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2004/03/05 00:58:07-05:00 len.brown@intel.com # Merge intel.com:/home/lenb/src/linux-acpi-test-2.4.22 # into intel.com:/home/lenb/src/linux-acpi-test-2.4.24 # # include/asm-x86_64/acpi.h # 2004/03/05 00:58:05-05:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2004/03/05 00:57:30-05:00 len.brown@intel.com # [ACPI] global lock macro fixes (Paul Menage, Luming Yu) # http://bugzilla.kernel.org/show_bug.cgi?id=1669 # # include/asm-x86_64/acpi.h # 2004/03/05 00:56:12-05:00 len.brown@intel.com +27 -32 # [ACPI] global lock macro fixes (Paul Menage, Luming Yu) # http://bugzilla.kernel.org/show_bug.cgi?id=1669 # # include/asm-i386/acpi.h # 2004/03/05 00:56:12-05:00 len.brown@intel.com +27 -24 # [ACPI] global lock macro fixes (Paul Menage, Luming Yu) # http://bugzilla.kernel.org/show_bug.cgi?id=1669 # # ChangeSet # 2004/03/05 00:55:19-05:00 len.brown@intel.com # [ACPI] acpi_wakeup_address - print only when broken # # arch/i386/kernel/acpi.c # 2004/02/27 10:49:13-05:00 len.brown@intel.com +2 -1 # acpi_wakeup_address - print only when broken # diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt --- a/Documentation/kernel-parameters.txt Sat Mar 13 04:58:44 2004 +++ b/Documentation/kernel-parameters.txt Sat Mar 13 04:58:44 2004 @@ -85,6 +85,10 @@ acpi_irq_pci= If irq_balance, Clear listed IRQs for use by PCI acpi_irq_isa= If irq_balance, Mark listed IRQs used by ISA + acpi_osi= [HW,ACPI] empty param disables _OSI + + acpi_serialize [HW,ACPI] force serialization of AML methods + ad1816= [HW,SOUND] ad1848= [HW,SOUND] diff -Nru a/arch/i386/kernel/acpi.c b/arch/i386/kernel/acpi.c --- a/arch/i386/kernel/acpi.c Sat Mar 13 04:58:44 2004 +++ b/arch/i386/kernel/acpi.c Sat Mar 13 04:58:44 2004 @@ -655,7 +655,8 @@ void __init acpi_reserve_bootmem(void) { acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE); - printk(KERN_DEBUG "ACPI: have wakeup address 0x%8.8lx\n", acpi_wakeup_address); + if (!acpi_wakeup_address) + printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n"); } void do_suspend_lowlevel_s4bios(int resume) diff -Nru a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c --- a/drivers/acpi/dispatcher/dsmethod.c Sat Mar 13 04:58:44 2004 +++ b/drivers/acpi/dispatcher/dsmethod.c Sat Mar 13 04:58:44 2004 @@ -106,7 +106,7 @@ /* Create a mutex for the method if there is a concurrency limit */ - if ((obj_desc->method.concurrency != INFINITE_CONCURRENCY) && + if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) && (!obj_desc->method.semaphore)) { status = acpi_os_create_semaphore (obj_desc->method.concurrency, obj_desc->method.concurrency, @@ -300,34 +300,37 @@ return_ACPI_STATUS (status); } - /* 1) Parse: Create a new walk state for the preempting walk */ + if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) { + /* 1) Parse: Create a new walk state for the preempting walk */ - next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, - op, obj_desc, NULL); - if (!next_walk_state) { - return_ACPI_STATUS (AE_NO_MEMORY); - } + next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, + op, obj_desc, NULL); + if (!next_walk_state) { + return_ACPI_STATUS (AE_NO_MEMORY); + } - /* Create and init a Root Node */ - op = acpi_ps_create_scope_op (); - if (!op) { - status = AE_NO_MEMORY; - goto cleanup; - } + /* Create and init a Root Node */ - status = acpi_ds_init_aml_walk (next_walk_state, op, method_node, - obj_desc->method.aml_start, obj_desc->method.aml_length, - NULL, NULL, 1); - if (ACPI_FAILURE (status)) { - acpi_ds_delete_walk_state (next_walk_state); - goto cleanup; - } + op = acpi_ps_create_scope_op (); + if (!op) { + status = AE_NO_MEMORY; + goto cleanup; + } + + status = acpi_ds_init_aml_walk (next_walk_state, op, method_node, + obj_desc->method.aml_start, obj_desc->method.aml_length, + NULL, NULL, 1); + if (ACPI_FAILURE (status)) { + acpi_ds_delete_walk_state (next_walk_state); + goto cleanup; + } - /* Begin AML parse */ + /* Begin AML parse */ - status = acpi_ps_parse_aml (next_walk_state); - acpi_ps_delete_parse_tree (op); + status = acpi_ps_parse_aml (next_walk_state); + acpi_ps_delete_parse_tree (op); + } /* 2) Execute: Create a new state for the preempting walk */ @@ -337,7 +340,6 @@ status = AE_NO_MEMORY; goto cleanup; } - /* * The resolved arguments were put on the previous walk state's operand * stack. Operands on the previous walk state stack always @@ -369,16 +371,25 @@ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Starting nested execution, newstate=%p\n", next_walk_state)); + if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { + status = obj_desc->method.implementation (next_walk_state); + return_ACPI_STATUS (status); + } + return_ACPI_STATUS (AE_OK); /* On error, we must delete the new walk state */ cleanup: + if (next_walk_state->method_desc) { + /* Decrement the thread count on the method parse tree */ + + next_walk_state->method_desc->method.thread_count--; + } (void) acpi_ds_terminate_control_method (next_walk_state); acpi_ds_delete_walk_state (next_walk_state); return_ACPI_STATUS (status); - } @@ -500,10 +511,30 @@ } } - /* Decrement the thread count on the method parse tree */ + if (walk_state->method_desc->method.thread_count) { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "*** Not deleting method namespace, there are still %d threads\n", + walk_state->method_desc->method.thread_count)); + } - walk_state->method_desc->method.thread_count--; if (!walk_state->method_desc->method.thread_count) { + /* + * Support to dynamically change a method from not_serialized to + * Serialized if it appears that the method is written foolishly and + * does not support multiple thread execution. The best example of this + * is if such a method creates namespace objects and blocks. A second + * thread will fail with an AE_ALREADY_EXISTS exception + * + * This code is here because we must wait until the last thread exits + * before creating the synchronization semaphore. + */ + if ((walk_state->method_desc->method.concurrency == 1) && + (!walk_state->method_desc->method.semaphore)) { + status = acpi_os_create_semaphore (1, + 1, + &walk_state->method_desc->method.semaphore); + } + /* * There are no more threads executing this method. Perform * additional cleanup. diff -Nru a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c --- a/drivers/acpi/events/evgpe.c Sat Mar 13 04:58:44 2004 +++ b/drivers/acpi/events/evgpe.c Sat Mar 13 04:58:44 2004 @@ -149,6 +149,11 @@ ACPI_FUNCTION_NAME ("ev_gpe_detect"); + /* Check for the case where there are no GPEs */ + + if (!gpe_xrupt_list) { + return (int_status); + } /* Examine all GPE blocks attached to this interrupt level */ diff -Nru a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c --- a/drivers/acpi/executer/excreate.c Sat Mar 13 04:58:44 2004 +++ b/drivers/acpi/executer/excreate.c Sat Mar 13 04:58:44 2004 @@ -587,27 +587,33 @@ obj_desc->method.aml_start = aml_start; obj_desc->method.aml_length = aml_length; - /* disassemble the method flags */ - + /* + * Disassemble the method flags. Split off the Arg Count + * for efficiency + */ method_flags = (u8) operand[1]->integer.value; - obj_desc->method.method_flags = method_flags; - obj_desc->method.param_count = (u8) (method_flags & METHOD_FLAGS_ARG_COUNT); + obj_desc->method.method_flags = (u8) (method_flags & ~AML_METHOD_ARG_COUNT); + obj_desc->method.param_count = (u8) (method_flags & AML_METHOD_ARG_COUNT); /* * Get the concurrency count. If required, a semaphore will be * created for this method when it is parsed. */ - if (method_flags & METHOD_FLAGS_SERIALIZED) { + if (acpi_gbl_all_methods_serialized) { + obj_desc->method.concurrency = 1; + obj_desc->method.method_flags |= AML_METHOD_SERIALIZED; + } + else if (method_flags & AML_METHOD_SERIALIZED) { /* * ACPI 1.0: Concurrency = 1 * ACPI 2.0: Concurrency = (sync_level (in method declaration) + 1) */ obj_desc->method.concurrency = (u8) - (((method_flags & METHOD_FLAGS_SYNCH_LEVEL) >> 4) + 1); + (((method_flags & AML_METHOD_SYNCH_LEVEL) >> 4) + 1); } else { - obj_desc->method.concurrency = INFINITE_CONCURRENCY; + obj_desc->method.concurrency = ACPI_INFINITE_CONCURRENCY; } /* Attach the new object to the method Node */ diff -Nru a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c --- a/drivers/acpi/executer/exmutex.c Sat Mar 13 04:58:44 2004 +++ b/drivers/acpi/executer/exmutex.c Sat Mar 13 04:58:44 2004 @@ -176,15 +176,18 @@ /* * Support for multiple acquires by the owning thread */ + if (obj_desc->mutex.owner_thread) { + /* Special case for Global Lock, allow all threads */ - if ((obj_desc->mutex.owner_thread) && - (obj_desc->mutex.owner_thread->thread_id == walk_state->thread->thread_id)) { - /* - * The mutex is already owned by this thread, - * just increment the acquisition depth - */ - obj_desc->mutex.acquisition_depth++; - return_ACPI_STATUS (AE_OK); + if ((obj_desc->mutex.owner_thread->thread_id == walk_state->thread->thread_id) || + (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore)) { + /* + * The mutex is already owned by this thread, + * just increment the acquisition depth + */ + obj_desc->mutex.acquisition_depth++; + return_ACPI_STATUS (AE_OK); + } } /* Acquire the mutex, wait if necessary */ @@ -254,9 +257,12 @@ return_ACPI_STATUS (AE_AML_INTERNAL); } - /* The Mutex is owned, but this thread must be the owner */ - - if (obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) { + /* + * The Mutex is owned, but this thread must be the owner. + * Special case for Global Lock, any thread can release + */ + if ((obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) && + (obj_desc->mutex.semaphore != acpi_gbl_global_lock_semaphore)) { ACPI_REPORT_ERROR (( "Thread %X cannot release Mutex [%4.4s] acquired by thread %X\n", walk_state->thread->thread_id, diff -Nru a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c --- a/drivers/acpi/namespace/nsaccess.c Sat Mar 13 04:58:44 2004 +++ b/drivers/acpi/namespace/nsaccess.c Sat Mar 13 04:58:44 2004 @@ -105,8 +105,15 @@ "Entering predefined entries into namespace\n")); for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) { + /* _OSI is optional for now, will be permanent later */ + + if (!ACPI_STRCMP (init_val->name, "_OSI") && !acpi_gbl_create_osi_method) { + continue; + } + status = acpi_ns_lookup (NULL, init_val->name, init_val->type, - ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH, NULL, &new_node); + ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH, + NULL, &new_node); if (ACPI_FAILURE (status) || (!new_node)) /* Must be on same line for code converter */ { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, @@ -122,7 +129,8 @@ if (init_val->val) { status = acpi_os_predefined_override (init_val, &val); if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not override predefined %s\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Could not override predefined %s\n", init_val->name)); } @@ -147,15 +155,20 @@ */ switch (init_val->type) { case ACPI_TYPE_METHOD: - obj_desc->method.param_count = - (u8) ACPI_STRTOUL (val, NULL, 10); + obj_desc->method.param_count = (u8) ACPI_STRTOUL + (val, NULL, 10); obj_desc->common.flags |= AOPOBJ_DATA_VALID; -#if defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) +#if defined (_ACPI_ASL_COMPILER) || defined (_ACPI_DUMP_App) - /* Compiler cheats by putting parameter count in the owner_iD */ + /* i_aSL Compiler cheats by putting parameter count in the owner_iD */ new_node->owner_id = obj_desc->method.param_count; +#else + /* Mark this as a very SPECIAL method */ + + obj_desc->method.method_flags = AML_METHOD_INTERNAL_ONLY; + obj_desc->method.implementation = acpi_ut_osi_implementation; #endif break; @@ -180,8 +193,8 @@ case ACPI_TYPE_MUTEX: obj_desc->mutex.node = new_node; - obj_desc->mutex.sync_level = - (u16) ACPI_STRTOUL (val, NULL, 10); + obj_desc->mutex.sync_level = (u16) ACPI_STRTOUL + (val, NULL, 10); if (ACPI_STRCMP (init_val->name, "_GL_") == 0) { /* @@ -213,6 +226,7 @@ default: + ACPI_REPORT_ERROR (("Unsupported initial type value %X\n", init_val->type)); acpi_ut_remove_reference (obj_desc); diff -Nru a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c --- a/drivers/acpi/namespace/nsalloc.c Sat Mar 13 04:58:44 2004 +++ b/drivers/acpi/namespace/nsalloc.c Sat Mar 13 04:58:44 2004 @@ -334,10 +334,11 @@ node->owner_id = owner_id; node->type = (u8) type; - ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%4.4s (%s) added to %4.4s (%s) %p at %p\n", - acpi_ut_get_node_name (node), acpi_ut_get_type_name (node->type), + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n", + acpi_ut_get_node_name (node), acpi_ut_get_type_name (node->type), node, owner_id, acpi_ut_get_node_name (parent_node), acpi_ut_get_type_name (parent_node->type), - parent_node, node)); + parent_node)); /* * Increment the reference count(s) of all parents up to diff -Nru a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c --- a/drivers/acpi/namespace/nseval.c Sat Mar 13 04:58:44 2004 +++ b/drivers/acpi/namespace/nseval.c Sat Mar 13 04:58:44 2004 @@ -82,11 +82,11 @@ union acpi_operand_object **params, union acpi_operand_object **return_object) { - struct acpi_namespace_node *prefix_node; acpi_status status; + struct acpi_namespace_node *prefix_node; struct acpi_namespace_node *node = NULL; + union acpi_generic_state *scope_info; char *internal_path = NULL; - union acpi_generic_state scope_info; ACPI_FUNCTION_TRACE ("ns_evaluate_relative"); @@ -106,6 +106,11 @@ return_ACPI_STATUS (status); } + scope_info = acpi_ut_create_generic_state (); + if (!scope_info) { + goto cleanup1; + } + /* Get the prefix handle and Node */ status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); @@ -122,8 +127,8 @@ /* Lookup the name in the namespace */ - scope_info.scope.node = prefix_node; - status = acpi_ns_lookup (&scope_info, internal_path, ACPI_TYPE_ANY, + scope_info->scope.node = prefix_node; + status = acpi_ns_lookup (scope_info, internal_path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL, &node); @@ -148,7 +153,9 @@ pathname)); cleanup: + acpi_ut_delete_generic_state (scope_info); +cleanup1: ACPI_MEM_FREE (internal_path); return_ACPI_STATUS (status); } diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c --- a/drivers/acpi/osl.c Sat Mar 13 04:58:44 2004 +++ b/drivers/acpi/osl.c Sat Mar 13 04:58:44 2004 @@ -1021,3 +1021,39 @@ } __setup("acpi_os_name=", acpi_os_name_setup); + +/* + * _OSI control + * empty string disables _OSI + * TBD additional string adds to _OSI + */ +int __init +acpi_osi_setup(char *str) +{ + if (str == NULL || *str == '\0') { + printk(KERN_INFO PREFIX "_OSI method disabled\n"); + acpi_gbl_create_osi_method = FALSE; + } else + { + /* TBD */ + printk(KERN_ERR PREFIX "_OSI additional string ignored -- %s\n", str); + } + + return 1; +} + +__setup("acpi_osi=", acpi_osi_setup); + +/* enable serialization to combat AE_ALREADY_EXISTS errors */ +int __init +acpi_serialize_setup(char *str) +{ + printk(KERN_INFO PREFIX "serialize enabled\n"); + + acpi_gbl_all_methods_serialized = TRUE; + + return 1; +} + +__setup("acpi_serialize", acpi_serialize_setup); + diff -Nru a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c --- a/drivers/acpi/parser/psparse.c Sat Mar 13 04:58:44 2004 +++ b/drivers/acpi/parser/psparse.c Sat Mar 13 04:58:44 2004 @@ -426,7 +426,7 @@ acpi_status status = AE_OK; union acpi_parse_object *op = NULL; /* current op */ union acpi_parse_object *arg = NULL; - union acpi_parse_object pre_op; + union acpi_parse_object *pre_op = NULL; struct acpi_parse_state *parser_state; u8 *aml_op_start = NULL; @@ -547,8 +547,17 @@ /* Create Op structure and append to parent's argument list */ if (walk_state->op_info->flags & AML_NAMED) { - pre_op.common.value.arg = NULL; - pre_op.common.aml_opcode = walk_state->opcode; + /* Allocate a new pre_op if necessary */ + + if (!pre_op) { + pre_op = acpi_ps_alloc_op (walk_state->opcode); + if (!pre_op) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + } + + pre_op->common.value.arg = NULL; + pre_op->common.aml_opcode = walk_state->opcode; /* * Get and append arguments until we find the node that contains @@ -562,7 +571,7 @@ goto close_this_op; } - acpi_ps_append_arg (&pre_op, arg); + acpi_ps_append_arg (pre_op, arg); INCREMENT_ARG_LIST (walk_state->arg_types); } @@ -603,7 +612,7 @@ goto close_this_op; } - acpi_ps_append_arg (op, pre_op.common.value.arg); + acpi_ps_append_arg (op, pre_op->common.value.arg); acpi_gbl_depth++; if (op->common.aml_opcode == AML_REGION_OP) { @@ -854,6 +863,10 @@ acpi_ps_complete_this_op (walk_state, op); op = NULL; + if (pre_op) { + acpi_ps_free_op (pre_op); + pre_op = NULL; + } switch (status) { case AE_OK: @@ -1118,6 +1131,27 @@ else if (status != AE_OK) { ACPI_REPORT_METHOD_ERROR ("Method execution failed", walk_state->method_node, NULL, status); + + /* Check for possible multi-thread reentrancy problem */ + + if ((status == AE_ALREADY_EXISTS) && + (!walk_state->method_desc->method.semaphore)) { + /* + * This method is marked not_serialized, but it tried to create a named + * object, causing the second thread entrance to fail. We will workaround + * this by marking the method permanently as Serialized. + */ + walk_state->method_desc->method.method_flags |= AML_METHOD_SERIALIZED; + walk_state->method_desc->method.concurrency = 1; + } + } + + if (walk_state->method_desc) { + /* Decrement the thread count on the method parse tree */ + + if (walk_state->method_desc->method.thread_count) { + walk_state->method_desc->method.thread_count--; + } } /* We are done with this walk, move on to the parent if any */ diff -Nru a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c --- a/drivers/acpi/parser/psscope.c Sat Mar 13 04:58:44 2004 +++ b/drivers/acpi/parser/psscope.c Sat Mar 13 04:58:44 2004 @@ -167,7 +167,6 @@ return_ACPI_STATUS (AE_NO_MEMORY); } - scope->common.data_type = ACPI_DESC_TYPE_STATE_PSCOPE; scope->parse_scope.op = op; scope->parse_scope.arg_list = remaining_args; @@ -178,13 +177,11 @@ acpi_ut_push_generic_state (&parser_state->scope, scope); - if (arg_count == ACPI_VAR_ARGS) { /* multiple arguments */ scope->parse_scope.arg_end = parser_state->pkg_end; } - else { /* single argument */ @@ -241,7 +238,6 @@ acpi_ut_delete_generic_state (scope); } - else { /* empty parse stack, prepare to fetch next opcode */ @@ -250,7 +246,6 @@ *arg_count = 0; } - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped Op %p Args %X\n", *op, *arg_count)); return_VOID; } @@ -275,13 +270,13 @@ { union acpi_generic_state *scope; + ACPI_FUNCTION_TRACE_PTR ("ps_cleanup_scope", parser_state); if (!parser_state) { - return; + return_VOID; } - /* Delete anything on the scope stack */ diff -Nru a/drivers/acpi/system.c b/drivers/acpi/system.c --- a/drivers/acpi/system.c Sat Mar 13 04:58:44 2004 +++ b/drivers/acpi/system.c Sat Mar 13 04:58:44 2004 @@ -40,6 +40,7 @@ #include #include #include +#include #ifdef CONFIG_ACPI_SLEEP #include @@ -99,6 +100,8 @@ { if (unlikely(in_interrupt())) BUG(); + /* Some SMP machines only can poweroff in boot CPU */ + set_cpus_allowed(current, 1UL << cpu_logical_map(0)); acpi_system_save_state(ACPI_STATE_S5); acpi_enter_sleep_state_prep(ACPI_STATE_S5); ACPI_DISABLE_IRQS(); diff -Nru a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c --- a/drivers/acpi/utilities/uteval.c Sat Mar 13 04:58:44 2004 +++ b/drivers/acpi/utilities/uteval.c Sat Mar 13 04:58:44 2004 @@ -53,6 +53,62 @@ /******************************************************************************* * + * FUNCTION: acpi_ut_osi_implementation + * + * PARAMETERS: walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Implementation of _OSI predefined control method + * Supported = _OSI (String) + * + ******************************************************************************/ + +acpi_status +acpi_ut_osi_implementation ( + struct acpi_walk_state *walk_state) +{ + union acpi_operand_object *string_desc; + union acpi_operand_object *return_desc; + acpi_native_uint i; + + + ACPI_FUNCTION_TRACE ("ut_osi_implementation"); + + + /* Validate the string input argument */ + + string_desc = walk_state->arguments[0].object; + if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) { + return_ACPI_STATUS (AE_TYPE); + } + + /* Create a return object (Default value = 0) */ + + return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!return_desc) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Compare input string to table of supported strings */ + + for (i = 0; i < ACPI_NUM_OSI_STRINGS; i++) { + if (!ACPI_STRCMP (string_desc->string.pointer, + (char *) acpi_gbl_valid_osi_strings[i])) { + /* This string is supported */ + + return_desc->integer.value = 0xFFFFFFFF; + break; + } + } + + walk_state->return_desc = return_desc; + return_ACPI_STATUS (AE_CTRL_TERMINATE); +} + + +/******************************************************************************* + * * FUNCTION: acpi_ut_evaluate_object * * PARAMETERS: prefix_node - Starting node diff -Nru a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c --- a/drivers/acpi/utilities/utglobal.c Sat Mar 13 04:58:44 2004 +++ b/drivers/acpi/utilities/utglobal.c Sat Mar 13 04:58:44 2004 @@ -185,6 +185,15 @@ "_S3D", "_S4D"}; +/* Strings supported by the _OSI predefined (internal) method */ + +const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = { + "Linux", + "Windows 2000", + "Windows 2001", + "Windows 2001.1"}; + + /****************************************************************************** * * Namespace globals @@ -195,14 +204,10 @@ /* * Predefined ACPI Names (Built-in to the Interpreter) * - * Initial values are currently supported only for types String and Number. - * Both are specified as strings in this table. - * * NOTES: - * 1) _SB_ is defined to be a device to allow _SB_/_INI to be run + * 1) _SB_ is defined to be a device to allow \_SB_._INI to be run * during the initialization sequence. */ - const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = { {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL}, {"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL}, @@ -213,7 +218,7 @@ {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, {"_GL_", ACPI_TYPE_MUTEX, "0"}, -#if defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) +#if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) {"_OSI", ACPI_TYPE_METHOD, "1"}, #endif {NULL, ACPI_TYPE_ANY, NULL} /* Table terminator */ @@ -224,7 +229,6 @@ * Properties of the ACPI Object Types, both internal and external. * The table is indexed by values of acpi_object_type */ - const u8 acpi_gbl_ns_properties[] = { ACPI_NS_NORMAL, /* 00 Any */ @@ -303,10 +307,8 @@ * ******************************************************************************/ - struct acpi_table_list acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES]; - struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES] = { /*********** Name, Signature, Global typed pointer Signature size, Type How many allowed?, Contains valid AML? */ @@ -470,9 +472,8 @@ * * The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching; when * stored in a table it really means that we have thus far seen no evidence to - * indicatewhat type is actually going to be stored for this entry. + * indicate what type is actually going to be stored for this entry. */ - static const char acpi_gbl_bad_type[] = "UNDEFINED"; #define TYPE_NAME_LENGTH 12 /* Maximum length of each string */ @@ -776,6 +777,11 @@ ACPI_FUNCTION_TRACE ("ut_init_globals"); + + /* Runtime configuration */ + + acpi_gbl_create_osi_method = TRUE; + acpi_gbl_all_methods_serialized = FALSE; /* Memory allocation and cache lists */ diff -Nru a/include/acpi/acconfig.h b/include/acpi/acconfig.h --- a/include/acpi/acconfig.h Sat Mar 13 04:58:44 2004 +++ b/include/acpi/acconfig.h Sat Mar 13 04:58:44 2004 @@ -64,7 +64,7 @@ /* Version string */ -#define ACPI_CA_VERSION 0x20040220 +#define ACPI_CA_VERSION 0x20040311 /* Maximum objects in the various object caches */ @@ -184,6 +184,10 @@ /* SMBus bidirectional buffer size */ #define ACPI_SMBUS_BUFFER_SIZE 34 + +/* Number of strings associated with the _OSI reserved method */ + +#define ACPI_NUM_OSI_STRINGS 4 /****************************************************************************** diff -Nru a/include/acpi/acglobal.h b/include/acpi/acglobal.h --- a/include/acpi/acglobal.h Sat Mar 13 04:58:44 2004 +++ b/include/acpi/acglobal.h Sat Mar 13 04:58:44 2004 @@ -79,6 +79,14 @@ extern u32 acpi_gbl_nesting_level; +/***************************************************************************** + * + * Runtime configuration + * + ****************************************************************************/ + +ACPI_EXTERN u8 acpi_gbl_create_osi_method; +ACPI_EXTERN u8 acpi_gbl_all_methods_serialized; /***************************************************************************** * @@ -169,6 +177,7 @@ extern const char *acpi_gbl_highest_dstate_names[4]; extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES]; extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS]; +extern const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS]; /***************************************************************************** @@ -179,7 +188,7 @@ #define NUM_NS_TYPES ACPI_TYPE_INVALID+1 -#if defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) +#if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) #define NUM_PREDEFINED_NAMES 10 #else #define NUM_PREDEFINED_NAMES 9 diff -Nru a/include/acpi/acmacros.h b/include/acpi/acmacros.h --- a/include/acpi/acmacros.h Sat Mar 13 04:58:44 2004 +++ b/include/acpi/acmacros.h Sat Mar 13 04:58:44 2004 @@ -681,7 +681,4 @@ #endif /* ACPI_DBG_TRACK_ALLOCATIONS */ - -#define ACPI_GET_STACK_POINTER _asm {mov eax, ebx} - #endif /* ACMACROS_H */ diff -Nru a/include/acpi/acobject.h b/include/acpi/acobject.h --- a/include/acpi/acobject.h Sat Mar 13 04:58:44 2004 +++ b/include/acpi/acobject.h Sat Mar 13 04:58:44 2004 @@ -180,7 +180,11 @@ }; -#define INFINITE_CONCURRENCY 0xFF +#define ACPI_INFINITE_CONCURRENCY 0xFF + +typedef +acpi_status (*ACPI_INTERNAL_METHOD) ( + struct acpi_walk_state *walk_state); struct acpi_object_method { @@ -190,6 +194,7 @@ u32 aml_length; void *semaphore; u8 *aml_start; + ACPI_INTERNAL_METHOD implementation; u8 concurrency; u8 thread_count; acpi_owner_id owning_id; diff -Nru a/include/acpi/actypes.h b/include/acpi/actypes.h --- a/include/acpi/actypes.h Sat Mar 13 04:58:44 2004 +++ b/include/acpi/actypes.h Sat Mar 13 04:58:44 2004 @@ -349,7 +349,6 @@ /* * Power state values */ - #define ACPI_STATE_UNKNOWN (u8) 0xFF #define ACPI_STATE_S0 (u8) 0 @@ -393,7 +392,6 @@ #define ACPI_NOTIFY_BUS_MODE_MISMATCH (u8) 6 #define ACPI_NOTIFY_POWER_FAULT (u8) 7 - /* * Table types. These values are passed to the table related APIs */ @@ -409,7 +407,6 @@ #define ACPI_TABLE_MAX 6 #define NUM_ACPI_TABLE_TYPES (ACPI_TABLE_MAX+1) - /* * Types associated with ACPI names and objects. The first group of * values (up to ACPI_TYPE_EXTERNAL_MAX) correspond to the definition @@ -794,7 +791,7 @@ #define ACPI_INIT_DEVICE_INI 1 -/* Address Spaces (Operation Regions */ +/* Address Spaces (For Operation Regions) */ typedef acpi_status (*acpi_adr_space_handler) ( diff -Nru a/include/acpi/acutils.h b/include/acpi/acutils.h --- a/include/acpi/acutils.h Sat Mar 13 04:58:44 2004 +++ b/include/acpi/acutils.h Sat Mar 13 04:58:44 2004 @@ -52,7 +52,6 @@ union acpi_generic_state *state, void *context); - acpi_status acpi_ut_walk_package_tree ( union acpi_operand_object *source_object, @@ -60,7 +59,6 @@ acpi_pkg_callback walk_callback, void *context); - struct acpi_pkg_info { u8 *free_space; @@ -474,6 +472,10 @@ #define METHOD_NAME__CRS "_CRS" #define METHOD_NAME__PRS "_PRS" + +acpi_status +acpi_ut_osi_implementation ( + struct acpi_walk_state *walk_state); acpi_status acpi_ut_evaluate_object ( diff -Nru a/include/acpi/amlcode.h b/include/acpi/amlcode.h --- a/include/acpi/amlcode.h Sat Mar 13 04:58:44 2004 +++ b/include/acpi/amlcode.h Sat Mar 13 04:58:44 2004 @@ -496,11 +496,17 @@ } AML_ACCESS_ATTRIBUTE; -/* bit fields in method_flags byte */ +/* Bit fields in method_flags byte */ -#define METHOD_FLAGS_ARG_COUNT 0x07 -#define METHOD_FLAGS_SERIALIZED 0x08 -#define METHOD_FLAGS_SYNCH_LEVEL 0xF0 +#define AML_METHOD_ARG_COUNT 0x07 +#define AML_METHOD_SERIALIZED 0x08 +#define AML_METHOD_SYNCH_LEVEL 0xF0 + +/* METHOD_FLAGS_ARG_COUNT is not used internally, define additional flags */ + +#define AML_METHOD_INTERNAL_ONLY 0x01 +#define AML_METHOD_RESERVED1 0x02 +#define AML_METHOD_RESERVED2 0x04 #endif /* __AMLCODE_H__ */ diff -Nru a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h --- a/include/asm-i386/acpi.h Sat Mar 13 04:58:44 2004 +++ b/include/asm-i386/acpi.h Sat Mar 13 04:58:44 2004 @@ -61,33 +61,36 @@ * Immediate values in the assembly are preceded by "$" as in "$0x1" * The final asm parameter are the operation altered non-output registers. */ + +static inline int +__acpi_acquire_global_lock (unsigned int *lock) +{ + unsigned int old, new, val; + do { + old = *lock; + new = (((old & ~0x3) + 2) + ((old >> 1) & 0x1)); + val = cmpxchg(lock, old, new); + } while (unlikely (val != old)); + return (new < 3) ? -1 : 0; +} + +static inline int +__acpi_release_global_lock (unsigned int *lock) +{ + unsigned int old, new, val; + do { + old = *lock; + new = old & ~0x3; + val = cmpxchg(lock, old, new); + } while (unlikely (val != old)); + return old & 0x1; +} + #define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ - do { \ - int dummy; \ - asm("1: movl (%1),%%eax;" \ - "movl %%eax,%%edx;" \ - "andl %2,%%edx;" \ - "btsl $0x1,%%edx;" \ - "adcl $0x0,%%edx;" \ - "lock; cmpxchgl %%edx,(%1);" \ - "jnz 1b;" \ - "cmpb $0x3,%%dl;" \ - "sbbl %%eax,%%eax" \ - :"=a"(Acq),"=c"(dummy):"c"(GLptr),"i"(~1L):"dx"); \ - } while(0) + ((Acq) = __acpi_acquire_global_lock((unsigned int *) GLptr)) #define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ - do { \ - int dummy; \ - asm("1: movl (%1),%%eax;" \ - "movl %%eax,%%edx;" \ - "andl %2,%%edx;" \ - "lock; cmpxchgl %%edx,(%1);" \ - "jnz 1b;" \ - "andl $0x1,%%eax" \ - :"=a"(Acq),"=c"(dummy):"c"(GLptr),"i"(~3L):"dx"); \ - } while(0) - + ((Acq) = __acpi_release_global_lock((unsigned int *) GLptr)) /* * Math helper asm macros diff -Nru a/include/asm-x86_64/acpi.h b/include/asm-x86_64/acpi.h --- a/include/asm-x86_64/acpi.h Sat Mar 13 04:58:44 2004 +++ b/include/asm-x86_64/acpi.h Sat Mar 13 04:58:44 2004 @@ -52,40 +52,35 @@ #define ACPI_ENABLE_IRQS() __sti() #define ACPI_FLUSH_CPU_CACHE() wbinvd() -/* - * A brief explanation as GNU inline assembly is a bit hairy - * %0 is the output parameter in RAX ("=a") - * %1 and %2 are the input parameters in RCX ("c") - * and an immediate value ("i") respectively - * All actual register references are preceded with "%%" as in "%%edx" - * Immediate values in the assembly are preceded by "$" as in "$0x1" - * The final asm parameter are the operation altered non-output registers. - */ +static inline int +__acpi_acquire_global_lock (unsigned int *lock) +{ + unsigned int old, new, val; + do { + old = *lock; + new = (((old & ~0x3) + 2) + ((old >> 1) & 0x1)); + val = cmpxchg(lock, old, new); + } while (unlikely (val != old)); + return (new < 3) ? -1 : 0; +} + +static inline int +__acpi_release_global_lock (unsigned int *lock) +{ + unsigned int old, new, val; + do { + old = *lock; + new = old & ~0x3; + val = cmpxchg(lock, old, new); + } while (unlikely (val != old)); + return old & 0x1; +} + #define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ - do { \ - unsigned long dummy; \ - asm("1: movl (%2),%%eax;" \ - "movl %%eax,%%edx;" \ - "andq %2,%%rdx;" \ - "btsl $0x1,%%edx;" \ - "adcl $0x0,%%edx;" \ - "lock; cmpxchgl %%edx,(%1);" \ - "jnz 1b;" \ - "cmpb $0x3,%%dl;" \ - "sbbl %%eax,%%eax" \ - :"=a"(Acq),"=c"(dummy):"c"(GLptr),"i"(~1L):"dx"); \ - } while(0) + ((Acq) = __acpi_acquire_global_lock((unsigned int *) GLptr)) + #define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ - do { \ - unsigned long dummy; \ - asm("1: movl (%2),%%eax;" \ - "movl %%eax,%%edx;" \ - "andq %2,%%rdx;" \ - "lock; cmpxchgl %%edx,(%1);" \ - "jnz 1b;" \ - "andl $0x1,%%eax" \ - :"=a"(Acq),"=c"(dummy):"c"(GLptr),"i"(~3L):"dx"); \ - } while(0) + ((Acq) = __acpi_release_global_lock((unsigned int *) GLptr)) /* * Math helper asm macros