diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 18:32:11 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 18:32:11 +0200 |
commit | c11f6c82581e8be4e1829c677db54e7f55cebece (patch) | |
tree | 1a116241b0831ded998aabe800bdc24104cbd826 /drivers/acpi/acpica/psloop.c | |
parent | Merge branch 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git... (diff) | |
parent | Merge branch 'video' into release (diff) | |
download | linux-c11f6c82581e8be4e1829c677db54e7f55cebece.tar.xz linux-c11f6c82581e8be4e1829c677db54e7f55cebece.zip |
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (119 commits)
ACPI: don't pass handle for fixed hardware notifications
ACPI: remove null pointer checks in deferred execution path
ACPI: simplify deferred execution path
acerhdf: additional BIOS versions
acerhdf: convert to dev_pm_ops
acerhdf: fix fan control for AOA150 model
thermal: add missing Kconfig dependency
acpi: switch /proc/acpi/{debug_layer,debug_level} to seq_file
hp-wmi: fix rfkill memory leak on unload
ACPI: remove unnecessary #ifdef CONFIG_DMI
ACPI: linux/acpi.h should not include linux/dmi.h
hwmon driver for ACPI 4.0 power meters
topstar-laptop: add new driver for hotkeys support on Topstar N01
thinkpad_acpi: fix rfkill memory leak on unload
thinkpad-acpi: report brightness events when required
thinkpad-acpi: don't poll by default any of the reserved hotkeys
thinkpad-acpi: Fix procfs hotkey reset command
thinkpad-acpi: deprecate hotkey_bios_mask
thinkpad-acpi: hotkey poll fixes
thinkpad-acpi: be more strict when detecting a ThinkPad
...
Diffstat (limited to 'drivers/acpi/acpica/psloop.c')
-rw-r--r-- | drivers/acpi/acpica/psloop.c | 119 |
1 files changed, 111 insertions, 8 deletions
diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c index c5f6ce19a401..cd7995b3aed4 100644 --- a/drivers/acpi/acpica/psloop.c +++ b/drivers/acpi/acpica/psloop.c @@ -86,6 +86,9 @@ static acpi_status acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, union acpi_parse_object *op, acpi_status status); +static void +acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id); + /******************************************************************************* * * FUNCTION: acpi_ps_get_aml_opcode @@ -390,6 +393,7 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, { acpi_status status = AE_OK; union acpi_parse_object *arg = NULL; + const struct acpi_opcode_info *op_info; ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state); @@ -449,13 +453,11 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, INCREMENT_ARG_LIST(walk_state->arg_types); } - /* Special processing for certain opcodes */ - - /* TBD (remove): Temporary mechanism to disable this code if needed */ - -#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE - - if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) && + /* + * Handle executable code at "module-level". This refers to + * executable opcodes that appear outside of any control method. + */ + if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2) && ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) { /* * We want to skip If/Else/While constructs during Pass1 because we @@ -469,6 +471,23 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, case AML_ELSE_OP: case AML_WHILE_OP: + /* + * Currently supported module-level opcodes are: + * IF/ELSE/WHILE. These appear to be the most common, + * and easiest to support since they open an AML + * package. + */ + if (walk_state->pass_number == + ACPI_IMODE_LOAD_PASS1) { + acpi_ps_link_module_code(aml_op_start, + walk_state-> + parser_state. + pkg_end - + aml_op_start, + walk_state-> + owner_id); + } + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Pass1: Skipping an If/Else/While body\n")); @@ -480,10 +499,34 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, break; default: + /* + * Check for an unsupported executable opcode at module + * level. We must be in PASS1, the parent must be a SCOPE, + * The opcode class must be EXECUTE, and the opcode must + * not be an argument to another opcode. + */ + if ((walk_state->pass_number == + ACPI_IMODE_LOAD_PASS1) + && (op->common.parent->common.aml_opcode == + AML_SCOPE_OP)) { + op_info = + acpi_ps_get_opcode_info(op->common. + aml_opcode); + if ((op_info->class == + AML_CLASS_EXECUTE) && (!arg)) { + ACPI_WARNING((AE_INFO, + "Detected an unsupported executable opcode " + "at module-level: [0x%.4X] at table offset 0x%.4X", + op->common.aml_opcode, + (u32)((aml_op_start - walk_state->parser_state.aml_start) + + sizeof(struct acpi_table_header)))); + } + } break; } } -#endif + + /* Special processing for certain opcodes */ switch (op->common.aml_opcode) { case AML_METHOD_OP: @@ -553,6 +596,66 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, /******************************************************************************* * + * FUNCTION: acpi_ps_link_module_code + * + * PARAMETERS: aml_start - Pointer to the AML + * aml_length - Length of executable AML + * owner_id - owner_id of module level code + * + * RETURN: None. + * + * DESCRIPTION: Wrap the module-level code with a method object and link the + * object to the global list. Note, the mutex field of the method + * object is used to link multiple module-level code objects. + * + ******************************************************************************/ + +static void +acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id) +{ + union acpi_operand_object *prev; + union acpi_operand_object *next; + union acpi_operand_object *method_obj; + + /* Get the tail of the list */ + + prev = next = acpi_gbl_module_code_list; + while (next) { + prev = next; + next = next->method.mutex; + } + + /* + * Insert the module level code into the list. Merge it if it is + * adjacent to the previous element. + */ + if (!prev || + ((prev->method.aml_start + prev->method.aml_length) != aml_start)) { + + /* Create, initialize, and link a new temporary method object */ + + method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD); + if (!method_obj) { + return; + } + + method_obj->method.aml_start = aml_start; + method_obj->method.aml_length = aml_length; + method_obj->method.owner_id = owner_id; + method_obj->method.flags |= AOPOBJ_MODULE_LEVEL; + + if (!prev) { + acpi_gbl_module_code_list = method_obj; + } else { + prev->method.mutex = method_obj; + } + } else { + prev->method.aml_length += aml_length; + } +} + +/******************************************************************************* + * * FUNCTION: acpi_ps_complete_op * * PARAMETERS: walk_state - Current state |