diff options
Diffstat (limited to 'drivers/acpi/acpica')
172 files changed, 17526 insertions, 10837 deletions
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 0ca208b6dcf..8bb43f06e11 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -31,6 +31,7 @@ acpi-y += \ evgpeinit.o \ evgpeutil.o \ evglock.o \ + evhandler.o \ evmisc.o \ evregion.o \ evrgnini.o \ @@ -68,18 +69,22 @@ acpi-y += \ acpi-y += \ hwacpi.o \ + hwesleep.o \ hwgpe.o \ hwpci.o \ hwregs.o \ hwsleep.o \ hwvalid.o \ - hwxface.o + hwxface.o \ + hwxfsleep.o acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o acpi-y += \ nsaccess.o \ nsalloc.o \ + nsarguments.o \ + nsconvert.o \ nsdump.o \ nseval.o \ nsinit.o \ @@ -88,6 +93,7 @@ acpi-y += \ nsobject.o \ nsparse.o \ nspredef.o \ + nsprepkg.o \ nsrepair.o \ nsrepair2.o \ nssearch.o \ @@ -102,7 +108,9 @@ acpi-$(ACPI_FUTURE_USAGE) += nsdumpdv.o acpi-y += \ psargs.o \ psloop.o \ + psobject.o \ psopcode.o \ + psopinfo.o \ psparse.o \ psscope.o \ pstree.o \ @@ -114,6 +122,8 @@ acpi-y += \ rsaddr.o \ rscalc.o \ rscreate.o \ + rsdump.o \ + rsdumpinfo.o \ rsinfo.o \ rsio.o \ rsirq.o \ @@ -124,23 +134,27 @@ acpi-y += \ rsutils.o \ rsxface.o -acpi-$(ACPI_FUTURE_USAGE) += rsdump.o - acpi-y += \ + tbdata.o \ tbfadt.o \ tbfind.o \ tbinstal.o \ + tbprint.o \ tbutils.o \ tbxface.o \ + tbxfload.o \ tbxfroot.o acpi-y += \ utaddress.o \ utalloc.o \ + utbuffer.o \ utcopy.o \ + utexcep.o \ utdebug.o \ utdecode.o \ utdelete.o \ + uterror.o \ uteval.o \ utglobal.o \ utids.o \ @@ -151,8 +165,15 @@ acpi-y += \ utmutex.o \ utobject.o \ utosi.o \ + utownerid.o \ + utpredef.o \ utresrc.o \ utstate.o \ + utstring.o \ utxface.o \ + utxfinit.o \ utxferror.o \ utxfmutex.o + +acpi-$(ACPI_FUTURE_USAGE) += uttrack.o utcache.o + diff --git a/drivers/acpi/acpica/acapps.h b/drivers/acpi/acpica/acapps.h new file mode 100644 index 00000000000..8698ffba6f3 --- /dev/null +++ b/drivers/acpi/acpica/acapps.h @@ -0,0 +1,170 @@ +/****************************************************************************** + * + * Module Name: acapps - common include for ACPI applications/tools + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef _ACAPPS +#define _ACAPPS + +/* Common info for tool signons */ + +#define ACPICA_NAME "Intel ACPI Component Architecture" +#define ACPICA_COPYRIGHT "Copyright (c) 2000 - 2014 Intel Corporation" + +#if ACPI_MACHINE_WIDTH == 64 +#define ACPI_WIDTH "-64" + +#elif ACPI_MACHINE_WIDTH == 32 +#define ACPI_WIDTH "-32" + +#else +#error unknown ACPI_MACHINE_WIDTH +#define ACPI_WIDTH "-??" + +#endif + +/* Macros for signons and file headers */ + +#define ACPI_COMMON_SIGNON(utility_name) \ + "\n%s\n%s version %8.8X%s [%s]\n%s\n\n", \ + ACPICA_NAME, \ + utility_name, ((u32) ACPI_CA_VERSION), ACPI_WIDTH, __DATE__, \ + ACPICA_COPYRIGHT + +#define ACPI_COMMON_HEADER(utility_name, prefix) \ + "%s%s\n%s%s version %8.8X%s [%s]\n%s%s\n%s\n", \ + prefix, ACPICA_NAME, \ + prefix, utility_name, ((u32) ACPI_CA_VERSION), ACPI_WIDTH, __DATE__, \ + prefix, ACPICA_COPYRIGHT, \ + prefix + +/* Macros for usage messages */ + +#define ACPI_USAGE_HEADER(usage) \ + printf ("Usage: %s\nOptions:\n", usage); + +#define ACPI_OPTION(name, description) \ + printf (" %-18s%s\n", name, description); + +#define FILE_SUFFIX_DISASSEMBLY "dsl" +#define ACPI_TABLE_FILE_SUFFIX ".dat" + +/* + * getopt + */ +int acpi_getopt(int argc, char **argv, char *opts); + +int acpi_getopt_argument(int argc, char **argv); + +extern int acpi_gbl_optind; +extern int acpi_gbl_opterr; +extern int acpi_gbl_sub_opt_char; +extern char *acpi_gbl_optarg; + +/* + * cmfsize - Common get file size function + */ +u32 cm_get_file_size(FILE * file); + +#ifndef ACPI_DUMP_APP +/* + * adisasm + */ +acpi_status +ad_aml_disassemble(u8 out_to_file, + char *filename, char *prefix, char **out_filename); + +void ad_print_statistics(void); + +acpi_status ad_find_dsdt(u8 **dsdt_ptr, u32 *dsdt_length); + +void ad_dump_tables(void); + +acpi_status ad_get_local_tables(void); + +acpi_status +ad_parse_table(struct acpi_table_header *table, + acpi_owner_id * owner_id, u8 load_table, u8 external); + +acpi_status ad_display_tables(char *filename, struct acpi_table_header *table); + +acpi_status ad_display_statistics(void); + +/* + * adwalk + */ +void +acpi_dm_cross_reference_namespace(union acpi_parse_object *parse_tree_root, + struct acpi_namespace_node *namespace_root, + acpi_owner_id owner_id); + +void acpi_dm_dump_tree(union acpi_parse_object *origin); + +void acpi_dm_find_orphan_methods(union acpi_parse_object *origin); + +void +acpi_dm_finish_namespace_load(union acpi_parse_object *parse_tree_root, + struct acpi_namespace_node *namespace_root, + acpi_owner_id owner_id); + +void +acpi_dm_convert_resource_indexes(union acpi_parse_object *parse_tree_root, + struct acpi_namespace_node *namespace_root); + +/* + * adfile + */ +acpi_status ad_initialize(void); + +char *fl_generate_filename(char *input_filename, char *suffix); + +acpi_status +fl_split_input_pathname(char *input_path, + char **out_directory_path, char **out_filename); + +char *ad_generate_filename(char *prefix, char *table_id); + +void +ad_write_table(struct acpi_table_header *table, + u32 length, char *table_name, char *oem_table_id); +#endif + +#endif /* _ACAPPS */ diff --git a/drivers/acpi/acpica/accommon.h b/drivers/acpi/acpica/accommon.h index a44bd424f9f..6f1c616910a 100644 --- a/drivers/acpi/acpica/accommon.h +++ b/drivers/acpi/acpica/accommon.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,7 +51,7 @@ * * Note: The order of these include files is important. */ -#include "acconfig.h" /* Global configuration constants */ +#include <acpi/acconfig.h> /* Global configuration constants */ #include "acmacros.h" /* C macros */ #include "aclocal.h" /* Internal data types */ #include "acobject.h" /* ACPI internal object */ diff --git a/drivers/acpi/acpica/acconfig.h b/drivers/acpi/acpica/acconfig.h deleted file mode 100644 index 1f30af613e8..00000000000 --- a/drivers/acpi/acpica/acconfig.h +++ /dev/null @@ -1,231 +0,0 @@ -/****************************************************************************** - * - * Name: acconfig.h - Global configuration constants - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2012, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#ifndef _ACCONFIG_H -#define _ACCONFIG_H - -/****************************************************************************** - * - * Configuration options - * - *****************************************************************************/ - -/* - * ACPI_DEBUG_OUTPUT - This switch enables all the debug facilities of the - * ACPI subsystem. This includes the DEBUG_PRINT output - * statements. When disabled, all DEBUG_PRINT - * statements are compiled out. - * - * ACPI_APPLICATION - Use this switch if the subsystem is going to be run - * at the application level. - * - */ - -/* - * OS name, used for the _OS object. The _OS object is essentially obsolete, - * but there is a large base of ASL/AML code in existing machines that check - * for the string below. The use of this string usually guarantees that - * the ASL will execute down the most tested code path. Also, there is some - * code that will not execute the _OSI method unless _OS matches the string - * below. Therefore, change this string at your own risk. - */ -#define ACPI_OS_NAME "Microsoft Windows NT" - -/* Maximum objects in the various object caches */ - -#define ACPI_MAX_STATE_CACHE_DEPTH 96 /* State objects */ -#define ACPI_MAX_PARSE_CACHE_DEPTH 96 /* Parse tree objects */ -#define ACPI_MAX_EXTPARSE_CACHE_DEPTH 96 /* Parse tree objects */ -#define ACPI_MAX_OBJECT_CACHE_DEPTH 96 /* Interpreter operand objects */ -#define ACPI_MAX_NAMESPACE_CACHE_DEPTH 96 /* Namespace objects */ - -/* - * Should the subsystem abort the loading of an ACPI table if the - * table checksum is incorrect? - */ -#define ACPI_CHECKSUM_ABORT FALSE - -/****************************************************************************** - * - * Subsystem Constants - * - *****************************************************************************/ - -/* Version of ACPI supported */ - -#define ACPI_CA_SUPPORT_LEVEL 3 - -/* Maximum count for a semaphore object */ - -#define ACPI_MAX_SEMAPHORE_COUNT 256 - -/* Maximum object reference count (detects object deletion issues) */ - -#define ACPI_MAX_REFERENCE_COUNT 0x1000 - -/* Default page size for use in mapping memory for operation regions */ - -#define ACPI_DEFAULT_PAGE_SIZE 4096 /* Must be power of 2 */ - -/* owner_id tracking. 8 entries allows for 255 owner_ids */ - -#define ACPI_NUM_OWNERID_MASKS 8 - -/* Size of the root table array is increased by this increment */ - -#define ACPI_ROOT_TABLE_SIZE_INCREMENT 4 - -/* Maximum number of While() loop iterations before forced abort */ - -#define ACPI_MAX_LOOP_ITERATIONS 0xFFFF - -/* Maximum sleep allowed via Sleep() operator */ - -#define ACPI_MAX_SLEEP 2000 /* Two seconds */ - -/* Address Range lists are per-space_id (Memory and I/O only) */ - -#define ACPI_ADDRESS_RANGE_MAX 2 - -/****************************************************************************** - * - * ACPI Specification constants (Do not change unless the specification changes) - * - *****************************************************************************/ - -/* Number of distinct GPE register blocks and register width */ - -#define ACPI_MAX_GPE_BLOCKS 2 -#define ACPI_GPE_REGISTER_WIDTH 8 - -/* Method info (in WALK_STATE), containing local variables and argumetns */ - -#define ACPI_METHOD_NUM_LOCALS 8 -#define ACPI_METHOD_MAX_LOCAL 7 - -#define ACPI_METHOD_NUM_ARGS 7 -#define ACPI_METHOD_MAX_ARG 6 - -/* Length of _HID, _UID, _CID, and UUID values */ - -#define ACPI_DEVICE_ID_LENGTH 0x09 -#define ACPI_MAX_CID_LENGTH 48 -#define ACPI_UUID_LENGTH 16 - -/* - * Operand Stack (in WALK_STATE), Must be large enough to contain METHOD_MAX_ARG - */ -#define ACPI_OBJ_NUM_OPERANDS 8 -#define ACPI_OBJ_MAX_OPERAND 7 - -/* Number of elements in the Result Stack frame, can be an arbitrary value */ - -#define ACPI_RESULTS_FRAME_OBJ_NUM 8 - -/* - * Maximal number of elements the Result Stack can contain, - * it may be an arbitray value not exceeding the types of - * result_size and result_count (now u8). - */ -#define ACPI_RESULTS_OBJ_NUM_MAX 255 - -/* Names within the namespace are 4 bytes long */ - -#define ACPI_NAME_SIZE 4 -#define ACPI_PATH_SEGMENT_LENGTH 5 /* 4 chars for name + 1 char for separator */ -#define ACPI_PATH_SEPARATOR '.' - -/* Sizes for ACPI table headers */ - -#define ACPI_OEM_ID_SIZE 6 -#define ACPI_OEM_TABLE_ID_SIZE 8 - -/* Constants used in searching for the RSDP in low memory */ - -#define ACPI_EBDA_PTR_LOCATION 0x0000040E /* Physical Address */ -#define ACPI_EBDA_PTR_LENGTH 2 -#define ACPI_EBDA_WINDOW_SIZE 1024 -#define ACPI_HI_RSDP_WINDOW_BASE 0x000E0000 /* Physical Address */ -#define ACPI_HI_RSDP_WINDOW_SIZE 0x00020000 -#define ACPI_RSDP_SCAN_STEP 16 - -/* Operation regions */ - -#define ACPI_USER_REGION_BEGIN 0x80 - -/* Maximum space_ids for Operation Regions */ - -#define ACPI_MAX_ADDRESS_SPACE 255 - -/* Array sizes. Used for range checking also */ - -#define ACPI_MAX_MATCH_OPCODE 5 - -/* RSDP checksums */ - -#define ACPI_RSDP_CHECKSUM_LENGTH 20 -#define ACPI_RSDP_XCHECKSUM_LENGTH 36 - -/* SMBus, GSBus and IPMI bidirectional buffer size */ - -#define ACPI_SMBUS_BUFFER_SIZE 34 -#define ACPI_GSBUS_BUFFER_SIZE 34 -#define ACPI_IPMI_BUFFER_SIZE 66 - -/* _sx_d and _sx_w control methods */ - -#define ACPI_NUM_sx_d_METHODS 4 -#define ACPI_NUM_sx_w_METHODS 5 - -/****************************************************************************** - * - * ACPI AML Debugger - * - *****************************************************************************/ - -#define ACPI_DEBUGGER_MAX_ARGS 8 /* Must be max method args + 1 */ - -#define ACPI_DEBUGGER_COMMAND_PROMPT '-' -#define ACPI_DEBUGGER_EXECUTE_PROMPT '%' - -#endif /* _ACCONFIG_H */ diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index deaa8197956..68a91eb0fa4 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,17 +44,28 @@ #ifndef __ACDEBUG_H__ #define __ACDEBUG_H__ -#define ACPI_DEBUG_BUFFER_SIZE 4196 +#define ACPI_DEBUG_BUFFER_SIZE 0x4000 /* 16K buffer for return objects */ -struct command_info { +struct acpi_db_command_info { char *name; /* Command Name */ u8 min_args; /* Minimum arguments required */ }; -struct argument_info { +struct acpi_db_command_help { + u8 line_count; /* Number of help lines */ + char *invocation; /* Command Invocation */ + char *description; /* Command Description */ +}; + +struct acpi_db_argument_info { char *name; /* Argument Name */ }; +struct acpi_db_execute_walk { + u32 count; + u32 max_count; +}; + #define PARAM_LIST(pl) pl #define DBTEST_OUTPUT_LEVEL(lvl) if (acpi_gbl_db_opt_verbose) #define VERBOSE_PRINT(fp) DBTEST_OUTPUT_LEVEL(lvl) {\ @@ -77,57 +88,91 @@ acpi_db_single_step(struct acpi_walk_state *walk_state, /* * dbcmds - debug commands and output routines */ -acpi_status acpi_db_disassemble_method(char *name); +struct acpi_namespace_node *acpi_db_convert_to_node(char *in_string); void acpi_db_display_table_info(char *table_arg); -void acpi_db_unload_acpi_table(char *table_arg, char *instance_arg); +void acpi_db_display_template(char *buffer_arg); -void -acpi_db_set_method_breakpoint(char *location, - struct acpi_walk_state *walk_state, - union acpi_parse_object *op); +void acpi_db_unload_acpi_table(char *name); -void acpi_db_set_method_call_breakpoint(union acpi_parse_object *op); +void acpi_db_send_notify(char *name, u32 value); -void acpi_db_get_bus_info(void); +void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg); -void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op); +acpi_status acpi_db_sleep(char *object_arg); -void acpi_db_dump_namespace(char *start_arg, char *depth_arg); +void acpi_db_display_locks(void); -void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg); +void acpi_db_display_resources(char *object_arg); -void acpi_db_send_notify(char *name, u32 value); +ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_display_gpes(void)) -void acpi_db_set_method_data(char *type_arg, char *index_arg, char *value_arg); +void acpi_db_display_handlers(void); + +ACPI_HW_DEPENDENT_RETURN_VOID(void + acpi_db_generate_gpe(char *gpe_arg, + char *block_arg)) +ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_sci(void)) + +void acpi_db_execute_test(char *type_arg); + +/* + * dbconvert - miscellaneous conversion routines + */ +acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value); + +acpi_status acpi_db_convert_to_package(char *string, union acpi_object *object); acpi_status -acpi_db_display_objects(char *obj_type_arg, char *display_count_arg); +acpi_db_convert_to_object(acpi_object_type type, + char *string, union acpi_object *object); -void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg); +u8 *acpi_db_encode_pld_buffer(struct acpi_pld_info *pld_info); -acpi_status acpi_db_find_name_in_namespace(char *name_arg); +void acpi_db_dump_pld_buffer(union acpi_object *obj_desc); -void acpi_db_set_scope(char *name); +/* + * dbmethod - control method commands + */ +void +acpi_db_set_method_breakpoint(char *location, + struct acpi_walk_state *walk_state, + union acpi_parse_object *op); -acpi_status acpi_db_sleep(char *object_arg); +void acpi_db_set_method_call_breakpoint(union acpi_parse_object *op); -void acpi_db_find_references(char *object_arg); +void acpi_db_set_method_data(char *type_arg, char *index_arg, char *value_arg); -void acpi_db_display_locks(void); +acpi_status acpi_db_disassemble_method(char *name); -void acpi_db_display_resources(char *object_arg); +void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op); -void acpi_db_display_gpes(void); +void acpi_db_batch_execute(char *count_arg); -void acpi_db_check_integrity(void); +/* + * dbnames - namespace commands + */ +void acpi_db_set_scope(char *name); + +void acpi_db_dump_namespace(char *start_arg, char *depth_arg); -void acpi_db_generate_gpe(char *gpe_arg, char *block_arg); +void acpi_db_dump_namespace_paths(void); + +void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg); + +acpi_status acpi_db_find_name_in_namespace(char *name_arg); void acpi_db_check_predefined_names(void); -void acpi_db_batch_execute(void); +acpi_status +acpi_db_display_objects(char *obj_type_arg, char *display_count_arg); + +void acpi_db_check_integrity(void); + +void acpi_db_find_references(char *object_arg); + +void acpi_db_get_bus_info(void); /* * dbdisply - debug display commands @@ -159,12 +204,15 @@ acpi_db_display_argument_object(union acpi_operand_object *obj_desc, /* * dbexec - debugger control method execution */ -void acpi_db_execute(char *name, char **args, u32 flags); +void +acpi_db_execute(char *name, char **args, acpi_object_type * types, u32 flags); void acpi_db_create_execution_threads(char *num_threads_arg, char *num_loops_arg, char *method_name_arg); +void acpi_db_delete_objects(u32 count, union acpi_object *objects); + #ifdef ACPI_DBG_TRACK_ALLOCATIONS u32 acpi_db_get_cache_info(struct acpi_memory_list *cache); #endif @@ -173,7 +221,8 @@ u32 acpi_db_get_cache_info(struct acpi_memory_list *cache); * dbfileio - Debugger file I/O commands */ acpi_object_type -acpi_db_match_argument(char *user_argument, struct argument_info *arguments); +acpi_db_match_argument(char *user_argument, + struct acpi_db_argument_info *arguments); void acpi_db_close_debug_file(void); @@ -196,6 +245,8 @@ void acpi_db_display_history(void); char *acpi_db_get_from_history(char *command_num_arg); +char *acpi_db_get_history_by_index(u32 commandd_num); + /* * dbinput - user front-end to the AML debugger */ @@ -206,6 +257,11 @@ acpi_db_command_dispatch(char *input_buffer, void ACPI_SYSTEM_XFACE acpi_db_execute_thread(void *context); +acpi_status acpi_db_user_commands(char prompt, union acpi_parse_object *op); + +char *acpi_db_get_next_token(char *string, + char **next, acpi_object_type * return_type); + /* * dbstats - Generation and display of ACPI table statistics */ diff --git a/drivers/acpi/acpica/acdispat.h b/drivers/acpi/acpica/acdispat.h index 5935ba6707e..d3e2cc395d7 100644 --- a/drivers/acpi/acpica/acdispat.h +++ b/drivers/acpi/acpica/acdispat.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -139,20 +139,21 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, struct acpi_walk_state *walk_state); /* - * dsload - Parser/Interpreter interface, pass 1 namespace load callbacks + * dsload - Parser/Interpreter interface */ acpi_status acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number); +/* dsload - pass 1 namespace load callbacks */ + acpi_status acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state, union acpi_parse_object **out_op); acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state); -/* - * dsload - Parser/Interpreter interface, pass 2 namespace load callbacks - */ +/* dsload - pass 2 namespace load callbacks */ + acpi_status acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, union acpi_parse_object **out_op); @@ -200,7 +201,9 @@ void acpi_ds_method_data_init(struct acpi_walk_state *walk_state); /* * dsmethod - Parser/Interpreter interface - control method parsing */ -acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node); +acpi_status +acpi_ds_auto_serialize_method(struct acpi_namespace_node *node, + union acpi_operand_object *obj_desc); acpi_status acpi_ds_call_control_method(struct acpi_thread_state *thread, @@ -309,10 +312,13 @@ acpi_ds_obj_stack_push(void *object, struct acpi_walk_state *walk_state); acpi_status acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state *walk_state); -struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_parse_object - *origin, union acpi_operand_object - *mth_desc, struct acpi_thread_state - *thread); +struct acpi_walk_state * acpi_ds_create_walk_state(acpi_owner_id owner_id, + union acpi_parse_object + *origin, + union acpi_operand_object + *mth_desc, + struct acpi_thread_state + *thread); acpi_status acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state, diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index c53caa521a3..7a7811a9fc2 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -69,10 +69,9 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node *node, */ acpi_status acpi_ev_init_global_lock_handler(void); -acpi_status acpi_ev_acquire_global_lock(u16 timeout); - -acpi_status acpi_ev_release_global_lock(void); - +ACPI_HW_DEPENDENT_RETURN_OK(acpi_status + acpi_ev_acquire_global_lock(u16 timeout)) +ACPI_HW_DEPENDENT_RETURN_OK(acpi_status acpi_ev_release_global_lock(void)) acpi_status acpi_ev_remove_global_lock_handler(void); /* @@ -85,9 +84,11 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info); acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info); -acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info); +acpi_status +acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info); -acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info); +acpi_status +acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info); struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, u32 gpe_number); @@ -103,9 +104,10 @@ acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info); */ acpi_status acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, - struct acpi_generic_address *gpe_block_address, + u64 address, + u8 space_id, u32 register_count, - u8 gpe_block_base_number, + u16 gpe_block_base_number, u32 interrupt_number, struct acpi_gpe_block_info **return_gpe_block); @@ -114,7 +116,9 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, struct acpi_gpe_block_info *gpe_block, void *context); -acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block); +ACPI_HW_DEPENDENT_RETURN_OK(acpi_status + acpi_ev_delete_gpe_block(struct acpi_gpe_block_info + *gpe_block)) u32 acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, @@ -126,7 +130,8 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, */ acpi_status acpi_ev_gpe_initialize(void); -void acpi_ev_update_gpes(acpi_owner_id table_owner_id); +ACPI_HW_DEPENDENT_RETURN_VOID(void + acpi_ev_update_gpes(acpi_owner_id table_owner_id)) acpi_status acpi_ev_match_gpe_method(acpi_handle obj_handle, @@ -144,7 +149,9 @@ acpi_status acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, struct acpi_gpe_block_info *gpe_block, void *context); -struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 interrupt_number); +acpi_status +acpi_ev_get_gpe_xrupt_block(u32 interrupt_number, + struct acpi_gpe_xrupt_info **gpe_xrupt_block); acpi_status acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt); @@ -154,10 +161,23 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, void *context); /* - * evregion - Address Space handling + * evhandler - Address space handling */ +u8 +acpi_ev_has_default_handler(struct acpi_namespace_node *node, + acpi_adr_space_type space_id); + acpi_status acpi_ev_install_region_handlers(void); +acpi_status +acpi_ev_install_space_handler(struct acpi_namespace_node *node, + acpi_adr_space_type space_id, + acpi_adr_space_handler handler, + acpi_adr_space_setup setup, void *context); + +/* + * evregion - Operation region support + */ acpi_status acpi_ev_initialize_op_regions(void); acpi_status @@ -176,12 +196,6 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, u8 acpi_ns_is_locked); acpi_status -acpi_ev_install_space_handler(struct acpi_namespace_node *node, - acpi_adr_space_type space_id, - acpi_adr_space_handler handler, - acpi_adr_space_setup setup, void *context); - -acpi_status acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, acpi_adr_space_type space_id); @@ -231,12 +245,11 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, */ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context); -u32 acpi_ev_install_sci_handler(void); - -acpi_status acpi_ev_remove_sci_handler(void); +u32 acpi_ev_sci_dispatch(void); -u32 acpi_ev_initialize_sCI(u32 program_sCI); +u32 acpi_ev_install_sci_handler(void); -void acpi_ev_terminate(void); +acpi_status acpi_ev_remove_all_sci_handlers(void); +ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_ev_terminate(void)) #endif /* __ACEVENTS_H__ */ diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 2853f7673f3..115eedcade1 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,177 +44,42 @@ #ifndef __ACGLOBAL_H__ #define __ACGLOBAL_H__ -/* - * Ensure that the globals are actually defined and initialized only once. - * - * The use of these macros allows a single list of globals (here) in order - * to simplify maintenance of the code. - */ -#ifdef DEFINE_ACPI_GLOBALS -#define ACPI_EXTERN -#define ACPI_INIT_GLOBAL(a,b) a=b -#else -#define ACPI_EXTERN extern -#define ACPI_INIT_GLOBAL(a,b) a -#endif - -#ifdef DEFINE_ACPI_GLOBALS - -/* Public globals, available from outside ACPICA subsystem */ - /***************************************************************************** * - * Runtime configuration (static defaults that can be overriden at runtime) + * Globals related to the ACPI tables * ****************************************************************************/ -/* - * Enable "slack" in the AML interpreter? Default is FALSE, and the - * interpreter strictly follows the ACPI specification. Setting to TRUE - * allows the interpreter to ignore certain errors and/or bad AML constructs. - * - * Currently, these features are enabled by this flag: - * - * 1) Allow "implicit return" of last value in a control method - * 2) Allow access beyond the end of an operation region - * 3) Allow access to uninitialized locals/args (auto-init to integer 0) - * 4) Allow ANY object type to be a source operand for the Store() operator - * 5) Allow unresolved references (invalid target name) in package objects - * 6) Enable warning messages for behavior that is not ACPI spec compliant - */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE); +/* Master list of all ACPI tables that were found in the RSDT/XSDT */ -/* - * Automatically serialize ALL control methods? Default is FALSE, meaning - * to use the Serialized/not_serialized method flags on a per method basis. - * Only change this if the ASL code is poorly written and cannot handle - * reentrancy even though methods are marked "NotSerialized". - */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_all_methods_serialized, FALSE); +ACPI_GLOBAL(struct acpi_table_list, acpi_gbl_root_table_list); -/* - * Create the predefined _OSI method in the namespace? Default is TRUE - * because ACPI CA is fully compatible with other ACPI implementations. - * Changing this will revert ACPI CA (and machine ASL) to pre-OSI behavior. - */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_create_osi_method, TRUE); - -/* - * Optionally use default values for the ACPI register widths. Set this to - * TRUE to use the defaults, if an FADT contains incorrect widths/lengths. - */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE); - -/* - * Optionally enable output from the AML Debug Object. - */ -bool ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE); - -/* - * Optionally copy the entire DSDT to local memory (instead of simply - * mapping it.) There are some BIOSs that corrupt or replace the original - * DSDT, creating the need for this option. Default is FALSE, do not copy - * the DSDT. - */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_copy_dsdt_locally, FALSE); - -/* - * Optionally truncate I/O addresses to 16 bits. Provides compatibility - * with other ACPI implementations. NOTE: During ACPICA initialization, - * this value is set to TRUE if any Windows OSI strings have been - * requested by the BIOS. - */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_truncate_io_addresses, FALSE); - -/* - * Disable runtime checking and repair of values returned by control methods. - * Use only if the repair is causing a problem on a particular machine. - */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_disable_auto_repair, FALSE); - -/* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */ - -struct acpi_table_fadt acpi_gbl_FADT; -u32 acpi_current_gpe_count; -u32 acpi_gbl_trace_flags; -acpi_name acpi_gbl_trace_method_name; -u8 acpi_gbl_system_awake_and_running; - -/* - * ACPI 5.0 introduces the concept of a "reduced hardware platform", meaning - * that the ACPI hardware is no longer required. A flag in the FADT indicates - * a reduced HW machine, and that flag is duplicated here for convenience. - */ -u8 acpi_gbl_reduced_hardware; - -#endif - -/* Do not disassemble buffers to resource descriptors */ - -ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_no_resource_disassembly, FALSE); - -/***************************************************************************** - * - * Debug support - * - ****************************************************************************/ - -/* Procedure nesting level for debug output */ - -extern u32 acpi_gbl_nesting_level; +/* DSDT information. Used to check for DSDT corruption */ -ACPI_EXTERN u32 acpi_gpe_count; -ACPI_EXTERN u32 acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS]; +ACPI_GLOBAL(struct acpi_table_header *, acpi_gbl_DSDT); +ACPI_GLOBAL(struct acpi_table_header, acpi_gbl_original_dsdt_header); -/* Support for dynamic control method tracing mechanism */ +#if (!ACPI_REDUCED_HARDWARE) +ACPI_GLOBAL(struct acpi_table_facs *, acpi_gbl_FACS); -ACPI_EXTERN u32 acpi_gbl_original_dbg_level; -ACPI_EXTERN u32 acpi_gbl_original_dbg_layer; -ACPI_EXTERN u32 acpi_gbl_trace_dbg_level; -ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer; - -/***************************************************************************** - * - * ACPI Table globals - * - ****************************************************************************/ - -/* - * acpi_gbl_root_table_list is the master list of ACPI tables that were - * found in the RSDT/XSDT. - */ -ACPI_EXTERN struct acpi_table_list acpi_gbl_root_table_list; -ACPI_EXTERN struct acpi_table_facs *acpi_gbl_FACS; +#endif /* !ACPI_REDUCED_HARDWARE */ /* These addresses are calculated from the FADT Event Block addresses */ -ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_status; -ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_enable; - -ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_status; -ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable; - -/* DSDT information. Used to check for DSDT corruption */ +ACPI_GLOBAL(struct acpi_generic_address, acpi_gbl_xpm1a_status); +ACPI_GLOBAL(struct acpi_generic_address, acpi_gbl_xpm1a_enable); -ACPI_EXTERN struct acpi_table_header *acpi_gbl_DSDT; -ACPI_EXTERN struct acpi_table_header acpi_gbl_original_dsdt_header; +ACPI_GLOBAL(struct acpi_generic_address, acpi_gbl_xpm1b_status); +ACPI_GLOBAL(struct acpi_generic_address, acpi_gbl_xpm1b_enable); /* - * Handle both ACPI 1.0 and ACPI 2.0 Integer widths. The integer width is + * Handle both ACPI 1.0 and ACPI 2.0+ Integer widths. The integer width is * determined by the revision of the DSDT: If the DSDT revision is less than * 2, use only the lower 32 bits of the internal 64-bit Integer. */ -ACPI_EXTERN u8 acpi_gbl_integer_bit_width; -ACPI_EXTERN u8 acpi_gbl_integer_byte_width; -ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; - -/* Mutex for _OSI support */ - -ACPI_EXTERN acpi_mutex acpi_gbl_osi_mutex; - -/* Reader/Writer lock is used for namespace walk and dynamic table unload */ - -ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock; +ACPI_GLOBAL(u8, acpi_gbl_integer_bit_width); +ACPI_GLOBAL(u8, acpi_gbl_integer_byte_width); +ACPI_GLOBAL(u8, acpi_gbl_integer_nybble_width); /***************************************************************************** * @@ -227,27 +92,36 @@ ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock; * actual OS mutex handles, indexed by the local ACPI_MUTEX_HANDLEs. * (The table maps local handles to the real OS handles) */ -ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[ACPI_NUM_MUTEX]; +ACPI_GLOBAL(struct acpi_mutex_info, acpi_gbl_mutex_info[ACPI_NUM_MUTEX]); /* * Global lock mutex is an actual AML mutex object * Global lock semaphore works in conjunction with the actual global lock * Global lock spinlock is used for "pending" handshake */ -ACPI_EXTERN union acpi_operand_object *acpi_gbl_global_lock_mutex; -ACPI_EXTERN acpi_semaphore acpi_gbl_global_lock_semaphore; -ACPI_EXTERN acpi_spinlock acpi_gbl_global_lock_pending_lock; -ACPI_EXTERN u16 acpi_gbl_global_lock_handle; -ACPI_EXTERN u8 acpi_gbl_global_lock_acquired; -ACPI_EXTERN u8 acpi_gbl_global_lock_present; -ACPI_EXTERN u8 acpi_gbl_global_lock_pending; +ACPI_GLOBAL(union acpi_operand_object *, acpi_gbl_global_lock_mutex); +ACPI_GLOBAL(acpi_semaphore, acpi_gbl_global_lock_semaphore); +ACPI_GLOBAL(acpi_spinlock, acpi_gbl_global_lock_pending_lock); +ACPI_GLOBAL(u16, acpi_gbl_global_lock_handle); +ACPI_GLOBAL(u8, acpi_gbl_global_lock_acquired); +ACPI_GLOBAL(u8, acpi_gbl_global_lock_present); +ACPI_GLOBAL(u8, acpi_gbl_global_lock_pending); /* * Spinlocks are used for interfaces that can be possibly called at * interrupt level */ -ACPI_EXTERN acpi_spinlock acpi_gbl_gpe_lock; /* For GPE data structs and registers */ -ACPI_EXTERN acpi_spinlock acpi_gbl_hardware_lock; /* For ACPI H/W except GPE registers */ +ACPI_GLOBAL(acpi_spinlock, acpi_gbl_gpe_lock); /* For GPE data structs and registers */ +ACPI_GLOBAL(acpi_spinlock, acpi_gbl_hardware_lock); /* For ACPI H/W except GPE registers */ +ACPI_GLOBAL(acpi_spinlock, acpi_gbl_reference_count_lock); + +/* Mutex for _OSI support */ + +ACPI_GLOBAL(acpi_mutex, acpi_gbl_osi_mutex); + +/* Reader/Writer lock is used for namespace walk and dynamic table unload */ + +ACPI_GLOBAL(struct acpi_rw_lock, acpi_gbl_namespace_rw_lock); /***************************************************************************** * @@ -255,81 +129,70 @@ ACPI_EXTERN acpi_spinlock acpi_gbl_hardware_lock; /* For ACPI H/W except GPE reg * ****************************************************************************/ -#ifdef ACPI_DBG_TRACK_ALLOCATIONS +/* Object caches */ -/* Lists for tracking memory allocations */ +ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_namespace_cache); +ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_state_cache); +ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_ps_node_cache); +ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_ps_node_ext_cache); +ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_operand_cache); -ACPI_EXTERN struct acpi_memory_list *acpi_gbl_global_list; -ACPI_EXTERN struct acpi_memory_list *acpi_gbl_ns_node_list; -ACPI_EXTERN u8 acpi_gbl_display_final_mem_stats; -#endif +/* System */ -/* Object caches */ - -ACPI_EXTERN acpi_cache_t *acpi_gbl_namespace_cache; -ACPI_EXTERN acpi_cache_t *acpi_gbl_state_cache; -ACPI_EXTERN acpi_cache_t *acpi_gbl_ps_node_cache; -ACPI_EXTERN acpi_cache_t *acpi_gbl_ps_node_ext_cache; -ACPI_EXTERN acpi_cache_t *acpi_gbl_operand_cache; +ACPI_INIT_GLOBAL(u32, acpi_gbl_startup_flags, 0); +ACPI_INIT_GLOBAL(u8, acpi_gbl_shutdown, TRUE); /* Global handlers */ -ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_device_notify; -ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_system_notify; -ACPI_EXTERN acpi_exception_handler acpi_gbl_exception_handler; -ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler; -ACPI_EXTERN acpi_tbl_handler acpi_gbl_table_handler; -ACPI_EXTERN void *acpi_gbl_table_handler_context; -ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; -ACPI_EXTERN acpi_interface_handler acpi_gbl_interface_handler; +ACPI_GLOBAL(struct acpi_global_notify_handler, acpi_gbl_global_notify[2]); +ACPI_GLOBAL(acpi_exception_handler, acpi_gbl_exception_handler); +ACPI_GLOBAL(acpi_init_handler, acpi_gbl_init_handler); +ACPI_GLOBAL(acpi_table_handler, acpi_gbl_table_handler); +ACPI_GLOBAL(void *, acpi_gbl_table_handler_context); +ACPI_GLOBAL(acpi_interface_handler, acpi_gbl_interface_handler); +ACPI_GLOBAL(struct acpi_sci_handler_info *, acpi_gbl_sci_handler_list); /* Owner ID support */ -ACPI_EXTERN u32 acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS]; -ACPI_EXTERN u8 acpi_gbl_last_owner_id_index; -ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset; +ACPI_GLOBAL(u32, acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS]); +ACPI_GLOBAL(u8, acpi_gbl_last_owner_id_index); +ACPI_GLOBAL(u8, acpi_gbl_next_owner_id_offset); /* Initialization sequencing */ -ACPI_EXTERN u8 acpi_gbl_reg_methods_executed; +ACPI_GLOBAL(u8, acpi_gbl_reg_methods_executed); /* Misc */ -ACPI_EXTERN u32 acpi_gbl_original_mode; -ACPI_EXTERN u32 acpi_gbl_rsdp_original_location; -ACPI_EXTERN u32 acpi_gbl_ns_lookup_count; -ACPI_EXTERN u32 acpi_gbl_ps_find_count; -ACPI_EXTERN u16 acpi_gbl_pm1_enable_register_save; -ACPI_EXTERN u8 acpi_gbl_debugger_configuration; -ACPI_EXTERN u8 acpi_gbl_step_to_next_call; -ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present; -ACPI_EXTERN u8 acpi_gbl_events_initialized; -ACPI_EXTERN u8 acpi_gbl_osi_data; -ACPI_EXTERN struct acpi_interface_info *acpi_gbl_supported_interfaces; -ACPI_EXTERN struct acpi_address_range - *acpi_gbl_address_range_list[ACPI_ADDRESS_RANGE_MAX]; - -#ifndef DEFINE_ACPI_GLOBALS - -/* Other miscellaneous */ - -extern u8 acpi_gbl_shutdown; -extern u32 acpi_gbl_startup_flags; +ACPI_GLOBAL(u32, acpi_gbl_original_mode); +ACPI_GLOBAL(u32, acpi_gbl_ns_lookup_count); +ACPI_GLOBAL(u32, acpi_gbl_ps_find_count); +ACPI_GLOBAL(u16, acpi_gbl_pm1_enable_register_save); +ACPI_GLOBAL(u8, acpi_gbl_debugger_configuration); +ACPI_GLOBAL(u8, acpi_gbl_step_to_next_call); +ACPI_GLOBAL(u8, acpi_gbl_acpi_hardware_present); +ACPI_GLOBAL(u8, acpi_gbl_events_initialized); +ACPI_GLOBAL(struct acpi_interface_info *, acpi_gbl_supported_interfaces); +ACPI_GLOBAL(struct acpi_address_range *, + acpi_gbl_address_range_list[ACPI_ADDRESS_RANGE_MAX]); + +/* Other miscellaneous, declared and initialized in utglobal */ + extern const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT]; extern const char *acpi_gbl_lowest_dstate_names[ACPI_NUM_sx_w_METHODS]; extern const char *acpi_gbl_highest_dstate_names[ACPI_NUM_sx_d_METHODS]; -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 struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES]; -#endif +#ifdef ACPI_DBG_TRACK_ALLOCATIONS -/* Exception codes */ +/* Lists for tracking memory allocations (debug only) */ -extern char const *acpi_gbl_exception_names_env[]; -extern char const *acpi_gbl_exception_names_pgm[]; -extern char const *acpi_gbl_exception_names_tbl[]; -extern char const *acpi_gbl_exception_names_aml[]; -extern char const *acpi_gbl_exception_names_ctrl[]; +ACPI_GLOBAL(struct acpi_memory_list *, acpi_gbl_global_list); +ACPI_GLOBAL(struct acpi_memory_list *, acpi_gbl_ns_node_list); +ACPI_GLOBAL(u8, acpi_gbl_display_final_mem_stats); +ACPI_GLOBAL(u8, acpi_gbl_disable_mem_tracking); +#endif /***************************************************************************** * @@ -343,22 +206,23 @@ extern char const *acpi_gbl_exception_names_ctrl[]; #define NUM_PREDEFINED_NAMES 9 #endif -ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct; -ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node; -ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device; -ACPI_EXTERN union acpi_operand_object *acpi_gbl_module_code_list; +ACPI_GLOBAL(struct acpi_namespace_node, acpi_gbl_root_node_struct); +ACPI_GLOBAL(struct acpi_namespace_node *, acpi_gbl_root_node); +ACPI_GLOBAL(struct acpi_namespace_node *, acpi_gbl_fadt_gpe_device); +ACPI_GLOBAL(union acpi_operand_object *, acpi_gbl_module_code_list); extern const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES]; extern const struct acpi_predefined_names acpi_gbl_pre_defined_names[NUM_PREDEFINED_NAMES]; #ifdef ACPI_DEBUG_OUTPUT -ACPI_EXTERN u32 acpi_gbl_current_node_count; -ACPI_EXTERN u32 acpi_gbl_current_node_size; -ACPI_EXTERN u32 acpi_gbl_max_concurrent_node_count; -ACPI_EXTERN acpi_size *acpi_gbl_entry_stack_pointer; -ACPI_EXTERN acpi_size *acpi_gbl_lowest_stack_pointer; -ACPI_EXTERN u32 acpi_gbl_deepest_nesting; +ACPI_GLOBAL(u32, acpi_gbl_current_node_count); +ACPI_GLOBAL(u32, acpi_gbl_current_node_size); +ACPI_GLOBAL(u32, acpi_gbl_max_concurrent_node_count); +ACPI_GLOBAL(acpi_size *, acpi_gbl_entry_stack_pointer); +ACPI_GLOBAL(acpi_size *, acpi_gbl_lowest_stack_pointer); +ACPI_GLOBAL(u32, acpi_gbl_deepest_nesting); +ACPI_INIT_GLOBAL(u32, acpi_gbl_nesting_level, 0); #endif /***************************************************************************** @@ -367,11 +231,11 @@ ACPI_EXTERN u32 acpi_gbl_deepest_nesting; * ****************************************************************************/ -ACPI_EXTERN struct acpi_thread_state *acpi_gbl_current_walk_list; +ACPI_GLOBAL(struct acpi_thread_state *, acpi_gbl_current_walk_list); /* Control method single step flag */ -ACPI_EXTERN u8 acpi_gbl_cm_single_step; +ACPI_GLOBAL(u8, acpi_gbl_cm_single_step); /***************************************************************************** * @@ -381,8 +245,9 @@ ACPI_EXTERN u8 acpi_gbl_cm_single_step; extern struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG]; -ACPI_EXTERN u8 acpi_gbl_sleep_type_a; -ACPI_EXTERN u8 acpi_gbl_sleep_type_b; + +ACPI_GLOBAL(u8, acpi_gbl_sleep_type_a); +ACPI_GLOBAL(u8, acpi_gbl_sleep_type_b); /***************************************************************************** * @@ -390,68 +255,123 @@ ACPI_EXTERN u8 acpi_gbl_sleep_type_b; * ****************************************************************************/ +#if (!ACPI_REDUCED_HARDWARE) + +ACPI_GLOBAL(u8, acpi_gbl_all_gpes_initialized); +ACPI_GLOBAL(struct acpi_gpe_xrupt_info *, acpi_gbl_gpe_xrupt_list_head); +ACPI_GLOBAL(struct acpi_gpe_block_info *, + acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]); +ACPI_GLOBAL(acpi_gbl_event_handler, acpi_gbl_global_event_handler); +ACPI_GLOBAL(void *, acpi_gbl_global_event_handler_context); +ACPI_GLOBAL(struct acpi_fixed_event_handler, + acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS]); + extern struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS]; -ACPI_EXTERN struct acpi_fixed_event_handler - acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS]; -ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head; -ACPI_EXTERN struct acpi_gpe_block_info -*acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]; -ACPI_EXTERN u8 acpi_gbl_all_gpes_initialized; -ACPI_EXTERN ACPI_GBL_EVENT_HANDLER acpi_gbl_global_event_handler; -ACPI_EXTERN void *acpi_gbl_global_event_handler_context; + +#endif /* !ACPI_REDUCED_HARDWARE */ /***************************************************************************** * - * Debugger globals + * Debug support * ****************************************************************************/ -ACPI_EXTERN u8 acpi_gbl_db_output_flags; +/* Event counters */ + +ACPI_GLOBAL(u32, acpi_method_count); +ACPI_GLOBAL(u32, acpi_gpe_count); +ACPI_GLOBAL(u32, acpi_sci_count); +ACPI_GLOBAL(u32, acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS]); + +/* Support for dynamic control method tracing mechanism */ + +ACPI_GLOBAL(u32, acpi_gbl_original_dbg_level); +ACPI_GLOBAL(u32, acpi_gbl_original_dbg_layer); +ACPI_GLOBAL(u32, acpi_gbl_trace_dbg_level); +ACPI_GLOBAL(u32, acpi_gbl_trace_dbg_layer); + +/***************************************************************************** + * + * Debugger and Disassembler globals + * + ****************************************************************************/ + +ACPI_GLOBAL(u8, acpi_gbl_db_output_flags); #ifdef ACPI_DISASSEMBLER -ACPI_EXTERN u8 acpi_gbl_db_opt_disasm; -ACPI_EXTERN u8 acpi_gbl_db_opt_verbose; +/* Do not disassemble buffers to resource descriptors */ + +ACPI_INIT_GLOBAL(u8, acpi_gbl_no_resource_disassembly, FALSE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_ignore_noop_operator, FALSE); + +ACPI_GLOBAL(u8, acpi_gbl_db_opt_disasm); +ACPI_GLOBAL(u8, acpi_gbl_db_opt_verbose); +ACPI_GLOBAL(u8, acpi_gbl_num_external_methods); +ACPI_GLOBAL(u32, acpi_gbl_resolved_external_methods); +ACPI_GLOBAL(struct acpi_external_list *, acpi_gbl_external_list); +ACPI_GLOBAL(struct acpi_external_file *, acpi_gbl_external_file_list); #endif #ifdef ACPI_DEBUGGER -extern u8 acpi_gbl_method_executing; -extern u8 acpi_gbl_abort_method; -extern u8 acpi_gbl_db_terminate_threads; - -ACPI_EXTERN u8 acpi_gbl_db_opt_tables; -ACPI_EXTERN u8 acpi_gbl_db_opt_stats; -ACPI_EXTERN u8 acpi_gbl_db_opt_ini_methods; - -ACPI_EXTERN char *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS]; -ACPI_EXTERN char acpi_gbl_db_line_buf[80]; -ACPI_EXTERN char acpi_gbl_db_parsed_buf[80]; -ACPI_EXTERN char acpi_gbl_db_scope_buf[40]; -ACPI_EXTERN char acpi_gbl_db_debug_filename[40]; -ACPI_EXTERN u8 acpi_gbl_db_output_to_file; -ACPI_EXTERN char *acpi_gbl_db_buffer; -ACPI_EXTERN char *acpi_gbl_db_filename; -ACPI_EXTERN u32 acpi_gbl_db_debug_level; -ACPI_EXTERN u32 acpi_gbl_db_console_debug_level; -ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_db_scope_node; +ACPI_INIT_GLOBAL(u8, acpi_gbl_db_terminate_threads, FALSE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_abort_method, FALSE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_method_executing, FALSE); + +ACPI_GLOBAL(u8, acpi_gbl_db_opt_tables); +ACPI_GLOBAL(u8, acpi_gbl_db_opt_stats); +ACPI_GLOBAL(u8, acpi_gbl_db_opt_ini_methods); +ACPI_GLOBAL(u8, acpi_gbl_db_opt_no_region_support); +ACPI_GLOBAL(u8, acpi_gbl_db_output_to_file); +ACPI_GLOBAL(char *, acpi_gbl_db_buffer); +ACPI_GLOBAL(char *, acpi_gbl_db_filename); +ACPI_GLOBAL(u32, acpi_gbl_db_debug_level); +ACPI_GLOBAL(u32, acpi_gbl_db_console_debug_level); +ACPI_GLOBAL(struct acpi_namespace_node *, acpi_gbl_db_scope_node); + +ACPI_GLOBAL(char *, acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS]); +ACPI_GLOBAL(acpi_object_type, acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS]); + +/* These buffers should all be the same size */ + +ACPI_GLOBAL(char, acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE]); +ACPI_GLOBAL(char, acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE]); +ACPI_GLOBAL(char, acpi_gbl_db_scope_buf[ACPI_DB_LINE_BUFFER_SIZE]); +ACPI_GLOBAL(char, acpi_gbl_db_debug_filename[ACPI_DB_LINE_BUFFER_SIZE]); /* * Statistic globals */ -ACPI_EXTERN u16 acpi_gbl_obj_type_count[ACPI_TYPE_NS_NODE_MAX + 1]; -ACPI_EXTERN u16 acpi_gbl_node_type_count[ACPI_TYPE_NS_NODE_MAX + 1]; -ACPI_EXTERN u16 acpi_gbl_obj_type_count_misc; -ACPI_EXTERN u16 acpi_gbl_node_type_count_misc; -ACPI_EXTERN u32 acpi_gbl_num_nodes; -ACPI_EXTERN u32 acpi_gbl_num_objects; - -ACPI_EXTERN u32 acpi_gbl_size_of_parse_tree; -ACPI_EXTERN u32 acpi_gbl_size_of_method_trees; -ACPI_EXTERN u32 acpi_gbl_size_of_node_entries; -ACPI_EXTERN u32 acpi_gbl_size_of_acpi_objects; +ACPI_GLOBAL(u16, acpi_gbl_obj_type_count[ACPI_TYPE_NS_NODE_MAX + 1]); +ACPI_GLOBAL(u16, acpi_gbl_node_type_count[ACPI_TYPE_NS_NODE_MAX + 1]); +ACPI_GLOBAL(u16, acpi_gbl_obj_type_count_misc); +ACPI_GLOBAL(u16, acpi_gbl_node_type_count_misc); +ACPI_GLOBAL(u32, acpi_gbl_num_nodes); +ACPI_GLOBAL(u32, acpi_gbl_num_objects); #endif /* ACPI_DEBUGGER */ +/***************************************************************************** + * + * Application globals + * + ****************************************************************************/ + +#ifdef ACPI_APPLICATION + +ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_debug_file, NULL); + +#endif /* ACPI_APPLICATION */ + +/***************************************************************************** + * + * Info/help support + * + ****************************************************************************/ + +extern const struct ah_predefined_name asl_predefined_info[]; +extern const struct ah_device_id asl_device_ids[]; + #endif /* __ACGLOBAL_H__ */ diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index 677793e938f..2ad2351a983 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -81,6 +81,26 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value); acpi_status acpi_hw_clear_acpi_status(void); /* + * hwsleep - sleep/wake support (Legacy sleep registers) + */ +acpi_status acpi_hw_legacy_sleep(u8 sleep_state); + +acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state); + +acpi_status acpi_hw_legacy_wake(u8 sleep_state); + +/* + * hwesleep - sleep/wake support (Extended FADT-V5 sleep registers) + */ +void acpi_hw_execute_sleep_method(char *method_name, u32 integer_argument); + +acpi_status acpi_hw_extended_sleep(u8 sleep_state); + +acpi_status acpi_hw_extended_wake_prep(u8 sleep_state); + +acpi_status acpi_hw_extended_wake(u8 sleep_state); + +/* * hwvalid - Port I/O with validation */ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width); @@ -90,8 +110,7 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width); /* * hwgpe - GPE support */ -u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info, - struct acpi_gpe_register_info *gpe_register_info); +u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info); acpi_status acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action); @@ -128,16 +147,4 @@ acpi_status acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id, acpi_handle root_pci_device, acpi_handle pci_region); -#ifdef ACPI_FUTURE_USAGE -/* - * hwtimer - ACPI Timer prototypes - */ -acpi_status acpi_get_timer_resolution(u32 * resolution); - -acpi_status acpi_get_timer(u32 * ticks); - -acpi_status -acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed); -#endif /* ACPI_FUTURE_USAGE */ - #endif /* __ACHWARE_H__ */ diff --git a/drivers/acpi/acpica/acinterp.h b/drivers/acpi/acpica/acinterp.h index eb308635da7..b01f71ce052 100644 --- a/drivers/acpi/acpica/acinterp.h +++ b/drivers/acpi/acpica/acinterp.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -87,6 +87,10 @@ typedef const struct acpi_exdump_info { #define ACPI_EXD_PACKAGE 11 #define ACPI_EXD_FIELD 12 #define ACPI_EXD_REFERENCE 13 +#define ACPI_EXD_LIST 14 /* Operand object list */ +#define ACPI_EXD_HDLR_LIST 15 /* Address Handler list */ +#define ACPI_EXD_RGN_LIST 16 /* Region list */ +#define ACPI_EXD_NODE 17 /* Namespace Node */ /* restore default alignment */ @@ -454,11 +458,7 @@ void acpi_ex_enter_interpreter(void); void acpi_ex_exit_interpreter(void); -void acpi_ex_reacquire_interpreter(void); - -void acpi_ex_relinquish_interpreter(void); - -void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc); +u8 acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc); void acpi_ex_acquire_global_lock(u32 rule); diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 3f24068837d..91f801a2e68 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -189,11 +189,10 @@ struct acpi_namespace_node { #define ANOBJ_EVALUATED 0x20 /* Set on first evaluation of node */ #define ANOBJ_ALLOCATED_BUFFER 0x40 /* Method AML buffer is dynamic (install_method) */ -#define ANOBJ_IS_EXTERNAL 0x08 /* i_aSL only: This object created via External() */ -#define ANOBJ_METHOD_NO_RETVAL 0x10 /* i_aSL only: Method has no return value */ -#define ANOBJ_METHOD_SOME_NO_RETVAL 0x20 /* i_aSL only: Method has at least one return value */ -#define ANOBJ_IS_BIT_OFFSET 0x40 /* i_aSL only: Reference is a bit offset */ -#define ANOBJ_IS_REFERENCED 0x80 /* i_aSL only: Object was referenced */ +#define ANOBJ_IS_EXTERNAL 0x08 /* iASL only: This object created via External() */ +#define ANOBJ_METHOD_NO_RETVAL 0x10 /* iASL only: Method has no return value */ +#define ANOBJ_METHOD_SOME_NO_RETVAL 0x20 /* iASL only: Method has at least one return value */ +#define ANOBJ_IS_REFERENCED 0x80 /* iASL only: Object was referenced */ /* Internal ACPI table management - master table list */ @@ -262,10 +261,10 @@ struct acpi_create_field_info { }; typedef -acpi_status(*ACPI_INTERNAL_METHOD) (struct acpi_walk_state * walk_state); +acpi_status(*acpi_internal_method) (struct acpi_walk_state * walk_state); /* - * Bitmapped ACPI types. Used internally only + * Bitmapped ACPI types. Used internally only */ #define ACPI_BTYPE_ANY 0x00000000 #define ACPI_BTYPE_INTEGER 0x00000001 @@ -295,17 +294,19 @@ acpi_status(*ACPI_INTERNAL_METHOD) (struct acpi_walk_state * walk_state); #define ACPI_BTYPE_OBJECTS_AND_REFS 0x0001FFFF /* ARG or LOCAL */ #define ACPI_BTYPE_ALL_OBJECTS 0x0000FFFF +#pragma pack(1) + /* * Information structure for ACPI predefined names. * Each entry in the table contains the following items: * - * Name - The ACPI reserved name + * name - The ACPI reserved name * param_count - Number of arguments to the method * expected_return_btypes - Allowed type(s) for the return value */ struct acpi_name_info { char name[ACPI_NAME_SIZE]; - u8 param_count; + u16 argument_list; u8 expected_btypes; }; @@ -328,7 +329,7 @@ struct acpi_package_info { u8 count1; u8 object_type2; u8 count2; - u8 reserved; + u16 reserved; }; /* Used for ACPI_PTYPE2_FIXED */ @@ -337,6 +338,7 @@ struct acpi_package_info2 { u8 type; u8 count; u8 object_type[4]; + u8 reserved; }; /* Used for ACPI_PTYPE1_OPTION */ @@ -346,7 +348,7 @@ struct acpi_package_info3 { u8 count; u8 object_type[2]; u8 tail_object_type; - u8 reserved; + u16 reserved; }; union acpi_predefined_info { @@ -356,20 +358,23 @@ union acpi_predefined_info { struct acpi_package_info3 ret_info3; }; -/* Data block used during object validation */ +/* Reset to default packing */ -struct acpi_predefined_data { - char *pathname; - const union acpi_predefined_info *predefined; - union acpi_operand_object *parent_package; - struct acpi_namespace_node *node; - u32 flags; - u8 node_flags; -}; +#pragma pack() -/* Defines for Flags field above */ +/* Return object auto-repair info */ -#define ACPI_OBJECT_REPAIRED 1 +typedef acpi_status(*acpi_object_converter) (union acpi_operand_object + *original_object, + union acpi_operand_object + **converted_object); + +struct acpi_simple_repair_info { + char name[ACPI_NAME_SIZE]; + u32 unexpected_btypes; + u32 package_index; + acpi_object_converter object_converter; +}; /* * Bitmapped return value types @@ -393,6 +398,14 @@ struct acpi_predefined_data { * ****************************************************************************/ +/* Dispatch info for each host-installed SCI handler */ + +struct acpi_sci_handler_info { + struct acpi_sci_handler_info *next; + acpi_sci_handler address; /* Address of handler */ + void *context; /* Context to be passed to handler */ +}; + /* Dispatch info for each GPE -- either a method or handler, cannot be both */ struct acpi_gpe_handler_info { @@ -403,15 +416,21 @@ struct acpi_gpe_handler_info { u8 originally_enabled; /* True if GPE was originally enabled */ }; -struct acpi_gpe_notify_object { - struct acpi_namespace_node *node; - struct acpi_gpe_notify_object *next; +/* Notify info for implicit notify, multiple device objects */ + +struct acpi_gpe_notify_info { + struct acpi_namespace_node *device_node; /* Device to be notified */ + struct acpi_gpe_notify_info *next; }; +/* + * GPE dispatch info. At any time, the GPE can have at most one type + * of dispatch - Method, Handler, or Implicit Notify. + */ union acpi_gpe_dispatch_info { struct acpi_namespace_node *method_node; /* Method node for this GPE level */ struct acpi_gpe_handler_info *handler; /* Installed GPE handler */ - struct acpi_gpe_notify_object device; /* List of _PRW devices for implicit notify */ + struct acpi_gpe_notify_info *notify_list; /* List of _PRW devices for implicit notifies */ }; /* @@ -419,7 +438,7 @@ union acpi_gpe_dispatch_info { * NOTE: Important to keep this struct as small as possible. */ struct acpi_gpe_event_info { - union acpi_gpe_dispatch_info dispatch; /* Either Method or Handler */ + union acpi_gpe_dispatch_info dispatch; /* Either Method, Handler, or notify_list */ struct acpi_gpe_register_info *register_info; /* Backpointer to register info */ u8 flags; /* Misc info about this GPE */ u8 gpe_number; /* This GPE */ @@ -431,9 +450,9 @@ struct acpi_gpe_event_info { struct acpi_gpe_register_info { struct acpi_generic_address status_address; /* Address of status reg */ struct acpi_generic_address enable_address; /* Address of enable reg */ + u16 base_gpe_number; /* Base GPE number for this register */ u8 enable_for_wake; /* GPEs to keep enabled when sleeping */ u8 enable_for_run; /* GPEs to keep enabled when running */ - u8 base_gpe_number; /* Base GPE number for this register */ }; /* @@ -447,11 +466,12 @@ struct acpi_gpe_block_info { struct acpi_gpe_xrupt_info *xrupt_block; /* Backpointer to interrupt block */ struct acpi_gpe_register_info *register_info; /* One per GPE register pair */ struct acpi_gpe_event_info *event_info; /* One for each GPE */ - struct acpi_generic_address block_address; /* Base address of the block */ + u64 address; /* Base address of the block */ u32 register_count; /* Number of register pairs in block */ u16 gpe_count; /* Number of individual GPEs in block */ - u8 block_base_number; /* Base GPE number for this block */ - u8 initialized; /* TRUE if this block is initialized */ + u16 block_base_number; /* Base GPE number for this block */ + u8 space_id; + u8 initialized; /* TRUE if this block is initialized */ }; /* Information about GPE interrupt handlers, one per each interrupt level used for GPEs */ @@ -478,8 +498,10 @@ struct acpi_gpe_device_info { struct acpi_namespace_node *gpe_device; }; -typedef acpi_status(*acpi_gpe_callback) (struct acpi_gpe_xrupt_info *gpe_xrupt_info, - struct acpi_gpe_block_info *gpe_block, void *context); +typedef acpi_status(*acpi_gpe_callback) (struct acpi_gpe_xrupt_info * + gpe_xrupt_info, + struct acpi_gpe_block_info *gpe_block, + void *context); /* Information about each particular fixed event */ @@ -574,7 +596,7 @@ struct acpi_pscope_state { }; /* - * Thread state - one per thread across multiple walk states. Multiple walk + * Thread state - one per thread across multiple walk states. Multiple walk * states are created when there are nested control methods executing. */ struct acpi_thread_state { @@ -599,13 +621,22 @@ acpi_status(*acpi_parse_downwards) (struct acpi_walk_state * walk_state, typedef acpi_status(*acpi_parse_upwards) (struct acpi_walk_state * walk_state); +/* Global handlers for AML Notifies */ + +struct acpi_global_notify_handler { + acpi_notify_handler handler; + void *context; +}; + /* * Notify info - used to pass info to the deferred notify * handler/dispatcher. */ struct acpi_notify_info { - ACPI_STATE_COMMON struct acpi_namespace_node *node; - union acpi_operand_object *handler_obj; + ACPI_STATE_COMMON u8 handler_list_id; + struct acpi_namespace_node *node; + union acpi_operand_object *handler_list_head; + struct acpi_global_notify_handler *global; }; /* Generic state is union of structs above */ @@ -628,7 +659,7 @@ union acpi_generic_state { * ****************************************************************************/ -typedef acpi_status(*ACPI_EXECUTE_OP) (struct acpi_walk_state * walk_state); +typedef acpi_status(*acpi_execute_op) (struct acpi_walk_state * walk_state); /* Address Range info block */ @@ -660,6 +691,8 @@ struct acpi_opcode_info { u8 type; /* Opcode type */ }; +/* Value associated with the parse object */ + union acpi_parse_value { u64 integer; /* Integer constant (Up to 64 bits) */ u32 size; /* bytelist or field size */ @@ -690,15 +723,19 @@ union acpi_parse_value { u8 disasm_opcode; /* Subtype used for disassembly */\ char aml_op_name[16]) /* Op name (debug only) */ -#define ACPI_DASM_BUFFER 0x00 -#define ACPI_DASM_RESOURCE 0x01 -#define ACPI_DASM_STRING 0x02 -#define ACPI_DASM_UNICODE 0x03 -#define ACPI_DASM_EISAID 0x04 -#define ACPI_DASM_MATCHOP 0x05 -#define ACPI_DASM_LNOT_PREFIX 0x06 -#define ACPI_DASM_LNOT_SUFFIX 0x07 -#define ACPI_DASM_IGNORE 0x08 +/* Flags for disasm_flags field above */ + +#define ACPI_DASM_BUFFER 0x00 /* Buffer is a simple data buffer */ +#define ACPI_DASM_RESOURCE 0x01 /* Buffer is a Resource Descriptor */ +#define ACPI_DASM_STRING 0x02 /* Buffer is a ASCII string */ +#define ACPI_DASM_UNICODE 0x03 /* Buffer is a Unicode string */ +#define ACPI_DASM_PLD_METHOD 0x04 /* Buffer is a _PLD method bit-packed buffer */ +#define ACPI_DASM_EISAID 0x05 /* Integer is an EISAID */ +#define ACPI_DASM_MATCHOP 0x06 /* Parent opcode is a Match() operator */ +#define ACPI_DASM_LNOT_PREFIX 0x07 /* Start of a Lnot_equal (etc.) pair of opcodes */ +#define ACPI_DASM_LNOT_SUFFIX 0x08 /* End of a Lnot_equal (etc.) pair of opcodes */ +#define ACPI_DASM_HID_STRING 0x09 /* String is a _HID or _CID */ +#define ACPI_DASM_IGNORE 0x0A /* Not used at this time */ /* * Generic operation (for example: If, While, Store) @@ -717,7 +754,7 @@ struct acpi_parse_obj_named { u32 name; /* 4-byte name or zero if no name */ }; -/* This version is used by the i_aSL compiler only */ +/* This version is used by the iASL compiler only */ #define ACPI_MAX_PARSEOP_NAME 20 @@ -786,6 +823,7 @@ struct acpi_parse_state { #define ACPI_PARSEOP_IGNORE 0x01 #define ACPI_PARSEOP_PARAMLIST 0x02 #define ACPI_PARSEOP_EMPTY_TERMLIST 0x04 +#define ACPI_PARSEOP_PREDEF_CHECKED 0x08 #define ACPI_PARSEOP_SPECIAL 0x10 /***************************************************************************** @@ -903,18 +941,6 @@ struct acpi_bit_register_info { /* Structs and definitions for _OSI support and I/O port validation */ -#define ACPI_OSI_WIN_2000 0x01 -#define ACPI_OSI_WIN_XP 0x02 -#define ACPI_OSI_WIN_XP_SP1 0x03 -#define ACPI_OSI_WINSRV_2003 0x04 -#define ACPI_OSI_WIN_XP_SP2 0x05 -#define ACPI_OSI_WINSRV_2003_SP1 0x06 -#define ACPI_OSI_WIN_VISTA 0x07 -#define ACPI_OSI_WINSRV_2008 0x08 -#define ACPI_OSI_WIN_VISTA_SP1 0x09 -#define ACPI_OSI_WIN_VISTA_SP2 0x0A -#define ACPI_OSI_WIN_7 0x0B - #define ACPI_ALWAYS_ILLEGAL 0x00 struct acpi_interface_info { @@ -926,6 +952,9 @@ struct acpi_interface_info { #define ACPI_OSI_INVALID 0x01 #define ACPI_OSI_DYNAMIC 0x02 +#define ACPI_OSI_FEATURE 0x04 +#define ACPI_OSI_DEFAULT_INVALID 0x08 +#define ACPI_OSI_OPTIONAL_FEATURE (ACPI_OSI_FEATURE | ACPI_OSI_DEFAULT_INVALID | ACPI_OSI_INVALID) struct acpi_port_info { char *name; @@ -1001,13 +1030,43 @@ struct acpi_port_info { /***************************************************************************** * + * Disassembler + * + ****************************************************************************/ + +struct acpi_external_list { + char *path; + char *internal_path; + struct acpi_external_list *next; + u32 value; + u16 length; + u16 flags; + u8 type; +}; + +/* Values for Flags field above */ + +#define ACPI_EXT_RESOLVED_REFERENCE 0x01 /* Object was resolved during cross ref */ +#define ACPI_EXT_ORIGIN_FROM_FILE 0x02 /* External came from a file */ +#define ACPI_EXT_INTERNAL_PATH_ALLOCATED 0x04 /* Deallocate internal path on completion */ +#define ACPI_EXT_EXTERNAL_EMITTED 0x08 /* External() statement has been emitted */ + +struct acpi_external_file { + char *path; + struct acpi_external_file *next; +}; + +/***************************************************************************** + * * Debugger * ****************************************************************************/ struct acpi_db_method_info { + acpi_handle method; acpi_handle main_thread_gate; acpi_handle thread_complete_gate; + acpi_handle info_gate; acpi_thread_id *threads; u32 num_threads; u32 num_created; @@ -1016,8 +1075,9 @@ struct acpi_db_method_info { char *name; u32 flags; u32 num_loops; - char pathname[128]; + char pathname[ACPI_DB_LINE_BUFFER_SIZE]; char **args; + acpi_object_type *types; /* * Arguments to be passed to method for the command @@ -1037,6 +1097,7 @@ struct acpi_integrity_info { u32 objects; }; +#define ACPI_DB_DISABLE_OUTPUT 0x00 #define ACPI_DB_REDIRECTABLE_OUTPUT 0x01 #define ACPI_DB_CONSOLE_OUTPUT 0x02 #define ACPI_DB_DUPLICATE_OUTPUT 0x03 @@ -1074,4 +1135,23 @@ struct acpi_debug_mem_block { #define ACPI_MEM_LIST_MAX 1 #define ACPI_NUM_MEM_LISTS 2 +/***************************************************************************** + * + * Info/help support + * + ****************************************************************************/ + +struct ah_predefined_name { + char *name; + char *description; +#ifndef ACPI_ASL_COMPILER + char *action; +#endif +}; + +struct ah_device_id { + char *name; + char *description; +}; + #endif /* __ACLOCAL_H__ */ diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h index ef338a96f5b..4bceb11c738 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,27 +49,35 @@ * get into potential aligment issues -- see the STORE macros below. * Use with care. */ -#define ACPI_GET8(ptr) *ACPI_CAST_PTR (u8, ptr) -#define ACPI_GET16(ptr) *ACPI_CAST_PTR (u16, ptr) -#define ACPI_GET32(ptr) *ACPI_CAST_PTR (u32, ptr) -#define ACPI_GET64(ptr) *ACPI_CAST_PTR (u64, ptr) -#define ACPI_SET8(ptr) *ACPI_CAST_PTR (u8, ptr) -#define ACPI_SET16(ptr) *ACPI_CAST_PTR (u16, ptr) -#define ACPI_SET32(ptr) *ACPI_CAST_PTR (u32, ptr) -#define ACPI_SET64(ptr) *ACPI_CAST_PTR (u64, ptr) +#define ACPI_CAST8(ptr) ACPI_CAST_PTR (u8, (ptr)) +#define ACPI_CAST16(ptr) ACPI_CAST_PTR (u16, (ptr)) +#define ACPI_CAST32(ptr) ACPI_CAST_PTR (u32, (ptr)) +#define ACPI_CAST64(ptr) ACPI_CAST_PTR (u64, (ptr)) +#define ACPI_GET8(ptr) (*ACPI_CAST8 (ptr)) +#define ACPI_GET16(ptr) (*ACPI_CAST16 (ptr)) +#define ACPI_GET32(ptr) (*ACPI_CAST32 (ptr)) +#define ACPI_GET64(ptr) (*ACPI_CAST64 (ptr)) +#define ACPI_SET8(ptr, val) (*ACPI_CAST8 (ptr) = (u8) (val)) +#define ACPI_SET16(ptr, val) (*ACPI_CAST16 (ptr) = (u16) (val)) +#define ACPI_SET32(ptr, val) (*ACPI_CAST32 (ptr) = (u32) (val)) +#define ACPI_SET64(ptr, val) (*ACPI_CAST64 (ptr) = (u64) (val)) /* - * printf() format helpers + * printf() format helpers. These macros are workarounds for the difficulties + * with emitting 64-bit integers and 64-bit pointers with the same code + * for both 32-bit and 64-bit hosts. */ - -/* Split 64-bit integer into two 32-bit values. Use with %8.8_x%8.8_x */ - #define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i), ACPI_LODWORD(i) #if ACPI_MACHINE_WIDTH == 64 #define ACPI_FORMAT_NATIVE_UINT(i) ACPI_FORMAT_UINT64(i) +#define ACPI_FORMAT_TO_UINT(i) ACPI_FORMAT_UINT64(i) +#define ACPI_PRINTF_UINT "0x%8.8X%8.8X" + #else -#define ACPI_FORMAT_NATIVE_UINT(i) 0, (i) +#define ACPI_FORMAT_NATIVE_UINT(i) 0, (u32) (i) +#define ACPI_FORMAT_TO_UINT(i) (u32) (i) +#define ACPI_PRINTF_UINT "0x%8.8X" #endif /* @@ -84,29 +92,29 @@ /* These macros reverse the bytes during the move, converting little-endian to big endian */ - /* Big Endian <== Little Endian */ - /* Hi...Lo Lo...Hi */ + /* Big Endian <== Little Endian */ + /* Hi...Lo Lo...Hi */ /* 16-bit source, 16/32/64 destination */ #define ACPI_MOVE_16_TO_16(d, s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[1];\ - (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[0];} + (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[0];} #define ACPI_MOVE_16_TO_32(d, s) {(*(u32 *)(void *)(d))=0;\ - ((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\ - ((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];} + ((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\ + ((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];} #define ACPI_MOVE_16_TO_64(d, s) {(*(u64 *)(void *)(d))=0;\ - ((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\ - ((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];} + ((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\ + ((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];} /* 32-bit source, 16/32/64 destination */ #define ACPI_MOVE_32_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */ #define ACPI_MOVE_32_TO_32(d, s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[3];\ - (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\ - (( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\ - (( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];} + (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\ + (( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\ + (( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];} #define ACPI_MOVE_32_TO_64(d, s) {(*(u64 *)(void *)(d))=0;\ ((u8 *)(void *)(d))[4] = ((u8 *)(void *)(s))[3];\ @@ -196,24 +204,12 @@ #endif #endif -/* Macros based on machine integer width */ - -#if ACPI_MACHINE_WIDTH == 32 -#define ACPI_MOVE_SIZE_TO_16(d, s) ACPI_MOVE_32_TO_16(d, s) - -#elif ACPI_MACHINE_WIDTH == 64 -#define ACPI_MOVE_SIZE_TO_16(d, s) ACPI_MOVE_64_TO_16(d, s) - -#else -#error unknown ACPI_MACHINE_WIDTH -#endif - /* * Fast power-of-two math macros for non-optimized compilers */ -#define _ACPI_DIV(value, power_of2) ((u32) ((value) >> (power_of2))) -#define _ACPI_MUL(value, power_of2) ((u32) ((value) << (power_of2))) -#define _ACPI_MOD(value, divisor) ((u32) ((value) & ((divisor) -1))) +#define _ACPI_DIV(value, power_of2) ((u32) ((value) >> (power_of2))) +#define _ACPI_MUL(value, power_of2) ((u32) ((value) << (power_of2))) +#define _ACPI_MOD(value, divisor) ((u32) ((value) & ((divisor) -1))) #define ACPI_DIV_2(a) _ACPI_DIV(a, 1) #define ACPI_MUL_2(a) _ACPI_MUL(a, 1) @@ -238,12 +234,12 @@ /* * Rounding macros (Power of two boundaries only) */ -#define ACPI_ROUND_DOWN(value, boundary) (((acpi_size)(value)) & \ - (~(((acpi_size) boundary)-1))) +#define ACPI_ROUND_DOWN(value, boundary) (((acpi_size)(value)) & \ + (~(((acpi_size) boundary)-1))) -#define ACPI_ROUND_UP(value, boundary) ((((acpi_size)(value)) + \ - (((acpi_size) boundary)-1)) & \ - (~(((acpi_size) boundary)-1))) +#define ACPI_ROUND_UP(value, boundary) ((((acpi_size)(value)) + \ + (((acpi_size) boundary)-1)) & \ + (~(((acpi_size) boundary)-1))) /* Note: sizeof(acpi_size) evaluates to either 4 or 8 (32- vs 64-bit mode) */ @@ -264,7 +260,7 @@ #define ACPI_ROUND_UP_TO(value, boundary) (((value) + ((boundary)-1)) / (boundary)) -#define ACPI_IS_MISALIGNED(value) (((acpi_size) value) & (sizeof(acpi_size)-1)) +#define ACPI_IS_MISALIGNED(value) (((acpi_size) value) & (sizeof(acpi_size)-1)) /* * Bitmask creation @@ -277,20 +273,65 @@ /* Bitfields within ACPI registers */ -#define ACPI_REGISTER_PREPARE_BITS(val, pos, mask) ((val << pos) & mask) -#define ACPI_REGISTER_INSERT_VALUE(reg, pos, mask, val) reg = (reg & (~(mask))) | ACPI_REGISTER_PREPARE_BITS(val, pos, mask) +#define ACPI_REGISTER_PREPARE_BITS(val, pos, mask) \ + ((val << pos) & mask) + +#define ACPI_REGISTER_INSERT_VALUE(reg, pos, mask, val) \ + reg = (reg & (~(mask))) | ACPI_REGISTER_PREPARE_BITS(val, pos, mask) + +#define ACPI_INSERT_BITS(target, mask, source) \ + target = ((target & (~(mask))) | (source & mask)) + +/* Generic bitfield macros and masks */ + +#define ACPI_GET_BITS(source_ptr, position, mask) \ + ((*source_ptr >> position) & mask) + +#define ACPI_SET_BITS(target_ptr, position, mask, value) \ + (*target_ptr |= ((value & mask) << position)) -#define ACPI_INSERT_BITS(target, mask, source) target = ((target & (~(mask))) | (source & mask)) +#define ACPI_1BIT_MASK 0x00000001 +#define ACPI_2BIT_MASK 0x00000003 +#define ACPI_3BIT_MASK 0x00000007 +#define ACPI_4BIT_MASK 0x0000000F +#define ACPI_5BIT_MASK 0x0000001F +#define ACPI_6BIT_MASK 0x0000003F +#define ACPI_7BIT_MASK 0x0000007F +#define ACPI_8BIT_MASK 0x000000FF +#define ACPI_16BIT_MASK 0x0000FFFF +#define ACPI_24BIT_MASK 0x00FFFFFF + +/* Macros to extract flag bits from position zero */ + +#define ACPI_GET_1BIT_FLAG(value) ((value) & ACPI_1BIT_MASK) +#define ACPI_GET_2BIT_FLAG(value) ((value) & ACPI_2BIT_MASK) +#define ACPI_GET_3BIT_FLAG(value) ((value) & ACPI_3BIT_MASK) +#define ACPI_GET_4BIT_FLAG(value) ((value) & ACPI_4BIT_MASK) + +/* Macros to extract flag bits from position one and above */ + +#define ACPI_EXTRACT_1BIT_FLAG(field, position) (ACPI_GET_1BIT_FLAG ((field) >> position)) +#define ACPI_EXTRACT_2BIT_FLAG(field, position) (ACPI_GET_2BIT_FLAG ((field) >> position)) +#define ACPI_EXTRACT_3BIT_FLAG(field, position) (ACPI_GET_3BIT_FLAG ((field) >> position)) +#define ACPI_EXTRACT_4BIT_FLAG(field, position) (ACPI_GET_4BIT_FLAG ((field) >> position)) + +/* ACPI Pathname helpers */ + +#define ACPI_IS_ROOT_PREFIX(c) ((c) == (u8) 0x5C) /* Backslash */ +#define ACPI_IS_PARENT_PREFIX(c) ((c) == (u8) 0x5E) /* Carat */ +#define ACPI_IS_PATH_SEPARATOR(c) ((c) == (u8) 0x2E) /* Period (dot) */ /* - * A struct acpi_namespace_node can appear in some contexts - * where a pointer to a union acpi_operand_object can also + * An object of type struct acpi_namespace_node can appear in some contexts + * where a pointer to an object of type union acpi_operand_object can also * appear. This macro is used to distinguish them. * - * The "Descriptor" field is the first field in both structures. + * The "DescriptorType" field is the second field in both structures. */ +#define ACPI_GET_DESCRIPTOR_PTR(d) (((union acpi_descriptor *)(void *)(d))->common.common_pointer) +#define ACPI_SET_DESCRIPTOR_PTR(d, p) (((union acpi_descriptor *)(void *)(d))->common.common_pointer = (p)) #define ACPI_GET_DESCRIPTOR_TYPE(d) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type) -#define ACPI_SET_DESCRIPTOR_TYPE(d, t) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type = t) +#define ACPI_SET_DESCRIPTOR_TYPE(d, t) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type = (t)) /* * Macros for the master AML opcode table @@ -332,16 +373,16 @@ * Ascii error messages can be configured out */ #ifndef ACPI_NO_ERROR_MESSAGES - /* * Error reporting. Callers module and line number are inserted by AE_INFO, * the plist contains a set of parens to allow variable-length lists. * These macros are used for both the debug and non-debug versions of the code. */ -#define ACPI_ERROR_NAMESPACE(s, e) acpi_ut_namespace_error (AE_INFO, s, e); -#define ACPI_ERROR_METHOD(s, n, p, e) acpi_ut_method_error (AE_INFO, s, n, p, e); -#define ACPI_WARN_PREDEFINED(plist) acpi_ut_predefined_warning plist -#define ACPI_INFO_PREDEFINED(plist) acpi_ut_predefined_info plist +#define ACPI_ERROR_NAMESPACE(s, e) acpi_ut_namespace_error (AE_INFO, s, e); +#define ACPI_ERROR_METHOD(s, n, p, e) acpi_ut_method_error (AE_INFO, s, n, p, e); +#define ACPI_WARN_PREDEFINED(plist) acpi_ut_predefined_warning plist +#define ACPI_INFO_PREDEFINED(plist) acpi_ut_predefined_info plist +#define ACPI_BIOS_ERROR_PREDEFINED(plist) acpi_ut_predefined_bios_error plist #else @@ -351,171 +392,16 @@ #define ACPI_ERROR_METHOD(s, n, p, e) #define ACPI_WARN_PREDEFINED(plist) #define ACPI_INFO_PREDEFINED(plist) +#define ACPI_BIOS_ERROR_PREDEFINED(plist) -#endif /* ACPI_NO_ERROR_MESSAGES */ - -/* - * Debug macros that are conditionally compiled - */ -#ifdef ACPI_DEBUG_OUTPUT - -/* - * Function entry tracing - */ -#ifdef CONFIG_ACPI_DEBUG_FUNC_TRACE - -#define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace(ACPI_DEBUG_PARAMETERS) -#define ACPI_FUNCTION_TRACE_PTR(a, b) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace_ptr(ACPI_DEBUG_PARAMETERS, (void *)b) -#define ACPI_FUNCTION_TRACE_U32(a, b) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace_u32(ACPI_DEBUG_PARAMETERS, (u32)b) -#define ACPI_FUNCTION_TRACE_STR(a, b) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace_str(ACPI_DEBUG_PARAMETERS, (char *)b) +#endif /* ACPI_NO_ERROR_MESSAGES */ -#define ACPI_FUNCTION_ENTRY() acpi_ut_track_stack_ptr() - -/* - * Function exit tracing. - * WARNING: These macros include a return statement. This is usually considered - * bad form, but having a separate exit macro is very ugly and difficult to maintain. - * One of the FUNCTION_TRACE macros above must be used in conjunction with these macros - * so that "_AcpiFunctionName" is defined. - * - * Note: the DO_WHILE0 macro is used to prevent some compilers from complaining - * about these constructs. - */ -#ifdef ACPI_USE_DO_WHILE_0 -#define ACPI_DO_WHILE0(a) do a while(0) +#if (!ACPI_REDUCED_HARDWARE) +#define ACPI_HW_OPTIONAL_FUNCTION(addr) addr #else -#define ACPI_DO_WHILE0(a) a +#define ACPI_HW_OPTIONAL_FUNCTION(addr) NULL #endif -#define return_VOID ACPI_DO_WHILE0 ({ \ - acpi_ut_exit (ACPI_DEBUG_PARAMETERS); \ - return;}) -/* - * There are two versions of most of the return macros. The default version is - * safer, since it avoids side-effects by guaranteeing that the argument will - * not be evaluated twice. - * - * A less-safe version of the macros is provided for optional use if the - * compiler uses excessive CPU stack (for example, this may happen in the - * debug case if code optimzation is disabled.) - */ -#ifndef ACPI_SIMPLE_RETURN_MACROS - -#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({ \ - register acpi_status _s = (s); \ - acpi_ut_status_exit (ACPI_DEBUG_PARAMETERS, _s); \ - return (_s); }) -#define return_PTR(s) ACPI_DO_WHILE0 ({ \ - register void *_s = (void *) (s); \ - acpi_ut_ptr_exit (ACPI_DEBUG_PARAMETERS, (u8 *) _s); \ - return (_s); }) -#define return_VALUE(s) ACPI_DO_WHILE0 ({ \ - register u64 _s = (s); \ - acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, _s); \ - return (_s); }) -#define return_UINT8(s) ACPI_DO_WHILE0 ({ \ - register u8 _s = (u8) (s); \ - acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, (u64) _s); \ - return (_s); }) -#define return_UINT32(s) ACPI_DO_WHILE0 ({ \ - register u32 _s = (u32) (s); \ - acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, (u64) _s); \ - return (_s); }) -#else /* Use original less-safe macros */ - -#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({ \ - acpi_ut_status_exit (ACPI_DEBUG_PARAMETERS, (s)); \ - return((s)); }) -#define return_PTR(s) ACPI_DO_WHILE0 ({ \ - acpi_ut_ptr_exit (ACPI_DEBUG_PARAMETERS, (u8 *) (s)); \ - return((s)); }) -#define return_VALUE(s) ACPI_DO_WHILE0 ({ \ - acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, (u64) (s)); \ - return((s)); }) -#define return_UINT8(s) return_VALUE(s) -#define return_UINT32(s) return_VALUE(s) - -#endif /* ACPI_SIMPLE_RETURN_MACROS */ - -#else /* !CONFIG_ACPI_DEBUG_FUNC_TRACE */ - -#define ACPI_FUNCTION_TRACE(a) -#define ACPI_FUNCTION_TRACE_PTR(a,b) -#define ACPI_FUNCTION_TRACE_U32(a,b) -#define ACPI_FUNCTION_TRACE_STR(a,b) -#define ACPI_FUNCTION_EXIT -#define ACPI_FUNCTION_STATUS_EXIT(s) -#define ACPI_FUNCTION_VALUE_EXIT(s) -#define ACPI_FUNCTION_TRACE(a) -#define ACPI_FUNCTION_ENTRY() - -#define return_VOID return -#define return_ACPI_STATUS(s) return(s) -#define return_VALUE(s) return(s) -#define return_UINT8(s) return(s) -#define return_UINT32(s) return(s) -#define return_PTR(s) return(s) - -#endif /* CONFIG_ACPI_DEBUG_FUNC_TRACE */ - -/* Conditional execution */ - -#define ACPI_DEBUG_EXEC(a) a -#define ACPI_NORMAL_EXEC(a) - -#define ACPI_DEBUG_DEFINE(a) a; -#define ACPI_DEBUG_ONLY_MEMBERS(a) a; -#define _VERBOSE_STRUCTURES - -/* Stack and buffer dumping */ - -#define ACPI_DUMP_STACK_ENTRY(a) acpi_ex_dump_operand((a), 0) -#define ACPI_DUMP_OPERANDS(a, b, c) acpi_ex_dump_operands(a, b, c) - -#define ACPI_DUMP_ENTRY(a, b) acpi_ns_dump_entry (a, b) -#define ACPI_DUMP_PATHNAME(a, b, c, d) acpi_ns_dump_pathname(a, b, c, d) -#define ACPI_DUMP_RESOURCE_LIST(a) acpi_rs_dump_resource_list(a) -#define ACPI_DUMP_BUFFER(a, b) acpi_ut_dump_buffer((u8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT) - -#else -/* - * This is the non-debug case -- make everything go away, - * leaving no executable debug code! - */ -#define ACPI_DEBUG_EXEC(a) -#define ACPI_NORMAL_EXEC(a) a; - -#define ACPI_DEBUG_DEFINE(a) do { } while(0) -#define ACPI_DEBUG_ONLY_MEMBERS(a) do { } while(0) -#define ACPI_FUNCTION_TRACE(a) do { } while(0) -#define ACPI_FUNCTION_TRACE_PTR(a, b) do { } while(0) -#define ACPI_FUNCTION_TRACE_U32(a, b) do { } while(0) -#define ACPI_FUNCTION_TRACE_STR(a, b) do { } while(0) -#define ACPI_FUNCTION_EXIT do { } while(0) -#define ACPI_FUNCTION_STATUS_EXIT(s) do { } while(0) -#define ACPI_FUNCTION_VALUE_EXIT(s) do { } while(0) -#define ACPI_FUNCTION_ENTRY() do { } while(0) -#define ACPI_DUMP_STACK_ENTRY(a) do { } while(0) -#define ACPI_DUMP_OPERANDS(a, b, c) do { } while(0) -#define ACPI_DUMP_ENTRY(a, b) do { } while(0) -#define ACPI_DUMP_TABLES(a, b) do { } while(0) -#define ACPI_DUMP_PATHNAME(a, b, c, d) do { } while(0) -#define ACPI_DUMP_RESOURCE_LIST(a) do { } while(0) -#define ACPI_DUMP_BUFFER(a, b) do { } while(0) - -#define return_VOID return -#define return_ACPI_STATUS(s) return(s) -#define return_VALUE(s) return(s) -#define return_UINT8(s) return(s) -#define return_UINT32(s) return(s) -#define return_PTR(s) return(s) - -#endif /* ACPI_DEBUG_OUTPUT */ - /* * Some code only gets executed when the debugger is built in. * Note that this is entirely independent of whether the @@ -527,52 +413,18 @@ #define ACPI_DEBUGGER_EXEC(a) #endif -#ifdef ACPI_DEBUG_OUTPUT -/* - * 1) Set name to blanks - * 2) Copy the object name - */ -#define ACPI_ADD_OBJECT_NAME(a,b) ACPI_MEMSET (a->common.name, ' ', sizeof (a->common.name));\ - ACPI_STRNCPY (a->common.name, acpi_gbl_ns_type_names[b], sizeof (a->common.name)) -#else - -#define ACPI_ADD_OBJECT_NAME(a,b) -#endif - /* - * Memory allocation tracking (DEBUG ONLY) + * Macros used for ACPICA utilities only */ -#define ACPI_MEM_PARAMETERS _COMPONENT, _acpi_module_name, __LINE__ - -#ifndef ACPI_DBG_TRACK_ALLOCATIONS - -/* Memory allocation */ - -#ifndef ACPI_ALLOCATE -#define ACPI_ALLOCATE(a) acpi_ut_allocate((acpi_size)(a), ACPI_MEM_PARAMETERS) -#endif -#ifndef ACPI_ALLOCATE_ZEROED -#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed((acpi_size)(a), ACPI_MEM_PARAMETERS) -#endif -#ifndef ACPI_FREE -#define ACPI_FREE(a) acpio_os_free(a) -#endif -#define ACPI_MEM_TRACKING(a) -#else +/* Generate a UUID */ -/* Memory allocation */ +#define ACPI_INIT_UUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ + (a) & 0xFF, ((a) >> 8) & 0xFF, ((a) >> 16) & 0xFF, ((a) >> 24) & 0xFF, \ + (b) & 0xFF, ((b) >> 8) & 0xFF, \ + (c) & 0xFF, ((c) >> 8) & 0xFF, \ + (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) -#define ACPI_ALLOCATE(a) acpi_ut_allocate_and_track((acpi_size)(a), ACPI_MEM_PARAMETERS) -#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed_and_track((acpi_size)(a), ACPI_MEM_PARAMETERS) -#define ACPI_FREE(a) acpi_ut_free_and_track(a, ACPI_MEM_PARAMETERS) -#define ACPI_MEM_TRACKING(a) a - -#endif /* ACPI_DBG_TRACK_ALLOCATIONS */ - -/* Preemption point */ -#ifndef ACPI_PREEMPTION_POINT -#define ACPI_PREEMPTION_POINT() /* no preemption */ -#endif +#define ACPI_IS_OCTAL_DIGIT(d) (((char)(d) >= '0') && ((char)(d) <= '7')) #endif /* ACMACROS_H */ diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index 2c9e0f04952..ee1c040f321 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -104,8 +104,8 @@ acpi_ns_walk_namespace(acpi_object_type type, acpi_handle start_object, u32 max_depth, u32 flags, - acpi_walk_callback pre_order_visit, - acpi_walk_callback post_order_visit, + acpi_walk_callback descending_callback, + acpi_walk_callback ascending_callback, void *context, void **return_value); struct acpi_namespace_node *acpi_ns_get_next_node(struct acpi_namespace_node @@ -167,6 +167,29 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent); int acpi_ns_compare_names(char *name1, char *name2); /* + * nsconvert - Dynamic object conversion routines + */ +acpi_status +acpi_ns_convert_to_integer(union acpi_operand_object *original_object, + union acpi_operand_object **return_object); + +acpi_status +acpi_ns_convert_to_string(union acpi_operand_object *original_object, + union acpi_operand_object **return_object); + +acpi_status +acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, + union acpi_operand_object **return_object); + +acpi_status +acpi_ns_convert_to_unicode(union acpi_operand_object *original_object, + union acpi_operand_object **return_object); + +acpi_status +acpi_ns_convert_to_resource(union acpi_operand_object *original_object, + union acpi_operand_object **return_object); + +/* * nsdump - Namespace dump/print utilities */ #ifdef ACPI_FUTURE_USAGE @@ -190,6 +213,12 @@ acpi_ns_dump_objects(acpi_object_type type, u8 display_type, u32 max_depth, acpi_owner_id owner_id, acpi_handle start_handle); + +void +acpi_ns_dump_object_paths(acpi_object_type type, + u8 display_type, + u32 max_depth, + acpi_owner_id owner_id, acpi_handle start_handle); #endif /* ACPI_FUTURE_USAGE */ /* @@ -200,23 +229,42 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info); void acpi_ns_exec_module_code_list(void); /* - * nspredef - Support for predefined/reserved names + * nsarguments - Argument count/type checking for predefined/reserved names */ -acpi_status -acpi_ns_check_predefined_names(struct acpi_namespace_node *node, - u32 user_param_count, - acpi_status return_status, - union acpi_operand_object **return_object); - -const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct - acpi_namespace_node - *node); +void +acpi_ns_check_argument_count(char *pathname, + struct acpi_namespace_node *node, + u32 user_param_count, + const union acpi_predefined_info *info); void -acpi_ns_check_parameter_count(char *pathname, +acpi_ns_check_acpi_compliance(char *pathname, struct acpi_namespace_node *node, - u32 user_param_count, - const union acpi_predefined_info *info); + const union acpi_predefined_info *predefined); + +void acpi_ns_check_argument_types(struct acpi_evaluate_info *info); + +/* + * nspredef - Return value checking for predefined/reserved names + */ +acpi_status +acpi_ns_check_return_value(struct acpi_namespace_node *node, + struct acpi_evaluate_info *info, + u32 user_param_count, + acpi_status return_status, + union acpi_operand_object **return_object); + +acpi_status +acpi_ns_check_object_type(struct acpi_evaluate_info *info, + union acpi_operand_object **return_object_ptr, + u32 expected_btypes, u32 package_index); + +/* + * nsprepkg - Validation of predefined name packages + */ +acpi_status +acpi_ns_check_package(struct acpi_evaluate_info *info, + union acpi_operand_object **return_object_ptr); /* * nsnames - Name and Scope manipulation @@ -277,23 +325,24 @@ acpi_ns_get_attached_data(struct acpi_namespace_node *node, * predefined methods/objects */ acpi_status -acpi_ns_repair_object(struct acpi_predefined_data *data, +acpi_ns_simple_repair(struct acpi_evaluate_info *info, u32 expected_btypes, u32 package_index, union acpi_operand_object **return_object_ptr); acpi_status -acpi_ns_repair_package_list(struct acpi_predefined_data *data, - union acpi_operand_object **obj_desc_ptr); +acpi_ns_wrap_with_package(struct acpi_evaluate_info *info, + union acpi_operand_object *original_object, + union acpi_operand_object **obj_desc_ptr); acpi_status -acpi_ns_repair_null_element(struct acpi_predefined_data *data, +acpi_ns_repair_null_element(struct acpi_evaluate_info *info, u32 expected_btypes, u32 package_index, union acpi_operand_object **return_object_ptr); void -acpi_ns_remove_null_elements(struct acpi_predefined_data *data, +acpi_ns_remove_null_elements(struct acpi_evaluate_info *info, u8 package_type, union acpi_operand_object *obj_desc); @@ -302,7 +351,7 @@ acpi_ns_remove_null_elements(struct acpi_predefined_data *data, * predefined methods/objects */ acpi_status -acpi_ns_complex_repairs(struct acpi_predefined_data *data, +acpi_ns_complex_repairs(struct acpi_evaluate_info *info, struct acpi_namespace_node *node, acpi_status validate_status, union acpi_operand_object **return_object_ptr); @@ -332,8 +381,6 @@ acpi_ns_install_node(struct acpi_walk_state *walk_state, /* * nsutils - Utility functions */ -u8 acpi_ns_valid_root_prefix(char prefix); - acpi_object_type acpi_ns_get_type(struct acpi_namespace_node *node); u32 acpi_ns_local(acpi_object_type type); diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index c065078ca83..22fb6449d3d 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -1,4 +1,3 @@ - /****************************************************************************** * * Name: acobject.h - Definition of union acpi_operand_object (Internal object only) @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -113,8 +112,8 @@ struct acpi_object_integer { }; /* - * Note: The String and Buffer object must be identical through the Pointer - * and length elements. There is code that depends on this. + * Note: The String and Buffer object must be identical through the + * pointer and length elements. There is code that depends on this. * * Fields common to both Strings and Buffers */ @@ -179,7 +178,7 @@ struct acpi_object_method { union acpi_operand_object *mutex; u8 *aml_start; union { - ACPI_INTERNAL_METHOD implementation; + acpi_internal_method implementation; union acpi_operand_object *handler; } dispatch; @@ -194,11 +193,12 @@ struct acpi_object_method { #define ACPI_METHOD_INTERNAL_ONLY 0x02 /* Method is implemented internally (_OSI) */ #define ACPI_METHOD_SERIALIZED 0x04 /* Method is serialized */ #define ACPI_METHOD_SERIALIZED_PENDING 0x08 /* Method is to be marked serialized */ -#define ACPI_METHOD_MODIFIED_NAMESPACE 0x10 /* Method modified the namespace */ +#define ACPI_METHOD_IGNORE_SYNC_LEVEL 0x10 /* Method was auto-serialized at table load time */ +#define ACPI_METHOD_MODIFIED_NAMESPACE 0x20 /* Method modified the namespace */ /****************************************************************************** * - * Objects that can be notified. All share a common notify_info area. + * Objects that can be notified. All share a common notify_info area. * *****************************************************************************/ @@ -206,8 +206,7 @@ struct acpi_object_method { * Common fields for objects that support ASL notifications */ #define ACPI_COMMON_NOTIFY_INFO \ - union acpi_operand_object *system_notify; /* Handler for system notifies */\ - union acpi_operand_object *device_notify; /* Handler for driver notifies */\ + union acpi_operand_object *notify_list[2]; /* Handlers for system/device notifies */\ union acpi_operand_object *handler; /* Handler for Address space */ struct acpi_object_notify_common { /* COMMON NOTIFY for POWER, PROCESSOR, DEVICE, and THERMAL */ @@ -236,7 +235,7 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO}; /****************************************************************************** * - * Fields. All share a common header/info field. + * Fields. All share a common header/info field. * *****************************************************************************/ @@ -296,10 +295,10 @@ struct acpi_object_buffer_field { struct acpi_object_notify_handler { ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *node; /* Parent device */ - u32 handler_type; - acpi_notify_handler handler; + u32 handler_type; /* Type: Device/System/Both */ + acpi_notify_handler handler; /* Handler address */ void *context; - struct acpi_object_notify_handler *next; + union acpi_operand_object *next[2]; /* Device and System handler lists */ }; struct acpi_object_addr_handler { @@ -309,7 +308,7 @@ struct acpi_object_addr_handler { struct acpi_namespace_node *node; /* Parent device */ void *context; acpi_adr_space_setup setup; - union acpi_operand_object *region_list; /* regions using this handler */ + union acpi_operand_object *region_list; /* Regions using this handler */ union acpi_operand_object *next; }; @@ -382,7 +381,7 @@ struct acpi_object_cache_list { /****************************************************************************** * - * union acpi_operand_object Descriptor - a giant union of all of the above + * union acpi_operand_object descriptor - a giant union of all of the above * *****************************************************************************/ diff --git a/drivers/acpi/acpica/acopcode.h b/drivers/acpi/acpica/acopcode.h index 9440d053fbb..dda0e6affcf 100644 --- a/drivers/acpi/acpica/acopcode.h +++ b/drivers/acpi/acpica/acopcode.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,7 +54,7 @@ #define _UNK 0x6B /* - * Reserved ASCII characters. Do not use any of these for + * Reserved ASCII characters. Do not use any of these for * internal opcodes, since they are used to differentiate * name strings from AML opcodes */ @@ -63,7 +63,7 @@ #define _PFX 0x6D /* - * All AML opcodes and the parse-time arguments for each. Used by the AML + * All AML opcodes and the parse-time arguments for each. Used by the AML * parser Each list is compressed into a 32-bit number and stored in the * master opcode table (in psopcode.c). */ @@ -193,7 +193,7 @@ #define ARGP_ZERO_OP ARG_NONE /* - * All AML opcodes and the runtime arguments for each. Used by the AML + * All AML opcodes and the runtime arguments for each. Used by the AML * interpreter Each list is compressed into a 32-bit number and stored * in the master opcode table (in psopcode.c). * diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h index b725d780d34..6168b85463e 100644 --- a/drivers/acpi/acpica/acparser.h +++ b/drivers/acpi/acpica/acparser.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -105,7 +105,28 @@ union acpi_parse_object *acpi_ps_find_name(union acpi_parse_object *scope, union acpi_parse_object *acpi_ps_get_parent(union acpi_parse_object *op); /* - * psopcode - AML Opcode information + * psobject - support for parse object processing + */ +acpi_status +acpi_ps_build_named_op(struct acpi_walk_state *walk_state, + u8 *aml_op_start, + union acpi_parse_object *unnamed_op, + union acpi_parse_object **op); + +acpi_status +acpi_ps_create_op(struct acpi_walk_state *walk_state, + u8 *aml_op_start, union acpi_parse_object **new_op); + +acpi_status +acpi_ps_complete_op(struct acpi_walk_state *walk_state, + union acpi_parse_object **op, acpi_status status); + +acpi_status +acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, + union acpi_parse_object *op, acpi_status status); + +/* + * psopinfo - AML Opcode information */ const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode); @@ -150,8 +171,7 @@ u8 acpi_ps_has_completed_scope(struct acpi_parse_state *parser_state); void acpi_ps_pop_scope(struct acpi_parse_state *parser_state, - union acpi_parse_object **op, - u32 * arg_list, u32 * arg_count); + union acpi_parse_object **op, u32 *arg_list, u32 *arg_count); acpi_status acpi_ps_push_scope(struct acpi_parse_state *parser_state, @@ -212,8 +232,6 @@ void acpi_ps_free_op(union acpi_parse_object *op); u8 acpi_ps_is_leading_char(u32 c); -u8 acpi_ps_is_prefix_char(u32 c); - #ifdef ACPI_FUTURE_USAGE u32 acpi_ps_get_name(union acpi_parse_object *op); #endif /* ACPI_FUTURE_USAGE */ diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h index bbb34c9be4e..bd08817cafd 100644 --- a/drivers/acpi/acpica/acpredef.h +++ b/drivers/acpi/acpica/acpredef.h @@ -1,12 +1,11 @@ /****************************************************************************** * * Name: acpredef - Information table for ACPI predefined methods and objects - * $Revision: 1.1 $ * *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,32 +48,34 @@ * * Return Package types * - * 1) PTYPE1 packages do not contain sub-packages. + * 1) PTYPE1 packages do not contain subpackages. * - * ACPI_PTYPE1_FIXED: Fixed length, 1 or 2 object types: + * ACPI_PTYPE1_FIXED: Fixed-length length, 1 or 2 object types: * object type * count * object type * count * - * ACPI_PTYPE1_VAR: Variable length: + * ACPI_PTYPE1_VAR: Variable-length length. Zero-length package is allowed: * object type (Int/Buf/Ref) * * ACPI_PTYPE1_OPTION: Package has some required and some optional elements * (Used for _PRW) * * - * 2) PTYPE2 packages contain a Variable-length number of sub-packages. Each - * of the different types describe the contents of each of the sub-packages. + * 2) PTYPE2 packages contain a Variable-length number of subpackages. Each + * of the different types describe the contents of each of the subpackages. * - * ACPI_PTYPE2: Each subpackage contains 1 or 2 object types: + * ACPI_PTYPE2: Each subpackage contains 1 or 2 object types. Zero-length + * parent package is allowed: * object type * count * object type * count * (Used for _ALR,_MLS,_PSS,_TRT,_TSS) * - * ACPI_PTYPE2_COUNT: Each subpackage has a count as first element: + * ACPI_PTYPE2_COUNT: Each subpackage has a count as first element. + * Zero-length parent package is allowed: * object type * (Used for _CSD,_PSD,_TSD) * @@ -85,17 +86,19 @@ * count * (Used for _CST) * - * ACPI_PTYPE2_FIXED: Each subpackage is of fixed length + * ACPI_PTYPE2_FIXED: Each subpackage is of Fixed-length. Zero-length + * parent package is allowed. * (Used for _PRT) * - * ACPI_PTYPE2_MIN: Each subpackage has a variable but minimum length + * ACPI_PTYPE2_MIN: Each subpackage has a Variable-length but minimum length. + * Zero-length parent package is allowed: * (Used for _HPX) * * ACPI_PTYPE2_REV_FIXED: Revision at start, each subpackage is Fixed-length * (Used for _ART, _FPS) * * ACPI_PTYPE2_FIX_VAR: Each subpackage consists of some fixed-length elements - * followed by an optional element + * followed by an optional element. Zero-length parent package is allowed. * object type * count * object type @@ -117,31 +120,72 @@ enum acpi_return_package_types { ACPI_PTYPE2_FIX_VAR = 10 }; +/* Support macros for users of the predefined info table */ + +#define METHOD_PREDEF_ARGS_MAX 4 +#define METHOD_ARG_BIT_WIDTH 3 +#define METHOD_ARG_MASK 0x0007 +#define ARG_COUNT_IS_MINIMUM 0x8000 +#define METHOD_MAX_ARG_TYPE ACPI_TYPE_PACKAGE + +#define METHOD_GET_ARG_COUNT(arg_list) ((arg_list) & METHOD_ARG_MASK) +#define METHOD_GET_NEXT_TYPE(arg_list) (((arg_list) >>= METHOD_ARG_BIT_WIDTH) & METHOD_ARG_MASK) + +/* Macros used to build the predefined info table */ + +#define METHOD_0ARGS 0 +#define METHOD_1ARGS(a1) (1 | (a1 << 3)) +#define METHOD_2ARGS(a1,a2) (2 | (a1 << 3) | (a2 << 6)) +#define METHOD_3ARGS(a1,a2,a3) (3 | (a1 << 3) | (a2 << 6) | (a3 << 9)) +#define METHOD_4ARGS(a1,a2,a3,a4) (4 | (a1 << 3) | (a2 << 6) | (a3 << 9) | (a4 << 12)) + +#define METHOD_RETURNS(type) (type) +#define METHOD_NO_RETURN_VALUE 0 + +#define PACKAGE_INFO(a,b,c,d,e,f) {{{(a),(b),(c),(d)}, ((((u16)(f)) << 8) | (e)), 0}} + +/* Support macros for the resource descriptor info table */ + +#define WIDTH_1 0x0001 +#define WIDTH_2 0x0002 +#define WIDTH_3 0x0004 +#define WIDTH_8 0x0008 +#define WIDTH_16 0x0010 +#define WIDTH_32 0x0020 +#define WIDTH_64 0x0040 +#define VARIABLE_DATA 0x0080 +#define NUM_RESOURCE_WIDTHS 8 + +#define WIDTH_ADDRESS WIDTH_16 | WIDTH_32 | WIDTH_64 + #ifdef ACPI_CREATE_PREDEFINED_TABLE -/* +/****************************************************************************** + * * Predefined method/object information table. * * These are the names that can actually be evaluated via acpi_evaluate_object. * Not present in this table are the following: * - * 1) Predefined/Reserved names that are never evaluated via acpi_evaluate_object: - * _Lxx and _Exx GPE methods - * _Qxx EC methods - * _T_x compiler temporary variables + * 1) Predefined/Reserved names that are never evaluated via + * acpi_evaluate_object: + * _Lxx and _Exx GPE methods + * _Qxx EC methods + * _T_x compiler temporary variables + * _Wxx wake events * * 2) Predefined names that never actually exist within the AML code: - * Predefined resource descriptor field names + * Predefined resource descriptor field names * * 3) Predefined names that are implemented within ACPICA: - * _OSI - * - * 4) Some predefined names that are not documented within the ACPI spec. - * _WDG, _WED + * _OSI * * The main entries in the table each contain the following items: * - * Name - The ACPI reserved name - * param_count - Number of arguments to the method + * name - The ACPI reserved name + * argument_list - Contains (in 16 bits), the number of required + * arguments to the method (3 bits), and a 3-bit type + * field for each argument (up to 4 arguments). The + * METHOD_?ARGS macros generate the correct packed data. * expected_btypes - Allowed type(s) for the return value. * 0 means that no return value is expected. * @@ -149,256 +193,517 @@ enum acpi_return_package_types { * information about the expected structure of the package. This information * is saved here (rather than in a separate table) in order to minimize the * overall size of the stored data. - */ -static const union acpi_predefined_info predefined_names[] = -{ - {{"_AC0", 0, ACPI_RTYPE_INTEGER}}, - {{"_AC1", 0, ACPI_RTYPE_INTEGER}}, - {{"_AC2", 0, ACPI_RTYPE_INTEGER}}, - {{"_AC3", 0, ACPI_RTYPE_INTEGER}}, - {{"_AC4", 0, ACPI_RTYPE_INTEGER}}, - {{"_AC5", 0, ACPI_RTYPE_INTEGER}}, - {{"_AC6", 0, ACPI_RTYPE_INTEGER}}, - {{"_AC7", 0, ACPI_RTYPE_INTEGER}}, - {{"_AC8", 0, ACPI_RTYPE_INTEGER}}, - {{"_AC9", 0, ACPI_RTYPE_INTEGER}}, - {{"_ADR", 0, ACPI_RTYPE_INTEGER}}, - {{"_AEI", 0, ACPI_RTYPE_BUFFER}}, - {{"_AL0", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_AL1", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_AL2", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_AL3", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_AL4", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_AL5", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_AL6", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_AL7", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_AL8", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_AL9", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_ALC", 0, ACPI_RTYPE_INTEGER}}, - {{"_ALI", 0, ACPI_RTYPE_INTEGER}}, - {{"_ALP", 0, ACPI_RTYPE_INTEGER}}, - {{"_ALR", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 2 (Ints) */ - {{{ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 2,0}, 0,0}}, - - {{"_ALT", 0, ACPI_RTYPE_INTEGER}}, - {{"_ART", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(rev), n Pkg (2 Ref/11 Int) */ - {{{ACPI_PTYPE2_REV_FIXED, ACPI_RTYPE_REFERENCE, 2, ACPI_RTYPE_INTEGER}, - 11, 0}}, - - {{"_BBN", 0, ACPI_RTYPE_INTEGER}}, - {{"_BCL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0}, 0,0}}, - - {{"_BCM", 1, 0}}, - {{"_BCT", 1, ACPI_RTYPE_INTEGER}}, - {{"_BDN", 0, ACPI_RTYPE_INTEGER}}, - {{"_BFS", 1, 0}}, - {{"_BIF", 0, ACPI_RTYPE_PACKAGE} }, /* Fixed-length (9 Int),(4 Str/Buf) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 9, - ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER}, 4, 0} }, - - {{"_BIX", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (16 Int),(4 Str) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16, ACPI_RTYPE_STRING}, 4, - 0}}, - - {{"_BLT", 3, 0}}, - {{"_BMA", 1, ACPI_RTYPE_INTEGER}}, - {{"_BMC", 1, 0}}, - {{"_BMD", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (5 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 5,0}, 0,0}}, - - {{"_BMS", 1, ACPI_RTYPE_INTEGER}}, - {{"_BQC", 0, ACPI_RTYPE_INTEGER}}, - {{"_BST", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0}, 0,0}}, - - {{"_BTM", 1, ACPI_RTYPE_INTEGER}}, - {{"_BTP", 1, 0}}, - {{"_CBA", 0, ACPI_RTYPE_INTEGER}}, /* See PCI firmware spec 3.0 */ - {{"_CDM", 0, ACPI_RTYPE_INTEGER}}, - {{"_CID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints/Strs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING, 0,0}, 0,0}}, - - {{"_CLS", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (3 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, 0}, 0, 0}}, - - {{"_CPC", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints/Bufs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER, 0, 0}, 0, - 0}}, - - {{"_CRS", 0, ACPI_RTYPE_BUFFER}}, - {{"_CRT", 0, ACPI_RTYPE_INTEGER}}, - {{"_CSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(n), n-1 Int) */ - {{{ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 0,0}, 0,0}}, - - {{"_CST", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(n), n Pkg (1 Buf/3 Int) */ - {{{ACPI_PTYPE2_PKG_COUNT,ACPI_RTYPE_BUFFER, 1, ACPI_RTYPE_INTEGER}, 3,0}}, - - {{"_CWS", 1, ACPI_RTYPE_INTEGER}}, - {{"_DCK", 1, ACPI_RTYPE_INTEGER}}, - {{"_DCS", 0, ACPI_RTYPE_INTEGER}}, - {{"_DDC", 1, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER}}, - {{"_DDN", 0, ACPI_RTYPE_STRING}}, - {{"_DEP", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}}, - - {{"_DGS", 0, ACPI_RTYPE_INTEGER}}, - {{"_DIS", 0, 0}}, - - {{"_DLM", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (1 Ref, 0/1 Optional Buf/Ref) */ - {{{ACPI_PTYPE2_FIX_VAR, ACPI_RTYPE_REFERENCE, 1, - ACPI_RTYPE_REFERENCE | ACPI_RTYPE_BUFFER}, 0, 0}}, - - {{"_DMA", 0, ACPI_RTYPE_BUFFER}}, - {{"_DOD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0}, 0,0}}, - - {{"_DOS", 1, 0}}, - {{"_DSM", 4, ACPI_RTYPE_ALL}}, /* Must return a type, but it can be of any type */ - {{"_DSS", 1, 0}}, - {{"_DSW", 3, 0}}, - {{"_DTI", 1, 0}}, - {{"_EC_", 0, ACPI_RTYPE_INTEGER}}, - {{"_EDL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs)*/ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_EJ0", 1, 0}}, - {{"_EJ1", 1, 0}}, - {{"_EJ2", 1, 0}}, - {{"_EJ3", 1, 0}}, - {{"_EJ4", 1, 0}}, - {{"_EJD", 0, ACPI_RTYPE_STRING}}, - {{"_EVT", 1, 0}}, - {{"_FDE", 0, ACPI_RTYPE_BUFFER}}, - {{"_FDI", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (16 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16,0}, 0,0}}, - - {{"_FDM", 1, 0}}, - {{"_FIF", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0}, 0, 0}}, - - {{"_FIX", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0}, 0,0}}, - - {{"_FPS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(rev), n Pkg (5 Int) */ - {{{ACPI_PTYPE2_REV_FIXED, ACPI_RTYPE_INTEGER, 5, 0}, 0, 0}}, - - {{"_FSL", 1, 0}}, - {{"_FST", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (3 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, 0}, 0, 0}}, - - {{"_GAI", 0, ACPI_RTYPE_INTEGER}}, - {{"_GCP", 0, ACPI_RTYPE_INTEGER}}, - {{"_GHL", 0, ACPI_RTYPE_INTEGER}}, - {{"_GLK", 0, ACPI_RTYPE_INTEGER}}, - {{"_GPD", 0, ACPI_RTYPE_INTEGER}}, - {{"_GPE", 0, ACPI_RTYPE_INTEGER}}, /* _GPE method, not _GPE scope */ - {{"_GRT", 0, ACPI_RTYPE_BUFFER}}, - {{"_GSB", 0, ACPI_RTYPE_INTEGER}}, - {{"_GTF", 0, ACPI_RTYPE_BUFFER}}, - {{"_GTM", 0, ACPI_RTYPE_BUFFER}}, - {{"_GTS", 1, 0}}, - {{"_GWS", 1, ACPI_RTYPE_INTEGER}}, - {{"_HID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING}}, - {{"_HOT", 0, ACPI_RTYPE_INTEGER}}, - {{"_HPP", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0}, 0,0}}, + * + * Note: The additional braces are intended to promote portability. + * + * Note2: Table is used by the kernel-resident subsystem, the iASL compiler, + * and the acpi_help utility. + * + * TBD: _PRT - currently ignore reversed entries. Attempt to fix in nsrepair. + * Possibly fixing package elements like _BIF, etc. + * + *****************************************************************************/ + +const union acpi_predefined_info acpi_gbl_predefined_methods[] = { + {{"_AC0", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_AC1", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_AC2", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_AC3", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_AC4", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_AC5", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_AC6", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_AC7", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_AC8", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_AC9", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_ADR", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_AEI", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, + + {{"_AL0", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_AL1", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_AL2", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_AL3", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_AL4", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_AL5", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_AL6", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_AL7", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_AL8", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_AL9", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_ALC", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_ALI", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_ALP", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_ALR", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each 2 (Ints) */ + PACKAGE_INFO(ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 2, 0, 0, 0), + + {{"_ALT", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_ART", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (1 Int(rev), n Pkg (2 Ref/11 Int) */ + PACKAGE_INFO(ACPI_PTYPE2_REV_FIXED, ACPI_RTYPE_REFERENCE, 2, + ACPI_RTYPE_INTEGER, 11, 0), + + {{"_BBN", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_BCL", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Ints) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0, 0, 0, 0), + + {{"_BCM", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_BCT", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_BDN", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_BFS", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_BIF", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (9 Int),(4 Str) */ + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 9, + ACPI_RTYPE_STRING, 4, 0), + + {{"_BIX", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (16 Int),(4 Str) */ + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16, + ACPI_RTYPE_STRING, 4, 0), + + {{"_BLT", + METHOD_3ARGS(ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_BMA", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_BMC", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_BMD", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (5 Int) */ + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 5, 0, 0, 0), + + {{"_BMS", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_BQC", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_BST", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (4 Int) */ + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0, 0, 0), + + {{"_BTM", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_BTP", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_CBA", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* See PCI firmware spec 3.0 */ + + {{"_CDM", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_CID", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Ints/Strs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING, 0, + 0, 0, 0), + + {{"_CLS", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (3 Int) */ + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, 0, 0, 0), + + {{"_CPC", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Ints/Bufs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER, 0, + 0, 0, 0), + + {{"_CRS", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, + + {{"_CRT", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_CSD", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (1 Int(n), n-1 Int) */ + PACKAGE_INFO(ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 0, 0, 0, 0), + + {{"_CST", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (1 Int(n), n Pkg (1 Buf/3 Int) */ + PACKAGE_INFO(ACPI_PTYPE2_PKG_COUNT, ACPI_RTYPE_BUFFER, 1, + ACPI_RTYPE_INTEGER, 3, 0), + + {{"_CWS", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_DCK", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_DCS", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_DDC", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER)}}, + + {{"_DDN", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_STRING)}}, + + {{"_DEP", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_DGS", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_DIS", METHOD_0ARGS, + METHOD_NO_RETURN_VALUE}}, + + {{"_DLM", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each (1 Ref, 0/1 Optional Buf/Ref) */ + PACKAGE_INFO(ACPI_PTYPE2_FIX_VAR, ACPI_RTYPE_REFERENCE, 1, + ACPI_RTYPE_REFERENCE | ACPI_RTYPE_BUFFER, 0, 0), + + {{"_DMA", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, + + {{"_DOD", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Ints) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0, 0, 0, 0), + + {{"_DOS", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_DSM", + METHOD_4ARGS(ACPI_TYPE_BUFFER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, + ACPI_TYPE_PACKAGE), + METHOD_RETURNS(ACPI_RTYPE_ALL)}}, /* Must return a value, but it can be of any type */ + + {{"_DSS", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_DSW", + METHOD_3ARGS(ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_DTI", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_EC_", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_EDL", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_EJ0", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_EJ1", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_EJ2", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_EJ3", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_EJ4", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_EJD", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_STRING)}}, + + {{"_ERR", + METHOD_3ARGS(ACPI_TYPE_INTEGER, ACPI_TYPE_STRING, ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* Internal use only, used by ACPICA test suites */ + + {{"_EVT", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_FDE", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, + + {{"_FDI", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (16 Int) */ + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16, 0, 0, 0), + + {{"_FDM", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_FIF", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (4 Int) */ + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0, 0, 0), + + {{"_FIX", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Ints) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0, 0, 0, 0), + + {{"_FPS", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (1 Int(rev), n Pkg (5 Int) */ + PACKAGE_INFO(ACPI_PTYPE2_REV_FIXED, ACPI_RTYPE_INTEGER, 5, 0, 0, 0), + + {{"_FSL", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_FST", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (3 Int) */ + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, 0, 0, 0), + + {{"_GAI", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_GCP", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_GHL", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_GLK", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_GPD", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_GPE", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* _GPE method, not _GPE scope */ + + {{"_GRT", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, + + {{"_GSB", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_GTF", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, + + {{"_GTM", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, + + {{"_GTS", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_GWS", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_HID", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING)}}, + + {{"_HOT", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_HPP", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (4 Int) */ + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0, 0, 0), /* - * For _HPX, a single package is returned, containing a Variable-length number - * of sub-packages. Each sub-package contains a PCI record setting. + * For _HPX, a single package is returned, containing a variable-length number + * of subpackages. Each subpackage contains a PCI record setting. * There are several different type of record settings, of different * lengths, but all elements of all settings are Integers. */ - {{"_HPX", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (var Ints) */ - {{{ACPI_PTYPE2_MIN, ACPI_RTYPE_INTEGER, 5,0}, 0,0}}, - - {{"_HRV", 0, ACPI_RTYPE_INTEGER}}, - {{"_IFT", 0, ACPI_RTYPE_INTEGER}}, /* See IPMI spec */ - {{"_INI", 0, 0}}, - {{"_IRC", 0, 0}}, - {{"_LCK", 1, 0}}, - {{"_LID", 0, ACPI_RTYPE_INTEGER}}, - {{"_MAT", 0, ACPI_RTYPE_BUFFER}}, - {{"_MBM", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (8 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 8, 0}, 0, 0}}, - - {{"_MLS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (2 Str) */ - {{{ACPI_PTYPE2, ACPI_RTYPE_STRING, 2,0}, 0,0}}, - - {{"_MSG", 1, 0}}, - {{"_MSM", 4, ACPI_RTYPE_INTEGER}}, - {{"_NTT", 0, ACPI_RTYPE_INTEGER}}, - {{"_OFF", 0, 0}}, - {{"_ON_", 0, 0}}, - {{"_OS_", 0, ACPI_RTYPE_STRING}}, - {{"_OSC", 4, ACPI_RTYPE_BUFFER}}, - {{"_OST", 3, 0}}, - {{"_PAI", 1, ACPI_RTYPE_INTEGER}}, - {{"_PCL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_PCT", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (2 Buf) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2,0}, 0,0}}, - - {{"_PDC", 1, 0}}, - {{"_PDL", 0, ACPI_RTYPE_INTEGER}}, - {{"_PIC", 1, 0}}, - {{"_PIF", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (3 Int),(3 Str) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, ACPI_RTYPE_STRING}, 3, 0}}, - - {{"_PLD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Bufs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_BUFFER, 0,0}, 0,0}}, - - {{"_PMC", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (11 Int),(3 Str) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 11, ACPI_RTYPE_STRING}, 3, - 0}}, - - {{"_PMD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}}, - - {{"_PMM", 0, ACPI_RTYPE_INTEGER}}, - {{"_PPC", 0, ACPI_RTYPE_INTEGER}}, - {{"_PPE", 0, ACPI_RTYPE_INTEGER}}, /* See dig64 spec */ - {{"_PR0", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_PR1", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_PR2", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_PR3", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}}, - - {{"_PRE", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}}, - - {{"_PRL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}}, - - {{"_PRS", 0, ACPI_RTYPE_BUFFER}}, + {{"_HPX", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each (var Ints) */ + PACKAGE_INFO(ACPI_PTYPE2_MIN, ACPI_RTYPE_INTEGER, 5, 0, 0, 0), + + {{"_HRV", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_IFT", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* See IPMI spec */ + + {{"_INI", METHOD_0ARGS, + METHOD_NO_RETURN_VALUE}}, + + {{"_IRC", METHOD_0ARGS, + METHOD_NO_RETURN_VALUE}}, + + {{"_LCK", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_LID", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_LPD", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (1 Int(rev), n Pkg (2 Int) */ + PACKAGE_INFO(ACPI_PTYPE2_REV_FIXED, ACPI_RTYPE_INTEGER, 2, 0, 0, 0), + + {{"_MAT", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, + + {{"_MBM", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (8 Int) */ + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 8, 0, 0, 0), + + {{"_MLS", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each (1 Str/1 Buf) */ + PACKAGE_INFO(ACPI_PTYPE2, ACPI_RTYPE_STRING, 1, ACPI_RTYPE_BUFFER, 1, + 0), + + {{"_MSG", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_MSM", + METHOD_4ARGS(ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, + ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_NTT", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_OFF", METHOD_0ARGS, + METHOD_NO_RETURN_VALUE}}, + + {{"_ON_", METHOD_0ARGS, + METHOD_NO_RETURN_VALUE}}, + + {{"_OS_", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_STRING)}}, + + {{"_OSC", + METHOD_4ARGS(ACPI_TYPE_BUFFER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, + ACPI_TYPE_BUFFER), + METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, + + {{"_OST", + METHOD_3ARGS(ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_BUFFER), + METHOD_NO_RETURN_VALUE}}, + + {{"_PAI", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_PCL", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_PCT", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (2 Buf) */ + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2, 0, 0, 0), + + {{"_PDC", METHOD_1ARGS(ACPI_TYPE_BUFFER), + METHOD_NO_RETURN_VALUE}}, + + {{"_PDL", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_PIC", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_PIF", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (3 Int),(3 Str) */ + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, + ACPI_RTYPE_STRING, 3, 0), + + {{"_PLD", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Bufs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_BUFFER, 0, 0, 0, 0), + + {{"_PMC", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (11 Int),(3 Str) */ + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 11, + ACPI_RTYPE_STRING, 3, 0), + + {{"_PMD", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_PMM", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_PPC", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_PPE", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* See dig64 spec */ + + {{"_PR0", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_PR1", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_PR2", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_PR3", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_PRE", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_PRL", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_PRS", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, /* * For _PRT, many BIOSs reverse the 3rd and 4th Package elements (Source @@ -408,47 +713,89 @@ static const union acpi_predefined_info predefined_names[] = * warning, add the ACPI_RTYPE_REFERENCE type to the 4th element (index 3) * in the statement below. */ - {{"_PRT", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (4): Int,Int,Int/Ref,Int */ - {{{ACPI_PTYPE2_FIXED, 4, ACPI_RTYPE_INTEGER,ACPI_RTYPE_INTEGER}, - ACPI_RTYPE_INTEGER | ACPI_RTYPE_REFERENCE, - ACPI_RTYPE_INTEGER}}, - - {{"_PRW", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each: Pkg/Int,Int,[Variable-length Refs] (Pkg is Ref/Int) */ - {{{ACPI_PTYPE1_OPTION, 2, ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE, - ACPI_RTYPE_INTEGER}, ACPI_RTYPE_REFERENCE,0}}, - - {{"_PS0", 0, 0}}, - {{"_PS1", 0, 0}}, - {{"_PS2", 0, 0}}, - {{"_PS3", 0, 0}}, - {{"_PSC", 0, ACPI_RTYPE_INTEGER}}, - {{"_PSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (5 Int) with count */ - {{{ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER,0,0}, 0,0}}, - - {{"_PSE", 1, 0}}, - {{"_PSL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_PSR", 0, ACPI_RTYPE_INTEGER}}, - {{"_PSS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (6 Int) */ - {{{ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 6,0}, 0,0}}, - - {{"_PSV", 0, ACPI_RTYPE_INTEGER}}, - {{"_PSW", 1, 0}}, - {{"_PTC", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (2 Buf) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2,0}, 0,0}}, - - {{"_PTP", 2, ACPI_RTYPE_INTEGER}}, - {{"_PTS", 1, 0}}, - {{"_PUR", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (2 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2, 0}, 0, 0}}, - - {{"_PXM", 0, ACPI_RTYPE_INTEGER}}, - {{"_REG", 2, 0}}, - {{"_REV", 0, ACPI_RTYPE_INTEGER}}, - {{"_RMV", 0, ACPI_RTYPE_INTEGER}}, - {{"_ROM", 2, ACPI_RTYPE_BUFFER}}, - {{"_RTV", 0, ACPI_RTYPE_INTEGER}}, + {{"_PRT", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each (4): Int,Int,Int/Ref,Int */ + PACKAGE_INFO(ACPI_PTYPE2_FIXED, 4, ACPI_RTYPE_INTEGER, + ACPI_RTYPE_INTEGER, + ACPI_RTYPE_INTEGER | ACPI_RTYPE_REFERENCE, + ACPI_RTYPE_INTEGER), + + {{"_PRW", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each: Pkg/Int,Int,[Variable-length Refs] (Pkg is Ref/Int) */ + PACKAGE_INFO(ACPI_PTYPE1_OPTION, 2, + ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE, + ACPI_RTYPE_INTEGER, ACPI_RTYPE_REFERENCE, 0), + + {{"_PS0", METHOD_0ARGS, + METHOD_NO_RETURN_VALUE}}, + + {{"_PS1", METHOD_0ARGS, + METHOD_NO_RETURN_VALUE}}, + + {{"_PS2", METHOD_0ARGS, + METHOD_NO_RETURN_VALUE}}, + + {{"_PS3", METHOD_0ARGS, + METHOD_NO_RETURN_VALUE}}, + + {{"_PSC", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_PSD", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each (5 Int) with count */ + PACKAGE_INFO(ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 0, 0, 0, 0), + + {{"_PSE", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_PSL", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_PSR", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_PSS", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each (6 Int) */ + PACKAGE_INFO(ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 6, 0, 0, 0), + + {{"_PSV", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_PSW", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_PTC", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (2 Buf) */ + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2, 0, 0, 0), + + {{"_PTP", METHOD_2ARGS(ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_PTS", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_PUR", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (2 Int) */ + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2, 0, 0, 0), + + {{"_PXM", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_REG", METHOD_2ARGS(ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_REV", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_RMV", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_ROM", METHOD_2ARGS(ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, + + {{"_RTV", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* * For _S0_ through _S5_, the ACPI spec defines a return Package @@ -456,109 +803,285 @@ static const union acpi_predefined_info predefined_names[] = * Allow this by making the objects "Variable-length length", but all elements * must be Integers. */ - {{"_S0_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, - - {{"_S1_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, - - {{"_S2_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, - - {{"_S3_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, - - {{"_S4_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, - - {{"_S5_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, - - {{"_S1D", 0, ACPI_RTYPE_INTEGER}}, - {{"_S2D", 0, ACPI_RTYPE_INTEGER}}, - {{"_S3D", 0, ACPI_RTYPE_INTEGER}}, - {{"_S4D", 0, ACPI_RTYPE_INTEGER}}, - {{"_S0W", 0, ACPI_RTYPE_INTEGER}}, - {{"_S1W", 0, ACPI_RTYPE_INTEGER}}, - {{"_S2W", 0, ACPI_RTYPE_INTEGER}}, - {{"_S3W", 0, ACPI_RTYPE_INTEGER}}, - {{"_S4W", 0, ACPI_RTYPE_INTEGER}}, - {{"_SBS", 0, ACPI_RTYPE_INTEGER}}, - {{"_SCP", 0x13, 0}}, /* Acpi 1.0 allowed 1 arg. Acpi 3.0 expanded to 3 args. Allow both. */ - /* Note: the 3-arg definition may be removed for ACPI 4.0 */ - {{"_SDD", 1, 0}}, - {{"_SEG", 0, ACPI_RTYPE_INTEGER}}, - {{"_SHL", 1, ACPI_RTYPE_INTEGER}}, - {{"_SLI", 0, ACPI_RTYPE_BUFFER}}, - {{"_SPD", 1, ACPI_RTYPE_INTEGER}}, - {{"_SRS", 1, 0}}, - {{"_SRT", 1, ACPI_RTYPE_INTEGER}}, - {{"_SRV", 0, ACPI_RTYPE_INTEGER}}, /* See IPMI spec */ - {{"_SST", 1, 0}}, - {{"_STA", 0, ACPI_RTYPE_INTEGER}}, - {{"_STM", 3, 0}}, - {{"_STP", 2, ACPI_RTYPE_INTEGER}}, - {{"_STR", 0, ACPI_RTYPE_BUFFER}}, - {{"_STV", 2, ACPI_RTYPE_INTEGER}}, - {{"_SUB", 0, ACPI_RTYPE_STRING}}, - {{"_SUN", 0, ACPI_RTYPE_INTEGER}}, - {{"_SWS", 0, ACPI_RTYPE_INTEGER}}, - {{"_TC1", 0, ACPI_RTYPE_INTEGER}}, - {{"_TC2", 0, ACPI_RTYPE_INTEGER}}, - {{"_TDL", 0, ACPI_RTYPE_INTEGER}}, - {{"_TIP", 1, ACPI_RTYPE_INTEGER}}, - {{"_TIV", 1, ACPI_RTYPE_INTEGER}}, - {{"_TMP", 0, ACPI_RTYPE_INTEGER}}, - {{"_TPC", 0, ACPI_RTYPE_INTEGER}}, - {{"_TPT", 1, 0}}, - {{"_TRT", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 2_ref/6_int */ - {{{ACPI_PTYPE2, ACPI_RTYPE_REFERENCE, 2, ACPI_RTYPE_INTEGER}, 6, 0}}, - - {{"_TSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 5_int with count */ - {{{ACPI_PTYPE2_COUNT,ACPI_RTYPE_INTEGER, 5,0}, 0,0}}, - - {{"_TSP", 0, ACPI_RTYPE_INTEGER}}, - {{"_TSS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 5_int */ - {{{ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 5,0}, 0,0}}, - - {{"_TST", 0, ACPI_RTYPE_INTEGER}}, - {{"_TTS", 1, 0}}, - {{"_TZD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_TZM", 0, ACPI_RTYPE_REFERENCE}}, - {{"_TZP", 0, ACPI_RTYPE_INTEGER}}, - {{"_UID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING}}, - {{"_UPC", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0}, 0,0}}, - - {{"_UPD", 0, ACPI_RTYPE_INTEGER}}, - {{"_UPP", 0, ACPI_RTYPE_INTEGER}}, - {{"_VPO", 0, ACPI_RTYPE_INTEGER}}, + {{"_S0_", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (1 Int) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0), + + {{"_S1_", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (1 Int) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0), + + {{"_S2_", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (1 Int) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0), + + {{"_S3_", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (1 Int) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0), + + {{"_S4_", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (1 Int) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0), + + {{"_S5_", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (1 Int) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0), + + {{"_S1D", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_S2D", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_S3D", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_S4D", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_S0W", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_S1W", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_S2W", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_S3W", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_S4W", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_SBS", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_SCP", METHOD_1ARGS(ACPI_TYPE_INTEGER) | ARG_COUNT_IS_MINIMUM, + METHOD_NO_RETURN_VALUE}}, /* Acpi 1.0 allowed 1 integer arg. Acpi 3.0 expanded to 3 args. Allow both. */ + + {{"_SDD", METHOD_1ARGS(ACPI_TYPE_BUFFER), + METHOD_NO_RETURN_VALUE}}, + + {{"_SEG", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_SHL", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_SLI", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, + + {{"_SPD", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_SRS", METHOD_1ARGS(ACPI_TYPE_BUFFER), + METHOD_NO_RETURN_VALUE}}, + + {{"_SRT", METHOD_1ARGS(ACPI_TYPE_BUFFER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_SRV", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* See IPMI spec */ + + {{"_SST", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_STA", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_STM", + METHOD_3ARGS(ACPI_TYPE_BUFFER, ACPI_TYPE_BUFFER, ACPI_TYPE_BUFFER), + METHOD_NO_RETURN_VALUE}}, + + {{"_STP", METHOD_2ARGS(ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_STR", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, + + {{"_STV", METHOD_2ARGS(ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_SUB", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_STRING)}}, + + {{"_SUN", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_SWS", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_TC1", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_TC2", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_TDL", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_TIP", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_TIV", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_TMP", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_TPC", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_TPT", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_TRT", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each 2 Ref/6 Int */ + PACKAGE_INFO(ACPI_PTYPE2, ACPI_RTYPE_REFERENCE, 2, ACPI_RTYPE_INTEGER, + 6, 0), + + {{"_TSD", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each 5 Int with count */ + PACKAGE_INFO(ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 5, 0, 0, 0), + + {{"_TSP", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_TSS", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each 5 Int */ + PACKAGE_INFO(ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 5, 0, 0, 0), + + {{"_TST", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_TTS", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_TZD", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + + {{"_TZM", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_REFERENCE)}}, + + {{"_TZP", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_UID", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING)}}, + + {{"_UPC", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (4 Int) */ + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0, 0, 0), + + {{"_UPD", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_UPP", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + + {{"_VPO", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* Acpi 1.0 defined _WAK with no return value. Later, it was changed to return a package */ - {{"_WAK", 1, ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE}}, - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2,0}, 0,0}}, /* Fixed-length (2 Int), but is optional */ + {{"_WAK", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | + ACPI_RTYPE_PACKAGE)}}, + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2, 0, 0, 0), /* Fixed-length (2 Int), but is optional */ /* _WDG/_WED are MS extensions defined by "Windows Instrumentation" */ - {{"_WDG", 0, ACPI_RTYPE_BUFFER}}, - {{"_WED", 1, - ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER}}, + {{"_WDG", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, + + {{"_WED", METHOD_1ARGS(ACPI_TYPE_INTEGER), + METHOD_RETURNS(ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | + ACPI_RTYPE_BUFFER)}}, - {{{0, 0, 0, 0}, 0, 0}} /* Table terminator */ + PACKAGE_INFO(0, 0, 0, 0, 0, 0) /* Table terminator */ }; +#else +extern const union acpi_predefined_info acpi_gbl_predefined_methods[]; +#endif -#if 0 - /* This is an internally implemented control method, no need to check */ - {{"_OSI", 1, ACPI_RTYPE_INTEGER}}, +#if (defined ACPI_CREATE_RESOURCE_TABLE && defined ACPI_APPLICATION) +/****************************************************************************** + * + * Predefined names for use in Resource Descriptors. These names do not + * appear in the global Predefined Name table (since these names never + * appear in actual AML byte code, only in the original ASL) + * + * Note: Used by iASL compiler and acpi_help utility only. + * + *****************************************************************************/ - /* TBD: */ +const union acpi_predefined_info acpi_gbl_resource_names[] = { + {{"_ADR", WIDTH_16 | WIDTH_64, 0}}, + {{"_ALN", WIDTH_8 | WIDTH_16 | WIDTH_32, 0}}, + {{"_ASI", WIDTH_8, 0}}, + {{"_ASZ", WIDTH_8, 0}}, + {{"_ATT", WIDTH_64, 0}}, + {{"_BAS", WIDTH_16 | WIDTH_32, 0}}, + {{"_BM_", WIDTH_1, 0}}, + {{"_DBT", WIDTH_16, 0}}, /* Acpi 5.0 */ + {{"_DEC", WIDTH_1, 0}}, + {{"_DMA", WIDTH_8, 0}}, + {{"_DPL", WIDTH_1, 0}}, /* Acpi 5.0 */ + {{"_DRS", WIDTH_16, 0}}, /* Acpi 5.0 */ + {{"_END", WIDTH_1, 0}}, /* Acpi 5.0 */ + {{"_FLC", WIDTH_2, 0}}, /* Acpi 5.0 */ + {{"_GRA", WIDTH_ADDRESS, 0}}, + {{"_HE_", WIDTH_1, 0}}, + {{"_INT", WIDTH_16 | WIDTH_32, 0}}, + {{"_IOR", WIDTH_2, 0}}, /* Acpi 5.0 */ + {{"_LEN", WIDTH_8 | WIDTH_ADDRESS, 0}}, + {{"_LIN", WIDTH_8, 0}}, /* Acpi 5.0 */ + {{"_LL_", WIDTH_1, 0}}, + {{"_MAF", WIDTH_1, 0}}, + {{"_MAX", WIDTH_ADDRESS, 0}}, + {{"_MEM", WIDTH_2, 0}}, + {{"_MIF", WIDTH_1, 0}}, + {{"_MIN", WIDTH_ADDRESS, 0}}, + {{"_MOD", WIDTH_1, 0}}, /* Acpi 5.0 */ + {{"_MTP", WIDTH_2, 0}}, + {{"_PAR", WIDTH_8, 0}}, /* Acpi 5.0 */ + {{"_PHA", WIDTH_1, 0}}, /* Acpi 5.0 */ + {{"_PIN", WIDTH_16, 0}}, /* Acpi 5.0 */ + {{"_PPI", WIDTH_8, 0}}, /* Acpi 5.0 */ + {{"_POL", WIDTH_1 | WIDTH_2, 0}}, /* Acpi 5.0 */ + {{"_RBO", WIDTH_8, 0}}, + {{"_RBW", WIDTH_8, 0}}, + {{"_RNG", WIDTH_1, 0}}, + {{"_RT_", WIDTH_8, 0}}, /* Acpi 3.0 */ + {{"_RW_", WIDTH_1, 0}}, + {{"_RXL", WIDTH_16, 0}}, /* Acpi 5.0 */ + {{"_SHR", WIDTH_2, 0}}, + {{"_SIZ", WIDTH_2, 0}}, + {{"_SLV", WIDTH_1, 0}}, /* Acpi 5.0 */ + {{"_SPE", WIDTH_32, 0}}, /* Acpi 5.0 */ + {{"_STB", WIDTH_2, 0}}, /* Acpi 5.0 */ + {{"_TRA", WIDTH_ADDRESS, 0}}, + {{"_TRS", WIDTH_1, 0}}, + {{"_TSF", WIDTH_8, 0}}, /* Acpi 3.0 */ + {{"_TTP", WIDTH_1, 0}}, + {{"_TXL", WIDTH_16, 0}}, /* Acpi 5.0 */ + {{"_TYP", WIDTH_2 | WIDTH_16, 0}}, + {{"_VEN", VARIABLE_DATA, 0}}, /* Acpi 5.0 */ + PACKAGE_INFO(0, 0, 0, 0, 0, 0) /* Table terminator */ +}; - _PRT - currently ignore reversed entries. attempt to fix here? - think about possibly fixing package elements like _BIF, etc. +static const union acpi_predefined_info acpi_gbl_scope_names[] = { + {{"_GPE", 0, 0}}, + {{"_PR_", 0, 0}}, + {{"_SB_", 0, 0}}, + {{"_SI_", 0, 0}}, + {{"_TZ_", 0, 0}}, + PACKAGE_INFO(0, 0, 0, 0, 0, 0) /* Table terminator */ +}; +#else +extern const union acpi_predefined_info acpi_gbl_resource_names[]; #endif #endif -#endif diff --git a/drivers/acpi/acpica/acresrc.h b/drivers/acpi/acpica/acresrc.h index 0347d099349..4b008e8884a 100644 --- a/drivers/acpi/acpica/acresrc.h +++ b/drivers/acpi/acpica/acresrc.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -184,7 +184,7 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, struct acpi_buffer *output_buffer); acpi_status -acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer, +acpi_rs_create_aml_resources(struct acpi_buffer *resource_list, struct acpi_buffer *output_buffer); acpi_status @@ -227,8 +227,8 @@ acpi_rs_get_list_length(u8 * aml_buffer, u32 aml_buffer_length, acpi_size * size_needed); acpi_status -acpi_rs_get_aml_length(struct acpi_resource *linked_list_buffer, - acpi_size * size_needed); +acpi_rs_get_aml_length(struct acpi_resource *resource_list, + acpi_size resource_list_size, acpi_size * size_needed); acpi_status acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, @@ -347,18 +347,21 @@ extern struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[]; extern struct acpi_rsdump_info *acpi_gbl_dump_serial_bus_dispatch[]; /* - * rsdump + * rsdumpinfo */ extern struct acpi_rsdump_info acpi_rs_dump_irq[]; +extern struct acpi_rsdump_info acpi_rs_dump_prt[]; extern struct acpi_rsdump_info acpi_rs_dump_dma[]; extern struct acpi_rsdump_info acpi_rs_dump_start_dpf[]; extern struct acpi_rsdump_info acpi_rs_dump_end_dpf[]; extern struct acpi_rsdump_info acpi_rs_dump_io[]; +extern struct acpi_rsdump_info acpi_rs_dump_io_flags[]; extern struct acpi_rsdump_info acpi_rs_dump_fixed_io[]; extern struct acpi_rsdump_info acpi_rs_dump_vendor[]; extern struct acpi_rsdump_info acpi_rs_dump_end_tag[]; extern struct acpi_rsdump_info acpi_rs_dump_memory24[]; extern struct acpi_rsdump_info acpi_rs_dump_memory32[]; +extern struct acpi_rsdump_info acpi_rs_dump_memory_flags[]; extern struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[]; extern struct acpi_rsdump_info acpi_rs_dump_address16[]; extern struct acpi_rsdump_info acpi_rs_dump_address32[]; @@ -372,6 +375,7 @@ extern struct acpi_rsdump_info acpi_rs_dump_common_serial_bus[]; extern struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[]; extern struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[]; extern struct acpi_rsdump_info acpi_rs_dump_uart_serial_bus[]; +extern struct acpi_rsdump_info acpi_rs_dump_general_flags[]; #endif #endif /* __ACRESRC_H__ */ diff --git a/drivers/acpi/acpica/acstruct.h b/drivers/acpi/acpica/acstruct.h index 0404df605bc..cf7346110bd 100644 --- a/drivers/acpi/acpica/acstruct.h +++ b/drivers/acpi/acpica/acstruct.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,7 +53,7 @@ ****************************************************************************/ /* - * Walk state - current state of a parse tree walk. Used for both a leisurely + * Walk state - current state of a parse tree walk. Used for both a leisurely * stroll through the tree (for whatever reason), and for control method * execution. */ @@ -68,7 +68,7 @@ #define ACPI_WALK_METHOD 0x01 #define ACPI_WALK_METHOD_RESTART 0x02 -/* Flags for i_aSL compiler only */ +/* Flags for iASL compiler only */ #define ACPI_WALK_CONST_REQUIRED 0x10 #define ACPI_WALK_CONST_OPTIONAL 0x20 @@ -133,6 +133,9 @@ struct acpi_init_walk_info { u32 table_index; u32 object_count; u32 method_count; + u32 serial_method_count; + u32 non_serial_method_count; + u32 serialized_method_count; u32 device_count; u32 op_region_count; u32 field_count; @@ -178,25 +181,41 @@ union acpi_aml_operands { }; /* - * Structure used to pass object evaluation parameters. + * Structure used to pass object evaluation information and parameters. * Purpose is to reduce CPU stack use. */ struct acpi_evaluate_info { - struct acpi_namespace_node *prefix_node; - char *pathname; - union acpi_operand_object *obj_desc; - union acpi_operand_object **parameters; - struct acpi_namespace_node *resolved_node; - union acpi_operand_object *return_object; - u8 param_count; - u8 pass_number; - u8 return_object_type; - u8 flags; + /* The first 3 elements are passed by the caller to acpi_ns_evaluate */ + + struct acpi_namespace_node *prefix_node; /* Input: starting node */ + char *relative_pathname; /* Input: path relative to prefix_node */ + union acpi_operand_object **parameters; /* Input: argument list */ + + struct acpi_namespace_node *node; /* Resolved node (prefix_node:relative_pathname) */ + union acpi_operand_object *obj_desc; /* Object attached to the resolved node */ + char *full_pathname; /* Full pathname of the resolved node */ + + const union acpi_predefined_info *predefined; /* Used if Node is a predefined name */ + union acpi_operand_object *return_object; /* Object returned from the evaluation */ + union acpi_operand_object *parent_package; /* Used if return object is a Package */ + + u32 return_flags; /* Used for return value analysis */ + u32 return_btype; /* Bitmapped type of the returned object */ + u16 param_count; /* Count of the input argument list */ + u8 pass_number; /* Parser pass number */ + u8 return_object_type; /* Object type of the returned object */ + u8 node_flags; /* Same as Node->Flags */ + u8 flags; /* General flags */ }; /* Values for Flags above */ -#define ACPI_IGNORE_RETURN_VALUE 1 +#define ACPI_IGNORE_RETURN_VALUE 1 + +/* Defines for return_flags field above */ + +#define ACPI_OBJECT_REPAIRED 1 +#define ACPI_OBJECT_WRAPPED 2 /* Info used by acpi_ns_initialize_devices */ diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h index d5bec304c82..f14882788ee 100644 --- a/drivers/acpi/acpica/actables.h +++ b/drivers/acpi/acpica/actables.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,6 +47,38 @@ acpi_status acpi_allocate_root_table(u32 initial_table_count); /* + * tbxfroot - Root pointer utilities + */ +acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp); + +u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length); + +/* + * tbdata - table data structure management + */ +acpi_status acpi_tb_get_next_root_index(u32 *table_index); + +void +acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc, + acpi_physical_address address, + u8 flags, struct acpi_table_header *table); + +acpi_status +acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc, + acpi_physical_address address, u8 flags); + +void acpi_tb_release_temp_table(struct acpi_table_desc *table_desc); + +acpi_status acpi_tb_validate_temp_table(struct acpi_table_desc *table_desc); + +acpi_status +acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc, char *signature); + +u8 acpi_tb_is_table_loaded(u32 table_index); + +void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded); + +/* * tbfadt - FADT parse/convert/validate */ void acpi_tb_parse_fadt(u32 table_index); @@ -65,17 +97,32 @@ acpi_tb_find_table(char *signature, */ acpi_status acpi_tb_resize_root_table_list(void); -acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc); +acpi_status acpi_tb_validate_table(struct acpi_table_desc *table_desc); + +void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc); + +void acpi_tb_override_table(struct acpi_table_desc *old_table_desc); acpi_status -acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index); +acpi_tb_acquire_table(struct acpi_table_desc *table_desc, + struct acpi_table_header **table_ptr, + u32 *table_length, u8 *table_flags); + +void +acpi_tb_release_table(struct acpi_table_header *table, + u32 table_length, u8 table_flags); + +acpi_status +acpi_tb_install_standard_table(acpi_physical_address address, + u8 flags, + u8 reload, u8 override, u32 *table_index); acpi_status acpi_tb_store_table(acpi_physical_address address, struct acpi_table_header *table, u32 length, u8 flags, u32 *table_index); -void acpi_tb_delete_table(struct acpi_table_desc *table_desc); +void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc); void acpi_tb_terminate(void); @@ -87,10 +134,6 @@ acpi_status acpi_tb_release_owner_id(u32 table_index); acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id); -u8 acpi_tb_is_table_loaded(u32 table_index); - -void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded); - /* * tbutils - table manager utilities */ @@ -112,8 +155,13 @@ void acpi_tb_check_dsdt_header(void); struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index); void -acpi_tb_install_table(acpi_physical_address address, - char *signature, u32 table_index); +acpi_tb_install_table_with_override(u32 table_index, + struct acpi_table_desc *new_table_desc, + u8 override); + +acpi_status +acpi_tb_install_fixed_table(acpi_physical_address address, + char *signature, u32 table_index); acpi_status acpi_tb_parse_root_table(acpi_physical_address rsdp_address); diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 925ccf22101..1e256c5bda2 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,7 +49,7 @@ extern const u8 acpi_gbl_resource_aml_serial_bus_sizes[]; /* Strings used by the disassembler and debugger resource dump routines */ -#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) +#if defined(ACPI_DEBUG_OUTPUT) || defined (ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) extern const char *acpi_gbl_bm_decode[]; extern const char *acpi_gbl_config_decode[]; @@ -69,8 +69,66 @@ extern const char *acpi_gbl_siz_decode[]; extern const char *acpi_gbl_trs_decode[]; extern const char *acpi_gbl_ttp_decode[]; extern const char *acpi_gbl_typ_decode[]; +extern const char *acpi_gbl_ppc_decode[]; +extern const char *acpi_gbl_ior_decode[]; +extern const char *acpi_gbl_dts_decode[]; +extern const char *acpi_gbl_ct_decode[]; +extern const char *acpi_gbl_sbt_decode[]; +extern const char *acpi_gbl_am_decode[]; +extern const char *acpi_gbl_sm_decode[]; +extern const char *acpi_gbl_wm_decode[]; +extern const char *acpi_gbl_cph_decode[]; +extern const char *acpi_gbl_cpo_decode[]; +extern const char *acpi_gbl_dp_decode[]; +extern const char *acpi_gbl_ed_decode[]; +extern const char *acpi_gbl_bpb_decode[]; +extern const char *acpi_gbl_sb_decode[]; +extern const char *acpi_gbl_fc_decode[]; +extern const char *acpi_gbl_pt_decode[]; #endif +/* + * For the iASL compiler case, the output is redirected to stderr so that + * any of the various ACPI errors and warnings do not appear in the output + * files, for either the compiler or disassembler portions of the tool. + */ +#ifdef ACPI_ASL_COMPILER + +#include <stdio.h> +extern FILE *acpi_gbl_output_file; + +#define ACPI_MSG_REDIRECT_BEGIN \ + FILE *output_file = acpi_gbl_output_file; \ + acpi_os_redirect_output (stderr); + +#define ACPI_MSG_REDIRECT_END \ + acpi_os_redirect_output (output_file); + +#else +/* + * non-iASL case - no redirection, nothing to do + */ +#define ACPI_MSG_REDIRECT_BEGIN +#define ACPI_MSG_REDIRECT_END +#endif + +/* + * Common error message prefixes + */ +#define ACPI_MSG_ERROR "ACPI Error: " +#define ACPI_MSG_EXCEPTION "ACPI Exception: " +#define ACPI_MSG_WARNING "ACPI Warning: " +#define ACPI_MSG_INFO "ACPI: " + +#define ACPI_MSG_BIOS_ERROR "ACPI BIOS Error (bug): " +#define ACPI_MSG_BIOS_WARNING "ACPI BIOS Warning (bug): " + +/* + * Common message suffix + */ +#define ACPI_MSG_SUFFIX \ + acpi_os_printf (" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, module_name, line_number) + /* Types for Resource descriptor entries */ #define ACPI_INVALID_RESOURCE 0 @@ -79,14 +137,14 @@ extern const char *acpi_gbl_typ_decode[]; #define ACPI_SMALL_VARIABLE_LENGTH 3 typedef -acpi_status(*acpi_walk_aml_callback) (u8 * aml, +acpi_status(*acpi_walk_aml_callback) (u8 *aml, u32 length, u32 offset, u8 resource_index, void **context); typedef acpi_status(*acpi_pkg_callback) (u8 object_type, - union acpi_operand_object * source_object, + union acpi_operand_object *source_object, union acpi_generic_state * state, void *context); @@ -97,9 +155,10 @@ struct acpi_pkg_info { u32 num_packages; }; +/* Object reference counts */ + #define REF_INCREMENT (u16) 0 #define REF_DECREMENT (u16) 1 -#define REF_FORCE_DELETE (u16) 2 /* acpi_ut_dump_buffer */ @@ -117,8 +176,7 @@ acpi_status acpi_ut_init_globals(void); char *acpi_ut_get_mutex_name(u32 mutex_id); -const char *acpi_ut_get_notify_name(u32 notify_value); - +const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type); #endif char *acpi_ut_get_type_name(acpi_object_type type); @@ -202,7 +260,9 @@ extern const u8 _acpi_ctype[]; #define ACPI_IS_PRINT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_SP | _ACPI_PU)) #define ACPI_IS_ALPHA(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP)) -#endif /* ACPI_USE_SYSTEM_CLIBRARY */ +#endif /* !ACPI_USE_SYSTEM_CLIBRARY */ + +#define ACPI_IS_ASCII(c) ((c) < 0x80) /* * utcopy - Object construction and conversion interfaces @@ -210,11 +270,11 @@ extern const u8 _acpi_ctype[]; acpi_status acpi_ut_build_simple_object(union acpi_operand_object *obj, union acpi_object *user_obj, - u8 * data_space, u32 * buffer_space_used); + u8 *data_space, u32 *buffer_space_used); acpi_status acpi_ut_build_package_object(union acpi_operand_object *obj, - u8 * buffer, u32 * space_used); + u8 *buffer, u32 *space_used); acpi_status acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *obj, @@ -287,9 +347,10 @@ acpi_ut_ptr_exit(u32 line_number, const char *function_name, const char *module_name, u32 component_id, u8 *ptr); -void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id); +void +acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id); -void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display); +void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 offset); void acpi_ut_report_error(char *module_name, u32 line_number); @@ -337,15 +398,19 @@ acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node, */ acpi_status acpi_ut_execute_HID(struct acpi_namespace_node *device_node, - struct acpica_device_id **return_id); + struct acpi_pnp_device_id ** return_id); acpi_status acpi_ut_execute_UID(struct acpi_namespace_node *device_node, - struct acpica_device_id **return_id); + struct acpi_pnp_device_id ** return_id); + +acpi_status +acpi_ut_execute_SUB(struct acpi_namespace_node *device_node, + struct acpi_pnp_device_id **return_id); acpi_status acpi_ut_execute_CID(struct acpi_namespace_node *device_node, - struct acpica_device_id_list **return_cid_list); + struct acpi_pnp_device_id_list ** return_cid_list); /* * utlock - reader/writer locks @@ -398,17 +463,39 @@ acpi_ut_get_object_size(union acpi_operand_object *obj, acpi_size * obj_length); */ acpi_status acpi_ut_initialize_interfaces(void); -void acpi_ut_interface_terminate(void); +acpi_status acpi_ut_interface_terminate(void); acpi_status acpi_ut_install_interface(acpi_string interface_name); acpi_status acpi_ut_remove_interface(acpi_string interface_name); +acpi_status acpi_ut_update_interfaces(u8 action); + struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name); acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state); /* + * utpredef - support for predefined names + */ +const union acpi_predefined_info *acpi_ut_get_next_predefined_method(const union + acpi_predefined_info + *this_name); + +const union acpi_predefined_info *acpi_ut_match_predefined_method(char *name); + +const union acpi_predefined_info *acpi_ut_match_resource_name(char *name); + +void +acpi_ut_display_predefined_method(char *buffer, + const union acpi_predefined_info *this_name, + u8 multi_line); + +void acpi_ut_get_expected_return_types(char *buffer, u32 expected_btypes); + +u32 acpi_ut_get_resource_bit_width(char *buffer, u16 types); + +/* * utstate - Generic state creation/cache routines */ void @@ -460,33 +547,18 @@ acpi_ut_short_divide(u64 in_dividend, /* * utmisc */ -const char *acpi_ut_validate_exception(acpi_status status); +const struct acpi_exception_info *acpi_ut_validate_exception(acpi_status + status); u8 acpi_ut_is_pci_root_bridge(char *id); u8 acpi_ut_is_aml_table(struct acpi_table_header *table); -acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id); - -void acpi_ut_release_owner_id(acpi_owner_id * owner_id); - acpi_status acpi_ut_walk_package_tree(union acpi_operand_object *source_object, void *target_object, acpi_pkg_callback walk_callback, void *context); -void acpi_ut_strupr(char *src_string); - -void acpi_ut_print_string(char *string, u8 max_length); - -u8 acpi_ut_valid_acpi_name(u32 name); - -acpi_name acpi_ut_repair_name(char *name); - -u8 acpi_ut_valid_acpi_char(char character, u32 position); - -acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer); - /* Values for Base above (16=Hex, 10=Decimal) */ #define ACPI_ANY_BASE 0 @@ -503,15 +575,25 @@ acpi_ut_display_init_pathname(u8 type, #endif /* + * utownerid - Support for Table/Method Owner IDs + */ +acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id); + +void acpi_ut_release_owner_id(acpi_owner_id * owner_id); + +/* * utresrc */ acpi_status -acpi_ut_walk_aml_resources(u8 * aml, +acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state, + u8 *aml, acpi_size aml_length, acpi_walk_aml_callback user_function, void **context); -acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index); +acpi_status +acpi_ut_validate_resource(struct acpi_walk_state *walk_state, + void *aml, u8 *return_index); u32 acpi_ut_get_descriptor_length(void *aml); @@ -522,8 +604,39 @@ u8 acpi_ut_get_resource_header_length(void *aml); u8 acpi_ut_get_resource_type(void *aml); acpi_status -acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, - u8 ** end_tag); +acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 **end_tag); + +/* + * utstring - String and character utilities + */ +void acpi_ut_strupr(char *src_string); + +void acpi_ut_strlwr(char *src_string); + +int acpi_ut_stricmp(char *string1, char *string2); + +acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer); + +void acpi_ut_print_string(char *string, u16 max_length); + +void ut_convert_backslashes(char *pathname); + +u8 acpi_ut_valid_acpi_name(char *name); + +u8 acpi_ut_valid_acpi_char(char character, u32 position); + +void acpi_ut_repair_name(char *name); + +#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION) +u8 acpi_ut_safe_strcpy(char *dest, acpi_size dest_size, char *source); + +u8 acpi_ut_safe_strcat(char *dest, acpi_size dest_size, char *source); + +u8 +acpi_ut_safe_strncat(char *dest, + acpi_size dest_size, + char *source, acpi_size max_transfer_length); +#endif /* * utmutex - mutex support @@ -549,12 +662,6 @@ acpi_status acpi_ut_initialize_buffer(struct acpi_buffer *buffer, acpi_size required_length); -void *acpi_ut_allocate(acpi_size size, - u32 component, const char *module, u32 line); - -void *acpi_ut_allocate_zeroed(acpi_size size, - u32 component, const char *module, u32 line); - #ifdef ACPI_DBG_TRACK_ALLOCATIONS void *acpi_ut_allocate_and_track(acpi_size size, u32 component, const char *module, u32 line); @@ -611,6 +718,12 @@ acpi_ut_predefined_info(const char *module_name, u32 line_number, char *pathname, u8 node_flags, const char *format, ...); +void ACPI_INTERNAL_VAR_XFACE +acpi_ut_predefined_bios_error(const char *module_name, + u32 line_number, + char *pathname, + u8 node_flags, const char *format, ...); + void acpi_ut_namespace_error(const char *module_name, u32 line_number, @@ -623,4 +736,11 @@ acpi_ut_method_error(const char *module_name, struct acpi_namespace_node *node, const char *path, acpi_status lookup_status); +/* + * Utility functions for ACPI names and IDs + */ +const struct ah_predefined_name *acpi_ah_match_predefined_name(char *nameseg); + +const struct ah_device_id *acpi_ah_match_hardware_id(char *hid); + #endif /* _ACUTILS_H */ diff --git a/drivers/acpi/acpica/amlcode.h b/drivers/acpi/acpica/amlcode.h index 905280fec0f..5908ccec6ae 100644 --- a/drivers/acpi/acpica/amlcode.h +++ b/drivers/acpi/acpica/amlcode.h @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -182,7 +182,7 @@ /* * Combination opcodes (actually two one-byte opcodes) - * Used by the disassembler and i_aSL compiler + * Used by the disassembler and iASL compiler */ #define AML_LGREATEREQUAL_OP (u16) 0x9295 #define AML_LLESSEQUAL_OP (u16) 0x9294 @@ -280,7 +280,7 @@ /* Multiple/complex types */ -#define ARGI_DATAOBJECT 0x12 /* Buffer, String, package or reference to a Node - Used only by size_of operator */ +#define ARGI_DATAOBJECT 0x12 /* Buffer, String, package or reference to a node - Used only by size_of operator */ #define ARGI_COMPLEXOBJ 0x13 /* Buffer, String, or package (Used by INDEX op only) */ #define ARGI_REF_OR_STRING 0x14 /* Reference or String (Used by DEREFOF op only) */ #define ARGI_REGION_OR_BUFFER 0x15 /* Used by LOAD op only */ diff --git a/drivers/acpi/acpica/amlresrc.h b/drivers/acpi/acpica/amlresrc.h index 7b2128f274e..f3f83440844 100644 --- a/drivers/acpi/acpica/amlresrc.h +++ b/drivers/acpi/acpica/amlresrc.h @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: amlresrc.h - AML resource descriptors @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -98,7 +97,7 @@ #define ACPI_RESTAG_TRANSLATION "_TRA" #define ACPI_RESTAG_TRANSTYPE "_TRS" /* Sparse(1), Dense(0) */ #define ACPI_RESTAG_TYPE "_TTP" /* Translation(1), Static (0) */ -#define ACPI_RESTAG_XFERTYPE "_SIZ" /* 8(0), 8_and16(1), 16(2) */ +#define ACPI_RESTAG_XFERTYPE "_SIZ" /* 8(0), 8And16(1), 16(2) */ #define ACPI_RESTAG_VENDORDATA "_VEN" /* Default sizes for "small" resource descriptors */ @@ -200,6 +199,12 @@ struct aml_resource_fixed_dma { struct aml_resource_large_header { AML_RESOURCE_LARGE_HEADER_COMMON}; +/* General Flags for address space resource descriptors */ + +#define ACPI_RESOURCE_FLAG_DEC 2 +#define ACPI_RESOURCE_FLAG_MIF 4 +#define ACPI_RESOURCE_FLAG_MAF 8 + struct aml_resource_memory24 { AML_RESOURCE_LARGE_HEADER_COMMON u8 flags; u16 minimum; @@ -235,7 +240,7 @@ AML_RESOURCE_LARGE_HEADER_COMMON AML_RESOURCE_ADDRESS_COMMON}; struct aml_resource_extended_address64 { AML_RESOURCE_LARGE_HEADER_COMMON - AML_RESOURCE_ADDRESS_COMMON u8 revision_iD; + AML_RESOURCE_ADDRESS_COMMON u8 revision_ID; u8 reserved; u64 granularity; u64 minimum; diff --git a/drivers/acpi/acpica/dsargs.c b/drivers/acpi/acpica/dsargs.c index 80eb1900297..720b1cdda71 100644 --- a/drivers/acpi/acpica/dsargs.c +++ b/drivers/acpi/acpica/dsargs.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -62,7 +62,7 @@ acpi_ds_execute_arguments(struct acpi_namespace_node *node, * * FUNCTION: acpi_ds_execute_arguments * - * PARAMETERS: Node - Object NS node + * PARAMETERS: node - Object NS node * scope_node - Parent NS node * aml_length - Length of executable AML * aml_start - Pointer to the AML @@ -158,7 +158,7 @@ acpi_ds_execute_arguments(struct acpi_namespace_node *node, walk_state->deferred_node = node; status = acpi_ps_parse_aml(walk_state); - cleanup: +cleanup: acpi_ps_delete_parse_tree(op); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c index effe4ca1133..8daf9de82b7 100644 --- a/drivers/acpi/acpica/dscontrol.c +++ b/drivers/acpi/acpica/dscontrol.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -56,7 +56,7 @@ ACPI_MODULE_NAME("dscontrol") * FUNCTION: acpi_ds_exec_begin_control_op * * PARAMETERS: walk_list - The list that owns the walk stack - * Op - The control Op + * op - The control Op * * RETURN: Status * @@ -78,7 +78,6 @@ acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, switch (op->common.aml_opcode) { case AML_WHILE_OP: - /* * If this is an additional iteration of a while loop, continue. * There is no need to allocate a new control state. @@ -99,7 +98,6 @@ acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, /*lint -fallthrough */ case AML_IF_OP: - /* * IF/WHILE: Create a new control state to manage these * constructs. We need to manage these as a stack, in order @@ -142,6 +140,7 @@ acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, break; default: + break; } @@ -153,7 +152,7 @@ acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, * FUNCTION: acpi_ds_exec_end_control_op * * PARAMETERS: walk_list - The list that owns the walk stack - * Op - The control Op + * op - The control Op * * RETURN: Status * @@ -280,7 +279,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, /* * Get the return value and save as the last result - * value. This is the only place where walk_state->return_desc + * value. This is the only place where walk_state->return_desc * is set to anything other than zero! */ walk_state->return_desc = walk_state->operands[0]; @@ -344,6 +343,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, case AML_NOOP_OP: /* Just do nothing! */ + break; case AML_BREAK_POINT_OP: diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c index cd243cf2cab..3661c8e9054 100644 --- a/drivers/acpi/acpica/dsfield.c +++ b/drivers/acpi/acpica/dsfield.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,16 +53,84 @@ ACPI_MODULE_NAME("dsfield") /* Local prototypes */ +#ifdef ACPI_ASL_COMPILER +#include "acdisasm.h" +static acpi_status +acpi_ds_create_external_region(acpi_status lookup_status, + union acpi_parse_object *op, + char *path, + struct acpi_walk_state *walk_state, + struct acpi_namespace_node **node); +#endif + static acpi_status acpi_ds_get_field_names(struct acpi_create_field_info *info, struct acpi_walk_state *walk_state, union acpi_parse_object *arg); +#ifdef ACPI_ASL_COMPILER +/******************************************************************************* + * + * FUNCTION: acpi_ds_create_external_region (iASL Disassembler only) + * + * PARAMETERS: lookup_status - Status from ns_lookup operation + * op - Op containing the Field definition and args + * path - Pathname of the region + * ` walk_state - Current method state + * node - Where the new region node is returned + * + * RETURN: Status + * + * DESCRIPTION: Add region to the external list if NOT_FOUND. Create a new + * region node/object. + * + ******************************************************************************/ + +static acpi_status +acpi_ds_create_external_region(acpi_status lookup_status, + union acpi_parse_object *op, + char *path, + struct acpi_walk_state *walk_state, + struct acpi_namespace_node **node) +{ + acpi_status status; + union acpi_operand_object *obj_desc; + + if (lookup_status != AE_NOT_FOUND) { + return (lookup_status); + } + + /* + * Table disassembly: + * operation_region not found. Generate an External for it, and + * insert the name into the namespace. + */ + acpi_dm_add_op_to_external_list(op, path, ACPI_TYPE_REGION, 0, 0); + status = acpi_ns_lookup(walk_state->scope_info, path, ACPI_TYPE_REGION, + ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, + walk_state, node); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Must create and install a region object for the new node */ + + obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + obj_desc->region.node = *node; + status = acpi_ns_attach_object(*node, obj_desc, ACPI_TYPE_REGION); + return (status); +} +#endif + /******************************************************************************* * * FUNCTION: acpi_ds_create_buffer_field * - * PARAMETERS: Op - Current parse op (create_xXField) + * PARAMETERS: op - Current parse op (create_XXField) * walk_state - Current state * * RETURN: Status @@ -99,7 +167,7 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, arg = acpi_ps_get_arg(op, 3); } else { - /* For all other create_xXXField operators, name is the 3rd argument */ + /* For all other create_XXXField operators, name is the 3rd argument */ arg = acpi_ps_get_arg(op, 2); } @@ -191,7 +259,7 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, goto cleanup; } - cleanup: +cleanup: /* Remove local reference to the object */ @@ -203,13 +271,13 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, * * FUNCTION: acpi_ds_get_field_names * - * PARAMETERS: Info - create_field info structure + * PARAMETERS: info - create_field info structure * ` walk_state - Current method state - * Arg - First parser arg for the field name list + * arg - First parser arg for the field name list * * RETURN: Status * - * DESCRIPTION: Process all named fields in a field declaration. Names are + * DESCRIPTION: Process all named fields in a field declaration. Names are * entered into the namespace. * ******************************************************************************/ @@ -234,10 +302,10 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, while (arg) { /* * Four types of field elements are handled: - * 1) Name - Enters a new named field into the namespace - * 2) Offset - specifies a bit offset + * 1) name - Enters a new named field into the namespace + * 2) offset - specifies a bit offset * 3) access_as - changes the access mode/attributes - * 4) Connection - Associate a resource template with the field + * 4) connection - Associate a resource template with the field */ switch (arg->common.aml_opcode) { case AML_INT_RESERVEDFIELD_OP: @@ -389,7 +457,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, * * FUNCTION: acpi_ds_create_field * - * PARAMETERS: Op - Op containing the Field definition and args + * PARAMETERS: op - Op containing the Field definition and args * region_node - Object for the containing Operation Region * ` walk_state - Current method state * @@ -413,12 +481,19 @@ acpi_ds_create_field(union acpi_parse_object *op, /* First arg is the name of the parent op_region (must already exist) */ arg = op->common.value.arg; + if (!region_node) { status = acpi_ns_lookup(walk_state->scope_info, arg->common.value.name, ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, ®ion_node); +#ifdef ACPI_ASL_COMPILER + status = acpi_ds_create_external_region(status, arg, + arg->common.value.name, + walk_state, + ®ion_node); +#endif if (ACPI_FAILURE(status)) { ACPI_ERROR_NAMESPACE(arg->common.value.name, status); return_ACPI_STATUS(status); @@ -446,7 +521,7 @@ acpi_ds_create_field(union acpi_parse_object *op, * * FUNCTION: acpi_ds_init_field_objects * - * PARAMETERS: Op - Op containing the Field definition and args + * PARAMETERS: op - Op containing the Field definition and args * ` walk_state - Current method state * * RETURN: Status @@ -488,21 +563,25 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, */ switch (walk_state->opcode) { case AML_FIELD_OP: + arg = acpi_ps_get_arg(op, 2); type = ACPI_TYPE_LOCAL_REGION_FIELD; break; case AML_BANK_FIELD_OP: + arg = acpi_ps_get_arg(op, 4); type = ACPI_TYPE_LOCAL_BANK_FIELD; break; case AML_INDEX_FIELD_OP: + arg = acpi_ps_get_arg(op, 3); type = ACPI_TYPE_LOCAL_INDEX_FIELD; break; default: + return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -561,7 +640,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, * * FUNCTION: acpi_ds_create_bank_field * - * PARAMETERS: Op - Op containing the Field definition and args + * PARAMETERS: op - Op containing the Field definition and args * region_node - Object for the containing Operation Region * walk_state - Current method state * @@ -591,6 +670,12 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, arg->common.value.name, ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, ®ion_node); +#ifdef ACPI_ASL_COMPILER + status = acpi_ds_create_external_region(status, arg, + arg->common.value.name, + walk_state, + ®ion_node); +#endif if (ACPI_FAILURE(status)) { ACPI_ERROR_NAMESPACE(arg->common.value.name, status); return_ACPI_STATUS(status); @@ -645,7 +730,7 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, * * FUNCTION: acpi_ds_create_index_field * - * PARAMETERS: Op - Op containing the Field definition and args + * PARAMETERS: op - Op containing the Field definition and args * region_node - Object for the containing Operation Region * ` walk_state - Current method state * diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c index 9e5ac7f780a..aee5e45f6d3 100644 --- a/drivers/acpi/acpica/dsinit.c +++ b/drivers/acpi/acpica/dsinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -60,8 +60,8 @@ acpi_ds_init_one_object(acpi_handle obj_handle, * FUNCTION: acpi_ds_init_one_object * * PARAMETERS: obj_handle - Node for the object - * Level - Current nesting level - * Context - Points to a init info struct + * level - Current nesting level + * context - Points to a init info struct * return_value - Not used * * RETURN: Status @@ -83,8 +83,8 @@ acpi_ds_init_one_object(acpi_handle obj_handle, (struct acpi_init_walk_info *)context; struct acpi_namespace_node *node = (struct acpi_namespace_node *)obj_handle; - acpi_object_type type; acpi_status status; + union acpi_operand_object *obj_desc; ACPI_FUNCTION_ENTRY(); @@ -100,9 +100,7 @@ acpi_ds_init_one_object(acpi_handle obj_handle, /* And even then, we are only interested in a few object types */ - type = acpi_ns_get_type(obj_handle); - - switch (type) { + switch (acpi_ns_get_type(obj_handle)) { case ACPI_TYPE_REGION: status = acpi_ds_initialize_region(obj_handle); @@ -117,8 +115,44 @@ acpi_ds_init_one_object(acpi_handle obj_handle, break; case ACPI_TYPE_METHOD: - + /* + * Auto-serialization support. We will examine each method that is + * not_serialized to determine if it creates any Named objects. If + * it does, it will be marked serialized to prevent problems if + * the method is entered by two or more threads and an attempt is + * made to create the same named object twice -- which results in + * an AE_ALREADY_EXISTS exception and method abort. + */ info->method_count++; + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + break; + } + + /* Ignore if already serialized */ + + if (obj_desc->method.info_flags & ACPI_METHOD_SERIALIZED) { + info->serial_method_count++; + break; + } + + if (acpi_gbl_auto_serialize_methods) { + + /* Parse/scan method and serialize it if necessary */ + + acpi_ds_auto_serialize_method(node, obj_desc); + if (obj_desc->method. + info_flags & ACPI_METHOD_SERIALIZED) { + + /* Method was just converted to Serialized */ + + info->serial_method_count++; + info->serialized_method_count++; + break; + } + } + + info->non_serial_method_count++; break; case ACPI_TYPE_DEVICE: @@ -127,6 +161,7 @@ acpi_ds_init_one_object(acpi_handle obj_handle, break; default: + break; } @@ -169,7 +204,6 @@ acpi_ds_initialize_objects(u32 table_index, ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "**** Starting initialization of namespace objects ****\n")); - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "Parsing all Control Methods:")); /* Set all init info to zero */ @@ -204,14 +238,16 @@ acpi_ds_initialize_objects(u32 table_index, } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "\nTable [%4.4s](id %4.4X) - %u Objects with %u Devices %u Methods %u Regions\n", + "Table [%4.4s] (id %4.4X) - %4u Objects with %3u Devices, " + "%3u Regions, %3u Methods (%u/%u/%u Serial/Non/Cvt)\n", table->signature, owner_id, info.object_count, - info.device_count, info.method_count, - info.op_region_count)); + info.device_count, info.op_region_count, + info.method_count, info.serial_method_count, + info.non_serial_method_count, + info.serialized_method_count)); - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "%u Methods, %u Regions\n", info.method_count, - info.op_region_count)); + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "%u Methods, %u Regions\n", + info.method_count, info.op_region_count)); return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index 00f5dab5bcc..3c7f7378b94 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,21 +47,160 @@ #include "acinterp.h" #include "acnamesp.h" #ifdef ACPI_DISASSEMBLER -#include <acpi/acdisasm.h> +#include "acdisasm.h" #endif +#include "acparser.h" +#include "amlcode.h" #define _COMPONENT ACPI_DISPATCHER ACPI_MODULE_NAME("dsmethod") /* Local prototypes */ static acpi_status +acpi_ds_detect_named_opcodes(struct acpi_walk_state *walk_state, + union acpi_parse_object **out_op); + +static acpi_status acpi_ds_create_method_mutex(union acpi_operand_object *method_desc); /******************************************************************************* * + * FUNCTION: acpi_ds_auto_serialize_method + * + * PARAMETERS: node - Namespace Node of the method + * obj_desc - Method object attached to node + * + * RETURN: Status + * + * DESCRIPTION: Parse a control method AML to scan for control methods that + * need serialization due to the creation of named objects. + * + * NOTE: It is a bit of overkill to mark all such methods serialized, since + * there is only a problem if the method actually blocks during execution. + * A blocking operation is, for example, a Sleep() operation, or any access + * to an operation region. However, it is probably not possible to easily + * detect whether a method will block or not, so we simply mark all suspicious + * methods as serialized. + * + * NOTE2: This code is essentially a generic routine for parsing a single + * control method. + * + ******************************************************************************/ + +acpi_status +acpi_ds_auto_serialize_method(struct acpi_namespace_node *node, + union acpi_operand_object *obj_desc) +{ + acpi_status status; + union acpi_parse_object *op = NULL; + struct acpi_walk_state *walk_state; + + ACPI_FUNCTION_TRACE_PTR(ds_auto_serialize_method, node); + + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "Method auto-serialization parse [%4.4s] %p\n", + acpi_ut_get_node_name(node), node)); + + /* Create/Init a root op for the method parse tree */ + + op = acpi_ps_alloc_op(AML_METHOD_OP); + if (!op) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + acpi_ps_set_name(op, node->name.integer); + op->common.node = node; + + /* Create and initialize a new walk state */ + + walk_state = + acpi_ds_create_walk_state(node->owner_id, NULL, NULL, NULL); + if (!walk_state) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + status = + acpi_ds_init_aml_walk(walk_state, op, node, + obj_desc->method.aml_start, + obj_desc->method.aml_length, NULL, 0); + if (ACPI_FAILURE(status)) { + acpi_ds_delete_walk_state(walk_state); + return_ACPI_STATUS(status); + } + + walk_state->descending_callback = acpi_ds_detect_named_opcodes; + + /* Parse the method, scan for creation of named objects */ + + status = acpi_ps_parse_aml(walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_ps_delete_parse_tree(op); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_detect_named_opcodes + * + * PARAMETERS: walk_state - Current state of the parse tree walk + * out_op - Unused, required for parser interface + * + * RETURN: Status + * + * DESCRIPTION: Descending callback used during the loading of ACPI tables. + * Currently used to detect methods that must be marked serialized + * in order to avoid problems with the creation of named objects. + * + ******************************************************************************/ + +static acpi_status +acpi_ds_detect_named_opcodes(struct acpi_walk_state *walk_state, + union acpi_parse_object **out_op) +{ + + ACPI_FUNCTION_NAME(acpi_ds_detect_named_opcodes); + + /* We are only interested in opcodes that create a new name */ + + if (! + (walk_state->op_info-> + flags & (AML_NAMED | AML_CREATE | AML_FIELD))) { + return (AE_OK); + } + + /* + * At this point, we know we have a Named object opcode. + * Mark the method as serialized. Later code will create a mutex for + * this method to enforce serialization. + * + * Note, ACPI_METHOD_IGNORE_SYNC_LEVEL flag means that we will ignore the + * Sync Level mechanism for this method, even though it is now serialized. + * Otherwise, there can be conflicts with existing ASL code that actually + * uses sync levels. + */ + walk_state->method_desc->method.sync_level = 0; + walk_state->method_desc->method.info_flags |= + (ACPI_METHOD_SERIALIZED | ACPI_METHOD_IGNORE_SYNC_LEVEL); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Method serialized [%4.4s] %p - [%s] (%4.4X)\n", + walk_state->method_node->name.ascii, + walk_state->method_node, walk_state->op_info->name, + walk_state->opcode)); + + /* Abort the parse, no need to examine this method any further */ + + return (AE_CTRL_TERMINATE); +} + +/******************************************************************************* + * * FUNCTION: acpi_ds_method_error * - * PARAMETERS: Status - Execution status + * PARAMETERS: status - Execution status * walk_state - Current state * * RETURN: Status @@ -74,7 +213,7 @@ acpi_ds_create_method_mutex(union acpi_operand_object *method_desc); ******************************************************************************/ acpi_status -acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state) +acpi_ds_method_error(acpi_status status, struct acpi_walk_state * walk_state) { ACPI_FUNCTION_ENTRY(); @@ -151,6 +290,7 @@ acpi_ds_create_method_mutex(union acpi_operand_object *method_desc) status = acpi_os_create_mutex(&mutex_desc->mutex.os_mutex); if (ACPI_FAILURE(status)) { + acpi_ut_delete_object_desc(mutex_desc); return_ACPI_STATUS(status); } @@ -170,7 +310,7 @@ acpi_ds_create_method_mutex(union acpi_operand_object *method_desc) * * RETURN: Status * - * DESCRIPTION: Prepare a method for execution. Parses the method if necessary, + * DESCRIPTION: Prepare a method for execution. Parses the method if necessary, * increments the thread count, and waits at the method semaphore * for clearance to execute. * @@ -216,13 +356,19 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, /* * The current_sync_level (per-thread) must be less than or equal to * the sync level of the method. This mechanism provides some - * deadlock prevention + * deadlock prevention. + * + * If the method was auto-serialized, we just ignore the sync level + * mechanism, because auto-serialization of methods can interfere + * with ASL code that actually uses sync levels. * * Top-level method invocation has no walk state at this point */ if (walk_state && - (walk_state->thread->current_sync_level > - obj_desc->method.mutex->mutex.sync_level)) { + (!(obj_desc->method. + info_flags & ACPI_METHOD_IGNORE_SYNC_LEVEL)) + && (walk_state->thread->current_sync_level > + obj_desc->method.mutex->mutex.sync_level)) { ACPI_ERROR((AE_INFO, "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%u)", acpi_ut_get_node_name(method_node), @@ -291,9 +437,10 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, * reentered one more time (even if it is the same thread) */ obj_desc->method.thread_count++; + acpi_method_count++; return_ACPI_STATUS(status); - cleanup: +cleanup: /* On error, must release the method mutex (if present) */ if (obj_desc->method.mutex) { @@ -306,9 +453,9 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, * * FUNCTION: acpi_ds_call_control_method * - * PARAMETERS: Thread - Info for this thread + * PARAMETERS: thread - Info for this thread * this_walk_state - Current walk state - * Op - Current Op to be walked + * op - Current Op to be walked * * RETURN: Status * @@ -378,7 +525,8 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, */ info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); if (!info) { - return_ACPI_STATUS(AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto cleanup; } info->parameters = &this_walk_state->operands[0]; @@ -422,7 +570,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, return_ACPI_STATUS(status); - cleanup: +cleanup: /* On error, we must terminate the method properly */ @@ -444,7 +592,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, * RETURN: Status * * DESCRIPTION: Restart a method that was preempted by another (nested) method - * invocation. Handle the return value (if any) from the callee. + * invocation. Handle the return value (if any) from the callee. * ******************************************************************************/ @@ -530,7 +678,7 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, * * RETURN: None * - * DESCRIPTION: Terminate a control method. Delete everything that the method + * DESCRIPTION: Terminate a control method. Delete everything that the method * created, delete all locals and arguments, and delete the parse * tree if requested. * @@ -665,7 +813,8 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, method_desc->method.info_flags &= ~ACPI_METHOD_SERIALIZED_PENDING; method_desc->method.info_flags |= - ACPI_METHOD_SERIALIZED; + (ACPI_METHOD_SERIALIZED | + ACPI_METHOD_IGNORE_SYNC_LEVEL); method_desc->method.sync_level = 0; } diff --git a/drivers/acpi/acpica/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c index b40bd507be5..b67522df01a 100644 --- a/drivers/acpi/acpica/dsmthdat.c +++ b/drivers/acpi/acpica/dsmthdat.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -76,7 +76,7 @@ acpi_ds_method_data_get_type(u16 opcode, * RETURN: Status * * DESCRIPTION: Initialize the data structures that hold the method's arguments - * and locals. The data struct is an array of namespace nodes for + * and locals. The data struct is an array of namespace nodes for * each - this allows ref_of and de_ref_of to work properly for these * special data types. * @@ -129,7 +129,7 @@ void acpi_ds_method_data_init(struct acpi_walk_state *walk_state) * * RETURN: None * - * DESCRIPTION: Delete method locals and arguments. Arguments are only + * DESCRIPTION: Delete method locals and arguments. Arguments are only * deleted if this method was called from another method. * ******************************************************************************/ @@ -177,13 +177,13 @@ void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state) * * FUNCTION: acpi_ds_method_data_init_args * - * PARAMETERS: *Params - Pointer to a parameter list for the method + * PARAMETERS: *params - Pointer to a parameter list for the method * max_param_count - The arg count for this method * walk_state - Current walk state object * * RETURN: Status * - * DESCRIPTION: Initialize arguments for a method. The parameter list is a list + * DESCRIPTION: Initialize arguments for a method. The parameter list is a list * of ACPI operand objects, either null terminated or whose length * is defined by max_param_count. * @@ -232,11 +232,11 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params, * * FUNCTION: acpi_ds_method_data_get_node * - * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or * ACPI_REFCLASS_ARG - * Index - Which Local or Arg whose type to get + * index - Which Local or Arg whose type to get * walk_state - Current walk state object - * Node - Where the node is returned. + * node - Where the node is returned. * * RETURN: Status and node * @@ -285,6 +285,7 @@ acpi_ds_method_data_get_node(u8 type, break; default: + ACPI_ERROR((AE_INFO, "Type %u is invalid", type)); return_ACPI_STATUS(AE_TYPE); } @@ -296,10 +297,10 @@ acpi_ds_method_data_get_node(u8 type, * * FUNCTION: acpi_ds_method_data_set_value * - * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or * ACPI_REFCLASS_ARG - * Index - Which Local or Arg to get - * Object - Object to be inserted into the stack entry + * index - Which Local or Arg to get + * object - Object to be inserted into the stack entry * walk_state - Current walk state object * * RETURN: Status @@ -336,7 +337,7 @@ acpi_ds_method_data_set_value(u8 type, * Increment ref count so object can't be deleted while installed. * NOTE: We do not copy the object in order to preserve the call by * reference semantics of ACPI Control Method invocation. - * (See ACPI Specification 2.0_c) + * (See ACPI Specification 2.0C) */ acpi_ut_add_reference(object); @@ -350,9 +351,9 @@ acpi_ds_method_data_set_value(u8 type, * * FUNCTION: acpi_ds_method_data_get_value * - * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or * ACPI_REFCLASS_ARG - * Index - Which local_var or argument to get + * index - Which localVar or argument to get * walk_state - Current walk state object * dest_desc - Where Arg or Local value is returned * @@ -401,7 +402,7 @@ acpi_ds_method_data_get_value(u8 type, * This means that either 1) The expected argument was * not passed to the method, or 2) A local variable * was referenced by the method (via the ASL) - * before it was initialized. Either case is an error. + * before it was initialized. Either case is an error. */ /* If slack enabled, init the local_x/arg_x to an Integer of value zero */ @@ -428,7 +429,6 @@ acpi_ds_method_data_get_value(u8 type, return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG); case ACPI_REFCLASS_LOCAL: - /* * No error message for this case, will be trapped again later to * detect and ignore cases of Store(local_x,local_x) @@ -458,14 +458,14 @@ acpi_ds_method_data_get_value(u8 type, * * FUNCTION: acpi_ds_method_data_delete_value * - * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or * ACPI_REFCLASS_ARG - * Index - Which local_var or argument to delete + * index - Which localVar or argument to delete * walk_state - Current walk state object * * RETURN: None * - * DESCRIPTION: Delete the entry at Opcode:Index. Inserts + * DESCRIPTION: Delete the entry at Opcode:Index. Inserts * a null into the stack slot after the object is deleted. * ******************************************************************************/ @@ -515,15 +515,15 @@ acpi_ds_method_data_delete_value(u8 type, * * FUNCTION: acpi_ds_store_object_to_local * - * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or + * PARAMETERS: type - Either ACPI_REFCLASS_LOCAL or * ACPI_REFCLASS_ARG - * Index - Which Local or Arg to set + * index - Which Local or Arg to set * obj_desc - Value to be stored * walk_state - Current walk state * * RETURN: Status * - * DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed + * DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed * as the new value for the Arg or Local and the reference count * for obj_desc is incremented. * @@ -566,7 +566,7 @@ acpi_ds_store_object_to_local(u8 type, /* * If the reference count on the object is more than one, we must - * take a copy of the object before we store. A reference count + * take a copy of the object before we store. A reference count * of exactly 1 means that the object was just created during the * evaluation of an expression, and we can safely use it since it * is not used anywhere else. @@ -670,8 +670,8 @@ acpi_ds_store_object_to_local(u8 type, * * FUNCTION: acpi_ds_method_data_get_type * - * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP - * Index - Which Local or Arg whose type to get + * PARAMETERS: opcode - Either AML_LOCAL_OP or AML_ARG_OP + * index - Which Local or Arg whose type to get * walk_state - Current walk state object * * RETURN: Data type of current value of the selected Arg or Local diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c index d7045ca3e32..a1e7e6b6fcf 100644 --- a/drivers/acpi/acpica/dsobject.c +++ b/drivers/acpi/acpica/dsobject.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -64,7 +64,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, * FUNCTION: acpi_ds_build_internal_object * * PARAMETERS: walk_state - Current walk state - * Op - Parser object to be translated + * op - Parser object to be translated * obj_desc_ptr - Where the ACPI internal object is returned * * RETURN: Status @@ -240,7 +240,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); } - exit: +exit: *obj_desc_ptr = obj_desc; return_ACPI_STATUS(status); } @@ -250,7 +250,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, * FUNCTION: acpi_ds_build_internal_buffer_obj * * PARAMETERS: walk_state - Current walk state - * Op - Parser object to be translated + * op - Parser object to be translated * buffer_length - Length of the buffer * obj_desc_ptr - Where the ACPI internal object is returned * @@ -293,7 +293,7 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, /* * Second arg is the buffer data (optional) byte_list can be either - * individual bytes or a string initializer. In either case, a + * individual bytes or a string initializer. In either case, a * byte_list appears in the AML. */ arg = op->common.value.arg; /* skip first arg */ @@ -354,7 +354,7 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, * FUNCTION: acpi_ds_build_internal_package_obj * * PARAMETERS: walk_state - Current walk state - * Op - Parser object to be translated + * op - Parser object to be translated * element_count - Number of elements in the package - this is * the num_elements argument to Package() * obj_desc_ptr - Where the ACPI internal object is returned @@ -388,7 +388,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, union acpi_parse_object *parent; union acpi_operand_object *obj_desc = NULL; acpi_status status = AE_OK; - unsigned i; + u32 i; u16 index; u16 reference_count; @@ -525,7 +525,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, } ACPI_INFO((AE_INFO, - "Actual Package length (%u) is larger than NumElements field (%u), truncated\n", + "Actual Package length (%u) is larger than NumElements field (%u), truncated", i, element_count)); } else if (i < element_count) { /* @@ -547,8 +547,8 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, * FUNCTION: acpi_ds_create_node * * PARAMETERS: walk_state - Current walk state - * Node - NS Node to be initialized - * Op - Parser object to be translated + * node - NS Node to be initialized + * op - Parser object to be translated * * RETURN: Status * @@ -568,7 +568,7 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state, /* * Because of the execution pass through the non-control-method - * parts of the table, we can arrive here twice. Only init + * parts of the table, we can arrive here twice. Only init * the named object node the first time through */ if (acpi_ns_get_attached_object(node)) { @@ -611,14 +611,14 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state, * FUNCTION: acpi_ds_init_object_from_op * * PARAMETERS: walk_state - Current walk state - * Op - Parser op used to init the internal object - * Opcode - AML opcode associated with the object + * op - Parser op used to init the internal object + * opcode - AML opcode associated with the object * ret_obj_desc - Namespace object to be initialized * * RETURN: Status * * DESCRIPTION: Initialize a namespace object from a parser Op and its - * associated arguments. The namespace object is a more compact + * associated arguments. The namespace object is a more compact * representation of the Op and its arguments. * ******************************************************************************/ @@ -648,7 +648,6 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, switch (obj_desc->common.type) { case ACPI_TYPE_BUFFER: - /* * Defer evaluation of Buffer term_arg operand */ @@ -660,7 +659,6 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, break; case ACPI_TYPE_PACKAGE: - /* * Defer evaluation of Package term_arg operand */ @@ -703,7 +701,7 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, /* Truncate value if we are executing from a 32-bit ACPI table */ #ifndef ACPI_NO_METHOD_EXECUTION - acpi_ex_truncate_for32bit_table(obj_desc); + (void)acpi_ex_truncate_for32bit_table(obj_desc); #endif break; @@ -725,12 +723,23 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, case AML_TYPE_LITERAL: obj_desc->integer.value = op->common.value.integer; + #ifndef ACPI_NO_METHOD_EXECUTION - acpi_ex_truncate_for32bit_table(obj_desc); + if (acpi_ex_truncate_for32bit_table(obj_desc)) { + + /* Warn if we found a 64-bit constant in a 32-bit table */ + + ACPI_WARNING((AE_INFO, + "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X", + ACPI_FORMAT_UINT64(op->common. + value.integer), + (u32)obj_desc->integer.value)); + } #endif break; default: + ACPI_ERROR((AE_INFO, "Unknown Integer type 0x%X", op_info->type)); status = AE_AML_OPERAND_TYPE; diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index e5eff758510..6c0759c0db4 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -1,11 +1,11 @@ /****************************************************************************** * - * Module Name: dsopcode - Dispatcher suport for regions and fields + * Module Name: dsopcode - Dispatcher support for regions and fields * *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -257,7 +257,7 @@ acpi_ds_init_buffer_field(u16 aml_opcode, (buffer_desc->common.reference_count + obj_desc->common.reference_count); - cleanup: +cleanup: /* Always delete the operands */ @@ -286,7 +286,7 @@ acpi_ds_init_buffer_field(u16 aml_opcode, * FUNCTION: acpi_ds_eval_buffer_field_operands * * PARAMETERS: walk_state - Current walk - * Op - A valid buffer_field Op object + * op - A valid buffer_field Op object * * RETURN: Status * @@ -370,7 +370,7 @@ acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state, * FUNCTION: acpi_ds_eval_region_operands * * PARAMETERS: walk_state - Current walk - * Op - A valid region Op object + * op - A valid region Op object * * RETURN: Status * @@ -397,7 +397,7 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, */ node = op->common.node; - /* next_op points to the op that holds the space_iD */ + /* next_op points to the op that holds the space_ID */ next_op = op->common.value.arg; @@ -461,7 +461,7 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, * FUNCTION: acpi_ds_eval_table_region_operands * * PARAMETERS: walk_state - Current walk - * Op - A valid region Op object + * op - A valid region Op object * * RETURN: Status * @@ -486,18 +486,18 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op); /* - * This is where we evaluate the signature_string and oem_iDString - * and oem_table_iDString of the data_table_region declaration + * This is where we evaluate the Signature string, oem_id string, + * and oem_table_id string of the Data Table Region declaration */ node = op->common.node; - /* next_op points to signature_string op */ + /* next_op points to Signature string op */ next_op = op->common.value.arg; /* - * Evaluate/create the signature_string and oem_iDString - * and oem_table_iDString operands + * Evaluate/create the Signature string, oem_id string, + * and oem_table_id string operands */ status = acpi_ds_create_operands(walk_state, next_op); if (ACPI_FAILURE(status)) { @@ -505,8 +505,8 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, } /* - * Resolve the signature_string and oem_iDString - * and oem_table_iDString operands + * Resolve the Signature string, oem_id string, + * and oem_table_id string operands */ status = acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS, walk_state); @@ -560,7 +560,7 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, * FUNCTION: acpi_ds_eval_data_object_operands * * PARAMETERS: walk_state - Current walk - * Op - A valid data_object Op object + * op - A valid data_object Op object * obj_desc - data_object * * RETURN: Status @@ -636,6 +636,7 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, break; default: + return_ACPI_STATUS(AE_AML_BAD_OPCODE); } @@ -649,7 +650,8 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) && (op->common.parent->common.aml_opcode != AML_VAR_PACKAGE_OP) - && (op->common.parent->common.aml_opcode != AML_NAME_OP))) { + && (op->common.parent->common.aml_opcode != + AML_NAME_OP))) { walk_state->result_obj = obj_desc; } } @@ -662,7 +664,7 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, * FUNCTION: acpi_ds_eval_bank_field_operands * * PARAMETERS: walk_state - Current walk - * Op - A valid bank_field Op object + * op - A valid bank_field Op object * * RETURN: Status * diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c index 1abcda31037..9f74795e226 100644 --- a/drivers/acpi/acpica/dsutils.c +++ b/drivers/acpi/acpica/dsutils.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,7 +61,7 @@ ACPI_MODULE_NAME("dsutils") * * RETURN: None. * - * DESCRIPTION: Clear and remove a reference on an implicit return value. Used + * 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.) @@ -107,7 +107,7 @@ void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state) * * 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 + * parent method exit. Before storing a new return value, we * delete the previous return value. * ******************************************************************************/ @@ -157,7 +157,7 @@ acpi_ds_do_implicit_return(union acpi_operand_object *return_desc, * * FUNCTION: acpi_ds_is_result_used * - * PARAMETERS: Op - Current Op + * PARAMETERS: op - Current Op * walk_state - Current State * * RETURN: TRUE if result is used, FALSE otherwise @@ -198,7 +198,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, * * 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 + * since each method is parsed separately. A method invoked externally * via execute_control_method has a scope_op as the parent. */ if ((!op->common.parent) || @@ -223,7 +223,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, } /* - * Decide what to do with the result based on the parent. If + * Decide what to do with the result based on the parent. If * the parent opcode will not use the result, delete the object. * Otherwise leave it as is, it will be deleted when it is used * as an operand later. @@ -240,7 +240,6 @@ acpi_ds_is_result_used(union acpi_parse_object * op, case AML_IF_OP: case AML_WHILE_OP: - /* * If we are executing the predicate AND this is the predicate op, * we will use the return value @@ -254,7 +253,9 @@ acpi_ds_is_result_used(union acpi_parse_object * op, break; default: + /* Ignore other control opcodes */ + break; } @@ -263,10 +264,9 @@ acpi_ds_is_result_used(union acpi_parse_object * op, goto result_not_used; case AML_CLASS_CREATE: - /* * These opcodes allow term_arg(s) as operands and therefore - * the operands can be method calls. The result is used. + * the operands can be method calls. The result is used. */ goto result_used; @@ -284,7 +284,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, AML_BANK_FIELD_OP)) { /* * These opcodes allow term_arg(s) as operands and therefore - * the operands can be method calls. The result is used. + * the operands can be method calls. The result is used. */ goto result_used; } @@ -292,7 +292,6 @@ acpi_ds_is_result_used(union acpi_parse_object * op, goto result_not_used; default: - /* * In all other cases. the parent will actually use the return * object, so keep it. @@ -300,7 +299,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, goto result_used; } - result_used: +result_used: ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Result of [%s] used by Parent [%s] Op=%p\n", acpi_ps_get_opcode_name(op->common.aml_opcode), @@ -309,7 +308,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, return_UINT8(TRUE); - result_not_used: +result_not_used: ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Result of [%s] not used by Parent [%s] Op=%p\n", acpi_ps_get_opcode_name(op->common.aml_opcode), @@ -323,15 +322,15 @@ acpi_ds_is_result_used(union acpi_parse_object * op, * * FUNCTION: acpi_ds_delete_result_if_not_used * - * PARAMETERS: Op - Current parse Op + * PARAMETERS: op - Current parse Op * result_obj - Result of the operation * walk_state - Current state * * RETURN: Status * - * DESCRIPTION: Used after interpretation of an opcode. If there is an internal + * DESCRIPTION: Used after interpretation of an opcode. If there is an internal * result descriptor, check if the parent opcode will actually use - * this result. If not, delete the result now so that it will + * this result. If not, delete the result now so that it will * not become orphaned. * ******************************************************************************/ @@ -376,7 +375,7 @@ acpi_ds_delete_result_if_not_used(union acpi_parse_object *op, * * RETURN: Status * - * DESCRIPTION: Resolve all operands to their values. Used to prepare + * DESCRIPTION: Resolve all operands to their values. Used to prepare * arguments to a control method invocation (a call from one * method to another.) * @@ -391,7 +390,7 @@ acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state) /* * Attempt to resolve each of the valid operands - * Method arguments are passed by reference, not by value. This means + * Method arguments are passed by reference, not by value. This means * that the actual objects are passed, not copies of the objects. */ for (i = 0; i < walk_state->num_operands; i++) { @@ -445,13 +444,13 @@ void acpi_ds_clear_operands(struct acpi_walk_state *walk_state) * FUNCTION: acpi_ds_create_operand * * PARAMETERS: walk_state - Current walk state - * Arg - Parse object for the argument + * arg - Parse object for the argument * arg_index - Which argument (zero based) * * RETURN: Status * * DESCRIPTION: Translate a parse tree object that is an argument to an AML - * opcode to the equivalent interpreter object. This may include + * opcode to the equivalent interpreter object. This may include * looking up a name or entering a new name into the internal * namespace. * @@ -496,9 +495,9 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, /* * Special handling for buffer_field declarations. This is a deferred * opcode that unfortunately defines the field name as the last - * parameter instead of the first. We get here when we are performing + * parameter instead of the first. We get here when we are performing * the deferred execution, so the actual name of the field is already - * in the namespace. We don't want to attempt to look it up again + * in the namespace. We don't want to attempt to look it up again * because we may be executing in a different scope than where the * actual opcode exists. */ @@ -560,7 +559,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, * indicate this to the interpreter, set the * object to the root */ - obj_desc = ACPI_CAST_PTR(union + obj_desc = + ACPI_CAST_PTR(union acpi_operand_object, acpi_gbl_root_node); status = AE_OK; @@ -604,8 +604,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, /* * If the name is null, this means that this is an * optional result parameter that was not specified - * in the original ASL. Create a Zero Constant for a - * placeholder. (Store to a constant is a Noop.) + * in the original ASL. Create a Zero Constant for a + * placeholder. (Store to a constant is a Noop.) */ opcode = AML_ZERO_OP; /* Has no arguments! */ @@ -727,32 +727,31 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, index++; } - index--; + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "NumOperands %d, ArgCount %d, Index %d\n", + walk_state->num_operands, arg_count, index)); - /* It is the appropriate order to get objects from the Result stack */ + /* Create the interpreter arguments, in reverse order */ + index--; for (i = 0; i < arg_count; i++) { arg = arguments[index]; - - /* Force the filling of the operand stack in inverse order */ - - walk_state->operand_index = (u8) index; + walk_state->operand_index = (u8)index; status = acpi_ds_create_operand(walk_state, arg, index); if (ACPI_FAILURE(status)) { goto cleanup; } - index--; - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Arg #%u (%p) done, Arg1=%p\n", index, arg, - first_arg)); + "Created Arg #%u (%p) %u args total\n", + index, arg, arg_count)); + index--; } return_ACPI_STATUS(status); - cleanup: +cleanup: /* * We must undo everything done above; meaning that we must * pop everything off of the operand stack and delete those @@ -851,7 +850,7 @@ acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state) goto exit; } - push_result: +push_result: walk_state->result_obj = new_obj_desc; @@ -863,7 +862,7 @@ acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state) op->common.flags |= ACPI_PARSEOP_IN_STACK; } - exit: +exit: return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c index 642f3c053e8..f7f5107e754 100644 --- a/drivers/acpi/acpica/dswexec.c +++ b/drivers/acpi/acpica/dswexec.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,7 +57,7 @@ ACPI_MODULE_NAME("dswexec") /* * Dispatch table for opcode classes */ -static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch[] = { +static acpi_execute_op acpi_gbl_op_type_dispatch[] = { acpi_ex_opcode_0A_0T_1R, acpi_ex_opcode_1A_0T_0R, acpi_ex_opcode_1A_0T_1R, @@ -149,7 +149,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, /* Truncate the predicate to 32-bits if necessary */ - acpi_ex_truncate_for32bit_table(local_obj_desc); + (void)acpi_ex_truncate_for32bit_table(local_obj_desc); /* * Save the result of the predicate evaluation on @@ -170,7 +170,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, (void)acpi_ds_do_implicit_return(local_obj_desc, walk_state, TRUE); - cleanup: +cleanup: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n", walk_state->control_state->common.value, @@ -204,7 +204,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, * RETURN: Status * * DESCRIPTION: Descending callback used during the execution of control - * methods. This is where most operators and operands are + * methods. This is where most operators and operands are * dispatched to the interpreter. * ****************************************************************************/ @@ -297,7 +297,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, if (walk_state->walk_type & ACPI_WALK_METHOD) { /* * Found a named object declaration during method execution; - * we must enter this object into the namespace. The created + * we must enter this object into the namespace. The created * object is temporary and will be deleted upon completion of * the execution of this method. * @@ -327,6 +327,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, break; default: + break; } @@ -334,7 +335,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); - error_exit: +error_exit: status = acpi_ds_method_error(status, walk_state); return_ACPI_STATUS(status); } @@ -348,7 +349,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, * RETURN: Status * * DESCRIPTION: Ascending callback used during the execution of control - * methods. The only thing we really need to do here is to + * methods. The only thing we really need to do here is to * notice the beginning of IF, ELSE, and WHILE blocks. * ****************************************************************************/ @@ -432,7 +433,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) if (ACPI_SUCCESS(status)) { /* * Dispatch the request to the appropriate interpreter handler - * routine. There is one routine per opcode "type" based upon the + * routine. There is one routine per opcode "type" based upon the * number of opcode arguments and return type. */ status = @@ -488,7 +489,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) 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 @@ -582,7 +582,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) switch (op->common.parent->common.aml_opcode) { case AML_NAME_OP: - /* * Put the Node on the object stack (Contains the ACPI Name * of this object) @@ -693,7 +692,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) default: ACPI_ERROR((AE_INFO, - "Unimplemented opcode, class=0x%X type=0x%X Opcode=-0x%X Op=%p", + "Unimplemented opcode, class=0x%X type=0x%X Opcode=0x%X Op=%p", op_class, op_type, op->common.aml_opcode, op)); @@ -706,7 +705,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) * ACPI 2.0 support for 64-bit integers: Truncate numeric * result value if we are executing from a 32-bit ACPI table */ - acpi_ex_truncate_for32bit_table(walk_state->result_obj); + (void)acpi_ex_truncate_for32bit_table(walk_state->result_obj); /* * Check if we just completed the evaluation of a @@ -723,7 +722,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) walk_state->result_obj = NULL; } - cleanup: +cleanup: if (walk_state->result_obj) { diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index 552aa3a50c8..15623da2620 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -50,7 +50,7 @@ #include "acnamesp.h" #ifdef ACPI_ASL_COMPILER -#include <acpi/acdisasm.h> +#include "acdisasm.h" #endif #define _COMPONENT ACPI_DISPATCHER @@ -73,7 +73,20 @@ acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) { switch (pass_number) { + case 0: + + /* Parse only - caller will setup callbacks */ + + walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | + ACPI_PARSE_DELETE_TREE | ACPI_PARSE_DISASSEMBLE; + walk_state->descending_callback = NULL; + walk_state->ascending_callback = NULL; + break; + case 1: + + /* Load pass 1 */ + walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE; walk_state->descending_callback = acpi_ds_load1_begin_op; @@ -81,6 +94,9 @@ acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) break; case 2: + + /* Load pass 2 */ + walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE; walk_state->descending_callback = acpi_ds_load2_begin_op; @@ -88,6 +104,9 @@ acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) break; case 3: + + /* Execution pass */ + #ifndef ACPI_NO_METHOD_EXECUTION walk_state->parse_flags |= ACPI_PARSE_EXECUTE | ACPI_PARSE_DELETE_TREE; @@ -97,6 +116,7 @@ acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) break; default: + return (AE_BAD_PARAMETER); } @@ -161,7 +181,6 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, switch (walk_state->opcode) { case AML_SCOPE_OP: - /* * The target name of the Scope() operator must exist at this point so * that we can actually open the scope to enter new names underneath it. @@ -178,7 +197,8 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, * Target of Scope() not found. Generate an External for it, and * insert the name into the namespace. */ - acpi_dm_add_to_external_list(path, ACPI_TYPE_DEVICE, 0); + acpi_dm_add_op_to_external_list(op, path, + ACPI_TYPE_DEVICE, 0, 0); status = acpi_ns_lookup(walk_state->scope_info, path, object_type, ACPI_IMODE_LOAD_PASS1, @@ -209,7 +229,6 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: - /* * These types we will allow, but we will change the type. * This enables some existing code of the form: @@ -230,6 +249,19 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, walk_state->scope_info->common.value = ACPI_TYPE_ANY; break; + case ACPI_TYPE_METHOD: + /* + * Allow scope change to root during execution of module-level + * code. Root is typed METHOD during this time. + */ + if ((node == acpi_gbl_root_node) && + (walk_state-> + parse_flags & ACPI_PARSE_MODULE_LEVEL)) { + break; + } + + /*lint -fallthrough */ + default: /* All other types are an error */ diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c index ae714772476..2ac28d29730 100644 --- a/drivers/acpi/acpica/dswload2.c +++ b/drivers/acpi/acpica/dswload2.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -222,7 +222,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, */ ACPI_WARNING((AE_INFO, "Type override - [%4.4s] had invalid type (%s) " - "for Scope operator, changed to type ANY\n", + "for Scope operator, changed to type ANY", acpi_ut_get_node_name(node), acpi_ut_get_type_name(node->type))); @@ -230,6 +230,20 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, walk_state->scope_info->common.value = ACPI_TYPE_ANY; break; + case ACPI_TYPE_METHOD: + + /* + * Allow scope change to root during execution of module-level + * code. Root is typed METHOD during this time. + */ + if ((node == acpi_gbl_root_node) && + (walk_state-> + parse_flags & ACPI_PARSE_MODULE_LEVEL)) { + break; + } + + /*lint -fallthrough */ + default: /* All other types are an error */ @@ -240,7 +254,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, acpi_ut_get_type_name(node->type), acpi_ut_get_node_name(node))); - return (AE_AML_OPERAND_TYPE); + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } break; @@ -495,6 +509,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) break; default: + /* All NAMED_FIELD opcodes must be handled above */ break; } @@ -534,6 +549,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) break; default: + /* Unknown opcode */ status = AE_OK; @@ -588,7 +604,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) region_space, walk_state); if (ACPI_FAILURE(status)) { - return (status); + return_ACPI_STATUS(status); } acpi_ex_exit_interpreter(); @@ -660,6 +676,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) #endif /* ACPI_NO_METHOD_EXECUTION */ default: + /* All NAMED_COMPLEX opcodes must be handled above */ break; } @@ -707,10 +724,11 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) break; default: + break; } - cleanup: +cleanup: /* Remove the Node pushed at the very beginning */ diff --git a/drivers/acpi/acpica/dswscope.c b/drivers/acpi/acpica/dswscope.c index 9e9490a9cbf..9d6e2c1de1f 100644 --- a/drivers/acpi/acpica/dswscope.c +++ b/drivers/acpi/acpica/dswscope.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -85,8 +85,8 @@ void acpi_ds_scope_stack_clear(struct acpi_walk_state *walk_state) * * FUNCTION: acpi_ds_scope_stack_push * - * PARAMETERS: Node - Name to be made current - * Type - Type of frame being pushed + * PARAMETERS: node - Name to be made current + * type - Type of frame being pushed * walk_state - Current state * * RETURN: Status diff --git a/drivers/acpi/acpica/dswstate.c b/drivers/acpi/acpica/dswstate.c index c9c2ac13e7c..24f7d5ea678 100644 --- a/drivers/acpi/acpica/dswstate.c +++ b/drivers/acpi/acpica/dswstate.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,14 +51,15 @@ ACPI_MODULE_NAME("dswstate") /* Local prototypes */ -static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *ws); -static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *ws); +static acpi_status +acpi_ds_result_stack_push(struct acpi_walk_state *walk_state); +static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state); /******************************************************************************* * * FUNCTION: acpi_ds_result_pop * - * PARAMETERS: Object - Where to return the popped object + * PARAMETERS: object - Where to return the popped object * walk_state - Current Walk state * * RETURN: Status @@ -132,7 +133,7 @@ acpi_ds_result_pop(union acpi_operand_object **object, * * FUNCTION: acpi_ds_result_push * - * PARAMETERS: Object - Where to return the popped object + * PARAMETERS: object - Where to return the popped object * walk_state - Current Walk state * * RETURN: Status @@ -296,7 +297,7 @@ static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state) * * FUNCTION: acpi_ds_obj_stack_push * - * PARAMETERS: Object - Object to push + * PARAMETERS: object - Object to push * walk_state - Current Walk state * * RETURN: Status @@ -347,7 +348,7 @@ acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state) * * RETURN: Status * - * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT + * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT * deleted by this routine. * ******************************************************************************/ @@ -433,7 +434,7 @@ acpi_ds_obj_stack_pop_and_delete(u32 pop_count, * * FUNCTION: acpi_ds_get_current_walk_state * - * PARAMETERS: Thread - Get current active state for this Thread + * PARAMETERS: thread - Get current active state for this Thread * * RETURN: Pointer to the current walk state * @@ -462,7 +463,7 @@ struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state * FUNCTION: acpi_ds_push_walk_state * * PARAMETERS: walk_state - State to push - * Thread - Thread state object + * thread - Thread state object * * RETURN: None * @@ -486,12 +487,12 @@ acpi_ds_push_walk_state(struct acpi_walk_state *walk_state, * * FUNCTION: acpi_ds_pop_walk_state * - * PARAMETERS: Thread - Current thread state + * PARAMETERS: thread - Current thread state * * RETURN: A walk_state object popped from the thread's stack * * DESCRIPTION: Remove and return the walkstate object that is at the head of - * the walk stack for the given walk list. NULL indicates that + * the walk stack for the given walk list. NULL indicates that * the list is empty. * ******************************************************************************/ @@ -525,20 +526,23 @@ struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread) * FUNCTION: acpi_ds_create_walk_state * * PARAMETERS: owner_id - ID for object creation - * Origin - Starting point for this walk + * origin - Starting point for this walk * method_desc - Method object - * Thread - Current thread state + * thread - Current thread state * * RETURN: Pointer to the new walk state. * - * DESCRIPTION: Allocate and initialize a new walk state. The current walk + * DESCRIPTION: Allocate and initialize a new walk state. The current walk * state is set to this new state. * ******************************************************************************/ -struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_parse_object - *origin, union acpi_operand_object - *method_desc, struct acpi_thread_state +struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, + union acpi_parse_object + *origin, + union acpi_operand_object + *method_desc, + struct acpi_thread_state *thread) { struct acpi_walk_state *walk_state; @@ -578,11 +582,11 @@ struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union * FUNCTION: acpi_ds_init_aml_walk * * PARAMETERS: walk_state - New state to be initialized - * Op - Current parse op + * op - Current parse op * method_node - Control method NS node, if any * aml_start - Start of AML * aml_length - Length of AML - * Info - Method info block (params, etc.) + * info - Method info block (params, etc.) * pass_number - 1, 2, or 3 * * RETURN: Status @@ -653,7 +657,7 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state, /* * Setup the current scope. * Find a Named Op that has a namespace node associated with it. - * search upwards from this Op. Current scope is the first + * search upwards from this Op. Current scope is the first * Op with a namespace node. */ extra_op = parser_state->start_op; @@ -704,13 +708,13 @@ void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state) ACPI_FUNCTION_TRACE_PTR(ds_delete_walk_state, walk_state); if (!walk_state) { - return; + return_VOID; } if (walk_state->descriptor_type != ACPI_DESC_TYPE_WALK) { ACPI_ERROR((AE_INFO, "%p is not a valid walk state", walk_state)); - return; + return_VOID; } /* There should not be any open scopes */ diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c index 6729ebe2f1e..c7bffff9ed3 100644 --- a/drivers/acpi/acpica/evevent.c +++ b/drivers/acpi/acpica/evevent.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,7 +47,7 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evevent") - +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /* Local prototypes */ static acpi_status acpi_ev_fixed_event_initialize(void); @@ -251,12 +251,14 @@ u32 acpi_ev_fixed_event_detect(void) * * FUNCTION: acpi_ev_fixed_event_dispatch * - * PARAMETERS: Event - Event type + * PARAMETERS: event - Event type * * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED * * DESCRIPTION: Clears the status bit for the requested event, calls the * handler that previously registered for the event. + * NOTE: If there is no handler for the event, the event is + * disabled to prevent further interrupts. * ******************************************************************************/ @@ -271,17 +273,17 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event) status_register_id, ACPI_CLEAR_STATUS); /* - * Make sure we've got a handler. If not, report an error. The event is - * disabled to prevent further interrupts. + * Make sure that a handler exists. If not, report an error + * and disable the event to prevent further interrupts. */ - if (NULL == acpi_gbl_fixed_event_handlers[event].handler) { + if (!acpi_gbl_fixed_event_handlers[event].handler) { (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. enable_register_id, ACPI_DISABLE_EVENT); ACPI_ERROR((AE_INFO, - "No installed handler for fixed event [0x%08X]", - event)); + "No installed handler for fixed event - %s (%u), disabling", + acpi_ut_get_event_name(event), event)); return (ACPI_INTERRUPT_NOT_HANDLED); } @@ -291,3 +293,5 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event) return ((acpi_gbl_fixed_event_handlers[event]. handler) (acpi_gbl_fixed_event_handlers[event].context)); } + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/evglock.c b/drivers/acpi/acpica/evglock.c index 5e5683cb1f0..3393a73ca0d 100644 --- a/drivers/acpi/acpica/evglock.c +++ b/drivers/acpi/acpica/evglock.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,7 +48,7 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evglock") - +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /* Local prototypes */ static u32 acpi_ev_global_lock_handler(void *context); @@ -128,6 +128,7 @@ acpi_status acpi_ev_remove_global_lock_handler(void) status = acpi_remove_fixed_event_handler(ACPI_EVENT_GLOBAL, acpi_ev_global_lock_handler); + acpi_os_delete_lock(acpi_gbl_global_lock_pending_lock); return_ACPI_STATUS(status); } @@ -135,7 +136,7 @@ acpi_status acpi_ev_remove_global_lock_handler(void) * * FUNCTION: acpi_ev_global_lock_handler * - * PARAMETERS: Context - From thread interface, not used + * PARAMETERS: context - From thread interface, not used * * RETURN: ACPI_INTERRUPT_HANDLED * @@ -172,7 +173,7 @@ static u32 acpi_ev_global_lock_handler(void *context) acpi_gbl_global_lock_pending = FALSE; - cleanup_and_exit: +cleanup_and_exit: acpi_os_release_lock(acpi_gbl_global_lock_pending_lock, flags); return (ACPI_INTERRUPT_HANDLED); @@ -182,7 +183,7 @@ static u32 acpi_ev_global_lock_handler(void *context) * * FUNCTION: acpi_ev_acquire_global_lock * - * PARAMETERS: Timeout - Max time to wait for the lock, in millisec. + * PARAMETERS: timeout - Max time to wait for the lock, in millisec. * * RETURN: Status * @@ -339,3 +340,5 @@ acpi_status acpi_ev_release_global_lock(void) acpi_os_release_mutex(acpi_gbl_global_lock_mutex->mutex.os_mutex); return_ACPI_STATUS(status); } + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index 9e88cb6fb25..48f70013b48 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,7 +48,7 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evgpe") - +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /* Local prototypes */ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context); @@ -80,8 +80,7 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info) return_ACPI_STATUS(AE_NOT_EXIST); } - register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info, - gpe_register_info); + register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); /* Clear the run bit up front */ @@ -90,7 +89,8 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info) /* Set the mask bit only if there are references to this GPE */ if (gpe_event_info->runtime_count) { - ACPI_SET_BIT(gpe_register_info->enable_for_run, (u8)register_bit); + ACPI_SET_BIT(gpe_register_info->enable_for_run, + (u8)register_bit); } return_ACPI_STATUS(AE_OK); @@ -107,8 +107,7 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info) * DESCRIPTION: Clear a GPE of stale events and enable it. * ******************************************************************************/ -acpi_status -acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) +acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) { acpi_status status; @@ -132,8 +131,8 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) } /* Enable the requested GPE */ - status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE); + status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE); return_ACPI_STATUS(status); } @@ -151,7 +150,8 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) * ******************************************************************************/ -acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info) +acpi_status +acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info) { acpi_status status = AE_OK; @@ -192,7 +192,8 @@ acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info * ******************************************************************************/ -acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info) +acpi_status +acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info) { acpi_status status = AE_OK; @@ -209,7 +210,8 @@ acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_i status = acpi_ev_update_gpe_enable_mask(gpe_event_info); if (ACPI_SUCCESS(status)) { - status = acpi_hw_low_set_gpe(gpe_event_info, + status = + acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); } @@ -307,7 +309,8 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, /* A Non-NULL gpe_device means this is a GPE Block Device */ - obj_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *) + obj_desc = + acpi_ns_get_attached_object((struct acpi_namespace_node *) gpe_device); if (!obj_desc || !obj_desc->device.gpe_block) { return (NULL); @@ -379,6 +382,18 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) */ if (!(gpe_register_info->enable_for_run | gpe_register_info->enable_for_wake)) { + ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS, + "Ignore disabled registers for GPE %02X-%02X: " + "RunEnable=%02X, WakeEnable=%02X\n", + gpe_register_info-> + base_gpe_number, + gpe_register_info-> + base_gpe_number + + (ACPI_GPE_REGISTER_WIDTH - 1), + gpe_register_info-> + enable_for_run, + gpe_register_info-> + enable_for_wake)); continue; } @@ -401,9 +416,14 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) } ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS, - "Read GPE Register at GPE%02X: Status=%02X, Enable=%02X\n", + "Read registers for GPE %02X-%02X: Status=%02X, Enable=%02X, " + "RunEnable=%02X, WakeEnable=%02X\n", gpe_register_info->base_gpe_number, - status_reg, enable_reg)); + gpe_register_info->base_gpe_number + + (ACPI_GPE_REGISTER_WIDTH - 1), + status_reg, enable_reg, + gpe_register_info->enable_for_run, + gpe_register_info->enable_for_wake)); /* Check if there is anything active at all in this register */ @@ -438,7 +458,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) gpe_block = gpe_block->next; } - unlock_and_exit: +unlock_and_exit: acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return (int_status); @@ -466,7 +486,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) acpi_status status; struct acpi_gpe_event_info *local_gpe_event_info; struct acpi_evaluate_info *info; - struct acpi_gpe_notify_object *notify_object; + struct acpi_gpe_notify_info *notify; ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method); @@ -502,6 +522,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { + ACPI_FREE(local_gpe_event_info); return_VOID; } @@ -509,7 +530,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) switch (local_gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) { case ACPI_GPE_DISPATCH_NOTIFY: - /* * Implicit notify. * Dispatch a DEVICE_WAKE notify to the appropriate handler. @@ -517,17 +537,17 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) * completes. The notify handlers are NOT invoked synchronously * from this thread -- because handlers may in turn run other * control methods. + * + * June 2012: Expand implicit notify mechanism to support + * notifies on multiple device objects. */ - status = acpi_ev_queue_notify_request( - local_gpe_event_info->dispatch.device.node, - ACPI_NOTIFY_DEVICE_WAKE); - - notify_object = local_gpe_event_info->dispatch.device.next; - while (ACPI_SUCCESS(status) && notify_object) { - status = acpi_ev_queue_notify_request( - notify_object->node, - ACPI_NOTIFY_DEVICE_WAKE); - notify_object = notify_object->next; + notify = local_gpe_event_info->dispatch.notify_list; + while (ACPI_SUCCESS(status) && notify) { + status = + acpi_ev_queue_notify_request(notify->device_node, + ACPI_NOTIFY_DEVICE_WAKE); + + notify = notify->next; } break; @@ -541,8 +561,8 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) status = AE_NO_MEMORY; } else { /* - * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx - * control method that corresponds to this GPE + * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the + * _Lxx/_Exx control method that corresponds to this GPE */ info->prefix_node = local_gpe_event_info->dispatch.method_node; @@ -559,11 +579,11 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) (local_gpe_event_info->dispatch. method_node))); } - break; default: - return_VOID; /* Should never happen */ + + return_VOID; /* Should never happen */ } /* Defer enabling of GPE until all notify handlers are done */ @@ -686,7 +706,8 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, status = acpi_hw_clear_gpe(gpe_event_info); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, - "Unable to clear GPE%02X", gpe_number)); + "Unable to clear GPE %02X", + gpe_number)); return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); } } @@ -703,7 +724,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, - "Unable to disable GPE%02X", gpe_number)); + "Unable to disable GPE %02X", gpe_number)); return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); } @@ -735,7 +756,6 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, case ACPI_GPE_DISPATCH_METHOD: case ACPI_GPE_DISPATCH_NOTIFY: - /* * Execute the method associated with the GPE * NOTE: Level-triggered GPEs are cleared after the method completes. @@ -745,20 +765,19 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, gpe_event_info); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, - "Unable to queue handler for GPE%2X - event disabled", + "Unable to queue handler for GPE %02X - event disabled", gpe_number)); } break; default: - /* * No handler or method to run! * 03/2010: This case should no longer be possible. We will not allow * a GPE to be enabled if it has no handler or method. */ ACPI_ERROR((AE_INFO, - "No handler or method for GPE%02X, disabling event", + "No handler or method for GPE %02X, disabling event", gpe_number)); break; @@ -766,3 +785,5 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, return_UINT32(ACPI_INTERRUPT_HANDLED); } + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index be75339cd5d..d86699eea33 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,7 +48,7 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evgpeblk") - +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /* Local prototypes */ static acpi_status acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block, @@ -87,9 +87,9 @@ acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block, return_ACPI_STATUS(status); } - gpe_xrupt_block = acpi_ev_get_gpe_xrupt_block(interrupt_number); - if (!gpe_xrupt_block) { - status = AE_NO_MEMORY; + status = + acpi_ev_get_gpe_xrupt_block(interrupt_number, &gpe_xrupt_block); + if (ACPI_FAILURE(status)) { goto unlock_and_exit; } @@ -111,8 +111,8 @@ acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block, gpe_block->xrupt_block = gpe_xrupt_block; acpi_os_release_lock(acpi_gbl_gpe_lock, flags); - unlock_and_exit: - status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); +unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } @@ -178,7 +178,7 @@ acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block) ACPI_FREE(gpe_block->event_info); ACPI_FREE(gpe_block); - unlock_and_exit: +unlock_and_exit: status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } @@ -252,21 +252,17 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) /* Init the register_info for this GPE register (8 GPEs) */ - this_register->base_gpe_number = - (u8) (gpe_block->block_base_number + - (i * ACPI_GPE_REGISTER_WIDTH)); + this_register->base_gpe_number = (u16) + (gpe_block->block_base_number + + (i * ACPI_GPE_REGISTER_WIDTH)); - this_register->status_address.address = - gpe_block->block_address.address + i; + this_register->status_address.address = gpe_block->address + i; this_register->enable_address.address = - gpe_block->block_address.address + i + - gpe_block->register_count; + gpe_block->address + i + gpe_block->register_count; - this_register->status_address.space_id = - gpe_block->block_address.space_id; - this_register->enable_address.space_id = - gpe_block->block_address.space_id; + this_register->status_address.space_id = gpe_block->space_id; + this_register->enable_address.space_id = gpe_block->space_id; this_register->status_address.bit_width = ACPI_GPE_REGISTER_WIDTH; this_register->enable_address.bit_width = @@ -302,7 +298,7 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) return_ACPI_STATUS(AE_OK); - error_exit: +error_exit: if (gpe_register_info) { ACPI_FREE(gpe_register_info); } @@ -318,7 +314,7 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) * FUNCTION: acpi_ev_create_gpe_block * * PARAMETERS: gpe_device - Handle to the parent GPE block - * gpe_block_address - Address and space_iD + * gpe_block_address - Address and space_ID * register_count - Number of GPE register pairs in the block * gpe_block_base_number - Starting GPE number for the block * interrupt_number - H/W interrupt for the block @@ -334,9 +330,10 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) acpi_status acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, - struct acpi_generic_address *gpe_block_address, + u64 address, + u8 space_id, u32 register_count, - u8 gpe_block_base_number, + u16 gpe_block_base_number, u32 interrupt_number, struct acpi_gpe_block_info **return_gpe_block) { @@ -359,15 +356,14 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, /* Initialize the new GPE block */ + gpe_block->address = address; + gpe_block->space_id = space_id; gpe_block->node = gpe_device; gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH); gpe_block->initialized = FALSE; gpe_block->register_count = register_count; gpe_block->block_base_number = gpe_block_base_number; - ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address, - sizeof(struct acpi_generic_address)); - /* * Create the register_info and event_info sub-structures * Note: disables and clears all GPEs in the block @@ -382,6 +378,8 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, status = acpi_ev_install_gpe_block(gpe_block, interrupt_number); if (ACPI_FAILURE(status)) { + ACPI_FREE(gpe_block->register_info); + ACPI_FREE(gpe_block->event_info); ACPI_FREE(gpe_block); return_ACPI_STATUS(status); } @@ -405,13 +403,15 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, (*return_gpe_block) = gpe_block; } - ACPI_DEBUG_PRINT((ACPI_DB_INIT, - "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n", - (u32) gpe_block->block_base_number, - (u32) (gpe_block->block_base_number + - (gpe_block->gpe_count - 1)), - gpe_device->name.ascii, gpe_block->register_count, - interrupt_number)); + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, + " Initialized GPE %02X to %02X [%4.4s] %u regs on interrupt 0x%X%s\n", + (u32)gpe_block->block_base_number, + (u32)(gpe_block->block_base_number + + (gpe_block->gpe_count - 1)), + gpe_device->name.ascii, gpe_block->register_count, + interrupt_number, + interrupt_number == + acpi_gbl_FADT.sci_interrupt ? " (SCI)" : "")); /* Update global count of currently available GPEs */ @@ -486,7 +486,8 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not enable GPE 0x%02X", - gpe_index + gpe_block->block_base_number)); + gpe_index + + gpe_block->block_base_number)); continue; } @@ -495,12 +496,16 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, } if (gpe_enabled_count) { - ACPI_DEBUG_PRINT((ACPI_DB_INIT, - "Enabled %u GPEs in this block\n", - gpe_enabled_count)); + ACPI_INFO((AE_INFO, + "Enabled %u GPEs in block %02X to %02X", + gpe_enabled_count, (u32)gpe_block->block_base_number, + (u32)(gpe_block->block_base_number + + (gpe_block->gpe_count - 1)))); } gpe_block->initialized = TRUE; return_ACPI_STATUS(AE_OK); } + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c index adf7494da9d..49fc7effd96 100644 --- a/drivers/acpi/acpica/evgpeinit.c +++ b/drivers/acpi/acpica/evgpeinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,7 +48,7 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evgpeinit") - +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /* * Note: History of _PRW support in ACPICA * @@ -86,6 +86,9 @@ acpi_status acpi_ev_gpe_initialize(void) ACPI_FUNCTION_TRACE(ev_gpe_initialize); + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, + "Initializing General Purpose Events (GPEs):\n")); + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -122,15 +125,16 @@ acpi_status acpi_ev_gpe_initialize(void) /* GPE block 0 exists (has both length and address > 0) */ register_count0 = (u16)(acpi_gbl_FADT.gpe0_block_length / 2); - gpe_number_max = (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1; /* Install GPE Block 0 */ status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, - &acpi_gbl_FADT.xgpe0_block, - register_count0, 0, + acpi_gbl_FADT.xgpe0_block. + address, + acpi_gbl_FADT.xgpe0_block. + space_id, register_count0, 0, acpi_gbl_FADT.sci_interrupt, &acpi_gbl_gpe_fadt_blocks[0]); @@ -167,8 +171,10 @@ acpi_status acpi_ev_gpe_initialize(void) status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, - &acpi_gbl_FADT.xgpe1_block, - register_count1, + acpi_gbl_FADT.xgpe1_block. + address, + acpi_gbl_FADT.xgpe1_block. + space_id, register_count1, acpi_gbl_FADT.gpe1_base, acpi_gbl_FADT. sci_interrupt, @@ -201,17 +207,7 @@ acpi_status acpi_ev_gpe_initialize(void) goto cleanup; } - /* Check for Max GPE number out-of-range */ - - if (gpe_number_max > ACPI_GPE_MAX) { - ACPI_ERROR((AE_INFO, - "Maximum GPE number from FADT is too large: 0x%X", - gpe_number_max)); - status = AE_BAD_VALUE; - goto cleanup; - } - - cleanup: +cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(AE_OK); } @@ -360,14 +356,17 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle, */ switch (name[1]) { case 'L': + type = ACPI_GPE_LEVEL_TRIGGERED; break; case 'E': + type = ACPI_GPE_EDGE_TRIGGERED; break; default: + /* Unknown method type, just ignore it */ ACPI_DEBUG_PRINT((ACPI_DB_LOAD, @@ -440,3 +439,5 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle, name, gpe_number)); return_ACPI_STATUS(AE_OK); } + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c index 25073932aa1..17e4bbfdb09 100644 --- a/drivers/acpi/acpica/evgpeutil.c +++ b/drivers/acpi/acpica/evgpeutil.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,12 +48,13 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evgpeutil") +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /******************************************************************************* * * FUNCTION: acpi_ev_walk_gpe_list * * PARAMETERS: gpe_walk_callback - Routine called for each GPE block - * Context - Value passed to callback + * context - Value passed to callback * * RETURN: Status * @@ -100,7 +101,7 @@ acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback, void *context) gpe_xrupt_info = gpe_xrupt_info->next; } - unlock_and_exit: +unlock_and_exit: acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } @@ -195,9 +196,10 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, * * FUNCTION: acpi_ev_get_gpe_xrupt_block * - * PARAMETERS: interrupt_number - Interrupt for a GPE block + * PARAMETERS: interrupt_number - Interrupt for a GPE block + * gpe_xrupt_block - Where the block is returned * - * RETURN: A GPE interrupt block + * RETURN: Status * * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt * block per unique interrupt level used for GPEs. Should be @@ -206,7 +208,9 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, * ******************************************************************************/ -struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 interrupt_number) +acpi_status +acpi_ev_get_gpe_xrupt_block(u32 interrupt_number, + struct acpi_gpe_xrupt_info ** gpe_xrupt_block) { struct acpi_gpe_xrupt_info *next_gpe_xrupt; struct acpi_gpe_xrupt_info *gpe_xrupt; @@ -220,7 +224,8 @@ struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 interrupt_number) next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head; while (next_gpe_xrupt) { if (next_gpe_xrupt->interrupt_number == interrupt_number) { - return_PTR(next_gpe_xrupt); + *gpe_xrupt_block = next_gpe_xrupt; + return_ACPI_STATUS(AE_OK); } next_gpe_xrupt = next_gpe_xrupt->next; @@ -230,7 +235,7 @@ struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 interrupt_number) gpe_xrupt = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_xrupt_info)); if (!gpe_xrupt) { - return_PTR(NULL); + return_ACPI_STATUS(AE_NO_MEMORY); } gpe_xrupt->interrupt_number = interrupt_number; @@ -249,6 +254,7 @@ struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 interrupt_number) } else { acpi_gbl_gpe_xrupt_list_head = gpe_xrupt; } + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); /* Install new interrupt handler if not SCI_INT */ @@ -258,14 +264,15 @@ struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 interrupt_number) acpi_ev_gpe_xrupt_handler, gpe_xrupt); if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not install GPE interrupt handler at level 0x%X", - interrupt_number)); - return_PTR(NULL); + ACPI_EXCEPTION((AE_INFO, status, + "Could not install GPE interrupt handler at level 0x%X", + interrupt_number)); + return_ACPI_STATUS(status); } } - return_PTR(gpe_xrupt); + *gpe_xrupt_block = gpe_xrupt; + return_ACPI_STATUS(AE_OK); } /******************************************************************************* @@ -346,6 +353,8 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, void *context) { struct acpi_gpe_event_info *gpe_event_info; + struct acpi_gpe_notify_info *notify; + struct acpi_gpe_notify_info *next; u32 i; u32 j; @@ -364,13 +373,34 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) { + + /* Delete an installed handler block */ + ACPI_FREE(gpe_event_info->dispatch.handler); gpe_event_info->dispatch.handler = NULL; gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; + } else + if ((gpe_event_info-> + flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_NOTIFY) { + + /* Delete the implicit notification device list */ + + notify = gpe_event_info->dispatch.notify_list; + while (notify) { + next = notify->next; + ACPI_FREE(notify); + notify = next; + } + gpe_event_info->dispatch.notify_list = NULL; + gpe_event_info->flags &= + ~ACPI_GPE_DISPATCH_MASK; } } } return_ACPI_STATUS(AE_OK); } + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/evhandler.c b/drivers/acpi/acpica/evhandler.c new file mode 100644 index 00000000000..78ac29351c9 --- /dev/null +++ b/drivers/acpi/acpica/evhandler.c @@ -0,0 +1,536 @@ +/****************************************************************************** + * + * Module Name: evhandler - Support for Address Space handlers + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acevents.h" +#include "acnamesp.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_EVENTS +ACPI_MODULE_NAME("evhandler") + +/* Local prototypes */ +static acpi_status +acpi_ev_install_handler(acpi_handle obj_handle, + u32 level, void *context, void **return_value); + +/* These are the address spaces that will get default handlers */ + +u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = { + ACPI_ADR_SPACE_SYSTEM_MEMORY, + ACPI_ADR_SPACE_SYSTEM_IO, + ACPI_ADR_SPACE_PCI_CONFIG, + ACPI_ADR_SPACE_DATA_TABLE +}; + +/******************************************************************************* + * + * FUNCTION: acpi_ev_install_region_handlers + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Installs the core subsystem default address space handlers. + * + ******************************************************************************/ + +acpi_status acpi_ev_install_region_handlers(void) +{ + acpi_status status; + u32 i; + + ACPI_FUNCTION_TRACE(ev_install_region_handlers); + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * All address spaces (PCI Config, EC, SMBus) are scope dependent and + * registration must occur for a specific device. + * + * In the case of the system memory and IO address spaces there is + * currently no device associated with the address space. For these we + * use the root. + * + * We install the default PCI config space handler at the root so that + * this space is immediately available even though the we have not + * enumerated all the PCI Root Buses yet. This is to conform to the ACPI + * specification which states that the PCI config space must be always + * available -- even though we are nowhere near ready to find the PCI root + * buses at this point. + * + * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler + * has already been installed (via acpi_install_address_space_handler). + * Similar for AE_SAME_HANDLER. + */ + for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { + status = acpi_ev_install_space_handler(acpi_gbl_root_node, + acpi_gbl_default_address_spaces + [i], + ACPI_DEFAULT_HANDLER, + NULL, NULL); + switch (status) { + case AE_OK: + case AE_SAME_HANDLER: + case AE_ALREADY_EXISTS: + + /* These exceptions are all OK */ + + status = AE_OK; + break; + + default: + + goto unlock_and_exit; + } + } + +unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_has_default_handler + * + * PARAMETERS: node - Namespace node for the device + * space_id - The address space ID + * + * RETURN: TRUE if default handler is installed, FALSE otherwise + * + * DESCRIPTION: Check if the default handler is installed for the requested + * space ID. + * + ******************************************************************************/ + +u8 +acpi_ev_has_default_handler(struct acpi_namespace_node *node, + acpi_adr_space_type space_id) +{ + union acpi_operand_object *obj_desc; + union acpi_operand_object *handler_obj; + + /* Must have an existing internal object */ + + obj_desc = acpi_ns_get_attached_object(node); + if (obj_desc) { + handler_obj = obj_desc->device.handler; + + /* Walk the linked list of handlers for this object */ + + while (handler_obj) { + if (handler_obj->address_space.space_id == space_id) { + if (handler_obj->address_space.handler_flags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) { + return (TRUE); + } + } + + handler_obj = handler_obj->address_space.next; + } + } + + return (FALSE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_install_handler + * + * PARAMETERS: walk_namespace callback + * + * DESCRIPTION: This routine installs an address handler into objects that are + * of type Region or Device. + * + * If the Object is a Device, and the device has a handler of + * the same type then the search is terminated in that branch. + * + * This is because the existing handler is closer in proximity + * to any more regions than the one we are trying to install. + * + ******************************************************************************/ + +static acpi_status +acpi_ev_install_handler(acpi_handle obj_handle, + u32 level, void *context, void **return_value) +{ + union acpi_operand_object *handler_obj; + union acpi_operand_object *next_handler_obj; + union acpi_operand_object *obj_desc; + struct acpi_namespace_node *node; + acpi_status status; + + ACPI_FUNCTION_NAME(ev_install_handler); + + handler_obj = (union acpi_operand_object *)context; + + /* Parameter validation */ + + if (!handler_obj) { + return (AE_OK); + } + + /* Convert and validate the device handle */ + + node = acpi_ns_validate_handle(obj_handle); + if (!node) { + return (AE_BAD_PARAMETER); + } + + /* + * We only care about regions and objects that are allowed to have + * address space handlers + */ + if ((node->type != ACPI_TYPE_DEVICE) && + (node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) { + return (AE_OK); + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + + /* No object, just exit */ + + return (AE_OK); + } + + /* Devices are handled different than regions */ + + if (obj_desc->common.type == ACPI_TYPE_DEVICE) { + + /* Check if this Device already has a handler for this address space */ + + next_handler_obj = obj_desc->device.handler; + while (next_handler_obj) { + + /* Found a handler, is it for the same address space? */ + + if (next_handler_obj->address_space.space_id == + handler_obj->address_space.space_id) { + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Found handler for region [%s] in device %p(%p) " + "handler %p\n", + acpi_ut_get_region_name + (handler_obj->address_space. + space_id), obj_desc, + next_handler_obj, + handler_obj)); + + /* + * Since the object we found it on was a device, then it + * means that someone has already installed a handler for + * the branch of the namespace from this device on. Just + * bail out telling the walk routine to not traverse this + * branch. This preserves the scoping rule for handlers. + */ + return (AE_CTRL_DEPTH); + } + + /* Walk the linked list of handlers attached to this device */ + + next_handler_obj = next_handler_obj->address_space.next; + } + + /* + * As long as the device didn't have a handler for this space we + * don't care about it. We just ignore it and proceed. + */ + return (AE_OK); + } + + /* Object is a Region */ + + if (obj_desc->region.space_id != handler_obj->address_space.space_id) { + + /* This region is for a different address space, just ignore it */ + + return (AE_OK); + } + + /* + * Now we have a region and it is for the handler's address space type. + * + * First disconnect region for any previous handler (if any) + */ + acpi_ev_detach_region(obj_desc, FALSE); + + /* Connect the region to the new handler */ + + status = acpi_ev_attach_region(handler_obj, obj_desc, FALSE); + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_install_space_handler + * + * PARAMETERS: node - Namespace node for the device + * space_id - The address space ID + * handler - Address of the handler + * setup - Address of the setup function + * context - Value passed to the handler on each access + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for all op_regions of a given space_id. + * Assumes namespace is locked + * + ******************************************************************************/ + +acpi_status +acpi_ev_install_space_handler(struct acpi_namespace_node * node, + acpi_adr_space_type space_id, + acpi_adr_space_handler handler, + acpi_adr_space_setup setup, void *context) +{ + union acpi_operand_object *obj_desc; + union acpi_operand_object *handler_obj; + acpi_status status; + acpi_object_type type; + u8 flags = 0; + + ACPI_FUNCTION_TRACE(ev_install_space_handler); + + /* + * This registration is valid for only the types below and the root. This + * is where the default handlers get placed. + */ + if ((node->type != ACPI_TYPE_DEVICE) && + (node->type != ACPI_TYPE_PROCESSOR) && + (node->type != ACPI_TYPE_THERMAL) && (node != acpi_gbl_root_node)) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + if (handler == ACPI_DEFAULT_HANDLER) { + flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; + + switch (space_id) { + case ACPI_ADR_SPACE_SYSTEM_MEMORY: + + handler = acpi_ex_system_memory_space_handler; + setup = acpi_ev_system_memory_region_setup; + break; + + case ACPI_ADR_SPACE_SYSTEM_IO: + + handler = acpi_ex_system_io_space_handler; + setup = acpi_ev_io_space_region_setup; + break; + + case ACPI_ADR_SPACE_PCI_CONFIG: + + handler = acpi_ex_pci_config_space_handler; + setup = acpi_ev_pci_config_region_setup; + break; + + case ACPI_ADR_SPACE_CMOS: + + handler = acpi_ex_cmos_space_handler; + setup = acpi_ev_cmos_region_setup; + break; + + case ACPI_ADR_SPACE_PCI_BAR_TARGET: + + handler = acpi_ex_pci_bar_space_handler; + setup = acpi_ev_pci_bar_region_setup; + break; + + case ACPI_ADR_SPACE_DATA_TABLE: + + handler = acpi_ex_data_table_space_handler; + setup = NULL; + break; + + default: + + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + } + + /* If the caller hasn't specified a setup routine, use the default */ + + if (!setup) { + setup = acpi_ev_default_region_setup; + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object(node); + if (obj_desc) { + /* + * The attached device object already exists. Make sure the handler + * is not already installed. + */ + handler_obj = obj_desc->device.handler; + + /* Walk the handler list for this device */ + + while (handler_obj) { + + /* Same space_id indicates a handler already installed */ + + if (handler_obj->address_space.space_id == space_id) { + if (handler_obj->address_space.handler == + handler) { + /* + * It is (relatively) OK to attempt to install the SAME + * handler twice. This can easily happen with the + * PCI_Config space. + */ + status = AE_SAME_HANDLER; + goto unlock_and_exit; + } else { + /* A handler is already installed */ + + status = AE_ALREADY_EXISTS; + } + goto unlock_and_exit; + } + + /* Walk the linked list of handlers */ + + handler_obj = handler_obj->address_space.next; + } + } else { + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Creating object on Device %p while installing handler\n", + node)); + + /* obj_desc does not exist, create one */ + + if (node->type == ACPI_TYPE_ANY) { + type = ACPI_TYPE_DEVICE; + } else { + type = node->type; + } + + obj_desc = acpi_ut_create_internal_object(type); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Init new descriptor */ + + obj_desc->common.type = (u8)type; + + /* Attach the new object to the Node */ + + status = acpi_ns_attach_object(node, obj_desc, type); + + /* Remove local reference to the object */ + + acpi_ut_remove_reference(obj_desc); + + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + } + + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", + acpi_ut_get_region_name(space_id), space_id, + acpi_ut_get_node_name(node), node, obj_desc)); + + /* + * Install the handler + * + * At this point there is no existing handler. Just allocate the object + * for the handler and link it into the list. + */ + handler_obj = + acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_ADDRESS_HANDLER); + if (!handler_obj) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Init handler obj */ + + handler_obj->address_space.space_id = (u8)space_id; + handler_obj->address_space.handler_flags = flags; + handler_obj->address_space.region_list = NULL; + handler_obj->address_space.node = node; + handler_obj->address_space.handler = handler; + handler_obj->address_space.context = context; + handler_obj->address_space.setup = setup; + + /* Install at head of Device.address_space list */ + + handler_obj->address_space.next = obj_desc->device.handler; + + /* + * The Device object is the first reference on the handler_obj. + * Each region that uses the handler adds a reference. + */ + obj_desc->device.handler = handler_obj; + + /* + * Walk the namespace finding all of the regions this + * handler will manage. + * + * Start at the device and search the branch toward + * the leaf nodes until either the leaf is encountered or + * a device is detected that has an address handler of the + * same type. + * + * In either case, back up and search down the remainder + * of the branch + */ + status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, + ACPI_NS_WALK_UNLOCK, + acpi_ev_install_handler, NULL, + handler_obj, NULL); + +unlock_and_exit: + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index 84966f41646..24ea3424981 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -56,7 +56,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context); * * FUNCTION: acpi_ev_is_notify_object * - * PARAMETERS: Node - Node to check + * PARAMETERS: node - Node to check * * RETURN: TRUE if notifies allowed on this object * @@ -78,6 +78,7 @@ u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node) return (TRUE); default: + return (FALSE); } } @@ -86,7 +87,7 @@ u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node) * * FUNCTION: acpi_ev_queue_notify_request * - * PARAMETERS: Node - NS node for the notified object + * PARAMETERS: node - NS node for the notified object * notify_value - Value from the Notify() request * * RETURN: Status @@ -101,99 +102,78 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, u32 notify_value) { union acpi_operand_object *obj_desc; - union acpi_operand_object *handler_obj = NULL; - union acpi_generic_state *notify_info; + union acpi_operand_object *handler_list_head = NULL; + union acpi_generic_state *info; + u8 handler_list_id = 0; acpi_status status = AE_OK; ACPI_FUNCTION_NAME(ev_queue_notify_request); - /* - * For value 3 (Ejection Request), some device method may need to be run. - * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need - * to be run. - * For value 0x80 (Status Change) on the power button or sleep button, - * initiate soft-off or sleep operation? - */ - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Dispatching Notify on [%4.4s] Node %p Value 0x%2.2X (%s)\n", - acpi_ut_get_node_name(node), node, notify_value, - acpi_ut_get_notify_name(notify_value))); + /* Are Notifies allowed on this object? */ - /* Get the notify object attached to the NS Node */ - - obj_desc = acpi_ns_get_attached_object(node); - if (obj_desc) { - - /* We have the notify object, Get the right handler */ - - switch (node->type) { + if (!acpi_ev_is_notify_object(node)) { + return (AE_TYPE); + } - /* Notify allowed only on these types */ + /* Get the correct notify list type (System or Device) */ - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_THERMAL: - case ACPI_TYPE_PROCESSOR: + if (notify_value <= ACPI_MAX_SYS_NOTIFY) { + handler_list_id = ACPI_SYSTEM_HANDLER_LIST; + } else { + handler_list_id = ACPI_DEVICE_HANDLER_LIST; + } - if (notify_value <= ACPI_MAX_SYS_NOTIFY) { - handler_obj = - obj_desc->common_notify.system_notify; - } else { - handler_obj = - obj_desc->common_notify.device_notify; - } - break; + /* Get the notify object attached to the namespace Node */ - default: + obj_desc = acpi_ns_get_attached_object(node); + if (obj_desc) { - /* All other types are not supported */ + /* We have an attached object, Get the correct handler list */ - return (AE_TYPE); - } + handler_list_head = + obj_desc->common_notify.notify_list[handler_list_id]; } /* - * If there is any handler to run, schedule the dispatcher. - * Check for: - * 1) Global system notify handler - * 2) Global device notify handler - * 3) Per-device notify handler + * If there is no notify handler (Global or Local) + * for this object, just ignore the notify */ - if ((acpi_gbl_system_notify.handler && - (notify_value <= ACPI_MAX_SYS_NOTIFY)) || - (acpi_gbl_device_notify.handler && - (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) { - notify_info = acpi_ut_create_generic_state(); - if (!notify_info) { - return (AE_NO_MEMORY); - } + if (!acpi_gbl_global_notify[handler_list_id].handler + && !handler_list_head) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "No notify handler for Notify, ignoring (%4.4s, %X) node %p\n", + acpi_ut_get_node_name(node), notify_value, + node)); - if (!handler_obj) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Executing system notify handler for Notify (%4.4s, %X) " - "node %p\n", - acpi_ut_get_node_name(node), - notify_value, node)); - } + return (AE_OK); + } - notify_info->common.descriptor_type = - ACPI_DESC_TYPE_STATE_NOTIFY; - notify_info->notify.node = node; - notify_info->notify.value = (u16) notify_value; - notify_info->notify.handler_obj = handler_obj; + /* Setup notify info and schedule the notify dispatcher */ - status = - acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch, - notify_info); - if (ACPI_FAILURE(status)) { - acpi_ut_delete_generic_state(notify_info); - } - } else { - /* There is no notify handler (per-device or system) for this device */ + info = acpi_ut_create_generic_state(); + if (!info) { + return (AE_NO_MEMORY); + } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "No notify handler for Notify (%4.4s, %X) node %p\n", - acpi_ut_get_node_name(node), notify_value, - node)); + info->common.descriptor_type = ACPI_DESC_TYPE_STATE_NOTIFY; + + info->notify.node = node; + info->notify.value = (u16)notify_value; + info->notify.handler_list_id = handler_list_id; + info->notify.handler_list_head = handler_list_head; + info->notify.global = &acpi_gbl_global_notify[handler_list_id]; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n", + acpi_ut_get_node_name(node), + acpi_ut_get_type_name(node->type), notify_value, + acpi_ut_get_notify_name(notify_value, ACPI_TYPE_ANY), + node)); + + status = acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch, + info); + if (ACPI_FAILURE(status)) { + acpi_ut_delete_generic_state(info); } return (status); @@ -203,7 +183,7 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, * * FUNCTION: acpi_ev_notify_dispatch * - * PARAMETERS: Context - To be passed to the notify handler + * PARAMETERS: context - To be passed to the notify handler * * RETURN: None. * @@ -214,62 +194,37 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context) { - union acpi_generic_state *notify_info = - (union acpi_generic_state *)context; - acpi_notify_handler global_handler = NULL; - void *global_context = NULL; + union acpi_generic_state *info = (union acpi_generic_state *)context; union acpi_operand_object *handler_obj; ACPI_FUNCTION_ENTRY(); - /* - * We will invoke a global notify handler if installed. This is done - * _before_ we invoke the per-device handler attached to the device. - */ - if (notify_info->notify.value <= ACPI_MAX_SYS_NOTIFY) { - - /* Global system notification handler */ - - if (acpi_gbl_system_notify.handler) { - global_handler = acpi_gbl_system_notify.handler; - global_context = acpi_gbl_system_notify.context; - } - } else { - /* Global driver notification handler */ - - if (acpi_gbl_device_notify.handler) { - global_handler = acpi_gbl_device_notify.handler; - global_context = acpi_gbl_device_notify.context; - } - } + /* Invoke a global notify handler if installed */ - /* Invoke the system handler first, if present */ - - if (global_handler) { - global_handler(notify_info->notify.node, - notify_info->notify.value, global_context); + if (info->notify.global->handler) { + info->notify.global->handler(info->notify.node, + info->notify.value, + info->notify.global->context); } - /* Now invoke the per-device handler, if present */ + /* Now invoke the local notify handler(s) if any are installed */ - handler_obj = notify_info->notify.handler_obj; - if (handler_obj) { - struct acpi_object_notify_handler *notifier; + handler_obj = info->notify.handler_list_head; + while (handler_obj) { + handler_obj->notify.handler(info->notify.node, + info->notify.value, + handler_obj->notify.context); - notifier = &handler_obj->notify; - while (notifier) { - notifier->handler(notify_info->notify.node, - notify_info->notify.value, - notifier->context); - notifier = notifier->next; - } + handler_obj = + handler_obj->notify.next[info->notify.handler_list_id]; } /* All done with the info object */ - acpi_ut_delete_generic_state(notify_info); + acpi_ut_delete_generic_state(info); } +#if (!ACPI_REDUCED_HARDWARE) /****************************************************************************** * * FUNCTION: acpi_ev_terminate @@ -310,18 +265,20 @@ void acpi_ev_terminate(void) status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL); - /* Remove SCI handler */ - - status = acpi_ev_remove_sci_handler(); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, "Could not remove SCI handler")); - } - status = acpi_ev_remove_global_lock_handler(); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "Could not remove Global Lock handler")); } + + acpi_gbl_events_initialized = FALSE; + } + + /* Remove SCI handlers */ + + status = acpi_ev_remove_all_sci_handlers(); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, "Could not remove SCI handler")); } /* Deallocate all handler objects installed within GPE info structs */ @@ -338,3 +295,5 @@ void acpi_ev_terminate(void) } return_VOID; } + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 1b0180a1b79..9957297d158 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -1,11 +1,11 @@ /****************************************************************************** * - * Module Name: evregion - ACPI address_space (op_region) handler dispatch + * Module Name: evregion - Operation Region support * *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -50,146 +50,17 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evregion") +extern u8 acpi_gbl_default_address_spaces[]; + /* Local prototypes */ -static u8 -acpi_ev_has_default_handler(struct acpi_namespace_node *node, - acpi_adr_space_type space_id); -static void acpi_ev_orphan_ec_reg_method(void); +static void +acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node); static acpi_status acpi_ev_reg_run(acpi_handle obj_handle, u32 level, void *context, void **return_value); -static acpi_status -acpi_ev_install_handler(acpi_handle obj_handle, - u32 level, void *context, void **return_value); - -/* These are the address spaces that will get default handlers */ - -#define ACPI_NUM_DEFAULT_SPACES 4 - -static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = { - ACPI_ADR_SPACE_SYSTEM_MEMORY, - ACPI_ADR_SPACE_SYSTEM_IO, - ACPI_ADR_SPACE_PCI_CONFIG, - ACPI_ADR_SPACE_DATA_TABLE -}; - -/******************************************************************************* - * - * FUNCTION: acpi_ev_install_region_handlers - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Installs the core subsystem default address space handlers. - * - ******************************************************************************/ - -acpi_status acpi_ev_install_region_handlers(void) -{ - acpi_status status; - u32 i; - - ACPI_FUNCTION_TRACE(ev_install_region_handlers); - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * All address spaces (PCI Config, EC, SMBus) are scope dependent and - * registration must occur for a specific device. - * - * In the case of the system memory and IO address spaces there is - * currently no device associated with the address space. For these we - * use the root. - * - * We install the default PCI config space handler at the root so that - * this space is immediately available even though the we have not - * enumerated all the PCI Root Buses yet. This is to conform to the ACPI - * specification which states that the PCI config space must be always - * available -- even though we are nowhere near ready to find the PCI root - * buses at this point. - * - * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler - * has already been installed (via acpi_install_address_space_handler). - * Similar for AE_SAME_HANDLER. - */ - for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { - status = acpi_ev_install_space_handler(acpi_gbl_root_node, - acpi_gbl_default_address_spaces - [i], - ACPI_DEFAULT_HANDLER, - NULL, NULL); - switch (status) { - case AE_OK: - case AE_SAME_HANDLER: - case AE_ALREADY_EXISTS: - - /* These exceptions are all OK */ - - status = AE_OK; - break; - - default: - - goto unlock_and_exit; - } - } - - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_has_default_handler - * - * PARAMETERS: Node - Namespace node for the device - * space_id - The address space ID - * - * RETURN: TRUE if default handler is installed, FALSE otherwise - * - * DESCRIPTION: Check if the default handler is installed for the requested - * space ID. - * - ******************************************************************************/ - -static u8 -acpi_ev_has_default_handler(struct acpi_namespace_node *node, - acpi_adr_space_type space_id) -{ - union acpi_operand_object *obj_desc; - union acpi_operand_object *handler_obj; - - /* Must have an existing internal object */ - - obj_desc = acpi_ns_get_attached_object(node); - if (obj_desc) { - handler_obj = obj_desc->device.handler; - - /* Walk the linked list of handlers for this object */ - - while (handler_obj) { - if (handler_obj->address_space.space_id == space_id) { - if (handler_obj->address_space.handler_flags & - ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) { - return (TRUE); - } - } - - handler_obj = handler_obj->address_space.next; - } - } - - return (FALSE); -} - /******************************************************************************* * * FUNCTION: acpi_ev_initialize_op_regions @@ -241,99 +112,14 @@ acpi_status acpi_ev_initialize_op_regions(void) /******************************************************************************* * - * FUNCTION: acpi_ev_execute_reg_method - * - * PARAMETERS: region_obj - Region object - * Function - Passed to _REG: On (1) or Off (0) - * - * RETURN: Status - * - * DESCRIPTION: Execute _REG method for a region - * - ******************************************************************************/ - -acpi_status -acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) -{ - struct acpi_evaluate_info *info; - union acpi_operand_object *args[3]; - union acpi_operand_object *region_obj2; - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_execute_reg_method); - - region_obj2 = acpi_ns_get_secondary_object(region_obj); - if (!region_obj2) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - if (region_obj2->extra.method_REG == NULL) { - return_ACPI_STATUS(AE_OK); - } - - /* Allocate and initialize the evaluation information block */ - - info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); - if (!info) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - info->prefix_node = region_obj2->extra.method_REG; - info->pathname = NULL; - info->parameters = args; - info->flags = ACPI_IGNORE_RETURN_VALUE; - - /* - * The _REG method has two arguments: - * - * Arg0 - Integer: - * Operation region space ID Same value as region_obj->Region.space_id - * - * Arg1 - Integer: - * connection status 1 for connecting the handler, 0 for disconnecting - * the handler (Passed as a parameter) - */ - args[0] = - acpi_ut_create_integer_object((u64) region_obj->region.space_id); - if (!args[0]) { - status = AE_NO_MEMORY; - goto cleanup1; - } - - args[1] = acpi_ut_create_integer_object((u64) function); - if (!args[1]) { - status = AE_NO_MEMORY; - goto cleanup2; - } - - args[2] = NULL; /* Terminate list */ - - /* Execute the method, no return value */ - - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname - (ACPI_TYPE_METHOD, info->prefix_node, NULL)); - - status = acpi_ns_evaluate(info); - acpi_ut_remove_reference(args[1]); - - cleanup2: - acpi_ut_remove_reference(args[0]); - - cleanup1: - ACPI_FREE(info); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * * FUNCTION: acpi_ev_address_space_dispatch * * PARAMETERS: region_obj - Internal region object * field_obj - Corresponding field. Can be NULL. - * Function - Read or Write operation + * function - Read or Write operation * region_offset - Where in the region to read or write * bit_width - Field width in bits (8, 16, 32, or 64) - * Value - Pointer to in or out value, must be + * value - Pointer to in or out value, must be * a full 64-bit integer * * RETURN: Status @@ -431,16 +217,11 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) { region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE; - if (region_obj2->extra.region_context) { - - /* The handler for this region was already installed */ - - ACPI_FREE(region_context); - } else { - /* - * Save the returned context for use in all accesses to - * this particular region - */ + /* + * Save the returned context for use in all accesses to + * the handler for this particular region + */ + if (!(region_obj2->extra.region_context)) { region_obj2->extra.region_context = region_context; } @@ -533,6 +314,7 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, { union acpi_operand_object *handler_obj; union acpi_operand_object *obj_desc; + union acpi_operand_object *start_desc; union acpi_operand_object **last_obj_ptr; acpi_adr_space_setup region_setup; void **region_context; @@ -560,6 +342,7 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, /* Find this region in the handler's list */ obj_desc = handler_obj->address_space.region_list; + start_desc = obj_desc; last_obj_ptr = &handler_obj->address_space.region_list; while (obj_desc) { @@ -616,6 +399,14 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, handler_obj->address_space. context, region_context); + /* + * region_context should have been released by the deactivate + * operation. We don't need access to it anymore here. + */ + if (region_context) { + *region_context = NULL; + } + /* Init routine may fail, Just ignore errors */ if (ACPI_FAILURE(status)) { @@ -649,6 +440,15 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, last_obj_ptr = &obj_desc->region.next; obj_desc = obj_desc->region.next; + + /* Prevent infinite loop if list is corrupted */ + + if (obj_desc == start_desc) { + ACPI_ERROR((AE_INFO, + "Circular handler list in region object %p", + region_obj)); + return_VOID; + } } /* If we get here, the region was not in the handler's region list */ @@ -709,351 +509,86 @@ acpi_ev_attach_region(union acpi_operand_object *handler_obj, /******************************************************************************* * - * FUNCTION: acpi_ev_install_handler - * - * PARAMETERS: walk_namespace callback - * - * DESCRIPTION: This routine installs an address handler into objects that are - * of type Region or Device. - * - * If the Object is a Device, and the device has a handler of - * the same type then the search is terminated in that branch. - * - * This is because the existing handler is closer in proximity - * to any more regions than the one we are trying to install. - * - ******************************************************************************/ - -static acpi_status -acpi_ev_install_handler(acpi_handle obj_handle, - u32 level, void *context, void **return_value) -{ - union acpi_operand_object *handler_obj; - union acpi_operand_object *next_handler_obj; - union acpi_operand_object *obj_desc; - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_NAME(ev_install_handler); - - handler_obj = (union acpi_operand_object *)context; - - /* Parameter validation */ - - if (!handler_obj) { - return (AE_OK); - } - - /* Convert and validate the device handle */ - - node = acpi_ns_validate_handle(obj_handle); - if (!node) { - return (AE_BAD_PARAMETER); - } - - /* - * We only care about regions and objects that are allowed to have - * address space handlers - */ - if ((node->type != ACPI_TYPE_DEVICE) && - (node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) { - return (AE_OK); - } - - /* Check for an existing internal object */ - - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - - /* No object, just exit */ - - return (AE_OK); - } - - /* Devices are handled different than regions */ - - if (obj_desc->common.type == ACPI_TYPE_DEVICE) { - - /* Check if this Device already has a handler for this address space */ - - next_handler_obj = obj_desc->device.handler; - while (next_handler_obj) { - - /* Found a handler, is it for the same address space? */ - - if (next_handler_obj->address_space.space_id == - handler_obj->address_space.space_id) { - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Found handler for region [%s] in device %p(%p) " - "handler %p\n", - acpi_ut_get_region_name - (handler_obj->address_space. - space_id), obj_desc, - next_handler_obj, - handler_obj)); - - /* - * Since the object we found it on was a device, then it - * means that someone has already installed a handler for - * the branch of the namespace from this device on. Just - * bail out telling the walk routine to not traverse this - * branch. This preserves the scoping rule for handlers. - */ - return (AE_CTRL_DEPTH); - } - - /* Walk the linked list of handlers attached to this device */ - - next_handler_obj = next_handler_obj->address_space.next; - } - - /* - * As long as the device didn't have a handler for this space we - * don't care about it. We just ignore it and proceed. - */ - return (AE_OK); - } - - /* Object is a Region */ - - if (obj_desc->region.space_id != handler_obj->address_space.space_id) { - - /* This region is for a different address space, just ignore it */ - - return (AE_OK); - } - - /* - * Now we have a region and it is for the handler's address space type. - * - * First disconnect region for any previous handler (if any) - */ - acpi_ev_detach_region(obj_desc, FALSE); - - /* Connect the region to the new handler */ - - status = acpi_ev_attach_region(handler_obj, obj_desc, FALSE); - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_install_space_handler + * FUNCTION: acpi_ev_execute_reg_method * - * PARAMETERS: Node - Namespace node for the device - * space_id - The address space ID - * Handler - Address of the handler - * Setup - Address of the setup function - * Context - Value passed to the handler on each access + * PARAMETERS: region_obj - Region object + * function - Passed to _REG: On (1) or Off (0) * * RETURN: Status * - * DESCRIPTION: Install a handler for all op_regions of a given space_id. - * Assumes namespace is locked + * DESCRIPTION: Execute _REG method for a region * ******************************************************************************/ acpi_status -acpi_ev_install_space_handler(struct acpi_namespace_node * node, - acpi_adr_space_type space_id, - acpi_adr_space_handler handler, - acpi_adr_space_setup setup, void *context) +acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) { - union acpi_operand_object *obj_desc; - union acpi_operand_object *handler_obj; + struct acpi_evaluate_info *info; + union acpi_operand_object *args[3]; + union acpi_operand_object *region_obj2; acpi_status status; - acpi_object_type type; - u8 flags = 0; - - ACPI_FUNCTION_TRACE(ev_install_space_handler); - /* - * This registration is valid for only the types below and the root. This - * is where the default handlers get placed. - */ - if ((node->type != ACPI_TYPE_DEVICE) && - (node->type != ACPI_TYPE_PROCESSOR) && - (node->type != ACPI_TYPE_THERMAL) && (node != acpi_gbl_root_node)) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } + ACPI_FUNCTION_TRACE(ev_execute_reg_method); - if (handler == ACPI_DEFAULT_HANDLER) { - flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; - - switch (space_id) { - case ACPI_ADR_SPACE_SYSTEM_MEMORY: - handler = acpi_ex_system_memory_space_handler; - setup = acpi_ev_system_memory_region_setup; - break; - - case ACPI_ADR_SPACE_SYSTEM_IO: - handler = acpi_ex_system_io_space_handler; - setup = acpi_ev_io_space_region_setup; - break; - - case ACPI_ADR_SPACE_PCI_CONFIG: - handler = acpi_ex_pci_config_space_handler; - setup = acpi_ev_pci_config_region_setup; - break; - - case ACPI_ADR_SPACE_CMOS: - handler = acpi_ex_cmos_space_handler; - setup = acpi_ev_cmos_region_setup; - break; - - case ACPI_ADR_SPACE_PCI_BAR_TARGET: - handler = acpi_ex_pci_bar_space_handler; - setup = acpi_ev_pci_bar_region_setup; - break; - - case ACPI_ADR_SPACE_DATA_TABLE: - handler = acpi_ex_data_table_space_handler; - setup = NULL; - break; - - default: - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } + region_obj2 = acpi_ns_get_secondary_object(region_obj); + if (!region_obj2) { + return_ACPI_STATUS(AE_NOT_EXIST); } - /* If the caller hasn't specified a setup routine, use the default */ - - if (!setup) { - setup = acpi_ev_default_region_setup; + if (region_obj2->extra.method_REG == NULL) { + return_ACPI_STATUS(AE_OK); } - /* Check for an existing internal object */ - - obj_desc = acpi_ns_get_attached_object(node); - if (obj_desc) { - /* - * The attached device object already exists. Make sure the handler - * is not already installed. - */ - handler_obj = obj_desc->device.handler; - - /* Walk the handler list for this device */ - - while (handler_obj) { - - /* Same space_id indicates a handler already installed */ - - if (handler_obj->address_space.space_id == space_id) { - if (handler_obj->address_space.handler == - handler) { - /* - * It is (relatively) OK to attempt to install the SAME - * handler twice. This can easily happen with the - * PCI_Config space. - */ - status = AE_SAME_HANDLER; - goto unlock_and_exit; - } else { - /* A handler is already installed */ - - status = AE_ALREADY_EXISTS; - } - goto unlock_and_exit; - } - - /* Walk the linked list of handlers */ - - handler_obj = handler_obj->address_space.next; - } - } else { - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Creating object on Device %p while installing handler\n", - node)); - - /* obj_desc does not exist, create one */ - - if (node->type == ACPI_TYPE_ANY) { - type = ACPI_TYPE_DEVICE; - } else { - type = node->type; - } - - obj_desc = acpi_ut_create_internal_object(type); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto unlock_and_exit; - } - - /* Init new descriptor */ - - obj_desc->common.type = (u8) type; - - /* Attach the new object to the Node */ - - status = acpi_ns_attach_object(node, obj_desc, type); - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); + /* Allocate and initialize the evaluation information block */ - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); } - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", - acpi_ut_get_region_name(space_id), space_id, - acpi_ut_get_node_name(node), node, obj_desc)); + info->prefix_node = region_obj2->extra.method_REG; + info->relative_pathname = NULL; + info->parameters = args; + info->flags = ACPI_IGNORE_RETURN_VALUE; /* - * Install the handler + * The _REG method has two arguments: * - * At this point there is no existing handler. Just allocate the object - * for the handler and link it into the list. + * arg0 - Integer: + * Operation region space ID Same value as region_obj->Region.space_id + * + * arg1 - Integer: + * connection status 1 for connecting the handler, 0 for disconnecting + * the handler (Passed as a parameter) */ - handler_obj = - acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_ADDRESS_HANDLER); - if (!handler_obj) { + args[0] = + acpi_ut_create_integer_object((u64)region_obj->region.space_id); + if (!args[0]) { status = AE_NO_MEMORY; - goto unlock_and_exit; + goto cleanup1; } - /* Init handler obj */ + args[1] = acpi_ut_create_integer_object((u64)function); + if (!args[1]) { + status = AE_NO_MEMORY; + goto cleanup2; + } - handler_obj->address_space.space_id = (u8) space_id; - handler_obj->address_space.handler_flags = flags; - handler_obj->address_space.region_list = NULL; - handler_obj->address_space.node = node; - handler_obj->address_space.handler = handler; - handler_obj->address_space.context = context; - handler_obj->address_space.setup = setup; + args[2] = NULL; /* Terminate list */ - /* Install at head of Device.address_space list */ + /* Execute the method, no return value */ - handler_obj->address_space.next = obj_desc->device.handler; + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname + (ACPI_TYPE_METHOD, info->prefix_node, NULL)); - /* - * The Device object is the first reference on the handler_obj. - * Each region that uses the handler adds a reference. - */ - obj_desc->device.handler = handler_obj; + status = acpi_ns_evaluate(info); + acpi_ut_remove_reference(args[1]); - /* - * Walk the namespace finding all of the regions this - * handler will manage. - * - * Start at the device and search the branch toward - * the leaf nodes until either the leaf is encountered or - * a device is detected that has an address handler of the - * same type. - * - * In either case, back up and search down the remainder - * of the branch - */ - status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, - ACPI_NS_WALK_UNLOCK, - acpi_ev_install_handler, NULL, - handler_obj, NULL); +cleanup2: + acpi_ut_remove_reference(args[0]); - unlock_and_exit: +cleanup1: + ACPI_FREE(info); return_ACPI_STATUS(status); } @@ -1061,7 +596,7 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node, * * FUNCTION: acpi_ev_execute_reg_methods * - * PARAMETERS: Node - Namespace node for the device + * PARAMETERS: node - Namespace node for the device * space_id - The address space ID * * RETURN: Status @@ -1092,7 +627,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, /* Special case for EC: handle "orphan" _REG methods with no region */ if (space_id == ACPI_ADR_SPACE_EC) { - acpi_ev_orphan_ec_reg_method(); + acpi_ev_orphan_ec_reg_method(node); } return_ACPI_STATUS(status); @@ -1104,7 +639,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, * * PARAMETERS: walk_namespace callback * - * DESCRIPTION: Run _REG method for region objects of the requested space_iD + * DESCRIPTION: Run _REG method for region objects of the requested spaceID * ******************************************************************************/ @@ -1161,7 +696,7 @@ acpi_ev_reg_run(acpi_handle obj_handle, * * FUNCTION: acpi_ev_orphan_ec_reg_method * - * PARAMETERS: None + * PARAMETERS: ec_device_node - Namespace node for an EC device * * RETURN: None * @@ -1173,37 +708,27 @@ acpi_ev_reg_run(acpi_handle obj_handle, * detected by providing a _REG method object underneath the * Embedded Controller device." * - * To quickly access the EC device, we use the EC_ID that appears - * within the ECDT. Otherwise, we would need to perform a time- - * consuming namespace walk, executing _HID methods to find the - * EC device. + * To quickly access the EC device, we use the ec_device_node used + * during EC handler installation. Otherwise, we would need to + * perform a time consuming namespace walk, executing _HID + * methods to find the EC device. + * + * MUTEX: Assumes the namespace is locked * ******************************************************************************/ -static void acpi_ev_orphan_ec_reg_method(void) +static void +acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node) { - struct acpi_table_ecdt *table; + acpi_handle reg_method; + struct acpi_namespace_node *next_node; acpi_status status; struct acpi_object_list args; union acpi_object objects[2]; - struct acpi_namespace_node *ec_device_node; - struct acpi_namespace_node *reg_method; - struct acpi_namespace_node *next_node; ACPI_FUNCTION_TRACE(ev_orphan_ec_reg_method); - /* Get the ECDT (if present in system) */ - - status = acpi_get_table(ACPI_SIG_ECDT, 0, - ACPI_CAST_INDIRECT_PTR(struct acpi_table_header, - &table)); - if (ACPI_FAILURE(status)) { - return_VOID; - } - - /* We need a valid EC_ID string */ - - if (!(*table->id)) { + if (!ec_device_node) { return_VOID; } @@ -1211,22 +736,11 @@ static void acpi_ev_orphan_ec_reg_method(void) (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - /* Get a handle to the EC device referenced in the ECDT */ - - status = acpi_get_handle(NULL, - ACPI_CAST_PTR(char, table->id), - ACPI_CAST_PTR(acpi_handle, &ec_device_node)); - if (ACPI_FAILURE(status)) { - goto exit; - } - /* Get a handle to a _REG method immediately under the EC device */ - status = acpi_get_handle(ec_device_node, - METHOD_NAME__REG, ACPI_CAST_PTR(acpi_handle, - ®_method)); + status = acpi_get_handle(ec_device_node, METHOD_NAME__REG, ®_method); if (ACPI_FAILURE(status)) { - goto exit; + goto exit; /* There is no _REG method present */ } /* @@ -1234,19 +748,20 @@ static void acpi_ev_orphan_ec_reg_method(void) * this scope with the Embedded Controller space ID. Otherwise, it * will already have been executed. Note, this allows for Regions * with other space IDs to be present; but the code below will then - * execute the _REG method with the EC space ID argument. + * execute the _REG method with the embedded_control space_ID argument. */ next_node = acpi_ns_get_next_node(ec_device_node, NULL); while (next_node) { if ((next_node->type == ACPI_TYPE_REGION) && (next_node->object) && (next_node->object->region.space_id == ACPI_ADR_SPACE_EC)) { - goto exit; /* Do not execute _REG */ + goto exit; /* Do not execute the _REG */ } + next_node = acpi_ns_get_next_node(ec_device_node, next_node); } - /* Evaluate the _REG(EC,Connect) method */ + /* Evaluate the _REG(embedded_control,Connect) method */ args.count = 2; args.pointer = objects; @@ -1257,7 +772,7 @@ static void acpi_ev_orphan_ec_reg_method(void) status = acpi_evaluate_object(reg_method, NULL, &args, NULL); - exit: +exit: /* We ignore all errors from above, don't care */ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index 819c17f5897..1b148a440d6 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -56,8 +56,8 @@ static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node); * * FUNCTION: acpi_ev_system_memory_region_setup * - * PARAMETERS: Handle - Region we are interested in - * Function - Start or stop + * PARAMETERS: handle - Region we are interested in + * function - Start or stop * handler_context - Address space handler context * region_context - Region specific context * @@ -118,8 +118,8 @@ acpi_ev_system_memory_region_setup(acpi_handle handle, * * FUNCTION: acpi_ev_io_space_region_setup * - * PARAMETERS: Handle - Region we are interested in - * Function - Start or stop + * PARAMETERS: handle - Region we are interested in + * function - Start or stop * handler_context - Address space handler context * region_context - Region specific context * @@ -149,8 +149,8 @@ acpi_ev_io_space_region_setup(acpi_handle handle, * * FUNCTION: acpi_ev_pci_config_region_setup * - * PARAMETERS: Handle - Region we are interested in - * Function - Start or stop + * PARAMETERS: handle - Region we are interested in + * function - Start or stop * handler_context - Address space handler context * region_context - Region specific context * @@ -227,8 +227,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, /* Install a handler for this PCI root bridge */ - status = - acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); + status = acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); if (ACPI_FAILURE(status)) { if (status == AE_SAME_HANDLER) { /* @@ -338,7 +337,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, * * FUNCTION: acpi_ev_is_pci_root_bridge * - * PARAMETERS: Node - Device node being examined + * PARAMETERS: node - Device node being examined * * RETURN: TRUE if device is a PCI/PCI-Express Root Bridge * @@ -350,8 +349,8 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) { acpi_status status; - struct acpica_device_id *hid; - struct acpica_device_id_list *cid; + struct acpi_pnp_device_id *hid; + struct acpi_pnp_device_id_list *cid; u32 i; u8 match; @@ -393,14 +392,14 @@ static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) * * FUNCTION: acpi_ev_pci_bar_region_setup * - * PARAMETERS: Handle - Region we are interested in - * Function - Start or stop + * PARAMETERS: handle - Region we are interested in + * function - Start or stop * handler_context - Address space handler context * region_context - Region specific context * * RETURN: Status * - * DESCRIPTION: Setup a pci_bAR operation region + * DESCRIPTION: Setup a pci_BAR operation region * * MUTEX: Assumes namespace is not locked * @@ -420,8 +419,8 @@ acpi_ev_pci_bar_region_setup(acpi_handle handle, * * FUNCTION: acpi_ev_cmos_region_setup * - * PARAMETERS: Handle - Region we are interested in - * Function - Start or stop + * PARAMETERS: handle - Region we are interested in + * function - Start or stop * handler_context - Address space handler context * region_context - Region specific context * @@ -447,8 +446,8 @@ acpi_ev_cmos_region_setup(acpi_handle handle, * * FUNCTION: acpi_ev_default_region_setup * - * PARAMETERS: Handle - Region we are interested in - * Function - Start or stop + * PARAMETERS: handle - Region we are interested in + * function - Start or stop * handler_context - Address space handler context * region_context - Region specific context * @@ -597,7 +596,9 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, break; default: + /* Ignore other objects */ + break; } diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c index 26065c612e7..29630e30382 100644 --- a/drivers/acpi/acpica/evsci.c +++ b/drivers/acpi/acpica/evsci.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,15 +48,59 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evsci") - +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /* Local prototypes */ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context); /******************************************************************************* * + * FUNCTION: acpi_ev_sci_dispatch + * + * PARAMETERS: None + * + * RETURN: Status code indicates whether interrupt was handled. + * + * DESCRIPTION: Dispatch the SCI to all host-installed SCI handlers. + * + ******************************************************************************/ + +u32 acpi_ev_sci_dispatch(void) +{ + struct acpi_sci_handler_info *sci_handler; + acpi_cpu_flags flags; + u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; + + ACPI_FUNCTION_NAME(ev_sci_dispatch); + + /* Are there any host-installed SCI handlers? */ + + if (!acpi_gbl_sci_handler_list) { + return (int_status); + } + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + /* Invoke all host-installed SCI handlers */ + + sci_handler = acpi_gbl_sci_handler_list; + while (sci_handler) { + + /* Invoke the installed handler (at interrupt level) */ + + int_status |= sci_handler->address(sci_handler->context); + + sci_handler = sci_handler->next; + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + return (int_status); +} + +/******************************************************************************* + * * FUNCTION: acpi_ev_sci_xrupt_handler * - * PARAMETERS: Context - Calling Context + * PARAMETERS: context - Calling Context * * RETURN: Status code indicates whether interrupt was handled. * @@ -73,7 +117,7 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context) ACPI_FUNCTION_TRACE(ev_sci_xrupt_handler); /* - * We are guaranteed by the ACPI CA initialization/shutdown code that + * We are guaranteed by the ACPICA initialization/shutdown code that * if this interrupt handler is installed, ACPI is enabled. */ @@ -89,6 +133,11 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context) */ interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); + /* Invoke all host-installed SCI handlers */ + + interrupt_handled |= acpi_ev_sci_dispatch(); + + acpi_sci_count++; return_UINT32(interrupt_handled); } @@ -96,7 +145,7 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context) * * FUNCTION: acpi_ev_gpe_xrupt_handler * - * PARAMETERS: Context - Calling Context + * PARAMETERS: context - Calling Context * * RETURN: Status code indicates whether interrupt was handled. * @@ -112,14 +161,13 @@ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context) ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler); /* - * We are guaranteed by the ACPI CA initialization/shutdown code that + * We are guaranteed by the ACPICA initialization/shutdown code that * if this interrupt handler is installed, ACPI is enabled. */ /* GPEs: Check for and dispatch any GPEs that have occurred */ interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); - return_UINT32(interrupt_handled); } @@ -150,15 +198,15 @@ u32 acpi_ev_install_sci_handler(void) /****************************************************************************** * - * FUNCTION: acpi_ev_remove_sci_handler + * FUNCTION: acpi_ev_remove_all_sci_handlers * * PARAMETERS: none * - * RETURN: E_OK if handler uninstalled OK, E_ERROR if handler was not + * RETURN: AE_OK if handler uninstalled, AE_ERROR if handler was not * installed to begin with * * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be - * taken. + * taken. Remove all host-installed SCI handlers. * * Note: It doesn't seem important to disable all events or set the event * enable registers to their original values. The OS should disable @@ -167,11 +215,13 @@ u32 acpi_ev_install_sci_handler(void) * ******************************************************************************/ -acpi_status acpi_ev_remove_sci_handler(void) +acpi_status acpi_ev_remove_all_sci_handlers(void) { + struct acpi_sci_handler_info *sci_handler; + acpi_cpu_flags flags; acpi_status status; - ACPI_FUNCTION_TRACE(ev_remove_sci_handler); + ACPI_FUNCTION_TRACE(ev_remove_all_sci_handlers); /* Just let the OS remove the handler and disable the level */ @@ -179,5 +229,22 @@ acpi_status acpi_ev_remove_sci_handler(void) acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt, acpi_ev_sci_xrupt_handler); + if (!acpi_gbl_sci_handler_list) { + return (status); + } + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + /* Free all host-installed SCI handlers */ + + while (acpi_gbl_sci_handler_list) { + sci_handler = acpi_gbl_sci_handler_list; + acpi_gbl_sci_handler_list = sci_handler->next; + ACPI_FREE(sci_handler); + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 61944e89565..11e5803b8b4 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include <linux/export.h> +#define EXPORT_ACPI_INTERFACES + #include <acpi/acpi.h> #include "accommon.h" #include "acnamesp.h" @@ -51,127 +52,325 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evxface") + /******************************************************************************* * - * FUNCTION: acpi_install_exception_handler + * FUNCTION: acpi_install_notify_handler * - * PARAMETERS: Handler - Pointer to the handler function for the - * event + * PARAMETERS: device - The device for which notifies will be handled + * handler_type - The type of handler: + * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) + * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) + * ACPI_ALL_NOTIFY: Both System and Device + * handler - Address of the handler + * context - Value passed to the handler on each GPE * * RETURN: Status * - * DESCRIPTION: Saves the pointer to the handler function + * DESCRIPTION: Install a handler for notifications on an ACPI Device, + * thermal_zone, or Processor object. + * + * NOTES: The Root namespace object may have only one handler for each + * type of notify (System/Device). Device/Thermal/Processor objects + * may have one device notify handler, and multiple system notify + * handlers. * ******************************************************************************/ -#ifdef ACPI_FUTURE_USAGE -acpi_status acpi_install_exception_handler(acpi_exception_handler handler) +acpi_status +acpi_install_notify_handler(acpi_handle device, + u32 handler_type, + acpi_notify_handler handler, void *context) { + struct acpi_namespace_node *node = + ACPI_CAST_PTR(struct acpi_namespace_node, device); + union acpi_operand_object *obj_desc; + union acpi_operand_object *handler_obj; acpi_status status; + u32 i; - ACPI_FUNCTION_TRACE(acpi_install_exception_handler); + ACPI_FUNCTION_TRACE(acpi_install_notify_handler); - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + /* Parameter validation */ + + if ((!device) || (!handler) || (!handler_type) || + (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - /* Don't allow two handlers. */ + /* + * Root Object: + * Registering a notify handler on the root object indicates that the + * caller wishes to receive notifications for all objects. Note that + * only one global handler can be registered per notify type. + * Ensure that a handler is not already installed. + */ + if (device == ACPI_ROOT_OBJECT) { + for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { + if (handler_type & (i + 1)) { + if (acpi_gbl_global_notify[i].handler) { + status = AE_ALREADY_EXISTS; + goto unlock_and_exit; + } - if (acpi_gbl_exception_handler) { - status = AE_ALREADY_EXISTS; - goto cleanup; + acpi_gbl_global_notify[i].handler = handler; + acpi_gbl_global_notify[i].context = context; + } + } + + goto unlock_and_exit; /* Global notify handler installed, all done */ } - /* Install the handler */ + /* + * All Other Objects: + * Caller will only receive notifications specific to the target + * object. Note that only certain object types are allowed to + * receive notifications. + */ - acpi_gbl_exception_handler = handler; + /* Are Notifies allowed on this object? */ - cleanup: - (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + if (!acpi_ev_is_notify_object(node)) { + status = AE_TYPE; + goto unlock_and_exit; + } + + /* Check for an existing internal object, might not exist */ + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + + /* Create a new object */ + + obj_desc = acpi_ut_create_internal_object(node->type); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Attach new object to the Node, remove local reference */ + + status = acpi_ns_attach_object(device, obj_desc, node->type); + acpi_ut_remove_reference(obj_desc); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + } + + /* Ensure that the handler is not already installed in the lists */ + + for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { + if (handler_type & (i + 1)) { + handler_obj = obj_desc->common_notify.notify_list[i]; + while (handler_obj) { + if (handler_obj->notify.handler == handler) { + status = AE_ALREADY_EXISTS; + goto unlock_and_exit; + } + + handler_obj = handler_obj->notify.next[i]; + } + } + } + + /* Create and populate a new notify handler object */ + + handler_obj = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY); + if (!handler_obj) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + handler_obj->notify.node = node; + handler_obj->notify.handler_type = handler_type; + handler_obj->notify.handler = handler; + handler_obj->notify.context = context; + + /* Install the handler at the list head(s) */ + + for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { + if (handler_type & (i + 1)) { + handler_obj->notify.next[i] = + obj_desc->common_notify.notify_list[i]; + + obj_desc->common_notify.notify_list[i] = handler_obj; + } + } + + /* Add an extra reference if handler was installed in both lists */ + + if (handler_type == ACPI_ALL_NOTIFY) { + acpi_ut_add_reference(handler_obj); + } + +unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) -#endif /* ACPI_FUTURE_USAGE */ +ACPI_EXPORT_SYMBOL(acpi_install_notify_handler) /******************************************************************************* * - * FUNCTION: acpi_install_global_event_handler + * FUNCTION: acpi_remove_notify_handler * - * PARAMETERS: Handler - Pointer to the global event handler function - * Context - Value passed to the handler on each event + * PARAMETERS: device - The device for which the handler is installed + * handler_type - The type of handler: + * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) + * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) + * ACPI_ALL_NOTIFY: Both System and Device + * handler - Address of the handler * * RETURN: Status * - * DESCRIPTION: Saves the pointer to the handler function. The global handler - * is invoked upon each incoming GPE and Fixed Event. It is - * invoked at interrupt level at the time of the event dispatch. - * Can be used to update event counters, etc. + * DESCRIPTION: Remove a handler for notifies on an ACPI device * ******************************************************************************/ acpi_status -acpi_install_global_event_handler(ACPI_GBL_EVENT_HANDLER handler, void *context) +acpi_remove_notify_handler(acpi_handle device, + u32 handler_type, acpi_notify_handler handler) { - acpi_status status; + struct acpi_namespace_node *node = + ACPI_CAST_PTR(struct acpi_namespace_node, device); + union acpi_operand_object *obj_desc; + union acpi_operand_object *handler_obj; + union acpi_operand_object *previous_handler_obj; + acpi_status status = AE_OK; + u32 i; - ACPI_FUNCTION_TRACE(acpi_install_global_event_handler); + ACPI_FUNCTION_TRACE(acpi_remove_notify_handler); /* Parameter validation */ - if (!handler) { + if ((!device) || (!handler) || (!handler_type) || + (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + /* Root Object. Global handlers are removed here */ + + if (device == ACPI_ROOT_OBJECT) { + for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { + if (handler_type & (i + 1)) { + status = + acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (!acpi_gbl_global_notify[i].handler || + (acpi_gbl_global_notify[i].handler != + handler)) { + status = AE_NOT_EXIST; + goto unlock_and_exit; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Removing global notify handler\n")); + + acpi_gbl_global_notify[i].handler = NULL; + acpi_gbl_global_notify[i].context = NULL; + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + + /* Make sure all deferred notify tasks are completed */ + + acpi_os_wait_events_complete(); + } + } + + return_ACPI_STATUS(AE_OK); } - /* Don't allow two handlers. */ + /* All other objects: Are Notifies allowed on this object? */ - if (acpi_gbl_global_event_handler) { - status = AE_ALREADY_EXISTS; - goto cleanup; + if (!acpi_ev_is_notify_object(node)) { + return_ACPI_STATUS(AE_TYPE); } - acpi_gbl_global_event_handler = handler; - acpi_gbl_global_event_handler_context = context; + /* Must have an existing internal object */ - cleanup: - (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* Internal object exists. Find the handler and remove it */ + + for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { + if (handler_type & (i + 1)) { + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + handler_obj = obj_desc->common_notify.notify_list[i]; + previous_handler_obj = NULL; + + /* Attempt to find the handler in the handler list */ + + while (handler_obj && + (handler_obj->notify.handler != handler)) { + previous_handler_obj = handler_obj; + handler_obj = handler_obj->notify.next[i]; + } + + if (!handler_obj) { + status = AE_NOT_EXIST; + goto unlock_and_exit; + } + + /* Remove the handler object from the list */ + + if (previous_handler_obj) { /* Handler is not at the list head */ + previous_handler_obj->notify.next[i] = + handler_obj->notify.next[i]; + } else { /* Handler is at the list head */ + + obj_desc->common_notify.notify_list[i] = + handler_obj->notify.next[i]; + } + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + + /* Make sure all deferred notify tasks are completed */ + + acpi_os_wait_events_complete(); + acpi_ut_remove_reference(handler_obj); + } + } + + return_ACPI_STATUS(status); + +unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler) +ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler) /******************************************************************************* * - * FUNCTION: acpi_install_fixed_event_handler + * FUNCTION: acpi_install_exception_handler * - * PARAMETERS: Event - Event type to enable. - * Handler - Pointer to the handler function for the + * PARAMETERS: handler - Pointer to the handler function for the * event - * Context - Value passed to the handler on each GPE * * RETURN: Status * - * DESCRIPTION: Saves the pointer to the handler function and then enables the - * event. + * DESCRIPTION: Saves the pointer to the handler function * ******************************************************************************/ -acpi_status -acpi_install_fixed_event_handler(u32 event, - acpi_event_handler handler, void *context) +#ifdef ACPI_FUTURE_USAGE +acpi_status acpi_install_exception_handler(acpi_exception_handler handler) { acpi_status status; - ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler); - - /* Parameter validation */ - - if (event > ACPI_EVENT_MAX) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } + ACPI_FUNCTION_TRACE(acpi_install_exception_handler); status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { @@ -180,528 +379,341 @@ acpi_install_fixed_event_handler(u32 event, /* Don't allow two handlers. */ - if (NULL != acpi_gbl_fixed_event_handlers[event].handler) { + if (acpi_gbl_exception_handler) { status = AE_ALREADY_EXISTS; goto cleanup; } - /* Install the handler before enabling the event */ - - acpi_gbl_fixed_event_handlers[event].handler = handler; - acpi_gbl_fixed_event_handlers[event].context = context; - - status = acpi_clear_event(event); - if (ACPI_SUCCESS(status)) - status = acpi_enable_event(event, 0); - if (ACPI_FAILURE(status)) { - ACPI_WARNING((AE_INFO, "Could not enable fixed event 0x%X", - event)); - - /* Remove the handler */ + /* Install the handler */ - acpi_gbl_fixed_event_handlers[event].handler = NULL; - acpi_gbl_fixed_event_handlers[event].context = NULL; - } else { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Enabled fixed event %X, Handler=%p\n", event, - handler)); - } + acpi_gbl_exception_handler = handler; - cleanup: +cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler) +ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) +#endif /* ACPI_FUTURE_USAGE */ +#if (!ACPI_REDUCED_HARDWARE) /******************************************************************************* * - * FUNCTION: acpi_remove_fixed_event_handler + * FUNCTION: acpi_install_sci_handler * - * PARAMETERS: Event - Event type to disable. - * Handler - Address of the handler + * PARAMETERS: address - Address of the handler + * context - Value passed to the handler on each SCI * * RETURN: Status * - * DESCRIPTION: Disables the event and unregisters the event handler. + * DESCRIPTION: Install a handler for a System Control Interrupt. * ******************************************************************************/ -acpi_status -acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler) +acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context) { - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler); + struct acpi_sci_handler_info *new_sci_handler; + struct acpi_sci_handler_info *sci_handler; + acpi_cpu_flags flags; + acpi_status status; - /* Parameter validation */ + ACPI_FUNCTION_TRACE(acpi_install_sci_handler); - if (event > ACPI_EVENT_MAX) { + if (!address) { return_ACPI_STATUS(AE_BAD_PARAMETER); } + /* Allocate and init a handler object */ + + new_sci_handler = ACPI_ALLOCATE(sizeof(struct acpi_sci_handler_info)); + if (!new_sci_handler) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + new_sci_handler->address = address; + new_sci_handler->context = context; + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto exit; } - /* Disable the event before removing the handler */ + /* Lock list during installation */ - status = acpi_disable_event(event, 0); + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + sci_handler = acpi_gbl_sci_handler_list; - /* Always Remove the handler */ + /* Ensure handler does not already exist */ - acpi_gbl_fixed_event_handlers[event].handler = NULL; - acpi_gbl_fixed_event_handlers[event].context = NULL; + while (sci_handler) { + if (address == sci_handler->address) { + status = AE_ALREADY_EXISTS; + goto unlock_and_exit; + } - if (ACPI_FAILURE(status)) { - ACPI_WARNING((AE_INFO, - "Could not write to fixed event enable register 0x%X", - event)); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X\n", - event)); + sci_handler = sci_handler->next; } + /* Install the new handler into the global list (at head) */ + + new_sci_handler->next = acpi_gbl_sci_handler_list; + acpi_gbl_sci_handler_list = new_sci_handler; + +unlock_and_exit: + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + +exit: + if (ACPI_FAILURE(status)) { + ACPI_FREE(new_sci_handler); + } return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler) +ACPI_EXPORT_SYMBOL(acpi_install_sci_handler) /******************************************************************************* * - * FUNCTION: acpi_populate_handler_object - * - * PARAMETERS: handler_obj - Handler object to populate - * handler_type - The type of handler: - * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) - * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) - * ACPI_ALL_NOTIFY: both system and device - * handler - Address of the handler - * context - Value passed to the handler on each GPE - * next - Address of a handler object to link to + * FUNCTION: acpi_remove_sci_handler * - * RETURN: None - * - * DESCRIPTION: Populate a handler object. - * - ******************************************************************************/ -static void -acpi_populate_handler_object(struct acpi_object_notify_handler *handler_obj, - u32 handler_type, - acpi_notify_handler handler, void *context, - struct acpi_object_notify_handler *next) -{ - handler_obj->handler_type = handler_type; - handler_obj->handler = handler; - handler_obj->context = context; - handler_obj->next = next; -} - -/******************************************************************************* - * - * FUNCTION: acpi_add_handler_object - * - * PARAMETERS: parent_obj - Parent of the new object - * handler - Address of the handler - * context - Value passed to the handler on each GPE + * PARAMETERS: address - Address of the handler * * RETURN: Status * - * DESCRIPTION: Create a new handler object and populate it. + * DESCRIPTION: Remove a handler for a System Control Interrupt. * ******************************************************************************/ -static acpi_status -acpi_add_handler_object(struct acpi_object_notify_handler *parent_obj, - acpi_notify_handler handler, void *context) +acpi_status acpi_remove_sci_handler(acpi_sci_handler address) { - struct acpi_object_notify_handler *handler_obj; + struct acpi_sci_handler_info *prev_sci_handler; + struct acpi_sci_handler_info *next_sci_handler; + acpi_cpu_flags flags; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_remove_sci_handler); + + if (!address) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } - /* The parent must not be a defice notify handler object. */ - if (parent_obj->handler_type & ACPI_DEVICE_NOTIFY) - return AE_BAD_PARAMETER; + /* Remove the SCI handler with lock */ + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); - handler_obj = ACPI_ALLOCATE_ZEROED(sizeof(*handler_obj)); - if (!handler_obj) - return AE_NO_MEMORY; + prev_sci_handler = NULL; + next_sci_handler = acpi_gbl_sci_handler_list; + while (next_sci_handler) { + if (next_sci_handler->address == address) { - acpi_populate_handler_object(handler_obj, - ACPI_SYSTEM_NOTIFY, - handler, context, - parent_obj->next); - parent_obj->next = handler_obj; + /* Unlink and free the SCI handler info block */ - return AE_OK; + if (prev_sci_handler) { + prev_sci_handler->next = next_sci_handler->next; + } else { + acpi_gbl_sci_handler_list = + next_sci_handler->next; + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + ACPI_FREE(next_sci_handler); + goto unlock_and_exit; + } + + prev_sci_handler = next_sci_handler; + next_sci_handler = next_sci_handler->next; + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + status = AE_NOT_EXIST; + +unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_remove_sci_handler) + /******************************************************************************* * - * FUNCTION: acpi_install_notify_handler + * FUNCTION: acpi_install_global_event_handler * - * PARAMETERS: Device - The device for which notifies will be handled - * handler_type - The type of handler: - * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) - * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) - * ACPI_ALL_NOTIFY: both system and device - * Handler - Address of the handler - * Context - Value passed to the handler on each GPE + * PARAMETERS: handler - Pointer to the global event handler function + * context - Value passed to the handler on each event * * RETURN: Status * - * DESCRIPTION: Install a handler for notifies on an ACPI device + * DESCRIPTION: Saves the pointer to the handler function. The global handler + * is invoked upon each incoming GPE and Fixed Event. It is + * invoked at interrupt level at the time of the event dispatch. + * Can be used to update event counters, etc. * ******************************************************************************/ acpi_status -acpi_install_notify_handler(acpi_handle device, - u32 handler_type, - acpi_notify_handler handler, void *context) +acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context) { - union acpi_operand_object *obj_desc; - union acpi_operand_object *notify_obj; - struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_TRACE(acpi_install_notify_handler); + ACPI_FUNCTION_TRACE(acpi_install_global_event_handler); /* Parameter validation */ - if ((!device) || - (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { + if (!handler) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - /* Convert and validate the device handle */ - - node = acpi_ns_validate_handle(device); - if (!node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - /* - * Root Object: - * Registering a notify handler on the root object indicates that the - * caller wishes to receive notifications for all objects. Note that - * only one <external> global handler can be regsitered (per notify type). - */ - if (device == ACPI_ROOT_OBJECT) { - - /* Make sure the handler is not already installed */ - - if (((handler_type & ACPI_SYSTEM_NOTIFY) && - acpi_gbl_system_notify.handler) || - ((handler_type & ACPI_DEVICE_NOTIFY) && - acpi_gbl_device_notify.handler)) { - status = AE_ALREADY_EXISTS; - goto unlock_and_exit; - } - - if (handler_type & ACPI_SYSTEM_NOTIFY) { - acpi_gbl_system_notify.node = node; - acpi_gbl_system_notify.handler = handler; - acpi_gbl_system_notify.context = context; - } - - if (handler_type & ACPI_DEVICE_NOTIFY) { - acpi_gbl_device_notify.node = node; - acpi_gbl_device_notify.handler = handler; - acpi_gbl_device_notify.context = context; - } + /* Don't allow two handlers. */ - /* Global notify handler installed */ + if (acpi_gbl_global_event_handler) { + status = AE_ALREADY_EXISTS; + goto cleanup; } - /* - * All Other Objects: - * Caller will only receive notifications specific to the target object. - * Note that only certain object types can receive notifications. - */ - else { - /* Notifies allowed on this object? */ - - if (!acpi_ev_is_notify_object(node)) { - status = AE_TYPE; - goto unlock_and_exit; - } - - /* Check for an existing internal object */ - - obj_desc = acpi_ns_get_attached_object(node); - if (obj_desc) { - - /* Object exists. */ - - /* For a device notify, make sure there's no handler. */ - if ((handler_type & ACPI_DEVICE_NOTIFY) && - obj_desc->common_notify.device_notify) { - status = AE_ALREADY_EXISTS; - goto unlock_and_exit; - } - - /* System notifies may have more handlers installed. */ - notify_obj = obj_desc->common_notify.system_notify; - - if ((handler_type & ACPI_SYSTEM_NOTIFY) && notify_obj) { - struct acpi_object_notify_handler *parent_obj; - - if (handler_type & ACPI_DEVICE_NOTIFY) { - status = AE_ALREADY_EXISTS; - goto unlock_and_exit; - } - - parent_obj = ¬ify_obj->notify; - status = acpi_add_handler_object(parent_obj, - handler, - context); - goto unlock_and_exit; - } - } else { - /* Create a new object */ - - obj_desc = acpi_ut_create_internal_object(node->type); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto unlock_and_exit; - } - - /* Attach new object to the Node */ - - status = - acpi_ns_attach_object(device, obj_desc, node->type); - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - } - - /* Install the handler */ - - notify_obj = - acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY); - if (!notify_obj) { - status = AE_NO_MEMORY; - goto unlock_and_exit; - } - - acpi_populate_handler_object(¬ify_obj->notify, - handler_type, - handler, context, - NULL); - - if (handler_type & ACPI_SYSTEM_NOTIFY) { - obj_desc->common_notify.system_notify = notify_obj; - } - - if (handler_type & ACPI_DEVICE_NOTIFY) { - obj_desc->common_notify.device_notify = notify_obj; - } - - if (handler_type == ACPI_ALL_NOTIFY) { - - /* Extra ref if installed in both */ - - acpi_ut_add_reference(notify_obj); - } - } + acpi_gbl_global_event_handler = handler; + acpi_gbl_global_event_handler_context = context; - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); +cleanup: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_install_notify_handler) +ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler) /******************************************************************************* * - * FUNCTION: acpi_remove_notify_handler + * FUNCTION: acpi_install_fixed_event_handler * - * PARAMETERS: Device - The device for which notifies will be handled - * handler_type - The type of handler: - * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) - * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) - * ACPI_ALL_NOTIFY: both system and device - * Handler - Address of the handler + * PARAMETERS: event - Event type to enable. + * handler - Pointer to the handler function for the + * event + * context - Value passed to the handler on each GPE * * RETURN: Status * - * DESCRIPTION: Remove a handler for notifies on an ACPI device + * DESCRIPTION: Saves the pointer to the handler function and then enables the + * event. * ******************************************************************************/ acpi_status -acpi_remove_notify_handler(acpi_handle device, - u32 handler_type, acpi_notify_handler handler) +acpi_install_fixed_event_handler(u32 event, + acpi_event_handler handler, void *context) { - union acpi_operand_object *notify_obj; - union acpi_operand_object *obj_desc; - struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_TRACE(acpi_remove_notify_handler); + ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler); /* Parameter validation */ - if ((!device) || - (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { - status = AE_BAD_PARAMETER; - goto exit; + if (event > ACPI_EVENT_MAX) { + return_ACPI_STATUS(AE_BAD_PARAMETER); } - - /* Make sure all deferred tasks are completed */ - acpi_os_wait_events_complete(NULL); - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { - goto exit; + return_ACPI_STATUS(status); } - /* Convert and validate the device handle */ + /* Do not allow multiple handlers */ - node = acpi_ns_validate_handle(device); - if (!node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; + if (acpi_gbl_fixed_event_handlers[event].handler) { + status = AE_ALREADY_EXISTS; + goto cleanup; } - /* Root Object */ + /* Install the handler before enabling the event */ - if (device == ACPI_ROOT_OBJECT) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Removing notify handler for namespace root object\n")); + acpi_gbl_fixed_event_handlers[event].handler = handler; + acpi_gbl_fixed_event_handlers[event].context = context; - if (((handler_type & ACPI_SYSTEM_NOTIFY) && - !acpi_gbl_system_notify.handler) || - ((handler_type & ACPI_DEVICE_NOTIFY) && - !acpi_gbl_device_notify.handler)) { - status = AE_NOT_EXIST; - goto unlock_and_exit; - } + status = acpi_clear_event(event); + if (ACPI_SUCCESS(status)) + status = acpi_enable_event(event, 0); + if (ACPI_FAILURE(status)) { + ACPI_WARNING((AE_INFO, + "Could not enable fixed event - %s (%u)", + acpi_ut_get_event_name(event), event)); - if (handler_type & ACPI_SYSTEM_NOTIFY) { - acpi_gbl_system_notify.node = NULL; - acpi_gbl_system_notify.handler = NULL; - acpi_gbl_system_notify.context = NULL; - } + /* Remove the handler */ - if (handler_type & ACPI_DEVICE_NOTIFY) { - acpi_gbl_device_notify.node = NULL; - acpi_gbl_device_notify.handler = NULL; - acpi_gbl_device_notify.context = NULL; - } + acpi_gbl_fixed_event_handlers[event].handler = NULL; + acpi_gbl_fixed_event_handlers[event].context = NULL; + } else { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Enabled fixed event %s (%X), Handler=%p\n", + acpi_ut_get_event_name(event), event, + handler)); } - /* All Other Objects */ - - else { - /* Notifies allowed on this object? */ - - if (!acpi_ev_is_notify_object(node)) { - status = AE_TYPE; - goto unlock_and_exit; - } +cleanup: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} - /* Check for an existing internal object */ +ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler) - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - status = AE_NOT_EXIST; - goto unlock_and_exit; - } +/******************************************************************************* + * + * FUNCTION: acpi_remove_fixed_event_handler + * + * PARAMETERS: event - Event type to disable. + * handler - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Disables the event and unregisters the event handler. + * + ******************************************************************************/ +acpi_status +acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler) +{ + acpi_status status = AE_OK; - /* Object exists - make sure there's an existing handler */ + ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler); - if (handler_type & ACPI_SYSTEM_NOTIFY) { - struct acpi_object_notify_handler *handler_obj; - struct acpi_object_notify_handler *parent_obj; + /* Parameter validation */ - notify_obj = obj_desc->common_notify.system_notify; - if (!notify_obj) { - status = AE_NOT_EXIST; - goto unlock_and_exit; - } + if (event > ACPI_EVENT_MAX) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } - handler_obj = ¬ify_obj->notify; - parent_obj = NULL; - while (handler_obj->handler != handler) { - if (handler_obj->next) { - parent_obj = handler_obj; - handler_obj = handler_obj->next; - } else { - break; - } - } + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } - if (handler_obj->handler != handler) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } + /* Disable the event before removing the handler */ - /* - * Remove the handler. There are three possible cases. - * First, we may need to remove a non-embedded object. - * Second, we may need to remove the embedded object's - * handler data, while non-embedded objects exist. - * Finally, we may need to remove the embedded object - * entirely along with its container. - */ - if (parent_obj) { - /* Non-embedded object is being removed. */ - parent_obj->next = handler_obj->next; - ACPI_FREE(handler_obj); - } else if (notify_obj->notify.next) { - /* - * The handler matches the embedded object, but - * there are more handler objects in the list. - * Replace the embedded object's data with the - * first next object's data and remove that - * object. - */ - parent_obj = ¬ify_obj->notify; - handler_obj = notify_obj->notify.next; - *parent_obj = *handler_obj; - ACPI_FREE(handler_obj); - } else { - /* No more handler objects in the list. */ - obj_desc->common_notify.system_notify = NULL; - acpi_ut_remove_reference(notify_obj); - } - } + status = acpi_disable_event(event, 0); - if (handler_type & ACPI_DEVICE_NOTIFY) { - notify_obj = obj_desc->common_notify.device_notify; - if (!notify_obj) { - status = AE_NOT_EXIST; - goto unlock_and_exit; - } + /* Always Remove the handler */ - if (notify_obj->notify.handler != handler) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } + acpi_gbl_fixed_event_handlers[event].handler = NULL; + acpi_gbl_fixed_event_handlers[event].context = NULL; - /* Remove the handler */ - obj_desc->common_notify.device_notify = NULL; - acpi_ut_remove_reference(notify_obj); - } + if (ACPI_FAILURE(status)) { + ACPI_WARNING((AE_INFO, + "Could not disable fixed event - %s (%u)", + acpi_ut_get_event_name(event), event)); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Disabled fixed event - %s (%X)\n", + acpi_ut_get_event_name(event), event)); } - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - exit: - if (ACPI_FAILURE(status)) - ACPI_EXCEPTION((AE_INFO, status, "Removing notify handler")); + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler) +ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler) /******************************************************************************* * @@ -710,10 +722,10 @@ ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler) * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT * defined GPEs) * gpe_number - The GPE number within the GPE block - * Type - Whether this GPE should be treated as an + * type - Whether this GPE should be treated as an * edge- or level-triggered interrupt. - * Address - Address of the handler - * Context - Value passed to the handler on each GPE + * address - Address of the handler + * context - Value passed to the handler on each GPE * * RETURN: Status * @@ -743,7 +755,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device, return_ACPI_STATUS(status); } - /* Allocate memory for the handler object */ + /* Allocate and init handler object (before lock) */ handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info)); if (!handler) { @@ -769,16 +781,15 @@ acpi_install_gpe_handler(acpi_handle gpe_device, goto free_and_exit; } - /* Allocate and init handler object */ - handler->address = address; handler->context = context; handler->method_node = gpe_event_info->dispatch.method_node; - handler->original_flags = gpe_event_info->flags & - (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); + handler->original_flags = (u8)(gpe_event_info->flags & + (ACPI_GPE_XRUPT_TYPE_MASK | + ACPI_GPE_DISPATCH_MASK)); /* - * If the GPE is associated with a method, it might have been enabled + * If the GPE is associated with a method, it may have been enabled * automatically during initialization, in which case it has to be * disabled now to avoid spurious execution of the handler. */ @@ -793,7 +804,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device, gpe_event_info->dispatch.handler = handler; - /* Setup up dispatch flags to indicate handler (vs. method) */ + /* Setup up dispatch flags to indicate handler (vs. method/notify) */ gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); @@ -820,7 +831,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler) * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT * defined GPEs) * gpe_number - The event to remove a handler - * Address - Address of the handler + * address - Address of the handler * * RETURN: Status * @@ -844,10 +855,6 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Make sure all deferred tasks are completed */ - - acpi_os_wait_events_complete(NULL); - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -894,14 +901,22 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, * enabled, it should be enabled at this point to restore the * post-initialization configuration. */ - - if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) - && handler->originally_enabled) + if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) && + handler->originally_enabled) { (void)acpi_ev_add_gpe_reference(gpe_event_info); + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + + /* Make sure all deferred GPE tasks are completed */ + + acpi_os_wait_events_complete(); /* Now we can free the handler object */ ACPI_FREE(handler); + return_ACPI_STATUS(status); unlock_and_exit: acpi_os_release_lock(acpi_gbl_gpe_lock, flags); @@ -916,8 +931,8 @@ ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler) * * FUNCTION: acpi_acquire_global_lock * - * PARAMETERS: Timeout - How long the caller is willing to wait - * Handle - Where the handle to the lock is returned + * PARAMETERS: timeout - How long the caller is willing to wait + * handle - Where the handle to the lock is returned * (if acquired) * * RETURN: Status @@ -964,7 +979,7 @@ ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock) * * FUNCTION: acpi_release_global_lock * - * PARAMETERS: Handle - Returned from acpi_acquire_global_lock + * PARAMETERS: handle - Returned from acpi_acquire_global_lock * * RETURN: Status * @@ -984,3 +999,4 @@ acpi_status acpi_release_global_lock(u32 handle) } ACPI_EXPORT_SYMBOL(acpi_release_global_lock) +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index 1768bbec100..e286640ad4f 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include <linux/export.h> +#define EXPORT_ACPI_INTERFACES + #include <acpi/acpi.h> #include "accommon.h" #include "actables.h" @@ -49,6 +50,7 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evxfevnt") +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /******************************************************************************* * * FUNCTION: acpi_enable @@ -60,7 +62,6 @@ ACPI_MODULE_NAME("evxfevnt") * DESCRIPTION: Transfers the system into ACPI mode. * ******************************************************************************/ - acpi_status acpi_enable(void) { acpi_status status; @@ -74,6 +75,12 @@ acpi_status acpi_enable(void) return_ACPI_STATUS(AE_NO_ACPI_TABLES); } + /* If the Hardware Reduced flag is set, machine is always in acpi mode */ + + if (acpi_gbl_reduced_hardware) { + return_ACPI_STATUS(AE_OK); + } + /* Check current mode */ if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) { @@ -126,6 +133,12 @@ acpi_status acpi_disable(void) ACPI_FUNCTION_TRACE(acpi_disable); + /* If the Hardware Reduced flag is set, machine is always in acpi mode */ + + if (acpi_gbl_reduced_hardware) { + return_ACPI_STATUS(AE_OK); + } + if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) { ACPI_DEBUG_PRINT((ACPI_DB_INIT, "System is already in legacy (non-ACPI) mode\n")); @@ -152,8 +165,8 @@ ACPI_EXPORT_SYMBOL(acpi_disable) * * FUNCTION: acpi_enable_event * - * PARAMETERS: Event - The fixed eventto be enabled - * Flags - Reserved + * PARAMETERS: event - The fixed eventto be enabled + * flags - Reserved * * RETURN: Status * @@ -209,8 +222,8 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event) * * FUNCTION: acpi_disable_event * - * PARAMETERS: Event - The fixed eventto be enabled - * Flags - Reserved + * PARAMETERS: event - The fixed event to be disabled + * flags - Reserved * * RETURN: Status * @@ -264,7 +277,7 @@ ACPI_EXPORT_SYMBOL(acpi_disable_event) * * FUNCTION: acpi_clear_event * - * PARAMETERS: Event - The fixed event to be cleared + * PARAMETERS: event - The fixed event to be cleared * * RETURN: Status * @@ -300,7 +313,7 @@ ACPI_EXPORT_SYMBOL(acpi_clear_event) * * FUNCTION: acpi_get_event_status * - * PARAMETERS: Event - The fixed event + * PARAMETERS: event - The fixed event * event_status - Where the current status of the event will * be returned * @@ -352,3 +365,4 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) } ACPI_EXPORT_SYMBOL(acpi_get_event_status) +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index 33388fd69df..cb534faf536 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include <linux/export.h> +#define EXPORT_ACPI_INTERFACES + #include <acpi/acpi.h> #include "accommon.h" #include "acevents.h" @@ -50,7 +51,8 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evxfgpe") -/****************************************************************************** +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ +/******************************************************************************* * * FUNCTION: acpi_update_all_gpes * @@ -171,6 +173,7 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } + ACPI_EXPORT_SYMBOL(acpi_disable_gpe) @@ -196,12 +199,12 @@ acpi_status acpi_setup_gpe_for_wake(acpi_handle wake_device, acpi_handle gpe_device, u32 gpe_number) { - acpi_status status = AE_BAD_PARAMETER; + acpi_status status; struct acpi_gpe_event_info *gpe_event_info; struct acpi_namespace_node *device_node; - struct acpi_gpe_notify_object *notify_object; + struct acpi_gpe_notify_info *notify; + struct acpi_gpe_notify_info *new_notify; acpi_cpu_flags flags; - u8 gpe_dispatch_mask; ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake); @@ -215,63 +218,96 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device, return_ACPI_STATUS(AE_BAD_PARAMETER); } + /* Handle root object case */ + + if (wake_device == ACPI_ROOT_OBJECT) { + device_node = acpi_gbl_root_node; + } else { + device_node = + ACPI_CAST_PTR(struct acpi_namespace_node, wake_device); + } + + /* Validate wake_device is of type Device */ + + if (device_node->type != ACPI_TYPE_DEVICE) { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* + * Allocate a new notify object up front, in case it is needed. + * Memory allocation while holding a spinlock is a big no-no + * on some hosts. + */ + new_notify = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_notify_info)); + if (!new_notify) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); /* Ensure that we have a valid GPE number */ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); if (!gpe_event_info) { + status = AE_BAD_PARAMETER; goto unlock_and_exit; } - if (wake_device == ACPI_ROOT_OBJECT) { - goto out; - } - /* * If there is no method or handler for this GPE, then the - * wake_device will be notified whenever this GPE fires (aka - * "implicit notify") Note: The GPE is assumed to be + * wake_device will be notified whenever this GPE fires. This is + * known as an "implicit notify". Note: The GPE is assumed to be * level-triggered (for windows compatibility). */ - gpe_dispatch_mask = gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK; - if (gpe_dispatch_mask != ACPI_GPE_DISPATCH_NONE - && gpe_dispatch_mask != ACPI_GPE_DISPATCH_NOTIFY) { - goto out; - } - - /* Validate wake_device is of type Device */ - - device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device); - if (device_node->type != ACPI_TYPE_DEVICE) { - goto unlock_and_exit; + if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_NONE) { + /* + * This is the first device for implicit notify on this GPE. + * Just set the flags here, and enter the NOTIFY block below. + */ + gpe_event_info->flags = + (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED); } - if (gpe_dispatch_mask == ACPI_GPE_DISPATCH_NONE) { - gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY | - ACPI_GPE_LEVEL_TRIGGERED); - gpe_event_info->dispatch.device.node = device_node; - gpe_event_info->dispatch.device.next = NULL; - } else { - /* There are multiple devices to notify implicitly. */ - - notify_object = ACPI_ALLOCATE_ZEROED(sizeof(*notify_object)); - if (!notify_object) { - status = AE_NO_MEMORY; - goto unlock_and_exit; + /* + * If we already have an implicit notify on this GPE, add + * this device to the notify list. + */ + if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_NOTIFY) { + + /* Ensure that the device is not already in the list */ + + notify = gpe_event_info->dispatch.notify_list; + while (notify) { + if (notify->device_node == device_node) { + status = AE_ALREADY_EXISTS; + goto unlock_and_exit; + } + notify = notify->next; } - notify_object->node = device_node; - notify_object->next = gpe_event_info->dispatch.device.next; - gpe_event_info->dispatch.device.next = notify_object; + /* Add this device to the notify list for this GPE */ + + new_notify->device_node = device_node; + new_notify->next = gpe_event_info->dispatch.notify_list; + gpe_event_info->dispatch.notify_list = new_notify; + new_notify = NULL; } - out: + /* Mark the GPE as a possible wake event */ + gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; status = AE_OK; - unlock_and_exit: +unlock_and_exit: acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + + /* Delete the notify object if it was not used above */ + + if (new_notify) { + ACPI_FREE(new_notify); + } return_ACPI_STATUS(status); } ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake) @@ -282,7 +318,7 @@ ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake) * * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 * gpe_number - GPE level within the GPE block - * Action - Enable or Disable + * action - Enable or Disable * * RETURN: Status * @@ -291,7 +327,8 @@ ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake) * ******************************************************************************/ -acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action) +acpi_status +acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action) { acpi_status status = AE_OK; struct acpi_gpe_event_info *gpe_event_info; @@ -324,23 +361,25 @@ acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 ac goto unlock_and_exit; } - register_bit = - acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info); + register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); /* Perform the action */ switch (action) { case ACPI_GPE_ENABLE: + ACPI_SET_BIT(gpe_register_info->enable_for_wake, (u8)register_bit); break; case ACPI_GPE_DISABLE: + ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, (u8)register_bit); break; default: + ACPI_ERROR((AE_INFO, "%u, Invalid action", action)); status = AE_BAD_PARAMETER; break; @@ -398,8 +437,8 @@ ACPI_EXPORT_SYMBOL(acpi_clear_gpe) * * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 * gpe_number - GPE level within the GPE block - * event_status - Where the current status of the event will - * be returned + * event_status - Where the current status of the event + * will be returned * * RETURN: Status * @@ -433,7 +472,7 @@ acpi_get_gpe_status(acpi_handle gpe_device, if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) *event_status |= ACPI_EVENT_FLAG_HANDLE; - unlock_and_exit: +unlock_and_exit: acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } @@ -507,7 +546,7 @@ ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes) * FUNCTION: acpi_install_gpe_block * * PARAMETERS: gpe_device - Handle to the parent GPE Block Device - * gpe_block_address - Address and space_iD + * gpe_block_address - Address and space_ID * register_count - Number of GPE register pairs in the block * interrupt_number - H/W interrupt for the block * @@ -535,7 +574,7 @@ acpi_install_gpe_block(acpi_handle gpe_device, status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { - return (status); + return_ACPI_STATUS(status); } node = acpi_ns_validate_handle(gpe_device); @@ -544,13 +583,26 @@ acpi_install_gpe_block(acpi_handle gpe_device, goto unlock_and_exit; } + /* Validate the parent device */ + + if (node->type != ACPI_TYPE_DEVICE) { + status = AE_TYPE; + goto unlock_and_exit; + } + + if (node->object) { + status = AE_ALREADY_EXISTS; + goto unlock_and_exit; + } + /* * For user-installed GPE Block Devices, the gpe_block_base_number * is always zero */ - status = - acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0, - interrupt_number, &gpe_block); + status = acpi_ev_create_gpe_block(node, gpe_block_address->address, + gpe_block_address->space_id, + register_count, 0, interrupt_number, + &gpe_block); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } @@ -586,7 +638,7 @@ acpi_install_gpe_block(acpi_handle gpe_device, obj_desc->device.gpe_block = gpe_block; - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } @@ -618,7 +670,7 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { - return (status); + return_ACPI_STATUS(status); } node = acpi_ns_validate_handle(gpe_device); @@ -627,6 +679,13 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) goto unlock_and_exit; } + /* Validate the parent device */ + + if (node->type != ACPI_TYPE_DEVICE) { + status = AE_TYPE; + goto unlock_and_exit; + } + /* Get the device_object attached to the node */ obj_desc = acpi_ns_get_attached_object(node); @@ -641,7 +700,7 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) obj_desc->device.gpe_block = NULL; } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } @@ -652,7 +711,7 @@ ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block) * * FUNCTION: acpi_get_gpe_device * - * PARAMETERS: Index - System GPE index (0-current_gpe_count) + * PARAMETERS: index - System GPE index (0-current_gpe_count) * gpe_device - Where the parent GPE Device is returned * * RETURN: Status @@ -662,8 +721,7 @@ ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block) * the FADT-defined gpe blocks. Otherwise, the GPE block device. * ******************************************************************************/ -acpi_status -acpi_get_gpe_device(u32 index, acpi_handle *gpe_device) +acpi_status acpi_get_gpe_device(u32 index, acpi_handle * gpe_device) { struct acpi_gpe_device_info info; acpi_status status; @@ -695,3 +753,4 @@ acpi_get_gpe_device(u32 index, acpi_handle *gpe_device) } ACPI_EXPORT_SYMBOL(acpi_get_gpe_device) +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 6019208cd4b..2d6f187939c 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,7 +42,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include <linux/export.h> +#define EXPORT_ACPI_INTERFACES + #include <acpi/acpi.h> #include "accommon.h" #include "acnamesp.h" @@ -55,11 +56,11 @@ ACPI_MODULE_NAME("evxfregn") * * FUNCTION: acpi_install_address_space_handler * - * PARAMETERS: Device - Handle for the device + * PARAMETERS: device - Handle for the device * space_id - The address space ID - * Handler - Address of the handler - * Setup - Address of the setup function - * Context - Value passed to the handler on each access + * handler - Address of the handler + * setup - Address of the setup function + * context - Value passed to the handler on each access * * RETURN: Status * @@ -112,16 +113,16 @@ acpi_install_address_space_handler(acpi_handle device, } /* - * For the default space_iDs, (the IDs for which there are default region handlers + * For the default space_IDs, (the IDs for which there are default region handlers * installed) Only execute the _REG methods if the global initialization _REG * methods have already been run (via acpi_initialize_objects). In other words, - * we will defer the execution of the _REG methods for these space_iDs until + * we will defer the execution of the _REG methods for these space_IDs until * execution of acpi_initialize_objects. This is done because we need the handlers * for the default spaces (mem/io/pci/table) to be installed before we can run * any control methods (or _REG methods). There is known BIOS code that depends * on this. * - * For all other space_iDs, we can safely execute the _REG methods immediately. + * For all other space_IDs, we can safely execute the _REG methods immediately. * This means that for IDs like embedded_controller, this function should be called * only after acpi_enable_subsystem has been called. */ @@ -139,6 +140,7 @@ acpi_install_address_space_handler(acpi_handle device, break; default: + break; } @@ -146,7 +148,7 @@ acpi_install_address_space_handler(acpi_handle device, status = acpi_ev_execute_reg_methods(node, space_id); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } @@ -157,9 +159,9 @@ ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler) * * FUNCTION: acpi_remove_address_space_handler * - * PARAMETERS: Device - Handle for the device + * PARAMETERS: device - Handle for the device * space_id - The address space ID - * Handler - Address of the handler + * handler - Address of the handler * * RETURN: Status * @@ -285,7 +287,7 @@ acpi_remove_address_space_handler(acpi_handle device, status = AE_NOT_EXIST; - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index c86d44e41bc..7d2949420db 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,6 +48,7 @@ #include "actables.h" #include "acdispat.h" #include "acevents.h" +#include "amlcode.h" #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exconfig") @@ -66,7 +67,7 @@ acpi_ex_region_read(union acpi_operand_object *obj_desc, * * FUNCTION: acpi_ex_add_table * - * PARAMETERS: Table - Pointer to raw table + * PARAMETERS: table - Pointer to raw table * parent_node - Where to load the table (scope) * ddb_handle - Where to return the table handle. * @@ -120,8 +121,11 @@ acpi_ex_add_table(u32 table_index, acpi_ns_exec_module_code_list(); acpi_ex_enter_interpreter(); - /* Update GPEs for any new _Lxx/_Exx methods. Ignore errors */ - + /* + * Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is + * responsible for discovering any new wake GPEs by running _PRW methods + * that may have been loaded by this table. + */ status = acpi_tb_get_owner_id(table_index, &owner_id); if (ACPI_SUCCESS(status)) { acpi_ev_update_gpes(owner_id); @@ -158,12 +162,12 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, ACPI_FUNCTION_TRACE(ex_load_table_op); - /* Validate lengths for the signature_string, OEMIDString, OEMtable_iD */ + /* Validate lengths for the Signature, oem_id, and oem_table_id strings */ if ((operand[0]->string.length > ACPI_NAME_SIZE) || (operand[1]->string.length > ACPI_OEM_ID_SIZE) || (operand[2]->string.length > ACPI_OEM_TABLE_ID_SIZE)) { - return_ACPI_STATUS(AE_BAD_PARAMETER); + return_ACPI_STATUS(AE_AML_STRING_LIMIT); } /* Find the ACPI table in the RSDT/XSDT */ @@ -210,8 +214,8 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, /* parameter_path (optional parameter) */ if (operand[4]->string.length > 0) { - if ((operand[4]->string.pointer[0] != '\\') && - (operand[4]->string.pointer[0] != '^')) { + if ((operand[4]->string.pointer[0] != AML_ROOT_PREFIX) && + (operand[4]->string.pointer[0] != AML_PARENT_PREFIX)) { /* * Path is not absolute, so it will be relative to the node * referenced by the root_path_string (or the NS root if omitted) @@ -276,8 +280,8 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, * FUNCTION: acpi_ex_region_read * * PARAMETERS: obj_desc - Region descriptor - * Length - Number of bytes to read - * Buffer - Pointer to where to put the data + * length - Number of bytes to read + * buffer - Pointer to where to put the data * * RETURN: Status * @@ -301,7 +305,7 @@ acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer) acpi_ev_address_space_dispatch(obj_desc, NULL, ACPI_READ, region_offset, 8, &value); if (ACPI_FAILURE(status)) { - return status; + return (status); } *buffer = (u8)value; @@ -309,7 +313,7 @@ acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer) region_offset++; } - return AE_OK; + return (AE_OK); } /******************************************************************************* @@ -318,7 +322,7 @@ acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer) * * PARAMETERS: obj_desc - Region or Buffer/Field where the table will be * obtained - * Target - Where a handle to the table will be stored + * target - Where a handle to the table will be stored * walk_state - Current state * * RETURN: Status @@ -339,16 +343,14 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, struct acpi_walk_state *walk_state) { union acpi_operand_object *ddb_handle; + struct acpi_table_header *table_header; struct acpi_table_header *table; - struct acpi_table_desc table_desc; u32 table_index; acpi_status status; u32 length; ACPI_FUNCTION_TRACE(ex_load_op); - ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc)); - /* Source Object can be either an op_region or a Buffer/Field */ switch (obj_desc->common.type) { @@ -376,17 +378,17 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, /* Get the table header first so we can get the table length */ - table = ACPI_ALLOCATE(sizeof(struct acpi_table_header)); - if (!table) { + table_header = ACPI_ALLOCATE(sizeof(struct acpi_table_header)); + if (!table_header) { return_ACPI_STATUS(AE_NO_MEMORY); } status = acpi_ex_region_read(obj_desc, sizeof(struct acpi_table_header), - ACPI_CAST_PTR(u8, table)); - length = table->length; - ACPI_FREE(table); + ACPI_CAST_PTR(u8, table_header)); + length = table_header->length; + ACPI_FREE(table_header); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -416,22 +418,19 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, /* Allocate a buffer for the table */ - table_desc.pointer = ACPI_ALLOCATE(length); - if (!table_desc.pointer) { + table = ACPI_ALLOCATE(length); + if (!table) { return_ACPI_STATUS(AE_NO_MEMORY); } /* Read the entire table */ status = acpi_ex_region_read(obj_desc, length, - ACPI_CAST_PTR(u8, - table_desc.pointer)); + ACPI_CAST_PTR(u8, table)); if (ACPI_FAILURE(status)) { - ACPI_FREE(table_desc.pointer); + ACPI_FREE(table); return_ACPI_STATUS(status); } - - table_desc.address = obj_desc->region.address; break; case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ @@ -448,10 +447,10 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, /* Get the actual table length from the table header */ - table = + table_header = ACPI_CAST_PTR(struct acpi_table_header, obj_desc->buffer.pointer); - length = table->length; + length = table_header->length; /* Table cannot extend beyond the buffer */ @@ -466,40 +465,45 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, * Copy the table from the buffer because the buffer could be modified * or even deleted in the future */ - table_desc.pointer = ACPI_ALLOCATE(length); - if (!table_desc.pointer) { + table = ACPI_ALLOCATE(length); + if (!table) { return_ACPI_STATUS(AE_NO_MEMORY); } - ACPI_MEMCPY(table_desc.pointer, table, length); - table_desc.address = ACPI_TO_INTEGER(table_desc.pointer); + ACPI_MEMCPY(table, table_header, length); break; default: + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } - /* Validate table checksum (will not get validated in tb_add_table) */ - - status = acpi_tb_verify_checksum(table_desc.pointer, length); - if (ACPI_FAILURE(status)) { - ACPI_FREE(table_desc.pointer); - return_ACPI_STATUS(status); - } + /* Install the new table into the local data structures */ - /* Complete the table descriptor */ + ACPI_INFO((AE_INFO, "Dynamic OEM Table Load:")); + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - table_desc.length = length; - table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; + status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table), + ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, + TRUE, TRUE, &table_index); - /* Install the new table into the local data structures */ - - status = acpi_tb_add_table(&table_desc, &table_index); + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); if (ACPI_FAILURE(status)) { /* Delete allocated table buffer */ - acpi_tb_delete_table(&table_desc); + ACPI_FREE(table); + return_ACPI_STATUS(status); + } + + /* + * Note: Now table is "INSTALLED", it must be validated before + * loading. + */ + status = + acpi_tb_validate_table(&acpi_gbl_root_table_list. + tables[table_index]); + if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -531,9 +535,6 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, return_ACPI_STATUS(status); } - ACPI_INFO((AE_INFO, "Dynamic OEM Table Load:")); - acpi_tb_print_table_header(0, table_desc.pointer); - /* Remove the reference by added by acpi_ex_store above */ acpi_ut_remove_reference(ddb_handle); @@ -541,8 +542,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, /* Invoke table handler if present */ if (acpi_gbl_table_handler) { - (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, - table_desc.pointer, + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table, acpi_gbl_table_handler_context); } @@ -571,6 +571,13 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) ACPI_FUNCTION_TRACE(ex_unload_table); /* + * Temporarily emit a warning so that the ASL for the machine can be + * hopefully obtained. This is to say that the Unload() operator is + * extremely rare if not completely unused. + */ + ACPI_WARNING((AE_INFO, "Received request to unload an ACPI table")); + + /* * Validate the handle * Although the handle is partially validated in acpi_ex_reconfiguration() * when it calls acpi_ex_resolve_operands(), the handle is more completely @@ -584,7 +591,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle) != ACPI_DESC_TYPE_OPERAND) || (ddb_handle->common.type != ACPI_TYPE_LOCAL_REFERENCE) || (!(ddb_handle->common.flags & AOPOBJ_DATA_VALID))) { - return_ACPI_STATUS(AE_BAD_PARAMETER); + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } /* Get the table index from the ddb_handle */ diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c index e385436bd42..c545386fee9 100644 --- a/drivers/acpi/acpica/exconvrt.c +++ b/drivers/acpi/acpica/exconvrt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -60,7 +60,7 @@ acpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 max_length); * PARAMETERS: obj_desc - Object to be converted. Must be an * Integer, Buffer, or String * result_desc - Where the new Integer object is returned - * Flags - Used for string conversion + * flags - Used for string conversion * * RETURN: Status * @@ -99,6 +99,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, break; default: + return_ACPI_STATUS(AE_TYPE); } @@ -117,7 +118,6 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, switch (obj_desc->common.type) { case ACPI_TYPE_STRING: - /* * Convert string to an integer - for most cases, the string must be * hexadecimal as per the ACPI specification. The only exception (as @@ -161,6 +161,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, default: /* No other types can get here */ + break; } @@ -176,7 +177,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, /* Save the Result */ - acpi_ex_truncate_for32bit_table(return_desc); + (void)acpi_ex_truncate_for32bit_table(return_desc); *result_desc = return_desc; return_ACPI_STATUS(AE_OK); } @@ -213,7 +214,6 @@ acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_OK); case ACPI_TYPE_INTEGER: - /* * Create a new Buffer object. * Need enough space for one integer @@ -233,7 +233,6 @@ acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc, break; case ACPI_TYPE_STRING: - /* * Create a new Buffer object * Size will be the string length @@ -258,6 +257,7 @@ acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc, break; default: + return_ACPI_STATUS(AE_TYPE); } @@ -272,9 +272,9 @@ acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc, * * FUNCTION: acpi_ex_convert_to_ascii * - * PARAMETERS: Integer - Value to be converted - * Base - ACPI_STRING_DECIMAL or ACPI_STRING_HEX - * String - Where the string is returned + * PARAMETERS: integer - Value to be converted + * base - ACPI_STRING_DECIMAL or ACPI_STRING_HEX + * string - Where the string is returned * data_width - Size of data item to be converted, in bytes * * RETURN: Actual string length @@ -304,15 +304,18 @@ acpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 data_width) switch (data_width) { case 1: + decimal_length = ACPI_MAX8_DECIMAL_DIGITS; break; case 4: + decimal_length = ACPI_MAX32_DECIMAL_DIGITS; break; case 8: default: + decimal_length = ACPI_MAX64_DECIMAL_DIGITS; break; } @@ -385,7 +388,7 @@ acpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 data_width) * PARAMETERS: obj_desc - Object to be converted. Must be an * Integer, Buffer, or String * result_desc - Where the string object is returned - * Type - String flags (base and conversion type) + * type - String flags (base and conversion type) * * RETURN: Status * @@ -516,8 +519,8 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, string_length--; } - return_desc = acpi_ut_create_string_object((acpi_size) - string_length); + return_desc = + acpi_ut_create_string_object((acpi_size) string_length); if (!return_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -546,6 +549,7 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, break; default: + return_ACPI_STATUS(AE_TYPE); } @@ -599,6 +603,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, break; default: + /* No conversion allowed for these types */ if (destination_type != source_desc->common.type) { @@ -649,6 +654,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, break; default: + ACPI_ERROR((AE_INFO, "Bad destination type during conversion: 0x%X", destination_type)); @@ -664,6 +670,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, break; default: + ACPI_ERROR((AE_INFO, "Unknown Target type ID 0x%X AmlOpcode 0x%X DestType %s", GET_CURRENT_ARG_TYPE(walk_state->op_info-> diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c index 3f5bc998c1c..95d23dabcfb 100644 --- a/drivers/acpi/acpica/excreate.c +++ b/drivers/acpi/acpica/excreate.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -78,7 +78,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { /* * Dereference an existing alias so that we don't create a chain - * of aliases. With this code, we guarantee that an alias is + * of aliases. With this code, we guarantee that an alias is * always exactly one level of indirection away from the * actual aliased name. */ @@ -90,7 +90,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) /* * For objects that can never change (i.e., the NS node will * permanently point to the same object), we can simply attach - * the object to the new NS node. For other objects (such as + * the object to the new NS node. For other objects (such as * Integers, buffers, etc.), we have to point the Alias node * to the original Node. */ @@ -103,7 +103,6 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) case ACPI_TYPE_BUFFER: case ACPI_TYPE_PACKAGE: case ACPI_TYPE_BUFFER_FIELD: - /* * These types open a new scope, so we need the NS node in order to access * any children. @@ -113,7 +112,6 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_THERMAL: case ACPI_TYPE_LOCAL_SCOPE: - /* * The new alias has the type ALIAS and points to the original * NS node, not the object itself. @@ -124,7 +122,6 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) break; case ACPI_TYPE_METHOD: - /* * Control method aliases need to be differentiated */ @@ -139,7 +136,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) /* * The new alias assumes the type of the target, and it points - * to the same object. The reference count of the object has an + * to the same object. The reference count of the object has an * additional reference to prevent deletion out from under either the * target node or the alias Node */ @@ -196,7 +193,7 @@ acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state) acpi_ns_attach_object((struct acpi_namespace_node *)walk_state-> operands[0], obj_desc, ACPI_TYPE_EVENT); - cleanup: +cleanup: /* * Remove local reference to the object (on error, will cause deletion * of both object and semaphore if present.) @@ -243,8 +240,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state) /* Init object and attach to NS node */ - obj_desc->mutex.sync_level = - (u8) walk_state->operands[1]->integer.value; + obj_desc->mutex.sync_level = (u8)walk_state->operands[1]->integer.value; obj_desc->mutex.node = (struct acpi_namespace_node *)walk_state->operands[0]; @@ -252,7 +248,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state) acpi_ns_attach_object(obj_desc->mutex.node, obj_desc, ACPI_TYPE_MUTEX); - cleanup: +cleanup: /* * Remove local reference to the object (on error, will cause deletion * of both object and semaphore if present.) @@ -351,7 +347,7 @@ acpi_ex_create_region(u8 * aml_start, status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION); - cleanup: +cleanup: /* Remove local reference to the object */ @@ -369,7 +365,7 @@ acpi_ex_create_region(u8 * aml_start, * * DESCRIPTION: Create a new processor object and populate the fields * - * Processor (Name[0], cpu_iD[1], pblock_addr[2], pblock_length[3]) + * Processor (Name[0], cpu_ID[1], pblock_addr[2], pblock_length[3]) * ******************************************************************************/ @@ -524,7 +520,7 @@ acpi_ex_create_method(u8 * aml_start, acpi_ut_remove_reference(obj_desc); - exit: +exit: /* Remove a reference to the operand */ acpi_ut_remove_reference(operand[1]); diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c index e211e9c1921..4cfc3d3b5c9 100644 --- a/drivers/acpi/acpica/exdebug.c +++ b/drivers/acpi/acpica/exdebug.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,8 +54,8 @@ ACPI_MODULE_NAME("exdebug") * FUNCTION: acpi_ex_do_debug_object * * PARAMETERS: source_desc - Object to be output to "Debug Object" - * Level - Indentation level (used for packages) - * Index - Current package element, zero if not pkg + * level - Indentation level (used for packages) + * index - Current package element, zero if not pkg * * RETURN: None * @@ -145,10 +145,10 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, case ACPI_TYPE_BUFFER: acpi_os_printf("[0x%.2X]\n", (u32)source_desc->buffer.length); - acpi_ut_dump_buffer2(source_desc->buffer.pointer, - (source_desc->buffer.length < 256) ? - source_desc->buffer.length : 256, - DB_BYTE_DISPLAY); + acpi_ut_dump_buffer(source_desc->buffer.pointer, + (source_desc->buffer.length < 256) ? + source_desc->buffer.length : 256, + DB_BYTE_DISPLAY, 0); break; case ACPI_TYPE_STRING: @@ -190,9 +190,10 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, acpi_os_printf("Table Index 0x%X\n", source_desc->reference.value); - return; + return_VOID; default: + break; } @@ -226,6 +227,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, break; default: + acpi_ex_do_debug_object((source_desc-> reference. node)->object, diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index 2a6ac0a3bc1..925202acc3e 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -94,12 +94,13 @@ static struct acpi_exdump_info acpi_ex_dump_buffer[5] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_buffer), NULL}, {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(buffer.length), "Length"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(buffer.pointer), "Pointer"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(buffer.node), "Parent Node"}, + {ACPI_EXD_NODE, ACPI_EXD_OFFSET(buffer.node), "Parent Node"}, {ACPI_EXD_BUFFER, 0, NULL} }; -static struct acpi_exdump_info acpi_ex_dump_package[5] = { +static struct acpi_exdump_info acpi_ex_dump_package[6] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_package), NULL}, + {ACPI_EXD_NODE, ACPI_EXD_OFFSET(package.node), "Parent Node"}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(package.flags), "Flags"}, {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(package.count), "Elements"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(package.elements), "Element List"}, @@ -108,11 +109,11 @@ static struct acpi_exdump_info acpi_ex_dump_package[5] = { static struct acpi_exdump_info acpi_ex_dump_device[4] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_device), NULL}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.handler), "Handler"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.system_notify), + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.notify_list[0]), "System Notify"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.device_notify), - "Device Notify"} + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.notify_list[1]), + "Device Notify"}, + {ACPI_EXD_HDLR_LIST, ACPI_EXD_OFFSET(device.handler), "Handler"} }; static struct acpi_exdump_info acpi_ex_dump_event[2] = { @@ -133,35 +134,39 @@ static struct acpi_exdump_info acpi_ex_dump_method[9] = { {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.aml_start), "Aml Start"} }; -static struct acpi_exdump_info acpi_ex_dump_mutex[5] = { +static struct acpi_exdump_info acpi_ex_dump_mutex[6] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.original_sync_level), + "Original Sync Level"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread), "Owner Thread"}, {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth), "Acquire Depth"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.os_mutex), "OsMutex"} }; -static struct acpi_exdump_info acpi_ex_dump_region[7] = { +static struct acpi_exdump_info acpi_ex_dump_region[8] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_region), NULL}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(region.space_id), "Space Id"}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(region.flags), "Flags"}, + {ACPI_EXD_NODE, ACPI_EXD_OFFSET(region.node), "Parent Node"}, {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET(region.address), "Address"}, {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(region.length), "Length"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(region.handler), "Handler"}, + {ACPI_EXD_HDLR_LIST, ACPI_EXD_OFFSET(region.handler), "Handler"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(region.next), "Next"} }; -static struct acpi_exdump_info acpi_ex_dump_power[5] = { +static struct acpi_exdump_info acpi_ex_dump_power[6] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_power), NULL}, {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(power_resource.system_level), "System Level"}, {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(power_resource.resource_order), "Resource Order"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.system_notify), + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.notify_list[0]), "System Notify"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.device_notify), - "Device Notify"} + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.notify_list[1]), + "Device Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.handler), "Handler"} }; static struct acpi_exdump_info acpi_ex_dump_processor[7] = { @@ -169,18 +174,18 @@ static struct acpi_exdump_info acpi_ex_dump_processor[7] = { {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(processor.proc_id), "Processor ID"}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(processor.length), "Length"}, {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET(processor.address), "Address"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.system_notify), + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.notify_list[0]), "System Notify"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.device_notify), + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.notify_list[1]), "Device Notify"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.handler), "Handler"} }; static struct acpi_exdump_info acpi_ex_dump_thermal[4] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_thermal), NULL}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.system_notify), + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.notify_list[0]), "System Notify"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.device_notify), + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.notify_list[1]), "Device Notify"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.handler), "Handler"} }; @@ -225,7 +230,7 @@ static struct acpi_exdump_info acpi_ex_dump_reference[8] = { {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.target_type), "Target Type"}, {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(reference.value), "Value"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.object), "Object Desc"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.node), "Node"}, + {ACPI_EXD_NODE, ACPI_EXD_OFFSET(reference.node), "Node"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.where), "Where"}, {ACPI_EXD_REFERENCE, 0, NULL} }; @@ -234,27 +239,49 @@ static struct acpi_exdump_info acpi_ex_dump_address_handler[6] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_address_handler), NULL}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(address_space.space_id), "Space Id"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.next), "Next"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.region_list), + {ACPI_EXD_HDLR_LIST, ACPI_EXD_OFFSET(address_space.next), "Next"}, + {ACPI_EXD_RGN_LIST, ACPI_EXD_OFFSET(address_space.region_list), "Region List"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.node), "Node"}, + {ACPI_EXD_NODE, ACPI_EXD_OFFSET(address_space.node), "Node"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.context), "Context"} }; -static struct acpi_exdump_info acpi_ex_dump_notify[3] = { +static struct acpi_exdump_info acpi_ex_dump_notify[7] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_notify), NULL}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.node), "Node"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.context), "Context"} + {ACPI_EXD_NODE, ACPI_EXD_OFFSET(notify.node), "Node"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(notify.handler_type), "Handler Type"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.handler), "Handler"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.context), "Context"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.next[0]), + "Next System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.next[1]), "Next Device Notify"} +}; + +static struct acpi_exdump_info acpi_ex_dump_extra[6] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_extra), NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(extra.method_REG), "_REG Method"}, + {ACPI_EXD_NODE, ACPI_EXD_OFFSET(extra.scope_node), "Scope Node"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(extra.region_context), + "Region Context"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(extra.aml_start), "Aml Start"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(extra.aml_length), "Aml Length"} +}; + +static struct acpi_exdump_info acpi_ex_dump_data[3] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_data), NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(data.handler), "Handler"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(data.pointer), "Raw Data"} }; /* Miscellaneous tables */ -static struct acpi_exdump_info acpi_ex_dump_common[4] = { +static struct acpi_exdump_info acpi_ex_dump_common[5] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_common), NULL}, {ACPI_EXD_TYPE, 0, NULL}, {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(common.reference_count), "Reference Count"}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common.flags), "Flags"} + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common.flags), "Flags"}, + {ACPI_EXD_LIST, ACPI_EXD_OFFSET(common.next_object), "Object List"} }; static struct acpi_exdump_info acpi_ex_dump_field_common[7] = { @@ -269,15 +296,17 @@ static struct acpi_exdump_info acpi_ex_dump_field_common[7] = { "Field Bit Offset"}, {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(common_field.base_byte_offset), "Base Byte Offset"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(common_field.node), "Parent Node"} + {ACPI_EXD_NODE, ACPI_EXD_OFFSET(common_field.node), "Parent Node"} }; -static struct acpi_exdump_info acpi_ex_dump_node[5] = { +static struct acpi_exdump_info acpi_ex_dump_node[7] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_node), NULL}, {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(flags), "Flags"}, {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(owner_id), "Owner Id"}, - {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(child), "Child List"}, - {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(peer), "Next Peer"} + {ACPI_EXD_LIST, ACPI_EXD_NSOFFSET(object), "Object List"}, + {ACPI_EXD_NODE, ACPI_EXD_NSOFFSET(parent), "Parent"}, + {ACPI_EXD_NODE, ACPI_EXD_NSOFFSET(child), "Child"}, + {ACPI_EXD_NODE, ACPI_EXD_NSOFFSET(peer), "Peer"} }; /* Dispatch table, indexed by object type */ @@ -310,7 +339,9 @@ static struct acpi_exdump_info *acpi_ex_dump_info[] = { acpi_ex_dump_address_handler, NULL, NULL, - NULL + NULL, + acpi_ex_dump_extra, + acpi_ex_dump_data }; /******************************************************************************* @@ -318,7 +349,7 @@ static struct acpi_exdump_info *acpi_ex_dump_info[] = { * FUNCTION: acpi_ex_dump_object * * PARAMETERS: obj_desc - Descriptor to dump - * Info - Info table corresponding to this object + * info - Info table corresponding to this object * type * * RETURN: None @@ -333,7 +364,12 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, { u8 *target; char *name; + const char *reference_name; u8 count; + union acpi_operand_object *start; + union acpi_operand_object *data = NULL; + union acpi_operand_object *next; + struct acpi_namespace_node *node; if (!info) { acpi_os_printf @@ -352,13 +388,14 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, switch (info->opcode) { case ACPI_EXD_INIT: + break; case ACPI_EXD_TYPE: - acpi_ex_out_string("Type", - acpi_ut_get_object_type_name - (obj_desc)); + acpi_os_printf("%20s : %2.2X [%s]\n", "Type", + obj_desc->common.type, + acpi_ut_get_object_type_name(obj_desc)); break; case ACPI_EXD_UINT8: @@ -420,13 +457,127 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, case ACPI_EXD_REFERENCE: + reference_name = acpi_ut_get_reference_name(obj_desc); acpi_ex_out_string("Class Name", - ACPI_CAST_PTR(char, - acpi_ut_get_reference_name - (obj_desc))); + ACPI_CAST_PTR(char, reference_name)); acpi_ex_dump_reference_obj(obj_desc); break; + case ACPI_EXD_LIST: + + start = *ACPI_CAST_PTR(void *, target); + next = start; + + acpi_os_printf("%20s : %p", name, next); + if (next) { + acpi_os_printf("(%s %2.2X)", + acpi_ut_get_object_type_name + (next), next->common.type); + + while (next->common.next_object) { + if ((next->common.type == + ACPI_TYPE_LOCAL_DATA) && !data) { + data = next; + } + + next = next->common.next_object; + acpi_os_printf("->%p(%s %2.2X)", next, + acpi_ut_get_object_type_name + (next), + next->common.type); + + if ((next == start) || (next == data)) { + acpi_os_printf + ("\n**** Error: Object list appears to be circular linked"); + break; + } + } + } + + acpi_os_printf("\n", next); + break; + + case ACPI_EXD_HDLR_LIST: + + start = *ACPI_CAST_PTR(void *, target); + next = start; + + acpi_os_printf("%20s : %p", name, next); + if (next) { + acpi_os_printf("(%s %2.2X)", + acpi_ut_get_object_type_name + (next), next->common.type); + + while (next->address_space.next) { + if ((next->common.type == + ACPI_TYPE_LOCAL_DATA) && !data) { + data = next; + } + + next = next->address_space.next; + acpi_os_printf("->%p(%s %2.2X)", next, + acpi_ut_get_object_type_name + (next), + next->common.type); + + if ((next == start) || (next == data)) { + acpi_os_printf + ("\n**** Error: Handler list appears to be circular linked"); + break; + } + } + } + + acpi_os_printf("\n", next); + break; + + case ACPI_EXD_RGN_LIST: + + start = *ACPI_CAST_PTR(void *, target); + next = start; + + acpi_os_printf("%20s : %p", name, next); + if (next) { + acpi_os_printf("(%s %2.2X)", + acpi_ut_get_object_type_name + (next), next->common.type); + + while (next->region.next) { + if ((next->common.type == + ACPI_TYPE_LOCAL_DATA) && !data) { + data = next; + } + + next = next->region.next; + acpi_os_printf("->%p(%s %2.2X)", next, + acpi_ut_get_object_type_name + (next), + next->common.type); + + if ((next == start) || (next == data)) { + acpi_os_printf + ("\n**** Error: Region list appears to be circular linked"); + break; + } + } + } + + acpi_os_printf("\n", next); + break; + + case ACPI_EXD_NODE: + + node = + *ACPI_CAST_PTR(struct acpi_namespace_node *, + target); + + acpi_os_printf("%20s : %p", name, node); + if (node) { + acpi_os_printf(" [%4.4s]", node->name.ascii); + } + acpi_os_printf("\n"); + break; + default: acpi_os_printf("**** Invalid table opcode [%X] ****\n", @@ -444,7 +595,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, * FUNCTION: acpi_ex_dump_operand * * PARAMETERS: *obj_desc - Pointer to entry to be dumped - * Depth - Current nesting depth + * depth - Current nesting depth * * RETURN: None * @@ -459,8 +610,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) ACPI_FUNCTION_NAME(ex_dump_operand) - if (!((ACPI_LV_EXEC & acpi_dbg_level) - && (_COMPONENT & acpi_dbg_layer))) { + /* Check if debug output enabled */ + if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_EXEC, _COMPONENT)) { return; } @@ -713,6 +864,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) break; default: + /* Unknown Type */ acpi_os_printf("Unknown Type %X\n", obj_desc->common.type); @@ -726,7 +878,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) * * FUNCTION: acpi_ex_dump_operands * - * PARAMETERS: Operands - A list of Operand objects + * PARAMETERS: operands - A list of Operand objects * opcode_name - AML opcode name * num_operands - Operand count for this opcode * @@ -769,10 +921,10 @@ acpi_ex_dump_operands(union acpi_operand_object **operands, * * FUNCTION: acpi_ex_out* functions * - * PARAMETERS: Title - Descriptive text - * Value - Value to be displayed + * PARAMETERS: title - Descriptive text + * value - Value to be displayed * - * DESCRIPTION: Object dump output formatting functions. These functions + * DESCRIPTION: Object dump output formatting functions. These functions * reduce the number of format strings required and keeps them * all in one place for easy modification. * @@ -792,8 +944,8 @@ static void acpi_ex_out_pointer(char *title, void *value) * * FUNCTION: acpi_ex_dump_namespace_node * - * PARAMETERS: Node - Descriptor to dump - * Flags - Force display if TRUE + * PARAMETERS: node - Descriptor to dump + * flags - Force display if TRUE * * DESCRIPTION: Dumps the members of the given.Node * @@ -805,17 +957,17 @@ void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags) ACPI_FUNCTION_ENTRY(); if (!flags) { - if (!((ACPI_LV_OBJECTS & acpi_dbg_level) - && (_COMPONENT & acpi_dbg_layer))) { + + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_OBJECTS, _COMPONENT)) { return; } } acpi_os_printf("%20s : %4.4s\n", "Name", acpi_ut_get_node_name(node)); - acpi_ex_out_string("Type", acpi_ut_get_type_name(node->type)); - acpi_ex_out_pointer("Attached Object", - acpi_ns_get_attached_object(node)); - acpi_ex_out_pointer("Parent", node->parent); + acpi_os_printf("%20s : %2.2X [%s]\n", "Type", + node->type, acpi_ut_get_type_name(node->type)); acpi_ex_dump_object(ACPI_CAST_PTR(union acpi_operand_object, node), acpi_ex_dump_node); @@ -825,7 +977,7 @@ void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags) * * FUNCTION: acpi_ex_dump_reference_obj * - * PARAMETERS: Object - Descriptor to dump + * PARAMETERS: object - Descriptor to dump * * DESCRIPTION: Dumps a reference object * @@ -882,8 +1034,8 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc) * FUNCTION: acpi_ex_dump_package_obj * * PARAMETERS: obj_desc - Descriptor to dump - * Level - Indentation Level - * Index - Package index for this object + * level - Indentation Level + * index - Package index for this object * * DESCRIPTION: Dumps the elements of the package * @@ -926,9 +1078,7 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, case ACPI_TYPE_STRING: acpi_os_printf("[String] Value: "); - for (i = 0; i < obj_desc->string.length; i++) { - acpi_os_printf("%c", obj_desc->string.pointer[i]); - } + acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX); acpi_os_printf("\n"); break; @@ -937,10 +1087,11 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, acpi_os_printf("[Buffer] Length %.2X = ", obj_desc->buffer.length); if (obj_desc->buffer.length) { - acpi_ut_dump_buffer(ACPI_CAST_PTR - (u8, obj_desc->buffer.pointer), - obj_desc->buffer.length, - DB_DWORD_DISPLAY, _COMPONENT); + acpi_ut_debug_dump_buffer(ACPI_CAST_PTR + (u8, + obj_desc->buffer.pointer), + obj_desc->buffer.length, + DB_DWORD_DISPLAY, _COMPONENT); } else { acpi_os_printf("\n"); } @@ -977,7 +1128,7 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, * FUNCTION: acpi_ex_dump_object_descriptor * * PARAMETERS: obj_desc - Descriptor to dump - * Flags - Force display if TRUE + * flags - Force display if TRUE * * DESCRIPTION: Dumps the members of the object descriptor given. * @@ -993,8 +1144,10 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags) } if (!flags) { - if (!((ACPI_LV_OBJECTS & acpi_dbg_level) - && (_COMPONENT & acpi_dbg_layer))) { + + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_OBJECTS, _COMPONENT)) { return_VOID; } } @@ -1007,22 +1160,26 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags) ((struct acpi_namespace_node *)obj_desc)-> object); - acpi_ex_dump_object_descriptor(((struct acpi_namespace_node *) - obj_desc)->object, flags); - return_VOID; + obj_desc = ((struct acpi_namespace_node *)obj_desc)->object; + goto dump_object; } if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) { - acpi_os_printf - ("ExDumpObjectDescriptor: %p is not an ACPI operand object: [%s]\n", - obj_desc, acpi_ut_get_descriptor_name(obj_desc)); + acpi_os_printf("%p is not an ACPI operand object: [%s]\n", + obj_desc, acpi_ut_get_descriptor_name(obj_desc)); return_VOID; } - if (obj_desc->common.type > ACPI_TYPE_NS_NODE_MAX) { + /* Validate the object type */ + + if (obj_desc->common.type > ACPI_TYPE_LOCAL_MAX) { + acpi_os_printf("Not a known object type: %2.2X\n", + obj_desc->common.type); return_VOID; } +dump_object: + /* Common Fields */ acpi_ex_dump_object(obj_desc, acpi_ex_dump_common); @@ -1030,6 +1187,22 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags) /* Object-specific fields */ acpi_ex_dump_object(obj_desc, acpi_ex_dump_info[obj_desc->common.type]); + + if (obj_desc->common.type == ACPI_TYPE_REGION) { + obj_desc = obj_desc->common.next_object; + if (obj_desc->common.type > ACPI_TYPE_LOCAL_MAX) { + acpi_os_printf + ("Secondary object is not a known object type: %2.2X\n", + obj_desc->common.type); + + return_VOID; + } + + acpi_os_printf("\nExtra attached Object (%p):\n", obj_desc); + acpi_ex_dump_object(obj_desc, + acpi_ex_dump_info[obj_desc->common.type]); + } + return_VOID; } diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index dc092f5b35d..12878e1982f 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,10 +45,71 @@ #include "accommon.h" #include "acdispat.h" #include "acinterp.h" +#include "amlcode.h" #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exfield") +/* Local prototypes */ +static u32 +acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length); + +/******************************************************************************* + * + * FUNCTION: acpi_get_serial_access_bytes + * + * PARAMETERS: accessor_type - The type of the protocol indicated by region + * field access attributes + * access_length - The access length of the region field + * + * RETURN: Decoded access length + * + * DESCRIPTION: This routine returns the length of the generic_serial_bus + * protocol bytes + * + ******************************************************************************/ + +static u32 +acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length) +{ + u32 length; + + switch (accessor_type) { + case AML_FIELD_ATTRIB_QUICK: + + length = 0; + break; + + case AML_FIELD_ATTRIB_SEND_RCV: + case AML_FIELD_ATTRIB_BYTE: + + length = 1; + break; + + case AML_FIELD_ATTRIB_WORD: + case AML_FIELD_ATTRIB_WORD_CALL: + + length = 2; + break; + + case AML_FIELD_ATTRIB_MULTIBYTE: + case AML_FIELD_ATTRIB_RAW_BYTES: + case AML_FIELD_ATTRIB_RAW_PROCESS: + + length = access_length; + break; + + case AML_FIELD_ATTRIB_BLOCK: + case AML_FIELD_ATTRIB_BLOCK_CALL: + default: + + length = ACPI_GSBUS_BUFFER_SIZE; + break; + } + + return (length); +} + /******************************************************************************* * * FUNCTION: acpi_ex_read_data_from_field @@ -59,12 +120,13 @@ ACPI_MODULE_NAME("exfield") * * RETURN: Status * - * DESCRIPTION: Read from a named field. Returns either an Integer or a + * DESCRIPTION: Read from a named field. Returns either an Integer or a * Buffer, depending on the size of the field. * ******************************************************************************/ + acpi_status -acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, +acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state, union acpi_operand_object *obj_desc, union acpi_operand_object **ret_buffer_desc) { @@ -73,6 +135,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, acpi_size length; void *buffer; u32 function; + u16 accessor_type; ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); @@ -116,9 +179,22 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, ACPI_READ | (obj_desc->field.attribute << 16); } else if (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) { - length = ACPI_GSBUS_BUFFER_SIZE; - function = - ACPI_READ | (obj_desc->field.attribute << 16); + accessor_type = obj_desc->field.attribute; + length = acpi_ex_get_serial_access_length(accessor_type, + obj_desc-> + field. + access_length); + + /* + * Add additional 2 bytes for modeled generic_serial_bus data buffer: + * typedef struct { + * BYTEStatus; // Byte 0 of the data buffer + * BYTELength; // Byte 1 of the data buffer + * BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer, + * } + */ + length += 2; + function = ACPI_READ | (accessor_type << 16); } else { /* IPMI */ length = ACPI_IPMI_BUFFER_SIZE; @@ -149,7 +225,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, * Allocate a buffer for the contents of the field. * * If the field is larger than the current integer width, create - * a BUFFER to hold it. Otherwise, use an INTEGER. This allows + * a BUFFER to hold it. Otherwise, use an INTEGER. This allows * the use of arithmetic operators on the returned value if the * field size is equal or smaller than an Integer. * @@ -197,7 +273,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length); acpi_ex_release_global_lock(obj_desc->common_field.field_flags); - exit: +exit: if (ACPI_FAILURE(status)) { acpi_ut_remove_reference(buffer_desc); } else { @@ -231,6 +307,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, void *buffer; union acpi_operand_object *buffer_desc; u32 function; + u16 accessor_type; ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); @@ -284,9 +361,22 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, ACPI_WRITE | (obj_desc->field.attribute << 16); } else if (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) { - length = ACPI_GSBUS_BUFFER_SIZE; - function = - ACPI_WRITE | (obj_desc->field.attribute << 16); + accessor_type = obj_desc->field.attribute; + length = acpi_ex_get_serial_access_length(accessor_type, + obj_desc-> + field. + access_length); + + /* + * Add additional 2 bytes for modeled generic_serial_bus data buffer: + * typedef struct { + * BYTEStatus; // Byte 0 of the data buffer + * BYTELength; // Byte 1 of the data buffer + * BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer, + * } + */ + length += 2; + function = ACPI_WRITE | (accessor_type << 16); } else { /* IPMI */ length = ACPI_IPMI_BUFFER_SIZE; @@ -331,21 +421,25 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, switch (source_desc->common.type) { case ACPI_TYPE_INTEGER: + buffer = &source_desc->integer.value; length = sizeof(source_desc->integer.value); break; case ACPI_TYPE_BUFFER: + buffer = source_desc->buffer.pointer; length = source_desc->buffer.length; break; case ACPI_TYPE_STRING: + buffer = source_desc->string.pointer; length = source_desc->string.length; break; default: + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index 149de45fdad..1d1b27a96c5 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,8 +54,7 @@ ACPI_MODULE_NAME("exfldio") /* Local prototypes */ static acpi_status acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, - u32 field_datum_byte_offset, - u64 *value, u32 read_write); + u32 field_datum_byte_offset, u64 *value, u32 read_write); static u8 acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value); @@ -124,12 +123,6 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, } } - /* Exit if Address/Length have been disallowed by the host OS */ - - if (rgn_desc->common.flags & AOPOBJ_INVALID) { - return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); - } - /* * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear * address space and the request cannot be directly validated @@ -155,7 +148,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, #endif /* - * Validate the request. The entire request from the byte offset for a + * Validate the request. The entire request from the byte offset for a * length of one field datum (access width) must fit within the region. * (Region length is specified in bytes) */ @@ -183,7 +176,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, obj_desc->common_field.access_byte_width) { /* * This is the case where the access_type (acc_word, etc.) is wider - * than the region itself. For example, a region of length one + * than the region itself. For example, a region of length one * byte, and a field with Dword access specified. */ ACPI_ERROR((AE_INFO, @@ -222,9 +215,9 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, * PARAMETERS: obj_desc - Field to be read * field_datum_byte_offset - Byte offset of this datum within the * parent field - * Value - Where to store value (must at least + * value - Where to store value (must at least * 64 bits) - * Function - Read or Write flag plus other region- + * function - Read or Write flag plus other region- * dependent flags * * RETURN: Status @@ -315,13 +308,13 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, * FUNCTION: acpi_ex_register_overflow * * PARAMETERS: obj_desc - Register(Field) to be written - * Value - Value to be stored + * value - Value to be stored * * RETURN: TRUE if value overflows the field, FALSE otherwise * * DESCRIPTION: Check if a value is out of range of the field being written. * Used to check if the values written to Index and Bank registers - * are out of range. Normally, the value is simply truncated + * are out of range. Normally, the value is simply truncated * to fit the field, but this case is most likely a serious * coding error in the ASL. * @@ -330,7 +323,6 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, static u8 acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value) { - ACPI_FUNCTION_NAME(ex_register_overflow); if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) { /* @@ -365,12 +357,12 @@ acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value) * PARAMETERS: obj_desc - Field to be read * field_datum_byte_offset - Byte offset of this datum within the * parent field - * Value - Where to store value (must be 64 bits) + * value - Where to store value (must be 64 bits) * read_write - Read or Write flag * * RETURN: Status * - * DESCRIPTION: Read or Write a single datum of a field. The field_type is + * DESCRIPTION: Read or Write a single datum of a field. The field_type is * demultiplexed here to handle the different types of fields * (buffer_field, region_field, index_field, bank_field) * @@ -448,7 +440,6 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, break; case ACPI_TYPE_LOCAL_BANK_FIELD: - /* * Ensure that the bank_value is not beyond the capacity of * the register @@ -490,7 +481,6 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, break; case ACPI_TYPE_LOCAL_INDEX_FIELD: - /* * Ensure that the index_value is not beyond the capacity of * the register @@ -574,7 +564,7 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, * FUNCTION: acpi_ex_write_with_update_rule * * PARAMETERS: obj_desc - Field to be written - * Mask - bitmask within field datum + * mask - bitmask within field datum * field_value - Value to write * field_datum_byte_offset - Offset of datum within field * @@ -678,7 +668,7 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc, * FUNCTION: acpi_ex_extract_from_field * * PARAMETERS: obj_desc - Field to be read - * Buffer - Where to store the field data + * buffer - Where to store the field data * buffer_length - Length of Buffer * * RETURN: Status @@ -722,7 +712,19 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, if ((obj_desc->common_field.start_field_bit_offset == 0) && (obj_desc->common_field.bit_length == access_bit_width)) { - status = acpi_ex_field_datum_io(obj_desc, 0, buffer, ACPI_READ); + if (buffer_length >= sizeof(u64)) { + status = + acpi_ex_field_datum_io(obj_desc, 0, buffer, + ACPI_READ); + } else { + /* Use raw_datum (u64) to handle buffers < 64 bits */ + + status = + acpi_ex_field_datum_io(obj_desc, 0, &raw_datum, + ACPI_READ); + ACPI_MEMCPY(buffer, &raw_datum, buffer_length); + } + return_ACPI_STATUS(status); } @@ -823,7 +825,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, * FUNCTION: acpi_ex_insert_into_field * * PARAMETERS: obj_desc - Field to be written - * Buffer - Data to be written + * buffer - Data to be written * buffer_length - Length of Buffer * * RETURN: Status @@ -860,7 +862,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); /* * We must have a buffer that is at least as long as the field - * we are writing to. This is because individual fields are + * we are writing to. This is because individual fields are * indivisible and partial writes are not supported -- as per * the ACPI specification. */ @@ -875,7 +877,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, /* * Copy the original data to the new buffer, starting - * at Byte zero. All unused (upper) bytes of the + * at Byte zero. All unused (upper) bytes of the * buffer will be 0. */ ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length); @@ -994,7 +996,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, mask, merged_datum, field_offset); - exit: +exit: /* Free temporary buffer if we used one */ if (new_buffer) { diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c index 0a089331034..2207e624f53 100644 --- a/drivers/acpi/acpica/exmisc.c +++ b/drivers/acpi/acpica/exmisc.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -106,7 +105,6 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, break; case ACPI_DESC_TYPE_NAMED: - /* * A named reference that has already been resolved to a Node */ @@ -144,8 +142,8 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, * * FUNCTION: acpi_ex_concat_template * - * PARAMETERS: Operand0 - First source object - * Operand1 - Second source object + * PARAMETERS: operand0 - First source object + * operand1 - Second source object * actual_return_desc - Where to place the return object * walk_state - Current walk state * @@ -229,8 +227,8 @@ acpi_ex_concat_template(union acpi_operand_object *operand0, * * FUNCTION: acpi_ex_do_concatenate * - * PARAMETERS: Operand0 - First source object - * Operand1 - Second source object + * PARAMETERS: operand0 - First source object + * operand1 - Second source object * actual_return_desc - Where to place the return object * walk_state - Current walk state * @@ -254,7 +252,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, ACPI_FUNCTION_TRACE(ex_do_concatenate); /* - * Convert the second operand if necessary. The first operand + * Convert the second operand if necessary. The first operand * determines the type of the second operand, (See the Data Types * section of the ACPI specification.) Both object types are * guaranteed to be either Integer/String/Buffer by the operand @@ -262,20 +260,24 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, */ switch (operand0->common.type) { case ACPI_TYPE_INTEGER: + status = acpi_ex_convert_to_integer(operand1, &local_operand1, 16); break; case ACPI_TYPE_STRING: + status = acpi_ex_convert_to_string(operand1, &local_operand1, ACPI_IMPLICIT_CONVERT_HEX); break; case ACPI_TYPE_BUFFER: + status = acpi_ex_convert_to_buffer(operand1, &local_operand1); break; default: + ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X", operand0->common.type)); status = AE_AML_INTERNAL; @@ -386,7 +388,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, *actual_return_desc = return_desc; - cleanup: +cleanup: if (local_operand1 != operand1) { acpi_ut_remove_reference(local_operand1); } @@ -397,9 +399,9 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, * * FUNCTION: acpi_ex_do_math_op * - * PARAMETERS: Opcode - AML opcode - * Integer0 - Integer operand #0 - * Integer1 - Integer operand #1 + * PARAMETERS: opcode - AML opcode + * integer0 - Integer operand #0 + * integer1 - Integer operand #1 * * RETURN: Integer result of the operation * @@ -479,9 +481,9 @@ u64 acpi_ex_do_math_op(u16 opcode, u64 integer0, u64 integer1) * * FUNCTION: acpi_ex_do_logical_numeric_op * - * PARAMETERS: Opcode - AML opcode - * Integer0 - Integer operand #0 - * Integer1 - Integer operand #1 + * PARAMETERS: opcode - AML opcode + * integer0 - Integer operand #0 + * integer1 - Integer operand #1 * logical_result - TRUE/FALSE result of the operation * * RETURN: Status @@ -520,6 +522,7 @@ acpi_ex_do_logical_numeric_op(u16 opcode, break; default: + status = AE_AML_INTERNAL; break; } @@ -534,9 +537,9 @@ acpi_ex_do_logical_numeric_op(u16 opcode, * * FUNCTION: acpi_ex_do_logical_op * - * PARAMETERS: Opcode - AML opcode - * Operand0 - operand #0 - * Operand1 - operand #1 + * PARAMETERS: opcode - AML opcode + * operand0 - operand #0 + * operand1 - operand #1 * logical_result - TRUE/FALSE result of the operation * * RETURN: Status @@ -573,7 +576,7 @@ acpi_ex_do_logical_op(u16 opcode, ACPI_FUNCTION_TRACE(ex_do_logical_op); /* - * Convert the second operand if necessary. The first operand + * Convert the second operand if necessary. The first operand * determines the type of the second operand, (See the Data Types * section of the ACPI 3.0+ specification.) Both object types are * guaranteed to be either Integer/String/Buffer by the operand @@ -581,20 +584,24 @@ acpi_ex_do_logical_op(u16 opcode, */ switch (operand0->common.type) { case ACPI_TYPE_INTEGER: + status = acpi_ex_convert_to_integer(operand1, &local_operand1, 16); break; case ACPI_TYPE_STRING: + status = acpi_ex_convert_to_string(operand1, &local_operand1, ACPI_IMPLICIT_CONVERT_HEX); break; case ACPI_TYPE_BUFFER: + status = acpi_ex_convert_to_buffer(operand1, &local_operand1); break; default: + status = AE_AML_INTERNAL; break; } @@ -637,6 +644,7 @@ acpi_ex_do_logical_op(u16 opcode, break; default: + status = AE_AML_INTERNAL; break; } @@ -704,12 +712,13 @@ acpi_ex_do_logical_op(u16 opcode, break; default: + status = AE_AML_INTERNAL; break; } } - cleanup: +cleanup: /* New object was created if implicit conversion performed - delete */ diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c index 60933e9dc3c..b49ea2a95f4 100644 --- a/drivers/acpi/acpica/exmutex.c +++ b/drivers/acpi/acpica/exmutex.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exmutex - ASL Mutex Acquire/Release functions @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -102,7 +101,7 @@ void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc) * FUNCTION: acpi_ex_link_mutex * * PARAMETERS: obj_desc - The mutex to be linked - * Thread - Current executing thread object + * thread - Current executing thread object * * RETURN: None * @@ -138,7 +137,7 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc, * * FUNCTION: acpi_ex_acquire_mutex_object * - * PARAMETERS: Timeout - Timeout in milliseconds + * PARAMETERS: timeout - Timeout in milliseconds * obj_desc - Mutex object * thread_id - Current thread state * @@ -305,7 +304,7 @@ acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc) ACPI_FUNCTION_TRACE(ex_release_mutex_object); if (obj_desc->mutex.acquisition_depth == 0) { - return (AE_NOT_ACQUIRED); + return_ACPI_STATUS(AE_NOT_ACQUIRED); } /* Match multiple Acquires with multiple Releases */ @@ -378,7 +377,8 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); } - /* Must have a valid thread. */ + /* Must have a valid thread ID */ + if (!walk_state->thread) { ACPI_ERROR((AE_INFO, "Cannot release Mutex [%4.4s], null thread info", @@ -443,7 +443,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, * * FUNCTION: acpi_ex_release_all_mutexes * - * PARAMETERS: Thread - Current executing thread object + * PARAMETERS: thread - Current executing thread object * * RETURN: Status * @@ -462,7 +462,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) union acpi_operand_object *next = thread->acquired_mutex_list; union acpi_operand_object *obj_desc; - ACPI_FUNCTION_ENTRY(); + ACPI_FUNCTION_NAME(ex_release_all_mutexes); /* Traverse the list of owned mutexes, releasing each one */ @@ -474,6 +474,10 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) obj_desc->mutex.next = NULL; obj_desc->mutex.acquisition_depth = 0; + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Force-releasing held mutex: %p\n", + obj_desc)); + /* Release the mutex, special case for Global Lock */ if (obj_desc == acpi_gbl_global_lock_mutex) { diff --git a/drivers/acpi/acpica/exnames.c b/drivers/acpi/acpica/exnames.c index fcc75fa27d3..dbb03b544e8 100644 --- a/drivers/acpi/acpica/exnames.c +++ b/drivers/acpi/acpica/exnames.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exnames - interpreter/scanner name load/execute @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,8 +52,7 @@ ACPI_MODULE_NAME("exnames") /* Local prototypes */ static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs); -static acpi_status -acpi_ex_name_segment(u8 ** in_aml_address, char *name_string); +static acpi_status acpi_ex_name_segment(u8 **in_aml_address, char *name_string); /******************************************************************************* * @@ -64,7 +62,7 @@ acpi_ex_name_segment(u8 ** in_aml_address, char *name_string); * (-1)==root, 0==none * num_name_segs - count of 4-character name segments * - * RETURN: A pointer to the allocated string segment. This segment must + * RETURN: A pointer to the allocated string segment. This segment must * be deleted by the caller. * * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name @@ -178,7 +176,8 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string) ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Bytes from stream:\n")); - for (index = 0; (index < ACPI_NAME_SIZE) + for (index = 0; + (index < ACPI_NAME_SIZE) && (acpi_ut_valid_acpi_char(*aml_address, 0)); index++) { char_buf[index] = *aml_address++; ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index])); diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c index 9ba8c73cea1..1b8e9410440 100644 --- a/drivers/acpi/acpica/exoparg1.c +++ b/drivers/acpi/acpica/exoparg1.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exoparg1 - AML execution - opcodes with 1 argument @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -116,7 +115,7 @@ acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state) break; } - cleanup: +cleanup: /* Delete return object on error */ @@ -235,7 +234,7 @@ acpi_status acpi_ex_opcode_1A_1T_0R(struct acpi_walk_state *walk_state) goto cleanup; } - cleanup: +cleanup: return_ACPI_STATUS(status); } @@ -328,7 +327,6 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) break; case AML_FROM_BCD_OP: /* from_bcd (BCDValue, Result) */ - /* * The 64-bit ACPI integer can hold 16 4-bit BCD characters * (if table is 32-bit, integer can hold 8 BCD characters) @@ -408,7 +406,6 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) break; case AML_COND_REF_OF_OP: /* cond_ref_of (source_object, Result) */ - /* * This op is a little strange because the internal return value is * different than the return value stored in the result descriptor @@ -443,13 +440,14 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) goto cleanup; default: + /* No other opcodes get here */ + break; } break; case AML_STORE_OP: /* Store (Source, Target) */ - /* * A store operand is typically a number, string, buffer or lvalue * Be careful about deleting the source object, @@ -553,7 +551,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) status = acpi_ex_store(return_desc, operand[1], walk_state); } - cleanup: +cleanup: /* Delete return object on error */ @@ -606,7 +604,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) } /* - * Set result to ONES (TRUE) if Value == 0. Note: + * Set result to ONES (TRUE) if Value == 0. Note: * return_desc->Integer.Value is initially == 0 (FALSE) from above. */ if (!operand[0]->integer.value) { @@ -616,9 +614,8 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) case AML_DECREMENT_OP: /* Decrement (Operand) */ case AML_INCREMENT_OP: /* Increment (Operand) */ - /* - * Create a new integer. Can't just get the base integer and + * Create a new integer. Can't just get the base integer and * increment it because it may be an Arg or Field. */ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); @@ -683,10 +680,9 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) break; case AML_TYPE_OP: /* object_type (source_object) */ - /* * Note: The operand is not resolved at this point because we want to - * get the associated object, not its value. For example, we don't + * get the associated object, not its value. For example, we don't * want to resolve a field_unit to its value, we want the actual * field_unit object. */ @@ -710,7 +706,6 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) break; case AML_SIZE_OF_OP: /* size_of (source_object) */ - /* * Note: The operand is not resolved at this point because we want to * get the associated object, not its value. @@ -727,7 +722,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) /* * The type of the base object must be integer, buffer, string, or - * package. All others are not supported. + * package. All others are not supported. * * NOTE: Integer is not specifically supported by the ACPI spec, * but is supported implicitly via implicit operand conversion. @@ -736,10 +731,12 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) */ switch (type) { case ACPI_TYPE_INTEGER: + value = acpi_gbl_integer_byte_width; break; case ACPI_TYPE_STRING: + value = temp_desc->string.length; break; @@ -760,6 +757,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) break; default: + ACPI_ERROR((AE_INFO, "Operand must be Buffer/Integer/String/Package - found type %s", acpi_ut_get_type_name(type))); @@ -861,9 +859,11 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) break; case ACPI_TYPE_STRING: + break; default: + status = AE_AML_OPERAND_TYPE; goto cleanup; } @@ -924,7 +924,6 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) */ switch (operand[0]->reference.class) { case ACPI_REFCLASS_INDEX: - /* * The target type for the Index operator must be * either a Buffer or a Package @@ -949,13 +948,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) */ return_desc = acpi_ut_create_integer_object((u64) - temp_desc-> - buffer. - pointer - [operand - [0]-> - reference. - value]); + temp_desc->buffer.pointer[operand[0]->reference.value]); if (!return_desc) { status = AE_NO_MEMORY; goto cleanup; @@ -963,17 +956,23 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) break; case ACPI_TYPE_PACKAGE: - /* - * Return the referenced element of the package. We must + * Return the referenced element of the package. We must * add another reference to the referenced object, however. */ return_desc = *(operand[0]->reference.where); - if (return_desc) { - acpi_ut_add_reference - (return_desc); + if (!return_desc) { + /* + * Element is NULL, do not allow the dereference. + * This provides compatibility with other ACPI + * implementations. + */ + return_ACPI_STATUS + (AE_AML_UNINITIALIZED_ELEMENT); } + + acpi_ut_add_reference(return_desc); break; default: @@ -998,14 +997,44 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) acpi_namespace_node *) return_desc); - } + if (!return_desc) { + break; + } + + /* + * June 2013: + * buffer_fields/field_units require additional resolution + */ + switch (return_desc->common.type) { + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: - /* Add another reference to the object! */ + status = + acpi_ex_read_data_from_field + (walk_state, return_desc, + &temp_desc); + if (ACPI_FAILURE(status)) { + goto cleanup; + } - acpi_ut_add_reference(return_desc); + return_desc = temp_desc; + break; + + default: + + /* Add another reference to the object */ + + acpi_ut_add_reference + (return_desc); + break; + } + } break; default: + ACPI_ERROR((AE_INFO, "Unknown class in reference(%p) - 0x%2.2X", operand[0], @@ -1025,7 +1054,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) goto cleanup; } - cleanup: +cleanup: /* Delete return object on error */ diff --git a/drivers/acpi/acpica/exoparg2.c b/drivers/acpi/acpica/exoparg2.c index 879e8a277b9..2ede656ee26 100644 --- a/drivers/acpi/acpica/exoparg2.c +++ b/drivers/acpi/acpica/exoparg2.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -123,7 +123,7 @@ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state) /* * Dispatch the notify to the appropriate handler * NOTE: the request is queued for execution after this method - * completes. The notify handlers are NOT invoked synchronously + * completes. The notify handlers are NOT invoked synchronously * from this thread -- because handlers may in turn run other * control methods. */ @@ -215,7 +215,7 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state) goto cleanup; } - cleanup: +cleanup: /* * Since the remainder is not returned indirectly, remove a reference to * it. Only the quotient is returned indirectly. @@ -257,7 +257,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) union acpi_operand_object *return_desc = NULL; u64 index; acpi_status status = AE_OK; - acpi_size length; + acpi_size length = 0; ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_1T_1R, acpi_ps_get_opcode_name(walk_state->opcode)); @@ -304,7 +304,6 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) break; case AML_TO_STRING_OP: /* to_string (Buffer, Length, Result) (ACPI 2.0) */ - /* * Input object is guaranteed to be a buffer at this point (it may have * been converted.) Copy the raw buffer data to a new object of @@ -320,7 +319,6 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) * NOTE: A length of zero is ok, and will create a zero-length, null * terminated string. */ - length = 0; while ((length < operand[0]->buffer.length) && (length < operand[1]->integer.value) && (operand[0]->buffer.pointer[length])) { @@ -376,6 +374,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) case ACPI_TYPE_STRING: if (index >= operand[0]->string.length) { + length = operand[0]->string.length; status = AE_AML_STRING_LIMIT; } @@ -386,6 +385,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) case ACPI_TYPE_BUFFER: if (index >= operand[0]->buffer.length) { + length = operand[0]->buffer.length; status = AE_AML_BUFFER_LIMIT; } @@ -396,6 +396,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) case ACPI_TYPE_PACKAGE: if (index >= operand[0]->package.count) { + length = operand[0]->package.count; status = AE_AML_PACKAGE_LIMIT; } @@ -414,8 +415,9 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, - "Index (0x%8.8X%8.8X) is beyond end of object", - ACPI_FORMAT_UINT64(index))); + "Index (0x%X%8.8X) is beyond end of object (length 0x%X)", + ACPI_FORMAT_UINT64(index), + (u32)length)); goto cleanup; } @@ -443,7 +445,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) break; } - store_result_to_target: +store_result_to_target: if (ACPI_SUCCESS(status)) { /* @@ -460,7 +462,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) } } - cleanup: +cleanup: /* Delete return object on error */ @@ -551,7 +553,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) goto cleanup; } - store_logical_result: +store_logical_result: /* * Set return value to according to logical_result. logical TRUE (all ones) * Default is FALSE (zero) @@ -560,7 +562,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) return_desc->integer.value = ACPI_UINT64_MAX; } - cleanup: +cleanup: /* Delete return object on error */ diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c index 71fcc65c9ff..363767cf01e 100644 --- a/drivers/acpi/acpica/exoparg3.c +++ b/drivers/acpi/acpica/exoparg3.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exoparg3 - AML execution - opcodes with 3 arguments @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -125,7 +124,7 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) goto cleanup; } - cleanup: +cleanup: return_ACPI_STATUS(status); } @@ -156,9 +155,8 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) switch (walk_state->opcode) { case AML_MID_OP: /* Mid (Source[0], Index[1], Length[2], Result[3]) */ - /* - * Create the return object. The Source operand is guaranteed to be + * Create the return object. The Source operand is guaranteed to be * either a String or a Buffer, so just use its type. */ return_desc = acpi_ut_create_internal_object((operand[0])-> @@ -254,7 +252,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) status = acpi_ex_store(return_desc, operand[3], walk_state); - cleanup: +cleanup: /* Delete return object on error */ diff --git a/drivers/acpi/acpica/exoparg6.c b/drivers/acpi/acpica/exoparg6.c index 0786b865906..29e9e99f7fe 100644 --- a/drivers/acpi/acpica/exoparg6.c +++ b/drivers/acpi/acpica/exoparg6.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exoparg6 - AML execution - opcodes with 6 arguments @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -120,7 +119,6 @@ acpi_ex_do_match(u32 match_op, break; case MATCH_MEQ: - /* * True if equal: (P[i] == M) * Change to: (M == P[i]) @@ -134,7 +132,6 @@ acpi_ex_do_match(u32 match_op, break; case MATCH_MLE: - /* * True if less than or equal: (P[i] <= M) (P[i] not_greater than M) * Change to: (M >= P[i]) (M not_less than P[i]) @@ -149,7 +146,6 @@ acpi_ex_do_match(u32 match_op, break; case MATCH_MLT: - /* * True if less than: (P[i] < M) * Change to: (M > P[i]) @@ -163,7 +159,6 @@ acpi_ex_do_match(u32 match_op, break; case MATCH_MGE: - /* * True if greater than or equal: (P[i] >= M) (P[i] not_less than M) * Change to: (M <= P[i]) (M not_greater than P[i]) @@ -178,7 +173,6 @@ acpi_ex_do_match(u32 match_op, break; case MATCH_MGT: - /* * True if greater than: (P[i] > M) * Change to: (M < P[i]) @@ -198,7 +192,7 @@ acpi_ex_do_match(u32 match_op, return (FALSE); } - return logical_result; + return (logical_result); } /******************************************************************************* @@ -269,7 +263,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) * and the next should be examined. * * Upon finding a match, the loop will terminate via "break" at - * the bottom. If it terminates "normally", match_value will be + * the bottom. If it terminates "normally", match_value will be * ACPI_UINT64_MAX (Ones) (its initial value) indicating that no * match was found. */ @@ -320,7 +314,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) goto cleanup; } - cleanup: +cleanup: /* Delete return object on error */ diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c index 30157f5a12d..ee3f872870b 100644 --- a/drivers/acpi/acpica/exprep.c +++ b/drivers/acpi/acpica/exprep.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exprep - ACPI AML (p-code) execution - field prep utilities @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -78,8 +77,8 @@ acpi_ex_generate_access(u32 field_bit_offset, * any_acc keyword. * * NOTE: Need to have the region_length in order to check for boundary - * conditions (end-of-region). However, the region_length is a deferred - * operation. Therefore, to complete this implementation, the generation + * conditions (end-of-region). However, the region_length is a deferred + * operation. Therefore, to complete this implementation, the generation * of this access width must be deferred until the region length has * been evaluated. * @@ -254,26 +253,31 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, case AML_FIELD_ACCESS_BYTE: case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */ + byte_alignment = 1; bit_length = 8; break; case AML_FIELD_ACCESS_WORD: + byte_alignment = 2; bit_length = 16; break; case AML_FIELD_ACCESS_DWORD: + byte_alignment = 4; bit_length = 32; break; case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */ + byte_alignment = 8; bit_length = 64; break; default: + /* Invalid field access type */ ACPI_ERROR((AE_INFO, "Unknown field access type 0x%X", access)); @@ -308,7 +312,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, * RETURN: Status * * DESCRIPTION: Initialize the areas of the field object that are common - * to the various types of fields. Note: This is very "sensitive" + * to the various types of fields. Note: This is very "sensitive" * code because we are solving the general case for field * alignment. * @@ -336,13 +340,13 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, obj_desc->common_field.bit_length = field_bit_length; /* - * Decode the access type so we can compute offsets. The access type gives + * Decode the access type so we can compute offsets. The access type gives * two pieces of information - the width of each field access and the * necessary byte_alignment (address granularity) of the access. * * For any_acc, the access_bit_width is the largest width that is both * necessary and possible in an attempt to access the whole field in one - * I/O operation. However, for any_acc, the byte_alignment is always one + * I/O operation. However, for any_acc, the byte_alignment is always one * byte. * * For all Buffer Fields, the byte_alignment is always one byte. @@ -363,7 +367,7 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, /* * base_byte_offset is the address of the start of the field within the - * region. It is the byte address of the first *datum* (field-width data + * region. It is the byte address of the first *datum* (field-width data * unit) of the field. (i.e., the first datum that contains at least the * first *bit* of the field.) * @@ -391,12 +395,12 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, * * FUNCTION: acpi_ex_prep_field_value * - * PARAMETERS: Info - Contains all field creation info + * PARAMETERS: info - Contains all field creation info * * RETURN: Status * - * DESCRIPTION: Construct a union acpi_operand_object of type def_field and - * connect it to the parent Node. + * DESCRIPTION: Construct an object of type union acpi_operand_object with a + * subtype of def_field and connect it to the parent Node. * ******************************************************************************/ @@ -599,7 +603,9 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) break; default: + /* No other types should get here */ + break; } diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c index 12d51df6d3b..cd5288a257a 100644 --- a/drivers/acpi/acpica/exregion.c +++ b/drivers/acpi/acpica/exregion.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exregion - ACPI default op_region (address space) handlers @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,10 +52,10 @@ ACPI_MODULE_NAME("exregion") * * FUNCTION: acpi_ex_system_memory_space_handler * - * PARAMETERS: Function - Read or Write operation - * Address - Where in the space to read or write + * PARAMETERS: function - Read or Write operation + * address - Where in the space to read or write * bit_width - Field width in bits (8, 16, or 32) - * Value - Pointer to in or out value + * value - Pointer to in or out value * handler_context - Pointer to Handler's context * region_context - Pointer to context specific to the * accessed region @@ -89,22 +88,27 @@ acpi_ex_system_memory_space_handler(u32 function, switch (bit_width) { case 8: + length = 1; break; case 16: + length = 2; break; case 32: + length = 4; break; case 64: + length = 8; break; default: + ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %u", bit_width)); return_ACPI_STATUS(AE_AML_OPERAND_VALUE); @@ -143,9 +147,9 @@ acpi_ex_system_memory_space_handler(u32 function, } /* - * Attempt to map from the requested address to the end of the region. - * However, we will never map more than one page, nor will we cross - * a page boundary. + * October 2009: Attempt to map from the requested address to the + * end of the region. However, we will never map more than one + * page, nor will we cross a page boundary. */ map_length = (acpi_size) ((mem_info->address + mem_info->length) - address); @@ -155,12 +159,15 @@ acpi_ex_system_memory_space_handler(u32 function, * a page boundary, just map up to the page boundary, do not cross. * On some systems, crossing a page boundary while mapping regions * can cause warnings if the pages have different attributes - * due to resource management + * due to resource management. + * + * This has the added benefit of constraining a single mapping to + * one page, which is similar to the original code that used a 4k + * maximum window. */ page_boundary_map_length = ACPI_ROUND_UP(address, ACPI_DEFAULT_PAGE_SIZE) - address; - - if (!page_boundary_map_length) { + if (page_boundary_map_length == 0) { page_boundary_map_length = ACPI_DEFAULT_PAGE_SIZE; } @@ -202,7 +209,7 @@ acpi_ex_system_memory_space_handler(u32 function, * Perform the memory read or write * * Note: For machines that do not support non-aligned transfers, the target - * address was checked for alignment above. We do not attempt to break the + * address was checked for alignment above. We do not attempt to break the * transfer up into smaller (byte-size) chunks because the AML specifically * asked for a transfer width that the hardware may require. */ @@ -212,23 +219,29 @@ acpi_ex_system_memory_space_handler(u32 function, *value = 0; switch (bit_width) { case 8: - *value = (u64) ACPI_GET8(logical_addr_ptr); + + *value = (u64)ACPI_GET8(logical_addr_ptr); break; case 16: - *value = (u64) ACPI_GET16(logical_addr_ptr); + + *value = (u64)ACPI_GET16(logical_addr_ptr); break; case 32: - *value = (u64) ACPI_GET32(logical_addr_ptr); + + *value = (u64)ACPI_GET32(logical_addr_ptr); break; case 64: - *value = (u64) ACPI_GET64(logical_addr_ptr); + + *value = (u64)ACPI_GET64(logical_addr_ptr); break; default: + /* bit_width was already validated */ + break; } break; @@ -237,28 +250,35 @@ acpi_ex_system_memory_space_handler(u32 function, switch (bit_width) { case 8: - ACPI_SET8(logical_addr_ptr) = (u8) * value; + + ACPI_SET8(logical_addr_ptr, *value); break; case 16: - ACPI_SET16(logical_addr_ptr) = (u16) * value; + + ACPI_SET16(logical_addr_ptr, *value); break; case 32: - ACPI_SET32(logical_addr_ptr) = (u32) * value; + + ACPI_SET32(logical_addr_ptr, *value); break; case 64: - ACPI_SET64(logical_addr_ptr) = (u64) * value; + + ACPI_SET64(logical_addr_ptr, *value); break; default: + /* bit_width was already validated */ + break; } break; default: + status = AE_BAD_PARAMETER; break; } @@ -270,10 +290,10 @@ acpi_ex_system_memory_space_handler(u32 function, * * FUNCTION: acpi_ex_system_io_space_handler * - * PARAMETERS: Function - Read or Write operation - * Address - Where in the space to read or write + * PARAMETERS: function - Read or Write operation + * address - Where in the space to read or write * bit_width - Field width in bits (8, 16, or 32) - * Value - Pointer to in or out value + * value - Pointer to in or out value * handler_context - Pointer to Handler's context * region_context - Pointer to context specific to the * accessed region @@ -318,6 +338,7 @@ acpi_ex_system_io_space_handler(u32 function, break; default: + status = AE_BAD_PARAMETER; break; } @@ -329,10 +350,10 @@ acpi_ex_system_io_space_handler(u32 function, * * FUNCTION: acpi_ex_pci_config_space_handler * - * PARAMETERS: Function - Read or Write operation - * Address - Where in the space to read or write + * PARAMETERS: function - Read or Write operation + * address - Where in the space to read or write * bit_width - Field width in bits (8, 16, or 32) - * Value - Pointer to in or out value + * value - Pointer to in or out value * handler_context - Pointer to Handler's context * region_context - Pointer to context specific to the * accessed region @@ -365,7 +386,7 @@ acpi_ex_pci_config_space_handler(u32 function, * pci_function is the PCI device function number * pci_register is the Config space register range 0-255 bytes * - * Value - input value for write, output address for read + * value - input value for write, output address for read * */ pci_id = (struct acpi_pci_id *)region_context; @@ -379,6 +400,7 @@ acpi_ex_pci_config_space_handler(u32 function, switch (function) { case ACPI_READ: + *value = 0; status = acpi_os_read_pci_configuration(pci_id, pci_register, value, bit_width); break; @@ -402,10 +424,10 @@ acpi_ex_pci_config_space_handler(u32 function, * * FUNCTION: acpi_ex_cmos_space_handler * - * PARAMETERS: Function - Read or Write operation - * Address - Where in the space to read or write + * PARAMETERS: function - Read or Write operation + * address - Where in the space to read or write * bit_width - Field width in bits (8, 16, or 32) - * Value - Pointer to in or out value + * value - Pointer to in or out value * handler_context - Pointer to Handler's context * region_context - Pointer to context specific to the * accessed region @@ -434,10 +456,10 @@ acpi_ex_cmos_space_handler(u32 function, * * FUNCTION: acpi_ex_pci_bar_space_handler * - * PARAMETERS: Function - Read or Write operation - * Address - Where in the space to read or write + * PARAMETERS: function - Read or Write operation + * address - Where in the space to read or write * bit_width - Field width in bits (8, 16, or 32) - * Value - Pointer to in or out value + * value - Pointer to in or out value * handler_context - Pointer to Handler's context * region_context - Pointer to context specific to the * accessed region @@ -466,10 +488,10 @@ acpi_ex_pci_bar_space_handler(u32 function, * * FUNCTION: acpi_ex_data_table_space_handler * - * PARAMETERS: Function - Read or Write operation - * Address - Where in the space to read or write + * PARAMETERS: function - Read or Write operation + * address - Where in the space to read or write * bit_width - Field width in bits (8, 16, or 32) - * Value - Pointer to in or out value + * value - Pointer to in or out value * handler_context - Pointer to Handler's context * region_context - Pointer to context specific to the * accessed region diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c index fa50e77e64a..ab060261b43 100644 --- a/drivers/acpi/acpica/exresnte.c +++ b/drivers/acpi/acpica/exresnte.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exresnte - AML Interpreter object resolution @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,8 +57,8 @@ ACPI_MODULE_NAME("exresnte") * PARAMETERS: object_ptr - Pointer to a location that contains * a pointer to a NS node, and will receive a * pointer to the resolved object. - * walk_state - Current state. Valid only if executing AML - * code. NULL if simply resolving an object + * walk_state - Current state. Valid only if executing AML + * code. NULL if simply resolving an object * * RETURN: Status * @@ -67,7 +66,7 @@ ACPI_MODULE_NAME("exresnte") * * Note: for some of the data types, the pointer attached to the Node * can be either a pointer to an actual internal object or a pointer into the - * AML stream itself. These types are currently: + * AML stream itself. These types are currently: * * ACPI_TYPE_INTEGER * ACPI_TYPE_STRING @@ -89,7 +88,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, ACPI_FUNCTION_TRACE(ex_resolve_node_to_value); /* - * The stack pointer points to a struct acpi_namespace_node (Node). Get the + * The stack pointer points to a struct acpi_namespace_node (Node). Get the * object that is attached to the Node. */ node = *object_ptr; @@ -125,7 +124,8 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, } if (!source_desc) { - ACPI_ERROR((AE_INFO, "No object attached to node %p", node)); + ACPI_ERROR((AE_INFO, "No object attached to node [%4.4s] %p", + node->name.ascii, node)); return_ACPI_STATUS(AE_AML_NO_OPERAND); } @@ -249,6 +249,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, break; default: + /* No named references are allowed here */ ACPI_ERROR((AE_INFO, diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c index 6e335dc3452..3cde553bcbe 100644 --- a/drivers/acpi/acpica/exresolv.c +++ b/drivers/acpi/acpica/exresolv.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exresolv - AML Interpreter object resolution @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -147,7 +146,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, stack_desc = *stack_ptr; - /* This is a union acpi_operand_object */ + /* This is an object of type union acpi_operand_object */ switch (stack_desc->common.type) { case ACPI_TYPE_LOCAL_REFERENCE: @@ -157,7 +156,6 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, switch (ref_type) { case ACPI_REFCLASS_LOCAL: case ACPI_REFCLASS_ARG: - /* * Get the local from the method's state info * Note: this increments the local's object reference count @@ -310,6 +308,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, break; default: + break; } @@ -321,13 +320,13 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, * FUNCTION: acpi_ex_resolve_multiple * * PARAMETERS: walk_state - Current state (contains AML opcode) - * Operand - Starting point for resolution + * operand - Starting point for resolution * return_type - Where the object type is returned * return_desc - Where the resolved object is returned * * RETURN: Status * - * DESCRIPTION: Return the base object and type. Traverse a reference list if + * DESCRIPTION: Return the base object and type. Traverse a reference list if * necessary to get to the base object. * ******************************************************************************/ @@ -349,10 +348,12 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) { case ACPI_DESC_TYPE_OPERAND: + type = obj_desc->common.type; break; case ACPI_DESC_TYPE_NAMED: + type = ((struct acpi_namespace_node *)obj_desc)->type; obj_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *) @@ -520,7 +521,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, */ type = obj_desc->common.type; - exit: +exit: /* Convert internal types to external types */ switch (type) { @@ -539,7 +540,9 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, break; default: + /* No change to Type required */ + break; } diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c index a67b1d925dd..3af8de3fcea 100644 --- a/drivers/acpi/acpica/exresop.c +++ b/drivers/acpi/acpica/exresop.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exresop - AML Interpreter operand/object resolution @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -87,7 +86,7 @@ acpi_ex_check_object_type(acpi_object_type type_needed, if (type_needed == ACPI_TYPE_LOCAL_REFERENCE) { /* * Allow the AML "Constant" opcodes (Zero, One, etc.) to be reference - * objects and thus allow them to be targets. (As per the ACPI + * objects and thus allow them to be targets. (As per the ACPI * specification, a store to a constant is a noop.) */ if ((this_type == ACPI_TYPE_INTEGER) && @@ -113,7 +112,7 @@ acpi_ex_check_object_type(acpi_object_type type_needed, * * FUNCTION: acpi_ex_resolve_operands * - * PARAMETERS: Opcode - Opcode being interpreted + * PARAMETERS: opcode - Opcode being interpreted * stack_ptr - Pointer to the operand stack to be * resolved * walk_state - Current state @@ -307,8 +306,7 @@ acpi_ex_resolve_operands(u16 opcode, case ARGI_DEVICE_REF: case ARGI_TARGETREF: /* Allows implicit conversion rules before store */ case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */ - case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */ - + case ARGI_SIMPLE_TARGET: /* Name, Local, or arg - no implicit conversion */ /* * Need an operand of type ACPI_TYPE_LOCAL_REFERENCE * A Namespace Node is OK as-is @@ -327,7 +325,6 @@ acpi_ex_resolve_operands(u16 opcode, goto next_operand; case ARGI_DATAREFOBJ: /* Store operator only */ - /* * We don't want to resolve index_op reference objects during * a store because this would be an implicit de_ref_of operation. @@ -337,13 +334,16 @@ acpi_ex_resolve_operands(u16 opcode, if ((opcode == AML_STORE_OP) && ((*stack_ptr)->common.type == ACPI_TYPE_LOCAL_REFERENCE) - && ((*stack_ptr)->reference.class == ACPI_REFCLASS_INDEX)) { + && ((*stack_ptr)->reference.class == + ACPI_REFCLASS_INDEX)) { goto next_operand; } break; default: + /* All cases covered above */ + break; } @@ -410,7 +410,7 @@ acpi_ex_resolve_operands(u16 opcode, /* * Need an operand of type ACPI_TYPE_INTEGER, * But we can implicitly convert from a STRING or BUFFER - * Aka - "Implicit Source Operand Conversion" + * aka - "Implicit Source Operand Conversion" */ status = acpi_ex_convert_to_integer(obj_desc, stack_ptr, 16); @@ -433,11 +433,10 @@ acpi_ex_resolve_operands(u16 opcode, goto next_operand; case ARGI_BUFFER: - /* * Need an operand of type ACPI_TYPE_BUFFER, * But we can implicitly convert from a STRING or INTEGER - * Aka - "Implicit Source Operand Conversion" + * aka - "Implicit Source Operand Conversion" */ status = acpi_ex_convert_to_buffer(obj_desc, stack_ptr); if (ACPI_FAILURE(status)) { @@ -459,11 +458,10 @@ acpi_ex_resolve_operands(u16 opcode, goto next_operand; case ARGI_STRING: - /* * Need an operand of type ACPI_TYPE_STRING, * But we can implicitly convert from a BUFFER or INTEGER - * Aka - "Implicit Source Operand Conversion" + * aka - "Implicit Source Operand Conversion" */ status = acpi_ex_convert_to_string(obj_desc, stack_ptr, ACPI_IMPLICIT_CONVERT_HEX); @@ -562,6 +560,7 @@ acpi_ex_resolve_operands(u16 opcode, break; default: + ACPI_ERROR((AE_INFO, "Needed [Buffer/String/Package/Reference], found [%s] %p", acpi_ut_get_object_type_name @@ -584,6 +583,7 @@ acpi_ex_resolve_operands(u16 opcode, break; default: + ACPI_ERROR((AE_INFO, "Needed [Buffer/String/Package], found [%s] %p", acpi_ut_get_object_type_name @@ -605,6 +605,7 @@ acpi_ex_resolve_operands(u16 opcode, break; default: + ACPI_ERROR((AE_INFO, "Needed [Region/Buffer], found [%s] %p", acpi_ut_get_object_type_name @@ -638,7 +639,7 @@ acpi_ex_resolve_operands(u16 opcode, if (acpi_gbl_enable_interpreter_slack) { /* * Enable original behavior of Store(), allowing any and all - * objects as the source operand. The ACPI spec does not + * objects as the source operand. The ACPI spec does not * allow this, however. */ break; @@ -682,7 +683,7 @@ acpi_ex_resolve_operands(u16 opcode, return_ACPI_STATUS(status); } - next_operand: +next_operand: /* * If more operands needed, decrement stack_ptr to point * to next operand on stack diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c index c6cf843cc4c..daf49f7ea31 100644 --- a/drivers/acpi/acpica/exstore.c +++ b/drivers/acpi/acpica/exstore.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,13 +57,18 @@ acpi_ex_store_object_to_index(union acpi_operand_object *val_desc, union acpi_operand_object *dest_desc, struct acpi_walk_state *walk_state); +static acpi_status +acpi_ex_store_direct_to_node(union acpi_operand_object *source_desc, + struct acpi_namespace_node *node, + struct acpi_walk_state *walk_state); + /******************************************************************************* * * FUNCTION: acpi_ex_store * * PARAMETERS: *source_desc - Value to be stored - * *dest_desc - Where to store it. Must be an NS node - * or a union acpi_operand_object of type + * *dest_desc - Where to store it. Must be an NS node + * or union acpi_operand_object of type * Reference; * walk_state - Current walk state * @@ -114,6 +119,7 @@ acpi_ex_store(union acpi_operand_object *source_desc, switch (dest_desc->common.type) { case ACPI_TYPE_LOCAL_REFERENCE: + break; case ACPI_TYPE_INTEGER: @@ -178,7 +184,6 @@ acpi_ex_store(union acpi_operand_object *source_desc, break; case ACPI_REFCLASS_DEBUG: - /* * Storing to the Debug object causes the value stored to be * displayed and otherwise has no effect -- see ACPI Specification @@ -291,7 +296,6 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, break; case ACPI_TYPE_BUFFER_FIELD: - /* * Store into a Buffer or String (not actually a real buffer_field) * at a location defined by an Index. @@ -361,7 +365,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, * FUNCTION: acpi_ex_store_object_to_node * * PARAMETERS: source_desc - Value to be stored - * Node - Named object to receive the value + * node - Named object to receive the value * walk_state - Current walk state * implicit_conversion - Perform implicit conversion (yes/no) * @@ -374,9 +378,13 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, * with the input value. * * When storing into an object the data is converted to the - * target object type then stored in the object. This means + * target object type then stored in the object. This means * that the target object type (for an initialized target) will - * not be changed by a store operation. + * not be changed by a store operation. A copy_object can change + * the target type, however. + * + * The implicit_conversion flag is set to NO/FALSE only when + * storing to an arg_x -- as per the rules of the ACPI spec. * * Assumes parameters are already validated. * @@ -400,7 +408,7 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, target_type = acpi_ns_get_type(node); target_desc = acpi_ns_get_attached_object(node); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n", + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p (%s) to node %p (%s)\n", source_desc, acpi_ut_get_object_type_name(source_desc), node, acpi_ut_get_type_name(target_type))); @@ -414,46 +422,30 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, return_ACPI_STATUS(status); } - /* If no implicit conversion, drop into the default case below */ - - if ((!implicit_conversion) || - ((walk_state->opcode == AML_COPY_OP) && - (target_type != ACPI_TYPE_LOCAL_REGION_FIELD) && - (target_type != ACPI_TYPE_LOCAL_BANK_FIELD) && - (target_type != ACPI_TYPE_LOCAL_INDEX_FIELD))) { - /* - * Force execution of default (no implicit conversion). Note: - * copy_object does not perform an implicit conversion, as per the ACPI - * spec -- except in case of region/bank/index fields -- because these - * objects must retain their original type permanently. - */ - target_type = ACPI_TYPE_ANY; - } - /* Do the actual store operation */ switch (target_type) { - case ACPI_TYPE_BUFFER_FIELD: - case ACPI_TYPE_LOCAL_REGION_FIELD: - case ACPI_TYPE_LOCAL_BANK_FIELD: - case ACPI_TYPE_LOCAL_INDEX_FIELD: - - /* For fields, copy the source data to the target field. */ - - status = acpi_ex_write_data_to_field(source_desc, target_desc, - &walk_state->result_obj); - break; - case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: - /* - * These target types are all of type Integer/String/Buffer, and - * therefore support implicit conversion before the store. - * - * Copy and/or convert the source object to a new target object + * The simple data types all support implicit source operand + * conversion before the store. */ + + if ((walk_state->opcode == AML_COPY_OP) || !implicit_conversion) { + /* + * However, copy_object and Stores to arg_x do not perform + * an implicit conversion, as per the ACPI specification. + * A direct store is performed instead. + */ + status = acpi_ex_store_direct_to_node(source_desc, node, + walk_state); + break; + } + + /* Store with implicit source operand conversion support */ + status = acpi_ex_store_object_to_object(source_desc, target_desc, &new_desc, walk_state); @@ -467,13 +459,12 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, * the Name's type to that of the value being stored in it. * source_desc reference count is incremented by attach_object. * - * Note: This may change the type of the node if an explicit store - * has been performed such that the node/object type has been - * changed. + * Note: This may change the type of the node if an explicit + * store has been performed such that the node/object type + * has been changed. */ - status = - acpi_ns_attach_object(node, new_desc, - new_desc->common.type); + status = acpi_ns_attach_object(node, new_desc, + new_desc->common.type); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Store %s into %s via Convert/Attach\n", @@ -484,19 +475,83 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, } break; + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + /* + * For all fields, always write the source data to the target + * field. Any required implicit source operand conversion is + * performed in the function below as necessary. Note, field + * objects must retain their original type permanently. + */ + status = acpi_ex_write_data_to_field(source_desc, target_desc, + &walk_state->result_obj); + break; + default: + /* + * No conversions for all other types. Directly store a copy of + * the source object. This is the ACPI spec-defined behavior for + * the copy_object operator. + * + * NOTE: For the Store operator, this is a departure from the + * ACPI spec, which states "If conversion is impossible, abort + * the running control method". Instead, this code implements + * "If conversion is impossible, treat the Store operation as + * a CopyObject". + */ + status = acpi_ex_store_direct_to_node(source_desc, node, + walk_state); + break; + } - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Storing %s (%p) directly into node (%p) with no implicit conversion\n", - acpi_ut_get_object_type_name(source_desc), - source_desc, node)); + return_ACPI_STATUS(status); +} - /* No conversions for all other types. Just attach the source object */ +/******************************************************************************* + * + * FUNCTION: acpi_ex_store_direct_to_node + * + * PARAMETERS: source_desc - Value to be stored + * node - Named object to receive the value + * walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: "Store" an object directly to a node. This involves a copy + * and an attach. + * + ******************************************************************************/ - status = acpi_ns_attach_object(node, source_desc, - source_desc->common.type); - break; +static acpi_status +acpi_ex_store_direct_to_node(union acpi_operand_object *source_desc, + struct acpi_namespace_node *node, + struct acpi_walk_state *walk_state) +{ + acpi_status status; + union acpi_operand_object *new_desc; + + ACPI_FUNCTION_TRACE(ex_store_direct_to_node); + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Storing [%s] (%p) directly into node [%s] (%p)" + " with no implicit conversion\n", + acpi_ut_get_object_type_name(source_desc), + source_desc, acpi_ut_get_type_name(node->type), + node)); + + /* Copy the source object to a new object */ + + status = + acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } + /* Attach the new object to the node */ + + status = acpi_ns_attach_object(node, new_desc, new_desc->common.type); + acpi_ut_remove_reference(new_desc); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/exstoren.c b/drivers/acpi/acpica/exstoren.c index b35bed52e06..04bd16c08f9 100644 --- a/drivers/acpi/acpica/exstoren.c +++ b/drivers/acpi/acpica/exstoren.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exstoren - AML Interpreter object store support, @@ -7,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,7 +60,7 @@ ACPI_MODULE_NAME("exstoren") * * RETURN: Status, resolved object in source_desc_ptr. * - * DESCRIPTION: Resolve an object. If the object is a reference, dereference + * DESCRIPTION: Resolve an object. If the object is a reference, dereference * it and return the actual object in the source_desc_ptr. * ******************************************************************************/ @@ -86,14 +85,12 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, * These cases all require only Integers or values that * can be converted to Integers (Strings or Buffers) */ - case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: - /* * Stores into a Field/Region or into a Integer/Buffer/String - * are all essentially the same. This case handles the + * are all essentially the same. This case handles the * "interchangeable" types Integer, String, and Buffer. */ if (source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) { @@ -134,7 +131,6 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, case ACPI_TYPE_LOCAL_ALIAS: case ACPI_TYPE_LOCAL_METHOD_ALIAS: - /* * All aliases should have been resolved earlier, during the * operand resolution phase. @@ -145,7 +141,6 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, case ACPI_TYPE_PACKAGE: default: - /* * All other types than Alias and the various Fields come here, * including the untyped case - ACPI_TYPE_ANY. @@ -167,7 +162,7 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, * * RETURN: Status * - * DESCRIPTION: "Store" an object to another object. This may include + * DESCRIPTION: "Store" an object to another object. This may include * converting the source type to the target type (implicit * conversion), and a copy of the value of the source to * the target. @@ -178,14 +173,14 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, * with the input value. * * When storing into an object the data is converted to the - * target object type then stored in the object. This means + * target object type then stored in the object. This means * that the target object type (for an initialized target) will * not be changed by a store operation. * * This module allows destination types of Number, String, * Buffer, and Package. * - * Assumes parameters are already validated. NOTE: source_desc + * Assumes parameters are already validated. NOTE: source_desc * resolution (from a reference object) must be performed by * the caller if necessary. * @@ -254,7 +249,7 @@ acpi_ex_store_object_to_object(union acpi_operand_object *source_desc, /* Truncate value if we are executing from a 32-bit ACPI table */ - acpi_ex_truncate_for32bit_table(dest_desc); + (void)acpi_ex_truncate_for32bit_table(dest_desc); break; case ACPI_TYPE_STRING: diff --git a/drivers/acpi/acpica/exstorob.c b/drivers/acpi/acpica/exstorob.c index 65a45d8335c..fd11018b016 100644 --- a/drivers/acpi/acpica/exstorob.c +++ b/drivers/acpi/acpica/exstorob.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exstorob - AML Interpreter object store support, store to object @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -108,16 +107,16 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc, #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" + * 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 + * standard. ACPI 3.0A 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 + * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer * copy must not truncate the original buffer. */ if (original_src_type == ACPI_TYPE_STRING) { diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c index 191a1294522..f7da64123ed 100644 --- a/drivers/acpi/acpica/exsystem.c +++ b/drivers/acpi/acpica/exsystem.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exsystem - Interface to OS services @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,13 +52,13 @@ ACPI_MODULE_NAME("exsystem") * * FUNCTION: acpi_ex_system_wait_semaphore * - * PARAMETERS: Semaphore - Semaphore to wait on - * Timeout - Max time to wait + * PARAMETERS: semaphore - Semaphore to wait on + * timeout - Max time to wait * * RETURN: Status * * DESCRIPTION: Implements a semaphore wait with a check to see if the - * semaphore is available immediately. If it is not, the + * semaphore is available immediately. If it is not, the * interpreter is released before waiting. * ******************************************************************************/ @@ -78,7 +77,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) /* We must wait, so unlock the interpreter */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); status = acpi_os_wait_semaphore(semaphore, 1, timeout); @@ -88,7 +87,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) /* Reacquire the interpreter */ - acpi_ex_reacquire_interpreter(); + acpi_ex_enter_interpreter(); } return_ACPI_STATUS(status); @@ -98,13 +97,13 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) * * FUNCTION: acpi_ex_system_wait_mutex * - * PARAMETERS: Mutex - Mutex to wait on - * Timeout - Max time to wait + * PARAMETERS: mutex - Mutex to wait on + * timeout - Max time to wait * * RETURN: Status * * DESCRIPTION: Implements a mutex wait with a check to see if the - * mutex is available immediately. If it is not, the + * mutex is available immediately. If it is not, the * interpreter is released before waiting. * ******************************************************************************/ @@ -124,7 +123,7 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) /* We must wait, so unlock the interpreter */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); status = acpi_os_acquire_mutex(mutex, timeout); @@ -134,7 +133,7 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) /* Reacquire the interpreter */ - acpi_ex_reacquire_interpreter(); + acpi_ex_enter_interpreter(); } return_ACPI_STATUS(status); @@ -152,7 +151,7 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) * DESCRIPTION: Suspend running thread for specified amount of time. * Note: ACPI specification requires that Stall() does not * relinquish the processor, and delays longer than 100 usec - * should use Sleep() instead. We allow stalls up to 255 usec + * should use Sleep() instead. We allow stalls up to 255 usec * for compatibility with other interpreters and existing BIOSs. * ******************************************************************************/ @@ -199,7 +198,7 @@ acpi_status acpi_ex_system_do_sleep(u64 how_long) /* Since this thread will sleep, we must release the interpreter */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); /* * For compatibility with other ACPI implementations and to prevent @@ -213,7 +212,7 @@ acpi_status acpi_ex_system_do_sleep(u64 how_long) /* And now we must get the interpreter again */ - acpi_ex_reacquire_interpreter(); + acpi_ex_enter_interpreter(); return (AE_OK); } @@ -254,7 +253,7 @@ acpi_status acpi_ex_system_signal_event(union acpi_operand_object * obj_desc) * RETURN: Status * * DESCRIPTION: Provides an access point to perform synchronization operations - * within the AML. This operation is a request to wait for an + * within the AML. This operation is a request to wait for an * event. * ******************************************************************************/ diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c index eb6798ba8b5..d9d72dff2a7 100644 --- a/drivers/acpi/acpica/exutils.c +++ b/drivers/acpi/acpica/exutils.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exutils - interpreter/scanner utilities @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,12 +44,12 @@ /* * DEFINE_AML_GLOBALS is tested in amlcode.h * to determine whether certain global names should be "defined" or only - * "declared" in the current compilation. This enhances maintainability + * "declared" in the current compilation. This enhances maintainability * by enabling a single header file to embody all knowledge of the names * in question. * * Exactly one module of any executable should #define DEFINE_GLOBALS - * before #including the header files which use this convention. The + * before #including the header files which use this convention. The * names in question will be defined and initialized in that module, * and declared as extern in all other modules which #include those * header files. @@ -101,37 +100,6 @@ void acpi_ex_enter_interpreter(void) /******************************************************************************* * - * FUNCTION: acpi_ex_reacquire_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Reacquire the interpreter execution region from within the - * interpreter code. Failure to enter the interpreter region is a - * fatal system error. Used in conjunction with - * relinquish_interpreter - * - ******************************************************************************/ - -void acpi_ex_reacquire_interpreter(void) -{ - ACPI_FUNCTION_TRACE(ex_reacquire_interpreter); - - /* - * If the global serialized flag is set, do not release the interpreter, - * since it was not actually released by acpi_ex_relinquish_interpreter. - * This forces the interpreter to be single threaded. - */ - if (!acpi_gbl_all_methods_serialized) { - acpi_ex_enter_interpreter(); - } - - return_VOID; -} - -/******************************************************************************* - * * FUNCTION: acpi_ex_exit_interpreter * * PARAMETERS: None @@ -140,7 +108,16 @@ void acpi_ex_reacquire_interpreter(void) * * DESCRIPTION: Exit the interpreter execution region. This is the top level * routine used to exit the interpreter when all processing has - * been completed. + * been completed, or when the method blocks. + * + * Cases where the interpreter is unlocked internally: + * 1) Method will be blocked on a Sleep() AML opcode + * 2) Method will be blocked on an Acquire() AML opcode + * 3) Method will be blocked on a Wait() AML opcode + * 4) Method will be blocked to acquire the global lock + * 5) Method will be blocked waiting to execute a serialized control + * method that is currently executing + * 6) About to invoke a user-installed opregion handler * ******************************************************************************/ @@ -161,77 +138,43 @@ void acpi_ex_exit_interpreter(void) /******************************************************************************* * - * FUNCTION: acpi_ex_relinquish_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Exit the interpreter execution region, from within the - * interpreter - before attempting an operation that will possibly - * block the running thread. - * - * Cases where the interpreter is unlocked internally - * 1) Method to be blocked on a Sleep() AML opcode - * 2) Method to be blocked on an Acquire() AML opcode - * 3) Method to be blocked on a Wait() AML opcode - * 4) Method to be blocked to acquire the global lock - * 5) Method to be blocked waiting to execute a serialized control method - * that is currently executing - * 6) About to invoke a user-installed opregion handler - * - ******************************************************************************/ - -void acpi_ex_relinquish_interpreter(void) -{ - ACPI_FUNCTION_TRACE(ex_relinquish_interpreter); - - /* - * If the global serialized flag is set, do not release the interpreter. - * This forces the interpreter to be single threaded. - */ - if (!acpi_gbl_all_methods_serialized) { - acpi_ex_exit_interpreter(); - } - - return_VOID; -} - -/******************************************************************************* - * * FUNCTION: acpi_ex_truncate_for32bit_table * * PARAMETERS: obj_desc - Object to be truncated * - * RETURN: none + * RETURN: TRUE if a truncation was performed, FALSE otherwise. * * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is * 32-bit, as determined by the revision of the DSDT. * ******************************************************************************/ -void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) +u8 acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) { ACPI_FUNCTION_ENTRY(); /* * Object must be a valid number and we must be executing - * a control method. NS node could be there for AML_INT_NAMEPATH_OP. + * a control method. Object could be NS node for AML_INT_NAMEPATH_OP. */ if ((!obj_desc) || (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) || (obj_desc->common.type != ACPI_TYPE_INTEGER)) { - return; + return (FALSE); } - if (acpi_gbl_integer_byte_width == 4) { + if ((acpi_gbl_integer_byte_width == 4) && + (obj_desc->integer.value > (u64)ACPI_UINT32_MAX)) { /* - * We are running a method that exists in a 32-bit ACPI table. + * We are executing in a 32-bit ACPI table. * Truncate the value to 32 bits by zeroing out the upper 32-bit field */ - obj_desc->integer.value &= (u64) ACPI_UINT32_MAX; + obj_desc->integer.value &= (u64)ACPI_UINT32_MAX; + return (TRUE); } + + return (FALSE); } /******************************************************************************* @@ -317,8 +260,8 @@ void acpi_ex_release_global_lock(u32 field_flags) * * FUNCTION: acpi_ex_digits_needed * - * PARAMETERS: Value - Value to be represented - * Base - Base of representation + * PARAMETERS: value - Value to be represented + * base - Base of representation * * RETURN: The number of digits. * @@ -408,7 +351,7 @@ void acpi_ex_eisa_id_to_string(char *out_string, u64 compressed_id) * PARAMETERS: out_string - Where to put the converted string. At least * 21 bytes are needed to hold the largest * possible 64-bit integer. - * Value - Value to be converted + * value - Value to be converted * * RETURN: None, string * @@ -443,7 +386,7 @@ void acpi_ex_integer_to_string(char *out_string, u64 value) * * RETURN: TRUE if valid/supported ID. * - * DESCRIPTION: Validate an operation region space_iD. + * DESCRIPTION: Validate an operation region space_ID. * ******************************************************************************/ diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c index d21ec5f0b3a..1e66d960fc1 100644 --- a/drivers/acpi/acpica/hwacpi.c +++ b/drivers/acpi/acpica/hwacpi.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,11 +47,12 @@ #define _COMPONENT ACPI_HARDWARE ACPI_MODULE_NAME("hwacpi") +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /****************************************************************************** * * FUNCTION: acpi_hw_set_mode * - * PARAMETERS: Mode - SYS_MODE_ACPI or SYS_MODE_LEGACY + * PARAMETERS: mode - SYS_MODE_ACPI or SYS_MODE_LEGACY * * RETURN: Status * @@ -66,6 +66,12 @@ acpi_status acpi_hw_set_mode(u32 mode) ACPI_FUNCTION_TRACE(hw_set_mode); + /* If the Hardware Reduced flag is set, machine is always in acpi mode */ + + if (acpi_gbl_reduced_hardware) { + return_ACPI_STATUS(AE_OK); + } + /* * ACPI 2.0 clarified that if SMI_CMD in FADT is zero, * system does not support mode transition. @@ -102,19 +108,18 @@ acpi_status acpi_hw_set_mode(u32 mode) break; case ACPI_SYS_MODE_LEGACY: - /* * BIOS should clear all fixed status bits and restore fixed event * enable bits to default */ status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, - (u32) acpi_gbl_FADT.acpi_disable, - 8); + (u32)acpi_gbl_FADT.acpi_disable, 8); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Attempting to enable Legacy (non-ACPI) mode\n")); break; default: + return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -135,7 +140,7 @@ acpi_status acpi_hw_set_mode(u32 mode) * * RETURN: SYS_MODE_ACPI or SYS_MODE_LEGACY * - * DESCRIPTION: Return current operating state of system. Determined by + * DESCRIPTION: Return current operating state of system. Determined by * querying the SCI_EN bit. * ******************************************************************************/ @@ -147,6 +152,12 @@ u32 acpi_hw_get_mode(void) ACPI_FUNCTION_TRACE(hw_get_mode); + /* If the Hardware Reduced flag is set, machine is always in acpi mode */ + + if (acpi_gbl_reduced_hardware) { + return_UINT32(ACPI_SYS_MODE_ACPI); + } + /* * ACPI 2.0 clarified that if SMI_CMD in FADT is zero, * system does not support mode transition. @@ -166,3 +177,5 @@ u32 acpi_hw_get_mode(void) return_UINT32(ACPI_SYS_MODE_LEGACY); } } + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c new file mode 100644 index 00000000000..858fdd6be59 --- /dev/null +++ b/drivers/acpi/acpica/hwesleep.c @@ -0,0 +1,243 @@ +/****************************************************************************** + * + * Name: hwesleep.c - ACPI Hardware Sleep/Wake Support functions for the + * extended FADT-V5 sleep registers. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include <linux/acpi.h> +#include "accommon.h" + +#define _COMPONENT ACPI_HARDWARE +ACPI_MODULE_NAME("hwesleep") + +/******************************************************************************* + * + * FUNCTION: acpi_hw_execute_sleep_method + * + * PARAMETERS: method_pathname - Pathname of method to execute + * integer_argument - Argument to pass to the method + * + * RETURN: None + * + * DESCRIPTION: Execute a sleep/wake related method with one integer argument + * and no return value. + * + ******************************************************************************/ +void acpi_hw_execute_sleep_method(char *method_pathname, u32 integer_argument) +{ + struct acpi_object_list arg_list; + union acpi_object arg; + acpi_status status; + + ACPI_FUNCTION_TRACE(hw_execute_sleep_method); + + /* One argument, integer_argument; No return value expected */ + + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = (u64)integer_argument; + + status = acpi_evaluate_object(NULL, method_pathname, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, "While executing method %s", + method_pathname)); + } + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_hw_extended_sleep + * + * PARAMETERS: sleep_state - Which sleep state to enter + * + * RETURN: Status + * + * DESCRIPTION: Enter a system sleep state via the extended FADT sleep + * registers (V5 FADT). + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED + * + ******************************************************************************/ + +acpi_status acpi_hw_extended_sleep(u8 sleep_state) +{ + acpi_status status; + u8 sleep_type_value; + u64 sleep_status; + + ACPI_FUNCTION_TRACE(hw_extended_sleep); + + /* Extended sleep registers must be valid */ + + if (!acpi_gbl_FADT.sleep_control.address || + !acpi_gbl_FADT.sleep_status.address) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* Clear wake status (WAK_STS) */ + + status = + acpi_write((u64)ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_gbl_system_awake_and_running = FALSE; + + /* Flush caches, as per ACPI specification */ + + ACPI_FLUSH_CPU_CACHE(); + + status = acpi_os_prepare_extended_sleep(sleep_state, + acpi_gbl_sleep_type_a, + acpi_gbl_sleep_type_b); + if (ACPI_SKIP(status)) + return_ACPI_STATUS(AE_OK); + if (ACPI_FAILURE(status)) + return_ACPI_STATUS(status); + + /* + * Set the SLP_TYP and SLP_EN bits. + * + * Note: We only use the first value returned by the \_Sx method + * (acpi_gbl_sleep_type_a) - As per ACPI specification. + */ + ACPI_DEBUG_PRINT((ACPI_DB_INIT, + "Entering sleep state [S%u]\n", sleep_state)); + + sleep_type_value = + ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) & + ACPI_X_SLEEP_TYPE_MASK); + + status = acpi_write((u64)(sleep_type_value | ACPI_X_SLEEP_ENABLE), + &acpi_gbl_FADT.sleep_control); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Wait for transition back to Working State */ + + do { + status = acpi_read(&sleep_status, &acpi_gbl_FADT.sleep_status); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + } while (!(((u8)sleep_status) & ACPI_X_WAKE_STATUS)); + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_hw_extended_wake_prep + * + * PARAMETERS: sleep_state - Which sleep state we just exited + * + * RETURN: Status + * + * DESCRIPTION: Perform first part of OS-independent ACPI cleanup after + * a sleep. Called with interrupts ENABLED. + * + ******************************************************************************/ + +acpi_status acpi_hw_extended_wake_prep(u8 sleep_state) +{ + acpi_status status; + u8 sleep_type_value; + + ACPI_FUNCTION_TRACE(hw_extended_wake_prep); + + status = acpi_get_sleep_type_data(ACPI_STATE_S0, + &acpi_gbl_sleep_type_a, + &acpi_gbl_sleep_type_b); + if (ACPI_SUCCESS(status)) { + sleep_type_value = + ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) & + ACPI_X_SLEEP_TYPE_MASK); + + (void)acpi_write((u64)(sleep_type_value | ACPI_X_SLEEP_ENABLE), + &acpi_gbl_FADT.sleep_control); + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_hw_extended_wake + * + * PARAMETERS: sleep_state - Which sleep state we just exited + * + * RETURN: Status + * + * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep + * Called with interrupts ENABLED. + * + ******************************************************************************/ + +acpi_status acpi_hw_extended_wake(u8 sleep_state) +{ + ACPI_FUNCTION_TRACE(hw_extended_wake); + + /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */ + + acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; + + /* Execute the wake methods */ + + acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WAKING); + acpi_hw_execute_sleep_method(METHOD_PATHNAME__WAK, sleep_state); + + /* + * Some BIOS code assumes that WAK_STS will be cleared on resume + * and use it to determine whether the system is rebooting or + * resuming. Clear WAK_STS for compatibility. + */ + (void)acpi_write((u64)ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status); + acpi_gbl_system_awake_and_running = TRUE; + + acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING); + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index 1a6894afef7..2e6caabba07 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: hwgpe - Low level GPE enable/disable/clear functions @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,7 +47,7 @@ #define _COMPONENT ACPI_HARDWARE ACPI_MODULE_NAME("hwgpe") - +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /* Local prototypes */ static acpi_status acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, @@ -60,7 +59,6 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, * FUNCTION: acpi_hw_get_gpe_register_bit * * PARAMETERS: gpe_event_info - Info block for the GPE - * gpe_register_info - Info block for the GPE register * * RETURN: Register mask with a one in the GPE bit position * @@ -69,11 +67,12 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, * ******************************************************************************/ -u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info, - struct acpi_gpe_register_info *gpe_register_info) +u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info) { - return (u32)1 << (gpe_event_info->gpe_number - - gpe_register_info->base_gpe_number); + + return ((u32)1 << + (gpe_event_info->gpe_number - + gpe_event_info->register_info->base_gpe_number)); } /****************************************************************************** @@ -115,8 +114,7 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action) /* Set or clear just the bit that corresponds to this GPE */ - register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info, - gpe_register_info); + register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); switch (action) { case ACPI_GPE_CONDITIONAL_ENABLE: @@ -129,15 +127,18 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action) /*lint -fallthrough */ case ACPI_GPE_ENABLE: + ACPI_SET_BIT(enable_mask, register_bit); break; case ACPI_GPE_DISABLE: + ACPI_CLEAR_BIT(enable_mask, register_bit); break; default: - ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u\n", action)); + + ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u", action)); return (AE_BAD_PARAMETER); } @@ -178,8 +179,7 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info) * Write a one to the appropriate bit in the status register to * clear this GPE. */ - register_bit = - acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info); + register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); status = acpi_hw_write(register_bit, &gpe_register_info->status_address); @@ -222,8 +222,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, /* Get the register bitmask for this GPE */ - register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info, - gpe_register_info); + register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); /* GPE currently enabled? (enabled for runtime?) */ @@ -344,7 +343,8 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, acpi_status acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, - struct acpi_gpe_block_info *gpe_block, void *context) + struct acpi_gpe_block_info * gpe_block, + void *context) { u32 i; acpi_status status; @@ -479,3 +479,5 @@ acpi_status acpi_hw_enable_all_wakeup_gpes(void) status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL); return_ACPI_STATUS(status); } + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/hwpci.c b/drivers/acpi/acpica/hwpci.c index 1455ddcdc32..6aade8e1d2a 100644 --- a/drivers/acpi/acpica/hwpci.c +++ b/drivers/acpi/acpica/hwpci.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -140,11 +140,12 @@ acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id, /* Walk the list, updating the PCI device/function/bus numbers */ status = acpi_hw_process_pci_list(pci_id, list_head); - } - /* Always delete the list */ + /* Delete the list */ + + acpi_hw_delete_pci_list(list_head); + } - acpi_hw_delete_pci_list(list_head); return_ACPI_STATUS(status); } @@ -187,6 +188,10 @@ acpi_hw_build_pci_list(acpi_handle root_pci_device, while (1) { status = acpi_get_parent(current_device, &parent_device); if (ACPI_FAILURE(status)) { + + /* Must delete the list before exit */ + + acpi_hw_delete_pci_list(*return_list_head); return (status); } @@ -199,6 +204,10 @@ acpi_hw_build_pci_list(acpi_handle root_pci_device, list_element = ACPI_ALLOCATE(sizeof(struct acpi_pci_device)); if (!list_element) { + + /* Must delete the list before exit */ + + acpi_hw_delete_pci_list(*return_list_head); return (AE_NO_MEMORY); } @@ -259,7 +268,7 @@ acpi_hw_process_pci_list(struct acpi_pci_id *pci_id, status = acpi_hw_get_pci_device_info(pci_id, info->device, &bus_number, &is_bridge); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + return (status); } info = info->next; @@ -271,7 +280,7 @@ acpi_hw_process_pci_list(struct acpi_pci_id *pci_id, pci_id->segment, pci_id->bus, pci_id->device, pci_id->function, status, bus_number, is_bridge)); - return_ACPI_STATUS(AE_OK); + return (AE_OK); } /******************************************************************************* diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 4ea4eeb51bf..e0fd9b4978c 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -1,4 +1,3 @@ - /******************************************************************************* * * Module Name: hwregs - Read/write access functions for the various ACPI @@ -7,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,12 +44,12 @@ #include <acpi/acpi.h> #include "accommon.h" -#include "acnamesp.h" #include "acevents.h" #define _COMPONENT ACPI_HARDWARE ACPI_MODULE_NAME("hwregs") +#if (!ACPI_REDUCED_HARDWARE) /* Local Prototypes */ static acpi_status acpi_hw_read_multiple(u32 *value, @@ -62,13 +61,15 @@ acpi_hw_write_multiple(u32 value, struct acpi_generic_address *register_a, struct acpi_generic_address *register_b); +#endif /* !ACPI_REDUCED_HARDWARE */ + /****************************************************************************** * * FUNCTION: acpi_hw_validate_register * - * PARAMETERS: Reg - GAS register structure + * PARAMETERS: reg - GAS register structure * max_bit_width - Max bit_width supported (32 or 64) - * Address - Pointer to where the gas->address + * address - Pointer to where the gas->address * is returned * * RETURN: Status @@ -99,7 +100,7 @@ acpi_hw_validate_register(struct acpi_generic_address *reg, return (AE_BAD_ADDRESS); } - /* Validate the space_iD */ + /* Validate the space_ID */ if ((reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) && (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { @@ -134,8 +135,8 @@ acpi_hw_validate_register(struct acpi_generic_address *reg, * * FUNCTION: acpi_hw_read * - * PARAMETERS: Value - Where the value is returned - * Reg - GAS register structure + * PARAMETERS: value - Where the value is returned + * reg - GAS register structure * * RETURN: Status * @@ -145,7 +146,7 @@ acpi_hw_validate_register(struct acpi_generic_address *reg, * * LIMITATIONS: <These limitations also apply to acpi_hw_write> * bit_width must be exactly 8, 16, or 32. - * space_iD must be system_memory or system_iO. + * space_ID must be system_memory or system_IO. * bit_offset and access_width are currently ignored, as there has * not been a need to implement these. * @@ -154,6 +155,7 @@ acpi_hw_validate_register(struct acpi_generic_address *reg, acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg) { u64 address; + u64 value64; acpi_status status; ACPI_FUNCTION_NAME(hw_read); @@ -175,7 +177,9 @@ acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg) */ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { status = acpi_os_read_memory((acpi_physical_address) - address, value, reg->bit_width); + address, &value64, reg->bit_width); + + *value = (u32)value64; } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ status = acpi_hw_read_port((acpi_io_address) @@ -194,8 +198,8 @@ acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg) * * FUNCTION: acpi_hw_write * - * PARAMETERS: Value - Value to be written - * Reg - GAS register structure + * PARAMETERS: value - Value to be written + * reg - GAS register structure * * RETURN: Status * @@ -225,7 +229,8 @@ acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg) */ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { status = acpi_os_write_memory((acpi_physical_address) - address, value, reg->bit_width); + address, (u64)value, + reg->bit_width); } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ status = acpi_hw_write_port((acpi_io_address) @@ -240,6 +245,7 @@ acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg) return (status); } +#if (!ACPI_REDUCED_HARDWARE) /******************************************************************************* * * FUNCTION: acpi_hw_clear_acpi_status @@ -285,7 +291,7 @@ exit: /******************************************************************************* * - * FUNCTION: acpi_hw_get_register_bit_mask + * FUNCTION: acpi_hw_get_bit_register_info * * PARAMETERS: register_id - Index of ACPI Register to access * @@ -357,8 +363,7 @@ acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control) * DESCRIPTION: Read from the specified ACPI register * ******************************************************************************/ -acpi_status -acpi_hw_register_read(u32 register_id, u32 * return_value) +acpi_status acpi_hw_register_read(u32 register_id, u32 *return_value) { u32 value = 0; acpi_status status; @@ -414,6 +419,7 @@ acpi_hw_register_read(u32 register_id, u32 * return_value) break; default: + ACPI_ERROR((AE_INFO, "Unknown Register ID: 0x%X", register_id)); status = AE_BAD_PARAMETER; break; @@ -431,7 +437,7 @@ acpi_hw_register_read(u32 register_id, u32 * return_value) * FUNCTION: acpi_hw_register_write * * PARAMETERS: register_id - ACPI Register ID - * Value - The value to write + * value - The value to write * * RETURN: Status * @@ -478,7 +484,7 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) &acpi_gbl_xpm1b_status); break; - case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access */ + case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ status = acpi_hw_write_multiple(value, &acpi_gbl_xpm1a_enable, @@ -486,7 +492,6 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) break; case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ - /* * Perform a read first to preserve certain bits (per ACPI spec) * Note: This includes SCI_EN, we never want to change this bit @@ -515,7 +520,6 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) break; case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ - /* * For control registers, all reserved bits must be preserved, * as per the ACPI spec. @@ -550,12 +554,13 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) break; default: + ACPI_ERROR((AE_INFO, "Unknown Register ID: 0x%X", register_id)); status = AE_BAD_PARAMETER; break; } - exit: +exit: return_ACPI_STATUS(status); } @@ -563,7 +568,7 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) * * FUNCTION: acpi_hw_read_multiple * - * PARAMETERS: Value - Where the register value is returned + * PARAMETERS: value - Where the register value is returned * register_a - First ACPI register (required) * register_b - Second ACPI register (optional) * @@ -616,7 +621,7 @@ acpi_hw_read_multiple(u32 *value, * * FUNCTION: acpi_hw_write_multiple * - * PARAMETERS: Value - The value to write + * PARAMETERS: value - The value to write * register_a - First ACPI register (required) * register_b - Second ACPI register (optional) * @@ -658,3 +663,5 @@ acpi_hw_write_multiple(u32 value, return (status); } + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 3c4a922a9fc..d590693eb54 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -1,12 +1,12 @@ - /****************************************************************************** * - * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface + * Name: hwsleep.c - ACPI Hardware Sleep/Wake Support functions for the + * original/legacy sleep/PM registers. * *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,213 +43,35 @@ */ #include <acpi/acpi.h> +#include <linux/acpi.h> #include "accommon.h" -#include "actables.h" -#include <linux/tboot.h> -#include <linux/module.h> #define _COMPONENT ACPI_HARDWARE ACPI_MODULE_NAME("hwsleep") +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /******************************************************************************* * - * FUNCTION: acpi_set_firmware_waking_vector - * - * PARAMETERS: physical_address - 32-bit physical address of ACPI real mode - * entry point. - * - * RETURN: Status - * - * DESCRIPTION: Sets the 32-bit firmware_waking_vector field of the FACS - * - ******************************************************************************/ -acpi_status -acpi_set_firmware_waking_vector(u32 physical_address) -{ - ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); - - - /* - * According to the ACPI specification 2.0c and later, the 64-bit - * waking vector should be cleared and the 32-bit waking vector should - * be used, unless we want the wake-up code to be called by the BIOS in - * Protected Mode. Some systems (for example HP dv5-1004nr) are known - * to fail to resume if the 64-bit vector is used. - */ - - /* Set the 32-bit vector */ - - acpi_gbl_FACS->firmware_waking_vector = physical_address; - - /* Clear the 64-bit vector if it exists */ - - if ((acpi_gbl_FACS->length > 32) && (acpi_gbl_FACS->version >= 1)) { - acpi_gbl_FACS->xfirmware_waking_vector = 0; - } - - return_ACPI_STATUS(AE_OK); -} - -ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) - -#if ACPI_MACHINE_WIDTH == 64 -/******************************************************************************* - * - * FUNCTION: acpi_set_firmware_waking_vector64 - * - * PARAMETERS: physical_address - 64-bit physical address of ACPI protected - * mode entry point. - * - * RETURN: Status - * - * DESCRIPTION: Sets the 64-bit X_firmware_waking_vector field of the FACS, if - * it exists in the table. This function is intended for use with - * 64-bit host operating systems. - * - ******************************************************************************/ -acpi_status -acpi_set_firmware_waking_vector64(u64 physical_address) -{ - ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector64); - - - /* Determine if the 64-bit vector actually exists */ - - if ((acpi_gbl_FACS->length <= 32) || (acpi_gbl_FACS->version < 1)) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - /* Clear 32-bit vector, set the 64-bit X_ vector */ - - acpi_gbl_FACS->firmware_waking_vector = 0; - acpi_gbl_FACS->xfirmware_waking_vector = physical_address; - - return_ACPI_STATUS(AE_OK); -} - -ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64) -#endif - -/******************************************************************************* - * - * FUNCTION: acpi_enter_sleep_state_prep + * FUNCTION: acpi_hw_legacy_sleep * * PARAMETERS: sleep_state - Which sleep state to enter * * RETURN: Status * - * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231) - * This function must execute with interrupts enabled. - * We break sleeping into 2 stages so that OSPM can handle - * various OS-specific tasks between the two steps. - * - ******************************************************************************/ -acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) -{ - acpi_status status; - struct acpi_object_list arg_list; - union acpi_object arg; - - ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep); - - /* _PSW methods could be run here to enable wake-on keyboard, LAN, etc. */ - - status = acpi_get_sleep_type_data(sleep_state, - &acpi_gbl_sleep_type_a, - &acpi_gbl_sleep_type_b); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Setup parameter object */ - - arg_list.count = 1; - arg_list.pointer = &arg; - - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = sleep_state; - - /* Run the _PTS method */ - - status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - return_ACPI_STATUS(status); - } - - /* Setup the argument to _SST */ - - switch (sleep_state) { - case ACPI_STATE_S0: - arg.integer.value = ACPI_SST_WORKING; - break; - - case ACPI_STATE_S1: - case ACPI_STATE_S2: - case ACPI_STATE_S3: - arg.integer.value = ACPI_SST_SLEEPING; - break; - - case ACPI_STATE_S4: - arg.integer.value = ACPI_SST_SLEEP_CONTEXT; - break; - - default: - arg.integer.value = ACPI_SST_INDICATOR_OFF; /* Default is off */ - break; - } - - /* - * Set the system indicators to show the desired sleep state. - * _SST is an optional method (return no error if not found) - */ - status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_EXCEPTION((AE_INFO, status, - "While executing method _SST")); - } - - return_ACPI_STATUS(AE_OK); -} - -ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) - -static unsigned int gts, bfs; -module_param(gts, uint, 0644); -module_param(bfs, uint, 0644); -MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend."); -MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".); - -/******************************************************************************* - * - * FUNCTION: acpi_enter_sleep_state - * - * PARAMETERS: sleep_state - Which sleep state to enter - * - * RETURN: Status - * - * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231) + * DESCRIPTION: Enter a system sleep state via the legacy FADT PM registers * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ -acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) +acpi_status acpi_hw_legacy_sleep(u8 sleep_state) { - u32 pm1a_control; - u32 pm1b_control; struct acpi_bit_register_info *sleep_type_reg_info; struct acpi_bit_register_info *sleep_enable_reg_info; + u32 pm1a_control; + u32 pm1b_control; u32 in_value; - struct acpi_object_list arg_list; - union acpi_object arg; acpi_status status; - ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); - - if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) || - (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) { - ACPI_ERROR((AE_INFO, "Sleep values out of range: A=0x%X B=0x%X", - acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b)); - return_ACPI_STATUS(AE_AML_OPERAND_VALUE); - } + ACPI_FUNCTION_TRACE(hw_legacy_sleep); sleep_type_reg_info = acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE); @@ -286,20 +108,6 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) return_ACPI_STATUS(status); } - if (gts) { - /* Execute the _GTS method */ - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = sleep_state; - - status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - return_ACPI_STATUS(status); - } - } - /* Get current value of PM1A control */ status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, @@ -344,8 +152,12 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) ACPI_FLUSH_CPU_CACHE(); - tboot_sleep(sleep_state, pm1a_control, pm1b_control); - + status = acpi_os_prepare_sleep(sleep_state, pm1a_control, + pm1b_control); + if (ACPI_SKIP(status)) + return_ACPI_STATUS(AE_OK); + if (ACPI_FAILURE(status)) + return_ACPI_STATUS(status); /* Write #2: Write both SLP_TYP + SLP_EN */ status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control); @@ -365,7 +177,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) * to still read the right value. Ideally, this block would go * away entirely. */ - acpi_os_stall(10000000); + acpi_os_stall(10 * ACPI_USEC_PER_SEC); status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL, sleep_enable_reg_info-> @@ -375,114 +187,43 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) } } - /* Wait until we enter sleep state */ + /* Wait for transition back to Working State */ do { - status = acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, - &in_value); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Spin until we wake */ - - } while (!in_value); - - return_ACPI_STATUS(AE_OK); -} - -ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state) - -/******************************************************************************* - * - * FUNCTION: acpi_enter_sleep_state_s4bios - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Perform a S4 bios request. - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED - * - ******************************************************************************/ -acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) -{ - u32 in_value; - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios); - - /* Clear the wake status bit (PM1) */ - - status = - acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = acpi_hw_clear_acpi_status(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * 1) Disable/Clear all GPEs - * 2) Enable all wakeup GPEs - */ - status = acpi_hw_disable_all_gpes(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - acpi_gbl_system_awake_and_running = FALSE; - - status = acpi_hw_enable_all_wakeup_gpes(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - ACPI_FLUSH_CPU_CACHE(); - - status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, - (u32) acpi_gbl_FADT.S4bios_request, 8); - - do { - acpi_os_stall(1000); status = acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } + } while (!in_value); return_ACPI_STATUS(AE_OK); } -ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios) - /******************************************************************************* * - * FUNCTION: acpi_leave_sleep_state_prep + * FUNCTION: acpi_hw_legacy_wake_prep * - * PARAMETERS: sleep_state - Which sleep state we are exiting + * PARAMETERS: sleep_state - Which sleep state we just exited * * RETURN: Status * * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a * sleep. - * Called with interrupts DISABLED. + * Called with interrupts ENABLED. * ******************************************************************************/ -acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) + +acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) { - struct acpi_object_list arg_list; - union acpi_object arg; acpi_status status; struct acpi_bit_register_info *sleep_type_reg_info; struct acpi_bit_register_info *sleep_enable_reg_info; u32 pm1a_control; u32 pm1b_control; - ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep); + ACPI_FUNCTION_TRACE(hw_legacy_wake_prep); /* * Set SLP_TYPE and SLP_EN to state S0. @@ -525,25 +266,12 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) } } - if (bfs) { - /* Execute the _BFS method */ - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = sleep_state; - - status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS")); - } - } return_ACPI_STATUS(status); } /******************************************************************************* * - * FUNCTION: acpi_leave_sleep_state + * FUNCTION: acpi_hw_legacy_wake * * PARAMETERS: sleep_state - Which sleep state we just exited * @@ -553,31 +281,17 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) * Called with interrupts ENABLED. * ******************************************************************************/ -acpi_status acpi_leave_sleep_state(u8 sleep_state) + +acpi_status acpi_hw_legacy_wake(u8 sleep_state) { - struct acpi_object_list arg_list; - union acpi_object arg; acpi_status status; - ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); + ACPI_FUNCTION_TRACE(hw_legacy_wake); /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */ acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; - - /* Setup parameter object */ - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - - /* Ignore any errors from these methods */ - - arg.integer.value = ACPI_SST_WAKING; - status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); - } + acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WAKING); /* * GPEs must be enabled before _WAK is called as GPEs @@ -591,46 +305,41 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } + status = acpi_hw_enable_all_runtime_gpes(); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - arg.integer.value = sleep_state; - status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK")); - } - /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */ - /* - * Some BIOSes assume that WAK_STS will be cleared on resume and use - * it to determine whether the system is rebooting or resuming. Clear - * it for compatibility. + * Now we can execute _WAK, etc. Some machines require that the GPEs + * are enabled before the wake methods are executed. */ - acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, 1); + acpi_hw_execute_sleep_method(METHOD_PATHNAME__WAK, sleep_state); + /* + * Some BIOS code assumes that WAK_STS will be cleared on resume + * and use it to determine whether the system is rebooting or + * resuming. Clear WAK_STS for compatibility. + */ + (void)acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, + ACPI_CLEAR_STATUS); acpi_gbl_system_awake_and_running = TRUE; /* Enable power button */ (void) acpi_write_bit_register(acpi_gbl_fixed_event_info - [ACPI_EVENT_POWER_BUTTON]. - enable_register_id, ACPI_ENABLE_EVENT); + [ACPI_EVENT_POWER_BUTTON]. + enable_register_id, ACPI_ENABLE_EVENT); (void) acpi_write_bit_register(acpi_gbl_fixed_event_info - [ACPI_EVENT_POWER_BUTTON]. - status_register_id, ACPI_CLEAR_STATUS); - - arg.integer.value = ACPI_SST_WORKING; - status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); - } + [ACPI_EVENT_POWER_BUTTON]. + status_register_id, ACPI_CLEAR_STATUS); + acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING); return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state) +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/hwtimer.c b/drivers/acpi/acpica/hwtimer.c index d4973d9da9f..76ab5c1a814 100644 --- a/drivers/acpi/acpica/hwtimer.c +++ b/drivers/acpi/acpica/hwtimer.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Name: hwtimer.c - ACPI Power Management Timer Interface @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,18 +41,20 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include <linux/export.h> +#define EXPORT_ACPI_INTERFACES + #include <acpi/acpi.h> #include "accommon.h" #define _COMPONENT ACPI_HARDWARE ACPI_MODULE_NAME("hwtimer") +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /****************************************************************************** * * FUNCTION: acpi_get_timer_resolution * - * PARAMETERS: Resolution - Where the resolution is returned + * PARAMETERS: resolution - Where the resolution is returned * * RETURN: Status and timer resolution * @@ -83,7 +84,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_timer_resolution) * * FUNCTION: acpi_get_timer * - * PARAMETERS: Ticks - Where the timer value is returned + * PARAMETERS: ticks - Where the timer value is returned * * RETURN: Status and current timer value (ticks) * @@ -100,9 +101,13 @@ acpi_status acpi_get_timer(u32 * ticks) return_ACPI_STATUS(AE_BAD_PARAMETER); } - status = - acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block); + /* ACPI 5.0A: PM Timer is optional */ + + if (!acpi_gbl_FADT.xpm_timer_block.address) { + return_ACPI_STATUS(AE_SUPPORT); + } + status = acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block); return_ACPI_STATUS(status); } @@ -128,7 +133,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_timer) * a versatile and accurate timer. * * Note that this function accommodates only a single timer - * rollover. Thus for 24-bit timers, this function should only + * rollover. Thus for 24-bit timers, this function should only * be used for calculating durations less than ~4.6 seconds * (~20 minutes for 32-bit timers) -- calculations below: * @@ -149,6 +154,12 @@ acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed) return_ACPI_STATUS(AE_BAD_PARAMETER); } + /* ACPI 5.0A: PM Timer is optional */ + + if (!acpi_gbl_FADT.xpm_timer_block.address) { + return_ACPI_STATUS(AE_SUPPORT); + } + /* * Compute Tick Delta: * Handle (max one) timer rollovers on 24-bit versus 32-bit timers. @@ -177,13 +188,15 @@ acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed) /* * Compute Duration (Requires a 64-bit multiply and divide): * - * time_elapsed = (delta_ticks * 1000000) / PM_TIMER_FREQUENCY; + * time_elapsed (microseconds) = + * (delta_ticks * ACPI_USEC_PER_SEC) / ACPI_PM_TIMER_FREQUENCY; */ - status = acpi_ut_short_divide(((u64) delta_ticks) * 1000000, - PM_TIMER_FREQUENCY, "ient, NULL); + status = acpi_ut_short_divide(((u64)delta_ticks) * ACPI_USEC_PER_SEC, + ACPI_PM_TIMER_FREQUENCY, "ient, NULL); *time_elapsed = (u32) quotient; return_ACPI_STATUS(status); } ACPI_EXPORT_SYMBOL(acpi_get_timer_duration) +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c index 6e5c43a60bb..6b919127cd9 100644 --- a/drivers/acpi/acpica/hwvalid.c +++ b/drivers/acpi/acpica/hwvalid.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: hwvalid - I/O request validation @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,7 +57,7 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width); * * The table is used to implement the Microsoft port access rules that * first appeared in Windows XP. Some ports are always illegal, and some - * ports are only illegal if the BIOS calls _OSI with a win_xP string or + * ports are only illegal if the BIOS calls _OSI with a win_XP string or * later (meaning that the BIOS itelf is post-XP.) * * This provides ACPICA with the desired port protections and @@ -66,7 +65,7 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width); * * Description of port entries: * DMA: DMA controller - * PIC0: Programmable Interrupt Controller (8259_a) + * PIC0: Programmable Interrupt Controller (8259A) * PIT1: System Timer 1 * PIT2: System Timer 2 failsafe * RTC: Real-time clock @@ -136,7 +135,7 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width) if ((bit_width != 8) && (bit_width != 16) && (bit_width != 32)) { ACPI_ERROR((AE_INFO, "Bad BitWidth parameter: %8.8X", bit_width)); - return AE_BAD_PARAMETER; + return (AE_BAD_PARAMETER); } port_info = acpi_protected_ports; @@ -235,11 +234,11 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width) status = acpi_hw_validate_io_request(address, width); if (ACPI_SUCCESS(status)) { status = acpi_os_read_port(address, value, width); - return status; + return (status); } if (status != AE_AML_ILLEGAL_ADDRESS) { - return status; + return (status); } /* @@ -254,7 +253,7 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width) if (acpi_hw_validate_io_request(address, 8) == AE_OK) { status = acpi_os_read_port(address, &one_byte, 8); if (ACPI_FAILURE(status)) { - return status; + return (status); } *value |= (one_byte << i); @@ -263,7 +262,7 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width) address++; } - return AE_OK; + return (AE_OK); } /****************************************************************************** @@ -298,11 +297,11 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width) status = acpi_hw_validate_io_request(address, width); if (ACPI_SUCCESS(status)) { status = acpi_os_write_port(address, value, width); - return status; + return (status); } if (status != AE_AML_ILLEGAL_ADDRESS) { - return status; + return (status); } /* @@ -318,12 +317,12 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width) status = acpi_os_write_port(address, (value >> i) & 0xFF, 8); if (ACPI_FAILURE(status)) { - return status; + return (status); } } address++; } - return AE_OK; + return (AE_OK); } diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index 9d38eb6c0d0..96d007df65e 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: hwxface - Public ACPICA hardware interfaces @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include <linux/export.h> +#define EXPORT_ACPI_INTERFACES + #include <acpi/acpi.h> #include "accommon.h" #include "acnamesp.h" @@ -81,14 +81,20 @@ acpi_status acpi_reset(void) if (reset_reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { /* - * For I/O space, write directly to the OSL. This - * bypasses the port validation mechanism, which may - * block a valid write to the reset register. Spec - * section 4.7.3.6 requires register width to be 8. + * For I/O space, write directly to the OSL. This bypasses the port + * validation mechanism, which may block a valid write to the reset + * register. + * + * NOTE: + * The ACPI spec requires the reset register width to be 8, so we + * hardcode it here and ignore the FADT value. This maintains + * compatibility with other ACPI implementations that have allowed + * BIOS code with bad register width values to go unnoticed. */ status = acpi_os_write_port((acpi_io_address) reset_reg->address, - acpi_gbl_FADT.reset_value, 8); + acpi_gbl_FADT.reset_value, + ACPI_RESET_REGISTER_WIDTH); } else { /* Write the reset value to the reset register */ @@ -104,8 +110,8 @@ ACPI_EXPORT_SYMBOL(acpi_reset) * * FUNCTION: acpi_read * - * PARAMETERS: Value - Where the value is returned - * Reg - GAS register structure + * PARAMETERS: value - Where the value is returned + * reg - GAS register structure * * RETURN: Status * @@ -113,14 +119,15 @@ ACPI_EXPORT_SYMBOL(acpi_reset) * * LIMITATIONS: <These limitations also apply to acpi_write> * bit_width must be exactly 8, 16, 32, or 64. - * space_iD must be system_memory or system_iO. + * space_ID must be system_memory or system_IO. * bit_offset and access_width are currently ignored, as there has * not been a need to implement these. * ******************************************************************************/ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg) { - u32 value; + u32 value_lo; + u32 value_hi; u32 width; u64 address; acpi_status status; @@ -138,59 +145,48 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg) return (status); } - width = reg->bit_width; - if (width == 64) { - width = 32; /* Break into two 32-bit transfers */ - } - - /* Initialize entire 64-bit return value to zero */ - - *return_value = 0; - value = 0; - /* - * Two address spaces supported: Memory or IO. PCI_Config is + * Two address spaces supported: Memory or I/O. PCI_Config is * not supported here because the GAS structure is insufficient */ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { status = acpi_os_read_memory((acpi_physical_address) - address, &value, width); + address, return_value, + reg->bit_width); if (ACPI_FAILURE(status)) { return (status); } - *return_value = value; + } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ - if (reg->bit_width == 64) { + value_lo = 0; + value_hi = 0; - /* Read the top 32 bits */ - - status = acpi_os_read_memory((acpi_physical_address) - (address + 4), &value, 32); - if (ACPI_FAILURE(status)) { - return (status); - } - *return_value |= ((u64)value << 32); + width = reg->bit_width; + if (width == 64) { + width = 32; /* Break into two 32-bit transfers */ } - } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ status = acpi_hw_read_port((acpi_io_address) - address, &value, width); + address, &value_lo, width); if (ACPI_FAILURE(status)) { return (status); } - *return_value = value; if (reg->bit_width == 64) { /* Read the top 32 bits */ status = acpi_hw_read_port((acpi_io_address) - (address + 4), &value, 32); + (address + 4), &value_hi, + 32); if (ACPI_FAILURE(status)) { return (status); } - *return_value |= ((u64)value << 32); } + + /* Set the return value only if status is AE_OK */ + + *return_value = (value_lo | ((u64)value_hi << 32)); } ACPI_DEBUG_PRINT((ACPI_DB_IO, @@ -199,7 +195,7 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg) ACPI_FORMAT_UINT64(address), acpi_ut_get_region_name(reg->space_id))); - return (status); + return (AE_OK); } ACPI_EXPORT_SYMBOL(acpi_read) @@ -208,8 +204,8 @@ ACPI_EXPORT_SYMBOL(acpi_read) * * FUNCTION: acpi_write * - * PARAMETERS: Value - Value to be written - * Reg - GAS register structure + * PARAMETERS: value - Value to be written + * reg - GAS register structure * * RETURN: Status * @@ -231,32 +227,22 @@ acpi_status acpi_write(u64 value, struct acpi_generic_address *reg) return (status); } - width = reg->bit_width; - if (width == 64) { - width = 32; /* Break into two 32-bit transfers */ - } - /* * Two address spaces supported: Memory or IO. PCI_Config is * not supported here because the GAS structure is insufficient */ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { status = acpi_os_write_memory((acpi_physical_address) - address, ACPI_LODWORD(value), - width); + address, value, reg->bit_width); if (ACPI_FAILURE(status)) { return (status); } + } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ - if (reg->bit_width == 64) { - status = acpi_os_write_memory((acpi_physical_address) - (address + 4), - ACPI_HIDWORD(value), 32); - if (ACPI_FAILURE(status)) { - return (status); - } + width = reg->bit_width; + if (width == 64) { + width = 32; /* Break into two 32-bit transfers */ } - } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ status = acpi_hw_write_port((acpi_io_address) address, ACPI_LODWORD(value), @@ -286,6 +272,7 @@ acpi_status acpi_write(u64 value, struct acpi_generic_address *reg) ACPI_EXPORT_SYMBOL(acpi_write) +#if (!ACPI_REDUCED_HARDWARE) /******************************************************************************* * * FUNCTION: acpi_read_bit_register @@ -355,7 +342,7 @@ ACPI_EXPORT_SYMBOL(acpi_read_bit_register) * FUNCTION: acpi_write_bit_register * * PARAMETERS: register_id - ID of ACPI Bit Register to access - * Value - Value to write to the register, in bit + * value - Value to write to the register, in bit * position zero. The bit is automatically * shifted to the correct position. * @@ -453,7 +440,7 @@ unlock_and_exit: } ACPI_EXPORT_SYMBOL(acpi_write_bit_register) - +#endif /* !ACPI_REDUCED_HARDWARE */ /******************************************************************************* * * FUNCTION: acpi_get_sleep_type_data @@ -462,17 +449,41 @@ ACPI_EXPORT_SYMBOL(acpi_write_bit_register) * *sleep_type_a - Where SLP_TYPa is returned * *sleep_type_b - Where SLP_TYPb is returned * - * RETURN: Status - ACPI status + * RETURN: Status + * + * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested + * sleep state via the appropriate \_Sx object. + * + * The sleep state package returned from the corresponding \_Sx_ object + * must contain at least one integer. + * + * March 2005: + * Added support for a package that contains two integers. This + * goes against the ACPI specification which defines this object as a + * package with one encoded DWORD integer. However, existing practice + * by many BIOS vendors is to return a package with 2 or more integer + * elements, at least one per sleep type (A/B). + * + * January 2013: + * Therefore, we must be prepared to accept a package with either a + * single integer or multiple integers. * - * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep - * state. + * The single integer DWORD format is as follows: + * BYTE 0 - Value for the PM1A SLP_TYP register + * BYTE 1 - Value for the PM1B SLP_TYP register + * BYTE 2-3 - Reserved + * + * The dual integer format is as follows: + * Integer 0 - Value for the PM1A SLP_TYP register + * Integer 1 - Value for the PM1A SLP_TYP register * ******************************************************************************/ acpi_status acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) { - acpi_status status = AE_OK; + acpi_status status; struct acpi_evaluate_info *info; + union acpi_operand_object **elements; ACPI_FUNCTION_TRACE(acpi_get_sleep_type_data); @@ -489,18 +500,14 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) return_ACPI_STATUS(AE_NO_MEMORY); } - info->pathname = + /* + * Evaluate the \_Sx namespace object containing the register values + * for this state + */ + info->relative_pathname = ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]); - - /* Evaluate the namespace object containing the values for this state */ - status = acpi_ns_evaluate(info); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "%s while evaluating SleepState [%s]\n", - acpi_format_exception(status), - info->pathname)); - goto cleanup; } @@ -508,65 +515,71 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) if (!info->return_object) { ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]", - info->pathname)); - status = AE_NOT_EXIST; + info->relative_pathname)); + status = AE_AML_NO_RETURN_VALUE; + goto cleanup; } - /* It must be of type Package */ + /* Return object must be of type Package */ - else if (info->return_object->common.type != ACPI_TYPE_PACKAGE) { + if (info->return_object->common.type != ACPI_TYPE_PACKAGE) { ACPI_ERROR((AE_INFO, "Sleep State return object is not a Package")); status = AE_AML_OPERAND_TYPE; + goto cleanup1; } /* - * The package must have at least two elements. NOTE (March 2005): This - * goes against the current ACPI spec which defines this object as a - * package with one encoded DWORD element. However, existing practice - * by BIOS vendors seems to be to have 2 or more elements, at least - * one per sleep type (A/B). + * Any warnings about the package length or the object types have + * already been issued by the predefined name module -- there is no + * need to repeat them here. */ - else if (info->return_object->package.count < 2) { - ACPI_ERROR((AE_INFO, - "Sleep State return package does not have at least two elements")); - status = AE_AML_NO_OPERAND; - } + elements = info->return_object->package.elements; + switch (info->return_object->package.count) { + case 0: - /* The first two elements must both be of type Integer */ + status = AE_AML_PACKAGE_LIMIT; + break; - else if (((info->return_object->package.elements[0])->common.type - != ACPI_TYPE_INTEGER) || - ((info->return_object->package.elements[1])->common.type - != ACPI_TYPE_INTEGER)) { - ACPI_ERROR((AE_INFO, - "Sleep State return package elements are not both Integers " - "(%s, %s)", - acpi_ut_get_object_type_name(info->return_object-> - package.elements[0]), - acpi_ut_get_object_type_name(info->return_object-> - package.elements[1]))); - status = AE_AML_OPERAND_TYPE; - } else { - /* Valid _Sx_ package size, type, and value */ + case 1: + + if (elements[0]->common.type != ACPI_TYPE_INTEGER) { + status = AE_AML_OPERAND_TYPE; + break; + } + + /* A valid _Sx_ package with one integer */ + + *sleep_type_a = (u8)elements[0]->integer.value; + *sleep_type_b = (u8)(elements[0]->integer.value >> 8); + break; + + case 2: + default: - *sleep_type_a = (u8) - (info->return_object->package.elements[0])->integer.value; - *sleep_type_b = (u8) - (info->return_object->package.elements[1])->integer.value; + if ((elements[0]->common.type != ACPI_TYPE_INTEGER) || + (elements[1]->common.type != ACPI_TYPE_INTEGER)) { + status = AE_AML_OPERAND_TYPE; + break; + } + + /* A valid _Sx_ package with two integers */ + + *sleep_type_a = (u8)elements[0]->integer.value; + *sleep_type_b = (u8)elements[1]->integer.value; + break; } +cleanup1: + acpi_ut_remove_reference(info->return_object); + +cleanup: if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, - "While evaluating SleepState [%s], bad Sleep object %p type %s", - info->pathname, info->return_object, - acpi_ut_get_object_type_name(info-> - return_object))); + "While evaluating Sleep State [%s]", + info->relative_pathname)); } - acpi_ut_remove_reference(info->return_object); - - cleanup: ACPI_FREE(info); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c new file mode 100644 index 00000000000..6921c7f3d20 --- /dev/null +++ b/drivers/acpi/acpica/hwxfsleep.c @@ -0,0 +1,432 @@ +/****************************************************************************** + * + * Name: hwxfsleep.c - ACPI Hardware Sleep/Wake External Interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define EXPORT_ACPI_INTERFACES + +#include <acpi/acpi.h> +#include "accommon.h" + +#define _COMPONENT ACPI_HARDWARE +ACPI_MODULE_NAME("hwxfsleep") + +/* Local prototypes */ +static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id); + +/* + * Dispatch table used to efficiently branch to the various sleep + * functions. + */ +#define ACPI_SLEEP_FUNCTION_ID 0 +#define ACPI_WAKE_PREP_FUNCTION_ID 1 +#define ACPI_WAKE_FUNCTION_ID 2 + +/* Legacy functions are optional, based upon ACPI_REDUCED_HARDWARE */ + +static struct acpi_sleep_functions acpi_sleep_dispatch[] = { + {ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_sleep), + acpi_hw_extended_sleep}, + {ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_wake_prep), + acpi_hw_extended_wake_prep}, + {ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_wake), acpi_hw_extended_wake} +}; + +/* + * These functions are removed for the ACPI_REDUCED_HARDWARE case: + * acpi_set_firmware_waking_vector + * acpi_set_firmware_waking_vector64 + * acpi_enter_sleep_state_s4bios + */ + +#if (!ACPI_REDUCED_HARDWARE) +/******************************************************************************* + * + * FUNCTION: acpi_set_firmware_waking_vector + * + * PARAMETERS: physical_address - 32-bit physical address of ACPI real mode + * entry point. + * + * RETURN: Status + * + * DESCRIPTION: Sets the 32-bit firmware_waking_vector field of the FACS + * + ******************************************************************************/ + +acpi_status acpi_set_firmware_waking_vector(u32 physical_address) +{ + ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); + + + /* + * According to the ACPI specification 2.0c and later, the 64-bit + * waking vector should be cleared and the 32-bit waking vector should + * be used, unless we want the wake-up code to be called by the BIOS in + * Protected Mode. Some systems (for example HP dv5-1004nr) are known + * to fail to resume if the 64-bit vector is used. + */ + + /* Set the 32-bit vector */ + + acpi_gbl_FACS->firmware_waking_vector = physical_address; + + /* Clear the 64-bit vector if it exists */ + + if ((acpi_gbl_FACS->length > 32) && (acpi_gbl_FACS->version >= 1)) { + acpi_gbl_FACS->xfirmware_waking_vector = 0; + } + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) + +#if ACPI_MACHINE_WIDTH == 64 +/******************************************************************************* + * + * FUNCTION: acpi_set_firmware_waking_vector64 + * + * PARAMETERS: physical_address - 64-bit physical address of ACPI protected + * mode entry point. + * + * RETURN: Status + * + * DESCRIPTION: Sets the 64-bit X_firmware_waking_vector field of the FACS, if + * it exists in the table. This function is intended for use with + * 64-bit host operating systems. + * + ******************************************************************************/ +acpi_status acpi_set_firmware_waking_vector64(u64 physical_address) +{ + ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector64); + + + /* Determine if the 64-bit vector actually exists */ + + if ((acpi_gbl_FACS->length <= 32) || (acpi_gbl_FACS->version < 1)) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* Clear 32-bit vector, set the 64-bit X_ vector */ + + acpi_gbl_FACS->firmware_waking_vector = 0; + acpi_gbl_FACS->xfirmware_waking_vector = physical_address; + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64) +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_enter_sleep_state_s4bios + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Perform a S4 bios request. + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED + * + ******************************************************************************/ +acpi_status acpi_enter_sleep_state_s4bios(void) +{ + u32 in_value; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios); + + /* Clear the wake status bit (PM1) */ + + status = + acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_hw_clear_acpi_status(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * 1) Disable/Clear all GPEs + * 2) Enable all wakeup GPEs + */ + status = acpi_hw_disable_all_gpes(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + acpi_gbl_system_awake_and_running = FALSE; + + status = acpi_hw_enable_all_wakeup_gpes(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + ACPI_FLUSH_CPU_CACHE(); + + status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, + (u32)acpi_gbl_FADT.s4_bios_request, 8); + + do { + acpi_os_stall(ACPI_USEC_PER_MSEC); + status = + acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } while (!in_value); + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios) +#endif /* !ACPI_REDUCED_HARDWARE */ +/******************************************************************************* + * + * FUNCTION: acpi_hw_sleep_dispatch + * + * PARAMETERS: sleep_state - Which sleep state to enter/exit + * function_id - Sleep, wake_prep, or Wake + * + * RETURN: Status from the invoked sleep handling function. + * + * DESCRIPTION: Dispatch a sleep/wake request to the appropriate handling + * function. + * + ******************************************************************************/ +static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id) +{ + acpi_status status; + struct acpi_sleep_functions *sleep_functions = + &acpi_sleep_dispatch[function_id]; + +#if (!ACPI_REDUCED_HARDWARE) + /* + * If the Hardware Reduced flag is set (from the FADT), we must + * use the extended sleep registers (FADT). Note: As per the ACPI + * specification, these extended registers are to be used for HW-reduced + * platforms only. They are not general-purpose replacements for the + * legacy PM register sleep support. + */ + if (acpi_gbl_reduced_hardware) { + status = sleep_functions->extended_function(sleep_state); + } else { + /* Legacy sleep */ + + status = sleep_functions->legacy_function(sleep_state); + } + + return (status); + +#else + /* + * For the case where reduced-hardware-only code is being generated, + * we know that only the extended sleep registers are available + */ + status = sleep_functions->extended_function(sleep_state); + return (status); + +#endif /* !ACPI_REDUCED_HARDWARE */ +} + +/******************************************************************************* + * + * FUNCTION: acpi_enter_sleep_state_prep + * + * PARAMETERS: sleep_state - Which sleep state to enter + * + * RETURN: Status + * + * DESCRIPTION: Prepare to enter a system sleep state. + * This function must execute with interrupts enabled. + * We break sleeping into 2 stages so that OSPM can handle + * various OS-specific tasks between the two steps. + * + ******************************************************************************/ + +acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) +{ + acpi_status status; + struct acpi_object_list arg_list; + union acpi_object arg; + u32 sst_value; + + ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep); + + status = acpi_get_sleep_type_data(sleep_state, + &acpi_gbl_sleep_type_a, + &acpi_gbl_sleep_type_b); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Execute the _PTS method (Prepare To Sleep) */ + + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = sleep_state; + + status = + acpi_evaluate_object(NULL, METHOD_PATHNAME__PTS, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + return_ACPI_STATUS(status); + } + + /* Setup the argument to the _SST method (System STatus) */ + + switch (sleep_state) { + case ACPI_STATE_S0: + + sst_value = ACPI_SST_WORKING; + break; + + case ACPI_STATE_S1: + case ACPI_STATE_S2: + case ACPI_STATE_S3: + + sst_value = ACPI_SST_SLEEPING; + break; + + case ACPI_STATE_S4: + + sst_value = ACPI_SST_SLEEP_CONTEXT; + break; + + default: + + sst_value = ACPI_SST_INDICATOR_OFF; /* Default is off */ + break; + } + + /* + * Set the system indicators to show the desired sleep state. + * _SST is an optional method (return no error if not found) + */ + acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, sst_value); + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) + +/******************************************************************************* + * + * FUNCTION: acpi_enter_sleep_state + * + * PARAMETERS: sleep_state - Which sleep state to enter + * + * RETURN: Status + * + * DESCRIPTION: Enter a system sleep state + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED + * + ******************************************************************************/ +acpi_status acpi_enter_sleep_state(u8 sleep_state) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); + + if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) || + (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) { + ACPI_ERROR((AE_INFO, "Sleep values out of range: A=0x%X B=0x%X", + acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b)); + return_ACPI_STATUS(AE_AML_OPERAND_VALUE); + } + + status = acpi_hw_sleep_dispatch(sleep_state, ACPI_SLEEP_FUNCTION_ID); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state) + +/******************************************************************************* + * + * FUNCTION: acpi_leave_sleep_state_prep + * + * PARAMETERS: sleep_state - Which sleep state we are exiting + * + * RETURN: Status + * + * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a + * sleep. Called with interrupts DISABLED. + * We break wake/resume into 2 stages so that OSPM can handle + * various OS-specific tasks between the two steps. + * + ******************************************************************************/ +acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep); + + status = + acpi_hw_sleep_dispatch(sleep_state, ACPI_WAKE_PREP_FUNCTION_ID); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state_prep) + +/******************************************************************************* + * + * FUNCTION: acpi_leave_sleep_state + * + * PARAMETERS: sleep_state - Which sleep state we are exiting + * + * RETURN: Status + * + * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep + * Called with interrupts ENABLED. + * + ******************************************************************************/ +acpi_status acpi_leave_sleep_state(u8 sleep_state) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); + + status = acpi_hw_sleep_dispatch(sleep_state, ACPI_WAKE_FUNCTION_ID); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state) diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index 61623f3f682..f1249e3463b 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -110,11 +110,11 @@ acpi_status acpi_ns_root_initialize(void) status = acpi_ns_lookup(NULL, init_val->name, init_val->type, 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 */ + if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not create predefined name %s", init_val->name)); + continue; } /* @@ -151,13 +151,14 @@ acpi_status acpi_ns_root_initialize(void) */ switch (init_val->type) { case ACPI_TYPE_METHOD: + obj_desc->method.param_count = (u8) ACPI_TO_INTEGER(val); obj_desc->common.flags |= AOPOBJ_DATA_VALID; #if defined (ACPI_ASL_COMPILER) - /* Save the parameter count for the i_aSL compiler */ + /* Save the parameter count for the iASL compiler */ new_node->value = obj_desc->method.param_count; #else @@ -179,8 +180,7 @@ acpi_status acpi_ns_root_initialize(void) /* Build an object around the static string */ - obj_desc->string.length = - (u32) ACPI_STRLEN(val); + obj_desc->string.length = (u32)ACPI_STRLEN(val); obj_desc->string.pointer = val; obj_desc->common.flags |= AOPOBJ_STATIC_POINTER; break; @@ -240,7 +240,7 @@ acpi_status acpi_ns_root_initialize(void) } } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); /* Save a handle to "_GPE", it is always present */ @@ -258,11 +258,11 @@ acpi_status acpi_ns_root_initialize(void) * FUNCTION: acpi_ns_lookup * * PARAMETERS: scope_info - Current scope info block - * Pathname - Search pathname, in internal format + * pathname - Search pathname, in internal format * (as represented in the AML stream) - * Type - Type associated with name + * type - Type associated with name * interpreter_mode - IMODE_LOAD_PASS2 => add name if not found - * Flags - Flags describing the search restrictions + * flags - Flags describing the search restrictions * walk_state - Current state of the walk * return_node - Where the Node is placed (if found * or created successfully) @@ -424,8 +424,9 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, /* Current scope has no parent scope */ ACPI_ERROR((AE_INFO, - "ACPI path has too many parent prefixes (^) " - "- reached beyond root node")); + "%s: Path has too many parent prefixes (^) " + "- reached beyond root node", + pathname)); return_ACPI_STATUS(AE_NOT_FOUND); } } diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c index 7c3d3ceb98b..607eb9e5150 100644 --- a/drivers/acpi/acpica/nsalloc.c +++ b/drivers/acpi/acpica/nsalloc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,7 +52,7 @@ ACPI_MODULE_NAME("nsalloc") * * FUNCTION: acpi_ns_create_node * - * PARAMETERS: Name - Name of the new node (4 char ACPI name) + * PARAMETERS: name - Name of the new node (4 char ACPI name) * * RETURN: New namespace node (Null on failure) * @@ -92,7 +92,7 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name) * * FUNCTION: acpi_ns_delete_node * - * PARAMETERS: Node - Node to be deleted + * PARAMETERS: node - Node to be deleted * * RETURN: None * @@ -106,6 +106,7 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name) void acpi_ns_delete_node(struct acpi_namespace_node *node) { union acpi_operand_object *obj_desc; + union acpi_operand_object *next_desc; ACPI_FUNCTION_NAME(ns_delete_node); @@ -114,12 +115,13 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) acpi_ns_detach_object(node); /* - * Delete an attached data object if present (an object that was created - * and attached via acpi_attach_data). Note: After any normal object is - * detached above, the only possible remaining object is a data object. + * Delete an attached data object list if present (objects that were + * attached via acpi_attach_data). Note: After any normal object is + * detached above, the only possible remaining object(s) are data + * objects, in a linked list. */ obj_desc = node->object; - if (obj_desc && (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) { + while (obj_desc && (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) { /* Invoke the attached data deletion handler if present */ @@ -127,7 +129,15 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) obj_desc->data.handler(node, obj_desc->data.pointer); } + next_desc = obj_desc->common.next_object; acpi_ut_remove_reference(obj_desc); + obj_desc = next_desc; + } + + /* Special case for the statically allocated root node */ + + if (node == acpi_gbl_root_node) { + return; } /* Now we can delete the node */ @@ -143,7 +153,7 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) * * FUNCTION: acpi_ns_remove_node * - * PARAMETERS: Node - Node to be removed/deleted + * PARAMETERS: node - Node to be removed/deleted * * RETURN: None * @@ -196,8 +206,8 @@ void acpi_ns_remove_node(struct acpi_namespace_node *node) * * PARAMETERS: walk_state - Current state of the walk * parent_node - The parent of the new Node - * Node - The new Node to install - * Type - ACPI object type of the new Node + * node - The new Node to install + * type - ACPI object type of the new Node * * RETURN: None * @@ -332,7 +342,7 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) * * RETURN: None. * - * DESCRIPTION: Delete a subtree of the namespace. This includes all objects + * DESCRIPTION: Delete a subtree of the namespace. This includes all objects * stored within the subtree. * ******************************************************************************/ @@ -418,7 +428,7 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node) * RETURN: Status * * DESCRIPTION: Delete entries within the namespace that are owned by a - * specific ID. Used to delete entire ACPI tables. All + * specific ID. Used to delete entire ACPI tables. All * reference counts are updated. * * MUTEX: Locks namespace during deletion walk. diff --git a/drivers/acpi/acpica/nsarguments.c b/drivers/acpi/acpica/nsarguments.c new file mode 100644 index 00000000000..80fcfc8c9c1 --- /dev/null +++ b/drivers/acpi/acpica/nsarguments.c @@ -0,0 +1,294 @@ +/****************************************************************************** + * + * Module Name: nsarguments - Validation of args for ACPI predefined methods + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acnamesp.h" +#include "acpredef.h" + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsarguments") + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_argument_types + * + * PARAMETERS: info - Method execution information block + * + * RETURN: None + * + * DESCRIPTION: Check the incoming argument count and all argument types + * against the argument type list for a predefined name. + * + ******************************************************************************/ +void acpi_ns_check_argument_types(struct acpi_evaluate_info *info) +{ + u16 arg_type_list; + u8 arg_count; + u8 arg_type; + u8 user_arg_type; + u32 i; + + /* If not a predefined name, cannot typecheck args */ + + if (!info->predefined) { + return; + } + + arg_type_list = info->predefined->info.argument_list; + arg_count = METHOD_GET_ARG_COUNT(arg_type_list); + + /* Typecheck all arguments */ + + for (i = 0; ((i < arg_count) && (i < info->param_count)); i++) { + arg_type = METHOD_GET_NEXT_TYPE(arg_type_list); + user_arg_type = info->parameters[i]->common.type; + + if (user_arg_type != arg_type) { + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + ACPI_WARN_ALWAYS, + "Argument #%u type mismatch - " + "Found [%s], ACPI requires [%s]", + (i + 1), + acpi_ut_get_type_name + (user_arg_type), + acpi_ut_get_type_name(arg_type))); + } + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_acpi_compliance + * + * PARAMETERS: pathname - Full pathname to the node (for error msgs) + * node - Namespace node for the method/object + * predefined - Pointer to entry in predefined name table + * + * RETURN: None + * + * DESCRIPTION: Check that the declared parameter count (in ASL/AML) for a + * predefined name is what is expected (matches what is defined in + * the ACPI specification for this predefined name.) + * + ******************************************************************************/ + +void +acpi_ns_check_acpi_compliance(char *pathname, + struct acpi_namespace_node *node, + const union acpi_predefined_info *predefined) +{ + u32 aml_param_count; + u32 required_param_count; + + if (!predefined) { + return; + } + + /* Get the ACPI-required arg count from the predefined info table */ + + required_param_count = + METHOD_GET_ARG_COUNT(predefined->info.argument_list); + + /* + * If this object is not a control method, we can check if the ACPI + * spec requires that it be a method. + */ + if (node->type != ACPI_TYPE_METHOD) { + if (required_param_count > 0) { + + /* Object requires args, must be implemented as a method */ + + ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, + ACPI_WARN_ALWAYS, + "Object (%s) must be a control method with %u arguments", + acpi_ut_get_type_name(node-> + type), + required_param_count)); + } else if (!required_param_count + && !predefined->info.expected_btypes) { + + /* Object requires no args and no return value, must be a method */ + + ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, + ACPI_WARN_ALWAYS, + "Object (%s) must be a control method " + "with no arguments and no return value", + acpi_ut_get_type_name(node-> + type))); + } + + return; + } + + /* + * This is a control method. + * Check that the ASL/AML-defined parameter count for this method + * matches the ACPI-required parameter count + * + * Some methods are allowed to have a "minimum" number of args (_SCP) + * because their definition in ACPI has changed over time. + * + * Note: These are BIOS errors in the declaration of the object + */ + aml_param_count = node->object->method.param_count; + + if (aml_param_count < required_param_count) { + ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS, + "Insufficient arguments - " + "ASL declared %u, ACPI requires %u", + aml_param_count, + required_param_count)); + } else if ((aml_param_count > required_param_count) + && !(predefined->info. + argument_list & ARG_COUNT_IS_MINIMUM)) { + ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS, + "Excess arguments - " + "ASL declared %u, ACPI requires %u", + aml_param_count, + required_param_count)); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_argument_count + * + * PARAMETERS: pathname - Full pathname to the node (for error msgs) + * node - Namespace node for the method/object + * user_param_count - Number of args passed in by the caller + * predefined - Pointer to entry in predefined name table + * + * RETURN: None + * + * DESCRIPTION: Check that incoming argument count matches the declared + * parameter count (in the ASL/AML) for an object. + * + ******************************************************************************/ + +void +acpi_ns_check_argument_count(char *pathname, + struct acpi_namespace_node *node, + u32 user_param_count, + const union acpi_predefined_info *predefined) +{ + u32 aml_param_count; + u32 required_param_count; + + if (!predefined) { + /* + * Not a predefined name. Check the incoming user argument count + * against the count that is specified in the method/object. + */ + if (node->type != ACPI_TYPE_METHOD) { + if (user_param_count) { + ACPI_INFO_PREDEFINED((AE_INFO, pathname, + ACPI_WARN_ALWAYS, + "%u arguments were passed to a non-method ACPI object (%s)", + user_param_count, + acpi_ut_get_type_name + (node->type))); + } + + return; + } + + /* + * This is a control method. Check the parameter count. + * We can only check the incoming argument count against the + * argument count declared for the method in the ASL/AML. + * + * Emit a message if too few or too many arguments have been passed + * by the caller. + * + * Note: Too many arguments will not cause the method to + * fail. However, the method will fail if there are too few + * arguments and the method attempts to use one of the missing ones. + */ + aml_param_count = node->object->method.param_count; + + if (user_param_count < aml_param_count) { + ACPI_WARN_PREDEFINED((AE_INFO, pathname, + ACPI_WARN_ALWAYS, + "Insufficient arguments - " + "Caller passed %u, method requires %u", + user_param_count, + aml_param_count)); + } else if (user_param_count > aml_param_count) { + ACPI_INFO_PREDEFINED((AE_INFO, pathname, + ACPI_WARN_ALWAYS, + "Excess arguments - " + "Caller passed %u, method requires %u", + user_param_count, + aml_param_count)); + } + + return; + } + + /* + * This is a predefined name. Validate the user-supplied parameter + * count against the ACPI specification. We don't validate against + * the method itself because what is important here is that the + * caller is in conformance with the spec. (The arg count for the + * method was checked against the ACPI spec earlier.) + * + * Some methods are allowed to have a "minimum" number of args (_SCP) + * because their definition in ACPI has changed over time. + */ + required_param_count = + METHOD_GET_ARG_COUNT(predefined->info.argument_list); + + if (user_param_count < required_param_count) { + ACPI_WARN_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS, + "Insufficient arguments - " + "Caller passed %u, ACPI requires %u", + user_param_count, required_param_count)); + } else if ((user_param_count > required_param_count) && + !(predefined->info.argument_list & ARG_COUNT_IS_MINIMUM)) { + ACPI_INFO_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS, + "Excess arguments - " + "Caller passed %u, ACPI requires %u", + user_param_count, required_param_count)); + } +} diff --git a/drivers/acpi/acpica/nsconvert.c b/drivers/acpi/acpica/nsconvert.c new file mode 100644 index 00000000000..b55642c4ee5 --- /dev/null +++ b/drivers/acpi/acpica/nsconvert.c @@ -0,0 +1,446 @@ +/****************************************************************************** + * + * Module Name: nsconvert - Object conversions for objects returned by + * predefined methods + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "acpredef.h" +#include "amlresrc.h" + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsconvert") + +/******************************************************************************* + * + * FUNCTION: acpi_ns_convert_to_integer + * + * PARAMETERS: original_object - Object to be converted + * return_object - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer. + * + ******************************************************************************/ +acpi_status +acpi_ns_convert_to_integer(union acpi_operand_object *original_object, + union acpi_operand_object **return_object) +{ + union acpi_operand_object *new_object; + acpi_status status; + u64 value = 0; + u32 i; + + switch (original_object->common.type) { + case ACPI_TYPE_STRING: + + /* String-to-Integer conversion */ + + status = acpi_ut_strtoul64(original_object->string.pointer, + ACPI_ANY_BASE, &value); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_TYPE_BUFFER: + + /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */ + + if (original_object->buffer.length > 8) { + return (AE_AML_OPERAND_TYPE); + } + + /* Extract each buffer byte to create the integer */ + + for (i = 0; i < original_object->buffer.length; i++) { + value |= + ((u64)original_object->buffer. + pointer[i] << (i * 8)); + } + break; + + default: + + return (AE_AML_OPERAND_TYPE); + } + + new_object = acpi_ut_create_integer_object(value); + if (!new_object) { + return (AE_NO_MEMORY); + } + + *return_object = new_object; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_convert_to_string + * + * PARAMETERS: original_object - Object to be converted + * return_object - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String. + * + ******************************************************************************/ + +acpi_status +acpi_ns_convert_to_string(union acpi_operand_object *original_object, + union acpi_operand_object **return_object) +{ + union acpi_operand_object *new_object; + acpi_size length; + acpi_status status; + + switch (original_object->common.type) { + case ACPI_TYPE_INTEGER: + /* + * Integer-to-String conversion. Commonly, convert + * an integer of value 0 to a NULL string. The last element of + * _BIF and _BIX packages occasionally need this fix. + */ + if (original_object->integer.value == 0) { + + /* Allocate a new NULL string object */ + + new_object = acpi_ut_create_string_object(0); + if (!new_object) { + return (AE_NO_MEMORY); + } + } else { + status = + acpi_ex_convert_to_string(original_object, + &new_object, + ACPI_IMPLICIT_CONVERT_HEX); + if (ACPI_FAILURE(status)) { + return (status); + } + } + break; + + case ACPI_TYPE_BUFFER: + /* + * Buffer-to-String conversion. Use a to_string + * conversion, no transform performed on the buffer data. The best + * example of this is the _BIF method, where the string data from + * the battery is often (incorrectly) returned as buffer object(s). + */ + length = 0; + while ((length < original_object->buffer.length) && + (original_object->buffer.pointer[length])) { + length++; + } + + /* Allocate a new string object */ + + new_object = acpi_ut_create_string_object(length); + if (!new_object) { + return (AE_NO_MEMORY); + } + + /* + * Copy the raw buffer data with no transform. String is already NULL + * terminated at Length+1. + */ + ACPI_MEMCPY(new_object->string.pointer, + original_object->buffer.pointer, length); + break; + + default: + + return (AE_AML_OPERAND_TYPE); + } + + *return_object = new_object; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_convert_to_buffer + * + * PARAMETERS: original_object - Object to be converted + * return_object - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer. + * + ******************************************************************************/ + +acpi_status +acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, + union acpi_operand_object **return_object) +{ + union acpi_operand_object *new_object; + acpi_status status; + union acpi_operand_object **elements; + u32 *dword_buffer; + u32 count; + u32 i; + + switch (original_object->common.type) { + case ACPI_TYPE_INTEGER: + /* + * Integer-to-Buffer conversion. + * Convert the Integer to a packed-byte buffer. _MAT and other + * objects need this sometimes, if a read has been performed on a + * Field object that is less than or equal to the global integer + * size (32 or 64 bits). + */ + status = + acpi_ex_convert_to_buffer(original_object, &new_object); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_TYPE_STRING: + + /* String-to-Buffer conversion. Simple data copy */ + + new_object = + acpi_ut_create_buffer_object(original_object->string. + length); + if (!new_object) { + return (AE_NO_MEMORY); + } + + ACPI_MEMCPY(new_object->buffer.pointer, + original_object->string.pointer, + original_object->string.length); + break; + + case ACPI_TYPE_PACKAGE: + /* + * This case is often seen for predefined names that must return a + * Buffer object with multiple DWORD integers within. For example, + * _FDE and _GTM. The Package can be converted to a Buffer. + */ + + /* All elements of the Package must be integers */ + + elements = original_object->package.elements; + count = original_object->package.count; + + for (i = 0; i < count; i++) { + if ((!*elements) || + ((*elements)->common.type != ACPI_TYPE_INTEGER)) { + return (AE_AML_OPERAND_TYPE); + } + elements++; + } + + /* Create the new buffer object to replace the Package */ + + new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count)); + if (!new_object) { + return (AE_NO_MEMORY); + } + + /* Copy the package elements (integers) to the buffer as DWORDs */ + + elements = original_object->package.elements; + dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer); + + for (i = 0; i < count; i++) { + *dword_buffer = (u32)(*elements)->integer.value; + dword_buffer++; + elements++; + } + break; + + default: + + return (AE_AML_OPERAND_TYPE); + } + + *return_object = new_object; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_convert_to_unicode + * + * PARAMETERS: original_object - ASCII String Object to be converted + * return_object - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer. + * + ******************************************************************************/ + +acpi_status +acpi_ns_convert_to_unicode(union acpi_operand_object *original_object, + union acpi_operand_object **return_object) +{ + union acpi_operand_object *new_object; + char *ascii_string; + u16 *unicode_buffer; + u32 unicode_length; + u32 i; + + if (!original_object) { + return (AE_OK); + } + + /* If a Buffer was returned, it must be at least two bytes long */ + + if (original_object->common.type == ACPI_TYPE_BUFFER) { + if (original_object->buffer.length < 2) { + return (AE_AML_OPERAND_VALUE); + } + + *return_object = NULL; + return (AE_OK); + } + + /* + * The original object is an ASCII string. Convert this string to + * a unicode buffer. + */ + ascii_string = original_object->string.pointer; + unicode_length = (original_object->string.length * 2) + 2; + + /* Create a new buffer object for the Unicode data */ + + new_object = acpi_ut_create_buffer_object(unicode_length); + if (!new_object) { + return (AE_NO_MEMORY); + } + + unicode_buffer = ACPI_CAST_PTR(u16, new_object->buffer.pointer); + + /* Convert ASCII to Unicode */ + + for (i = 0; i < original_object->string.length; i++) { + unicode_buffer[i] = (u16)ascii_string[i]; + } + + *return_object = new_object; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_convert_to_resource + * + * PARAMETERS: original_object - Object to be converted + * return_object - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful + * + * DESCRIPTION: Attempt to convert a Integer object to a resource_template + * Buffer. + * + ******************************************************************************/ + +acpi_status +acpi_ns_convert_to_resource(union acpi_operand_object *original_object, + union acpi_operand_object **return_object) +{ + union acpi_operand_object *new_object; + u8 *buffer; + + /* + * We can fix the following cases for an expected resource template: + * 1. No return value (interpreter slack mode is disabled) + * 2. A "Return (Zero)" statement + * 3. A "Return empty buffer" statement + * + * We will return a buffer containing a single end_tag + * resource descriptor. + */ + if (original_object) { + switch (original_object->common.type) { + case ACPI_TYPE_INTEGER: + + /* We can only repair an Integer==0 */ + + if (original_object->integer.value) { + return (AE_AML_OPERAND_TYPE); + } + break; + + case ACPI_TYPE_BUFFER: + + if (original_object->buffer.length) { + + /* Additional checks can be added in the future */ + + *return_object = NULL; + return (AE_OK); + } + break; + + case ACPI_TYPE_STRING: + default: + + return (AE_AML_OPERAND_TYPE); + } + } + + /* Create the new buffer object for the resource descriptor */ + + new_object = acpi_ut_create_buffer_object(2); + if (!new_object) { + return (AE_NO_MEMORY); + } + + buffer = ACPI_CAST_PTR(u8, new_object->buffer.pointer); + + /* Initialize the Buffer with a single end_tag descriptor */ + + buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE); + buffer[1] = 0x00; + + *return_object = new_object; + return (AE_OK); +} diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index b7f2b3be79a..3d88ef4a3e0 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,6 +44,7 @@ #include <acpi/acpi.h> #include "accommon.h" #include "acnamesp.h" +#include <acpi/acoutput.h> #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsdump") @@ -58,12 +59,23 @@ acpi_ns_dump_one_device(acpi_handle obj_handle, #endif #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + +#ifdef ACPI_FUTURE_USAGE +static acpi_status +acpi_ns_dump_one_object_path(acpi_handle obj_handle, + u32 level, void *context, void **return_value); + +static acpi_status +acpi_ns_get_max_depth(acpi_handle obj_handle, + u32 level, void *context, void **return_value); +#endif /* ACPI_FUTURE_USAGE */ + /******************************************************************************* * * FUNCTION: acpi_ns_print_pathname * * PARAMETERS: num_segments - Number of ACPI name segments - * Pathname - The compressed (internal) path + * pathname - The compressed (internal) path * * RETURN: None * @@ -77,8 +89,9 @@ void acpi_ns_print_pathname(u32 num_segments, char *pathname) ACPI_FUNCTION_NAME(ns_print_pathname); - if (!(acpi_dbg_level & ACPI_LV_NAMES) - || !(acpi_dbg_layer & ACPI_NAMESPACE)) { + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_NAMES, ACPI_NAMESPACE)) { return; } @@ -107,10 +120,10 @@ void acpi_ns_print_pathname(u32 num_segments, char *pathname) * * FUNCTION: acpi_ns_dump_pathname * - * PARAMETERS: Handle - Object - * Msg - Prefix message - * Level - Desired debug level - * Component - Caller's component ID + * PARAMETERS: handle - Object + * msg - Prefix message + * level - Desired debug level + * component - Caller's component ID * * RETURN: None * @@ -127,7 +140,7 @@ acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component) /* Do this only if the requested debug level and component are enabled */ - if (!(acpi_dbg_level & level) || !(acpi_dbg_layer & component)) { + if (!ACPI_IS_DEBUG_ENABLED(level, component)) { return_VOID; } @@ -143,8 +156,8 @@ acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component) * FUNCTION: acpi_ns_dump_one_object * * PARAMETERS: obj_handle - Node to be dumped - * Level - Nesting level of the handle - * Context - Passed into walk_namespace + * level - Nesting level of the handle + * context - Passed into walk_namespace * return_value - Not used * * RETURN: Status @@ -209,14 +222,6 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, "Invalid ACPI Object Type 0x%08X", type)); } - if (!acpi_ut_valid_acpi_name(this_node->name.integer)) { - this_node->name.integer = - acpi_ut_repair_name(this_node->name.ascii); - - ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X", - this_node->name.integer)); - } - acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node)); } @@ -242,7 +247,22 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, if (!obj_desc) { - /* No attached object, we are done */ + /* No attached object. Some types should always have an object */ + + switch (type) { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_PACKAGE: + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_METHOD: + + acpi_os_printf("<No attached object>"); + break; + + default: + + break; + } acpi_os_printf("\n"); return (AE_OK); @@ -251,7 +271,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, switch (type) { case ACPI_TYPE_PROCESSOR: - acpi_os_printf("ID %X Len %.4X Addr %p\n", + acpi_os_printf("ID %02X Len %02X Addr %p\n", obj_desc->processor.proc_id, obj_desc->processor.length, ACPI_CAST_PTR(void, @@ -426,6 +446,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, break; default: + break; } break; @@ -560,39 +581,46 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, goto cleanup; case ACPI_TYPE_BUFFER_FIELD: + obj_desc = (union acpi_operand_object *)obj_desc->buffer_field. buffer_obj; break; case ACPI_TYPE_PACKAGE: + obj_desc = (void *)obj_desc->package.elements; break; case ACPI_TYPE_METHOD: + obj_desc = (void *)obj_desc->method.aml_start; break; case ACPI_TYPE_LOCAL_REGION_FIELD: + obj_desc = (void *)obj_desc->field.region_obj; break; case ACPI_TYPE_LOCAL_BANK_FIELD: + obj_desc = (void *)obj_desc->bank_field.region_obj; break; case ACPI_TYPE_LOCAL_INDEX_FIELD: + obj_desc = (void *)obj_desc->index_field.index_obj; break; default: + goto cleanup; } obj_type = ACPI_TYPE_INVALID; /* Terminate loop after next pass */ } - cleanup: +cleanup: acpi_os_printf("\n"); return (AE_OK); } @@ -602,7 +630,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, * * FUNCTION: acpi_ns_dump_objects * - * PARAMETERS: Type - Object type to be dumped + * PARAMETERS: type - Object type to be dumped * display_type - 0 or ACPI_DISPLAY_SUMMARY * max_depth - Maximum depth of dump. Use ACPI_UINT32_MAX * for an effectively unlimited depth. @@ -654,11 +682,141 @@ acpi_ns_dump_objects(acpi_object_type type, } #endif /* ACPI_FUTURE_USAGE */ +#ifdef ACPI_FUTURE_USAGE +/******************************************************************************* + * + * FUNCTION: acpi_ns_dump_one_object_path, acpi_ns_get_max_depth + * + * PARAMETERS: obj_handle - Node to be dumped + * level - Nesting level of the handle + * context - Passed into walk_namespace + * return_value - Not used + * + * RETURN: Status + * + * DESCRIPTION: Dump the full pathname to a namespace object. acp_ns_get_max_depth + * computes the maximum nesting depth in the namespace tree, in + * order to simplify formatting in acpi_ns_dump_one_object_path. + * These procedures are user_functions called by acpi_ns_walk_namespace. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_dump_one_object_path(acpi_handle obj_handle, + u32 level, void *context, void **return_value) +{ + u32 max_level = *((u32 *)context); + char *pathname; + struct acpi_namespace_node *node; + int path_indent; + + if (!obj_handle) { + return (AE_OK); + } + + node = acpi_ns_validate_handle(obj_handle); + if (!node) { + + /* Ignore bad node during namespace walk */ + + return (AE_OK); + } + + pathname = acpi_ns_get_external_pathname(node); + + path_indent = 1; + if (level <= max_level) { + path_indent = max_level - level + 1; + } + + acpi_os_printf("%2d%*s%-12s%*s", + level, level, " ", acpi_ut_get_type_name(node->type), + path_indent, " "); + + acpi_os_printf("%s\n", &pathname[1]); + ACPI_FREE(pathname); + return (AE_OK); +} + +static acpi_status +acpi_ns_get_max_depth(acpi_handle obj_handle, + u32 level, void *context, void **return_value) +{ + u32 *max_level = (u32 *)context; + + if (level > *max_level) { + *max_level = level; + } + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_dump_object_paths + * + * PARAMETERS: type - Object type to be dumped + * display_type - 0 or ACPI_DISPLAY_SUMMARY + * max_depth - Maximum depth of dump. Use ACPI_UINT32_MAX + * for an effectively unlimited depth. + * owner_id - Dump only objects owned by this ID. Use + * ACPI_UINT32_MAX to match all owners. + * start_handle - Where in namespace to start/end search + * + * RETURN: None + * + * DESCRIPTION: Dump full object pathnames within the loaded namespace. Uses + * acpi_ns_walk_namespace in conjunction with acpi_ns_dump_one_object_path. + * + ******************************************************************************/ + +void +acpi_ns_dump_object_paths(acpi_object_type type, + u8 display_type, + u32 max_depth, + acpi_owner_id owner_id, acpi_handle start_handle) +{ + acpi_status status; + u32 max_level = 0; + + ACPI_FUNCTION_ENTRY(); + + /* + * Just lock the entire namespace for the duration of the dump. + * We don't want any changes to the namespace during this time, + * especially the temporary nodes since we are going to display + * them also. + */ + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not acquire namespace mutex\n"); + return; + } + + /* Get the max depth of the namespace tree, for formatting later */ + + (void)acpi_ns_walk_namespace(type, start_handle, max_depth, + ACPI_NS_WALK_NO_UNLOCK | + ACPI_NS_WALK_TEMP_NODES, + acpi_ns_get_max_depth, NULL, + (void *)&max_level, NULL); + + /* Now dump the entire namespace */ + + (void)acpi_ns_walk_namespace(type, start_handle, max_depth, + ACPI_NS_WALK_NO_UNLOCK | + ACPI_NS_WALK_TEMP_NODES, + acpi_ns_dump_one_object_path, NULL, + (void *)&max_level, NULL); + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); +} +#endif /* ACPI_FUTURE_USAGE */ + /******************************************************************************* * * FUNCTION: acpi_ns_dump_entry * - * PARAMETERS: Handle - Node to be dumped + * PARAMETERS: handle - Node to be dumped * debug_level - Output level * * RETURN: None @@ -687,7 +845,7 @@ void acpi_ns_dump_entry(acpi_handle handle, u32 debug_level) * * PARAMETERS: search_base - Root of subtree to be dumped, or * NS_ALL to dump the entire namespace - * max_depth - Maximum depth of dump. Use INT_MAX + * max_depth - Maximum depth of dump. Use INT_MAX * for an effectively unlimited depth. * * RETURN: None @@ -724,5 +882,5 @@ void acpi_ns_dump_tables(acpi_handle search_base, u32 max_depth) ACPI_OWNER_ID_MAX, search_handle); return_VOID; } -#endif /* _ACPI_ASL_COMPILER */ -#endif /* defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) */ +#endif +#endif diff --git a/drivers/acpi/acpica/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c index 30ea5bc53a7..42d37109aa5 100644 --- a/drivers/acpi/acpica/nsdumpdv.c +++ b/drivers/acpi/acpica/nsdumpdv.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,7 +42,6 @@ */ #include <acpi/acpi.h> -#include "accommon.h" /* TBD: This entire module is apparently obsolete and should be removed */ @@ -55,9 +54,9 @@ ACPI_MODULE_NAME("nsdumpdv") * * FUNCTION: acpi_ns_dump_one_device * - * PARAMETERS: Handle - Node to be dumped - * Level - Nesting level of the handle - * Context - Passed into walk_namespace + * PARAMETERS: handle - Node to be dumped + * level - Nesting level of the handle + * context - Passed into walk_namespace * return_value - Not used * * RETURN: Status @@ -70,6 +69,7 @@ static acpi_status acpi_ns_dump_one_device(acpi_handle obj_handle, u32 level, void *context, void **return_value) { + struct acpi_buffer buffer; struct acpi_device_info *info; acpi_status status; u32 i; @@ -79,15 +79,17 @@ acpi_ns_dump_one_device(acpi_handle obj_handle, status = acpi_ns_dump_one_object(obj_handle, level, context, return_value); - status = acpi_get_object_info(obj_handle, &info); + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_get_object_info(obj_handle, &buffer); if (ACPI_SUCCESS(status)) { + info = buffer.pointer; for (i = 0; i < level; i++) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, " ")); } ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, " HID: %s, ADR: %8.8X%8.8X, Status: %X\n", - info->hardware_id.string, + info->hardware_id.value, ACPI_FORMAT_UINT64(info->address), info->current_status)); ACPI_FREE(info); @@ -121,7 +123,7 @@ void acpi_ns_dump_root_devices(void) return; } - status = acpi_get_handle(NULL, ACPI_NS_SYSTEM_BUS, &sys_bus_handle); + status = acpi_get_handle(NULL, METHOD_NAME__SB_, &sys_bus_handle); if (ACPI_FAILURE(status)) { return; } diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c index f375cb82e32..e634a05974d 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -59,11 +59,11 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, * * FUNCTION: acpi_ns_evaluate * - * PARAMETERS: Info - Evaluation info block, contains: + * PARAMETERS: info - Evaluation info block, contains: * prefix_node - Prefix or Method/Object Node to execute - * Pathname - Name of method to execute, If NULL, the + * relative_path - Name of method to execute, If NULL, the * Node is the object to execute - * Parameters - List of parameters to pass to the method, + * parameters - List of parameters to pass to the method, * terminated by NULL. Params itself may be * NULL if no parameters are being passed. * return_object - Where to put method's return value (if @@ -71,7 +71,7 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, * parameter_type - Type of Parameter list * return_object - Where to put method's return value (if * any). If NULL, no value is returned. - * Flags - ACPI_IGNORE_RETURN_VALUE to delete return + * flags - ACPI_IGNORE_RETURN_VALUE to delete return * * RETURN: Status * @@ -82,10 +82,9 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, * ******************************************************************************/ -acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) +acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) { acpi_status status; - struct acpi_namespace_node *node; ACPI_FUNCTION_TRACE(ns_evaluate); @@ -93,79 +92,138 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Initialize the return value to an invalid object */ + if (!info->node) { + /* + * Get the actual namespace node for the target object if we + * need to. Handles these cases: + * + * 1) Null node, valid pathname from root (absolute path) + * 2) Node and valid pathname (path relative to Node) + * 3) Node, Null pathname + */ + status = + acpi_ns_get_node(info->prefix_node, info->relative_pathname, + ACPI_NS_NO_UPSEARCH, &info->node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* + * For a method alias, we must grab the actual method node so that + * proper scoping context will be established before execution. + */ + if (acpi_ns_get_type(info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) { + info->node = + ACPI_CAST_PTR(struct acpi_namespace_node, + info->node->object); + } + + /* Complete the info block initialization */ info->return_object = NULL; + info->node_flags = info->node->flags; + info->obj_desc = acpi_ns_get_attached_object(info->node); + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", + info->relative_pathname, info->node, + acpi_ns_get_attached_object(info->node))); + + /* Get info if we have a predefined name (_HID, etc.) */ + + info->predefined = + acpi_ut_match_predefined_method(info->node->name.ascii); + + /* Get the full pathname to the object, for use in warning messages */ + + info->full_pathname = acpi_ns_get_external_pathname(info->node); + if (!info->full_pathname) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Count the number of arguments being passed in */ + info->param_count = 0; + if (info->parameters) { + while (info->parameters[info->param_count]) { + info->param_count++; + } + + /* Warn on impossible argument count */ + + if (info->param_count > ACPI_METHOD_NUM_ARGS) { + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + ACPI_WARN_ALWAYS, + "Excess arguments (%u) - using only %u", + info->param_count, + ACPI_METHOD_NUM_ARGS)); + + info->param_count = ACPI_METHOD_NUM_ARGS; + } + } /* - * Get the actual namespace node for the target object. Handles these cases: - * - * 1) Null node, Pathname (absolute path) - * 2) Node, Pathname (path relative to Node) - * 3) Node, Null Pathname + * For predefined names: Check that the declared argument count + * matches the ACPI spec -- otherwise this is a BIOS error. */ - status = acpi_ns_get_node(info->prefix_node, info->pathname, - ACPI_NS_NO_UPSEARCH, &info->resolved_node); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + acpi_ns_check_acpi_compliance(info->full_pathname, info->node, + info->predefined); /* - * For a method alias, we must grab the actual method node so that proper - * scoping context will be established before execution. + * For all names: Check that the incoming argument count for + * this method/object matches the actual ASL/AML definition. */ - if (acpi_ns_get_type(info->resolved_node) == - ACPI_TYPE_LOCAL_METHOD_ALIAS) { - info->resolved_node = - ACPI_CAST_PTR(struct acpi_namespace_node, - info->resolved_node->object); - } + acpi_ns_check_argument_count(info->full_pathname, info->node, + info->param_count, info->predefined); - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", info->pathname, - info->resolved_node, - acpi_ns_get_attached_object(info->resolved_node))); + /* For predefined names: Typecheck all incoming arguments */ - node = info->resolved_node; + acpi_ns_check_argument_types(info); /* - * Two major cases here: + * Three major evaluation cases: * - * 1) The object is a control method -- execute it - * 2) The object is not a method -- just return it's current value + * 1) Object types that cannot be evaluated by definition + * 2) The object is a control method -- execute it + * 3) The object is not a method -- just return it's current value */ - if (acpi_ns_get_type(info->resolved_node) == ACPI_TYPE_METHOD) { + switch (acpi_ns_get_type(info->node)) { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_EVENT: + case ACPI_TYPE_MUTEX: + case ACPI_TYPE_REGION: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_LOCAL_SCOPE: /* - * 1) Object is a control method - execute it + * 1) Disallow evaluation of certain object types. For these, + * object evaluation is undefined and not supported. + */ + ACPI_ERROR((AE_INFO, + "%s: Evaluation of object type [%s] is not supported", + info->full_pathname, + acpi_ut_get_type_name(info->node->type))); + + status = AE_TYPE; + goto cleanup; + + case ACPI_TYPE_METHOD: + /* + * 2) Object is a control method - execute it */ /* Verify that there is a method object associated with this node */ - info->obj_desc = - acpi_ns_get_attached_object(info->resolved_node); if (!info->obj_desc) { ACPI_ERROR((AE_INFO, - "Control method has no attached sub-object")); - return_ACPI_STATUS(AE_NULL_OBJECT); - } - - /* Count the number of arguments being passed to the method */ - - if (info->parameters) { - while (info->parameters[info->param_count]) { - if (info->param_count > ACPI_METHOD_MAX_ARG) { - return_ACPI_STATUS(AE_LIMIT); - } - info->param_count++; - } + "%s: Method has no attached sub-object", + info->full_pathname)); + status = AE_NULL_OBJECT; + goto cleanup; } - - ACPI_DUMP_PATHNAME(info->resolved_node, "ACPI: Execute Method", - ACPI_LV_INFO, _COMPONENT); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Method at AML address %p Length %X\n", + "**** Execute method [%s] at AML address %p length %X\n", + info->full_pathname, info->obj_desc->method.aml_start + 1, info->obj_desc->method.aml_length - 1)); @@ -180,81 +238,61 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) acpi_ex_enter_interpreter(); status = acpi_ps_execute_method(info); acpi_ex_exit_interpreter(); - } else { + break; + + default: /* - * 2) Object is not a method, return its current value - * - * Disallow certain object types. For these, "evaluation" is undefined. + * 3) All other non-method objects -- get the current object value */ - switch (info->resolved_node->type) { - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_EVENT: - case ACPI_TYPE_MUTEX: - case ACPI_TYPE_REGION: - case ACPI_TYPE_THERMAL: - case ACPI_TYPE_LOCAL_SCOPE: - - ACPI_ERROR((AE_INFO, - "[%4.4s] Evaluation of object type [%s] is not supported", - info->resolved_node->name.ascii, - acpi_ut_get_type_name(info->resolved_node-> - type))); - - return_ACPI_STATUS(AE_TYPE); - - default: - break; - } /* - * Objects require additional resolution steps (e.g., the Node may be - * a field that must be read, etc.) -- we can't just grab the object - * out of the node. + * Some objects require additional resolution steps (e.g., the Node + * may be a field that must be read, etc.) -- we can't just grab + * the object out of the node. * * Use resolve_node_to_value() to get the associated value. * * NOTE: we can get away with passing in NULL for a walk state because - * resolved_node is guaranteed to not be a reference to either a method + * the Node is guaranteed to not be a reference to either a method * local or a method argument (because this interface is never called * from a running method.) * * Even though we do not directly invoke the interpreter for object - * resolution, we must lock it because we could access an opregion. - * The opregion access code assumes that the interpreter is locked. + * resolution, we must lock it because we could access an op_region. + * The op_region access code assumes that the interpreter is locked. */ acpi_ex_enter_interpreter(); - /* Function has a strange interface */ + /* TBD: resolve_node_to_value has a strange interface, fix */ + + info->return_object = + ACPI_CAST_PTR(union acpi_operand_object, info->node); status = - acpi_ex_resolve_node_to_value(&info->resolved_node, NULL); + acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR + (struct acpi_namespace_node, + &info->return_object), NULL); acpi_ex_exit_interpreter(); - /* - * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed - * in resolved_node. - */ - if (ACPI_SUCCESS(status)) { - status = AE_CTRL_RETURN_VALUE; - info->return_object = - ACPI_CAST_PTR(union acpi_operand_object, - info->resolved_node); - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Returning object %p [%s]\n", - info->return_object, - acpi_ut_get_object_type_name(info-> - return_object))); + if (ACPI_FAILURE(status)) { + goto cleanup; } + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Returned object %p [%s]\n", + info->return_object, + acpi_ut_get_object_type_name(info-> + return_object))); + + status = AE_CTRL_RETURN_VALUE; /* Always has a "return value" */ + break; } /* - * Check input argument count against the ASL-defined count for a method. - * Also check predefined names: argument count and return value against - * the ACPI specification. Some incorrect return value types are repaired. + * For predefined names, check the return value against the ACPI + * specification. Some incorrect return value types are repaired. */ - (void)acpi_ns_check_predefined_names(node, info->param_count, - status, &info->return_object); + (void)acpi_ns_check_return_value(info->node, info, info->param_count, + status, &info->return_object); /* Check if there is a return value that must be dealt with */ @@ -274,12 +312,15 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "*** Completed evaluation of object %s ***\n", - info->pathname)); + info->relative_pathname)); +cleanup: /* * Namespace was unlocked by the handling acpi_ns* function, so we - * just return + * just free the pathname and return */ + ACPI_FREE(info->full_pathname); + info->full_pathname = NULL; return_ACPI_STATUS(status); } @@ -351,7 +392,7 @@ void acpi_ns_exec_module_code_list(void) * FUNCTION: acpi_ns_exec_module_code * * PARAMETERS: method_obj - Object container for the module-level code - * Info - Info block for method evaluation + * info - Info block for method evaluation * * RETURN: None. Exceptions during method execution are ignored, since * we cannot abort a table load. @@ -445,7 +486,7 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, parent_node->type = (u8)type; } - exit: +exit: if (parent_obj) { acpi_ut_remove_reference(parent_obj); } diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index 9d84ec2f021..a3fb7e4c080 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,7 +46,6 @@ #include "acnamesp.h" #include "acdispat.h" #include "acinterp.h" -#include <linux/nmi.h> #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsinit") @@ -87,7 +86,7 @@ acpi_status acpi_ns_initialize_objects(void) ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "**** Starting initialization of namespace objects ****\n")); ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "Completing Region/Field/Buffer/Package initialization:")); + "Completing Region/Field/Buffer/Package initialization:\n")); /* Set all init info to zero */ @@ -96,14 +95,14 @@ acpi_status acpi_ns_initialize_objects(void) /* Walk entire namespace from the supplied root */ status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, acpi_ns_init_one_object, NULL, - &info, NULL); + ACPI_UINT32_MAX, acpi_ns_init_one_object, + NULL, &info, NULL); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "\nInitialized %u/%u Regions %u/%u Fields %u/%u " + " Initialized %u/%u Regions %u/%u Fields %u/%u " "Buffers %u/%u Packages (%u nodes)\n", info.op_region_init, info.op_region_count, info.field_init, info.field_count, @@ -112,9 +111,8 @@ acpi_status acpi_ns_initialize_objects(void) info.object_count)); ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "%u Control Methods found\n", info.method_count)); - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "%u Op Regions found\n", info.op_region_count)); + "%u Control Methods found\n%u Op Regions found\n", + info.method_count, info.op_region_count)); return_ACPI_STATUS(AE_OK); } @@ -150,7 +148,7 @@ acpi_status acpi_ns_initialize_devices(void) ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "Initializing Device/Processor/Thermal objects " - "by executing _INI methods:")); + "and executing _INI/_STA methods:\n")); /* Tree analysis: find all subtrees that contain _INI methods */ @@ -177,7 +175,7 @@ acpi_status acpi_ns_initialize_devices(void) * part of the ACPI specification. */ info.evaluate_info->prefix_node = acpi_gbl_root_node; - info.evaluate_info->pathname = METHOD_NAME__INI; + info.evaluate_info->relative_pathname = METHOD_NAME__INI; info.evaluate_info->parameters = NULL; info.evaluate_info->flags = ACPI_IGNORE_RETURN_VALUE; @@ -208,13 +206,13 @@ acpi_status acpi_ns_initialize_devices(void) } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "\nExecuted %u _INI methods requiring %u _STA executions " + " Executed %u _INI methods requiring %u _STA executions " "(examined %u objects)\n", info.num_INI, info.num_STA, info.device_count)); return_ACPI_STATUS(status); - error_exit: +error_exit: ACPI_EXCEPTION((AE_INFO, status, "During device initialization")); return_ACPI_STATUS(status); } @@ -224,8 +222,8 @@ acpi_status acpi_ns_initialize_devices(void) * FUNCTION: acpi_ns_init_one_object * * PARAMETERS: obj_handle - Node - * Level - Current nesting level - * Context - Points to a init info struct + * level - Current nesting level + * context - Points to a init info struct * return_value - Not used * * RETURN: Status @@ -267,28 +265,34 @@ acpi_ns_init_one_object(acpi_handle obj_handle, switch (type) { case ACPI_TYPE_REGION: + info->op_region_count++; break; case ACPI_TYPE_BUFFER_FIELD: + info->field_count++; break; case ACPI_TYPE_LOCAL_BANK_FIELD: + info->field_count++; break; case ACPI_TYPE_BUFFER: + info->buffer_count++; break; case ACPI_TYPE_PACKAGE: + info->package_count++; break; default: /* No init required, just exit now */ + return (AE_OK); } @@ -338,7 +342,9 @@ acpi_ns_init_one_object(acpi_handle obj_handle, break; default: + /* No other types can get here */ + break; } @@ -350,14 +356,6 @@ acpi_ns_init_one_object(acpi_handle obj_handle, } /* - * Print a dot for each object unless we are going to print the entire - * pathname - */ - if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); - } - - /* * We ignore errors from above, and always return OK, since we don't want * to abort the walk on any single error. */ @@ -425,6 +423,7 @@ acpi_ns_find_ini_methods(acpi_handle obj_handle, break; default: + break; } @@ -530,7 +529,7 @@ acpi_ns_init_one_device(acpi_handle obj_handle, * we will not run _INI, but we continue to examine the children * of this device. * - * From the ACPI spec, description of _STA: (Note - no mention + * From the ACPI spec, description of _STA: (note - no mention * of whether to run _INI or not on the device in question) * * "_STA may return bit 0 clear (not present) with bit 3 set @@ -567,33 +566,23 @@ acpi_ns_init_one_device(acpi_handle obj_handle, ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, device_node, METHOD_NAME__INI)); + ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info)); info->prefix_node = device_node; - info->pathname = METHOD_NAME__INI; + info->relative_pathname = METHOD_NAME__INI; info->parameters = NULL; info->flags = ACPI_IGNORE_RETURN_VALUE; - /* - * Some hardware relies on this being executed as atomically - * as possible (without an NMI being received in the middle of - * this) - so disable NMIs and initialize the device: - */ status = acpi_ns_evaluate(info); if (ACPI_SUCCESS(status)) { walk_info->num_INI++; - - if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) && - (!(acpi_dbg_level & ACPI_LV_INFO))) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); - } } #ifdef ACPI_DEBUG_OUTPUT else if (status != AE_NOT_FOUND) { /* Ignore error and move on to next device */ - char *scope_name = - acpi_ns_get_external_pathname(info->resolved_node); + char *scope_name = acpi_ns_get_external_pathname(info->node); ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution", scope_name)); diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c index 5cbf15ffe7d..7c9d0181f34 100644 --- a/drivers/acpi/acpica/nsload.c +++ b/drivers/acpi/acpica/nsload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -63,7 +63,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle); * FUNCTION: acpi_ns_load_table * * PARAMETERS: table_index - Index for table to be loaded - * Node - Owning NS node + * node - Owning NS node * * RETURN: Status * @@ -80,8 +80,8 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node) /* * Parse the table and load the namespace with all named - * objects found within. Control methods are NOT parsed - * at this time. In fact, the control methods cannot be + * objects found within. Control methods are NOT parsed + * at this time. In fact, the control methods cannot be * parsed until the entire namespace is loaded, because * if a control method makes a forward reference (call) * to another control method, we can't continue parsing @@ -114,7 +114,7 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node) (void)acpi_tb_release_owner_id(table_index); } - unlock: +unlock: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { @@ -122,18 +122,18 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node) } /* - * Now we can parse the control methods. We always parse + * Now we can parse the control methods. We always parse * them here for a sanity check, and if configured for * just-in-time parsing, we delete the control method * parse trees. */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "**** Begin Table Method Parsing and Object Initialization\n")); + "**** Begin Table Object Initialization\n")); status = acpi_ds_initialize_objects(table_index, node); ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "**** Completed Table Method Parsing and Object Initialization\n")); + "**** Completed Table Object Initialization\n")); return_ACPI_STATUS(status); } @@ -166,7 +166,7 @@ acpi_status acpi_ns_load_namespace(void) } /* - * Load the namespace. The DSDT is required, + * Load the namespace. The DSDT is required, * but the SSDT and PSDT tables are optional. */ status = acpi_ns_load_table_by_type(ACPI_TABLE_ID_DSDT); @@ -278,12 +278,12 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle) * * FUNCTION: acpi_ns_unload_name_space * - * PARAMETERS: Handle - Root of namespace subtree to be deleted + * PARAMETERS: handle - Root of namespace subtree to be deleted * * RETURN: Status * * DESCRIPTION: Shrinks the namespace, typically in response to an undocking - * event. Deletes an entire subtree starting from (and + * event. Deletes an entire subtree starting from (and * including) the given handle. * ******************************************************************************/ diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c index b20e7c8c3ff..7eee0a6f02f 100644 --- a/drivers/acpi/acpica/nsnames.c +++ b/drivers/acpi/acpica/nsnames.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,8 +53,8 @@ ACPI_MODULE_NAME("nsnames") * * FUNCTION: acpi_ns_build_external_path * - * PARAMETERS: Node - NS node whose pathname is needed - * Size - Size of the pathname + * PARAMETERS: node - NS node whose pathname is needed + * size - Size of the pathname * *name_buffer - Where to return the pathname * * RETURN: Status @@ -120,13 +120,14 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node, * * FUNCTION: acpi_ns_get_external_pathname * - * PARAMETERS: Node - Namespace node whose pathname is needed + * PARAMETERS: node - Namespace node whose pathname is needed * * RETURN: Pointer to storage containing the fully qualified name of * the node, In external format (name segments separated by path * separators.) * - * DESCRIPTION: Used for debug printing in acpi_ns_search_table(). + * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually + * for error and debug statements. * ******************************************************************************/ @@ -168,7 +169,7 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) * * FUNCTION: acpi_ns_get_pathname_length * - * PARAMETERS: Node - Namespace node + * PARAMETERS: node - Namespace node * * RETURN: Length of path, including prefix * @@ -195,7 +196,7 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node) ACPI_ERROR((AE_INFO, "Invalid Namespace Node (%p) while traversing namespace", next_node)); - return 0; + return (0); } size += ACPI_PATH_SEGMENT_LENGTH; next_node = next_node->parent; @@ -214,7 +215,7 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node) * * PARAMETERS: target_handle - Handle of named object whose name is * to be found - * Buffer - Where the pathname is returned + * buffer - Where the pathname is returned * * RETURN: Status, Buffer is filled with pathname if status is AE_OK * diff --git a/drivers/acpi/acpica/nsobject.c b/drivers/acpi/acpica/nsobject.c index dd77a3ce6e5..fe54a8c73b8 100644 --- a/drivers/acpi/acpica/nsobject.c +++ b/drivers/acpi/acpica/nsobject.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,15 +53,15 @@ ACPI_MODULE_NAME("nsobject") * * FUNCTION: acpi_ns_attach_object * - * PARAMETERS: Node - Parent Node - * Object - Object to be attached - * Type - Type of object, or ACPI_TYPE_ANY if not + * PARAMETERS: node - Parent Node + * object - Object to be attached + * type - Type of object, or ACPI_TYPE_ANY if not * known * * RETURN: Status * * DESCRIPTION: Record the given object as the value associated with the - * name whose acpi_handle is passed. If Object is NULL + * name whose acpi_handle is passed. If Object is NULL * and Type is ACPI_TYPE_ANY, set the name as having no value. * Note: Future may require that the Node->Flags field be passed * as a parameter. @@ -133,7 +133,7 @@ acpi_ns_attach_object(struct acpi_namespace_node *node, ((struct acpi_namespace_node *)object)->object) { /* * Value passed is a name handle and that name has a - * non-null value. Use that name's value and type. + * non-null value. Use that name's value and type. */ obj_desc = ((struct acpi_namespace_node *)object)->object; object_type = ((struct acpi_namespace_node *)object)->type; @@ -191,7 +191,7 @@ acpi_ns_attach_object(struct acpi_namespace_node *node, * * FUNCTION: acpi_ns_detach_object * - * PARAMETERS: Node - A Namespace node whose object will be detached + * PARAMETERS: node - A Namespace node whose object will be detached * * RETURN: None. * @@ -222,13 +222,19 @@ void acpi_ns_detach_object(struct acpi_namespace_node *node) } } - /* Clear the entry in all cases */ + /* Clear the Node entry in all cases */ node->object = NULL; if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) { + + /* Unlink object from front of possible object list */ + node->object = obj_desc->common.next_object; + + /* Handle possible 2-descriptor object */ + if (node->object && - ((node->object)->common.type != ACPI_TYPE_LOCAL_DATA)) { + (node->object->common.type != ACPI_TYPE_LOCAL_DATA)) { node->object = node->object->common.next_object; } } @@ -250,7 +256,7 @@ void acpi_ns_detach_object(struct acpi_namespace_node *node) * * FUNCTION: acpi_ns_get_attached_object * - * PARAMETERS: Node - Namespace node + * PARAMETERS: node - Namespace node * * RETURN: Current value of the object field from the Node whose * handle is passed @@ -285,7 +291,7 @@ union acpi_operand_object *acpi_ns_get_attached_object(struct * * FUNCTION: acpi_ns_get_secondary_object * - * PARAMETERS: Node - Namespace node + * PARAMETERS: node - Namespace node * * RETURN: Current value of the object field from the Node whose * handle is passed. @@ -315,13 +321,13 @@ union acpi_operand_object *acpi_ns_get_secondary_object(union * * FUNCTION: acpi_ns_attach_data * - * PARAMETERS: Node - Namespace node - * Handler - Handler to be associated with the data - * Data - Data to be attached + * PARAMETERS: node - Namespace node + * handler - Handler to be associated with the data + * data - Data to be attached * * RETURN: Status * - * DESCRIPTION: Low-level attach data. Create and attach a Data object. + * DESCRIPTION: Low-level attach data. Create and attach a Data object. * ******************************************************************************/ @@ -372,12 +378,12 @@ acpi_ns_attach_data(struct acpi_namespace_node *node, * * FUNCTION: acpi_ns_detach_data * - * PARAMETERS: Node - Namespace node - * Handler - Handler associated with the data + * PARAMETERS: node - Namespace node + * handler - Handler associated with the data * * RETURN: Status * - * DESCRIPTION: Low-level detach data. Delete the data node, but the caller + * DESCRIPTION: Low-level detach data. Delete the data node, but the caller * is responsible for the actual data. * ******************************************************************************/ @@ -416,9 +422,9 @@ acpi_ns_detach_data(struct acpi_namespace_node * node, * * FUNCTION: acpi_ns_get_attached_data * - * PARAMETERS: Node - Namespace node - * Handler - Handler associated with the data - * Data - Where the data is returned + * PARAMETERS: node - Namespace node + * handler - Handler associated with the data + * data - Where the data is returned * * RETURN: Status * diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c index ec7ba2d3463..e83cff31754 100644 --- a/drivers/acpi/acpica/nsparse.c +++ b/drivers/acpi/acpica/nsparse.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -140,7 +140,7 @@ acpi_ns_one_complete_parse(u32 pass_number, pass_number)); status = acpi_ps_parse_aml(walk_state); - cleanup: +cleanup: acpi_ps_delete_parse_tree(parse_root); return_ACPI_STATUS(status); } @@ -168,11 +168,11 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node) /* * AML Parse, pass 1 * - * In this pass, we load most of the namespace. Control methods - * are not parsed until later. A parse tree is not created. Instead, - * each Parser Op subtree is deleted when it is finished. This saves + * In this pass, we load most of the namespace. Control methods + * are not parsed until later. A parse tree is not created. Instead, + * each Parser Op subtree is deleted when it is finished. This saves * a great deal of memory, and allows a small cache of parse objects - * to service the entire parse. The second pass of the parse then + * to service the entire parse. The second pass of the parse then * performs another complete parse of the AML. */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n")); diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index bbe46a447d3..392910ffbed 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -1,12 +1,11 @@ /****************************************************************************** * * Module Name: nspredef - Validation of ACPI predefined methods and objects - * $Revision: 1.1 $ * *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -62,61 +61,29 @@ ACPI_MODULE_NAME("nspredef") * There are several areas that are validated: * * 1) The number of input arguments as defined by the method/object in the - * ASL is validated against the ACPI specification. + * ASL is validated against the ACPI specification. * 2) The type of the return object (if any) is validated against the ACPI - * specification. + * specification. * 3) For returned package objects, the count of package elements is - * validated, as well as the type of each package element. Nested - * packages are supported. + * validated, as well as the type of each package element. Nested + * packages are supported. * * For any problems found, a warning message is issued. * ******************************************************************************/ /* Local prototypes */ static acpi_status -acpi_ns_check_package(struct acpi_predefined_data *data, - union acpi_operand_object **return_object_ptr); - -static acpi_status -acpi_ns_check_package_list(struct acpi_predefined_data *data, - const union acpi_predefined_info *package, - union acpi_operand_object **elements, u32 count); - -static acpi_status -acpi_ns_check_package_elements(struct acpi_predefined_data *data, - union acpi_operand_object **elements, - u8 type1, - u32 count1, - u8 type2, u32 count2, u32 start_index); - -static acpi_status -acpi_ns_check_object_type(struct acpi_predefined_data *data, - union acpi_operand_object **return_object_ptr, - u32 expected_btypes, u32 package_index); - -static acpi_status -acpi_ns_check_reference(struct acpi_predefined_data *data, +acpi_ns_check_reference(struct acpi_evaluate_info *info, union acpi_operand_object *return_object); -static void acpi_ns_get_expected_types(char *buffer, u32 expected_btypes); - -/* - * Names for the types that can be returned by the predefined objects. - * Used for warning messages. Must be in the same order as the ACPI_RTYPEs - */ -static const char *acpi_rtype_names[] = { - "/Integer", - "/String", - "/Buffer", - "/Package", - "/Reference", -}; +static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object); /******************************************************************************* * - * FUNCTION: acpi_ns_check_predefined_names + * FUNCTION: acpi_ns_check_return_value * - * PARAMETERS: Node - Namespace node for the method/object + * PARAMETERS: node - Namespace node for the method/object + * info - Method execution information block * user_param_count - Number of parameters actually passed * return_status - Status from the object evaluation * return_object_ptr - Pointer to the object returned from the @@ -124,45 +91,25 @@ static const char *acpi_rtype_names[] = { * * RETURN: Status * - * DESCRIPTION: Check an ACPI name for a match in the predefined name list. + * DESCRIPTION: Check the value returned from a predefined name. * ******************************************************************************/ acpi_status -acpi_ns_check_predefined_names(struct acpi_namespace_node *node, - u32 user_param_count, - acpi_status return_status, - union acpi_operand_object **return_object_ptr) +acpi_ns_check_return_value(struct acpi_namespace_node *node, + struct acpi_evaluate_info *info, + u32 user_param_count, + acpi_status return_status, + union acpi_operand_object **return_object_ptr) { - union acpi_operand_object *return_object = *return_object_ptr; - acpi_status status = AE_OK; + acpi_status status; const union acpi_predefined_info *predefined; - char *pathname; - struct acpi_predefined_data *data; - - /* Match the name for this method/object against the predefined list */ - - predefined = acpi_ns_check_for_predefined_name(node); - - /* Get the full pathname to the object, for use in warning messages */ - - pathname = acpi_ns_get_external_pathname(node); - if (!pathname) { - return AE_OK; /* Could not get pathname, ignore */ - } - - /* - * Check that the parameter count for this method matches the ASL - * definition. For predefined names, ensure that both the caller and - * the method itself are in accordance with the ACPI specification. - */ - acpi_ns_check_parameter_count(pathname, node, user_param_count, - predefined); /* If not a predefined name, we cannot validate the return object */ + predefined = info->predefined; if (!predefined) { - goto cleanup; + return (AE_OK); } /* @@ -170,26 +117,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, * validate the return object */ if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) { - goto cleanup; - } - - /* - * If there is no return value, check if we require a return value for - * this predefined name. Either one return value is expected, or none, - * for both methods and other objects. - * - * Exit now if there is no return object. Warning if one was expected. - */ - if (!return_object) { - if ((predefined->info.expected_btypes) && - (!(predefined->info.expected_btypes & ACPI_RTYPE_NONE))) { - ACPI_WARN_PREDEFINED((AE_INFO, pathname, - ACPI_WARN_ALWAYS, - "Missing expected return value")); - - status = AE_AML_NO_RETURN_VALUE; - } - goto cleanup; + return (AE_OK); } /* @@ -208,25 +136,14 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, if (acpi_gbl_disable_auto_repair || (!predefined->info.expected_btypes) || (predefined->info.expected_btypes == ACPI_RTYPE_ALL)) { - goto cleanup; - } - - /* Create the parameter data block for object validation */ - - data = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_predefined_data)); - if (!data) { - goto cleanup; + return (AE_OK); } - data->predefined = predefined; - data->node = node; - data->node_flags = node->flags; - data->pathname = pathname; /* * Check that the type of the main return object is what is expected * for this predefined name */ - status = acpi_ns_check_object_type(data, return_object_ptr, + status = acpi_ns_check_object_type(info, return_object_ptr, predefined->info.expected_btypes, ACPI_NOT_PACKAGE_ELEMENT); if (ACPI_FAILURE(status)) { @@ -234,14 +151,29 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, } /* + * + * 4) If there is no return value and it is optional, just return + * AE_OK (_WAK). + */ + if (!(*return_object_ptr)) { + goto exit; + } + + /* * For returned Package objects, check the type of all sub-objects. * Note: Package may have been newly created by call above. */ if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) { - data->parent_package = *return_object_ptr; - status = acpi_ns_check_package(data, return_object_ptr); + info->parent_package = *return_object_ptr; + status = acpi_ns_check_package(info, return_object_ptr); if (ACPI_FAILURE(status)) { - goto exit; + + /* We might be able to fix some errors */ + + if ((status != AE_AML_OPERAND_TYPE) && + (status != AE_AML_OPERAND_VALUE)) { + goto exit; + } } } @@ -253,7 +185,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, * performed on a per-name basis, i.e., the code is specific to * particular predefined names. */ - status = acpi_ns_complex_repairs(data, node, status, return_object_ptr); + status = acpi_ns_complex_repairs(info, node, status, return_object_ptr); exit: /* @@ -261,714 +193,18 @@ exit: * or more objects, mark the parent node to suppress further warning * messages during the next evaluation of the same method/object. */ - if (ACPI_FAILURE(status) || (data->flags & ACPI_OBJECT_REPAIRED)) { + if (ACPI_FAILURE(status) || (info->return_flags & ACPI_OBJECT_REPAIRED)) { node->flags |= ANOBJ_EVALUATED; } - ACPI_FREE(data); -cleanup: - ACPI_FREE(pathname); return (status); } /******************************************************************************* * - * FUNCTION: acpi_ns_check_parameter_count - * - * PARAMETERS: Pathname - Full pathname to the node (for error msgs) - * Node - Namespace node for the method/object - * user_param_count - Number of args passed in by the caller - * Predefined - Pointer to entry in predefined name table - * - * RETURN: None - * - * DESCRIPTION: Check that the declared (in ASL/AML) parameter count for a - * predefined name is what is expected (i.e., what is defined in - * the ACPI specification for this predefined name.) - * - ******************************************************************************/ - -void -acpi_ns_check_parameter_count(char *pathname, - struct acpi_namespace_node *node, - u32 user_param_count, - const union acpi_predefined_info *predefined) -{ - u32 param_count; - u32 required_params_current; - u32 required_params_old; - - /* Methods have 0-7 parameters. All other types have zero. */ - - param_count = 0; - if (node->type == ACPI_TYPE_METHOD) { - param_count = node->object->method.param_count; - } - - if (!predefined) { - /* - * Check the parameter count for non-predefined methods/objects. - * - * Warning if too few or too many arguments have been passed by the - * caller. An incorrect number of arguments may not cause the method - * to fail. However, the method will fail if there are too few - * arguments and the method attempts to use one of the missing ones. - */ - if (user_param_count < param_count) { - ACPI_WARN_PREDEFINED((AE_INFO, pathname, - ACPI_WARN_ALWAYS, - "Insufficient arguments - needs %u, found %u", - param_count, user_param_count)); - } else if (user_param_count > param_count) { - ACPI_WARN_PREDEFINED((AE_INFO, pathname, - ACPI_WARN_ALWAYS, - "Excess arguments - needs %u, found %u", - param_count, user_param_count)); - } - return; - } - - /* - * Validate the user-supplied parameter count. - * Allow two different legal argument counts (_SCP, etc.) - */ - required_params_current = predefined->info.param_count & 0x0F; - required_params_old = predefined->info.param_count >> 4; - - if (user_param_count != ACPI_UINT32_MAX) { - if ((user_param_count != required_params_current) && - (user_param_count != required_params_old)) { - ACPI_WARN_PREDEFINED((AE_INFO, pathname, - ACPI_WARN_ALWAYS, - "Parameter count mismatch - " - "caller passed %u, ACPI requires %u", - user_param_count, - required_params_current)); - } - } - - /* - * Check that the ASL-defined parameter count is what is expected for - * this predefined name (parameter count as defined by the ACPI - * specification) - */ - if ((param_count != required_params_current) && - (param_count != required_params_old)) { - ACPI_WARN_PREDEFINED((AE_INFO, pathname, node->flags, - "Parameter count mismatch - ASL declared %u, ACPI requires %u", - param_count, required_params_current)); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_check_for_predefined_name - * - * PARAMETERS: Node - Namespace node for the method/object - * - * RETURN: Pointer to entry in predefined table. NULL indicates not found. - * - * DESCRIPTION: Check an object name against the predefined object list. - * - ******************************************************************************/ - -const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct - acpi_namespace_node - *node) -{ - const union acpi_predefined_info *this_name; - - /* Quick check for a predefined name, first character must be underscore */ - - if (node->name.ascii[0] != '_') { - return (NULL); - } - - /* Search info table for a predefined method/object name */ - - this_name = predefined_names; - while (this_name->info.name[0]) { - if (ACPI_COMPARE_NAME(node->name.ascii, this_name->info.name)) { - return (this_name); - } - - /* - * Skip next entry in the table if this name returns a Package - * (next entry contains the package info) - */ - if (this_name->info.expected_btypes & ACPI_RTYPE_PACKAGE) { - this_name++; - } - - this_name++; - } - - return (NULL); /* Not found */ -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_check_package - * - * PARAMETERS: Data - Pointer to validation data structure - * return_object_ptr - Pointer to the object returned from the - * evaluation of a method or object - * - * RETURN: Status - * - * DESCRIPTION: Check a returned package object for the correct count and - * correct type of all sub-objects. - * - ******************************************************************************/ - -static acpi_status -acpi_ns_check_package(struct acpi_predefined_data *data, - union acpi_operand_object **return_object_ptr) -{ - union acpi_operand_object *return_object = *return_object_ptr; - const union acpi_predefined_info *package; - union acpi_operand_object **elements; - acpi_status status = AE_OK; - u32 expected_count; - u32 count; - u32 i; - - ACPI_FUNCTION_NAME(ns_check_package); - - /* The package info for this name is in the next table entry */ - - package = data->predefined + 1; - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "%s Validating return Package of Type %X, Count %X\n", - data->pathname, package->ret_info.type, - return_object->package.count)); - - /* - * For variable-length Packages, we can safely remove all embedded - * and trailing NULL package elements - */ - acpi_ns_remove_null_elements(data, package->ret_info.type, - return_object); - - /* Extract package count and elements array */ - - elements = return_object->package.elements; - count = return_object->package.count; - - /* The package must have at least one element, else invalid */ - - if (!count) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Return Package has no elements (empty)")); - - return (AE_AML_OPERAND_VALUE); - } - - /* - * Decode the type of the expected package contents - * - * PTYPE1 packages contain no subpackages - * PTYPE2 packages contain sub-packages - */ - switch (package->ret_info.type) { - case ACPI_PTYPE1_FIXED: - - /* - * The package count is fixed and there are no sub-packages - * - * If package is too small, exit. - * If package is larger than expected, issue warning but continue - */ - expected_count = - package->ret_info.count1 + package->ret_info.count2; - if (count < expected_count) { - goto package_too_small; - } else if (count > expected_count) { - ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, - "%s: Return Package is larger than needed - " - "found %u, expected %u\n", - data->pathname, count, - expected_count)); - } - - /* Validate all elements of the returned package */ - - status = acpi_ns_check_package_elements(data, elements, - package->ret_info. - object_type1, - package->ret_info. - count1, - package->ret_info. - object_type2, - package->ret_info. - count2, 0); - break; - - case ACPI_PTYPE1_VAR: - - /* - * The package count is variable, there are no sub-packages, and all - * elements must be of the same type - */ - for (i = 0; i < count; i++) { - status = acpi_ns_check_object_type(data, elements, - package->ret_info. - object_type1, i); - if (ACPI_FAILURE(status)) { - return (status); - } - elements++; - } - break; - - case ACPI_PTYPE1_OPTION: - - /* - * The package count is variable, there are no sub-packages. There are - * a fixed number of required elements, and a variable number of - * optional elements. - * - * Check if package is at least as large as the minimum required - */ - expected_count = package->ret_info3.count; - if (count < expected_count) { - goto package_too_small; - } - - /* Variable number of sub-objects */ - - for (i = 0; i < count; i++) { - if (i < package->ret_info3.count) { - - /* These are the required package elements (0, 1, or 2) */ - - status = - acpi_ns_check_object_type(data, elements, - package-> - ret_info3. - object_type[i], - i); - if (ACPI_FAILURE(status)) { - return (status); - } - } else { - /* These are the optional package elements */ - - status = - acpi_ns_check_object_type(data, elements, - package-> - ret_info3. - tail_object_type, - i); - if (ACPI_FAILURE(status)) { - return (status); - } - } - elements++; - } - break; - - case ACPI_PTYPE2_REV_FIXED: - - /* First element is the (Integer) revision */ - - status = acpi_ns_check_object_type(data, elements, - ACPI_RTYPE_INTEGER, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - - elements++; - count--; - - /* Examine the sub-packages */ - - status = - acpi_ns_check_package_list(data, package, elements, count); - break; - - case ACPI_PTYPE2_PKG_COUNT: - - /* First element is the (Integer) count of sub-packages to follow */ - - status = acpi_ns_check_object_type(data, elements, - ACPI_RTYPE_INTEGER, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* - * Count cannot be larger than the parent package length, but allow it - * to be smaller. The >= accounts for the Integer above. - */ - expected_count = (u32) (*elements)->integer.value; - if (expected_count >= count) { - goto package_too_small; - } - - count = expected_count; - elements++; - - /* Examine the sub-packages */ - - status = - acpi_ns_check_package_list(data, package, elements, count); - break; - - case ACPI_PTYPE2: - case ACPI_PTYPE2_FIXED: - case ACPI_PTYPE2_MIN: - case ACPI_PTYPE2_COUNT: - case ACPI_PTYPE2_FIX_VAR: - - /* - * These types all return a single Package that consists of a - * variable number of sub-Packages. - * - * First, ensure that the first element is a sub-Package. If not, - * the BIOS may have incorrectly returned the object as a single - * package instead of a Package of Packages (a common error if - * there is only one entry). We may be able to repair this by - * wrapping the returned Package with a new outer Package. - */ - if (*elements - && ((*elements)->common.type != ACPI_TYPE_PACKAGE)) { - - /* Create the new outer package and populate it */ - - status = - acpi_ns_repair_package_list(data, - return_object_ptr); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* Update locals to point to the new package (of 1 element) */ - - return_object = *return_object_ptr; - elements = return_object->package.elements; - count = 1; - } - - /* Examine the sub-packages */ - - status = - acpi_ns_check_package_list(data, package, elements, count); - break; - - default: - - /* Should not get here if predefined info table is correct */ - - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Invalid internal return type in table entry: %X", - package->ret_info.type)); - - return (AE_AML_INTERNAL); - } - - return (status); - -package_too_small: - - /* Error exit for the case with an incorrect package count */ - - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Return Package is too small - found %u elements, expected %u", - count, expected_count)); - - return (AE_AML_OPERAND_VALUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_check_package_list - * - * PARAMETERS: Data - Pointer to validation data structure - * Package - Pointer to package-specific info for method - * Elements - Element list of parent package. All elements - * of this list should be of type Package. - * Count - Count of subpackages - * - * RETURN: Status - * - * DESCRIPTION: Examine a list of subpackages - * - ******************************************************************************/ - -static acpi_status -acpi_ns_check_package_list(struct acpi_predefined_data *data, - const union acpi_predefined_info *package, - union acpi_operand_object **elements, u32 count) -{ - union acpi_operand_object *sub_package; - union acpi_operand_object **sub_elements; - acpi_status status; - u32 expected_count; - u32 i; - u32 j; - - /* - * Validate each sub-Package in the parent Package - * - * NOTE: assumes list of sub-packages contains no NULL elements. - * Any NULL elements should have been removed by earlier call - * to acpi_ns_remove_null_elements. - */ - for (i = 0; i < count; i++) { - sub_package = *elements; - sub_elements = sub_package->package.elements; - data->parent_package = sub_package; - - /* Each sub-object must be of type Package */ - - status = acpi_ns_check_object_type(data, &sub_package, - ACPI_RTYPE_PACKAGE, i); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* Examine the different types of expected sub-packages */ - - data->parent_package = sub_package; - switch (package->ret_info.type) { - case ACPI_PTYPE2: - case ACPI_PTYPE2_PKG_COUNT: - case ACPI_PTYPE2_REV_FIXED: - - /* Each subpackage has a fixed number of elements */ - - expected_count = - package->ret_info.count1 + package->ret_info.count2; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } - - status = - acpi_ns_check_package_elements(data, sub_elements, - package->ret_info. - object_type1, - package->ret_info. - count1, - package->ret_info. - object_type2, - package->ret_info. - count2, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - case ACPI_PTYPE2_FIX_VAR: - /* - * Each subpackage has a fixed number of elements and an - * optional element - */ - expected_count = - package->ret_info.count1 + package->ret_info.count2; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } - - status = - acpi_ns_check_package_elements(data, sub_elements, - package->ret_info. - object_type1, - package->ret_info. - count1, - package->ret_info. - object_type2, - sub_package->package. - count - - package->ret_info. - count1, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - case ACPI_PTYPE2_FIXED: - - /* Each sub-package has a fixed length */ - - expected_count = package->ret_info2.count; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } - - /* Check the type of each sub-package element */ - - for (j = 0; j < expected_count; j++) { - status = - acpi_ns_check_object_type(data, - &sub_elements[j], - package-> - ret_info2. - object_type[j], - j); - if (ACPI_FAILURE(status)) { - return (status); - } - } - break; - - case ACPI_PTYPE2_MIN: - - /* Each sub-package has a variable but minimum length */ - - expected_count = package->ret_info.count1; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } - - /* Check the type of each sub-package element */ - - status = - acpi_ns_check_package_elements(data, sub_elements, - package->ret_info. - object_type1, - sub_package->package. - count, 0, 0, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - case ACPI_PTYPE2_COUNT: - - /* - * First element is the (Integer) count of elements, including - * the count field (the ACPI name is num_elements) - */ - status = acpi_ns_check_object_type(data, sub_elements, - ACPI_RTYPE_INTEGER, - 0); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* - * Make sure package is large enough for the Count and is - * is as large as the minimum size - */ - expected_count = (u32)(*sub_elements)->integer.value; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } - if (sub_package->package.count < - package->ret_info.count1) { - expected_count = package->ret_info.count1; - goto package_too_small; - } - if (expected_count == 0) { - /* - * Either the num_entries element was originally zero or it was - * a NULL element and repaired to an Integer of value zero. - * In either case, repair it by setting num_entries to be the - * actual size of the subpackage. - */ - expected_count = sub_package->package.count; - (*sub_elements)->integer.value = expected_count; - } - - /* Check the type of each sub-package element */ - - status = - acpi_ns_check_package_elements(data, - (sub_elements + 1), - package->ret_info. - object_type1, - (expected_count - 1), - 0, 0, 1); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - default: /* Should not get here, type was validated by caller */ - - return (AE_AML_INTERNAL); - } - - elements++; - } - - return (AE_OK); - -package_too_small: - - /* The sub-package count was smaller than required */ - - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Return Sub-Package[%u] is too small - found %u elements, expected %u", - i, sub_package->package.count, expected_count)); - - return (AE_AML_OPERAND_VALUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_check_package_elements - * - * PARAMETERS: Data - Pointer to validation data structure - * Elements - Pointer to the package elements array - * Type1 - Object type for first group - * Count1 - Count for first group - * Type2 - Object type for second group - * Count2 - Count for second group - * start_index - Start of the first group of elements - * - * RETURN: Status - * - * DESCRIPTION: Check that all elements of a package are of the correct object - * type. Supports up to two groups of different object types. - * - ******************************************************************************/ - -static acpi_status -acpi_ns_check_package_elements(struct acpi_predefined_data *data, - union acpi_operand_object **elements, - u8 type1, - u32 count1, - u8 type2, u32 count2, u32 start_index) -{ - union acpi_operand_object **this_element = elements; - acpi_status status; - u32 i; - - /* - * Up to two groups of package elements are supported by the data - * structure. All elements in each group must be of the same type. - * The second group can have a count of zero. - */ - for (i = 0; i < count1; i++) { - status = acpi_ns_check_object_type(data, this_element, - type1, i + start_index); - if (ACPI_FAILURE(status)) { - return (status); - } - this_element++; - } - - for (i = 0; i < count2; i++) { - status = acpi_ns_check_object_type(data, this_element, - type2, - (i + count1 + start_index)); - if (ACPI_FAILURE(status)) { - return (status); - } - this_element++; - } - - return (AE_OK); -} - -/******************************************************************************* - * * FUNCTION: acpi_ns_check_object_type * - * PARAMETERS: Data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * expected_btypes - Bitmap of expected return type(s) @@ -983,36 +219,21 @@ acpi_ns_check_package_elements(struct acpi_predefined_data *data, * ******************************************************************************/ -static acpi_status -acpi_ns_check_object_type(struct acpi_predefined_data *data, +acpi_status +acpi_ns_check_object_type(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr, u32 expected_btypes, u32 package_index) { union acpi_operand_object *return_object = *return_object_ptr; acpi_status status = AE_OK; - u32 return_btype; char type_buffer[48]; /* Room for 5 types */ - /* - * If we get a NULL return_object here, it is a NULL package element. - * Since all extraneous NULL package elements were removed earlier by a - * call to acpi_ns_remove_null_elements, this is an unexpected NULL element. - * We will attempt to repair it. - */ - if (!return_object) { - status = acpi_ns_repair_null_element(data, expected_btypes, - package_index, - return_object_ptr); - if (ACPI_SUCCESS(status)) { - return (AE_OK); /* Repair was successful */ - } - goto type_error_exit; - } - /* A Namespace node should not get here, but make sure */ - if (ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + if (return_object && + ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) { + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, "Invalid return type - Found a Namespace node [%4.4s] type %s", return_object->node.name.ascii, acpi_ut_get_type_name(return_object->node. @@ -1028,67 +249,48 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, * from all of the predefined names (including elements of returned * packages) */ - switch (return_object->common.type) { - case ACPI_TYPE_INTEGER: - return_btype = ACPI_RTYPE_INTEGER; - break; - - case ACPI_TYPE_BUFFER: - return_btype = ACPI_RTYPE_BUFFER; - break; + info->return_btype = acpi_ns_get_bitmapped_type(return_object); + if (info->return_btype == ACPI_RTYPE_ANY) { - case ACPI_TYPE_STRING: - return_btype = ACPI_RTYPE_STRING; - break; - - case ACPI_TYPE_PACKAGE: - return_btype = ACPI_RTYPE_PACKAGE; - break; - - case ACPI_TYPE_LOCAL_REFERENCE: - return_btype = ACPI_RTYPE_REFERENCE; - break; - - default: /* Not one of the supported objects, must be incorrect */ - goto type_error_exit; } - /* Is the object one of the expected types? */ - - if (return_btype & expected_btypes) { - - /* For reference objects, check that the reference type is correct */ - - if (return_object->common.type == ACPI_TYPE_LOCAL_REFERENCE) { - status = acpi_ns_check_reference(data, return_object); - } + /* For reference objects, check that the reference type is correct */ + if ((info->return_btype & expected_btypes) == ACPI_RTYPE_REFERENCE) { + status = acpi_ns_check_reference(info, return_object); return (status); } - /* Type mismatch -- attempt repair of the returned object */ + /* Attempt simple repair of the returned object if necessary */ - status = acpi_ns_repair_object(data, expected_btypes, + status = acpi_ns_simple_repair(info, expected_btypes, package_index, return_object_ptr); if (ACPI_SUCCESS(status)) { - return (AE_OK); /* Repair was successful */ + return (AE_OK); /* Successful repair */ } - type_error_exit: +type_error_exit: /* Create a string with all expected types for this predefined object */ - acpi_ns_get_expected_types(type_buffer, expected_btypes); + acpi_ut_get_expected_return_types(type_buffer, expected_btypes); - if (package_index == ACPI_NOT_PACKAGE_ELEMENT) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + if (!return_object) { + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, + "Expected return object of type %s", + type_buffer)); + } else if (package_index == ACPI_NOT_PACKAGE_ELEMENT) { + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, "Return type mismatch - found %s, expected %s", acpi_ut_get_object_type_name (return_object), type_buffer)); } else { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, "Return Package type mismatch at index %u - " "found %s, expected %s", package_index, acpi_ut_get_object_type_name @@ -1102,7 +304,7 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_check_reference * - * PARAMETERS: Data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object - Object returned from the evaluation of a * method or object * @@ -1115,7 +317,7 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, ******************************************************************************/ static acpi_status -acpi_ns_check_reference(struct acpi_predefined_data *data, +acpi_ns_check_reference(struct acpi_evaluate_info *info, union acpi_operand_object *return_object) { @@ -1128,7 +330,7 @@ acpi_ns_check_reference(struct acpi_predefined_data *data, return (AE_OK); } - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, "Return type mismatch - unexpected reference object type [%s] %2.2X", acpi_ut_get_reference_name(return_object), return_object->reference.class)); @@ -1138,36 +340,61 @@ acpi_ns_check_reference(struct acpi_predefined_data *data, /******************************************************************************* * - * FUNCTION: acpi_ns_get_expected_types + * FUNCTION: acpi_ns_get_bitmapped_type * - * PARAMETERS: Buffer - Pointer to where the string is returned - * expected_btypes - Bitmap of expected return type(s) + * PARAMETERS: return_object - Object returned from method/obj evaluation * - * RETURN: Buffer is populated with type names. + * RETURN: Object return type. ACPI_RTYPE_ANY indicates that the object + * type is not supported. ACPI_RTYPE_NONE indicates that no + * object was returned (return_object is NULL). * - * DESCRIPTION: Translate the expected types bitmap into a string of ascii - * names of expected types, for use in warning messages. + * DESCRIPTION: Convert object type into a bitmapped object return type. * ******************************************************************************/ -static void acpi_ns_get_expected_types(char *buffer, u32 expected_btypes) +static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object) { - u32 this_rtype; - u32 i; - u32 j; + u32 return_btype; + + if (!return_object) { + return (ACPI_RTYPE_NONE); + } - j = 1; - buffer[0] = 0; - this_rtype = ACPI_RTYPE_INTEGER; + /* Map acpi_object_type to internal bitmapped type */ - for (i = 0; i < ACPI_NUM_RTYPES; i++) { + switch (return_object->common.type) { + case ACPI_TYPE_INTEGER: - /* If one of the expected types, concatenate the name of this type */ + return_btype = ACPI_RTYPE_INTEGER; + break; - if (expected_btypes & this_rtype) { - ACPI_STRCAT(buffer, &acpi_rtype_names[i][j]); - j = 0; /* Use name separator from now on */ - } - this_rtype <<= 1; /* Next Rtype */ + case ACPI_TYPE_BUFFER: + + return_btype = ACPI_RTYPE_BUFFER; + break; + + case ACPI_TYPE_STRING: + + return_btype = ACPI_RTYPE_STRING; + break; + + case ACPI_TYPE_PACKAGE: + + return_btype = ACPI_RTYPE_PACKAGE; + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + + return_btype = ACPI_RTYPE_REFERENCE; + break; + + default: + + /* Not one of the supported objects, must be incorrect */ + + return_btype = ACPI_RTYPE_ANY; + break; } + + return (return_btype); } diff --git a/drivers/acpi/acpica/nsprepkg.c b/drivers/acpi/acpica/nsprepkg.c new file mode 100644 index 00000000000..68f725839eb --- /dev/null +++ b/drivers/acpi/acpica/nsprepkg.c @@ -0,0 +1,624 @@ +/****************************************************************************** + * + * Module Name: nsprepkg - Validation of package objects for predefined names + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acnamesp.h" +#include "acpredef.h" + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsprepkg") + +/* Local prototypes */ +static acpi_status +acpi_ns_check_package_list(struct acpi_evaluate_info *info, + const union acpi_predefined_info *package, + union acpi_operand_object **elements, u32 count); + +static acpi_status +acpi_ns_check_package_elements(struct acpi_evaluate_info *info, + union acpi_operand_object **elements, + u8 type1, + u32 count1, + u8 type2, u32 count2, u32 start_index); + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_package + * + * PARAMETERS: info - Method execution information block + * return_object_ptr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status + * + * DESCRIPTION: Check a returned package object for the correct count and + * correct type of all sub-objects. + * + ******************************************************************************/ + +acpi_status +acpi_ns_check_package(struct acpi_evaluate_info *info, + union acpi_operand_object **return_object_ptr) +{ + union acpi_operand_object *return_object = *return_object_ptr; + const union acpi_predefined_info *package; + union acpi_operand_object **elements; + acpi_status status = AE_OK; + u32 expected_count; + u32 count; + u32 i; + + ACPI_FUNCTION_NAME(ns_check_package); + + /* The package info for this name is in the next table entry */ + + package = info->predefined + 1; + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "%s Validating return Package of Type %X, Count %X\n", + info->full_pathname, package->ret_info.type, + return_object->package.count)); + + /* + * For variable-length Packages, we can safely remove all embedded + * and trailing NULL package elements + */ + acpi_ns_remove_null_elements(info, package->ret_info.type, + return_object); + + /* Extract package count and elements array */ + + elements = return_object->package.elements; + count = return_object->package.count; + + /* + * Most packages must have at least one element. The only exception + * is the variable-length package (ACPI_PTYPE1_VAR). + */ + if (!count) { + if (package->ret_info.type == ACPI_PTYPE1_VAR) { + return (AE_OK); + } + + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, + "Return Package has no elements (empty)")); + + return (AE_AML_OPERAND_VALUE); + } + + /* + * Decode the type of the expected package contents + * + * PTYPE1 packages contain no subpackages + * PTYPE2 packages contain subpackages + */ + switch (package->ret_info.type) { + case ACPI_PTYPE1_FIXED: + /* + * The package count is fixed and there are no subpackages + * + * If package is too small, exit. + * If package is larger than expected, issue warning but continue + */ + expected_count = + package->ret_info.count1 + package->ret_info.count2; + if (count < expected_count) { + goto package_too_small; + } else if (count > expected_count) { + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, + "%s: Return Package is larger than needed - " + "found %u, expected %u\n", + info->full_pathname, count, + expected_count)); + } + + /* Validate all elements of the returned package */ + + status = acpi_ns_check_package_elements(info, elements, + package->ret_info. + object_type1, + package->ret_info. + count1, + package->ret_info. + object_type2, + package->ret_info. + count2, 0); + break; + + case ACPI_PTYPE1_VAR: + /* + * The package count is variable, there are no subpackages, and all + * elements must be of the same type + */ + for (i = 0; i < count; i++) { + status = acpi_ns_check_object_type(info, elements, + package->ret_info. + object_type1, i); + if (ACPI_FAILURE(status)) { + return (status); + } + elements++; + } + break; + + case ACPI_PTYPE1_OPTION: + /* + * The package count is variable, there are no subpackages. There are + * a fixed number of required elements, and a variable number of + * optional elements. + * + * Check if package is at least as large as the minimum required + */ + expected_count = package->ret_info3.count; + if (count < expected_count) { + goto package_too_small; + } + + /* Variable number of sub-objects */ + + for (i = 0; i < count; i++) { + if (i < package->ret_info3.count) { + + /* These are the required package elements (0, 1, or 2) */ + + status = + acpi_ns_check_object_type(info, elements, + package-> + ret_info3. + object_type[i], + i); + if (ACPI_FAILURE(status)) { + return (status); + } + } else { + /* These are the optional package elements */ + + status = + acpi_ns_check_object_type(info, elements, + package-> + ret_info3. + tail_object_type, + i); + if (ACPI_FAILURE(status)) { + return (status); + } + } + elements++; + } + break; + + case ACPI_PTYPE2_REV_FIXED: + + /* First element is the (Integer) revision */ + + status = acpi_ns_check_object_type(info, elements, + ACPI_RTYPE_INTEGER, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + + elements++; + count--; + + /* Examine the subpackages */ + + status = + acpi_ns_check_package_list(info, package, elements, count); + break; + + case ACPI_PTYPE2_PKG_COUNT: + + /* First element is the (Integer) count of subpackages to follow */ + + status = acpi_ns_check_object_type(info, elements, + ACPI_RTYPE_INTEGER, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* + * Count cannot be larger than the parent package length, but allow it + * to be smaller. The >= accounts for the Integer above. + */ + expected_count = (u32)(*elements)->integer.value; + if (expected_count >= count) { + goto package_too_small; + } + + count = expected_count; + elements++; + + /* Examine the subpackages */ + + status = + acpi_ns_check_package_list(info, package, elements, count); + break; + + case ACPI_PTYPE2: + case ACPI_PTYPE2_FIXED: + case ACPI_PTYPE2_MIN: + case ACPI_PTYPE2_COUNT: + case ACPI_PTYPE2_FIX_VAR: + /* + * These types all return a single Package that consists of a + * variable number of subpackages. + * + * First, ensure that the first element is a subpackage. If not, + * the BIOS may have incorrectly returned the object as a single + * package instead of a Package of Packages (a common error if + * there is only one entry). We may be able to repair this by + * wrapping the returned Package with a new outer Package. + */ + if (*elements + && ((*elements)->common.type != ACPI_TYPE_PACKAGE)) { + + /* Create the new outer package and populate it */ + + status = + acpi_ns_wrap_with_package(info, return_object, + return_object_ptr); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Update locals to point to the new package (of 1 element) */ + + return_object = *return_object_ptr; + elements = return_object->package.elements; + count = 1; + } + + /* Examine the subpackages */ + + status = + acpi_ns_check_package_list(info, package, elements, count); + break; + + default: + + /* Should not get here if predefined info table is correct */ + + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, + "Invalid internal return type in table entry: %X", + package->ret_info.type)); + + return (AE_AML_INTERNAL); + } + + return (status); + +package_too_small: + + /* Error exit for the case with an incorrect package count */ + + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, + "Return Package is too small - found %u elements, expected %u", + count, expected_count)); + + return (AE_AML_OPERAND_VALUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_package_list + * + * PARAMETERS: info - Method execution information block + * package - Pointer to package-specific info for method + * elements - Element list of parent package. All elements + * of this list should be of type Package. + * count - Count of subpackages + * + * RETURN: Status + * + * DESCRIPTION: Examine a list of subpackages + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_package_list(struct acpi_evaluate_info *info, + const union acpi_predefined_info *package, + union acpi_operand_object **elements, u32 count) +{ + union acpi_operand_object *sub_package; + union acpi_operand_object **sub_elements; + acpi_status status; + u32 expected_count; + u32 i; + u32 j; + + /* + * Validate each subpackage in the parent Package + * + * NOTE: assumes list of subpackages contains no NULL elements. + * Any NULL elements should have been removed by earlier call + * to acpi_ns_remove_null_elements. + */ + for (i = 0; i < count; i++) { + sub_package = *elements; + sub_elements = sub_package->package.elements; + info->parent_package = sub_package; + + /* Each sub-object must be of type Package */ + + status = acpi_ns_check_object_type(info, &sub_package, + ACPI_RTYPE_PACKAGE, i); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Examine the different types of expected subpackages */ + + info->parent_package = sub_package; + switch (package->ret_info.type) { + case ACPI_PTYPE2: + case ACPI_PTYPE2_PKG_COUNT: + case ACPI_PTYPE2_REV_FIXED: + + /* Each subpackage has a fixed number of elements */ + + expected_count = + package->ret_info.count1 + package->ret_info.count2; + if (sub_package->package.count < expected_count) { + goto package_too_small; + } + + status = + acpi_ns_check_package_elements(info, sub_elements, + package->ret_info. + object_type1, + package->ret_info. + count1, + package->ret_info. + object_type2, + package->ret_info. + count2, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_PTYPE2_FIX_VAR: + /* + * Each subpackage has a fixed number of elements and an + * optional element + */ + expected_count = + package->ret_info.count1 + package->ret_info.count2; + if (sub_package->package.count < expected_count) { + goto package_too_small; + } + + status = + acpi_ns_check_package_elements(info, sub_elements, + package->ret_info. + object_type1, + package->ret_info. + count1, + package->ret_info. + object_type2, + sub_package->package. + count - + package->ret_info. + count1, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_PTYPE2_FIXED: + + /* Each subpackage has a fixed length */ + + expected_count = package->ret_info2.count; + if (sub_package->package.count < expected_count) { + goto package_too_small; + } + + /* Check the type of each subpackage element */ + + for (j = 0; j < expected_count; j++) { + status = + acpi_ns_check_object_type(info, + &sub_elements[j], + package-> + ret_info2. + object_type[j], + j); + if (ACPI_FAILURE(status)) { + return (status); + } + } + break; + + case ACPI_PTYPE2_MIN: + + /* Each subpackage has a variable but minimum length */ + + expected_count = package->ret_info.count1; + if (sub_package->package.count < expected_count) { + goto package_too_small; + } + + /* Check the type of each subpackage element */ + + status = + acpi_ns_check_package_elements(info, sub_elements, + package->ret_info. + object_type1, + sub_package->package. + count, 0, 0, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_PTYPE2_COUNT: + /* + * First element is the (Integer) count of elements, including + * the count field (the ACPI name is num_elements) + */ + status = acpi_ns_check_object_type(info, sub_elements, + ACPI_RTYPE_INTEGER, + 0); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* + * Make sure package is large enough for the Count and is + * is as large as the minimum size + */ + expected_count = (u32)(*sub_elements)->integer.value; + if (sub_package->package.count < expected_count) { + goto package_too_small; + } + if (sub_package->package.count < + package->ret_info.count1) { + expected_count = package->ret_info.count1; + goto package_too_small; + } + if (expected_count == 0) { + /* + * Either the num_entries element was originally zero or it was + * a NULL element and repaired to an Integer of value zero. + * In either case, repair it by setting num_entries to be the + * actual size of the subpackage. + */ + expected_count = sub_package->package.count; + (*sub_elements)->integer.value = expected_count; + } + + /* Check the type of each subpackage element */ + + status = + acpi_ns_check_package_elements(info, + (sub_elements + 1), + package->ret_info. + object_type1, + (expected_count - 1), + 0, 0, 1); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + default: /* Should not get here, type was validated by caller */ + + return (AE_AML_INTERNAL); + } + + elements++; + } + + return (AE_OK); + +package_too_small: + + /* The subpackage count was smaller than required */ + + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, + "Return SubPackage[%u] is too small - found %u elements, expected %u", + i, sub_package->package.count, expected_count)); + + return (AE_AML_OPERAND_VALUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_package_elements + * + * PARAMETERS: info - Method execution information block + * elements - Pointer to the package elements array + * type1 - Object type for first group + * count1 - Count for first group + * type2 - Object type for second group + * count2 - Count for second group + * start_index - Start of the first group of elements + * + * RETURN: Status + * + * DESCRIPTION: Check that all elements of a package are of the correct object + * type. Supports up to two groups of different object types. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_package_elements(struct acpi_evaluate_info *info, + union acpi_operand_object **elements, + u8 type1, + u32 count1, + u8 type2, u32 count2, u32 start_index) +{ + union acpi_operand_object **this_element = elements; + acpi_status status; + u32 i; + + /* + * Up to two groups of package elements are supported by the data + * structure. All elements in each group must be of the same type. + * The second group can have a count of zero. + */ + for (i = 0; i < count1; i++) { + status = acpi_ns_check_object_type(info, this_element, + type1, i + start_index); + if (ACPI_FAILURE(status)) { + return (status); + } + this_element++; + } + + for (i = 0; i < count2; i++) { + status = acpi_ns_check_object_type(info, this_element, + type2, + (i + count1 + start_index)); + if (ACPI_FAILURE(status)) { + return (status); + } + this_element++; + } + + return (AE_OK); +} diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index 9c35d20eb52..7e417aa5c91 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,6 +46,7 @@ #include "acnamesp.h" #include "acinterp.h" #include "acpredef.h" +#include "amlresrc.h" #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsrepair") @@ -72,34 +73,64 @@ ACPI_MODULE_NAME("nsrepair") * Buffer -> Package of Integers * Package -> Package of one Package * - * Additional possible repairs: + * Additional conversions that are available: + * Convert a null return or zero return value to an end_tag descriptor + * Convert an ASCII string to a Unicode buffer + * + * An incorrect standalone object is wrapped with required outer package * + * Additional possible repairs: * Required package elements that are NULL replaced by Integer/String/Buffer - * Incorrect standalone package wrapped with required outer package * ******************************************************************************/ /* Local prototypes */ -static acpi_status -acpi_ns_convert_to_integer(union acpi_operand_object *original_object, - union acpi_operand_object **return_object); - -static acpi_status -acpi_ns_convert_to_string(union acpi_operand_object *original_object, - union acpi_operand_object **return_object); +static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct + acpi_namespace_node + *node, + u32 + return_btype, + u32 + package_index); -static acpi_status -acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, - union acpi_operand_object **return_object); - -static acpi_status -acpi_ns_convert_to_package(union acpi_operand_object *original_object, - union acpi_operand_object **return_object); +/* + * Special but simple repairs for some names. + * + * 2nd argument: Unexpected types that can be repaired + */ +static const struct acpi_simple_repair_info acpi_object_repair_info[] = { + /* Resource descriptor conversions */ + + {"_CRS", + ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | + ACPI_RTYPE_NONE, + ACPI_NOT_PACKAGE_ELEMENT, + acpi_ns_convert_to_resource}, + {"_DMA", + ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | + ACPI_RTYPE_NONE, + ACPI_NOT_PACKAGE_ELEMENT, + acpi_ns_convert_to_resource}, + {"_PRS", + ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | + ACPI_RTYPE_NONE, + ACPI_NOT_PACKAGE_ELEMENT, + acpi_ns_convert_to_resource}, + + /* Unicode conversions */ + + {"_MLS", ACPI_RTYPE_STRING, 1, + acpi_ns_convert_to_unicode}, + {"_STR", ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER, + ACPI_NOT_PACKAGE_ELEMENT, + acpi_ns_convert_to_unicode}, + {{0, 0, 0, 0}, 0, 0, NULL} /* Table terminator */ +}; /******************************************************************************* * - * FUNCTION: acpi_ns_repair_object + * FUNCTION: acpi_ns_simple_repair * - * PARAMETERS: Data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * expected_btypes - Object types expected * package_index - Index of object within parent package (if * applicable - ACPI_NOT_PACKAGE_ELEMENT @@ -115,16 +146,54 @@ acpi_ns_convert_to_package(union acpi_operand_object *original_object, ******************************************************************************/ acpi_status -acpi_ns_repair_object(struct acpi_predefined_data *data, +acpi_ns_simple_repair(struct acpi_evaluate_info *info, u32 expected_btypes, u32 package_index, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; - union acpi_operand_object *new_object; + union acpi_operand_object *new_object = NULL; acpi_status status; + const struct acpi_simple_repair_info *predefined; - ACPI_FUNCTION_NAME(ns_repair_object); + ACPI_FUNCTION_NAME(ns_simple_repair); + + /* + * Special repairs for certain names that are in the repair table. + * Check if this name is in the list of repairable names. + */ + predefined = acpi_ns_match_simple_repair(info->node, + info->return_btype, + package_index); + if (predefined) { + if (!return_object) { + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + ACPI_WARN_ALWAYS, + "Missing expected return value")); + } + + status = + predefined->object_converter(return_object, &new_object); + if (ACPI_FAILURE(status)) { + + /* A fatal error occurred during a conversion */ + + ACPI_EXCEPTION((AE_INFO, status, + "During return object analysis")); + return (status); + } + if (new_object) { + goto object_repaired; + } + } + + /* + * Do not perform simple object repair unless the return type is not + * expected. + */ + if (info->return_btype & expected_btypes) { + return (AE_OK); + } /* * At this point, we know that the type of the returned object was not @@ -132,6 +201,41 @@ acpi_ns_repair_object(struct acpi_predefined_data *data, * repair the object by converting it to one of the expected object * types for this predefined name. */ + + /* + * If there is no return value, check if we require a return value for + * this predefined name. Either one return value is expected, or none, + * for both methods and other objects. + * + * Try to fix if there was no return object. Warning if failed to fix. + */ + if (!return_object) { + if (expected_btypes && (!(expected_btypes & ACPI_RTYPE_NONE))) { + if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { + ACPI_WARN_PREDEFINED((AE_INFO, + info->full_pathname, + ACPI_WARN_ALWAYS, + "Found unexpected NULL package element")); + + status = + acpi_ns_repair_null_element(info, + expected_btypes, + package_index, + return_object_ptr); + if (ACPI_SUCCESS(status)) { + return (AE_OK); /* Repair was successful */ + } + } else { + ACPI_WARN_PREDEFINED((AE_INFO, + info->full_pathname, + ACPI_WARN_ALWAYS, + "Missing expected return value")); + } + + return (AE_AML_NO_RETURN_VALUE); + } + } + if (expected_btypes & ACPI_RTYPE_INTEGER) { status = acpi_ns_convert_to_integer(return_object, &new_object); if (ACPI_SUCCESS(status)) { @@ -151,9 +255,24 @@ acpi_ns_repair_object(struct acpi_predefined_data *data, } } if (expected_btypes & ACPI_RTYPE_PACKAGE) { - status = acpi_ns_convert_to_package(return_object, &new_object); + /* + * A package is expected. We will wrap the existing object with a + * new package object. It is often the case that if a variable-length + * package is required, but there is only a single object needed, the + * BIOS will return that object instead of wrapping it with a Package + * object. Note: after the wrapping, the package will be validated + * for correct contents (expected object type or types). + */ + status = + acpi_ns_wrap_with_package(info, return_object, &new_object); if (ACPI_SUCCESS(status)) { - goto object_repaired; + /* + * The original object just had its reference count + * incremented for being inserted into the new package. + */ + *return_object_ptr = new_object; /* New Package object */ + info->return_flags |= ACPI_OBJECT_REPAIRED; + return (AE_OK); } } @@ -161,34 +280,39 @@ acpi_ns_repair_object(struct acpi_predefined_data *data, return (AE_AML_OPERAND_TYPE); - object_repaired: +object_repaired: /* Object was successfully repaired */ - /* - * If the original object is a package element, we need to: - * 1. Set the reference count of the new object to match the - * reference count of the old object. - * 2. Decrement the reference count of the original object. - */ if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { - new_object->common.reference_count = - return_object->common.reference_count; + /* + * The original object is a package element. We need to + * decrement the reference count of the original object, + * for removing it from the package. + * + * However, if the original object was just wrapped with a + * package object as part of the repair, we don't need to + * change the reference count. + */ + if (!(info->return_flags & ACPI_OBJECT_WRAPPED)) { + new_object->common.reference_count = + return_object->common.reference_count; - if (return_object->common.reference_count > 1) { - return_object->common.reference_count--; + if (return_object->common.reference_count > 1) { + return_object->common.reference_count--; + } } ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, - "%s: Converted %s to expected %s at index %u\n", - data->pathname, + "%s: Converted %s to expected %s at Package index %u\n", + info->full_pathname, acpi_ut_get_object_type_name(return_object), acpi_ut_get_object_type_name(new_object), package_index)); } else { ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Converted %s to expected %s\n", - data->pathname, + info->full_pathname, acpi_ut_get_object_type_name(return_object), acpi_ut_get_object_type_name(new_object))); } @@ -197,324 +321,62 @@ acpi_ns_repair_object(struct acpi_predefined_data *data, acpi_ut_remove_reference(return_object); *return_object_ptr = new_object; - data->flags |= ACPI_OBJECT_REPAIRED; - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_convert_to_integer - * - * PARAMETERS: original_object - Object to be converted - * return_object - Where the new converted object is returned - * - * RETURN: Status. AE_OK if conversion was successful. - * - * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer. - * - ******************************************************************************/ - -static acpi_status -acpi_ns_convert_to_integer(union acpi_operand_object *original_object, - union acpi_operand_object **return_object) -{ - union acpi_operand_object *new_object; - acpi_status status; - u64 value = 0; - u32 i; - - switch (original_object->common.type) { - case ACPI_TYPE_STRING: - - /* String-to-Integer conversion */ - - status = acpi_ut_strtoul64(original_object->string.pointer, - ACPI_ANY_BASE, &value); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - case ACPI_TYPE_BUFFER: - - /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */ - - if (original_object->buffer.length > 8) { - return (AE_AML_OPERAND_TYPE); - } - - /* Extract each buffer byte to create the integer */ - - for (i = 0; i < original_object->buffer.length; i++) { - value |= - ((u64) original_object->buffer. - pointer[i] << (i * 8)); - } - break; - - default: - return (AE_AML_OPERAND_TYPE); - } - - new_object = acpi_ut_create_integer_object(value); - if (!new_object) { - return (AE_NO_MEMORY); - } - - *return_object = new_object; - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_convert_to_string - * - * PARAMETERS: original_object - Object to be converted - * return_object - Where the new converted object is returned - * - * RETURN: Status. AE_OK if conversion was successful. - * - * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String. - * - ******************************************************************************/ - -static acpi_status -acpi_ns_convert_to_string(union acpi_operand_object *original_object, - union acpi_operand_object **return_object) -{ - union acpi_operand_object *new_object; - acpi_size length; - acpi_status status; - - switch (original_object->common.type) { - case ACPI_TYPE_INTEGER: - /* - * Integer-to-String conversion. Commonly, convert - * an integer of value 0 to a NULL string. The last element of - * _BIF and _BIX packages occasionally need this fix. - */ - if (original_object->integer.value == 0) { - - /* Allocate a new NULL string object */ - - new_object = acpi_ut_create_string_object(0); - if (!new_object) { - return (AE_NO_MEMORY); - } - } else { - status = - acpi_ex_convert_to_string(original_object, - &new_object, - ACPI_IMPLICIT_CONVERT_HEX); - if (ACPI_FAILURE(status)) { - return (status); - } - } - break; - - case ACPI_TYPE_BUFFER: - /* - * Buffer-to-String conversion. Use a to_string - * conversion, no transform performed on the buffer data. The best - * example of this is the _BIF method, where the string data from - * the battery is often (incorrectly) returned as buffer object(s). - */ - length = 0; - while ((length < original_object->buffer.length) && - (original_object->buffer.pointer[length])) { - length++; - } - - /* Allocate a new string object */ - - new_object = acpi_ut_create_string_object(length); - if (!new_object) { - return (AE_NO_MEMORY); - } - - /* - * Copy the raw buffer data with no transform. String is already NULL - * terminated at Length+1. - */ - ACPI_MEMCPY(new_object->string.pointer, - original_object->buffer.pointer, length); - break; - - default: - return (AE_AML_OPERAND_TYPE); - } - - *return_object = new_object; + info->return_flags |= ACPI_OBJECT_REPAIRED; return (AE_OK); } -/******************************************************************************* +/****************************************************************************** * - * FUNCTION: acpi_ns_convert_to_buffer + * FUNCTION: acpi_ns_match_simple_repair * - * PARAMETERS: original_object - Object to be converted - * return_object - Where the new converted object is returned + * PARAMETERS: node - Namespace node for the method/object + * return_btype - Object type that was returned + * package_index - Index of object within parent package (if + * applicable - ACPI_NOT_PACKAGE_ELEMENT + * otherwise) * - * RETURN: Status. AE_OK if conversion was successful. + * RETURN: Pointer to entry in repair table. NULL indicates not found. * - * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer. + * DESCRIPTION: Check an object name against the repairable object list. * - ******************************************************************************/ + *****************************************************************************/ -static acpi_status -acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, - union acpi_operand_object **return_object) +static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct + acpi_namespace_node + *node, + u32 + return_btype, + u32 + package_index) { - union acpi_operand_object *new_object; - acpi_status status; - union acpi_operand_object **elements; - u32 *dword_buffer; - u32 count; - u32 i; - - switch (original_object->common.type) { - case ACPI_TYPE_INTEGER: - /* - * Integer-to-Buffer conversion. - * Convert the Integer to a packed-byte buffer. _MAT and other - * objects need this sometimes, if a read has been performed on a - * Field object that is less than or equal to the global integer - * size (32 or 64 bits). - */ - status = - acpi_ex_convert_to_buffer(original_object, &new_object); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - case ACPI_TYPE_STRING: - - /* String-to-Buffer conversion. Simple data copy */ - - new_object = - acpi_ut_create_buffer_object(original_object->string. - length); - if (!new_object) { - return (AE_NO_MEMORY); - } + const struct acpi_simple_repair_info *this_name; - ACPI_MEMCPY(new_object->buffer.pointer, - original_object->string.pointer, - original_object->string.length); - break; - - case ACPI_TYPE_PACKAGE: - /* - * This case is often seen for predefined names that must return a - * Buffer object with multiple DWORD integers within. For example, - * _FDE and _GTM. The Package can be converted to a Buffer. - */ + /* Search info table for a repairable predefined method/object name */ - /* All elements of the Package must be integers */ + this_name = acpi_object_repair_info; + while (this_name->object_converter) { + if (ACPI_COMPARE_NAME(node->name.ascii, this_name->name)) { - elements = original_object->package.elements; - count = original_object->package.count; + /* Check if we can actually repair this name/type combination */ - for (i = 0; i < count; i++) { - if ((!*elements) || - ((*elements)->common.type != ACPI_TYPE_INTEGER)) { - return (AE_AML_OPERAND_TYPE); + if ((return_btype & this_name->unexpected_btypes) && + (package_index == this_name->package_index)) { + return (this_name); } - elements++; - } - - /* Create the new buffer object to replace the Package */ - new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count)); - if (!new_object) { - return (AE_NO_MEMORY); + return (NULL); } - - /* Copy the package elements (integers) to the buffer as DWORDs */ - - elements = original_object->package.elements; - dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer); - - for (i = 0; i < count; i++) { - *dword_buffer = (u32) (*elements)->integer.value; - dword_buffer++; - elements++; - } - break; - - default: - return (AE_AML_OPERAND_TYPE); + this_name++; } - *return_object = new_object; - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_convert_to_package - * - * PARAMETERS: original_object - Object to be converted - * return_object - Where the new converted object is returned - * - * RETURN: Status. AE_OK if conversion was successful. - * - * DESCRIPTION: Attempt to convert a Buffer object to a Package. Each byte of - * the buffer is converted to a single integer package element. - * - ******************************************************************************/ - -static acpi_status -acpi_ns_convert_to_package(union acpi_operand_object *original_object, - union acpi_operand_object **return_object) -{ - union acpi_operand_object *new_object; - union acpi_operand_object **elements; - u32 length; - u8 *buffer; - - switch (original_object->common.type) { - case ACPI_TYPE_BUFFER: - - /* Buffer-to-Package conversion */ - - length = original_object->buffer.length; - new_object = acpi_ut_create_package_object(length); - if (!new_object) { - return (AE_NO_MEMORY); - } - - /* Convert each buffer byte to an integer package element */ - - elements = new_object->package.elements; - buffer = original_object->buffer.pointer; - - while (length--) { - *elements = - acpi_ut_create_integer_object((u64) *buffer); - if (!*elements) { - acpi_ut_remove_reference(new_object); - return (AE_NO_MEMORY); - } - elements++; - buffer++; - } - break; - - default: - return (AE_AML_OPERAND_TYPE); - } - - *return_object = new_object; - return (AE_OK); + return (NULL); /* Name was not found in the repair table */ } /******************************************************************************* * * FUNCTION: acpi_ns_repair_null_element * - * PARAMETERS: Data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * expected_btypes - Object types expected * package_index - Index of object within parent package (if * applicable - ACPI_NOT_PACKAGE_ELEMENT @@ -529,7 +391,7 @@ acpi_ns_convert_to_package(union acpi_operand_object *original_object, ******************************************************************************/ acpi_status -acpi_ns_repair_null_element(struct acpi_predefined_data *data, +acpi_ns_repair_null_element(struct acpi_evaluate_info * info, u32 expected_btypes, u32 package_index, union acpi_operand_object **return_object_ptr) @@ -553,17 +415,17 @@ acpi_ns_repair_null_element(struct acpi_predefined_data *data, */ if (expected_btypes & ACPI_RTYPE_INTEGER) { - /* Need an Integer - create a zero-value integer */ + /* Need an integer - create a zero-value integer */ new_object = acpi_ut_create_integer_object((u64)0); } else if (expected_btypes & ACPI_RTYPE_STRING) { - /* Need a String - create a NULL string */ + /* Need a string - create a NULL string */ new_object = acpi_ut_create_string_object(0); } else if (expected_btypes & ACPI_RTYPE_BUFFER) { - /* Need a Buffer - create a zero-length buffer */ + /* Need a buffer - create a zero-length buffer */ new_object = acpi_ut_create_buffer_object(0); } else { @@ -579,16 +441,16 @@ acpi_ns_repair_null_element(struct acpi_predefined_data *data, /* Set the reference count according to the parent Package object */ new_object->common.reference_count = - data->parent_package->common.reference_count; + info->parent_package->common.reference_count; ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Converted NULL package element to expected %s at index %u\n", - data->pathname, + info->full_pathname, acpi_ut_get_object_type_name(new_object), package_index)); *return_object_ptr = new_object; - data->flags |= ACPI_OBJECT_REPAIRED; + info->return_flags |= ACPI_OBJECT_REPAIRED; return (AE_OK); } @@ -596,20 +458,20 @@ acpi_ns_repair_null_element(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_remove_null_elements * - * PARAMETERS: Data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * package_type - An acpi_return_package_types value * obj_desc - A Package object * * RETURN: None. * * DESCRIPTION: Remove all NULL package elements from packages that contain - * a variable number of sub-packages. For these types of + * a variable number of subpackages. For these types of * packages, NULL elements can be safely removed. * *****************************************************************************/ void -acpi_ns_remove_null_elements(struct acpi_predefined_data *data, +acpi_ns_remove_null_elements(struct acpi_evaluate_info *info, u8 package_type, union acpi_operand_object *obj_desc) { @@ -624,7 +486,7 @@ acpi_ns_remove_null_elements(struct acpi_predefined_data *data, /* * We can safely remove all NULL elements from these package types: * PTYPE1_VAR packages contain a variable number of simple data types. - * PTYPE2 packages contain a variable number of sub-packages. + * PTYPE2 packages contain a variable number of subpackages. */ switch (package_type) { case ACPI_PTYPE1_VAR: @@ -635,6 +497,7 @@ acpi_ns_remove_null_elements(struct acpi_predefined_data *data, case ACPI_PTYPE2_MIN: case ACPI_PTYPE2_REV_FIXED: case ACPI_PTYPE2_FIX_VAR: + break; default: @@ -666,7 +529,7 @@ acpi_ns_remove_null_elements(struct acpi_predefined_data *data, if (new_count < count) { ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Found and removed %u NULL elements\n", - data->pathname, (count - new_count))); + info->full_pathname, (count - new_count))); /* NULL terminate list and update the package count */ @@ -677,55 +540,56 @@ acpi_ns_remove_null_elements(struct acpi_predefined_data *data, /******************************************************************************* * - * FUNCTION: acpi_ns_repair_package_list + * FUNCTION: acpi_ns_wrap_with_package * - * PARAMETERS: Data - Pointer to validation data structure - * obj_desc_ptr - Pointer to the object to repair. The new - * package object is returned here, - * overwriting the old object. + * PARAMETERS: info - Method execution information block + * original_object - Pointer to the object to repair. + * obj_desc_ptr - The new package object is returned here * * RETURN: Status, new object in *obj_desc_ptr * - * DESCRIPTION: Repair a common problem with objects that are defined to return - * a variable-length Package of Packages. If the variable-length - * is one, some BIOS code mistakenly simply declares a single - * Package instead of a Package with one sub-Package. This - * function attempts to repair this error by wrapping a Package - * object around the original Package, creating the correct - * Package with one sub-Package. + * DESCRIPTION: Repair a common problem with objects that are defined to + * return a variable-length Package of sub-objects. If there is + * only one sub-object, some BIOS code mistakenly simply declares + * the single object instead of a Package with one sub-object. + * This function attempts to repair this error by wrapping a + * Package object around the original object, creating the + * correct and expected Package with one sub-object. * * Names that can be repaired in this manner include: - * _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS + * _ALR, _CSD, _HPX, _MLS, _PLD, _PRT, _PSS, _TRT, _TSS, + * _BCL, _DOD, _FIX, _Sx * ******************************************************************************/ acpi_status -acpi_ns_repair_package_list(struct acpi_predefined_data *data, - union acpi_operand_object **obj_desc_ptr) +acpi_ns_wrap_with_package(struct acpi_evaluate_info *info, + union acpi_operand_object *original_object, + union acpi_operand_object **obj_desc_ptr) { union acpi_operand_object *pkg_obj_desc; - ACPI_FUNCTION_NAME(ns_repair_package_list); + ACPI_FUNCTION_NAME(ns_wrap_with_package); /* * Create the new outer package and populate it. The new package will - * have a single element, the lone subpackage. + * have a single element, the lone sub-object. */ pkg_obj_desc = acpi_ut_create_package_object(1); if (!pkg_obj_desc) { return (AE_NO_MEMORY); } - pkg_obj_desc->package.elements[0] = *obj_desc_ptr; + pkg_obj_desc->package.elements[0] = original_object; + + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, + "%s: Wrapped %s with expected Package object\n", + info->full_pathname, + acpi_ut_get_object_type_name(original_object))); /* Return the new object in the object pointer */ *obj_desc_ptr = pkg_obj_desc; - data->flags |= ACPI_OBJECT_REPAIRED; - - ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, - "%s: Repaired incorrectly formed Package\n", - data->pathname)); - + info->return_flags |= ACPI_OBJECT_REPAIRED | ACPI_OBJECT_WRAPPED; return (AE_OK); } diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index 726bc8e687f..b09e6bef72b 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,8 +54,9 @@ ACPI_MODULE_NAME("nsrepair2") * be repaired on a per-name basis. */ typedef -acpi_status(*acpi_repair_function) (struct acpi_predefined_data *data, - union acpi_operand_object **return_object_ptr); +acpi_status(*acpi_repair_function) (struct acpi_evaluate_info * info, + union acpi_operand_object + **return_object_ptr); typedef struct acpi_repair_info { char name[ACPI_NAME_SIZE]; @@ -65,50 +66,62 @@ typedef struct acpi_repair_info { /* Local prototypes */ -static const struct acpi_repair_info *acpi_ns_match_repairable_name(struct - acpi_namespace_node - *node); +static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct + acpi_namespace_node + *node); static acpi_status -acpi_ns_repair_ALR(struct acpi_predefined_data *data, +acpi_ns_repair_ALR(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr); static acpi_status -acpi_ns_repair_CID(struct acpi_predefined_data *data, +acpi_ns_repair_CID(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr); static acpi_status -acpi_ns_repair_FDE(struct acpi_predefined_data *data, +acpi_ns_repair_CST(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr); static acpi_status -acpi_ns_repair_HID(struct acpi_predefined_data *data, +acpi_ns_repair_FDE(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr); static acpi_status -acpi_ns_repair_PSS(struct acpi_predefined_data *data, +acpi_ns_repair_HID(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr); static acpi_status -acpi_ns_repair_TSS(struct acpi_predefined_data *data, +acpi_ns_repair_PRT(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr); static acpi_status -acpi_ns_check_sorted_list(struct acpi_predefined_data *data, +acpi_ns_repair_PSS(struct acpi_evaluate_info *info, + union acpi_operand_object **return_object_ptr); + +static acpi_status +acpi_ns_repair_TSS(struct acpi_evaluate_info *info, + union acpi_operand_object **return_object_ptr); + +static acpi_status +acpi_ns_check_sorted_list(struct acpi_evaluate_info *info, union acpi_operand_object *return_object, + u32 start_index, u32 expected_count, u32 sort_index, u8 sort_direction, char *sort_key_name); -static void -acpi_ns_sort_list(union acpi_operand_object **elements, - u32 count, u32 index, u8 sort_direction); - /* Values for sort_direction above */ #define ACPI_SORT_ASCENDING 0 #define ACPI_SORT_DESCENDING 1 +static void +acpi_ns_remove_element(union acpi_operand_object *obj_desc, u32 index); + +static void +acpi_ns_sort_list(union acpi_operand_object **elements, + u32 count, u32 index, u8 sort_direction); + /* * This table contains the names of the predefined methods for which we can * perform more complex repairs. @@ -117,9 +130,11 @@ acpi_ns_sort_list(union acpi_operand_object **elements, * * _ALR: Sort the list ascending by ambient_illuminance * _CID: Strings: uppercase all, remove any leading asterisk + * _CST: Sort the list ascending by C state type * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs * _HID: Strings: uppercase all, remove any leading asterisk + * _PRT: Fix reversed source_name and source_index * _PSS: Sort the list descending by Power * _TSS: Sort the list descending by Power * @@ -133,9 +148,11 @@ acpi_ns_sort_list(union acpi_operand_object **elements, static const struct acpi_repair_info acpi_ns_repairable_names[] = { {"_ALR", acpi_ns_repair_ALR}, {"_CID", acpi_ns_repair_CID}, + {"_CST", acpi_ns_repair_CST}, {"_FDE", acpi_ns_repair_FDE}, {"_GTM", acpi_ns_repair_FDE}, /* _GTM has same repair as _FDE */ {"_HID", acpi_ns_repair_HID}, + {"_PRT", acpi_ns_repair_PRT}, {"_PSS", acpi_ns_repair_PSS}, {"_TSS", acpi_ns_repair_TSS}, {{0, 0, 0, 0}, NULL} /* Table terminator */ @@ -149,8 +166,8 @@ static const struct acpi_repair_info acpi_ns_repairable_names[] = { * * FUNCTION: acpi_ns_complex_repairs * - * PARAMETERS: Data - Pointer to validation data structure - * Node - Namespace node for the method/object + * PARAMETERS: info - Method execution information block + * node - Namespace node for the method/object * validate_status - Original status of earlier validation * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object @@ -164,7 +181,7 @@ static const struct acpi_repair_info acpi_ns_repairable_names[] = { *****************************************************************************/ acpi_status -acpi_ns_complex_repairs(struct acpi_predefined_data *data, +acpi_ns_complex_repairs(struct acpi_evaluate_info *info, struct acpi_namespace_node *node, acpi_status validate_status, union acpi_operand_object **return_object_ptr) @@ -174,20 +191,20 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data, /* Check if this name is in the list of repairable names */ - predefined = acpi_ns_match_repairable_name(node); + predefined = acpi_ns_match_complex_repair(node); if (!predefined) { return (validate_status); } - status = predefined->repair_function(data, return_object_ptr); + status = predefined->repair_function(info, return_object_ptr); return (status); } /****************************************************************************** * - * FUNCTION: acpi_ns_match_repairable_name + * FUNCTION: acpi_ns_match_complex_repair * - * PARAMETERS: Node - Namespace node for the method/object + * PARAMETERS: node - Namespace node for the method/object * * RETURN: Pointer to entry in repair table. NULL indicates not found. * @@ -195,9 +212,9 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data, * *****************************************************************************/ -static const struct acpi_repair_info *acpi_ns_match_repairable_name(struct - acpi_namespace_node - *node) +static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct + acpi_namespace_node + *node) { const struct acpi_repair_info *this_name; @@ -218,7 +235,7 @@ static const struct acpi_repair_info *acpi_ns_match_repairable_name(struct * * FUNCTION: acpi_ns_repair_ALR * - * PARAMETERS: Data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * @@ -230,13 +247,13 @@ static const struct acpi_repair_info *acpi_ns_match_repairable_name(struct *****************************************************************************/ static acpi_status -acpi_ns_repair_ALR(struct acpi_predefined_data *data, +acpi_ns_repair_ALR(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; acpi_status status; - status = acpi_ns_check_sorted_list(data, return_object, 2, 1, + status = acpi_ns_check_sorted_list(info, return_object, 0, 2, 1, ACPI_SORT_ASCENDING, "AmbientIlluminance"); @@ -247,7 +264,7 @@ acpi_ns_repair_ALR(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_repair_FDE * - * PARAMETERS: Data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * @@ -261,7 +278,7 @@ acpi_ns_repair_ALR(struct acpi_predefined_data *data, *****************************************************************************/ static acpi_status -acpi_ns_repair_FDE(struct acpi_predefined_data *data, +acpi_ns_repair_FDE(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; @@ -284,8 +301,8 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data, /* We can only repair if we have exactly 5 BYTEs */ if (return_object->buffer.length != ACPI_FDE_BYTE_BUFFER_SIZE) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, - data->node_flags, + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, "Incorrect return buffer length %u, expected %u", return_object->buffer.length, ACPI_FDE_DWORD_BUFFER_SIZE)); @@ -315,10 +332,11 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data, ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s Expanded Byte Buffer to expected DWord Buffer\n", - data->pathname)); + info->full_pathname)); break; default: + return (AE_AML_OPERAND_TYPE); } @@ -327,7 +345,7 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data, acpi_ut_remove_reference(return_object); *return_object_ptr = buffer_object; - data->flags |= ACPI_OBJECT_REPAIRED; + info->return_flags |= ACPI_OBJECT_REPAIRED; return (AE_OK); } @@ -335,7 +353,7 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_repair_CID * - * PARAMETERS: Data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * @@ -348,7 +366,7 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data, *****************************************************************************/ static acpi_status -acpi_ns_repair_CID(struct acpi_predefined_data *data, +acpi_ns_repair_CID(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { acpi_status status; @@ -361,7 +379,7 @@ acpi_ns_repair_CID(struct acpi_predefined_data *data, /* Check for _CID as a simple string */ if (return_object->common.type == ACPI_TYPE_STRING) { - status = acpi_ns_repair_HID(data, return_object_ptr); + status = acpi_ns_repair_HID(info, return_object_ptr); return (status); } @@ -378,7 +396,7 @@ acpi_ns_repair_CID(struct acpi_predefined_data *data, original_element = *element_ptr; original_ref_count = original_element->common.reference_count; - status = acpi_ns_repair_HID(data, element_ptr); + status = acpi_ns_repair_HID(info, element_ptr); if (ACPI_FAILURE(status)) { return (status); } @@ -403,9 +421,95 @@ acpi_ns_repair_CID(struct acpi_predefined_data *data, /****************************************************************************** * + * FUNCTION: acpi_ns_repair_CST + * + * PARAMETERS: info - Method execution information block + * return_object_ptr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status. AE_OK if object is OK or was repaired successfully + * + * DESCRIPTION: Repair for the _CST object: + * 1. Sort the list ascending by C state type + * 2. Ensure type cannot be zero + * 3. A subpackage count of zero means _CST is meaningless + * 4. Count must match the number of C state subpackages + * + *****************************************************************************/ + +static acpi_status +acpi_ns_repair_CST(struct acpi_evaluate_info *info, + union acpi_operand_object **return_object_ptr) +{ + union acpi_operand_object *return_object = *return_object_ptr; + union acpi_operand_object **outer_elements; + u32 outer_element_count; + union acpi_operand_object *obj_desc; + acpi_status status; + u8 removing; + u32 i; + + ACPI_FUNCTION_NAME(ns_repair_CST); + + /* + * Check if the C-state type values are proportional. + */ + outer_element_count = return_object->package.count - 1; + i = 0; + while (i < outer_element_count) { + outer_elements = &return_object->package.elements[i + 1]; + removing = FALSE; + + if ((*outer_elements)->package.count == 0) { + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, + "SubPackage[%u] - removing entry due to zero count", + i)); + removing = TRUE; + goto remove_element; + } + + obj_desc = (*outer_elements)->package.elements[1]; /* Index1 = Type */ + if ((u32)obj_desc->integer.value == 0) { + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, + "SubPackage[%u] - removing entry due to invalid Type(0)", + i)); + removing = TRUE; + } + +remove_element: + if (removing) { + acpi_ns_remove_element(return_object, i + 1); + outer_element_count--; + } else { + i++; + } + } + + /* Update top-level package count, Type "Integer" checked elsewhere */ + + obj_desc = return_object->package.elements[0]; + obj_desc->integer.value = outer_element_count; + + /* + * Entries (subpackages) in the _CST Package must be sorted by the + * C-state type, in ascending order. + */ + status = acpi_ns_check_sorted_list(info, return_object, 1, 4, 1, + ACPI_SORT_ASCENDING, "C-State Type"); + if (ACPI_FAILURE(status)) { + return (status); + } + + return (AE_OK); +} + +/****************************************************************************** + * * FUNCTION: acpi_ns_repair_HID * - * PARAMETERS: Data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * @@ -417,7 +521,7 @@ acpi_ns_repair_CID(struct acpi_predefined_data *data, *****************************************************************************/ static acpi_status -acpi_ns_repair_HID(struct acpi_predefined_data *data, +acpi_ns_repair_HID(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; @@ -434,12 +538,13 @@ acpi_ns_repair_HID(struct acpi_predefined_data *data, } if (return_object->string.length == 0) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, "Invalid zero-length _HID or _CID string")); /* Return AE_OK anyway, let driver handle it */ - data->flags |= ACPI_OBJECT_REPAIRED; + info->return_flags |= ACPI_OBJECT_REPAIRED; return (AE_OK); } @@ -463,7 +568,7 @@ acpi_ns_repair_HID(struct acpi_predefined_data *data, ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Removed invalid leading asterisk\n", - data->pathname)); + info->full_pathname)); } /* @@ -485,53 +590,76 @@ acpi_ns_repair_HID(struct acpi_predefined_data *data, /****************************************************************************** * - * FUNCTION: acpi_ns_repair_TSS + * FUNCTION: acpi_ns_repair_PRT * - * PARAMETERS: Data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * * RETURN: Status. AE_OK if object is OK or was repaired successfully * - * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list - * descending by the power dissipation values. + * DESCRIPTION: Repair for the _PRT object. If necessary, fix reversed + * source_name and source_index field, a common BIOS bug. * *****************************************************************************/ static acpi_status -acpi_ns_repair_TSS(struct acpi_predefined_data *data, +acpi_ns_repair_PRT(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { - union acpi_operand_object *return_object = *return_object_ptr; - acpi_status status; - struct acpi_namespace_node *node; + union acpi_operand_object *package_object = *return_object_ptr; + union acpi_operand_object **top_object_list; + union acpi_operand_object **sub_object_list; + union acpi_operand_object *obj_desc; + union acpi_operand_object *sub_package; + u32 element_count; + u32 index; - /* - * We can only sort the _TSS return package if there is no _PSS in the - * same scope. This is because if _PSS is present, the ACPI specification - * dictates that the _TSS Power Dissipation field is to be ignored, and - * therefore some BIOSs leave garbage values in the _TSS Power field(s). - * In this case, it is best to just return the _TSS package as-is. - * (May, 2011) - */ - status = - acpi_ns_get_node(data->node, "^_PSS", ACPI_NS_NO_UPSEARCH, &node); - if (ACPI_SUCCESS(status)) { - return (AE_OK); - } + /* Each element in the _PRT package is a subpackage */ - status = acpi_ns_check_sorted_list(data, return_object, 5, 1, - ACPI_SORT_DESCENDING, - "PowerDissipation"); + top_object_list = package_object->package.elements; + element_count = package_object->package.count; - return (status); + /* Examine each subpackage */ + + for (index = 0; index < element_count; index++, top_object_list++) { + sub_package = *top_object_list; + sub_object_list = sub_package->package.elements; + + /* Check for minimum required element count */ + + if (sub_package->package.count < 4) { + continue; + } + + /* + * If the BIOS has erroneously reversed the _PRT source_name (index 2) + * and the source_index (index 3), fix it. _PRT is important enough to + * workaround this BIOS error. This also provides compatibility with + * other ACPI implementations. + */ + obj_desc = sub_object_list[3]; + if (!obj_desc || (obj_desc->common.type != ACPI_TYPE_INTEGER)) { + sub_object_list[3] = sub_object_list[2]; + sub_object_list[2] = obj_desc; + info->return_flags |= ACPI_OBJECT_REPAIRED; + + ACPI_WARN_PREDEFINED((AE_INFO, + info->full_pathname, + info->node_flags, + "PRT[%X]: Fixed reversed SourceName and SourceIndex", + index)); + } + } + + return (AE_OK); } /****************************************************************************** * * FUNCTION: acpi_ns_repair_PSS * - * PARAMETERS: Data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * @@ -545,7 +673,7 @@ acpi_ns_repair_TSS(struct acpi_predefined_data *data, *****************************************************************************/ static acpi_status -acpi_ns_repair_PSS(struct acpi_predefined_data *data, +acpi_ns_repair_PSS(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; @@ -558,12 +686,12 @@ acpi_ns_repair_PSS(struct acpi_predefined_data *data, u32 i; /* - * Entries (sub-packages) in the _PSS Package must be sorted by power + * Entries (subpackages) in the _PSS Package must be sorted by power * dissipation, in descending order. If it appears that the list is * incorrectly sorted, sort it. We sort by cpu_frequency, since this * should be proportional to the power. */ - status = acpi_ns_check_sorted_list(data, return_object, 6, 0, + status = acpi_ns_check_sorted_list(info, return_object, 0, 6, 0, ACPI_SORT_DESCENDING, "CpuFrequency"); if (ACPI_FAILURE(status)) { @@ -583,8 +711,8 @@ acpi_ns_repair_PSS(struct acpi_predefined_data *data, obj_desc = elements[1]; /* Index1 = power_dissipation */ if ((u32) obj_desc->integer.value > previous_value) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, - data->node_flags, + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, "SubPackage[%u,%u] - suspicious power dissipation values", i - 1, i)); } @@ -598,12 +726,57 @@ acpi_ns_repair_PSS(struct acpi_predefined_data *data, /****************************************************************************** * + * FUNCTION: acpi_ns_repair_TSS + * + * PARAMETERS: info - Method execution information block + * return_object_ptr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status. AE_OK if object is OK or was repaired successfully + * + * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list + * descending by the power dissipation values. + * + *****************************************************************************/ + +static acpi_status +acpi_ns_repair_TSS(struct acpi_evaluate_info *info, + union acpi_operand_object **return_object_ptr) +{ + union acpi_operand_object *return_object = *return_object_ptr; + acpi_status status; + struct acpi_namespace_node *node; + + /* + * We can only sort the _TSS return package if there is no _PSS in the + * same scope. This is because if _PSS is present, the ACPI specification + * dictates that the _TSS Power Dissipation field is to be ignored, and + * therefore some BIOSs leave garbage values in the _TSS Power field(s). + * In this case, it is best to just return the _TSS package as-is. + * (May, 2011) + */ + status = acpi_ns_get_node(info->node, "^_PSS", + ACPI_NS_NO_UPSEARCH, &node); + if (ACPI_SUCCESS(status)) { + return (AE_OK); + } + + status = acpi_ns_check_sorted_list(info, return_object, 0, 5, 1, + ACPI_SORT_DESCENDING, + "PowerDissipation"); + + return (status); +} + +/****************************************************************************** + * * FUNCTION: acpi_ns_check_sorted_list * - * PARAMETERS: Data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object - Pointer to the top-level returned object - * expected_count - Minimum length of each sub-package - * sort_index - Sub-package entry to sort on + * start_index - Index of the first subpackage + * expected_count - Minimum length of each subpackage + * sort_index - Subpackage entry to sort on * sort_direction - Ascending or descending * sort_key_name - Name of the sort_index field * @@ -616,8 +789,9 @@ acpi_ns_repair_PSS(struct acpi_predefined_data *data, *****************************************************************************/ static acpi_status -acpi_ns_check_sorted_list(struct acpi_predefined_data *data, +acpi_ns_check_sorted_list(struct acpi_evaluate_info *info, union acpi_operand_object *return_object, + u32 start_index, u32 expected_count, u32 sort_index, u8 sort_direction, char *sort_key_name) @@ -638,16 +812,18 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data, } /* - * NOTE: assumes list of sub-packages contains no NULL elements. + * NOTE: assumes list of subpackages contains no NULL elements. * Any NULL elements should have been removed by earlier call * to acpi_ns_remove_null_elements. */ - outer_elements = return_object->package.elements; outer_element_count = return_object->package.count; - if (!outer_element_count) { + if (!outer_element_count || start_index >= outer_element_count) { return (AE_AML_PACKAGE_LIMIT); } + outer_elements = &return_object->package.elements[start_index]; + outer_element_count -= start_index; + previous_value = 0; if (sort_direction == ACPI_SORT_DESCENDING) { previous_value = ACPI_UINT32_MAX; @@ -663,7 +839,7 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data, return (AE_AML_OPERAND_TYPE); } - /* Each sub-package must have the minimum length */ + /* Each subpackage must have the minimum length */ if ((*outer_elements)->package.count < expected_count) { return (AE_AML_PACKAGE_LIMIT); @@ -684,15 +860,16 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data, (obj_desc->integer.value < previous_value)) || ((sort_direction == ACPI_SORT_DESCENDING) && (obj_desc->integer.value > previous_value))) { - acpi_ns_sort_list(return_object->package.elements, + acpi_ns_sort_list(&return_object->package. + elements[start_index], outer_element_count, sort_index, sort_direction); - data->flags |= ACPI_OBJECT_REPAIRED; + info->return_flags |= ACPI_OBJECT_REPAIRED; ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Repaired unsorted list - now sorted by %s\n", - data->pathname, sort_key_name)); + info->full_pathname, sort_key_name)); return (AE_OK); } @@ -707,9 +884,9 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_sort_list * - * PARAMETERS: Elements - Package object element list - * Count - Element count for above - * Index - Sort by which package element + * PARAMETERS: elements - Package object element list + * count - Element count for above + * index - Sort by which package element * sort_direction - Ascending or Descending sort * * RETURN: None @@ -751,3 +928,52 @@ acpi_ns_sort_list(union acpi_operand_object **elements, } } } + +/****************************************************************************** + * + * FUNCTION: acpi_ns_remove_element + * + * PARAMETERS: obj_desc - Package object element list + * index - Index of element to remove + * + * RETURN: None + * + * DESCRIPTION: Remove the requested element of a package and delete it. + * + *****************************************************************************/ + +static void +acpi_ns_remove_element(union acpi_operand_object *obj_desc, u32 index) +{ + union acpi_operand_object **source; + union acpi_operand_object **dest; + u32 count; + u32 new_count; + u32 i; + + ACPI_FUNCTION_NAME(ns_remove_element); + + count = obj_desc->package.count; + new_count = count - 1; + + source = obj_desc->package.elements; + dest = source; + + /* Examine all elements of the package object, remove matched index */ + + for (i = 0; i < count; i++) { + if (i == index) { + acpi_ut_remove_reference(*source); /* Remove one ref for being in pkg */ + acpi_ut_remove_reference(*source); + } else { + *dest = *source; + dest++; + } + source++; + } + + /* NULL terminate list and update the package count */ + + *dest = NULL; + obj_desc->package.count = new_count; +} diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c index 507043d6611..af1cc42a8aa 100644 --- a/drivers/acpi/acpica/nssearch.c +++ b/drivers/acpi/acpica/nssearch.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -65,7 +65,7 @@ acpi_ns_search_parent_tree(u32 target_name, * * PARAMETERS: target_name - Ascii ACPI name to search for * parent_node - Starting node where search will begin - * Type - Object type to match + * type - Object type to match * return_node - Where the matched Named obj is returned * * RETURN: Status @@ -175,8 +175,8 @@ acpi_ns_search_one_scope(u32 target_name, * FUNCTION: acpi_ns_search_parent_tree * * PARAMETERS: target_name - Ascii ACPI name to search for - * Node - Starting node where search will begin - * Type - Object type to match + * node - Starting node where search will begin + * type - Object type to match * return_node - Where the matched Node is returned * * RETURN: Status @@ -264,11 +264,11 @@ acpi_ns_search_parent_tree(u32 target_name, * * PARAMETERS: target_name - Ascii ACPI name to search for (4 chars) * walk_state - Current state of the walk - * Node - Starting node where search will begin + * node - Starting node where search will begin * interpreter_mode - Add names only in ACPI_MODE_LOAD_PASS_x. * Otherwise,search only. - * Type - Object type to match - * Flags - Flags describing the search restrictions + * type - Object type to match + * flags - Flags describing the search restrictions * return_node - Where the Node is returned * * RETURN: Status @@ -314,22 +314,7 @@ acpi_ns_search_and_enter(u32 target_name, * this problem, and we want to be able to enable ACPI support for them, * even though there are a few bad names. */ - if (!acpi_ut_valid_acpi_name(target_name)) { - target_name = - acpi_ut_repair_name(ACPI_CAST_PTR(char, &target_name)); - - /* Report warning only if in strict mode or debug mode */ - - if (!acpi_gbl_enable_interpreter_slack) { - ACPI_WARNING((AE_INFO, - "Found bad character(s) in name, repaired: [%4.4s]\n", - ACPI_CAST_PTR(char, &target_name))); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Found bad character(s) in name, repaired: [%4.4s]\n", - ACPI_CAST_PTR(char, &target_name))); - } - } + acpi_ut_repair_name(ACPI_CAST_PTR(char, &target_name)); /* Try to find the name in the namespace level specified by the caller */ @@ -343,6 +328,11 @@ acpi_ns_search_and_enter(u32 target_name, if ((status == AE_OK) && (flags & ACPI_NS_ERROR_IF_FOUND)) { status = AE_ALREADY_EXISTS; } +#ifdef ACPI_ASL_COMPILER + if (*return_node && (*return_node)->type == ACPI_TYPE_ANY) { + (*return_node)->flags |= ANOBJ_IS_EXTERNAL; + } +#endif /* Either found it or there was an error: finished either way */ @@ -391,7 +381,8 @@ acpi_ns_search_and_enter(u32 target_name, /* Node is an object defined by an External() statement */ - if (flags & ACPI_NS_EXTERNAL) { + if (flags & ACPI_NS_EXTERNAL || + (walk_state && walk_state->opcode == AML_SCOPE_OP)) { new_node->flags |= ANOBJ_IS_EXTERNAL; } #endif diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c index a535b7afda5..4a5e3f5c0ff 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,14 +46,11 @@ #include "accommon.h" #include "acnamesp.h" #include "amlcode.h" -#include "actables.h" #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsutils") /* Local prototypes */ -static u8 acpi_ns_valid_path_separator(char sep); - #ifdef ACPI_OBSOLETE_FUNCTIONS acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search); #endif @@ -62,8 +59,8 @@ acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search); * * FUNCTION: acpi_ns_print_node_pathname * - * PARAMETERS: Node - Object - * Message - Prefix message + * PARAMETERS: node - Object + * message - Prefix message * * DESCRIPTION: Print an object's full namespace pathname * Manages allocation/freeing of a pathname buffer @@ -99,45 +96,9 @@ acpi_ns_print_node_pathname(struct acpi_namespace_node *node, /******************************************************************************* * - * FUNCTION: acpi_ns_valid_root_prefix - * - * PARAMETERS: Prefix - Character to be checked - * - * RETURN: TRUE if a valid prefix - * - * DESCRIPTION: Check if a character is a valid ACPI Root prefix - * - ******************************************************************************/ - -u8 acpi_ns_valid_root_prefix(char prefix) -{ - - return ((u8) (prefix == '\\')); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_valid_path_separator - * - * PARAMETERS: Sep - Character to be checked - * - * RETURN: TRUE if a valid path separator - * - * DESCRIPTION: Check if a character is a valid ACPI path separator - * - ******************************************************************************/ - -static u8 acpi_ns_valid_path_separator(char sep) -{ - - return ((u8) (sep == '.')); -} - -/******************************************************************************* - * * FUNCTION: acpi_ns_get_type * - * PARAMETERS: Node - Parent Node to be examined + * PARAMETERS: node - Parent Node to be examined * * RETURN: Type field from Node whose handle is passed * @@ -151,17 +112,17 @@ acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node) if (!node) { ACPI_WARNING((AE_INFO, "Null Node parameter")); - return_UINT32(ACPI_TYPE_ANY); + return_UINT8(ACPI_TYPE_ANY); } - return_UINT32((acpi_object_type) node->type); + return_UINT8(node->type); } /******************************************************************************* * * FUNCTION: acpi_ns_local * - * PARAMETERS: Type - A namespace object type + * PARAMETERS: type - A namespace object type * * RETURN: LOCAL if names must be found locally in objects of the * passed type, 0 if enclosing scopes should be searched @@ -182,14 +143,14 @@ u32 acpi_ns_local(acpi_object_type type) return_UINT32(ACPI_NS_NORMAL); } - return_UINT32((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL); + return_UINT32(acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL); } /******************************************************************************* * * FUNCTION: acpi_ns_get_internal_name_length * - * PARAMETERS: Info - Info struct initialized with the + * PARAMETERS: info - Info struct initialized with the * external name pointer. * * RETURN: None @@ -218,19 +179,19 @@ void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info) * * strlen() + 1 covers the first name_seg, which has no path separator */ - if (acpi_ns_valid_root_prefix(*next_external_char)) { + if (ACPI_IS_ROOT_PREFIX(*next_external_char)) { info->fully_qualified = TRUE; next_external_char++; /* Skip redundant root_prefix, like \\_SB.PCI0.SBRG.EC0 */ - while (acpi_ns_valid_root_prefix(*next_external_char)) { + while (ACPI_IS_ROOT_PREFIX(*next_external_char)) { next_external_char++; } } else { /* Handle Carat prefixes */ - while (*next_external_char == '^') { + while (ACPI_IS_PARENT_PREFIX(*next_external_char)) { info->num_carats++; next_external_char++; } @@ -244,7 +205,7 @@ void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info) if (*next_external_char) { info->num_segments = 1; for (i = 0; next_external_char[i]; i++) { - if (acpi_ns_valid_path_separator(next_external_char[i])) { + if (ACPI_IS_PATH_SEPARATOR(next_external_char[i])) { info->num_segments++; } } @@ -260,7 +221,7 @@ void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info) * * FUNCTION: acpi_ns_build_internal_name * - * PARAMETERS: Info - Info struct fully initialized + * PARAMETERS: info - Info struct fully initialized * * RETURN: Status * @@ -282,7 +243,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) /* Setup the correct prefixes, counts, and pointers */ if (info->fully_qualified) { - internal_name[0] = '\\'; + internal_name[0] = AML_ROOT_PREFIX; if (num_segments <= 1) { result = &internal_name[1]; @@ -302,7 +263,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) i = 0; if (info->num_carats) { for (i = 0; i < info->num_carats; i++) { - internal_name[i] = '^'; + internal_name[i] = AML_PARENT_PREFIX; } } @@ -322,7 +283,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) for (; num_segments; num_segments--) { for (i = 0; i < ACPI_NAME_SIZE; i++) { - if (acpi_ns_valid_path_separator(*external_name) || + if (ACPI_IS_PATH_SEPARATOR(*external_name) || (*external_name == 0)) { /* Pad the segment with underscore(s) if segment is short */ @@ -339,9 +300,9 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) /* Now we must have a path separator, or the pathname is bad */ - if (!acpi_ns_valid_path_separator(*external_name) && + if (!ACPI_IS_PATH_SEPARATOR(*external_name) && (*external_name != 0)) { - return_ACPI_STATUS(AE_BAD_PARAMETER); + return_ACPI_STATUS(AE_BAD_PATHNAME); } /* Move on the next segment */ @@ -371,7 +332,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) * FUNCTION: acpi_ns_internalize_name * * PARAMETERS: *external_name - External representation of name - * **Converted Name - Where to return the resulting + * **Converted name - Where to return the resulting * internal represention of the name * * RETURN: Status @@ -457,13 +418,15 @@ acpi_ns_externalize_name(u32 internal_name_length, /* Check for a prefix (one '\' | one or more '^') */ switch (internal_name[0]) { - case '\\': + case AML_ROOT_PREFIX: + prefix_length = 1; break; - case '^': + case AML_PARENT_PREFIX: + for (i = 0; i < internal_name_length; i++) { - if (internal_name[i] == '^') { + if (ACPI_IS_PARENT_PREFIX(internal_name[i])) { prefix_length = i + 1; } else { break; @@ -477,6 +440,7 @@ acpi_ns_externalize_name(u32 internal_name_length, break; default: + break; } @@ -530,7 +494,7 @@ acpi_ns_externalize_name(u32 internal_name_length, ((num_segments > 0) ? (num_segments - 1) : 0) + 1; /* - * Check to see if we're still in bounds. If not, there's a problem + * Check to see if we're still in bounds. If not, there's a problem * with internal_name (invalid format). */ if (required_length > internal_name_length) { @@ -557,10 +521,14 @@ acpi_ns_externalize_name(u32 internal_name_length, (*converted_name)[j++] = '.'; } - (*converted_name)[j++] = internal_name[names_index++]; - (*converted_name)[j++] = internal_name[names_index++]; - (*converted_name)[j++] = internal_name[names_index++]; - (*converted_name)[j++] = internal_name[names_index++]; + /* Copy and validate the 4-char name segment */ + + ACPI_MOVE_NAME(&(*converted_name)[j], + &internal_name[names_index]); + acpi_ut_repair_name(&(*converted_name)[j]); + + j += ACPI_NAME_SIZE; + names_index += ACPI_NAME_SIZE; } } @@ -575,7 +543,7 @@ acpi_ns_externalize_name(u32 internal_name_length, * * FUNCTION: acpi_ns_validate_handle * - * PARAMETERS: Handle - Handle to be validated and typecast to a + * PARAMETERS: handle - Handle to be validated and typecast to a * namespace node. * * RETURN: A pointer to a namespace node @@ -625,24 +593,26 @@ struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle) void acpi_ns_terminate(void) { - union acpi_operand_object *obj_desc; + acpi_status status; ACPI_FUNCTION_TRACE(ns_terminate); /* - * 1) Free the entire namespace -- all nodes and objects - * - * Delete all object descriptors attached to namepsace nodes + * Free the entire namespace -- all nodes and all objects + * attached to the nodes */ acpi_ns_delete_namespace_subtree(acpi_gbl_root_node); - /* Detach any objects attached to the root */ + /* Delete any objects attached to the root node */ - obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node); - if (obj_desc) { - acpi_ns_detach_object(acpi_gbl_root_node); + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_VOID; } + acpi_ns_delete_node(acpi_gbl_root_node); + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n")); return_VOID; } @@ -651,7 +621,7 @@ void acpi_ns_terminate(void) * * FUNCTION: acpi_ns_opens_scope * - * PARAMETERS: Type - A valid namespace type + * PARAMETERS: type - A valid namespace type * * RETURN: NEWSCOPE if the passed type "opens a name scope" according * to the ACPI specification, else 0 @@ -660,36 +630,36 @@ void acpi_ns_terminate(void) u32 acpi_ns_opens_scope(acpi_object_type type) { - ACPI_FUNCTION_TRACE_STR(ns_opens_scope, acpi_ut_get_type_name(type)); + ACPI_FUNCTION_ENTRY(); - if (!acpi_ut_valid_object_type(type)) { + if (type > ACPI_TYPE_LOCAL_MAX) { /* type code out of range */ ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type)); - return_UINT32(ACPI_NS_NORMAL); + return (ACPI_NS_NORMAL); } - return_UINT32(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE); + return (((u32)acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE); } /******************************************************************************* * * FUNCTION: acpi_ns_get_node * - * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The + * PARAMETERS: *pathname - Name to be found, in external (ASL) format. The * \ (backslash) and ^ (carat) prefixes, and the * . (period) to separate segments are supported. * prefix_node - Root of subtree to be searched, or NS_ALL for the - * root of the name space. If Name is fully + * root of the name space. If Name is fully * qualified (first s8 is '\'), the passed value * of Scope will not be accessed. - * Flags - Used to indicate whether to perform upsearch or + * flags - Used to indicate whether to perform upsearch or * not. * return_node - Where the Node is returned * * DESCRIPTION: Look up a name relative to a given scope and return the - * corresponding Node. NOTE: Scope can be null. + * corresponding Node. NOTE: Scope can be null. * * MUTEX: Locks namespace * @@ -706,6 +676,8 @@ acpi_ns_get_node(struct acpi_namespace_node *prefix_node, ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname)); + /* Simplest case is a null pathname */ + if (!pathname) { *return_node = prefix_node; if (!prefix_node) { @@ -714,6 +686,13 @@ acpi_ns_get_node(struct acpi_namespace_node *prefix_node, return_ACPI_STATUS(AE_OK); } + /* Quick check for a reference to the root */ + + if (ACPI_IS_ROOT_PREFIX(pathname[0]) && (!pathname[1])) { + *return_node = acpi_gbl_root_node; + return_ACPI_STATUS(AE_OK); + } + /* Convert path to internal representation */ status = acpi_ns_internalize_name(pathname, &internal_path); @@ -745,7 +724,7 @@ acpi_ns_get_node(struct acpi_namespace_node *prefix_node, (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - cleanup: +cleanup: ACPI_FREE(internal_path); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/nswalk.c b/drivers/acpi/acpica/nswalk.c index f69895a5489..4758a1f2ce2 100644 --- a/drivers/acpi/acpica/nswalk.c +++ b/drivers/acpi/acpica/nswalk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -60,8 +60,8 @@ ACPI_MODULE_NAME("nswalk") * RETURN: struct acpi_namespace_node - Pointer to the NEXT child or NULL if * none is found. * - * DESCRIPTION: Return the next peer node within the namespace. If Handle - * is valid, Scope is ignored. Otherwise, the first node + * DESCRIPTION: Return the next peer node within the namespace. If Handle + * is valid, Scope is ignored. Otherwise, the first node * within Scope is returned. * ******************************************************************************/ @@ -76,19 +76,19 @@ struct acpi_namespace_node *acpi_ns_get_next_node(struct acpi_namespace_node /* It's really the parent's _scope_ that we want */ - return parent_node->child; + return (parent_node->child); } /* Otherwise just return the next peer */ - return child_node->peer; + return (child_node->peer); } /******************************************************************************* * * FUNCTION: acpi_ns_get_next_node_typed * - * PARAMETERS: Type - Type of node to be searched for + * PARAMETERS: type - Type of node to be searched for * parent_node - Parent node whose children we are * getting * child_node - Previous child that was found. @@ -97,8 +97,8 @@ struct acpi_namespace_node *acpi_ns_get_next_node(struct acpi_namespace_node * RETURN: struct acpi_namespace_node - Pointer to the NEXT child or NULL if * none is found. * - * DESCRIPTION: Return the next peer node within the namespace. If Handle - * is valid, Scope is ignored. Otherwise, the first node + * DESCRIPTION: Return the next peer node within the namespace. If Handle + * is valid, Scope is ignored. Otherwise, the first node * within Scope is returned. * ******************************************************************************/ @@ -151,16 +151,16 @@ struct acpi_namespace_node *acpi_ns_get_next_node_typed(acpi_object_type type, * * FUNCTION: acpi_ns_walk_namespace * - * PARAMETERS: Type - acpi_object_type to search for + * PARAMETERS: type - acpi_object_type to search for * start_node - Handle in namespace where search begins * max_depth - Depth to which search is to reach - * Flags - Whether to unlock the NS before invoking + * flags - Whether to unlock the NS before invoking * the callback routine - * pre_order_visit - Called during tree pre-order visit + * descending_callback - Called during tree descent * when an object of "Type" is found - * post_order_visit - Called during tree post-order visit + * ascending_callback - Called during tree ascent * when an object of "Type" is found - * Context - Passed to user function(s) above + * context - Passed to user function(s) above * return_value - from the user_function if terminated * early. Otherwise, returns NULL. * RETURNS: Status @@ -185,8 +185,8 @@ acpi_ns_walk_namespace(acpi_object_type type, acpi_handle start_node, u32 max_depth, u32 flags, - acpi_walk_callback pre_order_visit, - acpi_walk_callback post_order_visit, + acpi_walk_callback descending_callback, + acpi_walk_callback ascending_callback, void *context, void **return_value) { acpi_status status; @@ -255,22 +255,22 @@ acpi_ns_walk_namespace(acpi_object_type type, } /* - * Invoke the user function, either pre-order or post-order + * Invoke the user function, either descending, ascending, * or both. */ if (!node_previously_visited) { - if (pre_order_visit) { + if (descending_callback) { status = - pre_order_visit(child_node, level, - context, - return_value); + descending_callback(child_node, + level, context, + return_value); } } else { - if (post_order_visit) { + if (ascending_callback) { status = - post_order_visit(child_node, level, - context, - return_value); + ascending_callback(child_node, + level, context, + return_value); } } @@ -305,7 +305,7 @@ acpi_ns_walk_namespace(acpi_object_type type, /* * Depth first search: Attempt to go down another level in the - * namespace if we are allowed to. Don't go any further if we have + * namespace if we are allowed to. Don't go any further if we have * reached the caller specified maximum depth or if the user * function has specified that the maximum depth has been reached. */ diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index 71d15f61807..4bd558bf10d 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,7 +42,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include <linux/export.h> +#define EXPORT_ACPI_INTERFACES + #include <acpi/acpi.h> #include "accommon.h" #include "acnamesp.h" @@ -58,19 +59,19 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info); * * FUNCTION: acpi_evaluate_object_typed * - * PARAMETERS: Handle - Object handle (optional) - * Pathname - Object pathname (optional) + * PARAMETERS: handle - Object handle (optional) + * pathname - Object pathname (optional) * external_params - List of parameters to pass to method, - * terminated by NULL. May be NULL + * terminated by NULL. May be NULL * if no parameters are being passed. * return_buffer - Where to put method's return value (if - * any). If NULL, no value is returned. + * any). If NULL, no value is returned. * return_type - Expected type of return object * * RETURN: Status * * DESCRIPTION: Find and evaluate the given object, passing the given - * parameters if necessary. One of "Handle" or "Pathname" must + * parameters if necessary. One of "Handle" or "Pathname" must * be valid (non-null) * ******************************************************************************/ @@ -83,7 +84,7 @@ acpi_evaluate_object_typed(acpi_handle handle, acpi_object_type return_type) { acpi_status status; - u8 must_free = FALSE; + u8 free_buffer_on_error = FALSE; ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed); @@ -94,14 +95,13 @@ acpi_evaluate_object_typed(acpi_handle handle, } if (return_buffer->length == ACPI_ALLOCATE_BUFFER) { - must_free = TRUE; + free_buffer_on_error = TRUE; } /* Evaluate the object */ - status = - acpi_evaluate_object(handle, pathname, external_params, - return_buffer); + status = acpi_evaluate_object(handle, pathname, + external_params, return_buffer); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -134,11 +134,15 @@ acpi_evaluate_object_typed(acpi_handle handle, pointer)->type), acpi_ut_get_type_name(return_type))); - if (must_free) { - - /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ - - ACPI_FREE(return_buffer->pointer); + if (free_buffer_on_error) { + /* + * Free a buffer created via ACPI_ALLOCATE_BUFFER. + * Note: We use acpi_os_free here because acpi_os_allocate was used + * to allocate the buffer. This purposefully bypasses the + * (optionally enabled) allocation tracking mechanism since we + * only want to track internal allocations. + */ + acpi_os_free(return_buffer->pointer); return_buffer->pointer = NULL; } @@ -152,18 +156,18 @@ ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed) * * FUNCTION: acpi_evaluate_object * - * PARAMETERS: Handle - Object handle (optional) - * Pathname - Object pathname (optional) + * PARAMETERS: handle - Object handle (optional) + * pathname - Object pathname (optional) * external_params - List of parameters to pass to method, - * terminated by NULL. May be NULL + * terminated by NULL. May be NULL * if no parameters are being passed. * return_buffer - Where to put method's return value (if - * any). If NULL, no value is returned. + * any). If NULL, no value is returned. * * RETURN: Status * * DESCRIPTION: Find and evaluate the given object, passing the given - * parameters if necessary. One of "Handle" or "Pathname" must + * parameters if necessary. One of "Handle" or "Pathname" must * be valid (non-null) * ******************************************************************************/ @@ -187,8 +191,6 @@ acpi_evaluate_object(acpi_handle handle, return_ACPI_STATUS(AE_NO_MEMORY); } - info->pathname = pathname; - /* Convert and validate the device handle */ info->prefix_node = acpi_ns_validate_handle(handle); @@ -198,17 +200,64 @@ acpi_evaluate_object(acpi_handle handle, } /* - * If there are parameters to be passed to a control method, the external - * objects must all be converted to internal objects + * Get the actual namespace node for the target object. + * Handles these cases: + * + * 1) Null node, valid pathname from root (absolute path) + * 2) Node and valid pathname (path relative to Node) + * 3) Node, Null pathname + */ + if ((pathname) && (ACPI_IS_ROOT_PREFIX(pathname[0]))) { + + /* The path is fully qualified, just evaluate by name */ + + info->prefix_node = NULL; + } else if (!handle) { + /* + * A handle is optional iff a fully qualified pathname is specified. + * Since we've already handled fully qualified names above, this is + * an error. + */ + if (!pathname) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Both Handle and Pathname are NULL")); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Null Handle with relative pathname [%s]", + pathname)); + } + + status = AE_BAD_PARAMETER; + goto cleanup; + } + + info->relative_pathname = pathname; + + /* + * Convert all external objects passed as arguments to the + * internal version(s). */ if (external_params && external_params->count) { + info->param_count = (u16)external_params->count; + + /* Warn on impossible argument count */ + + if (info->param_count > ACPI_METHOD_NUM_ARGS) { + ACPI_WARN_PREDEFINED((AE_INFO, pathname, + ACPI_WARN_ALWAYS, + "Excess arguments (%u) - using only %u", + info->param_count, + ACPI_METHOD_NUM_ARGS)); + + info->param_count = ACPI_METHOD_NUM_ARGS; + } + /* * Allocate a new parameter block for the internal objects * Add 1 to count to allow for null terminated internal list */ - info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) - external_params-> - count + + info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) info-> + param_count + 1) * sizeof(void *)); if (!info->parameters) { status = AE_NO_MEMORY; @@ -217,7 +266,7 @@ acpi_evaluate_object(acpi_handle handle, /* Convert each external object in the list to an internal object */ - for (i = 0; i < external_params->count; i++) { + for (i = 0; i < info->param_count; i++) { status = acpi_ut_copy_eobject_to_iobject(&external_params-> pointer[i], @@ -227,43 +276,96 @@ acpi_evaluate_object(acpi_handle handle, goto cleanup; } } - info->parameters[external_params->count] = NULL; + + info->parameters[info->param_count] = NULL; } +#if 0 + /* - * Three major cases: - * 1) Fully qualified pathname - * 2) No handle, not fully qualified pathname (error) - * 3) Valid handle + * Begin incoming argument count analysis. Check for too few args + * and too many args. */ - if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) { - /* The path is fully qualified, just evaluate by name */ + switch (acpi_ns_get_type(info->node)) { + case ACPI_TYPE_METHOD: + + /* Check incoming argument count against the method definition */ + + if (info->obj_desc->method.param_count > info->param_count) { + ACPI_ERROR((AE_INFO, + "Insufficient arguments (%u) - %u are required", + info->param_count, + info->obj_desc->method.param_count)); + + status = AE_MISSING_ARGUMENTS; + goto cleanup; + } + + else if (info->obj_desc->method.param_count < info->param_count) { + ACPI_WARNING((AE_INFO, + "Excess arguments (%u) - only %u are required", + info->param_count, + info->obj_desc->method.param_count)); + + /* Just pass the required number of arguments */ + + info->param_count = info->obj_desc->method.param_count; + } - info->prefix_node = NULL; - status = acpi_ns_evaluate(info); - } else if (!handle) { /* - * A handle is optional iff a fully qualified pathname is specified. - * Since we've already handled fully qualified names above, this is - * an error + * Any incoming external objects to be passed as arguments to the + * method must be converted to internal objects */ - if (!pathname) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Both Handle and Pathname are NULL")); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Null Handle with relative pathname [%s]", - pathname)); + if (info->param_count) { + /* + * Allocate a new parameter block for the internal objects + * Add 1 to count to allow for null terminated internal list + */ + info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) + info-> + param_count + + 1) * + sizeof(void *)); + if (!info->parameters) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Convert each external object in the list to an internal object */ + + for (i = 0; i < info->param_count; i++) { + status = + acpi_ut_copy_eobject_to_iobject + (&external_params->pointer[i], + &info->parameters[i]); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + } + + info->parameters[info->param_count] = NULL; } + break; - status = AE_BAD_PARAMETER; - } else { - /* We have a namespace a node and a possible relative path */ + default: - status = acpi_ns_evaluate(info); + /* Warn if arguments passed to an object that is not a method */ + + if (info->param_count) { + ACPI_WARNING((AE_INFO, + "%u arguments were passed to a non-method ACPI object", + info->param_count)); + } + break; } +#endif + + /* Now we can evaluate the object */ + + status = acpi_ns_evaluate(info); + /* * If we are expecting a return value, and all went well above, * copy the return value to an external object. @@ -343,7 +445,7 @@ acpi_evaluate_object(acpi_handle handle, acpi_ex_exit_interpreter(); } - cleanup: +cleanup: /* Free the input parameter list (if we created one) */ @@ -364,7 +466,7 @@ ACPI_EXPORT_SYMBOL(acpi_evaluate_object) * * FUNCTION: acpi_ns_resolve_references * - * PARAMETERS: Info - Evaluation info block + * PARAMETERS: info - Evaluation info block * * RETURN: Info->return_object is replaced with the dereferenced object * @@ -413,6 +515,7 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info) break; default: + return; } @@ -431,14 +534,14 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info) * * FUNCTION: acpi_walk_namespace * - * PARAMETERS: Type - acpi_object_type to search for + * PARAMETERS: type - acpi_object_type to search for * start_object - Handle in namespace where search begins * max_depth - Depth to which search is to reach - * pre_order_visit - Called during tree pre-order visit + * descending_callback - Called during tree descent * when an object of "Type" is found - * post_order_visit - Called during tree post-order visit + * ascending_callback - Called during tree ascent * when an object of "Type" is found - * Context - Passed to user function(s) above + * context - Passed to user function(s) above * return_value - Location where return value of * user_function is put if terminated early * @@ -464,8 +567,8 @@ acpi_status acpi_walk_namespace(acpi_object_type type, acpi_handle start_object, u32 max_depth, - acpi_walk_callback pre_order_visit, - acpi_walk_callback post_order_visit, + acpi_walk_callback descending_callback, + acpi_walk_callback ascending_callback, void *context, void **return_value) { acpi_status status; @@ -475,7 +578,7 @@ acpi_walk_namespace(acpi_object_type type, /* Parameter validation */ if ((type > ACPI_TYPE_LOCAL_MAX) || - (!max_depth) || (!pre_order_visit && !post_order_visit)) { + (!max_depth) || (!descending_callback && !ascending_callback)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -492,7 +595,7 @@ acpi_walk_namespace(acpi_object_type type, */ status = acpi_ut_acquire_read_lock(&acpi_gbl_namespace_rw_lock); if (ACPI_FAILURE(status)) { - return status; + return_ACPI_STATUS(status); } /* @@ -506,14 +609,22 @@ acpi_walk_namespace(acpi_object_type type, goto unlock_and_exit; } + /* Now we can validate the starting node */ + + if (!acpi_ns_validate_handle(start_object)) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit2; + } + status = acpi_ns_walk_namespace(type, start_object, max_depth, - ACPI_NS_WALK_UNLOCK, pre_order_visit, - post_order_visit, context, - return_value); + ACPI_NS_WALK_UNLOCK, + descending_callback, ascending_callback, + context, return_value); +unlock_and_exit2: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_read_lock(&acpi_gbl_namespace_rw_lock); return_ACPI_STATUS(status); } @@ -542,8 +653,8 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, acpi_status status; struct acpi_namespace_node *node; u32 flags; - struct acpica_device_id *hid; - struct acpica_device_id_list *cid; + struct acpi_pnp_device_id *hid; + struct acpi_pnp_device_id_list *cid; u32 i; u8 found; int no_match; @@ -602,17 +713,22 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, /* Walk the CID list */ - found = 0; + found = FALSE; for (i = 0; i < cid->count; i++) { if (ACPI_STRCMP(cid->ids[i].string, info->hid) == 0) { - found = 1; + + /* Found a matching CID */ + + found = TRUE; break; } } + ACPI_FREE(cid); - if (!found) + if (!found) { return (AE_OK); + } } } @@ -646,7 +762,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, * * PARAMETERS: HID - HID to search for. Can be NULL. * user_function - Called when a matching object is found - * Context - Passed to user function + * context - Passed to user function * return_value - Location where return value of * user_function is put if terminated early * @@ -656,7 +772,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, * starting (and ending) at the object specified by start_handle. * The user_function is called whenever an object of type - * Device is found. If the user function returns + * Device is found. If the user function returns * a non-zero value, the search is terminated immediately and this * value is returned to the caller. * @@ -716,8 +832,8 @@ ACPI_EXPORT_SYMBOL(acpi_get_devices) * FUNCTION: acpi_attach_data * * PARAMETERS: obj_handle - Namespace node - * Handler - Handler for this attachment - * Data - Pointer to data to be attached + * handler - Handler for this attachment + * data - Pointer to data to be attached * * RETURN: Status * @@ -752,7 +868,7 @@ acpi_attach_data(acpi_handle obj_handle, status = acpi_ns_attach_data(node, handler, data); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); } @@ -764,7 +880,7 @@ ACPI_EXPORT_SYMBOL(acpi_attach_data) * FUNCTION: acpi_detach_data * * PARAMETERS: obj_handle - Namespace node handle - * Handler - Handler used in call to acpi_attach_data + * handler - Handler used in call to acpi_attach_data * * RETURN: Status * @@ -798,7 +914,7 @@ acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler) status = acpi_ns_detach_data(node, handler); - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); } @@ -807,19 +923,22 @@ ACPI_EXPORT_SYMBOL(acpi_detach_data) /******************************************************************************* * - * FUNCTION: acpi_get_data + * FUNCTION: acpi_get_data_full * * PARAMETERS: obj_handle - Namespace node - * Handler - Handler used in call to attach_data - * Data - Where the data is returned + * handler - Handler used in call to attach_data + * data - Where the data is returned + * callback - function to execute before returning * * RETURN: Status * - * DESCRIPTION: Retrieve data that was previously attached to a namespace node. + * DESCRIPTION: Retrieve data that was previously attached to a namespace node + * and execute a callback before returning. * ******************************************************************************/ acpi_status -acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) +acpi_get_data_full(acpi_handle obj_handle, acpi_object_handler handler, + void **data, void (*callback)(void *)) { struct acpi_namespace_node *node; acpi_status status; @@ -844,10 +963,34 @@ acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) } status = acpi_ns_get_attached_data(node, handler, data); + if (ACPI_SUCCESS(status) && callback) { + callback(*data); + } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); } +ACPI_EXPORT_SYMBOL(acpi_get_data_full) + +/******************************************************************************* + * + * FUNCTION: acpi_get_data + * + * PARAMETERS: obj_handle - Namespace node + * handler - Handler used in call to attach_data + * data - Where the data is returned + * + * RETURN: Status + * + * DESCRIPTION: Retrieve data that was previously attached to a namespace node. + * + ******************************************************************************/ +acpi_status +acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) +{ + return acpi_get_data_full(obj_handle, handler, data, NULL); +} + ACPI_EXPORT_SYMBOL(acpi_get_data) diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c index af401c9c4df..8c6c11ce976 100644 --- a/drivers/acpi/acpica/nsxfname.c +++ b/drivers/acpi/acpica/nsxfname.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,7 +42,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include <linux/export.h> +#define EXPORT_ACPI_INTERFACES + #include <acpi/acpi.h> #include "accommon.h" #include "acnamesp.h" @@ -53,24 +54,24 @@ ACPI_MODULE_NAME("nsxfname") /* Local prototypes */ -static char *acpi_ns_copy_device_id(struct acpica_device_id *dest, - struct acpica_device_id *source, +static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest, + struct acpi_pnp_device_id *source, char *string_area); /****************************************************************************** * * FUNCTION: acpi_get_handle * - * PARAMETERS: Parent - Object to search under (search scope). - * Pathname - Pointer to an asciiz string containing the + * PARAMETERS: parent - Object to search under (search scope). + * pathname - Pointer to an asciiz string containing the * name * ret_handle - Where the return handle is returned * * RETURN: Status * * DESCRIPTION: This routine will search for a caller specified name in the - * name space. The caller can restrict the search region by - * specifying a non NULL parent. The parent value is itself a + * name space. The caller can restrict the search region by + * specifying a non NULL parent. The parent value is itself a * namespace handle. * ******************************************************************************/ @@ -107,7 +108,7 @@ acpi_get_handle(acpi_handle parent, * * Error for <null Parent + relative path> */ - if (acpi_ns_valid_root_prefix(pathname[0])) { + if (ACPI_IS_ROOT_PREFIX(pathname[0])) { /* Pathname is fully qualified (starts with '\') */ @@ -142,14 +143,14 @@ ACPI_EXPORT_SYMBOL(acpi_get_handle) * * FUNCTION: acpi_get_name * - * PARAMETERS: Handle - Handle to be converted to a pathname + * PARAMETERS: handle - Handle to be converted to a pathname * name_type - Full pathname or single segment - * Buffer - Buffer for returned path + * buffer - Buffer for returned path * * RETURN: Pointer to a string containing the fully qualified Name. * * DESCRIPTION: This routine returns the fully qualified name associated with - * the Handle parameter. This and the acpi_pathname_to_handle are + * the Handle parameter. This and the acpi_pathname_to_handle are * complementary functions. * ******************************************************************************/ @@ -158,6 +159,7 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer) { acpi_status status; struct acpi_namespace_node *node; + char *node_name; /* Parameter validation */ @@ -202,12 +204,12 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer) /* Just copy the ACPI name from the Node and zero terminate it */ - ACPI_STRNCPY(buffer->pointer, acpi_ut_get_node_name(node), - ACPI_NAME_SIZE); + node_name = acpi_ut_get_node_name(node); + ACPI_MOVE_NAME(buffer->pointer, node_name); ((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0; status = AE_OK; - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); @@ -219,20 +221,21 @@ ACPI_EXPORT_SYMBOL(acpi_get_name) * * FUNCTION: acpi_ns_copy_device_id * - * PARAMETERS: Dest - Pointer to the destination DEVICE_ID - * Source - Pointer to the source DEVICE_ID + * PARAMETERS: dest - Pointer to the destination PNP_DEVICE_ID + * source - Pointer to the source PNP_DEVICE_ID * string_area - Pointer to where to copy the dest string * * RETURN: Pointer to the next string area * - * DESCRIPTION: Copy a single DEVICE_ID, including the string data. + * DESCRIPTION: Copy a single PNP_DEVICE_ID, including the string data. * ******************************************************************************/ -static char *acpi_ns_copy_device_id(struct acpica_device_id *dest, - struct acpica_device_id *source, +static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest, + struct acpi_pnp_device_id *source, char *string_area) { - /* Create the destination DEVICE_ID */ + + /* Create the destination PNP_DEVICE_ID */ dest->string = string_area; dest->length = source->length; @@ -247,7 +250,7 @@ static char *acpi_ns_copy_device_id(struct acpica_device_id *dest, * * FUNCTION: acpi_get_object_info * - * PARAMETERS: Handle - Object Handle + * PARAMETERS: handle - Object Handle * return_buffer - Where the info is returned * * RETURN: Status @@ -256,8 +259,8 @@ static char *acpi_ns_copy_device_id(struct acpica_device_id *dest, * namespace node and possibly by running several standard * control methods (Such as in the case of a device.) * - * For Device and Processor objects, run the Device _HID, _UID, _CID, _STA, - * _ADR, _sx_w, and _sx_d methods. + * For Device and Processor objects, run the Device _HID, _UID, _CID, _SUB, + * _STA, _ADR, _sx_w, and _sx_d methods. * * Note: Allocates the return buffer, must be freed by the caller. * @@ -269,9 +272,10 @@ acpi_get_object_info(acpi_handle handle, { struct acpi_namespace_node *node; struct acpi_device_info *info; - struct acpica_device_id_list *cid_list = NULL; - struct acpica_device_id *hid = NULL; - struct acpica_device_id *uid = NULL; + struct acpi_pnp_device_id_list *cid_list = NULL; + struct acpi_pnp_device_id *hid = NULL; + struct acpi_pnp_device_id *uid = NULL; + struct acpi_pnp_device_id *sub = NULL; char *next_id_string; acpi_object_type type; acpi_name name; @@ -289,7 +293,7 @@ acpi_get_object_info(acpi_handle handle, status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { - goto cleanup; + return (status); } node = acpi_ns_validate_handle(handle); @@ -316,7 +320,7 @@ acpi_get_object_info(acpi_handle handle, if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) { /* * Get extra info for ACPI Device/Processor objects only: - * Run the Device _HID, _UID, and _CID methods. + * Run the Device _HID, _UID, _SUB, and _CID methods. * * Note: none of these methods are required, so they may or may * not be present for this device. The Info->Valid bitfield is used @@ -339,6 +343,14 @@ acpi_get_object_info(acpi_handle handle, valid |= ACPI_VALID_UID; } + /* Execute the Device._SUB method */ + + status = acpi_ut_execute_SUB(node, &sub); + if (ACPI_SUCCESS(status)) { + info_size += sub->length; + valid |= ACPI_VALID_SUB; + } + /* Execute the Device._CID method */ status = acpi_ut_execute_CID(node, &cid_list); @@ -348,7 +360,7 @@ acpi_get_object_info(acpi_handle handle, info_size += (cid_list->list_size - - sizeof(struct acpica_device_id_list)); + sizeof(struct acpi_pnp_device_id_list)); valid |= ACPI_VALID_CID; } } @@ -370,9 +382,14 @@ acpi_get_object_info(acpi_handle handle, * Get extra info for ACPI Device/Processor objects only: * Run the _STA, _ADR and, sx_w, and _sx_d methods. * - * Note: none of these methods are required, so they may or may + * Notes: none of these methods are required, so they may or may * not be present for this device. The Info->Valid bitfield is used * to indicate which methods were found and run successfully. + * + * For _STA, if the method does not exist, then (as per the ACPI + * specification), the returned current_status flags will indicate + * that the device is present/functional/enabled. Otherwise, the + * current_status flags reflect the value returned from _STA. */ /* Execute the Device._STA method */ @@ -418,16 +435,17 @@ acpi_get_object_info(acpi_handle handle, next_id_string = ACPI_CAST_PTR(char, info->compatible_id_list.ids); if (cid_list) { - /* Point past the CID DEVICE_ID array */ + /* Point past the CID PNP_DEVICE_ID array */ next_id_string += ((acpi_size) cid_list->count * - sizeof(struct acpica_device_id)); + sizeof(struct acpi_pnp_device_id)); } /* - * Copy the HID, UID, and CIDs to the return buffer. The variable-length - * strings are copied to the reserved area at the end of the buffer. + * Copy the HID, UID, SUB, and CIDs to the return buffer. + * The variable-length strings are copied to the reserved area + * at the end of the buffer. * * For HID and CID, check if the ID is a PCI Root Bridge. */ @@ -445,6 +463,11 @@ acpi_get_object_info(acpi_handle handle, uid, next_id_string); } + if (sub) { + next_id_string = acpi_ns_copy_device_id(&info->subsystem_id, + sub, next_id_string); + } + if (cid_list) { info->compatible_id_list.count = cid_list->count; info->compatible_id_list.list_size = cid_list->list_size; @@ -474,13 +497,16 @@ acpi_get_object_info(acpi_handle handle, *return_buffer = info; status = AE_OK; - cleanup: +cleanup: if (hid) { ACPI_FREE(hid); } if (uid) { ACPI_FREE(uid); } + if (sub) { + ACPI_FREE(sub); + } if (cid_list) { ACPI_FREE(cid_list); } @@ -493,7 +519,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_object_info) * * FUNCTION: acpi_install_method * - * PARAMETERS: Buffer - An ACPI table containing one control method + * PARAMETERS: buffer - An ACPI table containing one control method * * RETURN: Status * @@ -521,14 +547,14 @@ acpi_status acpi_install_method(u8 *buffer) /* Parameter validation */ if (!buffer) { - return AE_BAD_PARAMETER; + return (AE_BAD_PARAMETER); } /* Table must be a DSDT or SSDT */ if (!ACPI_COMPARE_NAME(table->signature, ACPI_SIG_DSDT) && !ACPI_COMPARE_NAME(table->signature, ACPI_SIG_SSDT)) { - return AE_BAD_HEADER; + return (AE_BAD_HEADER); } /* First AML opcode in the table must be a control method */ @@ -536,7 +562,7 @@ acpi_status acpi_install_method(u8 *buffer) parser_state.aml = buffer + sizeof(struct acpi_table_header); opcode = acpi_ps_peek_opcode(&parser_state); if (opcode != AML_METHOD_OP) { - return AE_BAD_PARAMETER; + return (AE_BAD_PARAMETER); } /* Extract method information from the raw AML */ @@ -554,13 +580,13 @@ acpi_status acpi_install_method(u8 *buffer) */ aml_buffer = ACPI_ALLOCATE(aml_length); if (!aml_buffer) { - return AE_NO_MEMORY; + return (AE_NO_MEMORY); } method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD); if (!method_obj) { ACPI_FREE(aml_buffer); - return AE_NO_MEMORY; + return (AE_NO_MEMORY); } /* Lock namespace for acpi_ns_lookup, we may be creating a new node */ @@ -626,12 +652,12 @@ acpi_status acpi_install_method(u8 *buffer) /* Remove local reference to the method object */ acpi_ut_remove_reference(method_obj); - return status; + return (status); error_exit: ACPI_FREE(aml_buffer); ACPI_FREE(method_obj); - return status; + return (status); } ACPI_EXPORT_SYMBOL(acpi_install_method) diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c index 880a605cee2..dae9401be7a 100644 --- a/drivers/acpi/acpica/nsxfobj.c +++ b/drivers/acpi/acpica/nsxfobj.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,7 +42,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include <linux/export.h> +#define EXPORT_ACPI_INTERFACES + #include <acpi/acpi.h> #include "accommon.h" #include "acnamesp.h" @@ -98,7 +99,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_id) * * FUNCTION: acpi_get_type * - * PARAMETERS: Handle - Handle of object whose type is desired + * PARAMETERS: handle - Handle of object whose type is desired * ret_type - Where the type will be placed * * RETURN: Status @@ -151,7 +152,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_type) * * FUNCTION: acpi_get_parent * - * PARAMETERS: Handle - Handle of object whose parent is desired + * PARAMETERS: handle - Handle of object whose parent is desired * ret_handle - Where the parent handle will be placed * * RETURN: Status @@ -200,7 +201,7 @@ acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle) status = AE_NULL_ENTRY; } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); @@ -212,16 +213,16 @@ ACPI_EXPORT_SYMBOL(acpi_get_parent) * * FUNCTION: acpi_get_next_object * - * PARAMETERS: Type - Type of object to be searched for - * Parent - Parent object whose children we are getting + * PARAMETERS: type - Type of object to be searched for + * parent - Parent object whose children we are getting * last_child - Previous child that was found. * The NEXT child will be returned * ret_handle - Where handle to the next object is placed * * RETURN: Status * - * DESCRIPTION: Return the next peer object within the namespace. If Handle is - * valid, Scope is ignored. Otherwise, the first object within + * DESCRIPTION: Return the next peer object within the namespace. If Handle is + * valid, Scope is ignored. Otherwise, the first object within * Scope is returned. * ******************************************************************************/ @@ -280,7 +281,7 @@ acpi_get_next_object(acpi_object_type type, *ret_handle = ACPI_CAST_PTR(acpi_handle, node); } - unlock_and_exit: +unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c index 5ac36aba507..314d314340a 100644 --- a/drivers/acpi/acpica/psargs.c +++ b/drivers/acpi/acpica/psargs.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -120,7 +120,7 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state) * RETURN: Pointer to end-of-package +1 * * DESCRIPTION: Get next package length and return a pointer past the end of - * the package. Consumes the package length field + * the package. Consumes the package length field * ******************************************************************************/ @@ -147,8 +147,8 @@ u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state) * RETURN: Pointer to the start of the name string (pointer points into * the AML. * - * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name - * prefix characters. Set parser state to point past the string. + * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name + * prefix characters. Set parser state to point past the string. * (Name is consumed from the AML.) * ******************************************************************************/ @@ -162,7 +162,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) /* Point past any namestring prefix characters (backslash or carat) */ - while (acpi_ps_is_prefix_char(*end)) { + while (ACPI_IS_ROOT_PREFIX(*end) || ACPI_IS_PARENT_PREFIX(*end)) { end++; } @@ -210,7 +210,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) * FUNCTION: acpi_ps_get_next_namepath * * PARAMETERS: parser_state - Current parser state object - * Arg - Where the namepath will be stored + * arg - Where the namepath will be stored * arg_count - If the namepath points to a control method * the method's argument is returned here. * possible_method_call - Whether the namepath can possibly be the @@ -220,7 +220,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) * * DESCRIPTION: Get next name (if method call, return # of required args). * Names are looked up in the internal namespace to determine - * if the name represents a control method. If a method + * if the name represents a control method. If a method * is found, the number of arguments to the method is returned. * This information is critical for parsing to continue correctly. * @@ -379,7 +379,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, * * PARAMETERS: parser_state - Current parser state object * arg_type - The argument type (AML_*_ARG) - * Arg - Where the argument is returned + * arg - Where the argument is returned * * RETURN: None * @@ -618,6 +618,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP); if (!arg) { + acpi_ps_free_op(field); return_PTR(NULL); } @@ -628,24 +629,28 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state switch (opcode) { case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ + buffer_length = ACPI_GET8(parser_state->aml); parser_state->aml += 1; break; case AML_WORD_OP: /* AML_WORDDATA_ARG */ + buffer_length = ACPI_GET16(parser_state->aml); parser_state->aml += 2; break; case AML_DWORD_OP: /* AML_DWORDATA_ARG */ + buffer_length = ACPI_GET32(parser_state->aml); parser_state->aml += 4; break; default: + buffer_length = 0; break; } @@ -662,6 +667,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state } else { arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP); if (!arg) { + acpi_ps_free_op(field); return_PTR(NULL); } @@ -796,7 +802,8 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, subop = acpi_ps_peek_opcode(parser_state); if (subop == 0 || acpi_ps_is_leading_char(subop) || - acpi_ps_is_prefix_char(subop)) { + ACPI_IS_ROOT_PREFIX(subop) || + ACPI_IS_PARENT_PREFIX(subop)) { /* null_name or name_string */ diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c index 9547ad8a620..b058e2390fd 100644 --- a/drivers/acpi/acpica/psloop.c +++ b/drivers/acpi/acpica/psloop.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,329 +58,22 @@ #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME("psloop") -static u32 acpi_gbl_depth = 0; - /* Local prototypes */ - -static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state); - -static acpi_status -acpi_ps_build_named_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, - union acpi_parse_object *unnamed_op, - union acpi_parse_object **op); - -static acpi_status -acpi_ps_create_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, union acpi_parse_object **new_op); - static acpi_status acpi_ps_get_arguments(struct acpi_walk_state *walk_state, u8 * aml_op_start, union acpi_parse_object *op); -static acpi_status -acpi_ps_complete_op(struct acpi_walk_state *walk_state, - union acpi_parse_object **op, acpi_status status); - -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(union acpi_parse_object *parent_op, u8 *aml_start, u32 aml_length, acpi_owner_id owner_id); /******************************************************************************* * - * FUNCTION: acpi_ps_get_aml_opcode - * - * PARAMETERS: walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Extract the next AML opcode from the input stream. - * - ******************************************************************************/ - -static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state) -{ - - ACPI_FUNCTION_TRACE_PTR(ps_get_aml_opcode, walk_state); - - walk_state->aml_offset = - (u32) ACPI_PTR_DIFF(walk_state->parser_state.aml, - walk_state->parser_state.aml_start); - walk_state->opcode = acpi_ps_peek_opcode(&(walk_state->parser_state)); - - /* - * First cut to determine what we have found: - * 1) A valid AML opcode - * 2) A name string - * 3) An unknown/invalid opcode - */ - walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); - - switch (walk_state->op_info->class) { - case AML_CLASS_ASCII: - case AML_CLASS_PREFIX: - /* - * Starts with a valid prefix or ASCII char, this is a name - * string. Convert the bare name string to a namepath. - */ - walk_state->opcode = AML_INT_NAMEPATH_OP; - walk_state->arg_types = ARGP_NAMESTRING; - break; - - case AML_CLASS_UNKNOWN: - - /* The opcode is unrecognized. Just skip unknown opcodes */ - - ACPI_ERROR((AE_INFO, - "Found unknown opcode 0x%X at AML address %p offset 0x%X, ignoring", - walk_state->opcode, walk_state->parser_state.aml, - walk_state->aml_offset)); - - ACPI_DUMP_BUFFER(walk_state->parser_state.aml, 128); - - /* Assume one-byte bad opcode */ - - walk_state->parser_state.aml++; - return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); - - default: - - /* Found opcode info, this is a normal opcode */ - - walk_state->parser_state.aml += - acpi_ps_get_opcode_size(walk_state->opcode); - walk_state->arg_types = walk_state->op_info->parse_args; - break; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_build_named_op - * - * PARAMETERS: walk_state - Current state - * aml_op_start - Begin of named Op in AML - * unnamed_op - Early Op (not a named Op) - * Op - Returned Op - * - * RETURN: Status - * - * DESCRIPTION: Parse a named Op - * - ******************************************************************************/ - -static acpi_status -acpi_ps_build_named_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, - union acpi_parse_object *unnamed_op, - union acpi_parse_object **op) -{ - acpi_status status = AE_OK; - union acpi_parse_object *arg = NULL; - - ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state); - - unnamed_op->common.value.arg = NULL; - unnamed_op->common.arg_list_length = 0; - unnamed_op->common.aml_opcode = walk_state->opcode; - - /* - * Get and append arguments until we find the node that contains - * the name (the type ARGP_NAME). - */ - while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) && - (GET_CURRENT_ARG_TYPE(walk_state->arg_types) != ARGP_NAME)) { - status = - acpi_ps_get_next_arg(walk_state, - &(walk_state->parser_state), - GET_CURRENT_ARG_TYPE(walk_state-> - arg_types), &arg); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - acpi_ps_append_arg(unnamed_op, arg); - INCREMENT_ARG_LIST(walk_state->arg_types); - } - - /* - * Make sure that we found a NAME and didn't run out of arguments - */ - if (!GET_CURRENT_ARG_TYPE(walk_state->arg_types)) { - return_ACPI_STATUS(AE_AML_NO_OPERAND); - } - - /* We know that this arg is a name, move to next arg */ - - INCREMENT_ARG_LIST(walk_state->arg_types); - - /* - * Find the object. This will either insert the object into - * the namespace or simply look it up - */ - walk_state->op = NULL; - - status = walk_state->descending_callback(walk_state, op); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During name lookup/catalog")); - return_ACPI_STATUS(status); - } - - if (!*op) { - return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); - } - - status = acpi_ps_next_parse_state(walk_state, *op, status); - if (ACPI_FAILURE(status)) { - if (status == AE_CTRL_PENDING) { - return_ACPI_STATUS(AE_CTRL_PARSE_PENDING); - } - return_ACPI_STATUS(status); - } - - acpi_ps_append_arg(*op, unnamed_op->common.value.arg); - acpi_gbl_depth++; - - if ((*op)->common.aml_opcode == AML_REGION_OP || - (*op)->common.aml_opcode == AML_DATA_REGION_OP) { - /* - * Defer final parsing of an operation_region body, because we don't - * have enough info in the first pass to parse it correctly (i.e., - * there may be method calls within the term_arg elements of the body.) - * - * However, we must continue parsing because the opregion is not a - * standalone package -- we don't know where the end is at this point. - * - * (Length is unknown until parse of the body complete) - */ - (*op)->named.data = aml_op_start; - (*op)->named.length = 0; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_create_op - * - * PARAMETERS: walk_state - Current state - * aml_op_start - Op start in AML - * new_op - Returned Op - * - * RETURN: Status - * - * DESCRIPTION: Get Op from AML - * - ******************************************************************************/ - -static acpi_status -acpi_ps_create_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, union acpi_parse_object **new_op) -{ - acpi_status status = AE_OK; - union acpi_parse_object *op; - union acpi_parse_object *named_op = NULL; - union acpi_parse_object *parent_scope; - u8 argument_count; - const struct acpi_opcode_info *op_info; - - ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state); - - status = acpi_ps_get_aml_opcode(walk_state); - if (status == AE_CTRL_PARSE_CONTINUE) { - return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); - } - - /* Create Op structure and append to parent's argument list */ - - walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); - op = acpi_ps_alloc_op(walk_state->opcode); - if (!op) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - if (walk_state->op_info->flags & AML_NAMED) { - status = - acpi_ps_build_named_op(walk_state, aml_op_start, op, - &named_op); - acpi_ps_free_op(op); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - *new_op = named_op; - return_ACPI_STATUS(AE_OK); - } - - /* Not a named opcode, just allocate Op and append to parent */ - - if (walk_state->op_info->flags & AML_CREATE) { - /* - * Backup to beginning of create_xXXfield declaration - * body_length is unknown until we parse the body - */ - op->named.data = aml_op_start; - op->named.length = 0; - } - - if (walk_state->opcode == AML_BANK_FIELD_OP) { - /* - * Backup to beginning of bank_field declaration - * body_length is unknown until we parse the body - */ - op->named.data = aml_op_start; - op->named.length = 0; - } - - parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state)); - acpi_ps_append_arg(parent_scope, op); - - if (parent_scope) { - op_info = - acpi_ps_get_opcode_info(parent_scope->common.aml_opcode); - if (op_info->flags & AML_HAS_TARGET) { - argument_count = - acpi_ps_get_argument_count(op_info->type); - if (parent_scope->common.arg_list_length > - argument_count) { - op->common.flags |= ACPI_PARSEOP_TARGET; - } - } else if (parent_scope->common.aml_opcode == AML_INCREMENT_OP) { - op->common.flags |= ACPI_PARSEOP_TARGET; - } - } - - if (walk_state->descending_callback != NULL) { - /* - * Find the object. This will either insert the object into - * the namespace or simply look it up - */ - walk_state->op = *new_op = op; - - status = walk_state->descending_callback(walk_state, &op); - status = acpi_ps_next_parse_state(walk_state, op, status); - if (status == AE_CTRL_PENDING) { - status = AE_CTRL_PARSE_PENDING; - } - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * * FUNCTION: acpi_ps_get_arguments * * PARAMETERS: walk_state - Current state * aml_op_start - Op start in AML - * Op - Current Op + * op - Current Op * * RETURN: Status * @@ -471,7 +164,6 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, case AML_IF_OP: case AML_ELSE_OP: case AML_WHILE_OP: - /* * Currently supported module-level opcodes are: * IF/ELSE/WHILE. These appear to be the most common, @@ -519,11 +211,18 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, 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)))); + "Unsupported module-level executable opcode " + "0x%.2X at table offset 0x%.4X", + op->common. + aml_opcode, + (u32) + (ACPI_PTR_DIFF + (aml_op_start, + walk_state-> + parser_state. + aml_start) + + sizeof(struct + acpi_table_header)))); } } break; @@ -589,6 +288,7 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, default: /* No action for all other opcodes */ + break; } @@ -676,290 +376,6 @@ acpi_ps_link_module_code(union acpi_parse_object *parent_op, /******************************************************************************* * - * FUNCTION: acpi_ps_complete_op - * - * PARAMETERS: walk_state - Current state - * Op - Returned Op - * Status - Parse status before complete Op - * - * RETURN: Status - * - * DESCRIPTION: Complete Op - * - ******************************************************************************/ - -static acpi_status -acpi_ps_complete_op(struct acpi_walk_state *walk_state, - union acpi_parse_object **op, acpi_status status) -{ - acpi_status status2; - - ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state); - - /* - * Finished one argument of the containing scope - */ - walk_state->parser_state.scope->parse_scope.arg_count--; - - /* Close this Op (will result in parse subtree deletion) */ - - status2 = acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - - *op = NULL; - - switch (status) { - case AE_OK: - break; - - case AE_CTRL_TRANSFER: - - /* We are about to transfer to a called method */ - - walk_state->prev_op = NULL; - walk_state->prev_arg_types = walk_state->arg_types; - return_ACPI_STATUS(status); - - case AE_CTRL_END: - - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - - if (*op) { - walk_state->op = *op; - walk_state->op_info = - acpi_ps_get_opcode_info((*op)->common.aml_opcode); - walk_state->opcode = (*op)->common.aml_opcode; - - status = walk_state->ascending_callback(walk_state); - status = - acpi_ps_next_parse_state(walk_state, *op, status); - - status2 = acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - } - - status = AE_OK; - break; - - case AE_CTRL_BREAK: - case AE_CTRL_CONTINUE: - - /* Pop off scopes until we find the While */ - - while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) { - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - } - - /* Close this iteration of the While loop */ - - walk_state->op = *op; - walk_state->op_info = - acpi_ps_get_opcode_info((*op)->common.aml_opcode); - walk_state->opcode = (*op)->common.aml_opcode; - - status = walk_state->ascending_callback(walk_state); - status = acpi_ps_next_parse_state(walk_state, *op, status); - - status2 = acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - - status = AE_OK; - break; - - case AE_CTRL_TERMINATE: - - /* Clean up */ - do { - if (*op) { - status2 = - acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - - acpi_ut_delete_generic_state - (acpi_ut_pop_generic_state - (&walk_state->control_state)); - } - - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - - } while (*op); - - return_ACPI_STATUS(AE_OK); - - default: /* All other non-AE_OK status */ - - do { - if (*op) { - status2 = - acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - } - - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - - } while (*op); - -#if 0 - /* - * TBD: Cleanup parse ops on error - */ - if (*op == NULL) { - acpi_ps_pop_scope(parser_state, op, - &walk_state->arg_types, - &walk_state->arg_count); - } -#endif - walk_state->prev_op = NULL; - walk_state->prev_arg_types = walk_state->arg_types; - return_ACPI_STATUS(status); - } - - /* This scope complete? */ - - if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) { - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op)); - } else { - *op = NULL; - } - - ACPI_PREEMPTION_POINT(); - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_complete_final_op - * - * PARAMETERS: walk_state - Current state - * Op - Current Op - * Status - Current parse status before complete last - * Op - * - * RETURN: Status - * - * DESCRIPTION: Complete last Op. - * - ******************************************************************************/ - -static acpi_status -acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, - union acpi_parse_object *op, acpi_status status) -{ - acpi_status status2; - - ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state); - - /* - * Complete the last Op (if not completed), and clear the scope stack. - * It is easily possible to end an AML "package" with an unbounded number - * of open scopes (such as when several ASL blocks are closed with - * sequential closing braces). We want to terminate each one cleanly. - */ - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n", - op)); - do { - if (op) { - if (walk_state->ascending_callback != NULL) { - walk_state->op = op; - walk_state->op_info = - acpi_ps_get_opcode_info(op->common. - aml_opcode); - walk_state->opcode = op->common.aml_opcode; - - status = - walk_state->ascending_callback(walk_state); - status = - acpi_ps_next_parse_state(walk_state, op, - status); - if (status == AE_CTRL_PENDING) { - status = - acpi_ps_complete_op(walk_state, &op, - AE_OK); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - if (status == AE_CTRL_TERMINATE) { - status = AE_OK; - - /* Clean up */ - do { - if (op) { - status2 = - acpi_ps_complete_this_op - (walk_state, op); - if (ACPI_FAILURE - (status2)) { - return_ACPI_STATUS - (status2); - } - } - - acpi_ps_pop_scope(& - (walk_state-> - parser_state), - &op, - &walk_state-> - arg_types, - &walk_state-> - arg_count); - - } while (op); - - return_ACPI_STATUS(status); - } - - else if (ACPI_FAILURE(status)) { - - /* First error is most important */ - - (void) - acpi_ps_complete_this_op(walk_state, - op); - return_ACPI_STATUS(status); - } - } - - status2 = acpi_ps_complete_this_op(walk_state, op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - } - - acpi_ps_pop_scope(&(walk_state->parser_state), &op, - &walk_state->arg_types, - &walk_state->arg_count); - - } while (op); - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * * FUNCTION: acpi_ps_parse_loop * * PARAMETERS: walk_state - Current state @@ -1064,6 +480,10 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) status = AE_OK; } + if (status == AE_CTRL_TERMINATE) { + return_ACPI_STATUS(status); + } + status = acpi_ps_complete_op(walk_state, &op, status); @@ -1144,10 +564,6 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) walk_state->op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); if (walk_state->op_info->flags & AML_NAMED) { - if (acpi_gbl_depth) { - acpi_gbl_depth--; - } - if (op->common.aml_opcode == AML_REGION_OP || op->common.aml_opcode == AML_DATA_REGION_OP) { /* @@ -1165,7 +581,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) if (walk_state->op_info->flags & AML_CREATE) { /* - * Backup to beginning of create_xXXfield declaration (1 for + * Backup to beginning of create_XXXfield declaration (1 for * Opcode) * * body_length is unknown until we parse the body diff --git a/drivers/acpi/acpica/psobject.c b/drivers/acpi/acpica/psobject.c new file mode 100644 index 00000000000..a6885077d59 --- /dev/null +++ b/drivers/acpi/acpica/psobject.c @@ -0,0 +1,651 @@ +/****************************************************************************** + * + * Module Name: psobject - Support for parse objects + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_PARSER +ACPI_MODULE_NAME("psobject") + +/* Local prototypes */ +static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state); + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_aml_opcode + * + * PARAMETERS: walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Extract the next AML opcode from the input stream. + * + ******************************************************************************/ + +static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state) +{ + + ACPI_FUNCTION_TRACE_PTR(ps_get_aml_opcode, walk_state); + + walk_state->aml_offset = + (u32)ACPI_PTR_DIFF(walk_state->parser_state.aml, + walk_state->parser_state.aml_start); + walk_state->opcode = acpi_ps_peek_opcode(&(walk_state->parser_state)); + + /* + * First cut to determine what we have found: + * 1) A valid AML opcode + * 2) A name string + * 3) An unknown/invalid opcode + */ + walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); + + switch (walk_state->op_info->class) { + case AML_CLASS_ASCII: + case AML_CLASS_PREFIX: + /* + * Starts with a valid prefix or ASCII char, this is a name + * string. Convert the bare name string to a namepath. + */ + walk_state->opcode = AML_INT_NAMEPATH_OP; + walk_state->arg_types = ARGP_NAMESTRING; + break; + + case AML_CLASS_UNKNOWN: + + /* The opcode is unrecognized. Complain and skip unknown opcodes */ + + if (walk_state->pass_number == 2) { + ACPI_ERROR((AE_INFO, + "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring", + walk_state->opcode, + (u32)(walk_state->aml_offset + + sizeof(struct acpi_table_header)))); + + ACPI_DUMP_BUFFER((walk_state->parser_state.aml - 16), + 48); + +#ifdef ACPI_ASL_COMPILER + /* + * This is executed for the disassembler only. Output goes + * to the disassembled ASL output file. + */ + acpi_os_printf + ("/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n", + walk_state->opcode, + (u32)(walk_state->aml_offset + + sizeof(struct acpi_table_header))); + + /* Dump the context surrounding the invalid opcode */ + + acpi_ut_dump_buffer(((u8 *)walk_state->parser_state. + aml - 16), 48, DB_BYTE_DISPLAY, + (walk_state->aml_offset + + sizeof(struct acpi_table_header) - + 16)); + acpi_os_printf(" */\n"); +#endif + } + + /* Increment past one-byte or two-byte opcode */ + + walk_state->parser_state.aml++; + if (walk_state->opcode > 0xFF) { /* Can only happen if first byte is 0x5B */ + walk_state->parser_state.aml++; + } + + return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); + + default: + + /* Found opcode info, this is a normal opcode */ + + walk_state->parser_state.aml += + acpi_ps_get_opcode_size(walk_state->opcode); + walk_state->arg_types = walk_state->op_info->parse_args; + break; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_build_named_op + * + * PARAMETERS: walk_state - Current state + * aml_op_start - Begin of named Op in AML + * unnamed_op - Early Op (not a named Op) + * op - Returned Op + * + * RETURN: Status + * + * DESCRIPTION: Parse a named Op + * + ******************************************************************************/ + +acpi_status +acpi_ps_build_named_op(struct acpi_walk_state *walk_state, + u8 *aml_op_start, + union acpi_parse_object *unnamed_op, + union acpi_parse_object **op) +{ + acpi_status status = AE_OK; + union acpi_parse_object *arg = NULL; + + ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state); + + unnamed_op->common.value.arg = NULL; + unnamed_op->common.arg_list_length = 0; + unnamed_op->common.aml_opcode = walk_state->opcode; + + /* + * Get and append arguments until we find the node that contains + * the name (the type ARGP_NAME). + */ + while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) && + (GET_CURRENT_ARG_TYPE(walk_state->arg_types) != ARGP_NAME)) { + status = + acpi_ps_get_next_arg(walk_state, + &(walk_state->parser_state), + GET_CURRENT_ARG_TYPE(walk_state-> + arg_types), &arg); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_ps_append_arg(unnamed_op, arg); + INCREMENT_ARG_LIST(walk_state->arg_types); + } + + /* + * Make sure that we found a NAME and didn't run out of arguments + */ + if (!GET_CURRENT_ARG_TYPE(walk_state->arg_types)) { + return_ACPI_STATUS(AE_AML_NO_OPERAND); + } + + /* We know that this arg is a name, move to next arg */ + + INCREMENT_ARG_LIST(walk_state->arg_types); + + /* + * Find the object. This will either insert the object into + * the namespace or simply look it up + */ + walk_state->op = NULL; + + status = walk_state->descending_callback(walk_state, op); + if (ACPI_FAILURE(status)) { + if (status != AE_CTRL_TERMINATE) { + ACPI_EXCEPTION((AE_INFO, status, + "During name lookup/catalog")); + } + return_ACPI_STATUS(status); + } + + if (!*op) { + return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); + } + + status = acpi_ps_next_parse_state(walk_state, *op, status); + if (ACPI_FAILURE(status)) { + if (status == AE_CTRL_PENDING) { + status = AE_CTRL_PARSE_PENDING; + } + return_ACPI_STATUS(status); + } + + acpi_ps_append_arg(*op, unnamed_op->common.value.arg); + + if ((*op)->common.aml_opcode == AML_REGION_OP || + (*op)->common.aml_opcode == AML_DATA_REGION_OP) { + /* + * Defer final parsing of an operation_region body, because we don't + * have enough info in the first pass to parse it correctly (i.e., + * there may be method calls within the term_arg elements of the body.) + * + * However, we must continue parsing because the opregion is not a + * standalone package -- we don't know where the end is at this point. + * + * (Length is unknown until parse of the body complete) + */ + (*op)->named.data = aml_op_start; + (*op)->named.length = 0; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_create_op + * + * PARAMETERS: walk_state - Current state + * aml_op_start - Op start in AML + * new_op - Returned Op + * + * RETURN: Status + * + * DESCRIPTION: Get Op from AML + * + ******************************************************************************/ + +acpi_status +acpi_ps_create_op(struct acpi_walk_state *walk_state, + u8 *aml_op_start, union acpi_parse_object **new_op) +{ + acpi_status status = AE_OK; + union acpi_parse_object *op; + union acpi_parse_object *named_op = NULL; + union acpi_parse_object *parent_scope; + u8 argument_count; + const struct acpi_opcode_info *op_info; + + ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state); + + status = acpi_ps_get_aml_opcode(walk_state); + if (status == AE_CTRL_PARSE_CONTINUE) { + return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); + } + + /* Create Op structure and append to parent's argument list */ + + walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); + op = acpi_ps_alloc_op(walk_state->opcode); + if (!op) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + if (walk_state->op_info->flags & AML_NAMED) { + status = + acpi_ps_build_named_op(walk_state, aml_op_start, op, + &named_op); + acpi_ps_free_op(op); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + *new_op = named_op; + return_ACPI_STATUS(AE_OK); + } + + /* Not a named opcode, just allocate Op and append to parent */ + + if (walk_state->op_info->flags & AML_CREATE) { + /* + * Backup to beginning of create_XXXfield declaration + * body_length is unknown until we parse the body + */ + op->named.data = aml_op_start; + op->named.length = 0; + } + + if (walk_state->opcode == AML_BANK_FIELD_OP) { + /* + * Backup to beginning of bank_field declaration + * body_length is unknown until we parse the body + */ + op->named.data = aml_op_start; + op->named.length = 0; + } + + parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state)); + acpi_ps_append_arg(parent_scope, op); + + if (parent_scope) { + op_info = + acpi_ps_get_opcode_info(parent_scope->common.aml_opcode); + if (op_info->flags & AML_HAS_TARGET) { + argument_count = + acpi_ps_get_argument_count(op_info->type); + if (parent_scope->common.arg_list_length > + argument_count) { + op->common.flags |= ACPI_PARSEOP_TARGET; + } + } else if (parent_scope->common.aml_opcode == AML_INCREMENT_OP) { + op->common.flags |= ACPI_PARSEOP_TARGET; + } + } + + if (walk_state->descending_callback != NULL) { + /* + * Find the object. This will either insert the object into + * the namespace or simply look it up + */ + walk_state->op = *new_op = op; + + status = walk_state->descending_callback(walk_state, &op); + status = acpi_ps_next_parse_state(walk_state, op, status); + if (status == AE_CTRL_PENDING) { + status = AE_CTRL_PARSE_PENDING; + } + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_complete_op + * + * PARAMETERS: walk_state - Current state + * op - Returned Op + * status - Parse status before complete Op + * + * RETURN: Status + * + * DESCRIPTION: Complete Op + * + ******************************************************************************/ + +acpi_status +acpi_ps_complete_op(struct acpi_walk_state *walk_state, + union acpi_parse_object **op, acpi_status status) +{ + acpi_status status2; + + ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state); + + /* + * Finished one argument of the containing scope + */ + walk_state->parser_state.scope->parse_scope.arg_count--; + + /* Close this Op (will result in parse subtree deletion) */ + + status2 = acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + + *op = NULL; + + switch (status) { + case AE_OK: + + break; + + case AE_CTRL_TRANSFER: + + /* We are about to transfer to a called method */ + + walk_state->prev_op = NULL; + walk_state->prev_arg_types = walk_state->arg_types; + return_ACPI_STATUS(status); + + case AE_CTRL_END: + + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + + if (*op) { + walk_state->op = *op; + walk_state->op_info = + acpi_ps_get_opcode_info((*op)->common.aml_opcode); + walk_state->opcode = (*op)->common.aml_opcode; + + status = walk_state->ascending_callback(walk_state); + status = + acpi_ps_next_parse_state(walk_state, *op, status); + + status2 = acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + } + + status = AE_OK; + break; + + case AE_CTRL_BREAK: + case AE_CTRL_CONTINUE: + + /* Pop off scopes until we find the While */ + + while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) { + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + } + + /* Close this iteration of the While loop */ + + walk_state->op = *op; + walk_state->op_info = + acpi_ps_get_opcode_info((*op)->common.aml_opcode); + walk_state->opcode = (*op)->common.aml_opcode; + + status = walk_state->ascending_callback(walk_state); + status = acpi_ps_next_parse_state(walk_state, *op, status); + + status2 = acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + + status = AE_OK; + break; + + case AE_CTRL_TERMINATE: + + /* Clean up */ + do { + if (*op) { + status2 = + acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + + acpi_ut_delete_generic_state + (acpi_ut_pop_generic_state + (&walk_state->control_state)); + } + + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + + } while (*op); + + return_ACPI_STATUS(AE_OK); + + default: /* All other non-AE_OK status */ + + do { + if (*op) { + status2 = + acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + } + + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + + } while (*op); + +#if 0 + /* + * TBD: Cleanup parse ops on error + */ + if (*op == NULL) { + acpi_ps_pop_scope(parser_state, op, + &walk_state->arg_types, + &walk_state->arg_count); + } +#endif + walk_state->prev_op = NULL; + walk_state->prev_arg_types = walk_state->arg_types; + return_ACPI_STATUS(status); + } + + /* This scope complete? */ + + if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) { + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op)); + } else { + *op = NULL; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_complete_final_op + * + * PARAMETERS: walk_state - Current state + * op - Current Op + * status - Current parse status before complete last + * Op + * + * RETURN: Status + * + * DESCRIPTION: Complete last Op. + * + ******************************************************************************/ + +acpi_status +acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, + union acpi_parse_object *op, acpi_status status) +{ + acpi_status status2; + + ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state); + + /* + * Complete the last Op (if not completed), and clear the scope stack. + * It is easily possible to end an AML "package" with an unbounded number + * of open scopes (such as when several ASL blocks are closed with + * sequential closing braces). We want to terminate each one cleanly. + */ + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n", + op)); + do { + if (op) { + if (walk_state->ascending_callback != NULL) { + walk_state->op = op; + walk_state->op_info = + acpi_ps_get_opcode_info(op->common. + aml_opcode); + walk_state->opcode = op->common.aml_opcode; + + status = + walk_state->ascending_callback(walk_state); + status = + acpi_ps_next_parse_state(walk_state, op, + status); + if (status == AE_CTRL_PENDING) { + status = + acpi_ps_complete_op(walk_state, &op, + AE_OK); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + if (status == AE_CTRL_TERMINATE) { + status = AE_OK; + + /* Clean up */ + do { + if (op) { + status2 = + acpi_ps_complete_this_op + (walk_state, op); + if (ACPI_FAILURE + (status2)) { + return_ACPI_STATUS + (status2); + } + } + + acpi_ps_pop_scope(& + (walk_state-> + parser_state), + &op, + &walk_state-> + arg_types, + &walk_state-> + arg_count); + + } while (op); + + return_ACPI_STATUS(status); + } + + else if (ACPI_FAILURE(status)) { + + /* First error is most important */ + + (void) + acpi_ps_complete_this_op(walk_state, + op); + return_ACPI_STATUS(status); + } + } + + status2 = acpi_ps_complete_this_op(walk_state, op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + } + + acpi_ps_pop_scope(&(walk_state->parser_state), &op, + &walk_state->arg_types, + &walk_state->arg_count); + + } while (op); + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/psopcode.c b/drivers/acpi/acpica/psopcode.c index a0226fdcf75..1755d2ac565 100644 --- a/drivers/acpi/acpica/psopcode.c +++ b/drivers/acpi/acpica/psopcode.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,27 +43,22 @@ #include <acpi/acpi.h> #include "accommon.h" -#include "acparser.h" #include "acopcode.h" #include "amlcode.h" #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME("psopcode") -static const u8 acpi_gbl_argument_count[] = - { 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 6 }; - /******************************************************************************* * * NAME: acpi_gbl_aml_op_info * * DESCRIPTION: Opcode table. Each entry contains <opcode, type, name, operands> * The name is a simple ascii string, the operand specifier is an - * ascii string with one letter per operand. The letter specifies + * ascii string with one letter per operand. The letter specifies * the operand type. * ******************************************************************************/ - /* * Summary of opcode types/flags * @@ -181,9 +176,8 @@ static const u8 acpi_gbl_argument_count[] = AML_CREATE_QWORD_FIELD_OP ******************************************************************************/ - /* - * Master Opcode information table. A summary of everything we know about each + * Master Opcode information table. A summary of everything we know about each * opcode, all in one place. */ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { @@ -392,10 +386,12 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE), /* 38 */ ACPI_OP("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, - AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT), + AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | + AML_CONSTANT), /* 39 */ ACPI_OP("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, - AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT), + AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | + AML_CONSTANT), /* 3A */ ACPI_OP("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), @@ -495,7 +491,8 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { AML_NSNODE | AML_NAMED | AML_DEFER), /* 59 */ ACPI_OP("Field", ARGP_FIELD_OP, ARGI_FIELD_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_FIELD), /* 5A */ ACPI_OP("Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP, ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, @@ -519,12 +516,13 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { /* 5E */ ACPI_OP("IndexField", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_FIELD), /* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP, - ACPI_TYPE_LOCAL_BANK_FIELD, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD | - AML_DEFER), + ACPI_TYPE_LOCAL_BANK_FIELD, + AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_FIELD | AML_DEFER), /* Internal opcodes that map to invalid AML opcodes */ @@ -632,7 +630,8 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { /* 7D */ ACPI_OP("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE), + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE), /* ACPI 3.0 opcodes */ @@ -651,169 +650,3 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { /*! [End] no source code translation !*/ }; - -/* - * This table is directly indexed by the opcodes, and returns an - * index into the table above - */ -static const u8 acpi_gbl_short_op_index[256] = { -/* 0 1 2 3 4 5 6 7 */ -/* 8 9 A B C D E F */ -/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK, -/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK, -/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK, -/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX, -/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D, -/* 0x38 */ 0x7F, 0x80, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, -/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, -/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, -/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC, -/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, -/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK, -/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, -/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, -/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30, -/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72, -/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74, -/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A, -/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61, -/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK, -/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45, -}; - -/* - * This table is indexed by the second opcode of the extended opcode - * pair. It returns an index into the opcode table (acpi_gbl_aml_op_info) - */ -static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] = { -/* 0 1 2 3 4 5 6 7 */ -/* 8 9 A B C D E F */ -/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK, -/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B, -/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, -/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK, -/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, -/* 0x88 */ 0x7C, -}; - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_opcode_info - * - * PARAMETERS: Opcode - The AML opcode - * - * RETURN: A pointer to the info about the opcode. - * - * DESCRIPTION: Find AML opcode description based on the opcode. - * NOTE: This procedure must ALWAYS return a valid pointer! - * - ******************************************************************************/ - -const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode) -{ - ACPI_FUNCTION_NAME(ps_get_opcode_info); - - /* - * Detect normal 8-bit opcode or extended 16-bit opcode - */ - if (!(opcode & 0xFF00)) { - - /* Simple (8-bit) opcode: 0-255, can't index beyond table */ - - return (&acpi_gbl_aml_op_info - [acpi_gbl_short_op_index[(u8) opcode]]); - } - - if (((opcode & 0xFF00) == AML_EXTENDED_OPCODE) && - (((u8) opcode) <= MAX_EXTENDED_OPCODE)) { - - /* Valid extended (16-bit) opcode */ - - return (&acpi_gbl_aml_op_info - [acpi_gbl_long_op_index[(u8) opcode]]); - } - - /* Unknown AML opcode */ - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Unknown AML opcode [%4.4X]\n", opcode)); - - return (&acpi_gbl_aml_op_info[_UNK]); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_opcode_name - * - * PARAMETERS: Opcode - The AML opcode - * - * RETURN: A pointer to the name of the opcode (ASCII String) - * Note: Never returns NULL. - * - * DESCRIPTION: Translate an opcode into a human-readable string - * - ******************************************************************************/ - -char *acpi_ps_get_opcode_name(u16 opcode) -{ -#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT) - - const struct acpi_opcode_info *op; - - op = acpi_ps_get_opcode_info(opcode); - - /* Always guaranteed to return a valid pointer */ - - return (op->name); - -#else - return ("OpcodeName unavailable"); - -#endif -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_argument_count - * - * PARAMETERS: op_type - Type associated with the AML opcode - * - * RETURN: Argument count - * - * DESCRIPTION: Obtain the number of expected arguments for an AML opcode - * - ******************************************************************************/ - -u8 acpi_ps_get_argument_count(u32 op_type) -{ - - if (op_type <= AML_TYPE_EXEC_6A_0T_1R) { - return (acpi_gbl_argument_count[op_type]); - } - - return (0); -} diff --git a/drivers/acpi/acpica/psopinfo.c b/drivers/acpi/acpica/psopinfo.c new file mode 100644 index 00000000000..0d8d37ffd04 --- /dev/null +++ b/drivers/acpi/acpica/psopinfo.c @@ -0,0 +1,270 @@ +/****************************************************************************** + * + * Module Name: psopinfo - AML opcode information functions and dispatch tables + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acparser.h" +#include "acopcode.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_PARSER +ACPI_MODULE_NAME("psopinfo") + +extern const u8 acpi_gbl_short_op_index[]; +extern const u8 acpi_gbl_long_op_index[]; + +static const u8 acpi_gbl_argument_count[] = + { 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 6 }; + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_opcode_info + * + * PARAMETERS: opcode - The AML opcode + * + * RETURN: A pointer to the info about the opcode. + * + * DESCRIPTION: Find AML opcode description based on the opcode. + * NOTE: This procedure must ALWAYS return a valid pointer! + * + ******************************************************************************/ + +const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode) +{ +#ifdef ACPI_DEBUG_OUTPUT + const char *opcode_name = "Unknown AML opcode"; +#endif + + ACPI_FUNCTION_NAME(ps_get_opcode_info); + + /* + * Detect normal 8-bit opcode or extended 16-bit opcode + */ + if (!(opcode & 0xFF00)) { + + /* Simple (8-bit) opcode: 0-255, can't index beyond table */ + + return (&acpi_gbl_aml_op_info + [acpi_gbl_short_op_index[(u8)opcode]]); + } + + if (((opcode & 0xFF00) == AML_EXTENDED_OPCODE) && + (((u8)opcode) <= MAX_EXTENDED_OPCODE)) { + + /* Valid extended (16-bit) opcode */ + + return (&acpi_gbl_aml_op_info + [acpi_gbl_long_op_index[(u8)opcode]]); + } +#if defined ACPI_ASL_COMPILER && defined ACPI_DEBUG_OUTPUT +#include "asldefine.h" + + switch (opcode) { + case AML_RAW_DATA_BYTE: + opcode_name = "-Raw Data Byte-"; + break; + + case AML_RAW_DATA_WORD: + opcode_name = "-Raw Data Word-"; + break; + + case AML_RAW_DATA_DWORD: + opcode_name = "-Raw Data Dword-"; + break; + + case AML_RAW_DATA_QWORD: + opcode_name = "-Raw Data Qword-"; + break; + + case AML_RAW_DATA_BUFFER: + opcode_name = "-Raw Data Buffer-"; + break; + + case AML_RAW_DATA_CHAIN: + opcode_name = "-Raw Data Buffer Chain-"; + break; + + case AML_PACKAGE_LENGTH: + opcode_name = "-Package Length-"; + break; + + case AML_UNASSIGNED_OPCODE: + opcode_name = "-Unassigned Opcode-"; + break; + + case AML_DEFAULT_ARG_OP: + opcode_name = "-Default Arg-"; + break; + + default: + break; + } +#endif + + /* Unknown AML opcode */ + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%4.4X]\n", opcode_name, opcode)); + + return (&acpi_gbl_aml_op_info[_UNK]); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_opcode_name + * + * PARAMETERS: opcode - The AML opcode + * + * RETURN: A pointer to the name of the opcode (ASCII String) + * Note: Never returns NULL. + * + * DESCRIPTION: Translate an opcode into a human-readable string + * + ******************************************************************************/ + +char *acpi_ps_get_opcode_name(u16 opcode) +{ +#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT) + + const struct acpi_opcode_info *op; + + op = acpi_ps_get_opcode_info(opcode); + + /* Always guaranteed to return a valid pointer */ + + return (op->name); + +#else + return ("OpcodeName unavailable"); + +#endif +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_argument_count + * + * PARAMETERS: op_type - Type associated with the AML opcode + * + * RETURN: Argument count + * + * DESCRIPTION: Obtain the number of expected arguments for an AML opcode + * + ******************************************************************************/ + +u8 acpi_ps_get_argument_count(u32 op_type) +{ + + if (op_type <= AML_TYPE_EXEC_6A_0T_1R) { + return (acpi_gbl_argument_count[op_type]); + } + + return (0); +} + +/* + * This table is directly indexed by the opcodes It returns + * an index into the opcode table (acpi_gbl_aml_op_info) + */ +const u8 acpi_gbl_short_op_index[256] = { +/* 0 1 2 3 4 5 6 7 */ +/* 8 9 A B C D E F */ +/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK, +/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK, +/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK, +/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX, +/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D, +/* 0x38 */ 0x7F, 0x80, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC, +/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, +/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK, +/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, +/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, +/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30, +/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72, +/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74, +/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A, +/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61, +/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK, +/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45, +}; + +/* + * This table is indexed by the second opcode of the extended opcode + * pair. It returns an index into the opcode table (acpi_gbl_aml_op_info) + */ +const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] = { +/* 0 1 2 3 4 5 6 7 */ +/* 8 9 A B C D E F */ +/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK, +/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B, +/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, +/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK, +/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, +/* 0x88 */ 0x7C, +}; diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c index 2ff9c35a196..6d27b597394 100644 --- a/drivers/acpi/acpica/psparse.c +++ b/drivers/acpi/acpica/psparse.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,9 +43,9 @@ /* * Parse the AML and build an operation tree as most interpreters, - * like Perl, do. Parsing is done by hand rather than with a YACC + * like Perl, do. Parsing is done by hand rather than with a YACC * generated parser to tightly constrain stack and dynamic memory - * usage. At the same time, parsing is kept flexible and the code + * usage. At the same time, parsing is kept flexible and the code * fairly compact by parsing based on a list of AML opcode * templates in aml_op_info[] */ @@ -64,7 +64,7 @@ ACPI_MODULE_NAME("psparse") * * FUNCTION: acpi_ps_get_opcode_size * - * PARAMETERS: Opcode - An AML opcode + * PARAMETERS: opcode - An AML opcode * * RETURN: Size of the opcode, in bytes (1 or 2) * @@ -121,7 +121,7 @@ u16 acpi_ps_peek_opcode(struct acpi_parse_state * parser_state) * FUNCTION: acpi_ps_complete_this_op * * PARAMETERS: walk_state - Current State - * Op - Op to complete + * op - Op to complete * * RETURN: Status * @@ -176,10 +176,10 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, switch (parent_info->class) { case AML_CLASS_CONTROL: + break; case AML_CLASS_CREATE: - /* * These opcodes contain term_arg operands. The current * op must be replaced by a placeholder return op @@ -192,7 +192,6 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, break; case AML_CLASS_NAMED_OBJECT: - /* * These opcodes contain term_arg operands. The current * op must be replaced by a placeholder return op @@ -298,7 +297,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, } } - cleanup: +cleanup: /* Now we can actually delete the subtree rooted at Op */ @@ -311,7 +310,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, * FUNCTION: acpi_ps_next_parse_state * * PARAMETERS: walk_state - Current state - * Op - Current parse op + * op - Current parse op * callback_status - Status from previous operation * * RETURN: Status @@ -379,7 +378,7 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state, case AE_CTRL_FALSE: /* * Either an IF/WHILE Predicate was false or we encountered a BREAK - * opcode. In both cases, we do not execute the rest of the + * opcode. In both cases, we do not execute the rest of the * package; We simply close out the parent (finishing the walk of * this branch of the tree) and continue execution at the parent * level. @@ -459,8 +458,9 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) /* Executing a control method - additional cleanup */ - acpi_ds_terminate_control_method( - walk_state->method_desc, walk_state); + acpi_ds_terminate_control_method(walk_state-> + method_desc, + walk_state); } acpi_ds_delete_walk_state(walk_state); @@ -487,7 +487,7 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) acpi_gbl_current_walk_list = thread; /* - * Execute the walk loop as long as there is a valid Walk State. This + * Execute the walk loop as long as there is a valid Walk State. This * handles nested control method invocations without recursion. */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "State=%p\n", walk_state)); diff --git a/drivers/acpi/acpica/psscope.c b/drivers/acpi/acpica/psscope.c index c872aa4b926..32d250feea2 100644 --- a/drivers/acpi/acpica/psscope.c +++ b/drivers/acpi/acpica/psscope.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -93,7 +93,7 @@ u8 acpi_ps_has_completed_scope(struct acpi_parse_state * parser_state) * FUNCTION: acpi_ps_init_scope * * PARAMETERS: parser_state - Current parser state object - * Root - the Root Node of this new scope + * root - the Root Node of this new scope * * RETURN: Status * @@ -131,7 +131,7 @@ acpi_ps_init_scope(struct acpi_parse_state * parser_state, * FUNCTION: acpi_ps_push_scope * * PARAMETERS: parser_state - Current parser state object - * Op - Current op to be pushed + * op - Current op to be pushed * remaining_args - List of args remaining * arg_count - Fixed or variable number of args * @@ -184,7 +184,7 @@ acpi_ps_push_scope(struct acpi_parse_state *parser_state, * FUNCTION: acpi_ps_pop_scope * * PARAMETERS: parser_state - Current parser state object - * Op - Where the popped op is returned + * op - Where the popped op is returned * arg_list - Where the popped "next argument" is * returned * arg_count - Count of objects in arg_list diff --git a/drivers/acpi/acpica/pstree.c b/drivers/acpi/acpica/pstree.c index 2b03cdbbe1c..0b64181e772 100644 --- a/drivers/acpi/acpica/pstree.c +++ b/drivers/acpi/acpica/pstree.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,8 +58,8 @@ union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op); * * FUNCTION: acpi_ps_get_arg * - * PARAMETERS: Op - Get an argument for this op - * Argn - Nth argument to get + * PARAMETERS: op - Get an argument for this op + * argn - Nth argument to get * * RETURN: The argument (as an Op object). NULL if argument does not exist * @@ -114,8 +114,8 @@ union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn) * * FUNCTION: acpi_ps_append_arg * - * PARAMETERS: Op - Append an argument to this Op. - * Arg - Argument Op to append + * PARAMETERS: op - Append an argument to this Op. + * arg - Argument Op to append * * RETURN: None. * @@ -188,8 +188,8 @@ acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg) * * FUNCTION: acpi_ps_get_depth_next * - * PARAMETERS: Origin - Root of subtree to search - * Op - Last (previous) Op that was found + * PARAMETERS: origin - Root of subtree to search + * op - Last (previous) Op that was found * * RETURN: Next Op found in the search. * @@ -261,7 +261,7 @@ union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin, * * FUNCTION: acpi_ps_get_child * - * PARAMETERS: Op - Get the child of this Op + * PARAMETERS: op - Get the child of this Op * * RETURN: Child Op, Null if none is found. * @@ -308,7 +308,9 @@ union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op) break; default: + /* All others have no children */ + break; } diff --git a/drivers/acpi/acpica/psutils.c b/drivers/acpi/acpica/psutils.c index 13bb131ae12..3cd48802eed 100644 --- a/drivers/acpi/acpica/psutils.c +++ b/drivers/acpi/acpica/psutils.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -77,8 +77,8 @@ union acpi_parse_object *acpi_ps_create_scope_op(void) * * FUNCTION: acpi_ps_init_op * - * PARAMETERS: Op - A newly allocated Op object - * Opcode - Opcode to store in the Op + * PARAMETERS: op - A newly allocated Op object + * opcode - Opcode to store in the Op * * RETURN: None * @@ -103,12 +103,12 @@ void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode) * * FUNCTION: acpi_ps_alloc_op * - * PARAMETERS: Opcode - Opcode that will be stored in the new Op + * PARAMETERS: opcode - Opcode that will be stored in the new Op * * RETURN: Pointer to the new Op, null on failure * * DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on - * opcode. A cache of opcodes is available for the pure + * opcode. A cache of opcodes is available for the pure * GENERIC_OP, since this is by far the most commonly used. * ******************************************************************************/ @@ -160,11 +160,11 @@ union acpi_parse_object *acpi_ps_alloc_op(u16 opcode) * * FUNCTION: acpi_ps_free_op * - * PARAMETERS: Op - Op to be freed + * PARAMETERS: op - Op to be freed * * RETURN: None. * - * DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list + * DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list * or actually free it. * ******************************************************************************/ @@ -202,14 +202,6 @@ u8 acpi_ps_is_leading_char(u32 c) } /* - * Is "c" a namestring prefix character? - */ -u8 acpi_ps_is_prefix_char(u32 c) -{ - return ((u8) (c == '\\' || c == '^')); -} - -/* * Get op's name (4-byte name segment) or 0 if unnamed */ #ifdef ACPI_FUTURE_USAGE diff --git a/drivers/acpi/acpica/pswalk.c b/drivers/acpi/acpica/pswalk.c index ab96cf47896..9cb07e1e76d 100644 --- a/drivers/acpi/acpica/pswalk.c +++ b/drivers/acpi/acpica/pswalk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c index 9d98c5ff66a..e135acaa5e1 100644 --- a/drivers/acpi/acpica/psxface.c +++ b/drivers/acpi/acpica/psxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -66,7 +66,7 @@ acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action); * PARAMETERS: method_name - Valid ACPI name string * debug_level - Optional level mask. 0 to use default * debug_layer - Optional layer mask. 0 to use default - * Flags - bit 1: one shot(1) or persistent(0) + * flags - bit 1: one shot(1) or persistent(0) * * RETURN: Status * @@ -105,7 +105,7 @@ acpi_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags) * * FUNCTION: acpi_ps_start_trace * - * PARAMETERS: Info - Method info struct + * PARAMETERS: info - Method info struct * * RETURN: None * @@ -125,7 +125,7 @@ static void acpi_ps_start_trace(struct acpi_evaluate_info *info) } if ((!acpi_gbl_trace_method_name) || - (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) { + (acpi_gbl_trace_method_name != info->node->name.integer)) { goto exit; } @@ -142,7 +142,7 @@ static void acpi_ps_start_trace(struct acpi_evaluate_info *info) acpi_dbg_layer = acpi_gbl_trace_dbg_layer; } - exit: +exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); } @@ -150,7 +150,7 @@ static void acpi_ps_start_trace(struct acpi_evaluate_info *info) * * FUNCTION: acpi_ps_stop_trace * - * PARAMETERS: Info - Method info struct + * PARAMETERS: info - Method info struct * * RETURN: None * @@ -170,7 +170,7 @@ static void acpi_ps_stop_trace(struct acpi_evaluate_info *info) } if ((!acpi_gbl_trace_method_name) || - (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) { + (acpi_gbl_trace_method_name != info->node->name.integer)) { goto exit; } @@ -185,7 +185,7 @@ static void acpi_ps_stop_trace(struct acpi_evaluate_info *info) acpi_dbg_level = acpi_gbl_original_dbg_level; acpi_dbg_layer = acpi_gbl_original_dbg_layer; - exit: +exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); } @@ -193,10 +193,10 @@ static void acpi_ps_stop_trace(struct acpi_evaluate_info *info) * * FUNCTION: acpi_ps_execute_method * - * PARAMETERS: Info - Method info block, contains: - * Node - Method Node to execute + * PARAMETERS: info - Method info block, contains: + * node - Method Node to execute * obj_desc - Method object - * Parameters - List of parameters to pass to the method, + * parameters - List of parameters to pass to the method, * terminated by NULL. Params itself may be * NULL if no parameters are being passed. * return_object - Where to put method's return value (if @@ -226,15 +226,14 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) /* Validate the Info and method Node */ - if (!info || !info->resolved_node) { + if (!info || !info->node) { return_ACPI_STATUS(AE_NULL_ENTRY); } /* Init for new method, wait on concurrency semaphore */ status = - acpi_ds_begin_method_execution(info->resolved_node, info->obj_desc, - NULL); + acpi_ds_begin_method_execution(info->node, info->obj_desc, NULL); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -253,8 +252,7 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n", - info->resolved_node->name.ascii, info->resolved_node, - info->obj_desc)); + info->node->name.ascii, info->node, info->obj_desc)); /* Create and init a Root Node */ @@ -275,7 +273,7 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) goto cleanup; } - status = acpi_ds_init_aml_walk(walk_state, op, info->resolved_node, + status = acpi_ds_init_aml_walk(walk_state, op, info->node, info->obj_desc->method.aml_start, info->obj_desc->method.aml_length, info, info->pass_number); @@ -325,7 +323,7 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) /* walk_state was deleted by parse_aml */ - cleanup: +cleanup: acpi_ps_delete_parse_tree(op); /* End optional tracing */ @@ -361,9 +359,9 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) * * FUNCTION: acpi_ps_update_parameter_list * - * PARAMETERS: Info - See struct acpi_evaluate_info + * PARAMETERS: info - See struct acpi_evaluate_info * (Used: parameter_type and Parameters) - * Action - Add or Remove reference + * action - Add or Remove reference * * RETURN: Status * diff --git a/drivers/acpi/acpica/rsaddr.c b/drivers/acpi/acpica/rsaddr.c index a0305652394..916fd095ff3 100644 --- a/drivers/acpi/acpica/rsaddr.c +++ b/drivers/acpi/acpica/rsaddr.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -182,8 +182,8 @@ struct acpi_rsconvert_info acpi_rs_convert_ext_address64[5] = { /* Revision ID */ - {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.ext_address64.revision_iD), - AML_OFFSET(ext_address64.revision_iD), + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.ext_address64.revision_ID), + AML_OFFSET(ext_address64.revision_ID), 1}, /* * These fields are contiguous in both the source and destination: @@ -215,7 +215,7 @@ static struct acpi_rsconvert_info acpi_rs_convert_general_flags[6] = { AML_OFFSET(address.resource_type), 1}, - /* General Flags - Consume, Decode, min_fixed, max_fixed */ + /* General flags - Consume, Decode, min_fixed, max_fixed */ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.producer_consumer), AML_OFFSET(address.flags), @@ -293,8 +293,8 @@ static struct acpi_rsconvert_info acpi_rs_convert_io_flags[4] = { * * FUNCTION: acpi_rs_get_address_common * - * PARAMETERS: Resource - Pointer to the internal resource struct - * Aml - Pointer to the AML resource descriptor + * PARAMETERS: resource - Pointer to the internal resource struct + * aml - Pointer to the AML resource descriptor * * RETURN: TRUE if the resource_type field is OK, FALSE otherwise * @@ -343,8 +343,8 @@ acpi_rs_get_address_common(struct acpi_resource *resource, * * FUNCTION: acpi_rs_set_address_common * - * PARAMETERS: Aml - Pointer to the AML resource descriptor - * Resource - Pointer to the internal resource struct + * PARAMETERS: aml - Pointer to the AML resource descriptor + * resource - Pointer to the internal resource struct * * RETURN: None * diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c index 3c6df4b7eb2..689556744b0 100644 --- a/drivers/acpi/acpica/rscalc.c +++ b/drivers/acpi/acpica/rscalc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -84,7 +84,7 @@ static u8 acpi_rs_count_set_bits(u16 bit_field) bit_field &= (u16) (bit_field - 1); } - return bits_set; + return (bits_set); } /******************************************************************************* @@ -173,7 +173,8 @@ acpi_rs_stream_option_length(u32 resource_length, * * FUNCTION: acpi_rs_get_aml_length * - * PARAMETERS: Resource - Pointer to the resource linked list + * PARAMETERS: resource - Pointer to the resource linked list + * resource_list_size - Size of the resource linked list * size_needed - Where the required size is returned * * RETURN: Status @@ -185,16 +186,20 @@ acpi_rs_stream_option_length(u32 resource_length, ******************************************************************************/ acpi_status -acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed) +acpi_rs_get_aml_length(struct acpi_resource *resource, + acpi_size resource_list_size, acpi_size * size_needed) { acpi_size aml_size_needed = 0; + struct acpi_resource *resource_end; acpi_rs_length total_size; ACPI_FUNCTION_TRACE(rs_get_aml_length); /* Traverse entire list of internal resource descriptors */ - while (resource) { + resource_end = + ACPI_ADD_PTR(struct acpi_resource, resource, resource_list_size); + while (resource < resource_end) { /* Validate the descriptor type */ @@ -202,6 +207,12 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed) return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); } + /* Sanity check the length. It must not be zero, or we loop forever */ + + if (!resource->length) { + return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); + } + /* Get the base size of the (external stream) resource descriptor */ total_size = acpi_gbl_aml_resource_sizes[resource->type]; @@ -346,6 +357,7 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed) break; default: + break; } @@ -407,7 +419,9 @@ acpi_rs_get_list_length(u8 * aml_buffer, /* Validate the Resource Type and Resource Length */ - status = acpi_ut_validate_resource(aml_buffer, &resource_index); + status = + acpi_ut_validate_resource(NULL, aml_buffer, + &resource_index); if (ACPI_FAILURE(status)) { /* * Exit on failure. Cannot continue because the descriptor length @@ -457,6 +471,15 @@ acpi_rs_get_list_length(u8 * aml_buffer, * Get the number of vendor data bytes */ extra_struct_bytes = resource_length; + + /* + * There is already one byte included in the minimum + * descriptor size. If there are extra struct bytes, + * subtract one from the count. + */ + if (extra_struct_bytes) { + extra_struct_bytes--; + } break; case ACPI_RESOURCE_NAME_END_TAG: @@ -522,6 +545,7 @@ acpi_rs_get_list_length(u8 * aml_buffer, break; default: + break; } @@ -601,7 +625,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, /* * Calculate the size of the return buffer. * The base size is the number of elements * the sizes of the - * structures. Additional space for the strings is added below. + * structures. Additional space for the strings is added below. * The minus one is to subtract the size of the u8 Source[1] * member because it is added below. * @@ -612,7 +636,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, for (index = 0; index < number_of_elements; index++) { - /* Dereference the sub-package */ + /* Dereference the subpackage */ package_element = *top_object_list; @@ -633,8 +657,9 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, name_found = FALSE; - for (table_index = 0; table_index < 4 && !name_found; - table_index++) { + for (table_index = 0; + table_index < package_element->package.count + && !name_found; table_index++) { if (*sub_object_list && /* Null object allowed */ ((ACPI_TYPE_STRING == (*sub_object_list)->common.type) || @@ -664,8 +689,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, (*sub_object_list)->string. length + 1); } else { - temp_size_needed += - acpi_ns_get_pathname_length((*sub_object_list)->reference.node); + temp_size_needed += acpi_ns_get_pathname_length((*sub_object_list)->reference.node); } } else { /* diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c index 46d6eb38ae6..049d9c22a0f 100644 --- a/drivers/acpi/acpica/rscreate.c +++ b/drivers/acpi/acpica/rscreate.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -72,6 +72,8 @@ acpi_buffer_to_resource(u8 *aml_buffer, void *resource; void *current_resource_ptr; + ACPI_FUNCTION_TRACE(acpi_buffer_to_resource); + /* * Note: we allow AE_AML_NO_RESOURCE_END_TAG, since an end tag * is not required here. @@ -85,7 +87,7 @@ acpi_buffer_to_resource(u8 *aml_buffer, status = AE_OK; } if (ACPI_FAILURE(status)) { - return (status); + return_ACPI_STATUS(status); } /* Allocate a buffer for the converted resource */ @@ -93,12 +95,12 @@ acpi_buffer_to_resource(u8 *aml_buffer, resource = ACPI_ALLOCATE_ZEROED(list_size_needed); current_resource_ptr = resource; if (!resource) { - return (AE_NO_MEMORY); + return_ACPI_STATUS(AE_NO_MEMORY); } /* Perform the AML-to-Resource conversion */ - status = acpi_ut_walk_aml_resources(aml_buffer, aml_buffer_length, + status = acpi_ut_walk_aml_resources(NULL, aml_buffer, aml_buffer_length, acpi_rs_convert_aml_to_resources, ¤t_resource_ptr); if (status == AE_AML_NO_RESOURCE_END_TAG) { @@ -110,9 +112,11 @@ acpi_buffer_to_resource(u8 *aml_buffer, *resource_ptr = resource; } - return (status); + return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_buffer_to_resource) + /******************************************************************************* * * FUNCTION: acpi_rs_create_resource_list @@ -130,10 +134,9 @@ acpi_buffer_to_resource(u8 *aml_buffer, * of device resources. * ******************************************************************************/ - acpi_status acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, - struct acpi_buffer * output_buffer) + struct acpi_buffer *output_buffer) { acpi_status status; @@ -174,7 +177,7 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, /* Do the conversion */ resource = output_buffer->pointer; - status = acpi_ut_walk_aml_resources(aml_start, aml_buffer_length, + status = acpi_ut_walk_aml_resources(NULL, aml_start, aml_buffer_length, acpi_rs_convert_aml_to_resources, &resource); if (ACPI_FAILURE(status)) { @@ -190,8 +193,8 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, * * FUNCTION: acpi_rs_create_pci_routing_table * - * PARAMETERS: package_object - Pointer to a union acpi_operand_object - * package + * PARAMETERS: package_object - Pointer to a package containing one + * of more ACPI_OPERAND_OBJECTs * output_buffer - Pointer to the user's buffer * * RETURN: Status AE_OK if okay, else a valid acpi_status code. @@ -199,7 +202,7 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, * AE_BUFFER_OVERFLOW and output_buffer->Length will point * to the size buffer needed. * - * DESCRIPTION: Takes the union acpi_operand_object package and creates a + * DESCRIPTION: Takes the union acpi_operand_object package and creates a * linked list of PCI interrupt descriptions * * NOTE: It is the caller's responsibility to ensure that the start of the @@ -273,18 +276,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, */ user_prt->length = (sizeof(struct acpi_pci_routing_table) - 4); - /* Each element of the top-level package must also be a package */ - - if ((*top_object_list)->common.type != ACPI_TYPE_PACKAGE) { - ACPI_ERROR((AE_INFO, - "(PRT[%u]) Need sub-package, found %s", - index, - acpi_ut_get_object_type_name - (*top_object_list))); - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - - /* Each sub-package must be of length 4 */ + /* Each subpackage must be of length 4 */ if ((*top_object_list)->package.count != 4) { ACPI_ERROR((AE_INFO, @@ -294,7 +286,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, } /* - * Dereference the sub-package. + * Dereference the subpackage. * The sub_object_list will now point to an array of the four IRQ * elements: [Address, Pin, Source, source_index] */ @@ -303,7 +295,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* 1) First subobject: Dereference the PRT.Address */ obj_desc = sub_object_list[0]; - if (obj_desc->common.type != ACPI_TYPE_INTEGER) { + if (!obj_desc || obj_desc->common.type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "(PRT[%u].Address) Need Integer, found %s", index, @@ -316,7 +308,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* 2) Second subobject: Dereference the PRT.Pin */ obj_desc = sub_object_list[1]; - if (obj_desc->common.type != ACPI_TYPE_INTEGER) { + if (!obj_desc || obj_desc->common.type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "(PRT[%u].Pin) Need Integer, found %s", index, @@ -327,22 +319,6 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, user_prt->pin = (u32) obj_desc->integer.value; /* - * If the BIOS has erroneously reversed the _PRT source_name (index 2) - * and the source_index (index 3), fix it. _PRT is important enough to - * workaround this BIOS error. This also provides compatibility with - * other ACPI implementations. - */ - obj_desc = sub_object_list[3]; - if (!obj_desc || (obj_desc->common.type != ACPI_TYPE_INTEGER)) { - sub_object_list[3] = sub_object_list[2]; - sub_object_list[2] = obj_desc; - - ACPI_WARNING((AE_INFO, - "(PRT[%X].Source) SourceName and SourceIndex are reversed, fixed", - index)); - } - - /* * 3) Third subobject: Dereference the PRT.source_name * The name may be unresolved (slack mode), so allow a null object */ @@ -421,7 +397,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* 4) Fourth subobject: Dereference the PRT.source_index */ obj_desc = sub_object_list[3]; - if (obj_desc->common.type != ACPI_TYPE_INTEGER) { + if (!obj_desc || obj_desc->common.type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "(PRT[%u].SourceIndex) Need Integer, found %s", index, @@ -445,22 +421,21 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, * * FUNCTION: acpi_rs_create_aml_resources * - * PARAMETERS: linked_list_buffer - Pointer to the resource linked list - * output_buffer - Pointer to the user's buffer + * PARAMETERS: resource_list - Pointer to the resource list buffer + * output_buffer - Where the AML buffer is returned * * RETURN: Status AE_OK if okay, else a valid acpi_status code. * If the output_buffer is too small, the error will be * AE_BUFFER_OVERFLOW and output_buffer->Length will point * to the size buffer needed. * - * DESCRIPTION: Takes the linked list of device resources and - * creates a bytestream to be used as input for the - * _SRS control method. + * DESCRIPTION: Converts a list of device resources to an AML bytestream + * to be used as input for the _SRS control method. * ******************************************************************************/ acpi_status -acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer, +acpi_rs_create_aml_resources(struct acpi_buffer *resource_list, struct acpi_buffer *output_buffer) { acpi_status status; @@ -468,20 +443,19 @@ acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer, ACPI_FUNCTION_TRACE(rs_create_aml_resources); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "LinkedListBuffer = %p\n", - linked_list_buffer)); + /* Params already validated, no need to re-validate here */ - /* - * Params already validated, so we don't re-validate here - * - * Pass the linked_list_buffer into a module that calculates - * the buffer size needed for the byte stream. - */ - status = acpi_rs_get_aml_length(linked_list_buffer, &aml_size_needed); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ResourceList Buffer = %p\n", + resource_list->pointer)); + + /* Get the buffer size needed for the AML byte stream */ + + status = acpi_rs_get_aml_length(resource_list->pointer, + resource_list->length, + &aml_size_needed); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n", - (u32) aml_size_needed, - acpi_format_exception(status))); + (u32)aml_size_needed, acpi_format_exception(status))); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -495,10 +469,9 @@ acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer, /* Do the conversion */ - status = - acpi_rs_convert_resources_to_aml(linked_list_buffer, - aml_size_needed, - output_buffer->pointer); + status = acpi_rs_convert_resources_to_aml(resource_list->pointer, + aml_size_needed, + output_buffer->pointer); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/rsdump.c b/drivers/acpi/acpica/rsdump.c index b4c58113239..c3c56b5a978 100644 --- a/drivers/acpi/acpica/rsdump.c +++ b/drivers/acpi/acpica/rsdump.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,7 +47,8 @@ #define _COMPONENT ACPI_RESOURCES ACPI_MODULE_NAME("rsdump") -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DISASSEMBLER) || defined(ACPI_DEBUGGER) /* Local prototypes */ static void acpi_rs_out_string(char *title, char *value); @@ -77,419 +78,16 @@ static void acpi_rs_dump_address_common(union acpi_resource_data *resource); static void acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table); -#define ACPI_RSD_OFFSET(f) (u8) ACPI_OFFSET (union acpi_resource_data,f) -#define ACPI_PRT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_pci_routing_table,f) -#define ACPI_RSD_TABLE_SIZE(name) (sizeof(name) / sizeof (struct acpi_rsdump_info)) - -/******************************************************************************* - * - * Resource Descriptor info tables - * - * Note: The first table entry must be a Title or Literal and must contain - * the table length (number of table entries) - * - ******************************************************************************/ - -struct acpi_rsdump_info acpi_rs_dump_irq[7] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.descriptor_length), - "Descriptor Length", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering", - acpi_gbl_he_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity", - acpi_gbl_ll_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.sharable), "Sharing", - acpi_gbl_shr_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.interrupt_count), - "Interrupt Count", NULL}, - {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(irq.interrupts[0]), - "Interrupt List", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_dma[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_dma), "DMA", NULL}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.type), "Speed", - acpi_gbl_typ_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(dma.bus_master), "Mastering", - acpi_gbl_bm_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.transfer), "Transfer Type", - acpi_gbl_siz_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(dma.channel_count), "Channel Count", - NULL}, - {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(dma.channels[0]), "Channel List", - NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_start_dpf[4] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_start_dpf), - "Start-Dependent-Functions", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(start_dpf.descriptor_length), - "Descriptor Length", NULL}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.compatibility_priority), - "Compatibility Priority", acpi_gbl_config_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.performance_robustness), - "Performance/Robustness", acpi_gbl_config_decode} -}; - -struct acpi_rsdump_info acpi_rs_dump_end_dpf[1] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_dpf), - "End-Dependent-Functions", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_io[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io), "I/O", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(io.io_decode), "Address Decoding", - acpi_gbl_io_decode}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.minimum), "Address Minimum", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.maximum), "Address Maximum", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.alignment), "Alignment", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.address_length), "Address Length", - NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_fixed_io[3] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_io), - "Fixed I/O", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_io.address), "Address", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_io.address_length), - "Address Length", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_vendor[3] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_vendor), - "Vendor Specific", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(vendor.byte_length), "Length", NULL}, - {ACPI_RSD_LONGLIST, ACPI_RSD_OFFSET(vendor.byte_data[0]), "Vendor Data", - NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_end_tag[1] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "EndTag", - NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_memory24[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory24), - "24-Bit Memory Range", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory24.write_protect), - "Write Protect", acpi_gbl_rw_decode}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.alignment), "Alignment", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.address_length), - "Address Length", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_memory32[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory32), - "32-Bit Memory Range", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory32.write_protect), - "Write Protect", acpi_gbl_rw_decode}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.alignment), "Alignment", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.address_length), - "Address Length", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[4] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_memory32), - "32-Bit Fixed Memory Range", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(fixed_memory32.write_protect), - "Write Protect", acpi_gbl_rw_decode}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address), "Address", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address_length), - "Address Length", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_address16[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address16), - "16-Bit WORD Address Space", NULL}, - {ACPI_RSD_ADDRESS, 0, NULL, NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.granularity), "Granularity", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.translation_offset), - "Translation Offset", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.address_length), - "Address Length", NULL}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address16.resource_source), NULL, NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_address32[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address32), - "32-Bit DWORD Address Space", NULL}, - {ACPI_RSD_ADDRESS, 0, NULL, NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.granularity), "Granularity", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.translation_offset), - "Translation Offset", NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.address_length), - "Address Length", NULL}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address32.resource_source), NULL, NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_address64[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address64), - "64-Bit QWORD Address Space", NULL}, - {ACPI_RSD_ADDRESS, 0, NULL, NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.granularity), "Granularity", - NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.translation_offset), - "Translation Offset", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.address_length), - "Address Length", NULL}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address64.resource_source), NULL, NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_ext_address64[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_address64), - "64-Bit Extended Address Space", NULL}, - {ACPI_RSD_ADDRESS, 0, NULL, NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.granularity), - "Granularity", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.minimum), - "Address Minimum", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.maximum), - "Address Maximum", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.translation_offset), - "Translation Offset", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.address_length), - "Address Length", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.type_specific), - "Type-Specific Attribute", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_ext_irq[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_irq), - "Extended IRQ", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.producer_consumer), - "Type", acpi_gbl_consume_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.triggering), - "Triggering", acpi_gbl_he_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.polarity), "Polarity", - acpi_gbl_ll_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.sharable), "Sharing", - acpi_gbl_shr_decode}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(extended_irq.resource_source), NULL, - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(extended_irq.interrupt_count), - "Interrupt Count", NULL}, - {ACPI_RSD_DWORDLIST, ACPI_RSD_OFFSET(extended_irq.interrupts[0]), - "Interrupt List", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_generic_reg[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_generic_reg), - "Generic Register", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.space_id), "Space ID", - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_width), "Bit Width", - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_offset), "Bit Offset", - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.access_size), - "Access Size", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(generic_reg.address), "Address", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_gpio[16] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_gpio), "GPIO", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.revision_id), "RevisionId", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.connection_type), - "ConnectionType", acpi_gbl_ct_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(gpio.producer_consumer), - "ProducerConsumer", acpi_gbl_consume_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.pin_config), "PinConfig", - acpi_gbl_ppc_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.sharable), "Sharable", - acpi_gbl_shr_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.io_restriction), - "IoRestriction", acpi_gbl_ior_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(gpio.triggering), "Triggering", - acpi_gbl_he_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.polarity), "Polarity", - acpi_gbl_ll_decode}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.drive_strength), "DriveStrength", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.debounce_timeout), - "DebounceTimeout", NULL}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(gpio.resource_source), - "ResourceSource", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.pin_table_length), - "PinTableLength", NULL}, - {ACPI_RSD_WORDLIST, ACPI_RSD_OFFSET(gpio.pin_table), "PinTable", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.vendor_length), "VendorLength", - NULL}, - {ACPI_RSD_SHORTLISTX, ACPI_RSD_OFFSET(gpio.vendor_data), "VendorData", - NULL}, -}; - -struct acpi_rsdump_info acpi_rs_dump_fixed_dma[4] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_dma), - "FixedDma", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_dma.request_lines), - "RequestLines", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_dma.channels), "Channels", - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_dma.width), "TransferWidth", - acpi_gbl_dts_decode}, -}; - -#define ACPI_RS_DUMP_COMMON_SERIAL_BUS \ - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.revision_id), "RevisionId", NULL}, \ - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.type), "Type", acpi_gbl_sbt_decode}, \ - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.producer_consumer), "ProducerConsumer", acpi_gbl_consume_decode}, \ - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.slave_mode), "SlaveMode", acpi_gbl_sm_decode}, \ - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.type_revision_id), "TypeRevisionId", NULL}, \ - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (common_serial_bus.type_data_length), "TypeDataLength", NULL}, \ - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (common_serial_bus.resource_source), "ResourceSource", NULL}, \ - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (common_serial_bus.vendor_length), "VendorLength", NULL}, \ - {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (common_serial_bus.vendor_data), "VendorData", NULL}, - -struct acpi_rsdump_info acpi_rs_dump_common_serial_bus[10] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_common_serial_bus), - "Common Serial Bus", NULL}, - ACPI_RS_DUMP_COMMON_SERIAL_BUS -}; - -struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[13] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_i2c_serial_bus), - "I2C Serial Bus", NULL}, - ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG, - ACPI_RSD_OFFSET(i2c_serial_bus. - access_mode), - "AccessMode", acpi_gbl_am_decode}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(i2c_serial_bus.connection_speed), - "ConnectionSpeed", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(i2c_serial_bus.slave_address), - "SlaveAddress", NULL}, -}; - -struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[17] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_spi_serial_bus), - "Spi Serial Bus", NULL}, - ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG, - ACPI_RSD_OFFSET(spi_serial_bus. - wire_mode), "WireMode", - acpi_gbl_wm_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(spi_serial_bus.device_polarity), - "DevicePolarity", acpi_gbl_dp_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.data_bit_length), - "DataBitLength", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.clock_phase), - "ClockPhase", acpi_gbl_cph_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.clock_polarity), - "ClockPolarity", acpi_gbl_cpo_decode}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(spi_serial_bus.device_selection), - "DeviceSelection", NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(spi_serial_bus.connection_speed), - "ConnectionSpeed", NULL}, -}; - -struct acpi_rsdump_info acpi_rs_dump_uart_serial_bus[19] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_uart_serial_bus), - "Uart Serial Bus", NULL}, - ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_2BITFLAG, - ACPI_RSD_OFFSET(uart_serial_bus. - flow_control), - "FlowControl", acpi_gbl_fc_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.stop_bits), - "StopBits", acpi_gbl_sb_decode}, - {ACPI_RSD_3BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.data_bits), - "DataBits", acpi_gbl_bpb_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.endian), "Endian", - acpi_gbl_ed_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(uart_serial_bus.parity), "Parity", - acpi_gbl_pt_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(uart_serial_bus.lines_enabled), - "LinesEnabled", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(uart_serial_bus.rx_fifo_size), - "RxFifoSize", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(uart_serial_bus.tx_fifo_size), - "TxFifoSize", NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(uart_serial_bus.default_baud_rate), - "ConnectionSpeed", NULL}, -}; - -/* - * Tables used for common address descriptor flag fields - */ -static struct acpi_rsdump_info acpi_rs_dump_general_flags[5] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_general_flags), NULL, - NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.producer_consumer), - "Consumer/Producer", acpi_gbl_consume_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.decode), "Address Decode", - acpi_gbl_dec_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.min_address_fixed), - "Min Relocatability", acpi_gbl_min_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.max_address_fixed), - "Max Relocatability", acpi_gbl_max_decode} -}; - -static struct acpi_rsdump_info acpi_rs_dump_memory_flags[5] = { - {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory_flags), - "Resource Type", (void *)"Memory Range"}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.write_protect), - "Write Protect", acpi_gbl_rw_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.caching), - "Caching", acpi_gbl_mem_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.range_type), - "Range Type", acpi_gbl_mtp_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.translation), - "Translation", acpi_gbl_ttp_decode} -}; - -static struct acpi_rsdump_info acpi_rs_dump_io_flags[4] = { - {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io_flags), - "Resource Type", (void *)"I/O Range"}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.io.range_type), - "Range Type", acpi_gbl_rng_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation), - "Translation", acpi_gbl_ttp_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation_type), - "Translation Type", acpi_gbl_trs_decode} -}; - -/* - * Table used to dump _PRT contents - */ -static struct acpi_rsdump_info acpi_rs_dump_prt[5] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_prt), NULL, NULL}, - {ACPI_RSD_UINT64, ACPI_PRT_OFFSET(address), "Address", NULL}, - {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(pin), "Pin", NULL}, - {ACPI_RSD_STRING, ACPI_PRT_OFFSET(source[0]), "Source", NULL}, - {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(source_index), "Source Index", NULL} -}; - /******************************************************************************* * * FUNCTION: acpi_rs_dump_descriptor * - * PARAMETERS: Resource + * PARAMETERS: resource - Buffer containing the resource + * table - Table entry to decode the resource * * RETURN: None * - * DESCRIPTION: + * DESCRIPTION: Dump a resource descriptor based on a dump table entry. * ******************************************************************************/ @@ -523,17 +121,20 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) /* Strings */ case ACPI_RSD_LITERAL: + acpi_rs_out_string(name, ACPI_CAST_PTR(char, table->pointer)); break; case ACPI_RSD_STRING: + acpi_rs_out_string(name, ACPI_CAST_PTR(char, target)); break; /* Data items, 8/16/32/64 bit */ case ACPI_RSD_UINT8: + if (table->pointer) { acpi_rs_out_string(name, ACPI_CAST_PTR(char, table-> @@ -545,20 +146,24 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) break; case ACPI_RSD_UINT16: + acpi_rs_out_integer16(name, ACPI_GET16(target)); break; case ACPI_RSD_UINT32: + acpi_rs_out_integer32(name, ACPI_GET32(target)); break; case ACPI_RSD_UINT64: + acpi_rs_out_integer64(name, ACPI_GET64(target)); break; /* Flags: 1-bit and 2-bit flags supported */ case ACPI_RSD_1BITFLAG: + acpi_rs_out_string(name, ACPI_CAST_PTR(char, table-> pointer[*target & @@ -566,6 +171,7 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) break; case ACPI_RSD_2BITFLAG: + acpi_rs_out_string(name, ACPI_CAST_PTR(char, table-> pointer[*target & @@ -573,6 +179,7 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) break; case ACPI_RSD_3BITFLAG: + acpi_rs_out_string(name, ACPI_CAST_PTR(char, table-> pointer[*target & @@ -654,12 +261,14 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) /* * Optional resource_source for Address resources */ - acpi_rs_dump_resource_source(ACPI_CAST_PTR(struct + acpi_rs_dump_resource_source(ACPI_CAST_PTR + (struct acpi_resource_source, target)); break; default: + acpi_os_printf("**** Invalid table opcode [%X] ****\n", table->opcode); return; @@ -703,7 +312,7 @@ acpi_rs_dump_resource_source(struct acpi_resource_source *resource_source) * * FUNCTION: acpi_rs_dump_address_common * - * PARAMETERS: Resource - Pointer to an internal resource descriptor + * PARAMETERS: resource - Pointer to an internal resource descriptor * * RETURN: None * @@ -765,8 +374,9 @@ void acpi_rs_dump_resource_list(struct acpi_resource *resource_list) ACPI_FUNCTION_ENTRY(); - if (!(acpi_dbg_level & ACPI_LV_RESOURCES) - || !(_COMPONENT & acpi_dbg_layer)) { + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_RESOURCES, _COMPONENT)) { return; } @@ -786,6 +396,14 @@ void acpi_rs_dump_resource_list(struct acpi_resource *resource_list) return; } + /* Sanity check the length. It must not be zero, or we loop forever */ + + if (!resource_list->length) { + acpi_os_printf + ("Invalid zero length descriptor in resource list\n"); + return; + } + /* Dump the resource descriptor */ if (type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { @@ -827,8 +445,9 @@ void acpi_rs_dump_irq_list(u8 * route_table) ACPI_FUNCTION_ENTRY(); - if (!(acpi_dbg_level & ACPI_LV_RESOURCES) - || !(_COMPONENT & acpi_dbg_layer)) { + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_RESOURCES, _COMPONENT)) { return; } @@ -850,8 +469,8 @@ void acpi_rs_dump_irq_list(u8 * route_table) * * FUNCTION: acpi_rs_out* * - * PARAMETERS: Title - Name of the resource field - * Value - Value of the resource field + * PARAMETERS: title - Name of the resource field + * value - Value of the resource field * * RETURN: None * @@ -898,8 +517,8 @@ static void acpi_rs_out_title(char *title) * * FUNCTION: acpi_rs_dump*List * - * PARAMETERS: Length - Number of elements in the list - * Data - Start of the list + * PARAMETERS: length - Number of elements in the list + * data - Start of the list * * RETURN: None * diff --git a/drivers/acpi/acpica/rsdumpinfo.c b/drivers/acpi/acpica/rsdumpinfo.c new file mode 100644 index 00000000000..2f9332d5c97 --- /dev/null +++ b/drivers/acpi/acpica/rsdumpinfo.c @@ -0,0 +1,454 @@ +/******************************************************************************* + * + * Module Name: rsdumpinfo - Tables used to display resource descriptors. + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES +ACPI_MODULE_NAME("rsdumpinfo") + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DISASSEMBLER) || defined(ACPI_DEBUGGER) +#define ACPI_RSD_OFFSET(f) (u8) ACPI_OFFSET (union acpi_resource_data,f) +#define ACPI_PRT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_pci_routing_table,f) +#define ACPI_RSD_TABLE_SIZE(name) (sizeof(name) / sizeof (struct acpi_rsdump_info)) +/******************************************************************************* + * + * Resource Descriptor info tables + * + * Note: The first table entry must be a Title or Literal and must contain + * the table length (number of table entries) + * + ******************************************************************************/ +struct acpi_rsdump_info acpi_rs_dump_irq[7] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.descriptor_length), + "Descriptor Length", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering", + acpi_gbl_he_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity", + acpi_gbl_ll_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(irq.sharable), "Sharing", + acpi_gbl_shr_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.interrupt_count), + "Interrupt Count", NULL}, + {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(irq.interrupts[0]), + "Interrupt List", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_dma[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_dma), "DMA", NULL}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.type), "Speed", + acpi_gbl_typ_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(dma.bus_master), "Mastering", + acpi_gbl_bm_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.transfer), "Transfer Type", + acpi_gbl_siz_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(dma.channel_count), "Channel Count", + NULL}, + {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(dma.channels[0]), "Channel List", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_start_dpf[4] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_start_dpf), + "Start-Dependent-Functions", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(start_dpf.descriptor_length), + "Descriptor Length", NULL}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.compatibility_priority), + "Compatibility Priority", acpi_gbl_config_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.performance_robustness), + "Performance/Robustness", acpi_gbl_config_decode} +}; + +struct acpi_rsdump_info acpi_rs_dump_end_dpf[1] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_dpf), + "End-Dependent-Functions", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_io[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io), "I/O", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(io.io_decode), "Address Decoding", + acpi_gbl_io_decode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.minimum), "Address Minimum", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.maximum), "Address Maximum", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.alignment), "Alignment", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.address_length), "Address Length", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_fixed_io[3] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_io), + "Fixed I/O", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_io.address), "Address", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_io.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_vendor[3] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_vendor), + "Vendor Specific", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(vendor.byte_length), "Length", NULL}, + {ACPI_RSD_LONGLIST, ACPI_RSD_OFFSET(vendor.byte_data[0]), "Vendor Data", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_end_tag[1] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "EndTag", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_memory24[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory24), + "24-Bit Memory Range", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory24.write_protect), + "Write Protect", acpi_gbl_rw_decode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.alignment), "Alignment", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_memory32[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory32), + "32-Bit Memory Range", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory32.write_protect), + "Write Protect", acpi_gbl_rw_decode}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.alignment), "Alignment", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[4] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_memory32), + "32-Bit Fixed Memory Range", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(fixed_memory32.write_protect), + "Write Protect", acpi_gbl_rw_decode}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address), "Address", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_address16[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address16), + "16-Bit WORD Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.granularity), "Granularity", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.address_length), + "Address Length", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address16.resource_source), NULL, NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_address32[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address32), + "32-Bit DWORD Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.granularity), "Granularity", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.address_length), + "Address Length", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address32.resource_source), NULL, NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_address64[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address64), + "64-Bit QWORD Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.granularity), "Granularity", + NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.address_length), + "Address Length", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address64.resource_source), NULL, NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_ext_address64[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_address64), + "64-Bit Extended Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.granularity), + "Granularity", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.minimum), + "Address Minimum", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.maximum), + "Address Maximum", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.address_length), + "Address Length", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.type_specific), + "Type-Specific Attribute", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_ext_irq[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_irq), + "Extended IRQ", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.producer_consumer), + "Type", acpi_gbl_consume_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.triggering), + "Triggering", acpi_gbl_he_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.polarity), "Polarity", + acpi_gbl_ll_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(extended_irq.sharable), "Sharing", + acpi_gbl_shr_decode}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(extended_irq.resource_source), NULL, + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(extended_irq.interrupt_count), + "Interrupt Count", NULL}, + {ACPI_RSD_DWORDLIST, ACPI_RSD_OFFSET(extended_irq.interrupts[0]), + "Interrupt List", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_generic_reg[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_generic_reg), + "Generic Register", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.space_id), "Space ID", + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_width), "Bit Width", + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_offset), "Bit Offset", + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.access_size), + "Access Size", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(generic_reg.address), "Address", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_gpio[16] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_gpio), "GPIO", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.revision_id), "RevisionId", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.connection_type), + "ConnectionType", acpi_gbl_ct_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(gpio.producer_consumer), + "ProducerConsumer", acpi_gbl_consume_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.pin_config), "PinConfig", + acpi_gbl_ppc_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.sharable), "Sharing", + acpi_gbl_shr_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.io_restriction), + "IoRestriction", acpi_gbl_ior_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(gpio.triggering), "Triggering", + acpi_gbl_he_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.polarity), "Polarity", + acpi_gbl_ll_decode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.drive_strength), "DriveStrength", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.debounce_timeout), + "DebounceTimeout", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(gpio.resource_source), + "ResourceSource", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.pin_table_length), + "PinTableLength", NULL}, + {ACPI_RSD_WORDLIST, ACPI_RSD_OFFSET(gpio.pin_table), "PinTable", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.vendor_length), "VendorLength", + NULL}, + {ACPI_RSD_SHORTLISTX, ACPI_RSD_OFFSET(gpio.vendor_data), "VendorData", + NULL}, +}; + +struct acpi_rsdump_info acpi_rs_dump_fixed_dma[4] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_dma), + "FixedDma", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_dma.request_lines), + "RequestLines", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_dma.channels), "Channels", + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_dma.width), "TransferWidth", + acpi_gbl_dts_decode}, +}; + +#define ACPI_RS_DUMP_COMMON_SERIAL_BUS \ + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.revision_id), "RevisionId", NULL}, \ + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.type), "Type", acpi_gbl_sbt_decode}, \ + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.producer_consumer), "ProducerConsumer", acpi_gbl_consume_decode}, \ + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.slave_mode), "SlaveMode", acpi_gbl_sm_decode}, \ + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.type_revision_id), "TypeRevisionId", NULL}, \ + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (common_serial_bus.type_data_length), "TypeDataLength", NULL}, \ + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (common_serial_bus.resource_source), "ResourceSource", NULL}, \ + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (common_serial_bus.vendor_length), "VendorLength", NULL}, \ + {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (common_serial_bus.vendor_data), "VendorData", NULL}, + +struct acpi_rsdump_info acpi_rs_dump_common_serial_bus[10] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_common_serial_bus), + "Common Serial Bus", NULL}, + ACPI_RS_DUMP_COMMON_SERIAL_BUS +}; + +struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[13] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_i2c_serial_bus), + "I2C Serial Bus", NULL}, + ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG, + ACPI_RSD_OFFSET(i2c_serial_bus. + access_mode), + "AccessMode", acpi_gbl_am_decode}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(i2c_serial_bus.connection_speed), + "ConnectionSpeed", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(i2c_serial_bus.slave_address), + "SlaveAddress", NULL}, +}; + +struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[17] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_spi_serial_bus), + "Spi Serial Bus", NULL}, + ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG, + ACPI_RSD_OFFSET(spi_serial_bus. + wire_mode), "WireMode", + acpi_gbl_wm_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(spi_serial_bus.device_polarity), + "DevicePolarity", acpi_gbl_dp_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.data_bit_length), + "DataBitLength", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.clock_phase), + "ClockPhase", acpi_gbl_cph_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.clock_polarity), + "ClockPolarity", acpi_gbl_cpo_decode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(spi_serial_bus.device_selection), + "DeviceSelection", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(spi_serial_bus.connection_speed), + "ConnectionSpeed", NULL}, +}; + +struct acpi_rsdump_info acpi_rs_dump_uart_serial_bus[19] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_uart_serial_bus), + "Uart Serial Bus", NULL}, + ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_2BITFLAG, + ACPI_RSD_OFFSET(uart_serial_bus. + flow_control), + "FlowControl", acpi_gbl_fc_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.stop_bits), + "StopBits", acpi_gbl_sb_decode}, + {ACPI_RSD_3BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.data_bits), + "DataBits", acpi_gbl_bpb_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.endian), "Endian", + acpi_gbl_ed_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(uart_serial_bus.parity), "Parity", + acpi_gbl_pt_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(uart_serial_bus.lines_enabled), + "LinesEnabled", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(uart_serial_bus.rx_fifo_size), + "RxFifoSize", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(uart_serial_bus.tx_fifo_size), + "TxFifoSize", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(uart_serial_bus.default_baud_rate), + "ConnectionSpeed", NULL}, +}; + +/* + * Tables used for common address descriptor flag fields + */ +struct acpi_rsdump_info acpi_rs_dump_general_flags[5] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_general_flags), NULL, + NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.producer_consumer), + "Consumer/Producer", acpi_gbl_consume_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.decode), "Address Decode", + acpi_gbl_dec_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.min_address_fixed), + "Min Relocatability", acpi_gbl_min_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.max_address_fixed), + "Max Relocatability", acpi_gbl_max_decode} +}; + +struct acpi_rsdump_info acpi_rs_dump_memory_flags[5] = { + {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory_flags), + "Resource Type", (void *)"Memory Range"}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.write_protect), + "Write Protect", acpi_gbl_rw_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.caching), + "Caching", acpi_gbl_mem_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.range_type), + "Range Type", acpi_gbl_mtp_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.translation), + "Translation", acpi_gbl_ttp_decode} +}; + +struct acpi_rsdump_info acpi_rs_dump_io_flags[4] = { + {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io_flags), + "Resource Type", (void *)"I/O Range"}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.io.range_type), + "Range Type", acpi_gbl_rng_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation), + "Translation", acpi_gbl_ttp_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation_type), + "Translation Type", acpi_gbl_trs_decode} +}; + +/* + * Table used to dump _PRT contents + */ +struct acpi_rsdump_info acpi_rs_dump_prt[5] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_prt), NULL, NULL}, + {ACPI_RSD_UINT64, ACPI_PRT_OFFSET(address), "Address", NULL}, + {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(pin), "Pin", NULL}, + {ACPI_RSD_STRING, ACPI_PRT_OFFSET(source[0]), "Source", NULL}, + {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(source_index), "Source Index", NULL} +}; + +#endif diff --git a/drivers/acpi/acpica/rsinfo.c b/drivers/acpi/acpica/rsinfo.c index a9fa5158200..9d3f8a9a24b 100644 --- a/drivers/acpi/acpica/rsinfo.c +++ b/drivers/acpi/acpica/rsinfo.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -132,8 +132,7 @@ struct acpi_rsconvert_info *acpi_gbl_convert_resource_serial_bus_dispatch[] = { acpi_rs_convert_uart_serial_bus, }; -#ifdef ACPI_FUTURE_USAGE -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DISASSEMBLER) || defined(ACPI_DEBUGGER) /* Dispatch table for resource dump functions */ @@ -168,7 +167,6 @@ struct acpi_rsdump_info *acpi_gbl_dump_serial_bus_dispatch[] = { }; #endif -#endif /* ACPI_FUTURE_USAGE */ /* * Base sizes for external AML resource descriptors, indexed by internal type. * Includes size of the descriptor header (1 byte for small descriptors, diff --git a/drivers/acpi/acpica/rsio.c b/drivers/acpi/acpica/rsio.c index f6a081057a2..19d64873290 100644 --- a/drivers/acpi/acpica/rsio.c +++ b/drivers/acpi/acpica/rsio.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsirq.c b/drivers/acpi/acpica/rsirq.c index e23a9ec248c..3461f7db26d 100644 --- a/drivers/acpi/acpica/rsirq.c +++ b/drivers/acpi/acpica/rsirq.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,7 +53,7 @@ ACPI_MODULE_NAME("rsirq") * acpi_rs_get_irq * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_get_irq[8] = { +struct acpi_rsconvert_info acpi_rs_get_irq[9] = { {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IRQ, ACPI_RS_SIZE(struct acpi_resource_irq), ACPI_RSC_TABLE_SIZE(acpi_rs_get_irq)}, @@ -80,7 +80,7 @@ struct acpi_rsconvert_info acpi_rs_get_irq[8] = { {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 3}, - /* Get flags: Triggering[0], Polarity[3], Sharing[4] */ + /* Get flags: Triggering[0], Polarity[3], Sharing[4], Wake[5] */ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering), AML_OFFSET(irq.flags), @@ -92,7 +92,11 @@ struct acpi_rsconvert_info acpi_rs_get_irq[8] = { {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable), AML_OFFSET(irq.flags), - 4} + 4}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.wake_capable), + AML_OFFSET(irq.flags), + 5} }; /******************************************************************************* @@ -101,7 +105,7 @@ struct acpi_rsconvert_info acpi_rs_get_irq[8] = { * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_set_irq[13] = { +struct acpi_rsconvert_info acpi_rs_set_irq[14] = { /* Start with a default descriptor of length 3 */ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IRQ, @@ -114,7 +118,7 @@ struct acpi_rsconvert_info acpi_rs_set_irq[13] = { AML_OFFSET(irq.irq_mask), ACPI_RS_OFFSET(data.irq.interrupt_count)}, - /* Set the flags byte */ + /* Set flags: Triggering[0], Polarity[3], Sharing[4], Wake[5] */ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering), AML_OFFSET(irq.flags), @@ -128,6 +132,10 @@ struct acpi_rsconvert_info acpi_rs_set_irq[13] = { AML_OFFSET(irq.flags), 4}, + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.wake_capable), + AML_OFFSET(irq.flags), + 5}, + /* * All done if the output descriptor length is required to be 3 * (i.e., optimization to 2 bytes cannot be attempted) @@ -181,7 +189,7 @@ struct acpi_rsconvert_info acpi_rs_set_irq[13] = { * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_convert_ext_irq[9] = { +struct acpi_rsconvert_info acpi_rs_convert_ext_irq[10] = { {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_IRQ, ACPI_RS_SIZE(struct acpi_resource_extended_irq), ACPI_RSC_TABLE_SIZE(acpi_rs_convert_ext_irq)}, @@ -190,8 +198,10 @@ struct acpi_rsconvert_info acpi_rs_convert_ext_irq[9] = { sizeof(struct aml_resource_extended_irq), 0}, - /* Flag bits */ - + /* + * Flags: Producer/Consumer[0], Triggering[1], Polarity[2], + * Sharing[3], Wake[4] + */ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.producer_consumer), AML_OFFSET(extended_irq.flags), 0}, @@ -208,19 +218,21 @@ struct acpi_rsconvert_info acpi_rs_convert_ext_irq[9] = { AML_OFFSET(extended_irq.flags), 3}, + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.wake_capable), + AML_OFFSET(extended_irq.flags), + 4}, + /* IRQ Table length (Byte4) */ {ACPI_RSC_COUNT, ACPI_RS_OFFSET(data.extended_irq.interrupt_count), AML_OFFSET(extended_irq.interrupt_count), - sizeof(u32)} - , + sizeof(u32)}, /* Copy every IRQ in the table, each is 32 bits */ {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.extended_irq.interrupts[0]), AML_OFFSET(extended_irq.interrupts[0]), - 0} - , + 0}, /* Optional resource_source (Index and String) */ @@ -285,7 +297,6 @@ struct acpi_rsconvert_info acpi_rs_convert_fixed_dma[4] = { * request_lines * Channels */ - {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.fixed_dma.request_lines), AML_OFFSET(fixed_dma.request_lines), 2}, @@ -293,5 +304,4 @@ struct acpi_rsconvert_info acpi_rs_convert_fixed_dma[4] = { {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.fixed_dma.width), AML_OFFSET(fixed_dma.width), 1}, - }; diff --git a/drivers/acpi/acpica/rslist.c b/drivers/acpi/acpica/rslist.c index 9be129f5d6f..77291293af6 100644 --- a/drivers/acpi/acpica/rslist.c +++ b/drivers/acpi/acpica/rslist.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -109,7 +109,7 @@ acpi_rs_convert_aml_to_resources(u8 * aml, ACPI_ERROR((AE_INFO, "Invalid/unsupported resource descriptor: Type 0x%2.2X", resource_index)); - return (AE_AML_INVALID_RESOURCE_TYPE); + return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); } /* Convert the AML byte stream resource to a local resource struct */ @@ -139,7 +139,7 @@ acpi_rs_convert_aml_to_resources(u8 * aml, * * FUNCTION: acpi_rs_convert_resources_to_aml * - * PARAMETERS: Resource - Pointer to the resource linked list + * PARAMETERS: resource - Pointer to the resource linked list * aml_size_needed - Calculated size of the byte stream * needed from calling acpi_rs_get_aml_length() * The size of the output_buffer is @@ -178,6 +178,14 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, return_ACPI_STATUS(AE_BAD_DATA); } + /* Sanity check the length. It must not be zero, or we loop forever */ + + if (!resource->length) { + ACPI_ERROR((AE_INFO, + "Invalid zero length descriptor in resource list\n")); + return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); + } + /* Perform the conversion */ if (resource->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { @@ -200,7 +208,7 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, ACPI_ERROR((AE_INFO, "Invalid/unsupported resource descriptor: Type 0x%2.2X", resource->type)); - return (AE_AML_INVALID_RESOURCE_TYPE); + return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); } status = acpi_rs_convert_resource_to_aml(resource, @@ -217,9 +225,10 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, /* Perform final sanity check on the new AML resource descriptor */ - status = - acpi_ut_validate_resource(ACPI_CAST_PTR - (union aml_resource, aml), NULL); + status = acpi_ut_validate_resource(NULL, + ACPI_CAST_PTR(union + aml_resource, + aml), NULL); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/rsmemory.c b/drivers/acpi/acpica/rsmemory.c index 4fd611ad02b..eab4483ff5f 100644 --- a/drivers/acpi/acpica/rsmemory.c +++ b/drivers/acpi/acpica/rsmemory.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -156,8 +156,7 @@ struct acpi_rsconvert_info acpi_rs_get_vendor_small[3] = { {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length), 0, - sizeof(u8)} - , + sizeof(u8)}, /* Vendor data */ @@ -181,8 +180,7 @@ struct acpi_rsconvert_info acpi_rs_get_vendor_large[3] = { {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length), 0, - sizeof(u8)} - , + sizeof(u8)}, /* Vendor data */ diff --git a/drivers/acpi/acpica/rsmisc.c b/drivers/acpi/acpica/rsmisc.c index 8073b371cc7..41eea4bc089 100644 --- a/drivers/acpi/acpica/rsmisc.c +++ b/drivers/acpi/acpica/rsmisc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,9 +57,9 @@ ACPI_MODULE_NAME("rsmisc") * * FUNCTION: acpi_rs_convert_aml_to_resource * - * PARAMETERS: Resource - Pointer to the resource descriptor - * Aml - Where the AML descriptor is returned - * Info - Pointer to appropriate conversion table + * PARAMETERS: resource - Pointer to the resource descriptor + * aml - Where the AML descriptor is returned + * info - Pointer to appropriate conversion table * * RETURN: Status * @@ -136,30 +136,30 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, /* * Mask and shift the flag bit */ - ACPI_SET8(destination) = (u8) - ((ACPI_GET8(source) >> info->value) & 0x01); + ACPI_SET8(destination, + ((ACPI_GET8(source) >> info->value) & 0x01)); break; case ACPI_RSC_2BITFLAG: /* * Mask and shift the flag bits */ - ACPI_SET8(destination) = (u8) - ((ACPI_GET8(source) >> info->value) & 0x03); + ACPI_SET8(destination, + ((ACPI_GET8(source) >> info->value) & 0x03)); break; case ACPI_RSC_3BITFLAG: /* * Mask and shift the flag bits */ - ACPI_SET8(destination) = (u8) - ((ACPI_GET8(source) >> info->value) & 0x07); + ACPI_SET8(destination, + ((ACPI_GET8(source) >> info->value) & 0x07)); break; case ACPI_RSC_COUNT: item_count = ACPI_GET8(source); - ACPI_SET8(destination) = (u8) item_count; + ACPI_SET8(destination, item_count); resource->length = resource->length + (info->value * (item_count - 1)); @@ -168,7 +168,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, case ACPI_RSC_COUNT16: item_count = aml_resource_length; - ACPI_SET16(destination) = item_count; + ACPI_SET16(destination, item_count); resource->length = resource->length + (info->value * (item_count - 1)); @@ -181,20 +181,19 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, resource->length = resource->length + item_count; item_count = item_count / 2; - ACPI_SET16(destination) = item_count; + ACPI_SET16(destination, item_count); break; case ACPI_RSC_COUNT_GPIO_VEN: item_count = ACPI_GET8(source); - ACPI_SET8(destination) = (u8)item_count; + ACPI_SET8(destination, item_count); resource->length = resource->length + (info->value * item_count); break; case ACPI_RSC_COUNT_GPIO_RES: - /* * Vendor data is optional (length/offset may both be zero) * Examine vendor data length field first @@ -216,7 +215,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, } resource->length = resource->length + item_count; - ACPI_SET16(destination) = item_count; + ACPI_SET16(destination, item_count); break; case ACPI_RSC_COUNT_SERIAL_VEN: @@ -224,7 +223,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, item_count = ACPI_GET16(source) - info->value; resource->length = resource->length + item_count; - ACPI_SET16(destination) = item_count; + ACPI_SET16(destination, item_count); break; case ACPI_RSC_COUNT_SERIAL_RES: @@ -234,7 +233,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, - ACPI_GET16(source) - info->value; resource->length = resource->length + item_count; - ACPI_SET16(destination) = item_count; + ACPI_SET16(destination, item_count); break; case ACPI_RSC_LENGTH: @@ -385,7 +384,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, } target = ACPI_ADD_PTR(char, resource, info->value); - ACPI_SET8(target) = (u8) item_count; + ACPI_SET8(target, item_count); break; case ACPI_RSC_BITMASK16: @@ -401,21 +400,23 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, } target = ACPI_ADD_PTR(char, resource, info->value); - ACPI_SET8(target) = (u8) item_count; + ACPI_SET8(target, item_count); break; case ACPI_RSC_EXIT_NE: /* - * Control - Exit conversion if not equal + * control - Exit conversion if not equal */ switch (info->resource_offset) { case ACPI_RSC_COMPARE_AML_LENGTH: + if (aml_resource_length != info->value) { goto exit; } break; case ACPI_RSC_COMPARE_VALUE: + if (ACPI_GET8(source) != info->value) { goto exit; } @@ -439,7 +440,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, info++; } - exit: +exit: if (!flags_mode) { /* Round the resource struct length up to the next boundary (32 or 64) */ @@ -454,9 +455,9 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, * * FUNCTION: acpi_rs_convert_resource_to_aml * - * PARAMETERS: Resource - Pointer to the resource descriptor - * Aml - Where the AML descriptor is returned - * Info - Pointer to appropriate conversion table + * PARAMETERS: resource - Pointer to the resource descriptor + * aml - Where the AML descriptor is returned + * info - Pointer to appropriate conversion table * * RETURN: Status * @@ -514,37 +515,40 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, /* * Clear the flag byte */ - ACPI_SET8(destination) = 0; + ACPI_SET8(destination, 0); break; case ACPI_RSC_1BITFLAG: /* * Mask and shift the flag bit */ - ACPI_SET8(destination) |= (u8) - ((ACPI_GET8(source) & 0x01) << info->value); + ACPI_SET_BIT(*ACPI_CAST8(destination), (u8) + ((ACPI_GET8(source) & 0x01) << info-> + value)); break; case ACPI_RSC_2BITFLAG: /* * Mask and shift the flag bits */ - ACPI_SET8(destination) |= (u8) - ((ACPI_GET8(source) & 0x03) << info->value); + ACPI_SET_BIT(*ACPI_CAST8(destination), (u8) + ((ACPI_GET8(source) & 0x03) << info-> + value)); break; case ACPI_RSC_3BITFLAG: /* * Mask and shift the flag bits */ - ACPI_SET8(destination) |= (u8) - ((ACPI_GET8(source) & 0x07) << info->value); + ACPI_SET_BIT(*ACPI_CAST8(destination), (u8) + ((ACPI_GET8(source) & 0x07) << info-> + value)); break; case ACPI_RSC_COUNT: item_count = ACPI_GET8(source); - ACPI_SET8(destination) = (u8) item_count; + ACPI_SET8(destination, item_count); aml_length = (u16) (aml_length + @@ -561,18 +565,18 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, case ACPI_RSC_COUNT_GPIO_PIN: item_count = ACPI_GET16(source); - ACPI_SET16(destination) = (u16)aml_length; + ACPI_SET16(destination, aml_length); aml_length = (u16)(aml_length + item_count * 2); target = ACPI_ADD_PTR(void, aml, info->value); - ACPI_SET16(target) = (u16)aml_length; + ACPI_SET16(target, aml_length); acpi_rs_set_resource_length(aml_length, aml); break; case ACPI_RSC_COUNT_GPIO_VEN: item_count = ACPI_GET16(source); - ACPI_SET16(destination) = (u16)item_count; + ACPI_SET16(destination, item_count); aml_length = (u16)(aml_length + (info->value * item_count)); @@ -584,7 +588,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, /* Set resource source string length */ item_count = ACPI_GET16(source); - ACPI_SET16(destination) = (u16)aml_length; + ACPI_SET16(destination, aml_length); /* Compute offset for the Vendor Data */ @@ -594,7 +598,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, /* Set vendor offset only if there is vendor data */ if (resource->data.gpio.vendor_length) { - ACPI_SET16(target) = (u16)aml_length; + ACPI_SET16(target, aml_length); } acpi_rs_set_resource_length(aml_length, aml); @@ -603,7 +607,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, case ACPI_RSC_COUNT_SERIAL_VEN: item_count = ACPI_GET16(source); - ACPI_SET16(destination) = item_count + info->value; + ACPI_SET16(destination, item_count + info->value); aml_length = (u16)(aml_length + item_count); acpi_rs_set_resource_length(aml_length, aml); break; @@ -686,7 +690,8 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, * Optional resource_source (Index and String) */ aml_length = - acpi_rs_set_resource_source(aml, (acpi_rs_length) + acpi_rs_set_resource_source(aml, + (acpi_rs_length) aml_length, source); acpi_rs_set_resource_length(aml_length, aml); break; @@ -706,10 +711,12 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, /* * 8-bit encoded bitmask (DMA macro) */ - ACPI_SET8(destination) = (u8) - acpi_rs_encode_bitmask(source, - *ACPI_ADD_PTR(u8, resource, - info->value)); + ACPI_SET8(destination, + acpi_rs_encode_bitmask(source, + *ACPI_ADD_PTR(u8, + resource, + info-> + value))); break; case ACPI_RSC_BITMASK16: @@ -726,7 +733,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, case ACPI_RSC_EXIT_LE: /* - * Control - Exit conversion if less than or equal + * control - Exit conversion if less than or equal */ if (item_count <= info->value) { goto exit; @@ -735,7 +742,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, case ACPI_RSC_EXIT_NE: /* - * Control - Exit conversion if not equal + * control - Exit conversion if not equal */ switch (COMPARE_OPCODE(info)) { case ACPI_RSC_COMPARE_VALUE: @@ -757,7 +764,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, case ACPI_RSC_EXIT_EQ: /* - * Control - Exit conversion if equal + * control - Exit conversion if equal */ if (*ACPI_ADD_PTR(u8, resource, COMPARE_TARGET(info)) == @@ -776,14 +783,14 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, info++; } - exit: +exit: return_ACPI_STATUS(AE_OK); } #if 0 /* Previous resource validations */ -if (aml->ext_address64.revision_iD != AML_RESOURCE_EXTENDED_ADDRESS_REVISION) { +if (aml->ext_address64.revision_ID != AML_RESOURCE_EXTENDED_ADDRESS_REVISION) { return_ACPI_STATUS(AE_SUPPORT); } diff --git a/drivers/acpi/acpica/rsserial.c b/drivers/acpi/acpica/rsserial.c index 9aa5e689b44..9e8407223d9 100644 --- a/drivers/acpi/acpica/rsserial.c +++ b/drivers/acpi/acpica/rsserial.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,7 +53,7 @@ ACPI_MODULE_NAME("rsserial") * acpi_rs_convert_gpio * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_convert_gpio[17] = { +struct acpi_rsconvert_info acpi_rs_convert_gpio[18] = { {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_GPIO, ACPI_RS_SIZE(struct acpi_resource_gpio), ACPI_RSC_TABLE_SIZE(acpi_rs_convert_gpio)}, @@ -75,10 +75,14 @@ struct acpi_rsconvert_info acpi_rs_convert_gpio[17] = { AML_OFFSET(gpio.flags), 0}, - {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.gpio.sharable), + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.gpio.sharable), AML_OFFSET(gpio.int_flags), 3}, + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.gpio.wake_capable), + AML_OFFSET(gpio.int_flags), + 4}, + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.gpio.io_restriction), AML_OFFSET(gpio.int_flags), 0}, diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c index 433a375deb9..897a5ceb042 100644 --- a/drivers/acpi/acpica/rsutils.c +++ b/drivers/acpi/acpica/rsutils.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,8 +53,8 @@ ACPI_MODULE_NAME("rsutils") * * FUNCTION: acpi_rs_decode_bitmask * - * PARAMETERS: Mask - Bitmask to decode - * List - Where the converted list is returned + * PARAMETERS: mask - Bitmask to decode + * list - Where the converted list is returned * * RETURN: Count of bits set (length of list) * @@ -86,8 +86,8 @@ u8 acpi_rs_decode_bitmask(u16 mask, u8 * list) * * FUNCTION: acpi_rs_encode_bitmask * - * PARAMETERS: List - List of values to encode - * Count - Length of list + * PARAMETERS: list - List of values to encode + * count - Length of list * * RETURN: Encoded bitmask * @@ -108,15 +108,15 @@ u16 acpi_rs_encode_bitmask(u8 * list, u8 count) mask |= (0x1 << list[i]); } - return mask; + return (mask); } /******************************************************************************* * * FUNCTION: acpi_rs_move_data * - * PARAMETERS: Destination - Pointer to the destination descriptor - * Source - Pointer to the source descriptor + * PARAMETERS: destination - Pointer to the destination descriptor + * source - Pointer to the source descriptor * item_count - How many items to move * move_type - Byte width * @@ -147,6 +147,7 @@ acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type) case ACPI_RSC_MOVE_GPIO_RES: case ACPI_RSC_MOVE_SERIAL_VEN: case ACPI_RSC_MOVE_SERIAL_RES: + ACPI_MEMCPY(destination, source, item_count); return; @@ -157,21 +158,25 @@ acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type) */ case ACPI_RSC_MOVE16: case ACPI_RSC_MOVE_GPIO_PIN: + ACPI_MOVE_16_TO_16(&ACPI_CAST_PTR(u16, destination)[i], &ACPI_CAST_PTR(u16, source)[i]); break; case ACPI_RSC_MOVE32: + ACPI_MOVE_32_TO_32(&ACPI_CAST_PTR(u32, destination)[i], &ACPI_CAST_PTR(u32, source)[i]); break; case ACPI_RSC_MOVE64: + ACPI_MOVE_64_TO_64(&ACPI_CAST_PTR(u64, destination)[i], &ACPI_CAST_PTR(u64, source)[i]); break; default: + return; } } @@ -183,7 +188,7 @@ acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type) * * PARAMETERS: total_length - Length of the AML descriptor, including * the header and length fields. - * Aml - Pointer to the raw AML descriptor + * aml - Pointer to the raw AML descriptor * * RETURN: None * @@ -235,7 +240,7 @@ acpi_rs_set_resource_length(acpi_rsdesc_size total_length, * PARAMETERS: descriptor_type - Byte to be inserted as the type * total_length - Length of the AML descriptor, including * the header and length fields. - * Aml - Pointer to the raw AML descriptor + * aml - Pointer to the raw AML descriptor * * RETURN: None * @@ -265,8 +270,8 @@ acpi_rs_set_resource_header(u8 descriptor_type, * * FUNCTION: acpi_rs_strcpy * - * PARAMETERS: Destination - Pointer to the destination string - * Source - Pointer to the source string + * PARAMETERS: destination - Pointer to the destination string + * source - Pointer to the source string * * RETURN: String length, including NULL terminator * @@ -300,7 +305,7 @@ static u16 acpi_rs_strcpy(char *destination, char *source) * minimum_length - Minimum length of the descriptor (minus * any optional fields) * resource_source - Where the resource_source is returned - * Aml - Pointer to the raw AML descriptor + * aml - Pointer to the raw AML descriptor * string_ptr - (optional) where to store the actual * resource_source string * @@ -358,8 +363,10 @@ acpi_rs_get_resource_source(acpi_rs_length resource_length, * * Zero the entire area of the buffer. */ - total_length = (u32) - ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) + 1; + total_length = + (u32) + ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) + + 1; total_length = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(total_length); ACPI_MEMSET(resource_source->string_ptr, 0, total_length); @@ -386,7 +393,7 @@ acpi_rs_get_resource_source(acpi_rs_length resource_length, * * FUNCTION: acpi_rs_set_resource_source * - * PARAMETERS: Aml - Pointer to the raw AML descriptor + * PARAMETERS: aml - Pointer to the raw AML descriptor * minimum_length - Minimum length of the descriptor (minus * any optional fields) * resource_source - Internal resource_source @@ -445,7 +452,7 @@ acpi_rs_set_resource_source(union aml_resource * aml, * * FUNCTION: acpi_rs_get_prt_method_data * - * PARAMETERS: Node - Device node + * PARAMETERS: node - Device node * ret_buffer - Pointer to a buffer structure for the * results * @@ -494,7 +501,7 @@ acpi_rs_get_prt_method_data(struct acpi_namespace_node * node, * * FUNCTION: acpi_rs_get_crs_method_data * - * PARAMETERS: Node - Device node + * PARAMETERS: node - Device node * ret_buffer - Pointer to a buffer structure for the * results * @@ -534,7 +541,7 @@ acpi_rs_get_crs_method_data(struct acpi_namespace_node *node, */ status = acpi_rs_create_resource_list(obj_desc, ret_buffer); - /* On exit, we must delete the object returned by evaluate_object */ + /* On exit, we must delete the object returned by evaluateObject */ acpi_ut_remove_reference(obj_desc); return_ACPI_STATUS(status); @@ -544,7 +551,7 @@ acpi_rs_get_crs_method_data(struct acpi_namespace_node *node, * * FUNCTION: acpi_rs_get_prs_method_data * - * PARAMETERS: Node - Device node + * PARAMETERS: node - Device node * ret_buffer - Pointer to a buffer structure for the * results * @@ -585,7 +592,7 @@ acpi_rs_get_prs_method_data(struct acpi_namespace_node *node, */ status = acpi_rs_create_resource_list(obj_desc, ret_buffer); - /* On exit, we must delete the object returned by evaluate_object */ + /* On exit, we must delete the object returned by evaluateObject */ acpi_ut_remove_reference(obj_desc); return_ACPI_STATUS(status); @@ -596,7 +603,7 @@ acpi_rs_get_prs_method_data(struct acpi_namespace_node *node, * * FUNCTION: acpi_rs_get_aei_method_data * - * PARAMETERS: Node - Device node + * PARAMETERS: node - Device node * ret_buffer - Pointer to a buffer structure for the * results * @@ -636,7 +643,7 @@ acpi_rs_get_aei_method_data(struct acpi_namespace_node *node, */ status = acpi_rs_create_resource_list(obj_desc, ret_buffer); - /* On exit, we must delete the object returned by evaluate_object */ + /* On exit, we must delete the object returned by evaluateObject */ acpi_ut_remove_reference(obj_desc); return_ACPI_STATUS(status); @@ -646,8 +653,8 @@ acpi_rs_get_aei_method_data(struct acpi_namespace_node *node, * * FUNCTION: acpi_rs_get_method_data * - * PARAMETERS: Handle - Handle to the containing object - * Path - Path to method, relative to Handle + * PARAMETERS: handle - Handle to the containing object + * path - Path to method, relative to Handle * ret_buffer - Pointer to a buffer structure for the * results * @@ -675,7 +682,9 @@ acpi_rs_get_method_data(acpi_handle handle, /* Execute the method, no parameters */ status = - acpi_ut_evaluate_object(handle, path, ACPI_BTYPE_BUFFER, &obj_desc); + acpi_ut_evaluate_object(ACPI_CAST_PTR + (struct acpi_namespace_node, handle), path, + ACPI_BTYPE_BUFFER, &obj_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -697,7 +706,7 @@ acpi_rs_get_method_data(acpi_handle handle, * * FUNCTION: acpi_rs_set_srs_method_data * - * PARAMETERS: Node - Device node + * PARAMETERS: node - Device node * in_buffer - Pointer to a buffer structure of the * parameter * @@ -732,7 +741,7 @@ acpi_rs_set_srs_method_data(struct acpi_namespace_node *node, } info->prefix_node = node; - info->pathname = METHOD_NAME__SRS; + info->relative_pathname = METHOD_NAME__SRS; info->parameters = args; info->flags = ACPI_IGNORE_RETURN_VALUE; @@ -744,7 +753,7 @@ acpi_rs_set_srs_method_data(struct acpi_namespace_node *node, * Convert the linked list into a byte stream */ buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_rs_create_aml_resources(in_buffer->pointer, &buffer); + status = acpi_rs_create_aml_resources(in_buffer, &buffer); if (ACPI_FAILURE(status)) { goto cleanup; } @@ -775,7 +784,7 @@ acpi_rs_set_srs_method_data(struct acpi_namespace_node *node, acpi_ut_remove_reference(args[0]); - cleanup: +cleanup: ACPI_FREE(info); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c index f58c098c7ae..877ab920213 100644 --- a/drivers/acpi/acpica/rsxface.c +++ b/drivers/acpi/acpica/rsxface.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,7 +41,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include <linux/export.h> +#define EXPORT_ACPI_INTERFACES + #include <acpi/acpi.h> #include "accommon.h" #include "acresrc.h" @@ -79,7 +80,7 @@ acpi_rs_validate_parameters(acpi_handle device_handle, * FUNCTION: acpi_rs_validate_parameters * * PARAMETERS: device_handle - Handle to a device - * Buffer - Pointer to a data buffer + * buffer - Pointer to a data buffer * return_node - Pointer to where the device node is returned * * RETURN: Status @@ -351,8 +352,8 @@ ACPI_EXPORT_SYMBOL(acpi_get_event_resources) * * FUNCTION: acpi_resource_to_address64 * - * PARAMETERS: Resource - Pointer to a resource - * Out - Pointer to the users's return buffer + * PARAMETERS: resource - Pointer to a resource + * out - Pointer to the users's return buffer * (a struct acpi_resource_address64) * * RETURN: Status @@ -402,6 +403,7 @@ acpi_resource_to_address64(struct acpi_resource *resource, break; default: + return (AE_BAD_PARAMETER); } @@ -415,15 +417,15 @@ ACPI_EXPORT_SYMBOL(acpi_resource_to_address64) * FUNCTION: acpi_get_vendor_resource * * PARAMETERS: device_handle - Handle for the parent device object - * Name - Method name for the parent resource + * name - Method name for the parent resource * (METHOD_NAME__CRS or METHOD_NAME__PRS) - * Uuid - Pointer to the UUID to be matched. + * uuid - Pointer to the UUID to be matched. * includes both subtype and 16-byte UUID * ret_buffer - Where the vendor resource is returned * * RETURN: Status * - * DESCRIPTION: Walk a resource template for the specified evice to find a + * DESCRIPTION: Walk a resource template for the specified device to find a * vendor-defined resource that matches the supplied UUID and * UUID subtype. Returns a struct acpi_resource of type Vendor. * @@ -522,69 +524,60 @@ acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context) /******************************************************************************* * - * FUNCTION: acpi_walk_resources + * FUNCTION: acpi_walk_resource_buffer * - * PARAMETERS: device_handle - Handle to the device object for the - * device we are querying - * Name - Method name of the resources we want. - * (METHOD_NAME__CRS, METHOD_NAME__PRS, or - * METHOD_NAME__AEI) + * PARAMETERS: buffer - Formatted buffer returned by one of the + * various Get*Resource functions * user_function - Called for each resource - * Context - Passed to user_function + * context - Passed to user_function * * RETURN: Status * - * DESCRIPTION: Retrieves the current or possible resource list for the - * specified device. The user_function is called once for - * each resource in the list. + * DESCRIPTION: Walks the input resource template. The user_function is called + * once for each resource in the list. * ******************************************************************************/ + acpi_status -acpi_walk_resources(acpi_handle device_handle, - char *name, - acpi_walk_resource_callback user_function, void *context) +acpi_walk_resource_buffer(struct acpi_buffer * buffer, + acpi_walk_resource_callback user_function, + void *context) { - acpi_status status; - struct acpi_buffer buffer; + acpi_status status = AE_OK; struct acpi_resource *resource; struct acpi_resource *resource_end; - ACPI_FUNCTION_TRACE(acpi_walk_resources); + ACPI_FUNCTION_TRACE(acpi_walk_resource_buffer); /* Parameter validation */ - if (!device_handle || !user_function || !name || - (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) && - !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS) && - !ACPI_COMPARE_NAME(name, METHOD_NAME__AEI))) { + if (!buffer || !buffer->pointer || !user_function) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Get the _CRS/_PRS/_AEI resource list */ - - buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_rs_get_method_data(device_handle, name, &buffer); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Buffer now contains the resource list */ + /* Buffer contains the resource list and length */ - resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer); + resource = ACPI_CAST_PTR(struct acpi_resource, buffer->pointer); resource_end = - ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length); + ACPI_ADD_PTR(struct acpi_resource, buffer->pointer, buffer->length); /* Walk the resource list until the end_tag is found (or buffer end) */ while (resource < resource_end) { - /* Sanity check the resource */ + /* Sanity check the resource type */ if (resource->type > ACPI_RESOURCE_TYPE_MAX) { status = AE_AML_INVALID_RESOURCE_TYPE; break; } + /* Sanity check the length. It must not be zero, or we loop forever */ + + if (!resource->length) { + return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); + } + /* Invoke the user function, abort on any error returned */ status = user_function(resource, context); @@ -606,11 +599,63 @@ acpi_walk_resources(acpi_handle device_handle, /* Get the next resource descriptor */ - resource = - ACPI_ADD_PTR(struct acpi_resource, resource, - resource->length); + resource = ACPI_NEXT_RESOURCE(resource); } + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_walk_resource_buffer) + +/******************************************************************************* + * + * FUNCTION: acpi_walk_resources + * + * PARAMETERS: device_handle - Handle to the device object for the + * device we are querying + * name - Method name of the resources we want. + * (METHOD_NAME__CRS, METHOD_NAME__PRS, or + * METHOD_NAME__AEI) + * user_function - Called for each resource + * context - Passed to user_function + * + * RETURN: Status + * + * DESCRIPTION: Retrieves the current or possible resource list for the + * specified device. The user_function is called once for + * each resource in the list. + * + ******************************************************************************/ +acpi_status +acpi_walk_resources(acpi_handle device_handle, + char *name, + acpi_walk_resource_callback user_function, void *context) +{ + acpi_status status; + struct acpi_buffer buffer; + + ACPI_FUNCTION_TRACE(acpi_walk_resources); + + /* Parameter validation */ + + if (!device_handle || !user_function || !name || + (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) && + !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS) && + !ACPI_COMPARE_NAME(name, METHOD_NAME__AEI))) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Get the _CRS/_PRS/_AEI resource list */ + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_rs_get_method_data(device_handle, name, &buffer); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Walk the resource list and cleanup */ + + status = acpi_walk_resource_buffer(&buffer, user_function, context); ACPI_FREE(buffer.pointer); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/tbdata.c b/drivers/acpi/acpica/tbdata.c new file mode 100644 index 00000000000..f499c10ceb4 --- /dev/null +++ b/drivers/acpi/acpica/tbdata.c @@ -0,0 +1,760 @@ +/****************************************************************************** + * + * Module Name: tbdata - Table manager data structure functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acnamesp.h" +#include "actables.h" + +#define _COMPONENT ACPI_TABLES +ACPI_MODULE_NAME("tbdata") + +/******************************************************************************* + * + * FUNCTION: acpi_tb_init_table_descriptor + * + * PARAMETERS: table_desc - Table descriptor + * address - Physical address of the table + * flags - Allocation flags of the table + * table - Pointer to the table + * + * RETURN: None + * + * DESCRIPTION: Initialize a new table descriptor + * + ******************************************************************************/ +void +acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc, + acpi_physical_address address, + u8 flags, struct acpi_table_header *table) +{ + + /* + * Initialize the table descriptor. Set the pointer to NULL, since the + * table is not fully mapped at this time. + */ + ACPI_MEMSET(table_desc, 0, sizeof(struct acpi_table_desc)); + table_desc->address = address; + table_desc->length = table->length; + table_desc->flags = flags; + ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_acquire_table + * + * PARAMETERS: table_desc - Table descriptor + * table_ptr - Where table is returned + * table_length - Where table length is returned + * table_flags - Where table allocation flags are returned + * + * RETURN: Status + * + * DESCRIPTION: Acquire an ACPI table. It can be used for tables not + * maintained in the acpi_gbl_root_table_list. + * + ******************************************************************************/ + +acpi_status +acpi_tb_acquire_table(struct acpi_table_desc *table_desc, + struct acpi_table_header **table_ptr, + u32 *table_length, u8 *table_flags) +{ + struct acpi_table_header *table = NULL; + + switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { + case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: + + table = + acpi_os_map_memory(table_desc->address, table_desc->length); + break; + + case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: + case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: + + table = + ACPI_CAST_PTR(struct acpi_table_header, + table_desc->address); + break; + + default: + + break; + } + + /* Table is not valid yet */ + + if (!table) { + return (AE_NO_MEMORY); + } + + /* Fill the return values */ + + *table_ptr = table; + *table_length = table_desc->length; + *table_flags = table_desc->flags; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_release_table + * + * PARAMETERS: table - Pointer for the table + * table_length - Length for the table + * table_flags - Allocation flags for the table + * + * RETURN: None + * + * DESCRIPTION: Release a table. The inverse of acpi_tb_acquire_table(). + * + ******************************************************************************/ + +void +acpi_tb_release_table(struct acpi_table_header *table, + u32 table_length, u8 table_flags) +{ + + switch (table_flags & ACPI_TABLE_ORIGIN_MASK) { + case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: + + acpi_os_unmap_memory(table, table_length); + break; + + case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: + case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: + default: + + break; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_acquire_temp_table + * + * PARAMETERS: table_desc - Table descriptor to be acquired + * address - Address of the table + * flags - Allocation flags of the table + * + * RETURN: Status + * + * DESCRIPTION: This function validates the table header to obtain the length + * of a table and fills the table descriptor to make its state as + * "INSTALLED". Such a table descriptor is only used for verified + * installation. + * + ******************************************************************************/ + +acpi_status +acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc, + acpi_physical_address address, u8 flags) +{ + struct acpi_table_header *table_header; + + switch (flags & ACPI_TABLE_ORIGIN_MASK) { + case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: + + /* Get the length of the full table from the header */ + + table_header = + acpi_os_map_memory(address, + sizeof(struct acpi_table_header)); + if (!table_header) { + return (AE_NO_MEMORY); + } + + acpi_tb_init_table_descriptor(table_desc, address, flags, + table_header); + acpi_os_unmap_memory(table_header, + sizeof(struct acpi_table_header)); + return (AE_OK); + + case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: + case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: + + table_header = ACPI_CAST_PTR(struct acpi_table_header, address); + if (!table_header) { + return (AE_NO_MEMORY); + } + + acpi_tb_init_table_descriptor(table_desc, address, flags, + table_header); + return (AE_OK); + + default: + + break; + } + + /* Table is not valid yet */ + + return (AE_NO_MEMORY); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_release_temp_table + * + * PARAMETERS: table_desc - Table descriptor to be released + * + * RETURN: Status + * + * DESCRIPTION: The inverse of acpi_tb_acquire_temp_table(). + * + *****************************************************************************/ + +void acpi_tb_release_temp_table(struct acpi_table_desc *table_desc) +{ + + /* + * Note that the .Address is maintained by the callers of + * acpi_tb_acquire_temp_table(), thus do not invoke acpi_tb_uninstall_table() + * where .Address will be freed. + */ + acpi_tb_invalidate_table(table_desc); +} + +/****************************************************************************** + * + * FUNCTION: acpi_tb_validate_table + * + * PARAMETERS: table_desc - Table descriptor + * + * RETURN: Status + * + * DESCRIPTION: This function is called to validate the table, the returned + * table descriptor is in "VALIDATED" state. + * + *****************************************************************************/ + +acpi_status acpi_tb_validate_table(struct acpi_table_desc *table_desc) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(tb_validate_table); + + /* Validate the table if necessary */ + + if (!table_desc->pointer) { + status = acpi_tb_acquire_table(table_desc, &table_desc->pointer, + &table_desc->length, + &table_desc->flags); + if (!table_desc->pointer) { + status = AE_NO_MEMORY; + } + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_invalidate_table + * + * PARAMETERS: table_desc - Table descriptor + * + * RETURN: None + * + * DESCRIPTION: Invalidate one internal ACPI table, this is the inverse of + * acpi_tb_validate_table(). + * + ******************************************************************************/ + +void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc) +{ + + ACPI_FUNCTION_TRACE(tb_invalidate_table); + + /* Table must be validated */ + + if (!table_desc->pointer) { + return_VOID; + } + + acpi_tb_release_table(table_desc->pointer, table_desc->length, + table_desc->flags); + table_desc->pointer = NULL; + + return_VOID; +} + +/****************************************************************************** + * + * FUNCTION: acpi_tb_validate_temp_table + * + * PARAMETERS: table_desc - Table descriptor + * + * RETURN: Status + * + * DESCRIPTION: This function is called to validate the table, the returned + * table descriptor is in "VALIDATED" state. + * + *****************************************************************************/ + +acpi_status acpi_tb_validate_temp_table(struct acpi_table_desc *table_desc) +{ + + if (!table_desc->pointer && !acpi_gbl_verify_table_checksum) { + /* + * Only validates the header of the table. + * Note that Length contains the size of the mapping after invoking + * this work around, this value is required by + * acpi_tb_release_temp_table(). + * We can do this because in acpi_init_table_descriptor(), the Length + * field of the installed descriptor is filled with the actual + * table length obtaining from the table header. + */ + table_desc->length = sizeof(struct acpi_table_header); + } + + return (acpi_tb_validate_table(table_desc)); +} + +/****************************************************************************** + * + * FUNCTION: acpi_tb_verify_temp_table + * + * PARAMETERS: table_desc - Table descriptor + * signature - Table signature to verify + * + * RETURN: Status + * + * DESCRIPTION: This function is called to validate and verify the table, the + * returned table descriptor is in "VALIDATED" state. + * + *****************************************************************************/ + +acpi_status +acpi_tb_verify_temp_table(struct acpi_table_desc * table_desc, char *signature) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(tb_verify_temp_table); + + /* Validate the table */ + + status = acpi_tb_validate_temp_table(table_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* If a particular signature is expected (DSDT/FACS), it must match */ + + if (signature && !ACPI_COMPARE_NAME(&table_desc->signature, signature)) { + ACPI_BIOS_ERROR((AE_INFO, + "Invalid signature 0x%X for ACPI table, expected [%s]", + table_desc->signature.integer, signature)); + status = AE_BAD_SIGNATURE; + goto invalidate_and_exit; + } + + /* Verify the checksum */ + + if (acpi_gbl_verify_table_checksum) { + status = + acpi_tb_verify_checksum(table_desc->pointer, + table_desc->length); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, + "%4.4s " ACPI_PRINTF_UINT + " Attempted table install failed", + acpi_ut_valid_acpi_name(table_desc-> + signature. + ascii) ? + table_desc->signature.ascii : "????", + ACPI_FORMAT_TO_UINT(table_desc-> + address))); + goto invalidate_and_exit; + } + } + + return_ACPI_STATUS(AE_OK); + +invalidate_and_exit: + acpi_tb_invalidate_table(table_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_resize_root_table_list + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Expand the size of global table array + * + ******************************************************************************/ + +acpi_status acpi_tb_resize_root_table_list(void) +{ + struct acpi_table_desc *tables; + u32 table_count; + + ACPI_FUNCTION_TRACE(tb_resize_root_table_list); + + /* allow_resize flag is a parameter to acpi_initialize_tables */ + + if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) { + ACPI_ERROR((AE_INFO, + "Resize of Root Table Array is not allowed")); + return_ACPI_STATUS(AE_SUPPORT); + } + + /* Increase the Table Array size */ + + if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { + table_count = acpi_gbl_root_table_list.max_table_count; + } else { + table_count = acpi_gbl_root_table_list.current_table_count; + } + + tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count + + ACPI_ROOT_TABLE_SIZE_INCREMENT) * + sizeof(struct acpi_table_desc)); + if (!tables) { + ACPI_ERROR((AE_INFO, + "Could not allocate new root table array")); + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Copy and free the previous table array */ + + if (acpi_gbl_root_table_list.tables) { + ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, + (acpi_size) table_count * + sizeof(struct acpi_table_desc)); + + if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { + ACPI_FREE(acpi_gbl_root_table_list.tables); + } + } + + acpi_gbl_root_table_list.tables = tables; + acpi_gbl_root_table_list.max_table_count = + table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT; + acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED; + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_get_next_root_index + * + * PARAMETERS: table_index - Where table index is returned + * + * RETURN: Status and table index. + * + * DESCRIPTION: Allocate a new ACPI table entry to the global table list + * + ******************************************************************************/ + +acpi_status acpi_tb_get_next_root_index(u32 *table_index) +{ + acpi_status status; + + /* Ensure that there is room for the table in the Root Table List */ + + if (acpi_gbl_root_table_list.current_table_count >= + acpi_gbl_root_table_list.max_table_count) { + status = acpi_tb_resize_root_table_list(); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + *table_index = acpi_gbl_root_table_list.current_table_count; + acpi_gbl_root_table_list.current_table_count++; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_terminate + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Delete all internal ACPI tables + * + ******************************************************************************/ + +void acpi_tb_terminate(void) +{ + u32 i; + + ACPI_FUNCTION_TRACE(tb_terminate); + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + + /* Delete the individual tables */ + + for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { + acpi_tb_uninstall_table(&acpi_gbl_root_table_list.tables[i]); + } + + /* + * Delete the root table array if allocated locally. Array cannot be + * mapped, so we don't need to check for that flag. + */ + if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { + ACPI_FREE(acpi_gbl_root_table_list.tables); + } + + acpi_gbl_root_table_list.tables = NULL; + acpi_gbl_root_table_list.flags = 0; + acpi_gbl_root_table_list.current_table_count = 0; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n")); + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_delete_namespace_by_owner + * + * PARAMETERS: table_index - Table index + * + * RETURN: Status + * + * DESCRIPTION: Delete all namespace objects created when this table was loaded. + * + ******************************************************************************/ + +acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index) +{ + acpi_owner_id owner_id; + acpi_status status; + + ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner); + + status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (table_index >= acpi_gbl_root_table_list.current_table_count) { + + /* The table index does not exist */ + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* Get the owner ID for this table, used to delete namespace nodes */ + + owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id; + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + + /* + * Need to acquire the namespace writer lock to prevent interference + * with any concurrent namespace walks. The interpreter must be + * released during the deletion since the acquisition of the deletion + * lock may block, and also since the execution of a namespace walk + * must be allowed to use the interpreter. + */ + (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); + status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock); + + acpi_ns_delete_namespace_by_owner(owner_id); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock); + + status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_allocate_owner_id + * + * PARAMETERS: table_index - Table index + * + * RETURN: Status + * + * DESCRIPTION: Allocates owner_id in table_desc + * + ******************************************************************************/ + +acpi_status acpi_tb_allocate_owner_id(u32 table_index) +{ + acpi_status status = AE_BAD_PARAMETER; + + ACPI_FUNCTION_TRACE(tb_allocate_owner_id); + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (table_index < acpi_gbl_root_table_list.current_table_count) { + status = + acpi_ut_allocate_owner_id(& + (acpi_gbl_root_table_list. + tables[table_index].owner_id)); + } + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_release_owner_id + * + * PARAMETERS: table_index - Table index + * + * RETURN: Status + * + * DESCRIPTION: Releases owner_id in table_desc + * + ******************************************************************************/ + +acpi_status acpi_tb_release_owner_id(u32 table_index) +{ + acpi_status status = AE_BAD_PARAMETER; + + ACPI_FUNCTION_TRACE(tb_release_owner_id); + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (table_index < acpi_gbl_root_table_list.current_table_count) { + acpi_ut_release_owner_id(& + (acpi_gbl_root_table_list. + tables[table_index].owner_id)); + status = AE_OK; + } + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_get_owner_id + * + * PARAMETERS: table_index - Table index + * owner_id - Where the table owner_id is returned + * + * RETURN: Status + * + * DESCRIPTION: returns owner_id for the ACPI table + * + ******************************************************************************/ + +acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id * owner_id) +{ + acpi_status status = AE_BAD_PARAMETER; + + ACPI_FUNCTION_TRACE(tb_get_owner_id); + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (table_index < acpi_gbl_root_table_list.current_table_count) { + *owner_id = + acpi_gbl_root_table_list.tables[table_index].owner_id; + status = AE_OK; + } + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_is_table_loaded + * + * PARAMETERS: table_index - Index into the root table + * + * RETURN: Table Loaded Flag + * + ******************************************************************************/ + +u8 acpi_tb_is_table_loaded(u32 table_index) +{ + u8 is_loaded = FALSE; + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (table_index < acpi_gbl_root_table_list.current_table_count) { + is_loaded = (u8) + (acpi_gbl_root_table_list.tables[table_index].flags & + ACPI_TABLE_IS_LOADED); + } + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return (is_loaded); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_set_table_loaded_flag + * + * PARAMETERS: table_index - Table index + * is_loaded - TRUE if table is loaded, FALSE otherwise + * + * RETURN: None + * + * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE. + * + ******************************************************************************/ + +void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded) +{ + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (table_index < acpi_gbl_root_table_list.current_table_count) { + if (is_loaded) { + acpi_gbl_root_table_list.tables[table_index].flags |= + ACPI_TABLE_IS_LOADED; + } else { + acpi_gbl_root_table_list.tables[table_index].flags &= + ~ACPI_TABLE_IS_LOADED; + } + } + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); +} diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index c5d870406f4..41519a95808 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,16 +49,19 @@ ACPI_MODULE_NAME("tbfadt") /* Local prototypes */ -static ACPI_INLINE void +static void acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, - u8 space_id, u8 byte_width, u64 address); + u8 space_id, + u8 byte_width, + u64 address, char *register_name, u8 flags); static void acpi_tb_convert_fadt(void); -static void acpi_tb_validate_fadt(void); - static void acpi_tb_setup_fadt_registers(void); +static u64 +acpi_tb_select_address(char *register_name, u32 address32, u64 address64); + /* Table for conversion of FADT to common internal format and FADT validation */ typedef struct acpi_fadt_info { @@ -67,13 +70,14 @@ typedef struct acpi_fadt_info { u16 address32; u16 length; u8 default_length; - u8 type; + u8 flags; } acpi_fadt_info; #define ACPI_FADT_OPTIONAL 0 #define ACPI_FADT_REQUIRED 1 #define ACPI_FADT_SEPARATE_LENGTH 2 +#define ACPI_FADT_GPE_REGISTER 4 static struct acpi_fadt_info fadt_info_table[] = { {"Pm1aEventBlock", @@ -116,21 +120,21 @@ static struct acpi_fadt_info fadt_info_table[] = { ACPI_FADT_OFFSET(pm_timer_block), ACPI_FADT_OFFSET(pm_timer_length), ACPI_PM_TIMER_WIDTH, - ACPI_FADT_REQUIRED}, + ACPI_FADT_SEPARATE_LENGTH}, /* ACPI 5.0A: Timer is optional */ {"Gpe0Block", ACPI_FADT_OFFSET(xgpe0_block), ACPI_FADT_OFFSET(gpe0_block), ACPI_FADT_OFFSET(gpe0_block_length), 0, - ACPI_FADT_SEPARATE_LENGTH}, + ACPI_FADT_SEPARATE_LENGTH | ACPI_FADT_GPE_REGISTER}, {"Gpe1Block", ACPI_FADT_OFFSET(xgpe1_block), ACPI_FADT_OFFSET(gpe1_block), ACPI_FADT_OFFSET(gpe1_block_length), 0, - ACPI_FADT_SEPARATE_LENGTH} + ACPI_FADT_SEPARATE_LENGTH | ACPI_FADT_GPE_REGISTER} }; #define ACPI_FADT_INFO_ENTRIES \ @@ -171,8 +175,10 @@ static struct acpi_fadt_pm_info fadt_pm_info_table[] = { * FUNCTION: acpi_tb_init_generic_address * * PARAMETERS: generic_address - GAS struct to be initialized + * space_id - ACPI Space ID for this register * byte_width - Width of this register - * Address - Address of the register + * address - Address of the register + * register_name - ASCII name of the ACPI register * * RETURN: None * @@ -182,10 +188,35 @@ static struct acpi_fadt_pm_info fadt_pm_info_table[] = { * ******************************************************************************/ -static ACPI_INLINE void +static void acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, - u8 space_id, u8 byte_width, u64 address) + u8 space_id, + u8 byte_width, + u64 address, char *register_name, u8 flags) { + u8 bit_width; + + /* + * Bit width field in the GAS is only one byte long, 255 max. + * Check for bit_width overflow in GAS. + */ + bit_width = (u8)(byte_width * 8); + if (byte_width > 31) { /* (31*8)=248, (32*8)=256 */ + /* + * No error for GPE blocks, because we do not use the bit_width + * for GPEs, the legacy length (byte_width) is used instead to + * allow for a large number of GPEs. + */ + if (!(flags & ACPI_FADT_GPE_REGISTER)) { + ACPI_ERROR((AE_INFO, + "%s - 32-bit FADT register is too long (%u bytes, %u bits) " + "to convert to GAS struct - 255 bits max, truncating", + register_name, byte_width, + (byte_width * 8))); + } + + bit_width = 255; + } /* * The 64-bit Address field is non-aligned in the byte packed @@ -196,13 +227,75 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, /* All other fields are byte-wide */ generic_address->space_id = space_id; - generic_address->bit_width = (u8)ACPI_MUL_8(byte_width); + generic_address->bit_width = bit_width; generic_address->bit_offset = 0; generic_address->access_width = 0; /* Access width ANY */ } /******************************************************************************* * + * FUNCTION: acpi_tb_select_address + * + * PARAMETERS: register_name - ASCII name of the ACPI register + * address32 - 32-bit address of the register + * address64 - 64-bit address of the register + * + * RETURN: The resolved 64-bit address + * + * DESCRIPTION: Select between 32-bit and 64-bit versions of addresses within + * the FADT. Used for the FACS and DSDT addresses. + * + * NOTES: + * + * Check for FACS and DSDT address mismatches. An address mismatch between + * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and + * DSDT/X_DSDT) could be a corrupted address field or it might indicate + * the presence of two FACS or two DSDT tables. + * + * November 2013: + * By default, as per the ACPICA specification, a valid 64-bit address is + * used regardless of the value of the 32-bit address. However, this + * behavior can be overridden via the acpi_gbl_use32_bit_fadt_addresses flag. + * + ******************************************************************************/ + +static u64 +acpi_tb_select_address(char *register_name, u32 address32, u64 address64) +{ + + if (!address64) { + + /* 64-bit address is zero, use 32-bit address */ + + return ((u64)address32); + } + + if (address32 && (address64 != (u64)address32)) { + + /* Address mismatch between 32-bit and 64-bit versions */ + + ACPI_BIOS_WARNING((AE_INFO, + "32/64X %s address mismatch in FADT: " + "0x%8.8X/0x%8.8X%8.8X, using %u-bit address", + register_name, address32, + ACPI_FORMAT_UINT64(address64), + acpi_gbl_use32_bit_fadt_addresses ? 32 : + 64)); + + /* 32-bit address override */ + + if (acpi_gbl_use32_bit_fadt_addresses) { + return ((u64)address32); + } + } + + /* Default is to use the 64-bit address */ + + return (address64); +} + +/******************************************************************************* + * * FUNCTION: acpi_tb_parse_fadt * * PARAMETERS: table_index - Index for the FADT @@ -251,15 +344,15 @@ void acpi_tb_parse_fadt(u32 table_index) /* Obtain the DSDT and FACS tables via their addresses within the FADT */ - acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt, - ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); + acpi_tb_install_fixed_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt, + ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); /* If Hardware Reduced flag is set, there is no FACS */ if (!acpi_gbl_reduced_hardware) { - acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT. - Xfacs, ACPI_SIG_FACS, - ACPI_TABLE_INDEX_FACS); + acpi_tb_install_fixed_table((acpi_physical_address) + acpi_gbl_FADT.Xfacs, ACPI_SIG_FACS, + ACPI_TABLE_INDEX_FACS); } } @@ -267,8 +360,8 @@ void acpi_tb_parse_fadt(u32 table_index) * * FUNCTION: acpi_tb_create_local_fadt * - * PARAMETERS: Table - Pointer to BIOS FADT - * Length - Length of the table + * PARAMETERS: table - Pointer to BIOS FADT + * length - Length of the table * * RETURN: None * @@ -287,11 +380,11 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) * a warning. */ if (length > sizeof(struct acpi_table_fadt)) { - ACPI_WARNING((AE_INFO, - "FADT (revision %u) is longer than ACPI 5.0 version, " - "truncating length %u to %u", - table->revision, length, - (u32)sizeof(struct acpi_table_fadt))); + ACPI_BIOS_WARNING((AE_INFO, + "FADT (revision %u) is longer than ACPI 5.0 version, " + "truncating length %u to %u", + table->revision, length, + (u32)sizeof(struct acpi_table_fadt))); } /* Clear the entire local FADT */ @@ -314,10 +407,6 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) acpi_tb_convert_fadt(); - /* Validate FADT values now, before we make any changes */ - - acpi_tb_validate_fadt(); - /* Initialize the global ACPI register structures */ acpi_tb_setup_fadt_registers(); @@ -327,76 +416,62 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) * * FUNCTION: acpi_tb_convert_fadt * - * PARAMETERS: None, uses acpi_gbl_FADT + * PARAMETERS: none - acpi_gbl_FADT is used. * * RETURN: None * * DESCRIPTION: Converts all versions of the FADT to a common internal format. - * Expand 32-bit addresses to 64-bit as necessary. + * Expand 32-bit addresses to 64-bit as necessary. Also validate + * important fields within the FADT. * - * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), - * and must contain a copy of the actual FADT. + * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), and must + * contain a copy of the actual BIOS-provided FADT. * * Notes on 64-bit register addresses: * * After this FADT conversion, later ACPICA code will only use the 64-bit "X" * fields of the FADT for all ACPI register addresses. * - * The 64-bit "X" fields are optional extensions to the original 32-bit FADT + * The 64-bit X fields are optional extensions to the original 32-bit FADT * V1.0 fields. Even if they are present in the FADT, they are optional and * are unused if the BIOS sets them to zero. Therefore, we must copy/expand - * 32-bit V1.0 fields if the corresponding X field is zero. + * 32-bit V1.0 fields to the 64-bit X fields if the the 64-bit X field is + * originally zero. * - * For ACPI 1.0 FADTs, all 32-bit address fields are expanded to the - * corresponding "X" fields in the internal FADT. + * For ACPI 1.0 FADTs (that contain no 64-bit addresses), all 32-bit address + * fields are expanded to the corresponding 64-bit X fields in the internal + * common FADT. * * For ACPI 2.0+ FADTs, all valid (non-zero) 32-bit address fields are expanded - * to the corresponding 64-bit X fields. For compatibility with other ACPI - * implementations, we ignore the 64-bit field if the 32-bit field is valid, - * regardless of whether the host OS is 32-bit or 64-bit. + * to the corresponding 64-bit X fields, if the 64-bit field is originally + * zero. Adhering to the ACPI specification, we completely ignore the 32-bit + * field if the 64-bit field is valid, regardless of whether the host OS is + * 32-bit or 64-bit. + * + * Possible additional checks: + * (acpi_gbl_FADT.pm1_event_length >= 4) + * (acpi_gbl_FADT.pm1_control_length >= 2) + * (acpi_gbl_FADT.pm_timer_length >= 4) + * Gpe block lengths must be multiple of 2 * ******************************************************************************/ static void acpi_tb_convert_fadt(void) { + char *name; struct acpi_generic_address *address64; u32 address32; + u8 length; + u8 flags; u32 i; - /* Update the local FADT table header length */ - - acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); - - /* - * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary. - * Later code will always use the X 64-bit field. Also, check for an - * address mismatch between the 32-bit and 64-bit address fields - * (FIRMWARE_CTRL/X_FIRMWARE_CTRL, DSDT/X_DSDT) which would indicate - * the presence of two FACS or two DSDT tables. - */ - if (!acpi_gbl_FADT.Xfacs) { - acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs; - } else if (acpi_gbl_FADT.facs && - (acpi_gbl_FADT.Xfacs != (u64) acpi_gbl_FADT.facs)) { - ACPI_WARNING((AE_INFO, - "32/64 FACS address mismatch in FADT - two FACS tables!")); - } - - if (!acpi_gbl_FADT.Xdsdt) { - acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt; - } else if (acpi_gbl_FADT.dsdt && - (acpi_gbl_FADT.Xdsdt != (u64) acpi_gbl_FADT.dsdt)) { - ACPI_WARNING((AE_INFO, - "32/64 DSDT address mismatch in FADT - two DSDT tables!")); - } - /* * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which * should be zero are indeed zero. This will workaround BIOSs that * inadvertently place values in these fields. * - * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at - * offset 45, 55, 95, and the word located at offset 109, 110. + * The ACPI 1.0 reserved fields that will be zeroed are the bytes located + * at offset 45, 55, 95, and the word located at offset 109, 110. * * Note: The FADT revision value is unreliable. Only the length can be * trusted. @@ -409,111 +484,23 @@ static void acpi_tb_convert_fadt(void) } /* - * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" - * generic address structures as necessary. Later code will always use - * the 64-bit address structures. - * - * March 2009: - * We now always use the 32-bit address if it is valid (non-null). This - * is not in accordance with the ACPI specification which states that - * the 64-bit address supersedes the 32-bit version, but we do this for - * compatibility with other ACPI implementations. Most notably, in the - * case where both the 32 and 64 versions are non-null, we use the 32-bit - * version. This is the only address that is guaranteed to have been - * tested by the BIOS manufacturer. + * Now we can update the local FADT length to the length of the + * current FADT version as defined by the ACPI specification. + * Thus, we will have a common FADT internally. */ - for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { - address32 = *ACPI_ADD_PTR(u32, - &acpi_gbl_FADT, - fadt_info_table[i].address32); - - address64 = ACPI_ADD_PTR(struct acpi_generic_address, - &acpi_gbl_FADT, - fadt_info_table[i].address64); - - /* - * If both 32- and 64-bit addresses are valid (non-zero), - * they must match. - */ - if (address64->address && address32 && - (address64->address != (u64) address32)) { - ACPI_ERROR((AE_INFO, - "32/64X address mismatch in %s: 0x%8.8X/0x%8.8X%8.8X, using 32", - fadt_info_table[i].name, address32, - ACPI_FORMAT_UINT64(address64->address))); - } - - /* Always use 32-bit address if it is valid (non-null) */ - - if (address32) { - /* - * Copy the 32-bit address to the 64-bit GAS structure. The - * Space ID is always I/O for 32-bit legacy address fields - */ - acpi_tb_init_generic_address(address64, - ACPI_ADR_SPACE_SYSTEM_IO, - *ACPI_ADD_PTR(u8, - &acpi_gbl_FADT, - fadt_info_table - [i].length), - (u64) address32); - } - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_validate_fadt - * - * PARAMETERS: Table - Pointer to the FADT to be validated - * - * RETURN: None - * - * DESCRIPTION: Validate various important fields within the FADT. If a problem - * is found, issue a message, but no status is returned. - * Used by both the table manager and the disassembler. - * - * Possible additional checks: - * (acpi_gbl_FADT.pm1_event_length >= 4) - * (acpi_gbl_FADT.pm1_control_length >= 2) - * (acpi_gbl_FADT.pm_timer_length >= 4) - * Gpe block lengths must be multiple of 2 - * - ******************************************************************************/ - -static void acpi_tb_validate_fadt(void) -{ - char *name; - struct acpi_generic_address *address64; - u8 length; - u32 i; + acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); /* - * Check for FACS and DSDT address mismatches. An address mismatch between - * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and - * DSDT/X_DSDT) would indicate the presence of two FACS or two DSDT tables. + * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary. + * Later ACPICA code will always use the X 64-bit field. */ - if (acpi_gbl_FADT.facs && - (acpi_gbl_FADT.Xfacs != (u64) acpi_gbl_FADT.facs)) { - ACPI_WARNING((AE_INFO, - "32/64X FACS address mismatch in FADT - " - "0x%8.8X/0x%8.8X%8.8X, using 32", - acpi_gbl_FADT.facs, - ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xfacs))); - - acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs; - } + acpi_gbl_FADT.Xfacs = acpi_tb_select_address("FACS", + acpi_gbl_FADT.facs, + acpi_gbl_FADT.Xfacs); - if (acpi_gbl_FADT.dsdt && - (acpi_gbl_FADT.Xdsdt != (u64) acpi_gbl_FADT.dsdt)) { - ACPI_WARNING((AE_INFO, - "32/64X DSDT address mismatch in FADT - " - "0x%8.8X/0x%8.8X%8.8X, using 32", - acpi_gbl_FADT.dsdt, - ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xdsdt))); - - acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt; - } + acpi_gbl_FADT.Xdsdt = acpi_tb_select_address("DSDT", + acpi_gbl_FADT.dsdt, + acpi_gbl_FADT.Xdsdt); /* If Hardware Reduced flag is set, we are all done */ @@ -525,58 +512,141 @@ static void acpi_tb_validate_fadt(void) for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { /* - * Generate pointer to the 64-bit address, get the register - * length (width) and the register name + * Get the 32-bit and 64-bit addresses, as well as the register + * length and register name. */ + address32 = *ACPI_ADD_PTR(u32, + &acpi_gbl_FADT, + fadt_info_table[i].address32); + address64 = ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, fadt_info_table[i].address64); - length = - *ACPI_ADD_PTR(u8, &acpi_gbl_FADT, - fadt_info_table[i].length); + + length = *ACPI_ADD_PTR(u8, + &acpi_gbl_FADT, + fadt_info_table[i].length); + name = fadt_info_table[i].name; + flags = fadt_info_table[i].flags; + + /* + * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" + * generic address structures as necessary. Later code will always use + * the 64-bit address structures. + * + * November 2013: + * Now always use the 64-bit address if it is valid (non-zero), in + * accordance with the ACPI specification which states that a 64-bit + * address supersedes the 32-bit version. This behavior can be + * overridden by the acpi_gbl_use32_bit_fadt_addresses flag. + * + * During 64-bit address construction and verification, + * these cases are handled: + * + * Address32 zero, Address64 [don't care] - Use Address64 + * + * Address32 non-zero, Address64 zero - Copy/use Address32 + * Address32 non-zero == Address64 non-zero - Use Address64 + * Address32 non-zero != Address64 non-zero - Warning, use Address64 + * + * Override: if acpi_gbl_use32_bit_fadt_addresses is TRUE, and: + * Address32 non-zero != Address64 non-zero - Warning, copy/use Address32 + * + * Note: space_id is always I/O for 32-bit legacy address fields + */ + if (address32) { + if (!address64->address) { + + /* 64-bit address is zero, use 32-bit address */ + + acpi_tb_init_generic_address(address64, + ACPI_ADR_SPACE_SYSTEM_IO, + *ACPI_ADD_PTR(u8, + &acpi_gbl_FADT, + fadt_info_table + [i]. + length), + (u64)address32, + name, flags); + } else if (address64->address != (u64)address32) { + + /* Address mismatch */ + + ACPI_BIOS_WARNING((AE_INFO, + "32/64X address mismatch in FADT/%s: " + "0x%8.8X/0x%8.8X%8.8X, using %u-bit address", + name, address32, + ACPI_FORMAT_UINT64 + (address64->address), + acpi_gbl_use32_bit_fadt_addresses + ? 32 : 64)); + + if (acpi_gbl_use32_bit_fadt_addresses) { + + /* 32-bit address override */ + + acpi_tb_init_generic_address(address64, + ACPI_ADR_SPACE_SYSTEM_IO, + *ACPI_ADD_PTR + (u8, + &acpi_gbl_FADT, + fadt_info_table + [i]. + length), + (u64) + address32, + name, + flags); + } + } + } /* * For each extended field, check for length mismatch between the * legacy length field and the corresponding 64-bit X length field. + * Note: If the legacy length field is > 0xFF bits, ignore this + * check. (GPE registers can be larger than the 64-bit GAS structure + * can accomodate, 0xFF bits). */ if (address64->address && + (ACPI_MUL_8(length) <= ACPI_UINT8_MAX) && (address64->bit_width != ACPI_MUL_8(length))) { - ACPI_WARNING((AE_INFO, - "32/64X length mismatch in %s: %u/%u", - name, ACPI_MUL_8(length), - address64->bit_width)); + ACPI_BIOS_WARNING((AE_INFO, + "32/64X length mismatch in FADT/%s: %u/%u", + name, ACPI_MUL_8(length), + address64->bit_width)); } - if (fadt_info_table[i].type & ACPI_FADT_REQUIRED) { + if (fadt_info_table[i].flags & ACPI_FADT_REQUIRED) { /* - * Field is required (Pm1a_event, Pm1a_control, pm_timer). + * Field is required (Pm1a_event, Pm1a_control). * Both the address and length must be non-zero. */ if (!address64->address || !length) { - ACPI_ERROR((AE_INFO, - "Required field %s has zero address and/or length:" - " 0x%8.8X%8.8X/0x%X", - name, - ACPI_FORMAT_UINT64(address64-> - address), - length)); + ACPI_BIOS_ERROR((AE_INFO, + "Required FADT field %s has zero address and/or length: " + "0x%8.8X%8.8X/0x%X", + name, + ACPI_FORMAT_UINT64(address64-> + address), + length)); } - } else if (fadt_info_table[i].type & ACPI_FADT_SEPARATE_LENGTH) { + } else if (fadt_info_table[i].flags & ACPI_FADT_SEPARATE_LENGTH) { /* - * Field is optional (PM2Control, GPE0, GPE1) AND has its own + * Field is optional (Pm2_control, GPE0, GPE1) AND has its own * length field. If present, both the address and length must * be valid. */ if ((address64->address && !length) || (!address64->address && length)) { - ACPI_WARNING((AE_INFO, - "Optional field %s has zero address or length: " - "0x%8.8X%8.8X/0x%X", - name, - ACPI_FORMAT_UINT64(address64-> - address), - length)); + ACPI_BIOS_WARNING((AE_INFO, + "Optional FADT field %s has zero address or length: " + "0x%8.8X%8.8X/0x%X", + name, + ACPI_FORMAT_UINT64 + (address64->address), + length)); } } } @@ -621,12 +691,12 @@ static void acpi_tb_setup_fadt_registers(void) (fadt_info_table[i].default_length > 0) && (fadt_info_table[i].default_length != target64->bit_width)) { - ACPI_WARNING((AE_INFO, - "Invalid length for %s: %u, using default %u", - fadt_info_table[i].name, - target64->bit_width, - fadt_info_table[i]. - default_length)); + ACPI_BIOS_WARNING((AE_INFO, + "Invalid length for FADT/%s: %u, using default %u", + fadt_info_table[i].name, + target64->bit_width, + fadt_info_table[i]. + default_length)); /* Incorrect size, set width to the default */ @@ -670,7 +740,8 @@ static void acpi_tb_setup_fadt_registers(void) source64->address + (fadt_pm_info_table[i]. register_num * - pm1_register_byte_width)); + pm1_register_byte_width), + "PmRegisters", 0); } } } diff --git a/drivers/acpi/acpica/tbfind.c b/drivers/acpi/acpica/tbfind.c index 4903e36ea75..cb947700206 100644 --- a/drivers/acpi/acpica/tbfind.c +++ b/drivers/acpi/acpica/tbfind.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,7 +52,7 @@ ACPI_MODULE_NAME("tbfind") * * FUNCTION: acpi_tb_find_table * - * PARAMETERS: Signature - String with ACPI table signature + * PARAMETERS: signature - String with ACPI table signature * oem_id - String with the table OEM ID * oem_table_id - String with the OEM Table ID * table_index - Where the table index is returned @@ -77,7 +77,7 @@ acpi_tb_find_table(char *signature, /* Normalize the input strings */ ACPI_MEMSET(&header, 0, sizeof(struct acpi_table_header)); - ACPI_STRNCPY(header.signature, signature, ACPI_NAME_SIZE); + ACPI_MOVE_NAME(header.signature, signature); ACPI_STRNCPY(header.oem_id, oem_id, ACPI_OEM_ID_SIZE); ACPI_STRNCPY(header.oem_table_id, oem_table_id, ACPI_OEM_TABLE_ID_SIZE); @@ -99,8 +99,8 @@ acpi_tb_find_table(char *signature, /* Table is not currently mapped, map it */ status = - acpi_tb_verify_table(&acpi_gbl_root_table_list. - tables[i]); + acpi_tb_validate_table(&acpi_gbl_root_table_list. + tables[i]); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 1aecf7baa4e..755b90c40dd 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,604 +43,483 @@ #include <acpi/acpi.h> #include "accommon.h" -#include "acnamesp.h" #include "actables.h" #define _COMPONENT ACPI_TABLES ACPI_MODULE_NAME("tbinstal") -/****************************************************************************** - * - * FUNCTION: acpi_tb_verify_table - * - * PARAMETERS: table_desc - table - * - * RETURN: Status - * - * DESCRIPTION: this function is called to verify and map table - * - *****************************************************************************/ -acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(tb_verify_table); - - /* Map the table if necessary */ - - if (!table_desc->pointer) { - if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == - ACPI_TABLE_ORIGIN_MAPPED) { - table_desc->pointer = - acpi_os_map_memory(table_desc->address, - table_desc->length); - } - if (!table_desc->pointer) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - } - - /* FACS is the odd table, has no standard ACPI header and no checksum */ - - if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) { - - /* Always calculate checksum, ignore bad checksum if requested */ - - status = - acpi_tb_verify_checksum(table_desc->pointer, - table_desc->length); - } - - return_ACPI_STATUS(status); -} +/* Local prototypes */ +static u8 +acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index); /******************************************************************************* * - * FUNCTION: acpi_tb_add_table + * FUNCTION: acpi_tb_compare_tables * - * PARAMETERS: table_desc - Table descriptor - * table_index - Where the table index is returned + * PARAMETERS: table_desc - Table 1 descriptor to be compared + * table_index - Index of table 2 to be compared * - * RETURN: Status + * RETURN: TRUE if both tables are identical. * - * DESCRIPTION: This function is called to add an ACPI table. It is used to - * dynamically load tables via the Load and load_table AML - * operators. + * DESCRIPTION: This function compares a table with another table that has + * already been installed in the root table list. * ******************************************************************************/ -acpi_status -acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) +static u8 +acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index) { - u32 i; acpi_status status = AE_OK; - struct acpi_table_header *override_table = NULL; - - ACPI_FUNCTION_TRACE(tb_add_table); - - if (!table_desc->pointer) { - status = acpi_tb_verify_table(table_desc); - if (ACPI_FAILURE(status) || !table_desc->pointer) { - return_ACPI_STATUS(status); - } - } - - /* - * Validate the incoming table signature. - * - * 1) Originally, we checked the table signature for "SSDT" or "PSDT". - * 2) We added support for OEMx tables, signature "OEM". - * 3) Valid tables were encountered with a null signature, so we just - * gave up on validating the signature, (05/2008). - * 4) We encountered non-AML tables such as the MADT, which caused - * interpreter errors and kernel faults. So now, we once again allow - * only "SSDT", "OEMx", and now, also a null signature. (05/2011). - */ - if ((table_desc->pointer->signature[0] != 0x00) && - (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)) - && (ACPI_STRNCMP(table_desc->pointer->signature, "OEM", 3))) { - ACPI_ERROR((AE_INFO, - "Table has invalid signature [%4.4s] (0x%8.8X), must be SSDT or OEMx", - acpi_ut_valid_acpi_name(*(u32 *)table_desc-> - pointer-> - signature) ? table_desc-> - pointer->signature : "????", - *(u32 *)table_desc->pointer->signature)); - - return_ACPI_STATUS(AE_BAD_SIGNATURE); - } - - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - - /* Check if table is already registered */ - - for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { - if (!acpi_gbl_root_table_list.tables[i].pointer) { - status = - acpi_tb_verify_table(&acpi_gbl_root_table_list. - tables[i]); - if (ACPI_FAILURE(status) - || !acpi_gbl_root_table_list.tables[i].pointer) { - continue; - } - } - - /* - * Check for a table match on the entire table length, - * not just the header. - */ - if (table_desc->length != - acpi_gbl_root_table_list.tables[i].length) { - continue; - } - - if (ACPI_MEMCMP(table_desc->pointer, - acpi_gbl_root_table_list.tables[i].pointer, - acpi_gbl_root_table_list.tables[i].length)) { - continue; - } - - /* - * Note: the current mechanism does not unregister a table if it is - * dynamically unloaded. The related namespace entries are deleted, - * but the table remains in the root table list. - * - * The assumption here is that the number of different tables that - * will be loaded is actually small, and there is minimal overhead - * in just keeping the table in case it is needed again. - * - * If this assumption changes in the future (perhaps on large - * machines with many table load/unload operations), tables will - * need to be unregistered when they are unloaded, and slots in the - * root table list should be reused when empty. - */ - - /* - * Table is already registered. - * We can delete the table that was passed as a parameter. - */ - acpi_tb_delete_table(table_desc); - *table_index = i; - - if (acpi_gbl_root_table_list.tables[i]. - flags & ACPI_TABLE_IS_LOADED) { - - /* Table is still loaded, this is an error */ - - status = AE_ALREADY_EXISTS; - goto release; - } else { - /* Table was unloaded, allow it to be reloaded */ - - table_desc->pointer = - acpi_gbl_root_table_list.tables[i].pointer; - table_desc->address = - acpi_gbl_root_table_list.tables[i].address; - status = AE_OK; - goto print_header; - } + u8 is_identical; + struct acpi_table_header *table; + u32 table_length; + u8 table_flags; + + status = + acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index], + &table, &table_length, &table_flags); + if (ACPI_FAILURE(status)) { + return (FALSE); } /* - * ACPI Table Override: - * Allow the host to override dynamically loaded tables. + * Check for a table match on the entire table length, + * not just the header. */ - status = acpi_os_table_override(table_desc->pointer, &override_table); - if (ACPI_SUCCESS(status) && override_table) { - ACPI_INFO((AE_INFO, - "%4.4s @ 0x%p Table override, replaced with:", - table_desc->pointer->signature, - ACPI_CAST_PTR(void, table_desc->address))); - - /* We can delete the table that was passed as a parameter */ - - acpi_tb_delete_table(table_desc); - - /* Setup descriptor for the new table */ + is_identical = (u8)((table_desc->length != table_length || + ACPI_MEMCMP(table_desc->pointer, table, + table_length)) ? FALSE : TRUE); - table_desc->address = ACPI_PTR_TO_PHYSADDR(override_table); - table_desc->pointer = override_table; - table_desc->length = override_table->length; - table_desc->flags = ACPI_TABLE_ORIGIN_OVERRIDE; - } - - /* Add the table to the global root table list */ - - status = acpi_tb_store_table(table_desc->address, table_desc->pointer, - table_desc->length, table_desc->flags, - table_index); - if (ACPI_FAILURE(status)) { - goto release; - } - - print_header: - acpi_tb_print_table_header(table_desc->address, table_desc->pointer); + /* Release the acquired table */ - release: - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(status); + acpi_tb_release_table(table, table_length, table_flags); + return (is_identical); } /******************************************************************************* * - * FUNCTION: acpi_tb_resize_root_table_list + * FUNCTION: acpi_tb_install_table_with_override * - * PARAMETERS: None + * PARAMETERS: table_index - Index into root table array + * new_table_desc - New table descriptor to install + * override - Whether override should be performed * - * RETURN: Status + * RETURN: None * - * DESCRIPTION: Expand the size of global table array + * DESCRIPTION: Install an ACPI table into the global data structure. The + * table override mechanism is called to allow the host + * OS to replace any table before it is installed in the root + * table array. * ******************************************************************************/ -acpi_status acpi_tb_resize_root_table_list(void) +void +acpi_tb_install_table_with_override(u32 table_index, + struct acpi_table_desc *new_table_desc, + u8 override) { - struct acpi_table_desc *tables; - - ACPI_FUNCTION_TRACE(tb_resize_root_table_list); - /* allow_resize flag is a parameter to acpi_initialize_tables */ - - if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) { - ACPI_ERROR((AE_INFO, - "Resize of Root Table Array is not allowed")); - return_ACPI_STATUS(AE_SUPPORT); + if (table_index >= acpi_gbl_root_table_list.current_table_count) { + return; } - /* Increase the Table Array size */ - - tables = ACPI_ALLOCATE_ZEROED(((acpi_size) acpi_gbl_root_table_list. - max_table_count + - ACPI_ROOT_TABLE_SIZE_INCREMENT) * - sizeof(struct acpi_table_desc)); - if (!tables) { - ACPI_ERROR((AE_INFO, - "Could not allocate new root table array")); - return_ACPI_STATUS(AE_NO_MEMORY); + /* + * ACPI Table Override: + * + * Before we install the table, let the host OS override it with a new + * one if desired. Any table within the RSDT/XSDT can be replaced, + * including the DSDT which is pointed to by the FADT. + */ + if (override) { + acpi_tb_override_table(new_table_desc); } - /* Copy and free the previous table array */ + acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list. + tables[table_index], + new_table_desc->address, + new_table_desc->flags, + new_table_desc->pointer); - if (acpi_gbl_root_table_list.tables) { - ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, - (acpi_size) acpi_gbl_root_table_list. - max_table_count * sizeof(struct acpi_table_desc)); + acpi_tb_print_table_header(new_table_desc->address, + new_table_desc->pointer); - if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { - ACPI_FREE(acpi_gbl_root_table_list.tables); - } - } + /* Set the global integer width (based upon revision of the DSDT) */ - acpi_gbl_root_table_list.tables = tables; - acpi_gbl_root_table_list.max_table_count += - ACPI_ROOT_TABLE_SIZE_INCREMENT; - acpi_gbl_root_table_list.flags |= (u8)ACPI_ROOT_ORIGIN_ALLOCATED; - - return_ACPI_STATUS(AE_OK); + if (table_index == ACPI_TABLE_INDEX_DSDT) { + acpi_ut_set_integer_width(new_table_desc->pointer->revision); + } } /******************************************************************************* * - * FUNCTION: acpi_tb_store_table + * FUNCTION: acpi_tb_install_fixed_table * - * PARAMETERS: Address - Table address - * Table - Table header - * Length - Table length - * Flags - flags + * PARAMETERS: address - Physical address of DSDT or FACS + * signature - Table signature, NULL if no need to + * match + * table_index - Index into root table array * - * RETURN: Status and table index. + * RETURN: Status * - * DESCRIPTION: Add an ACPI table to the global table list + * DESCRIPTION: Install a fixed ACPI table (DSDT/FACS) into the global data + * structure. * ******************************************************************************/ acpi_status -acpi_tb_store_table(acpi_physical_address address, - struct acpi_table_header *table, - u32 length, u8 flags, u32 *table_index) +acpi_tb_install_fixed_table(acpi_physical_address address, + char *signature, u32 table_index) { + struct acpi_table_desc new_table_desc; acpi_status status; - struct acpi_table_desc *new_table; - /* Ensure that there is room for the table in the Root Table List */ + ACPI_FUNCTION_TRACE(tb_install_fixed_table); - if (acpi_gbl_root_table_list.current_table_count >= - acpi_gbl_root_table_list.max_table_count) { - status = acpi_tb_resize_root_table_list(); - if (ACPI_FAILURE(status)) { - return (status); - } + if (!address) { + ACPI_ERROR((AE_INFO, + "Null physical address for ACPI table [%s]", + signature)); + return (AE_NO_MEMORY); } - new_table = - &acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list. - current_table_count]; + /* Fill a table descriptor for validation */ - /* Initialize added table */ + status = acpi_tb_acquire_temp_table(&new_table_desc, address, + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, "Could not acquire table length at %p", + ACPI_CAST_PTR(void, address))); + return_ACPI_STATUS(status); + } - new_table->address = address; - new_table->pointer = table; - new_table->length = length; - new_table->owner_id = 0; - new_table->flags = flags; + /* Validate and verify a table before installation */ - ACPI_MOVE_32_TO_32(&new_table->signature, table->signature); + status = acpi_tb_verify_temp_table(&new_table_desc, signature); + if (ACPI_FAILURE(status)) { + goto release_and_exit; + } - *table_index = acpi_gbl_root_table_list.current_table_count; - acpi_gbl_root_table_list.current_table_count++; - return (AE_OK); -} + acpi_tb_install_table_with_override(table_index, &new_table_desc, TRUE); -/******************************************************************************* - * - * FUNCTION: acpi_tb_delete_table - * - * PARAMETERS: table_index - Table index - * - * RETURN: None - * - * DESCRIPTION: Delete one internal ACPI table - * - ******************************************************************************/ +release_and_exit: -void acpi_tb_delete_table(struct acpi_table_desc *table_desc) -{ - /* Table must be mapped or allocated */ - if (!table_desc->pointer) { - return; - } - switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { - case ACPI_TABLE_ORIGIN_MAPPED: - acpi_os_unmap_memory(table_desc->pointer, table_desc->length); - break; - case ACPI_TABLE_ORIGIN_ALLOCATED: - ACPI_FREE(table_desc->pointer); - break; - default:; - } + /* Release the temporary table descriptor */ - table_desc->pointer = NULL; + acpi_tb_release_temp_table(&new_table_desc); + return_ACPI_STATUS(status); } /******************************************************************************* * - * FUNCTION: acpi_tb_terminate + * FUNCTION: acpi_tb_install_standard_table * - * PARAMETERS: None + * PARAMETERS: address - Address of the table (might be a virtual + * address depending on the table_flags) + * flags - Flags for the table + * reload - Whether reload should be performed + * override - Whether override should be performed + * table_index - Where the table index is returned * - * RETURN: None + * RETURN: Status * - * DESCRIPTION: Delete all internal ACPI tables + * DESCRIPTION: This function is called to install an ACPI table that is + * neither DSDT nor FACS (a "standard" table.) + * When this function is called by "Load" or "LoadTable" opcodes, + * or by acpi_load_table() API, the "Reload" parameter is set. + * After sucessfully returning from this function, table is + * "INSTALLED" but not "VALIDATED". * ******************************************************************************/ -void acpi_tb_terminate(void) +acpi_status +acpi_tb_install_standard_table(acpi_physical_address address, + u8 flags, + u8 reload, u8 override, u32 *table_index) { u32 i; + acpi_status status = AE_OK; + struct acpi_table_desc new_table_desc; - ACPI_FUNCTION_TRACE(tb_terminate); - - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + ACPI_FUNCTION_TRACE(tb_install_standard_table); - /* Delete the individual tables */ + /* Acquire a temporary table descriptor for validation */ - for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { - acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]); + status = acpi_tb_acquire_temp_table(&new_table_desc, address, flags); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, "Could not acquire table length at %p", + ACPI_CAST_PTR(void, address))); + return_ACPI_STATUS(status); } /* - * Delete the root table array if allocated locally. Array cannot be - * mapped, so we don't need to check for that flag. + * Optionally do not load any SSDTs from the RSDT/XSDT. This can + * be useful for debugging ACPI problems on some machines. */ - if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { - ACPI_FREE(acpi_gbl_root_table_list.tables); + if (!reload && + acpi_gbl_disable_ssdt_table_install && + ACPI_COMPARE_NAME(&new_table_desc.signature, ACPI_SIG_SSDT)) { + ACPI_INFO((AE_INFO, "Ignoring installation of %4.4s at %p", + new_table_desc.signature.ascii, ACPI_CAST_PTR(void, + address))); + goto release_and_exit; } - acpi_gbl_root_table_list.tables = NULL; - acpi_gbl_root_table_list.flags = 0; - acpi_gbl_root_table_list.current_table_count = 0; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n")); - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); -} + /* Validate and verify a table before installation */ -/******************************************************************************* - * - * FUNCTION: acpi_tb_delete_namespace_by_owner - * - * PARAMETERS: table_index - Table index - * - * RETURN: Status - * - * DESCRIPTION: Delete all namespace objects created when this table was loaded. - * - ******************************************************************************/ - -acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index) -{ - acpi_owner_id owner_id; - acpi_status status; - - ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner); - - status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + status = acpi_tb_verify_temp_table(&new_table_desc, NULL); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto release_and_exit; } - if (table_index >= acpi_gbl_root_table_list.current_table_count) { - - /* The table index does not exist */ + if (reload) { + /* + * Validate the incoming table signature. + * + * 1) Originally, we checked the table signature for "SSDT" or "PSDT". + * 2) We added support for OEMx tables, signature "OEM". + * 3) Valid tables were encountered with a null signature, so we just + * gave up on validating the signature, (05/2008). + * 4) We encountered non-AML tables such as the MADT, which caused + * interpreter errors and kernel faults. So now, we once again allow + * only "SSDT", "OEMx", and now, also a null signature. (05/2011). + */ + if ((new_table_desc.signature.ascii[0] != 0x00) && + (!ACPI_COMPARE_NAME + (&new_table_desc.signature, ACPI_SIG_SSDT)) + && (ACPI_STRNCMP(new_table_desc.signature.ascii, "OEM", 3))) + { + ACPI_BIOS_ERROR((AE_INFO, + "Table has invalid signature [%4.4s] (0x%8.8X), " + "must be SSDT or OEMx", + acpi_ut_valid_acpi_name(new_table_desc. + signature. + ascii) ? + new_table_desc.signature. + ascii : "????", + new_table_desc.signature.integer)); + + status = AE_BAD_SIGNATURE; + goto release_and_exit; + } - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(AE_NOT_EXIST); - } + /* Check if table is already registered */ - /* Get the owner ID for this table, used to delete namespace nodes */ + for (i = 0; i < acpi_gbl_root_table_list.current_table_count; + ++i) { + /* + * Check for a table match on the entire table length, + * not just the header. + */ + if (!acpi_tb_compare_tables(&new_table_desc, i)) { + continue; + } - owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id; - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + /* + * Note: the current mechanism does not unregister a table if it is + * dynamically unloaded. The related namespace entries are deleted, + * but the table remains in the root table list. + * + * The assumption here is that the number of different tables that + * will be loaded is actually small, and there is minimal overhead + * in just keeping the table in case it is needed again. + * + * If this assumption changes in the future (perhaps on large + * machines with many table load/unload operations), tables will + * need to be unregistered when they are unloaded, and slots in the + * root table list should be reused when empty. + */ + if (acpi_gbl_root_table_list.tables[i]. + flags & ACPI_TABLE_IS_LOADED) { + + /* Table is still loaded, this is an error */ + + status = AE_ALREADY_EXISTS; + goto release_and_exit; + } else { + /* + * Table was unloaded, allow it to be reloaded. + * As we are going to return AE_OK to the caller, we should + * take the responsibility of freeing the input descriptor. + * Refill the input descriptor to ensure + * acpi_tb_install_table_with_override() can be called again to + * indicate the re-installation. + */ + acpi_tb_uninstall_table(&new_table_desc); + *table_index = i; + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(AE_OK); + } + } + } - /* - * Need to acquire the namespace writer lock to prevent interference - * with any concurrent namespace walks. The interpreter must be - * released during the deletion since the acquisition of the deletion - * lock may block, and also since the execution of a namespace walk - * must be allowed to use the interpreter. - */ - (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); - status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock); + /* Add the table to the global root table list */ - acpi_ns_delete_namespace_by_owner(owner_id); + status = acpi_tb_get_next_root_index(&i); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto release_and_exit; } - acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock); + *table_index = i; + acpi_tb_install_table_with_override(i, &new_table_desc, override); + +release_and_exit: - status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); + /* Release the temporary table descriptor */ + + acpi_tb_release_temp_table(&new_table_desc); return_ACPI_STATUS(status); } /******************************************************************************* * - * FUNCTION: acpi_tb_allocate_owner_id + * FUNCTION: acpi_tb_override_table * - * PARAMETERS: table_index - Table index + * PARAMETERS: old_table_desc - Validated table descriptor to be + * overridden * - * RETURN: Status + * RETURN: None * - * DESCRIPTION: Allocates owner_id in table_desc + * DESCRIPTION: Attempt table override by calling the OSL override functions. + * Note: If the table is overridden, then the entire new table + * is acquired and returned by this function. + * Before/after invocation, the table descriptor is in a state + * that is "VALIDATED". * ******************************************************************************/ -acpi_status acpi_tb_allocate_owner_id(u32 table_index) +void acpi_tb_override_table(struct acpi_table_desc *old_table_desc) { - acpi_status status = AE_BAD_PARAMETER; + acpi_status status; + char *override_type; + struct acpi_table_desc new_table_desc; + struct acpi_table_header *table; + acpi_physical_address address; + u32 length; + + /* (1) Attempt logical override (returns a logical address) */ + + status = acpi_os_table_override(old_table_desc->pointer, &table); + if (ACPI_SUCCESS(status) && table) { + acpi_tb_acquire_temp_table(&new_table_desc, + ACPI_PTR_TO_PHYSADDR(table), + ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL); + override_type = "Logical"; + goto finish_override; + } - ACPI_FUNCTION_TRACE(tb_allocate_owner_id); + /* (2) Attempt physical override (returns a physical address) */ - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.current_table_count) { - status = acpi_ut_allocate_owner_id - (&(acpi_gbl_root_table_list.tables[table_index].owner_id)); + status = acpi_os_physical_table_override(old_table_desc->pointer, + &address, &length); + if (ACPI_SUCCESS(status) && address && length) { + acpi_tb_acquire_temp_table(&new_table_desc, address, + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); + override_type = "Physical"; + goto finish_override; } - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_release_owner_id - * - * PARAMETERS: table_index - Table index - * - * RETURN: Status - * - * DESCRIPTION: Releases owner_id in table_desc - * - ******************************************************************************/ + return; /* There was no override */ -acpi_status acpi_tb_release_owner_id(u32 table_index) -{ - acpi_status status = AE_BAD_PARAMETER; +finish_override: - ACPI_FUNCTION_TRACE(tb_release_owner_id); + /* Validate and verify a table before overriding */ - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.current_table_count) { - acpi_ut_release_owner_id(& - (acpi_gbl_root_table_list. - tables[table_index].owner_id)); - status = AE_OK; + status = acpi_tb_verify_temp_table(&new_table_desc, NULL); + if (ACPI_FAILURE(status)) { + return; } - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(status); -} + ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT + " %s table override, new table: " ACPI_PRINTF_UINT, + old_table_desc->signature.ascii, + ACPI_FORMAT_TO_UINT(old_table_desc->address), + override_type, ACPI_FORMAT_TO_UINT(new_table_desc.address))); -/******************************************************************************* - * - * FUNCTION: acpi_tb_get_owner_id - * - * PARAMETERS: table_index - Table index - * owner_id - Where the table owner_id is returned - * - * RETURN: Status - * - * DESCRIPTION: returns owner_id for the ACPI table - * - ******************************************************************************/ + /* We can now uninstall the original table */ -acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id) -{ - acpi_status status = AE_BAD_PARAMETER; + acpi_tb_uninstall_table(old_table_desc); - ACPI_FUNCTION_TRACE(tb_get_owner_id); + /* + * Replace the original table descriptor and keep its state as + * "VALIDATED". + */ + acpi_tb_init_table_descriptor(old_table_desc, new_table_desc.address, + new_table_desc.flags, + new_table_desc.pointer); + acpi_tb_validate_temp_table(old_table_desc); - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.current_table_count) { - *owner_id = - acpi_gbl_root_table_list.tables[table_index].owner_id; - status = AE_OK; - } + /* Release the temporary table descriptor */ - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(status); + acpi_tb_release_temp_table(&new_table_desc); } /******************************************************************************* * - * FUNCTION: acpi_tb_is_table_loaded + * FUNCTION: acpi_tb_store_table + * + * PARAMETERS: address - Table address + * table - Table header + * length - Table length + * flags - Install flags + * table_index - Where the table index is returned * - * PARAMETERS: table_index - Table index + * RETURN: Status and table index. * - * RETURN: Table Loaded Flag + * DESCRIPTION: Add an ACPI table to the global table list * ******************************************************************************/ -u8 acpi_tb_is_table_loaded(u32 table_index) +acpi_status +acpi_tb_store_table(acpi_physical_address address, + struct acpi_table_header * table, + u32 length, u8 flags, u32 *table_index) { - u8 is_loaded = FALSE; + acpi_status status; + struct acpi_table_desc *table_desc; - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.current_table_count) { - is_loaded = (u8) - (acpi_gbl_root_table_list.tables[table_index].flags & - ACPI_TABLE_IS_LOADED); + status = acpi_tb_get_next_root_index(table_index); + if (ACPI_FAILURE(status)) { + return (status); } - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return (is_loaded); + /* Initialize added table */ + + table_desc = &acpi_gbl_root_table_list.tables[*table_index]; + acpi_tb_init_table_descriptor(table_desc, address, flags, table); + table_desc->pointer = table; + return (AE_OK); } /******************************************************************************* * - * FUNCTION: acpi_tb_set_table_loaded_flag + * FUNCTION: acpi_tb_uninstall_table * - * PARAMETERS: table_index - Table index - * is_loaded - TRUE if table is loaded, FALSE otherwise + * PARAMETERS: table_desc - Table descriptor * * RETURN: None * - * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE. + * DESCRIPTION: Delete one internal ACPI table * ******************************************************************************/ -void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded) +void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc) { - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.current_table_count) { - if (is_loaded) { - acpi_gbl_root_table_list.tables[table_index].flags |= - ACPI_TABLE_IS_LOADED; - } else { - acpi_gbl_root_table_list.tables[table_index].flags &= - ~ACPI_TABLE_IS_LOADED; - } + ACPI_FUNCTION_TRACE(tb_uninstall_table); + + /* Table must be installed */ + + if (!table_desc->address) { + return_VOID; + } + + acpi_tb_invalidate_table(table_desc); + + if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == + ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) { + ACPI_FREE(ACPI_CAST_PTR(void, table_desc->address)); } - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL); + return_VOID; } diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c new file mode 100644 index 00000000000..df3bb20ea32 --- /dev/null +++ b/drivers/acpi/acpica/tbprint.c @@ -0,0 +1,251 @@ +/****************************************************************************** + * + * Module Name: tbprint - Table output utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "actables.h" + +#define _COMPONENT ACPI_TABLES +ACPI_MODULE_NAME("tbprint") + +/* Local prototypes */ +static void acpi_tb_fix_string(char *string, acpi_size length); + +static void +acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, + struct acpi_table_header *header); + +/******************************************************************************* + * + * FUNCTION: acpi_tb_fix_string + * + * PARAMETERS: string - String to be repaired + * length - Maximum length + * + * RETURN: None + * + * DESCRIPTION: Replace every non-printable or non-ascii byte in the string + * with a question mark '?'. + * + ******************************************************************************/ + +static void acpi_tb_fix_string(char *string, acpi_size length) +{ + + while (length && *string) { + if (!ACPI_IS_PRINT(*string)) { + *string = '?'; + } + string++; + length--; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_cleanup_table_header + * + * PARAMETERS: out_header - Where the cleaned header is returned + * header - Input ACPI table header + * + * RETURN: Returns the cleaned header in out_header + * + * DESCRIPTION: Copy the table header and ensure that all "string" fields in + * the header consist of printable characters. + * + ******************************************************************************/ + +static void +acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, + struct acpi_table_header *header) +{ + + ACPI_MEMCPY(out_header, header, sizeof(struct acpi_table_header)); + + acpi_tb_fix_string(out_header->signature, ACPI_NAME_SIZE); + acpi_tb_fix_string(out_header->oem_id, ACPI_OEM_ID_SIZE); + acpi_tb_fix_string(out_header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE); + acpi_tb_fix_string(out_header->asl_compiler_id, ACPI_NAME_SIZE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_print_table_header + * + * PARAMETERS: address - Table physical address + * header - Table header + * + * RETURN: None + * + * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP. + * + ******************************************************************************/ + +void +acpi_tb_print_table_header(acpi_physical_address address, + struct acpi_table_header *header) +{ + struct acpi_table_header local_header; + + /* + * The reason that we use ACPI_PRINTF_UINT and ACPI_FORMAT_TO_UINT is to + * support both 32-bit and 64-bit hosts/addresses in a consistent manner. + * The %p specifier does not emit uniform output on all hosts. On some, + * leading zeros are not supported. + */ + if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) { + + /* FACS only has signature and length fields */ + + ACPI_INFO((AE_INFO, "%-4.4s " ACPI_PRINTF_UINT " %06X", + header->signature, ACPI_FORMAT_TO_UINT(address), + header->length)); + } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) { + + /* RSDP has no common fields */ + + ACPI_MEMCPY(local_header.oem_id, + ACPI_CAST_PTR(struct acpi_table_rsdp, + header)->oem_id, ACPI_OEM_ID_SIZE); + acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE); + + ACPI_INFO((AE_INFO, + "RSDP " ACPI_PRINTF_UINT " %06X (v%.2d %-6.6s)", + ACPI_FORMAT_TO_UINT(address), + (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> + revision > + 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, + header)->length : 20, + ACPI_CAST_PTR(struct acpi_table_rsdp, + header)->revision, + local_header.oem_id)); + } else { + /* Standard ACPI table with full common header */ + + acpi_tb_cleanup_table_header(&local_header, header); + + ACPI_INFO((AE_INFO, + "%-4.4s " ACPI_PRINTF_UINT + " %06X (v%.2d %-6.6s %-8.8s %08X %-4.4s %08X)", + local_header.signature, ACPI_FORMAT_TO_UINT(address), + local_header.length, local_header.revision, + local_header.oem_id, local_header.oem_table_id, + local_header.oem_revision, + local_header.asl_compiler_id, + local_header.asl_compiler_revision)); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_validate_checksum + * + * PARAMETERS: table - ACPI table to verify + * length - Length of entire table + * + * RETURN: Status + * + * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns + * exception on bad checksum. + * + ******************************************************************************/ + +acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) +{ + u8 checksum; + + /* + * FACS/S3PT: + * They are the odd tables, have no standard ACPI header and no checksum + */ + + if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_S3PT) || + ACPI_COMPARE_NAME(table->signature, ACPI_SIG_FACS)) { + return (AE_OK); + } + + /* Compute the checksum on the table */ + + checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length); + + /* Checksum ok? (should be zero) */ + + if (checksum) { + ACPI_BIOS_WARNING((AE_INFO, + "Incorrect checksum in table [%4.4s] - 0x%2.2X, " + "should be 0x%2.2X", + table->signature, table->checksum, + (u8)(table->checksum - checksum))); + +#if (ACPI_CHECKSUM_ABORT) + return (AE_BAD_CHECKSUM); +#endif + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_checksum + * + * PARAMETERS: buffer - Pointer to memory region to be checked + * length - Length of this memory region + * + * RETURN: Checksum (u8) + * + * DESCRIPTION: Calculates circular checksum of memory region. + * + ******************************************************************************/ + +u8 acpi_tb_checksum(u8 *buffer, u32 length) +{ + u8 sum = 0; + u8 *end = buffer + length; + + while (buffer < end) { + sum = (u8)(sum + *(buffer++)); + } + + return (sum); +} diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 09ca39e1433..6b1ca9991b9 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -1,11 +1,11 @@ /****************************************************************************** * - * Module Name: tbutils - table utilities + * Module Name: tbutils - ACPI Table utilities * *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,75 +49,10 @@ ACPI_MODULE_NAME("tbutils") /* Local prototypes */ -static void acpi_tb_fix_string(char *string, acpi_size length); - -static void -acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, - struct acpi_table_header *header); - static acpi_physical_address acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size); -/******************************************************************************* - * - * FUNCTION: acpi_tb_check_xsdt - * - * PARAMETERS: address - Pointer to the XSDT - * - * RETURN: status - * AE_OK - XSDT is okay - * AE_NO_MEMORY - can't map XSDT - * AE_INVALID_TABLE_LENGTH - invalid table length - * AE_NULL_ENTRY - XSDT has NULL entry - * - * DESCRIPTION: validate XSDT -******************************************************************************/ - -static acpi_status -acpi_tb_check_xsdt(acpi_physical_address address) -{ - struct acpi_table_header *table; - u32 length; - u64 xsdt_entry_address; - u8 *table_entry; - u32 table_count; - int i; - - table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); - if (!table) - return AE_NO_MEMORY; - - length = table->length; - acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); - if (length < sizeof(struct acpi_table_header)) - return AE_INVALID_TABLE_LENGTH; - - table = acpi_os_map_memory(address, length); - if (!table) - return AE_NO_MEMORY; - - /* Calculate the number of tables described in XSDT */ - table_count = - (u32) ((table->length - - sizeof(struct acpi_table_header)) / sizeof(u64)); - table_entry = - ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); - for (i = 0; i < table_count; i++) { - ACPI_MOVE_64_TO_64(&xsdt_entry_address, table_entry); - if (!xsdt_entry_address) { - /* XSDT has NULL entry */ - break; - } - table_entry += sizeof(u64); - } - acpi_os_unmap_memory(table, length); - - if (i < table_count) - return AE_NULL_ENTRY; - else - return AE_OK; -} - +#if (!ACPI_REDUCED_HARDWARE) /******************************************************************************* * * FUNCTION: acpi_tb_initialize_facs @@ -146,8 +81,9 @@ acpi_status acpi_tb_initialize_facs(void) ACPI_CAST_INDIRECT_PTR(struct acpi_table_header, &acpi_gbl_FACS)); - return status; + return (status); } +#endif /* !ACPI_REDUCED_HARDWARE */ /******************************************************************************* * @@ -174,188 +110,6 @@ u8 acpi_tb_tables_loaded(void) /******************************************************************************* * - * FUNCTION: acpi_tb_fix_string - * - * PARAMETERS: String - String to be repaired - * Length - Maximum length - * - * RETURN: None - * - * DESCRIPTION: Replace every non-printable or non-ascii byte in the string - * with a question mark '?'. - * - ******************************************************************************/ - -static void acpi_tb_fix_string(char *string, acpi_size length) -{ - - while (length && *string) { - if (!ACPI_IS_PRINT(*string)) { - *string = '?'; - } - string++; - length--; - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_cleanup_table_header - * - * PARAMETERS: out_header - Where the cleaned header is returned - * Header - Input ACPI table header - * - * RETURN: Returns the cleaned header in out_header - * - * DESCRIPTION: Copy the table header and ensure that all "string" fields in - * the header consist of printable characters. - * - ******************************************************************************/ - -static void -acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, - struct acpi_table_header *header) -{ - - ACPI_MEMCPY(out_header, header, sizeof(struct acpi_table_header)); - - acpi_tb_fix_string(out_header->signature, ACPI_NAME_SIZE); - acpi_tb_fix_string(out_header->oem_id, ACPI_OEM_ID_SIZE); - acpi_tb_fix_string(out_header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE); - acpi_tb_fix_string(out_header->asl_compiler_id, ACPI_NAME_SIZE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_print_table_header - * - * PARAMETERS: Address - Table physical address - * Header - Table header - * - * RETURN: None - * - * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP. - * - ******************************************************************************/ - -void -acpi_tb_print_table_header(acpi_physical_address address, - struct acpi_table_header *header) -{ - struct acpi_table_header local_header; - - /* - * The reason that the Address is cast to a void pointer is so that we - * can use %p which will work properly on both 32-bit and 64-bit hosts. - */ - if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) { - - /* FACS only has signature and length fields */ - - ACPI_INFO((AE_INFO, "%4.4s %p %05X", - header->signature, ACPI_CAST_PTR(void, address), - header->length)); - } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) { - - /* RSDP has no common fields */ - - ACPI_MEMCPY(local_header.oem_id, - ACPI_CAST_PTR(struct acpi_table_rsdp, - header)->oem_id, ACPI_OEM_ID_SIZE); - acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE); - - ACPI_INFO((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)", - ACPI_CAST_PTR (void, address), - (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> - revision > - 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, - header)->length : 20, - ACPI_CAST_PTR(struct acpi_table_rsdp, - header)->revision, - local_header.oem_id)); - } else { - /* Standard ACPI table with full common header */ - - acpi_tb_cleanup_table_header(&local_header, header); - - ACPI_INFO((AE_INFO, - "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", - local_header.signature, ACPI_CAST_PTR(void, address), - local_header.length, local_header.revision, - local_header.oem_id, local_header.oem_table_id, - local_header.oem_revision, - local_header.asl_compiler_id, - local_header.asl_compiler_revision)); - - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_validate_checksum - * - * PARAMETERS: Table - ACPI table to verify - * Length - Length of entire table - * - * RETURN: Status - * - * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns - * exception on bad checksum. - * - ******************************************************************************/ - -acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) -{ - u8 checksum; - - /* Compute the checksum on the table */ - - checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length); - - /* Checksum ok? (should be zero) */ - - if (checksum) { - ACPI_WARNING((AE_INFO, - "Incorrect checksum in table [%4.4s] - 0x%2.2X, should be 0x%2.2X", - table->signature, table->checksum, - (u8) (table->checksum - checksum))); - -#if (ACPI_CHECKSUM_ABORT) - - return (AE_BAD_CHECKSUM); -#endif - } - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_checksum - * - * PARAMETERS: Buffer - Pointer to memory region to be checked - * Length - Length of this memory region - * - * RETURN: Checksum (u8) - * - * DESCRIPTION: Calculates circular checksum of memory region. - * - ******************************************************************************/ - -u8 acpi_tb_checksum(u8 *buffer, u32 length) -{ - u8 sum = 0; - u8 *end = buffer + length; - - while (buffer < end) { - sum = (u8) (sum + *(buffer++)); - } - - return sum; -} - -/******************************************************************************* - * * FUNCTION: acpi_tb_check_dsdt_header * * PARAMETERS: None @@ -375,8 +129,9 @@ void acpi_tb_check_dsdt_header(void) if (acpi_gbl_original_dsdt_header.length != acpi_gbl_DSDT->length || acpi_gbl_original_dsdt_header.checksum != acpi_gbl_DSDT->checksum) { - ACPI_ERROR((AE_INFO, - "The DSDT has been corrupted or replaced - old, new headers below")); + ACPI_BIOS_ERROR((AE_INFO, + "The DSDT has been corrupted or replaced - " + "old, new headers below")); acpi_tb_print_table_header(0, &acpi_gbl_original_dsdt_header); acpi_tb_print_table_header(0, acpi_gbl_DSDT); @@ -421,9 +176,13 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index) } ACPI_MEMCPY(new_table, table_desc->pointer, table_desc->length); - acpi_tb_delete_table(table_desc); - table_desc->pointer = new_table; - table_desc->flags = ACPI_TABLE_ORIGIN_ALLOCATED; + acpi_tb_uninstall_table(table_desc); + + acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list. + tables[ACPI_TABLE_INDEX_DSDT], + ACPI_PTR_TO_PHYSADDR(new_table), + ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, + new_table); ACPI_INFO((AE_INFO, "Forced DSDT copy: length 0x%05X copied locally, original unmapped", @@ -434,108 +193,6 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index) /******************************************************************************* * - * FUNCTION: acpi_tb_install_table - * - * PARAMETERS: Address - Physical address of DSDT or FACS - * Signature - Table signature, NULL if no need to - * match - * table_index - Index into root table array - * - * RETURN: None - * - * DESCRIPTION: Install an ACPI table into the global data structure. The - * table override mechanism is implemented here to allow the host - * OS to replace any table before it is installed in the root - * table array. - * - ******************************************************************************/ - -void -acpi_tb_install_table(acpi_physical_address address, - char *signature, u32 table_index) -{ - u8 flags; - acpi_status status; - struct acpi_table_header *table_to_install; - struct acpi_table_header *mapped_table; - struct acpi_table_header *override_table = NULL; - - if (!address) { - ACPI_ERROR((AE_INFO, - "Null physical address for ACPI table [%s]", - signature)); - return; - } - - /* Map just the table header */ - - mapped_table = - acpi_os_map_memory(address, sizeof(struct acpi_table_header)); - if (!mapped_table) { - return; - } - - /* If a particular signature is expected (DSDT/FACS), it must match */ - - if (signature && !ACPI_COMPARE_NAME(mapped_table->signature, signature)) { - ACPI_ERROR((AE_INFO, - "Invalid signature 0x%X for ACPI table, expected [%s]", - *ACPI_CAST_PTR(u32, mapped_table->signature), - signature)); - goto unmap_and_exit; - } - - /* - * ACPI Table Override: - * - * Before we install the table, let the host OS override it with a new - * one if desired. Any table within the RSDT/XSDT can be replaced, - * including the DSDT which is pointed to by the FADT. - */ - status = acpi_os_table_override(mapped_table, &override_table); - if (ACPI_SUCCESS(status) && override_table) { - ACPI_INFO((AE_INFO, - "%4.4s @ 0x%p Table override, replaced with:", - mapped_table->signature, ACPI_CAST_PTR(void, - address))); - - acpi_gbl_root_table_list.tables[table_index].pointer = - override_table; - address = ACPI_PTR_TO_PHYSADDR(override_table); - - table_to_install = override_table; - flags = ACPI_TABLE_ORIGIN_OVERRIDE; - } else { - table_to_install = mapped_table; - flags = ACPI_TABLE_ORIGIN_MAPPED; - } - - /* Initialize the table entry */ - - acpi_gbl_root_table_list.tables[table_index].address = address; - acpi_gbl_root_table_list.tables[table_index].length = - table_to_install->length; - acpi_gbl_root_table_list.tables[table_index].flags = flags; - - ACPI_MOVE_32_TO_32(& - (acpi_gbl_root_table_list.tables[table_index]. - signature), table_to_install->signature); - - acpi_tb_print_table_header(address, table_to_install); - - if (table_index == ACPI_TABLE_INDEX_DSDT) { - - /* Global integer width is based upon revision of the DSDT */ - - acpi_ut_set_integer_width(table_to_install->revision); - } - - unmap_and_exit: - acpi_os_unmap_memory(mapped_table, sizeof(struct acpi_table_header)); -} - -/******************************************************************************* - * * FUNCTION: acpi_tb_get_root_table_entry * * PARAMETERS: table_entry - Pointer to the RSDT/XSDT table entry @@ -560,7 +217,7 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) * Get the table physical address (32-bit for RSDT, 64-bit for XSDT): * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT */ - if (table_entry_size == sizeof(u32)) { + if (table_entry_size == ACPI_RSDT_ENTRY_SIZE) { /* * 32-bit platform, RSDT: Return 32-bit table entry * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return @@ -580,10 +237,10 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) /* Will truncate 64-bit address to 32 bits, issue warning */ - ACPI_WARNING((AE_INFO, - "64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X)," - " truncating", - ACPI_FORMAT_UINT64(address64))); + ACPI_BIOS_WARNING((AE_INFO, + "64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X)," + " truncating", + ACPI_FORMAT_UINT64(address64))); } #endif return ((acpi_physical_address) (address64)); @@ -594,7 +251,7 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) * * FUNCTION: acpi_tb_parse_root_table * - * PARAMETERS: Rsdp - Pointer to the RSDP + * PARAMETERS: rsdp - Pointer to the RSDP * * RETURN: Status * @@ -607,8 +264,7 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) * ******************************************************************************/ -acpi_status __init -acpi_tb_parse_root_table(acpi_physical_address rsdp_address) +acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) { struct acpi_table_rsdp *rsdp; u32 table_entry_size; @@ -616,16 +272,15 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address) u32 table_count; struct acpi_table_header *table; acpi_physical_address address; - acpi_physical_address uninitialized_var(rsdt_address); u32 length; u8 *table_entry; acpi_status status; + u32 table_index; ACPI_FUNCTION_TRACE(tb_parse_root_table); - /* - * Map the entire RSDP and extract the address of the RSDT or XSDT - */ + /* Map the entire RSDP and extract the address of the RSDT or XSDT */ + rsdp = acpi_os_map_memory(rsdp_address, sizeof(struct acpi_table_rsdp)); if (!rsdp) { return_ACPI_STATUS(AE_NO_MEMORY); @@ -635,24 +290,22 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address) ACPI_CAST_PTR(struct acpi_table_header, rsdp)); - /* Differentiate between RSDT and XSDT root tables */ + /* Use XSDT if present and not overridden. Otherwise, use RSDT */ - if (rsdp->revision > 1 && rsdp->xsdt_physical_address - && !acpi_rsdt_forced) { + if ((rsdp->revision > 1) && + rsdp->xsdt_physical_address && !acpi_gbl_do_not_use_xsdt) { /* - * Root table is an XSDT (64-bit physical addresses). We must use the - * XSDT if the revision is > 1 and the XSDT pointer is present, as per - * the ACPI specification. + * RSDP contains an XSDT (64-bit physical addresses). We must use + * the XSDT if the revision is > 1 and the XSDT pointer is present, + * as per the ACPI specification. */ address = (acpi_physical_address) rsdp->xsdt_physical_address; - table_entry_size = sizeof(u64); - rsdt_address = (acpi_physical_address) - rsdp->rsdt_physical_address; + table_entry_size = ACPI_XSDT_ENTRY_SIZE; } else { /* Root table is an RSDT (32-bit physical addresses) */ address = (acpi_physical_address) rsdp->rsdt_physical_address; - table_entry_size = sizeof(u32); + table_entry_size = ACPI_RSDT_ENTRY_SIZE; } /* @@ -661,15 +314,6 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address) */ acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp)); - if (table_entry_size == sizeof(u64)) { - if (acpi_tb_check_xsdt(address) == AE_NULL_ENTRY) { - /* XSDT has NULL entry, RSDT is used */ - address = rsdt_address; - table_entry_size = sizeof(u32); - ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry, " - "using RSDT")); - } - } /* Map the RSDT/XSDT table header to get the full table length */ table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); @@ -679,14 +323,17 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address) acpi_tb_print_table_header(address, table); - /* Get the length of the full table, verify length and map entire table */ - + /* + * Validate length of the table, and map entire table. + * Minimum length table must contain at least one entry. + */ length = table->length; acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); - if (length < sizeof(struct acpi_table_header)) { - ACPI_ERROR((AE_INFO, "Invalid length 0x%X in RSDT/XSDT", - length)); + if (length < (sizeof(struct acpi_table_header) + table_entry_size)) { + ACPI_BIOS_ERROR((AE_INFO, + "Invalid table length 0x%X in RSDT/XSDT", + length)); return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); } @@ -703,72 +350,52 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address) return_ACPI_STATUS(status); } - /* Calculate the number of tables described in the root table */ + /* Get the number of entries and pointer to first entry */ table_count = (u32)((table->length - sizeof(struct acpi_table_header)) / table_entry_size); + table_entry = ACPI_ADD_PTR(u8, table, sizeof(struct acpi_table_header)); + /* * First two entries in the table array are reserved for the DSDT * and FACS, which are not actually present in the RSDT/XSDT - they * come from the FADT */ - table_entry = - ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); acpi_gbl_root_table_list.current_table_count = 2; - /* - * Initialize the root table array from the RSDT/XSDT - */ + /* Initialize the root table array from the RSDT/XSDT */ + for (i = 0; i < table_count; i++) { - if (acpi_gbl_root_table_list.current_table_count >= - acpi_gbl_root_table_list.max_table_count) { - - /* There is no more room in the root table array, attempt resize */ - - status = acpi_tb_resize_root_table_list(); - if (ACPI_FAILURE(status)) { - ACPI_WARNING((AE_INFO, - "Truncating %u table entries!", - (unsigned) (table_count - - (acpi_gbl_root_table_list. - current_table_count - - 2)))); - break; - } - } /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ - acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list. - current_table_count].address = + address = acpi_tb_get_root_table_entry(table_entry, table_entry_size); - table_entry += table_entry_size; - acpi_gbl_root_table_list.current_table_count++; - } - - /* - * It is not possible to map more than one entry in some environments, - * so unmap the root table here before mapping other tables - */ - acpi_os_unmap_memory(table, length); + /* Skip NULL entries in RSDT/XSDT */ - /* - * Complete the initialization of the root table array by examining - * the header of each table - */ - for (i = 2; i < acpi_gbl_root_table_list.current_table_count; i++) { - acpi_tb_install_table(acpi_gbl_root_table_list.tables[i]. - address, NULL, i); + if (!address) { + goto next_table; + } - /* Special case for FADT - get the DSDT and FACS */ + status = acpi_tb_install_standard_table(address, + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, + FALSE, TRUE, + &table_index); - if (ACPI_COMPARE_NAME - (&acpi_gbl_root_table_list.tables[i].signature, - ACPI_SIG_FADT)) { - acpi_tb_parse_fadt(i); + if (ACPI_SUCCESS(status) && + ACPI_COMPARE_NAME(&acpi_gbl_root_table_list. + tables[table_index].signature, + ACPI_SIG_FADT)) { + acpi_tb_parse_fadt(table_index); } + +next_table: + + table_entry += table_entry_size; } + acpi_os_unmap_memory(table, length); + return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index abcc6412c24..6482b0ded65 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -1,12 +1,11 @@ /****************************************************************************** * - * Module Name: tbxface - Public interfaces to the ACPI subsystem - * ACPI table oriented interfaces + * Module Name: tbxface - ACPI table-oriented external interfaces * *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,20 +41,15 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include <linux/export.h> +#define EXPORT_ACPI_INTERFACES + #include <acpi/acpi.h> #include "accommon.h" -#include "acnamesp.h" #include "actables.h" #define _COMPONENT ACPI_TABLES ACPI_MODULE_NAME("tbxface") -/* Local prototypes */ -static acpi_status acpi_tb_load_namespace(void); - -static int no_auto_ssdt; - /******************************************************************************* * * FUNCTION: acpi_allocate_root_table @@ -65,11 +59,10 @@ static int no_auto_ssdt; * * RETURN: Status * - * DESCRIPTION: Allocate a root table array. Used by i_aSL compiler and + * DESCRIPTION: Allocate a root table array. Used by iASL compiler and * acpi_initialize_tables. * ******************************************************************************/ - acpi_status acpi_allocate_root_table(u32 initial_table_count) { @@ -88,7 +81,7 @@ acpi_status acpi_allocate_root_table(u32 initial_table_count) * array is dynamically allocated. * initial_table_count - Size of initial_table_array, in number of * struct acpi_table_desc structures - * allow_realloc - Flag to tell Table Manager if resize of + * allow_resize - Flag to tell Table Manager if resize of * pre-allocated array is allowed. Ignored * if initial_table_array is NULL. * @@ -115,8 +108,8 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array, ACPI_FUNCTION_TRACE(acpi_initialize_tables); /* - * Set up the Root Table Array - * Allocate the table array if requested + * Setup the Root Table Array and allocate the table array + * if requested */ if (!initial_table_array) { status = acpi_allocate_root_table(initial_table_count); @@ -155,6 +148,8 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array, return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_tables) + /******************************************************************************* * * FUNCTION: acpi_reallocate_root_table @@ -166,14 +161,12 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array, * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the * root list from the previously provided scratch area. Should * be called once dynamic memory allocation is available in the - * kernel + * kernel. * ******************************************************************************/ -acpi_status acpi_reallocate_root_table(void) +acpi_status __init acpi_reallocate_root_table(void) { - struct acpi_table_desc *tables; - acpi_size new_size; - acpi_size current_size; + acpi_status status; ACPI_FUNCTION_TRACE(acpi_reallocate_root_table); @@ -185,89 +178,20 @@ acpi_status acpi_reallocate_root_table(void) return_ACPI_STATUS(AE_SUPPORT); } - /* - * Get the current size of the root table and add the default - * increment to create the new table size. - */ - current_size = (acpi_size) - acpi_gbl_root_table_list.current_table_count * - sizeof(struct acpi_table_desc); - - new_size = current_size + - (ACPI_ROOT_TABLE_SIZE_INCREMENT * sizeof(struct acpi_table_desc)); - - /* Create new array and copy the old array */ - - tables = ACPI_ALLOCATE_ZEROED(new_size); - if (!tables) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, current_size); - - /* - * Update the root table descriptor. The new size will be the current - * number of tables plus the increment, independent of the reserved - * size of the original table list. - */ - acpi_gbl_root_table_list.tables = tables; - acpi_gbl_root_table_list.max_table_count = - acpi_gbl_root_table_list.current_table_count + - ACPI_ROOT_TABLE_SIZE_INCREMENT; - acpi_gbl_root_table_list.flags = - ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE; - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_load_table - * - * PARAMETERS: table_ptr - pointer to a buffer containing the entire - * table to be loaded - * - * RETURN: Status - * - * DESCRIPTION: This function is called to load a table from the caller's - * buffer. The buffer must contain an entire ACPI Table including - * a valid header. The header fields will be verified, and if it - * is determined that the table is invalid, the call will fail. - * - ******************************************************************************/ -acpi_status acpi_load_table(struct acpi_table_header *table_ptr) -{ - acpi_status status; - u32 table_index; - struct acpi_table_desc table_desc; - - if (!table_ptr) - return AE_BAD_PARAMETER; - - ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc)); - table_desc.pointer = table_ptr; - table_desc.length = table_ptr->length; - table_desc.flags = ACPI_TABLE_ORIGIN_UNKNOWN; + acpi_gbl_root_table_list.flags |= ACPI_ROOT_ALLOW_RESIZE; - /* - * Install the new table into the local data structures - */ - status = acpi_tb_add_table(&table_desc, &table_index); - if (ACPI_FAILURE(status)) { - return status; - } - status = acpi_ns_load_table(table_index, acpi_gbl_root_node); - return status; + status = acpi_tb_resize_root_table_list(); + return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_load_table) +ACPI_EXPORT_SYMBOL_INIT(acpi_reallocate_root_table) /******************************************************************************* * * FUNCTION: acpi_get_table_header * - * PARAMETERS: Signature - ACPI signature of needed table - * Instance - Which instance (for SSDTs) + * PARAMETERS: signature - ACPI signature of needed table + * instance - Which instance (for SSDTs) * out_table_header - The pointer to the table header to fill * * RETURN: Status and pointer to mapped table header @@ -282,8 +206,8 @@ acpi_status acpi_get_table_header(char *signature, u32 instance, struct acpi_table_header *out_table_header) { - u32 i; - u32 j; + u32 i; + u32 j; struct acpi_table_header *header; /* Parameter validation */ @@ -309,14 +233,14 @@ acpi_get_table_header(char *signature, if (!acpi_gbl_root_table_list.tables[i].pointer) { if ((acpi_gbl_root_table_list.tables[i].flags & ACPI_TABLE_ORIGIN_MASK) == - ACPI_TABLE_ORIGIN_MAPPED) { + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL) { header = acpi_os_map_memory(acpi_gbl_root_table_list. tables[i].address, sizeof(struct acpi_table_header)); if (!header) { - return AE_NO_MEMORY; + return (AE_NO_MEMORY); } ACPI_MEMCPY(out_table_header, header, sizeof(struct acpi_table_header)); @@ -324,7 +248,7 @@ acpi_get_table_header(char *signature, sizeof(struct acpi_table_header)); } else { - return AE_NOT_FOUND; + return (AE_NOT_FOUND); } } else { ACPI_MEMCPY(out_table_header, @@ -382,13 +306,14 @@ ACPI_EXPORT_SYMBOL(acpi_unload_table_id) * * FUNCTION: acpi_get_table_with_size * - * PARAMETERS: Signature - ACPI signature of needed table - * Instance - Which instance (for SSDTs) + * PARAMETERS: signature - ACPI signature of needed table + * instance - Which instance (for SSDTs) * out_table - Where the pointer to the table is returned * - * RETURN: Status and pointer to table + * RETURN: Status and pointer to the requested table * - * DESCRIPTION: Finds and verifies an ACPI table. + * DESCRIPTION: Finds and verifies an ACPI table. Table must be in the + * RSDT/XSDT. * ******************************************************************************/ acpi_status @@ -396,8 +321,8 @@ acpi_get_table_with_size(char *signature, u32 instance, struct acpi_table_header **out_table, acpi_size *tbl_size) { - u32 i; - u32 j; + u32 i; + u32 j; acpi_status status; /* Parameter validation */ @@ -421,7 +346,7 @@ acpi_get_table_with_size(char *signature, } status = - acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]); + acpi_tb_validate_table(&acpi_gbl_root_table_list.tables[i]); if (ACPI_SUCCESS(status)) { *out_table = acpi_gbl_root_table_list.tables[i].pointer; *tbl_size = acpi_gbl_root_table_list.tables[i].length; @@ -437,6 +362,8 @@ acpi_get_table_with_size(char *signature, return (AE_NOT_FOUND); } +ACPI_EXPORT_SYMBOL(acpi_get_table_with_size) + acpi_status acpi_get_table(char *signature, u32 instance, struct acpi_table_header **out_table) @@ -446,6 +373,7 @@ acpi_get_table(char *signature, return acpi_get_table_with_size(signature, instance, out_table, &tbl_size); } + ACPI_EXPORT_SYMBOL(acpi_get_table) /******************************************************************************* @@ -453,15 +381,16 @@ ACPI_EXPORT_SYMBOL(acpi_get_table) * FUNCTION: acpi_get_table_by_index * * PARAMETERS: table_index - Table index - * Table - Where the pointer to the table is returned + * table - Where the pointer to the table is returned * - * RETURN: Status and pointer to the table + * RETURN: Status and pointer to the requested table * - * DESCRIPTION: Obtain a table by an index into the global table list. + * DESCRIPTION: Obtain a table by an index into the global table list. Used + * internally also. * ******************************************************************************/ acpi_status -acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table) +acpi_get_table_by_index(u32 table_index, struct acpi_table_header ** table) { acpi_status status; @@ -487,8 +416,8 @@ acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table) /* Table is not mapped, map it */ status = - acpi_tb_verify_table(&acpi_gbl_root_table_list. - tables[table_index]); + acpi_tb_validate_table(&acpi_gbl_root_table_list. + tables[table_index]); if (ACPI_FAILURE(status)) { (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_ACPI_STATUS(status); @@ -504,163 +433,18 @@ ACPI_EXPORT_SYMBOL(acpi_get_table_by_index) /******************************************************************************* * - * FUNCTION: acpi_tb_load_namespace - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in - * the RSDT/XSDT. - * - ******************************************************************************/ -static acpi_status acpi_tb_load_namespace(void) -{ - acpi_status status; - u32 i; - struct acpi_table_header *new_dsdt; - - ACPI_FUNCTION_TRACE(tb_load_namespace); - - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - - /* - * Load the namespace. The DSDT is required, but any SSDT and - * PSDT tables are optional. Verify the DSDT. - */ - if (!acpi_gbl_root_table_list.current_table_count || - !ACPI_COMPARE_NAME(& - (acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT].signature), - ACPI_SIG_DSDT) - || - ACPI_FAILURE(acpi_tb_verify_table - (&acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT]))) { - status = AE_NO_ACPI_TABLES; - goto unlock_and_exit; - } - - /* - * Save the DSDT pointer for simple access. This is the mapped memory - * address. We must take care here because the address of the .Tables - * array can change dynamically as tables are loaded at run-time. Note: - * .Pointer field is not validated until after call to acpi_tb_verify_table. - */ - acpi_gbl_DSDT = - acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer; - - /* - * Optionally copy the entire DSDT to local memory (instead of simply - * mapping it.) There are some BIOSs that corrupt or replace the original - * DSDT, creating the need for this option. Default is FALSE, do not copy - * the DSDT. - */ - if (acpi_gbl_copy_dsdt_locally) { - new_dsdt = acpi_tb_copy_dsdt(ACPI_TABLE_INDEX_DSDT); - if (new_dsdt) { - acpi_gbl_DSDT = new_dsdt; - } - } - - /* - * Save the original DSDT header for detection of table corruption - * and/or replacement of the DSDT from outside the OS. - */ - ACPI_MEMCPY(&acpi_gbl_original_dsdt_header, acpi_gbl_DSDT, - sizeof(struct acpi_table_header)); - - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - - /* Load and parse tables */ - - status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ - - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { - if ((!ACPI_COMPARE_NAME - (&(acpi_gbl_root_table_list.tables[i].signature), - ACPI_SIG_SSDT) - && - !ACPI_COMPARE_NAME(& - (acpi_gbl_root_table_list.tables[i]. - signature), ACPI_SIG_PSDT)) - || - ACPI_FAILURE(acpi_tb_verify_table - (&acpi_gbl_root_table_list.tables[i]))) { - continue; - } - - if (no_auto_ssdt) { - printk(KERN_WARNING "ACPI: SSDT ignored due to \"acpi_no_auto_ssdt\"\n"); - continue; - } - - /* Ignore errors while loading tables, get as many as possible */ - - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - (void)acpi_ns_load_table(i, acpi_gbl_root_node); - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - } - - ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); - - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_load_tables - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT - * - ******************************************************************************/ - -acpi_status acpi_load_tables(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_load_tables); - - /* Load the namespace from the tables */ - - status = acpi_tb_load_namespace(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "While loading namespace from ACPI tables")); - } - - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_load_tables) - - -/******************************************************************************* - * * FUNCTION: acpi_install_table_handler * - * PARAMETERS: Handler - Table event handler - * Context - Value passed to the handler on each event + * PARAMETERS: handler - Table event handler + * context - Value passed to the handler on each event * * RETURN: Status * - * DESCRIPTION: Install table event handler + * DESCRIPTION: Install a global table event handler. * ******************************************************************************/ acpi_status -acpi_install_table_handler(acpi_tbl_handler handler, void *context) +acpi_install_table_handler(acpi_table_handler handler, void *context) { acpi_status status; @@ -687,7 +471,7 @@ acpi_install_table_handler(acpi_tbl_handler handler, void *context) acpi_gbl_table_handler = handler; acpi_gbl_table_handler_context = context; - cleanup: +cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } @@ -698,15 +482,15 @@ ACPI_EXPORT_SYMBOL(acpi_install_table_handler) * * FUNCTION: acpi_remove_table_handler * - * PARAMETERS: Handler - Table event handler that was installed + * PARAMETERS: handler - Table event handler that was installed * previously. * * RETURN: Status * - * DESCRIPTION: Remove table event handler + * DESCRIPTION: Remove a table event handler * ******************************************************************************/ -acpi_status acpi_remove_table_handler(acpi_tbl_handler handler) +acpi_status acpi_remove_table_handler(acpi_table_handler handler) { acpi_status status; @@ -728,21 +512,9 @@ acpi_status acpi_remove_table_handler(acpi_tbl_handler handler) acpi_gbl_table_handler = NULL; - cleanup: +cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } ACPI_EXPORT_SYMBOL(acpi_remove_table_handler) - - -static int __init acpi_no_auto_ssdt_setup(char *s) { - - printk(KERN_NOTICE "ACPI: SSDT auto-load disabled\n"); - - no_auto_ssdt = 1; - - return 1; -} - -__setup("acpi_no_auto_ssdt", acpi_no_auto_ssdt_setup); diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c new file mode 100644 index 00000000000..ab5308b81aa --- /dev/null +++ b/drivers/acpi/acpica/tbxfload.c @@ -0,0 +1,418 @@ +/****************************************************************************** + * + * Module Name: tbxfload - Table load/unload external interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define EXPORT_ACPI_INTERFACES + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acnamesp.h" +#include "actables.h" + +#define _COMPONENT ACPI_TABLES +ACPI_MODULE_NAME("tbxfload") + +/* Local prototypes */ +static acpi_status acpi_tb_load_namespace(void); + +/******************************************************************************* + * + * FUNCTION: acpi_load_tables + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT + * + ******************************************************************************/ + +acpi_status __init acpi_load_tables(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_load_tables); + + /* Load the namespace from the tables */ + + status = acpi_tb_load_namespace(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "While loading namespace from ACPI tables")); + } + + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL_INIT(acpi_load_tables) + +/******************************************************************************* + * + * FUNCTION: acpi_tb_load_namespace + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in + * the RSDT/XSDT. + * + ******************************************************************************/ +static acpi_status acpi_tb_load_namespace(void) +{ + acpi_status status; + u32 i; + struct acpi_table_header *new_dsdt; + + ACPI_FUNCTION_TRACE(tb_load_namespace); + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + + /* + * Load the namespace. The DSDT is required, but any SSDT and + * PSDT tables are optional. Verify the DSDT. + */ + if (!acpi_gbl_root_table_list.current_table_count || + !ACPI_COMPARE_NAME(& + (acpi_gbl_root_table_list. + tables[ACPI_TABLE_INDEX_DSDT].signature), + ACPI_SIG_DSDT) + || + ACPI_FAILURE(acpi_tb_validate_table + (&acpi_gbl_root_table_list. + tables[ACPI_TABLE_INDEX_DSDT]))) { + status = AE_NO_ACPI_TABLES; + goto unlock_and_exit; + } + + /* + * Save the DSDT pointer for simple access. This is the mapped memory + * address. We must take care here because the address of the .Tables + * array can change dynamically as tables are loaded at run-time. Note: + * .Pointer field is not validated until after call to acpi_tb_validate_table. + */ + acpi_gbl_DSDT = + acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer; + + /* + * Optionally copy the entire DSDT to local memory (instead of simply + * mapping it.) There are some BIOSs that corrupt or replace the original + * DSDT, creating the need for this option. Default is FALSE, do not copy + * the DSDT. + */ + if (acpi_gbl_copy_dsdt_locally) { + new_dsdt = acpi_tb_copy_dsdt(ACPI_TABLE_INDEX_DSDT); + if (new_dsdt) { + acpi_gbl_DSDT = new_dsdt; + } + } + + /* + * Save the original DSDT header for detection of table corruption + * and/or replacement of the DSDT from outside the OS. + */ + ACPI_MEMCPY(&acpi_gbl_original_dsdt_header, acpi_gbl_DSDT, + sizeof(struct acpi_table_header)); + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + + /* Load and parse tables */ + + status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { + if ((!ACPI_COMPARE_NAME + (&(acpi_gbl_root_table_list.tables[i].signature), + ACPI_SIG_SSDT) + && + !ACPI_COMPARE_NAME(& + (acpi_gbl_root_table_list.tables[i]. + signature), ACPI_SIG_PSDT)) + || + ACPI_FAILURE(acpi_tb_validate_table + (&acpi_gbl_root_table_list.tables[i]))) { + continue; + } + + /* Ignore errors while loading tables, get as many as possible */ + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + (void)acpi_ns_load_table(i, acpi_gbl_root_node); + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + } + + ACPI_INFO((AE_INFO, "All ACPI Tables successfully acquired")); + +unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_install_table + * + * PARAMETERS: address - Address of the ACPI table to be installed. + * physical - Whether the address is a physical table + * address or not + * + * RETURN: Status + * + * DESCRIPTION: Dynamically install an ACPI table. + * Note: This function should only be invoked after + * acpi_initialize_tables() and before acpi_load_tables(). + * + ******************************************************************************/ + +acpi_status __init +acpi_install_table(acpi_physical_address address, u8 physical) +{ + acpi_status status; + u8 flags; + u32 table_index; + + ACPI_FUNCTION_TRACE(acpi_install_table); + + if (physical) { + flags = ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL; + } else { + flags = ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL; + } + + status = acpi_tb_install_standard_table(address, flags, + FALSE, FALSE, &table_index); + + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL_INIT(acpi_install_table) + +/******************************************************************************* + * + * FUNCTION: acpi_load_table + * + * PARAMETERS: table - Pointer to a buffer containing the ACPI + * table to be loaded. + * + * RETURN: Status + * + * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must + * be a valid ACPI table with a valid ACPI table header. + * Note1: Mainly intended to support hotplug addition of SSDTs. + * Note2: Does not copy the incoming table. User is responsible + * to ensure that the table is not deleted or unmapped. + * + ******************************************************************************/ +acpi_status acpi_load_table(struct acpi_table_header *table) +{ + acpi_status status; + u32 table_index; + + ACPI_FUNCTION_TRACE(acpi_load_table); + + /* Parameter validation */ + + if (!table) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Must acquire the interpreter lock during this operation */ + + status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Install the table and load it into the namespace */ + + ACPI_INFO((AE_INFO, "Host-directed Dynamic ACPI Table Load:")); + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + + status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table), + ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, + TRUE, FALSE, &table_index); + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + + /* + * Note: Now table is "INSTALLED", it must be validated before + * using. + */ + status = + acpi_tb_validate_table(&acpi_gbl_root_table_list. + tables[table_index]); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + + status = acpi_ns_load_table(table_index, acpi_gbl_root_node); + + /* Invoke table handler if present */ + + if (acpi_gbl_table_handler) { + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table, + acpi_gbl_table_handler_context); + } + +unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_load_table) + +/******************************************************************************* + * + * FUNCTION: acpi_unload_parent_table + * + * PARAMETERS: object - Handle to any namespace object owned by + * the table to be unloaded + * + * RETURN: Status + * + * DESCRIPTION: Via any namespace object within an SSDT or OEMx table, unloads + * the table and deletes all namespace objects associated with + * that table. Unloading of the DSDT is not allowed. + * Note: Mainly intended to support hotplug removal of SSDTs. + * + ******************************************************************************/ +acpi_status acpi_unload_parent_table(acpi_handle object) +{ + struct acpi_namespace_node *node = + ACPI_CAST_PTR(struct acpi_namespace_node, object); + acpi_status status = AE_NOT_EXIST; + acpi_owner_id owner_id; + u32 i; + + ACPI_FUNCTION_TRACE(acpi_unload_parent_table); + + /* Parameter validation */ + + if (!object) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * The node owner_id is currently the same as the parent table ID. + * However, this could change in the future. + */ + owner_id = node->owner_id; + if (!owner_id) { + + /* owner_id==0 means DSDT is the owner. DSDT cannot be unloaded */ + + return_ACPI_STATUS(AE_TYPE); + } + + /* Must acquire the interpreter lock during this operation */ + + status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Find the table in the global table list */ + + for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { + if (owner_id != acpi_gbl_root_table_list.tables[i].owner_id) { + continue; + } + + /* + * Allow unload of SSDT and OEMx tables only. Do not allow unload + * of the DSDT. No other types of tables should get here, since + * only these types can contain AML and thus are the only types + * that can create namespace objects. + */ + if (ACPI_COMPARE_NAME + (acpi_gbl_root_table_list.tables[i].signature.ascii, + ACPI_SIG_DSDT)) { + status = AE_TYPE; + break; + } + + /* Ensure the table is actually loaded */ + + if (!acpi_tb_is_table_loaded(i)) { + status = AE_NOT_EXIST; + break; + } + + /* Invoke table handler if present */ + + if (acpi_gbl_table_handler) { + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD, + acpi_gbl_root_table_list. + tables[i].pointer, + acpi_gbl_table_handler_context); + } + + /* + * Delete all namespace objects owned by this table. Note that + * these objects can appear anywhere in the namespace by virtue + * of the AML "Scope" operator. Thus, we need to track ownership + * by an ID, not simply a position within the hierarchy. + */ + status = acpi_tb_delete_namespace_by_owner(i); + if (ACPI_FAILURE(status)) { + break; + } + + status = acpi_tb_release_owner_id(i); + acpi_tb_set_table_loaded_flag(i, FALSE); + break; + } + + (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_unload_parent_table) diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c index 4258f647ca3..65ab8fed3d5 100644 --- a/drivers/acpi/acpica/tbxfroot.c +++ b/drivers/acpi/acpica/tbxfroot.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,26 +48,19 @@ #define _COMPONENT ACPI_TABLES ACPI_MODULE_NAME("tbxfroot") -/* Local prototypes */ -static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length); - -static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp); - /******************************************************************************* * * FUNCTION: acpi_tb_validate_rsdp * - * PARAMETERS: Rsdp - Pointer to unvalidated RSDP + * PARAMETERS: rsdp - Pointer to unvalidated RSDP * * RETURN: Status * * DESCRIPTION: Validate the RSDP (ptr) * ******************************************************************************/ - -static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) +acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) { - ACPI_FUNCTION_ENTRY(); /* * The signature and checksum must both be correct @@ -75,8 +68,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) * Note: Sometimes there exists more than one RSDP in memory; the valid * RSDP has a valid checksum, all others have an invalid checksum. */ - if (ACPI_STRNCMP((char *)rsdp, ACPI_SIG_RSDP, - sizeof(ACPI_SIG_RSDP) - 1) != 0) { + if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) { /* Nope, BAD Signature */ @@ -107,10 +99,10 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) * * RETURN: Status, RSDP physical address * - * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor - * pointer structure. If it is found, set *RSDP to point to it. + * DESCRIPTION: Search lower 1Mbyte of memory for the root system descriptor + * pointer structure. If it is found, set *RSDP to point to it. * - * NOTE1: The RSDP must be either in the first 1_k of the Extended + * NOTE1: The RSDP must be either in the first 1K of the Extended * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) * Only a 32-bit physical address is necessary. * @@ -119,7 +111,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) * ******************************************************************************/ -acpi_status acpi_find_root_pointer(acpi_size *table_address) +acpi_status __init acpi_find_root_pointer(acpi_size *table_address) { u8 *table_ptr; u8 *mem_rover; @@ -152,7 +144,7 @@ acpi_status acpi_find_root_pointer(acpi_size *table_address) if (physical_address > 0x400) { /* * 1b) Search EBDA paragraphs (EBDA is required to be a - * minimum of 1_k length) + * minimum of 1K length) */ table_ptr = acpi_os_map_memory((acpi_physical_address) physical_address, @@ -216,7 +208,7 @@ acpi_status acpi_find_root_pointer(acpi_size *table_address) /* A valid RSDP was not found */ - ACPI_ERROR((AE_INFO, "A valid RSDP was not found")); + ACPI_BIOS_ERROR((AE_INFO, "A valid RSDP was not found")); return_ACPI_STATUS(AE_NOT_FOUND); } @@ -225,14 +217,14 @@ acpi_status acpi_find_root_pointer(acpi_size *table_address) * FUNCTION: acpi_tb_scan_memory_for_rsdp * * PARAMETERS: start_address - Starting pointer for search - * Length - Maximum length to search + * length - Maximum length to search * * RETURN: Pointer to the RSDP if found, otherwise NULL. * * DESCRIPTION: Search a block of memory for the RSDP signature * ******************************************************************************/ -static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length) +u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length) { acpi_status status; u8 *mem_rover; diff --git a/drivers/acpi/acpica/utaddress.c b/drivers/acpi/acpica/utaddress.c index 67932aebe6d..a1acec9d2ef 100644 --- a/drivers/acpi/acpica/utaddress.c +++ b/drivers/acpi/acpica/utaddress.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,8 +53,8 @@ ACPI_MODULE_NAME("utaddress") * FUNCTION: acpi_ut_add_address_range * * PARAMETERS: space_id - Address space ID - * Address - op_region start address - * Length - op_region length + * address - op_region start address + * length - op_region length * region_node - op_region namespace node * * RETURN: Status @@ -186,9 +186,9 @@ acpi_ut_remove_address_range(acpi_adr_space_type space_id, * FUNCTION: acpi_ut_check_address_range * * PARAMETERS: space_id - Address space ID - * Address - Start address - * Length - Length of address range - * Warn - TRUE if warning on overlap desired + * address - Start address + * length - Length of address range + * warn - TRUE if warning on overlap desired * * RETURN: Count of the number of conflicts detected. Zero is always * returned for Space IDs other than Memory or I/O. @@ -224,10 +224,11 @@ acpi_ut_check_address_range(acpi_adr_space_type space_id, while (range_info) { /* - * Check if the requested Address/Length overlaps this address_range. - * Four cases to consider: + * Check if the requested address/length overlaps this + * address range. There are four cases to consider: * - * 1) Input address/length is contained completely in the address range + * 1) Input address/length is contained completely in the + * address range * 2) Input address/length overlaps range at the range start * 3) Input address/length overlaps range at the range end * 4) Input address/length completely encompasses the range @@ -244,11 +245,17 @@ acpi_ut_check_address_range(acpi_adr_space_type space_id, region_node); ACPI_WARNING((AE_INFO, - "0x%p-0x%p %s conflicts with Region %s %d", + "%s range 0x%p-0x%p conflicts with OpRegion 0x%p-0x%p (%s)", + acpi_ut_get_region_name(space_id), ACPI_CAST_PTR(void, address), ACPI_CAST_PTR(void, end_address), - acpi_ut_get_region_name(space_id), - pathname, overlap_count)); + ACPI_CAST_PTR(void, + range_info-> + start_address), + ACPI_CAST_PTR(void, + range_info-> + end_address), + pathname)); ACPI_FREE(pathname); } } diff --git a/drivers/acpi/acpica/utalloc.c b/drivers/acpi/acpica/utalloc.c index 9982d2ea66f..efac83c606d 100644 --- a/drivers/acpi/acpica/utalloc.c +++ b/drivers/acpi/acpica/utalloc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,6 +48,39 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utalloc") +#if !defined (USE_NATIVE_ALLOCATE_ZEROED) +/******************************************************************************* + * + * FUNCTION: acpi_os_allocate_zeroed + * + * PARAMETERS: size - Size of the allocation + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory. + * This is the default implementation. Can be overridden via the + * USE_NATIVE_ALLOCATE_ZEROED flag. + * + ******************************************************************************/ +void *acpi_os_allocate_zeroed(acpi_size size) +{ + void *allocation; + + ACPI_FUNCTION_ENTRY(); + + allocation = acpi_os_allocate(size); + if (allocation) { + + /* Clear the memory block */ + + ACPI_MEMSET(allocation, 0, size); + } + + return (allocation); +} + +#endif /* !USE_NATIVE_ALLOCATE_ZEROED */ + /******************************************************************************* * * FUNCTION: acpi_ut_create_caches @@ -59,6 +92,7 @@ ACPI_MODULE_NAME("utalloc") * DESCRIPTION: Create all local caches * ******************************************************************************/ + acpi_status acpi_ut_create_caches(void) { acpi_status status; @@ -175,10 +209,10 @@ acpi_status acpi_ut_delete_caches(void) /* Free memory lists */ - ACPI_FREE(acpi_gbl_global_list); + acpi_os_free(acpi_gbl_global_list); acpi_gbl_global_list = NULL; - ACPI_FREE(acpi_gbl_ns_node_list); + acpi_os_free(acpi_gbl_ns_node_list); acpi_gbl_ns_node_list = NULL; #endif @@ -189,7 +223,7 @@ acpi_status acpi_ut_delete_caches(void) * * FUNCTION: acpi_ut_validate_buffer * - * PARAMETERS: Buffer - Buffer descriptor to be validated + * PARAMETERS: buffer - Buffer descriptor to be validated * * RETURN: Status * @@ -227,7 +261,7 @@ acpi_status acpi_ut_validate_buffer(struct acpi_buffer * buffer) * * FUNCTION: acpi_ut_initialize_buffer * - * PARAMETERS: Buffer - Buffer to be validated + * PARAMETERS: buffer - Buffer to be validated * required_length - Length needed * * RETURN: Status @@ -268,9 +302,13 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer, return (AE_BUFFER_OVERFLOW); case ACPI_ALLOCATE_BUFFER: - - /* Allocate a new buffer */ - + /* + * Allocate a new buffer. We directectly call acpi_os_allocate here to + * purposefully bypass the (optionally enabled) internal allocation + * tracking mechanism since we only want to track internal + * allocations. Note: The caller should use acpi_os_free to free this + * buffer created via ACPI_ALLOCATE_BUFFER. + */ buffer->pointer = acpi_os_allocate(required_length); break; @@ -302,82 +340,3 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer, ACPI_MEMSET(buffer->pointer, 0, required_length); return (AE_OK); } - -#ifdef NOT_USED_BY_LINUX -/******************************************************************************* - * - * FUNCTION: acpi_ut_allocate - * - * PARAMETERS: Size - Size of the allocation - * Component - Component type of caller - * Module - Source file name of caller - * Line - Line number of caller - * - * RETURN: Address of the allocated memory on success, NULL on failure. - * - * DESCRIPTION: Subsystem equivalent of malloc. - * - ******************************************************************************/ - -void *acpi_ut_allocate(acpi_size size, - u32 component, const char *module, u32 line) -{ - void *allocation; - - ACPI_FUNCTION_TRACE_U32(ut_allocate, size); - - /* Check for an inadvertent size of zero bytes */ - - if (!size) { - ACPI_WARNING((module, line, - "Attempt to allocate zero bytes, allocating 1 byte")); - size = 1; - } - - allocation = acpi_os_allocate(size); - if (!allocation) { - - /* Report allocation error */ - - ACPI_WARNING((module, line, - "Could not allocate size %u", (u32) size)); - - return_PTR(NULL); - } - - return_PTR(allocation); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_allocate_zeroed - * - * PARAMETERS: Size - Size of the allocation - * Component - Component type of caller - * Module - Source file name of caller - * Line - Line number of caller - * - * RETURN: Address of the allocated memory on success, NULL on failure. - * - * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory. - * - ******************************************************************************/ - -void *acpi_ut_allocate_zeroed(acpi_size size, - u32 component, const char *module, u32 line) -{ - void *allocation; - - ACPI_FUNCTION_ENTRY(); - - allocation = acpi_ut_allocate(size, component, module, line); - if (allocation) { - - /* Clear the memory block */ - - ACPI_MEMSET(allocation, 0, size); - } - - return (allocation); -} -#endif diff --git a/drivers/acpi/acpica/utbuffer.c b/drivers/acpi/acpica/utbuffer.c new file mode 100644 index 00000000000..3c169974065 --- /dev/null +++ b/drivers/acpi/acpica/utbuffer.c @@ -0,0 +1,201 @@ +/****************************************************************************** + * + * Module Name: utbuffer - Buffer dump routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utbuffer") + +/******************************************************************************* + * + * FUNCTION: acpi_ut_dump_buffer + * + * PARAMETERS: buffer - Buffer to dump + * count - Amount to dump, in bytes + * display - BYTE, WORD, DWORD, or QWORD display: + * DB_BYTE_DISPLAY + * DB_WORD_DISPLAY + * DB_DWORD_DISPLAY + * DB_QWORD_DISPLAY + * base_offset - Beginning buffer offset (display only) + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii. + * + ******************************************************************************/ +void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 base_offset) +{ + u32 i = 0; + u32 j; + u32 temp32; + u8 buf_char; + + if (!buffer) { + acpi_os_printf("Null Buffer Pointer in DumpBuffer!\n"); + return; + } + + if ((count < 4) || (count & 0x01)) { + display = DB_BYTE_DISPLAY; + } + + /* Nasty little dump buffer routine! */ + + while (i < count) { + + /* Print current offset */ + + acpi_os_printf("%6.4X: ", (base_offset + i)); + + /* Print 16 hex chars */ + + for (j = 0; j < 16;) { + if (i + j >= count) { + + /* Dump fill spaces */ + + acpi_os_printf("%*s", ((display * 2) + 1), " "); + j += display; + continue; + } + + switch (display) { + case DB_BYTE_DISPLAY: + default: /* Default is BYTE display */ + + acpi_os_printf("%02X ", + buffer[(acpi_size) i + j]); + break; + + case DB_WORD_DISPLAY: + + ACPI_MOVE_16_TO_32(&temp32, + &buffer[(acpi_size) i + j]); + acpi_os_printf("%04X ", temp32); + break; + + case DB_DWORD_DISPLAY: + + ACPI_MOVE_32_TO_32(&temp32, + &buffer[(acpi_size) i + j]); + acpi_os_printf("%08X ", temp32); + break; + + case DB_QWORD_DISPLAY: + + ACPI_MOVE_32_TO_32(&temp32, + &buffer[(acpi_size) i + j]); + acpi_os_printf("%08X", temp32); + + ACPI_MOVE_32_TO_32(&temp32, + &buffer[(acpi_size) i + j + + 4]); + acpi_os_printf("%08X ", temp32); + break; + } + + j += display; + } + + /* + * Print the ASCII equivalent characters but watch out for the bad + * unprintable ones (printable chars are 0x20 through 0x7E) + */ + acpi_os_printf(" "); + for (j = 0; j < 16; j++) { + if (i + j >= count) { + acpi_os_printf("\n"); + return; + } + + buf_char = buffer[(acpi_size) i + j]; + if (ACPI_IS_PRINT(buf_char)) { + acpi_os_printf("%c", buf_char); + } else { + acpi_os_printf("."); + } + } + + /* Done with that line. */ + + acpi_os_printf("\n"); + i += 16; + } + + return; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_debug_dump_buffer + * + * PARAMETERS: buffer - Buffer to dump + * count - Amount to dump, in bytes + * display - BYTE, WORD, DWORD, or QWORD display: + * DB_BYTE_DISPLAY + * DB_WORD_DISPLAY + * DB_DWORD_DISPLAY + * DB_QWORD_DISPLAY + * component_ID - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii. + * + ******************************************************************************/ + +void +acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id) +{ + + /* Only dump the buffer if tracing is enabled */ + + if (!((ACPI_LV_TABLES & acpi_dbg_level) && + (component_id & acpi_dbg_layer))) { + return; + } + + acpi_ut_dump_buffer(buffer, count, display, 0); +} diff --git a/drivers/acpi/acpica/utcache.c b/drivers/acpi/acpica/utcache.c new file mode 100644 index 00000000000..78fde0aac48 --- /dev/null +++ b/drivers/acpi/acpica/utcache.c @@ -0,0 +1,313 @@ +/****************************************************************************** + * + * Module Name: utcache - local cache allocation routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utcache") + +#ifdef ACPI_USE_LOCAL_CACHE +/******************************************************************************* + * + * FUNCTION: acpi_os_create_cache + * + * PARAMETERS: cache_name - Ascii name for the cache + * object_size - Size of each cached object + * max_depth - Maximum depth of the cache (in objects) + * return_cache - Where the new cache object is returned + * + * RETURN: Status + * + * DESCRIPTION: Create a cache object + * + ******************************************************************************/ +acpi_status +acpi_os_create_cache(char *cache_name, + u16 object_size, + u16 max_depth, struct acpi_memory_list **return_cache) +{ + struct acpi_memory_list *cache; + + ACPI_FUNCTION_ENTRY(); + + if (!cache_name || !return_cache || (object_size < 16)) { + return (AE_BAD_PARAMETER); + } + + /* Create the cache object */ + + cache = acpi_os_allocate(sizeof(struct acpi_memory_list)); + if (!cache) { + return (AE_NO_MEMORY); + } + + /* Populate the cache object and return it */ + + ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list)); + cache->list_name = cache_name; + cache->object_size = object_size; + cache->max_depth = max_depth; + + *return_cache = cache; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_purge_cache + * + * PARAMETERS: cache - Handle to cache object + * + * RETURN: Status + * + * DESCRIPTION: Free all objects within the requested cache. + * + ******************************************************************************/ + +acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache) +{ + void *next; + acpi_status status; + + ACPI_FUNCTION_ENTRY(); + + if (!cache) { + return (AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Walk the list of objects in this cache */ + + while (cache->list_head) { + + /* Delete and unlink one cached state object */ + + next = ACPI_GET_DESCRIPTOR_PTR(cache->list_head); + ACPI_FREE(cache->list_head); + + cache->list_head = next; + cache->current_depth--; + } + + (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_delete_cache + * + * PARAMETERS: cache - Handle to cache object + * + * RETURN: Status + * + * DESCRIPTION: Free all objects within the requested cache and delete the + * cache object. + * + ******************************************************************************/ + +acpi_status acpi_os_delete_cache(struct acpi_memory_list * cache) +{ + acpi_status status; + + ACPI_FUNCTION_ENTRY(); + + /* Purge all objects in the cache */ + + status = acpi_os_purge_cache(cache); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Now we can delete the cache object */ + + acpi_os_free(cache); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_release_object + * + * PARAMETERS: cache - Handle to cache object + * object - The object to be released + * + * RETURN: None + * + * DESCRIPTION: Release an object to the specified cache. If cache is full, + * the object is deleted. + * + ******************************************************************************/ + +acpi_status +acpi_os_release_object(struct acpi_memory_list * cache, void *object) +{ + acpi_status status; + + ACPI_FUNCTION_ENTRY(); + + if (!cache || !object) { + return (AE_BAD_PARAMETER); + } + + /* If cache is full, just free this object */ + + if (cache->current_depth >= cache->max_depth) { + ACPI_FREE(object); + ACPI_MEM_TRACKING(cache->total_freed++); + } + + /* Otherwise put this object back into the cache */ + + else { + status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Mark the object as cached */ + + ACPI_MEMSET(object, 0xCA, cache->object_size); + ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_CACHED); + + /* Put the object at the head of the cache list */ + + ACPI_SET_DESCRIPTOR_PTR(object, cache->list_head); + cache->list_head = object; + cache->current_depth++; + + (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_acquire_object + * + * PARAMETERS: cache - Handle to cache object + * + * RETURN: the acquired object. NULL on error + * + * DESCRIPTION: Get an object from the specified cache. If cache is empty, + * the object is allocated. + * + ******************************************************************************/ + +void *acpi_os_acquire_object(struct acpi_memory_list *cache) +{ + acpi_status status; + void *object; + + ACPI_FUNCTION_NAME(os_acquire_object); + + if (!cache) { + return_PTR(NULL); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); + if (ACPI_FAILURE(status)) { + return_PTR(NULL); + } + + ACPI_MEM_TRACKING(cache->requests++); + + /* Check the cache first */ + + if (cache->list_head) { + + /* There is an object available, use it */ + + object = cache->list_head; + cache->list_head = ACPI_GET_DESCRIPTOR_PTR(object); + + cache->current_depth--; + + ACPI_MEM_TRACKING(cache->hits++); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Object %p from %s cache\n", object, + cache->list_name)); + + status = acpi_ut_release_mutex(ACPI_MTX_CACHES); + if (ACPI_FAILURE(status)) { + return_PTR(NULL); + } + + /* Clear (zero) the previously used Object */ + + ACPI_MEMSET(object, 0, cache->object_size); + } else { + /* The cache is empty, create a new object */ + + ACPI_MEM_TRACKING(cache->total_allocated++); + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + if ((cache->total_allocated - cache->total_freed) > + cache->max_occupied) { + cache->max_occupied = + cache->total_allocated - cache->total_freed; + } +#endif + + /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */ + + status = acpi_ut_release_mutex(ACPI_MTX_CACHES); + if (ACPI_FAILURE(status)) { + return_PTR(NULL); + } + + object = ACPI_ALLOCATE_ZEROED(cache->object_size); + if (!object) { + return_PTR(NULL); + } + } + + return_PTR(object); +} +#endif /* ACPI_USE_LOCAL_CACHE */ diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c index 3317c0a406e..270c16464dd 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -178,7 +178,6 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, switch (internal_object->reference.class) { case ACPI_REFCLASS_NAME: - /* * For namepath, return the object handle ("reference") * We are referring to the namespace node @@ -264,7 +263,6 @@ acpi_ut_copy_ielement_to_eelement(u8 object_type, switch (object_type) { case ACPI_COPY_TYPE_SIMPLE: - /* * This is a simple or null object */ @@ -278,7 +276,6 @@ acpi_ut_copy_ielement_to_eelement(u8 object_type, break; case ACPI_COPY_TYPE_PACKAGE: - /* * Build the package object */ @@ -304,6 +301,7 @@ acpi_ut_copy_ielement_to_eelement(u8 object_type, break; default: + return (AE_BAD_PARAMETER); } @@ -317,7 +315,7 @@ acpi_ut_copy_ielement_to_eelement(u8 object_type, * FUNCTION: acpi_ut_copy_ipackage_to_epackage * * PARAMETERS: internal_object - Pointer to the object we are returning - * Buffer - Where the object is returned + * buffer - Where the object is returned * space_used - Where the object length is returned * * RETURN: Status @@ -481,6 +479,7 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, return_ACPI_STATUS(AE_OK); default: + /* All other types are not supported */ ACPI_ERROR((AE_INFO, @@ -536,22 +535,24 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, case ACPI_TYPE_LOCAL_REFERENCE: - /* TBD: should validate incoming handle */ + /* An incoming reference is defined to be a namespace node */ - internal_object->reference.class = ACPI_REFCLASS_NAME; - internal_object->reference.node = + internal_object->reference.class = ACPI_REFCLASS_REFOF; + internal_object->reference.object = external_object->reference.handle; break; default: + /* Other types can't get here */ + break; } *ret_internal_object = internal_object; return_ACPI_STATUS(AE_OK); - error_exit: +error_exit: acpi_ut_remove_reference(internal_object); return_ACPI_STATUS(AE_NO_MEMORY); } @@ -785,7 +786,7 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, status = acpi_os_create_mutex(&dest_desc->mutex.os_mutex); if (ACPI_FAILURE(status)) { - return status; + return (status); } break; @@ -795,12 +796,14 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, &dest_desc->event. os_semaphore); if (ACPI_FAILURE(status)) { - return status; + return (status); } break; default: + /* Nothing to do for other simple objects */ + break; } @@ -868,7 +871,6 @@ acpi_ut_copy_ielement_to_ielement(u8 object_type, break; case ACPI_COPY_TYPE_PACKAGE: - /* * This object is a package - go down another nesting level * Create and build the package object @@ -891,12 +893,13 @@ acpi_ut_copy_ielement_to_ielement(u8 object_type, break; default: + return (AE_BAD_PARAMETER); } return (status); - error_exit: +error_exit: acpi_ut_remove_reference(target_object); return (status); } diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index a0998a88631..21a20ac5b1e 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -1,11 +1,11 @@ /****************************************************************************** * - * Module Name: utdebug - Debug print routines + * Module Name: utdebug - Debug print/trace routines * *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,14 +41,16 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include <linux/export.h> +#define EXPORT_ACPI_INTERFACES + #include <acpi/acpi.h> #include "accommon.h" #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utdebug") + #ifdef ACPI_DEBUG_OUTPUT -static acpi_thread_id acpi_gbl_prev_thread_id; +static acpi_thread_id acpi_gbl_prev_thread_id = (acpi_thread_id) 0xFFFFFFFF; static char *acpi_gbl_fn_entry_str = "----Entry"; static char *acpi_gbl_fn_exit_str = "----Exit-"; @@ -109,7 +111,7 @@ void acpi_ut_track_stack_ptr(void) * RETURN: Updated pointer to the function name * * DESCRIPTION: Remove the "Acpi" prefix from the function name, if present. - * This allows compiler macros such as __func__ to be used + * This allows compiler macros such as __FUNCTION__ to be used * with no change to the debug output. * ******************************************************************************/ @@ -145,7 +147,7 @@ static const char *acpi_ut_trim_function_name(const char *function_name) * function_name - Caller's procedure name * module_name - Caller's module name * component_id - Caller's component ID - * Format - Printf format field + * format - Printf format field * ... - Optional printf arguments * * RETURN: None @@ -165,11 +167,9 @@ acpi_debug_print(u32 requested_debug_level, acpi_thread_id thread_id; va_list args; - /* - * Stay silent if the debug level or component ID is disabled - */ - if (!(requested_debug_level & acpi_dbg_level) || - !(component_id & acpi_dbg_layer)) { + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(requested_debug_level, component_id)) { return; } @@ -185,21 +185,30 @@ acpi_debug_print(u32 requested_debug_level, } acpi_gbl_prev_thread_id = thread_id; + acpi_gbl_nesting_level = 0; } /* * Display the module name, current line number, thread ID (if requested), * current procedure nesting level, and the current procedure name */ - acpi_os_printf("%8s-%04ld ", module_name, line_number); + acpi_os_printf("%9s-%04ld ", module_name, line_number); +#ifdef ACPI_APPLICATION + /* + * For acpi_exec/iASL only, emit the thread ID and nesting level. + * Note: nesting level is really only useful during a single-thread + * execution. Otherwise, multiple threads will keep resetting the + * level. + */ if (ACPI_LV_THREADS & acpi_dbg_level) { acpi_os_printf("[%u] ", (u32)thread_id); } - acpi_os_printf("[%02ld] %-22.22s: ", - acpi_gbl_nesting_level, - acpi_ut_trim_function_name(function_name)); + acpi_os_printf("[%02ld] ", acpi_gbl_nesting_level); +#endif + + acpi_os_printf("%-22.22s: ", acpi_ut_trim_function_name(function_name)); va_start(args, format); acpi_os_vprintf(format, args); @@ -217,12 +226,12 @@ ACPI_EXPORT_SYMBOL(acpi_debug_print) * function_name - Caller's procedure name * module_name - Caller's module name * component_id - Caller's component ID - * Format - Printf format field + * format - Printf format field * ... - Optional printf arguments * * RETURN: None * - * DESCRIPTION: Print message with no headers. Has same interface as + * DESCRIPTION: Print message with no headers. Has same interface as * debug_print so that the same macros can be used. * ******************************************************************************/ @@ -235,8 +244,9 @@ acpi_debug_print_raw(u32 requested_debug_level, { va_list args; - if (!(requested_debug_level & acpi_dbg_level) || - !(component_id & acpi_dbg_layer)) { + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(requested_debug_level, component_id)) { return; } @@ -258,7 +268,7 @@ ACPI_EXPORT_SYMBOL(acpi_debug_print_raw) * * RETURN: None * - * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is * set in debug_level * ******************************************************************************/ @@ -271,9 +281,13 @@ acpi_ut_trace(u32 line_number, acpi_gbl_nesting_level++; acpi_ut_track_stack_ptr(); - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s\n", acpi_gbl_fn_entry_str); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s\n", acpi_gbl_fn_entry_str); + } } ACPI_EXPORT_SYMBOL(acpi_ut_trace) @@ -286,11 +300,11 @@ ACPI_EXPORT_SYMBOL(acpi_ut_trace) * function_name - Caller's procedure name * module_name - Caller's module name * component_id - Caller's component ID - * Pointer - Pointer to display + * pointer - Pointer to display * * RETURN: None * - * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is * set in debug_level * ******************************************************************************/ @@ -299,12 +313,18 @@ acpi_ut_trace_ptr(u32 line_number, const char *function_name, const char *module_name, u32 component_id, void *pointer) { + acpi_gbl_nesting_level++; acpi_ut_track_stack_ptr(); - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %p\n", acpi_gbl_fn_entry_str, pointer); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s %p\n", acpi_gbl_fn_entry_str, + pointer); + } } /******************************************************************************* @@ -315,11 +335,11 @@ acpi_ut_trace_ptr(u32 line_number, * function_name - Caller's procedure name * module_name - Caller's module name * component_id - Caller's component ID - * String - Additional string to display + * string - Additional string to display * * RETURN: None * - * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is * set in debug_level * ******************************************************************************/ @@ -333,9 +353,14 @@ acpi_ut_trace_str(u32 line_number, acpi_gbl_nesting_level++; acpi_ut_track_stack_ptr(); - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %s\n", acpi_gbl_fn_entry_str, string); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s %s\n", acpi_gbl_fn_entry_str, + string); + } } /******************************************************************************* @@ -346,11 +371,11 @@ acpi_ut_trace_str(u32 line_number, * function_name - Caller's procedure name * module_name - Caller's module name * component_id - Caller's component ID - * Integer - Integer to display + * integer - Integer to display * * RETURN: None * - * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is * set in debug_level * ******************************************************************************/ @@ -364,9 +389,14 @@ acpi_ut_trace_u32(u32 line_number, acpi_gbl_nesting_level++; acpi_ut_track_stack_ptr(); - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %08X\n", acpi_gbl_fn_entry_str, integer); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s %08X\n", + acpi_gbl_fn_entry_str, integer); + } } /******************************************************************************* @@ -380,7 +410,7 @@ acpi_ut_trace_u32(u32 line_number, * * RETURN: None * - * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is * set in debug_level * ******************************************************************************/ @@ -391,11 +421,17 @@ acpi_ut_exit(u32 line_number, const char *module_name, u32 component_id) { - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s\n", acpi_gbl_fn_exit_str); + /* Check if enabled up-front for performance */ - acpi_gbl_nesting_level--; + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s\n", acpi_gbl_fn_exit_str); + } + + if (acpi_gbl_nesting_level) { + acpi_gbl_nesting_level--; + } } ACPI_EXPORT_SYMBOL(acpi_ut_exit) @@ -408,11 +444,11 @@ ACPI_EXPORT_SYMBOL(acpi_ut_exit) * function_name - Caller's procedure name * module_name - Caller's module name * component_id - Caller's component ID - * Status - Exit status code + * status - Exit status code * * RETURN: None * - * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is * set in debug_level. Prints exit status also. * ******************************************************************************/ @@ -423,20 +459,28 @@ acpi_ut_status_exit(u32 line_number, u32 component_id, acpi_status status) { - if (ACPI_SUCCESS(status)) { - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, - component_id, "%s %s\n", acpi_gbl_fn_exit_str, - acpi_format_exception(status)); - } else { - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, - component_id, "%s ****Exception****: %s\n", - acpi_gbl_fn_exit_str, - acpi_format_exception(status)); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + if (ACPI_SUCCESS(status)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, + module_name, component_id, "%s %s\n", + acpi_gbl_fn_exit_str, + acpi_format_exception(status)); + } else { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, + module_name, component_id, + "%s ****Exception****: %s\n", + acpi_gbl_fn_exit_str, + acpi_format_exception(status)); + } } - acpi_gbl_nesting_level--; + if (acpi_gbl_nesting_level) { + acpi_gbl_nesting_level--; + } } ACPI_EXPORT_SYMBOL(acpi_ut_status_exit) @@ -449,11 +493,11 @@ ACPI_EXPORT_SYMBOL(acpi_ut_status_exit) * function_name - Caller's procedure name * module_name - Caller's module name * component_id - Caller's component ID - * Value - Value to be printed with exit msg + * value - Value to be printed with exit msg * * RETURN: None * - * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is * set in debug_level. Prints exit value also. * ******************************************************************************/ @@ -463,12 +507,19 @@ acpi_ut_value_exit(u32 line_number, const char *module_name, u32 component_id, u64 value) { - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %8.8X%8.8X\n", acpi_gbl_fn_exit_str, - ACPI_FORMAT_UINT64(value)); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s %8.8X%8.8X\n", + acpi_gbl_fn_exit_str, + ACPI_FORMAT_UINT64(value)); + } - acpi_gbl_nesting_level--; + if (acpi_gbl_nesting_level) { + acpi_gbl_nesting_level--; + } } ACPI_EXPORT_SYMBOL(acpi_ut_value_exit) @@ -481,11 +532,11 @@ ACPI_EXPORT_SYMBOL(acpi_ut_value_exit) * function_name - Caller's procedure name * module_name - Caller's module name * component_id - Caller's component ID - * Ptr - Pointer to display + * ptr - Pointer to display * * RETURN: None * - * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is * set in debug_level. Prints exit value also. * ******************************************************************************/ @@ -495,156 +546,18 @@ acpi_ut_ptr_exit(u32 line_number, const char *module_name, u32 component_id, u8 *ptr) { - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %p\n", acpi_gbl_fn_exit_str, ptr); - - acpi_gbl_nesting_level--; -} + /* Check if enabled up-front for performance */ -#endif - -/******************************************************************************* - * - * FUNCTION: acpi_ut_dump_buffer - * - * PARAMETERS: Buffer - Buffer to dump - * Count - Amount to dump, in bytes - * Display - BYTE, WORD, DWORD, or QWORD display - * component_iD - Caller's component ID - * - * RETURN: None - * - * DESCRIPTION: Generic dump buffer in both hex and ascii. - * - ******************************************************************************/ - -void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display) -{ - u32 i = 0; - u32 j; - u32 temp32; - u8 buf_char; - - if (!buffer) { - acpi_os_printf("Null Buffer Pointer in DumpBuffer!\n"); - return; - } - - if ((count < 4) || (count & 0x01)) { - display = DB_BYTE_DISPLAY; + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s %p\n", acpi_gbl_fn_exit_str, + ptr); } - /* Nasty little dump buffer routine! */ - - while (i < count) { - - /* Print current offset */ - - acpi_os_printf("%6.4X: ", i); - - /* Print 16 hex chars */ - - for (j = 0; j < 16;) { - if (i + j >= count) { - - /* Dump fill spaces */ - - acpi_os_printf("%*s", ((display * 2) + 1), " "); - j += display; - continue; - } - - switch (display) { - case DB_BYTE_DISPLAY: - default: /* Default is BYTE display */ - - acpi_os_printf("%02X ", - buffer[(acpi_size) i + j]); - break; - - case DB_WORD_DISPLAY: - - ACPI_MOVE_16_TO_32(&temp32, - &buffer[(acpi_size) i + j]); - acpi_os_printf("%04X ", temp32); - break; - - case DB_DWORD_DISPLAY: - - ACPI_MOVE_32_TO_32(&temp32, - &buffer[(acpi_size) i + j]); - acpi_os_printf("%08X ", temp32); - break; - - case DB_QWORD_DISPLAY: - - ACPI_MOVE_32_TO_32(&temp32, - &buffer[(acpi_size) i + j]); - acpi_os_printf("%08X", temp32); - - ACPI_MOVE_32_TO_32(&temp32, - &buffer[(acpi_size) i + j + - 4]); - acpi_os_printf("%08X ", temp32); - break; - } - - j += display; - } - - /* - * Print the ASCII equivalent characters but watch out for the bad - * unprintable ones (printable chars are 0x20 through 0x7E) - */ - acpi_os_printf(" "); - for (j = 0; j < 16; j++) { - if (i + j >= count) { - acpi_os_printf("\n"); - return; - } - - buf_char = buffer[(acpi_size) i + j]; - if (ACPI_IS_PRINT(buf_char)) { - acpi_os_printf("%c", buf_char); - } else { - acpi_os_printf("."); - } - } - - /* Done with that line. */ - - acpi_os_printf("\n"); - i += 16; + if (acpi_gbl_nesting_level) { + acpi_gbl_nesting_level--; } - - return; } -/******************************************************************************* - * - * FUNCTION: acpi_ut_dump_buffer - * - * PARAMETERS: Buffer - Buffer to dump - * Count - Amount to dump, in bytes - * Display - BYTE, WORD, DWORD, or QWORD display - * component_iD - Caller's component ID - * - * RETURN: None - * - * DESCRIPTION: Generic dump buffer in both hex and ascii. - * - ******************************************************************************/ - -void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id) -{ - - /* Only dump the buffer if tracing is enabled */ - - if (!((ACPI_LV_TABLES & acpi_dbg_level) && - (component_id & acpi_dbg_layer))) { - return; - } - - acpi_ut_dump_buffer2(buffer, count, display); -} +#endif diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c index d42ede5260c..90ec37c473c 100644 --- a/drivers/acpi/acpica/utdecode.c +++ b/drivers/acpi/acpica/utdecode.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,7 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include <linux/export.h> #include <acpi/acpi.h> #include "accommon.h" #include "acnamesp.h" @@ -49,41 +48,6 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utdecode") -/******************************************************************************* - * - * FUNCTION: acpi_format_exception - * - * PARAMETERS: Status - The acpi_status code to be formatted - * - * RETURN: A string containing the exception text. A valid pointer is - * always returned. - * - * DESCRIPTION: This function translates an ACPI exception into an ASCII string - * It is here instead of utxface.c so it is always present. - * - ******************************************************************************/ -const char *acpi_format_exception(acpi_status status) -{ - const char *exception = NULL; - - ACPI_FUNCTION_ENTRY(); - - exception = acpi_ut_validate_exception(status); - if (!exception) { - - /* Exception code was not recognized */ - - ACPI_ERROR((AE_INFO, - "Unknown exception code: 0x%8.8X", status)); - - exception = "UNKNOWN_STATUS_CODE"; - } - - return (ACPI_CAST_PTR(const char, exception)); -} - -ACPI_EXPORT_SYMBOL(acpi_format_exception) - /* * Properties of the ACPI Object Types, both internal and external. * The table is indexed by values of acpi_object_type @@ -126,8 +90,8 @@ const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES] = { * * FUNCTION: acpi_ut_hex_to_ascii_char * - * PARAMETERS: Integer - Contains the hex digit - * Position - bit position of the digit within the + * PARAMETERS: integer - Contains the hex digit + * position - bit position of the digit within the * integer (multiple of 4) * * RETURN: The converted Ascii character @@ -164,16 +128,17 @@ char acpi_ut_hex_to_ascii_char(u64 integer, u32 position) /* Region type decoding */ const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = { - "SystemMemory", - "SystemIO", - "PCI_Config", - "EmbeddedControl", - "SMBus", - "SystemCMOS", - "PCIBARTarget", - "IPMI", - "GeneralPurposeIo", - "GenericSerialBus" + "SystemMemory", /* 0x00 */ + "SystemIO", /* 0x01 */ + "PCI_Config", /* 0x02 */ + "EmbeddedControl", /* 0x03 */ + "SMBus", /* 0x04 */ + "SystemCMOS", /* 0x05 */ + "PCIBARTarget", /* 0x06 */ + "IPMI", /* 0x07 */ + "GeneralPurposeIo", /* 0x08 */ + "GenericSerialBus", /* 0x09 */ + "PCC" /* 0x0A */ }; char *acpi_ut_get_region_name(u8 space_id) @@ -228,7 +193,7 @@ char *acpi_ut_get_event_name(u32 event_id) * * FUNCTION: acpi_ut_get_type_name * - * PARAMETERS: Type - An ACPI object type + * PARAMETERS: type - An ACPI object type * * RETURN: Decoded ACPI object type name * @@ -306,7 +271,7 @@ char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc) * * FUNCTION: acpi_ut_get_node_name * - * PARAMETERS: Object - A namespace node + * PARAMETERS: object - A namespace node * * RETURN: ASCII name of the node * @@ -351,7 +316,7 @@ char *acpi_ut_get_node_name(void *object) * * FUNCTION: acpi_ut_get_descriptor_name * - * PARAMETERS: Object - An ACPI object + * PARAMETERS: object - An ACPI object * * RETURN: Decoded name of the descriptor type * @@ -401,7 +366,7 @@ char *acpi_ut_get_descriptor_name(void *object) * * FUNCTION: acpi_ut_get_reference_name * - * PARAMETERS: Object - An ACPI reference object + * PARAMETERS: object - An ACPI reference object * * RETURN: Decoded name of the type of reference * @@ -497,32 +462,86 @@ char *acpi_ut_get_mutex_name(u32 mutex_id) /* Names for Notify() values, used for debug output */ -static const char *acpi_gbl_notify_value_names[] = { - "Bus Check", - "Device Check", - "Device Wake", - "Eject Request", - "Device Check Light", - "Frequency Mismatch", - "Bus Mode Mismatch", - "Power Fault", - "Capabilities Check", - "Device PLD Check", - "Reserved", - "System Locality Update" +static const char *acpi_gbl_generic_notify[ACPI_NOTIFY_MAX + 1] = { + /* 00 */ "Bus Check", + /* 01 */ "Device Check", + /* 02 */ "Device Wake", + /* 03 */ "Eject Request", + /* 04 */ "Device Check Light", + /* 05 */ "Frequency Mismatch", + /* 06 */ "Bus Mode Mismatch", + /* 07 */ "Power Fault", + /* 08 */ "Capabilities Check", + /* 09 */ "Device PLD Check", + /* 0A */ "Reserved", + /* 0B */ "System Locality Update", + /* 0C */ "Shutdown Request" +}; + +static const char *acpi_gbl_device_notify[4] = { + /* 80 */ "Status Change", + /* 81 */ "Information Change", + /* 82 */ "Device-Specific Change", + /* 83 */ "Device-Specific Change" +}; + +static const char *acpi_gbl_processor_notify[4] = { + /* 80 */ "Performance Capability Change", + /* 81 */ "C-State Change", + /* 82 */ "Throttling Capability Change", + /* 83 */ "Device-Specific Change" +}; + +static const char *acpi_gbl_thermal_notify[4] = { + /* 80 */ "Thermal Status Change", + /* 81 */ "Thermal Trip Point Change", + /* 82 */ "Thermal Device List Change", + /* 83 */ "Thermal Relationship Change" }; -const char *acpi_ut_get_notify_name(u32 notify_value) +const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type) { + /* 00 - 0C are common to all object types */ + if (notify_value <= ACPI_NOTIFY_MAX) { - return (acpi_gbl_notify_value_names[notify_value]); - } else if (notify_value <= ACPI_MAX_SYS_NOTIFY) { + return (acpi_gbl_generic_notify[notify_value]); + } + + /* 0D - 7F are reserved */ + + if (notify_value <= ACPI_MAX_SYS_NOTIFY) { return ("Reserved"); - } else { /* Greater or equal to 0x80 */ + } - return ("**Device Specific**"); + /* 80 - 83 are per-object-type */ + + if (notify_value <= 0x83) { + switch (type) { + case ACPI_TYPE_ANY: + case ACPI_TYPE_DEVICE: + return (acpi_gbl_device_notify[notify_value - 0x80]); + + case ACPI_TYPE_PROCESSOR: + return (acpi_gbl_processor_notify[notify_value - 0x80]); + + case ACPI_TYPE_THERMAL: + return (acpi_gbl_thermal_notify[notify_value - 0x80]); + + default: + return ("Target object type does not support notifies"); + } } + + /* 84 - BF are device-specific */ + + if (notify_value <= ACPI_MAX_DEVICE_SPECIFIC_NOTIFY) { + return ("Device-Specific"); + } + + /* C0 and above are hardware-specific */ + + return ("Hardware-Specific"); } #endif @@ -530,7 +549,7 @@ const char *acpi_ut_get_notify_name(u32 notify_value) * * FUNCTION: acpi_ut_valid_object_type * - * PARAMETERS: Type - Object type to be validated + * PARAMETERS: type - Object type to be validated * * RETURN: TRUE if valid object type, FALSE otherwise * diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c index 2a6c3e18369..a3516de213f 100644 --- a/drivers/acpi/acpica/utdelete.c +++ b/drivers/acpi/acpica/utdelete.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -60,7 +60,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action); * * FUNCTION: acpi_ut_delete_internal_obj * - * PARAMETERS: Object - Object to be deleted + * PARAMETERS: object - Object to be deleted * * RETURN: None * @@ -75,6 +75,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) union acpi_operand_object *handler_desc; union acpi_operand_object *second_desc; union acpi_operand_object *next_desc; + union acpi_operand_object *start_desc; union acpi_operand_object **last_obj_ptr; ACPI_FUNCTION_TRACE_PTR(ut_delete_internal_obj, object); @@ -152,7 +153,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_THERMAL: - /* Walk the notify handler list for this object */ + /* Walk the address handler list for this object */ handler_desc = object->common_notify.handler; while (handler_desc) { @@ -235,10 +236,11 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) if (handler_desc) { next_desc = handler_desc->address_space.region_list; + start_desc = next_desc; last_obj_ptr = &handler_desc->address_space.region_list; - /* Remove the region object from the handler's list */ + /* Remove the region object from the handler list */ while (next_desc) { if (next_desc == object) { @@ -247,10 +249,19 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) break; } - /* Walk the linked list of handler */ + /* Walk the linked list of handlers */ last_obj_ptr = &next_desc->region.next; next_desc = next_desc->region.next; + + /* Prevent infinite loop if list is corrupted */ + + if (next_desc == start_desc) { + ACPI_ERROR((AE_INFO, + "Circular region list in address handler object %p", + handler_desc)); + return_VOID; + } } if (handler_desc->address_space.handler_flags & @@ -303,6 +314,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) break; default: + break; } @@ -340,7 +352,7 @@ void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list) { union acpi_operand_object **internal_obj; - ACPI_FUNCTION_TRACE(ut_delete_internal_object_list); + ACPI_FUNCTION_ENTRY(); /* Walk the null-terminated internal list */ @@ -351,27 +363,28 @@ void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list) /* Free the combined parameter pointer list and object array */ ACPI_FREE(obj_list); - return_VOID; + return; } /******************************************************************************* * * FUNCTION: acpi_ut_update_ref_count * - * PARAMETERS: Object - Object whose ref count is to be updated - * Action - What to do + * PARAMETERS: object - Object whose ref count is to be updated + * action - What to do (REF_INCREMENT or REF_DECREMENT) * - * RETURN: New ref count + * RETURN: None. Sets new reference count within the object * - * DESCRIPTION: Modify the ref count and return it. + * DESCRIPTION: Modify the reference count for an internal acpi object * ******************************************************************************/ static void acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) { - u16 count; - u16 new_count; + u16 original_count; + u16 new_count = 0; + acpi_cpu_flags lock_flags; ACPI_FUNCTION_NAME(ut_update_ref_count); @@ -379,76 +392,79 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) return; } - count = object->common.reference_count; - new_count = count; - /* - * Perform the reference count action (increment, decrement, force delete) + * Always get the reference count lock. Note: Interpreter and/or + * Namespace is not always locked when this function is called. */ + lock_flags = acpi_os_acquire_lock(acpi_gbl_reference_count_lock); + original_count = object->common.reference_count; + + /* Perform the reference count action (increment, decrement) */ + switch (action) { case REF_INCREMENT: - new_count++; + new_count = original_count + 1; object->common.reference_count = new_count; + acpi_os_release_lock(acpi_gbl_reference_count_lock, lock_flags); + + /* The current reference count should never be zero here */ + + if (!original_count) { + ACPI_WARNING((AE_INFO, + "Obj %p, Reference Count was zero before increment\n", + object)); + } ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "Obj %p Refs=%X, [Incremented]\n", - object, new_count)); + "Obj %p Type %.2X Refs %.2X [Incremented]\n", + object, object->common.type, new_count)); break; case REF_DECREMENT: - if (count < 1) { - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "Obj %p Refs=%X, can't decrement! (Set to 0)\n", - object, new_count)); - - new_count = 0; - } else { - new_count--; + /* The current reference count must be non-zero */ - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "Obj %p Refs=%X, [Decremented]\n", - object, new_count)); + if (original_count) { + new_count = original_count - 1; + object->common.reference_count = new_count; } - if (object->common.type == ACPI_TYPE_METHOD) { - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "Method Obj %p Refs=%X, [Decremented]\n", - object, new_count)); - } + acpi_os_release_lock(acpi_gbl_reference_count_lock, lock_flags); - object->common.reference_count = new_count; - if (new_count == 0) { - acpi_ut_delete_internal_obj(object); + if (!original_count) { + ACPI_WARNING((AE_INFO, + "Obj %p, Reference Count is already zero, cannot decrement\n", + object)); } - break; - - case REF_FORCE_DELETE: ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, - "Obj %p Refs=%X, Force delete! (Set to 0)\n", - object, count)); + "Obj %p Type %.2X Refs %.2X [Decremented]\n", + object, object->common.type, new_count)); - new_count = 0; - object->common.reference_count = new_count; - acpi_ut_delete_internal_obj(object); + /* Actually delete the object on a reference count of zero */ + + if (new_count == 0) { + acpi_ut_delete_internal_obj(object); + } break; default: - ACPI_ERROR((AE_INFO, "Unknown action (0x%X)", action)); - break; + acpi_os_release_lock(acpi_gbl_reference_count_lock, lock_flags); + ACPI_ERROR((AE_INFO, "Unknown Reference Count action (0x%X)", + action)); + return; } /* * Sanity check the reference count, for debug purposes only. * (A deleted object will have a huge reference count) */ - if (count > ACPI_MAX_REFERENCE_COUNT) { + if (new_count > ACPI_MAX_REFERENCE_COUNT) { ACPI_WARNING((AE_INFO, - "Large Reference Count (0x%X) in object %p", - count, object)); + "Large Reference Count (0x%X) in object %p, Type=0x%.2X", + new_count, object, object->common.type)); } } @@ -456,10 +472,9 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) * * FUNCTION: acpi_ut_update_object_reference * - * PARAMETERS: Object - Increment ref count for this object + * PARAMETERS: object - Increment ref count for this object * and all sub-objects - * Action - Either REF_INCREMENT or REF_DECREMENT or - * REF_FORCE_DELETE + * action - Either REF_INCREMENT or REF_DECREMENT * * RETURN: Status * @@ -480,10 +495,11 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) acpi_status status = AE_OK; union acpi_generic_state *state_list = NULL; union acpi_operand_object *next_object = NULL; + union acpi_operand_object *prev_object; union acpi_generic_state *state; u32 i; - ACPI_FUNCTION_TRACE_PTR(ut_update_object_reference, object); + ACPI_FUNCTION_NAME(ut_update_object_reference); while (object) { @@ -492,7 +508,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) if (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) { ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Object %p is NS handle\n", object)); - return_ACPI_STATUS(AE_OK); + return (AE_OK); } /* @@ -504,13 +520,21 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_POWER: case ACPI_TYPE_THERMAL: - - /* Update the notify objects for these types (if present) */ - - acpi_ut_update_ref_count(object->common_notify. - system_notify, action); - acpi_ut_update_ref_count(object->common_notify. - device_notify, action); + /* + * Update the notify objects for these types (if present) + * Two lists, system and device notify handlers. + */ + for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { + prev_object = + object->common_notify.notify_list[i]; + while (prev_object) { + next_object = + prev_object->notify.next[i]; + acpi_ut_update_ref_count(prev_object, + action); + prev_object = next_object; + } + } break; case ACPI_TYPE_PACKAGE: @@ -520,18 +544,42 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) */ for (i = 0; i < object->package.count; i++) { /* - * Push each element onto the stack for later processing. - * Note: There can be null elements within the package, - * these are simply ignored + * Null package elements are legal and can be simply + * ignored. */ - status = - acpi_ut_create_update_state_and_push - (object->package.elements[i], action, - &state_list); - if (ACPI_FAILURE(status)) { - goto error_exit; + next_object = object->package.elements[i]; + if (!next_object) { + continue; + } + + switch (next_object->common.type) { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + /* + * For these very simple sub-objects, we can just + * update the reference count here and continue. + * Greatly increases performance of this operation. + */ + acpi_ut_update_ref_count(next_object, + action); + break; + + default: + /* + * For complex sub-objects, push them onto the stack + * for later processing (this eliminates recursion.) + */ + status = + acpi_ut_create_update_state_and_push + (next_object, action, &state_list); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + break; } } + next_object = NULL; break; case ACPI_TYPE_BUFFER_FIELD: @@ -586,6 +634,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) case ACPI_TYPE_REGION: default: + break; /* No subobjects for all other types */ } @@ -609,9 +658,9 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) } } - return_ACPI_STATUS(AE_OK); + return (AE_OK); - error_exit: +error_exit: ACPI_EXCEPTION((AE_INFO, status, "Could not update object reference count")); @@ -623,14 +672,14 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) acpi_ut_delete_generic_state(state); } - return_ACPI_STATUS(status); + return (status); } /******************************************************************************* * * FUNCTION: acpi_ut_add_reference * - * PARAMETERS: Object - Object whose reference count is to be + * PARAMETERS: object - Object whose reference count is to be * incremented * * RETURN: None @@ -642,12 +691,12 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) void acpi_ut_add_reference(union acpi_operand_object *object) { - ACPI_FUNCTION_TRACE_PTR(ut_add_reference, object); + ACPI_FUNCTION_NAME(ut_add_reference); /* Ensure that we have a valid object */ if (!acpi_ut_valid_internal_object(object)) { - return_VOID; + return; } ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, @@ -657,14 +706,14 @@ void acpi_ut_add_reference(union acpi_operand_object *object) /* Increment the reference count */ (void)acpi_ut_update_object_reference(object, REF_INCREMENT); - return_VOID; + return; } /******************************************************************************* * * FUNCTION: acpi_ut_remove_reference * - * PARAMETERS: Object - Object whose ref count will be decremented + * PARAMETERS: object - Object whose ref count will be decremented * * RETURN: None * @@ -675,22 +724,21 @@ void acpi_ut_add_reference(union acpi_operand_object *object) void acpi_ut_remove_reference(union acpi_operand_object *object) { - ACPI_FUNCTION_TRACE_PTR(ut_remove_reference, object); + ACPI_FUNCTION_NAME(ut_remove_reference); /* * Allow a NULL pointer to be passed in, just ignore it. This saves * each caller from having to check. Also, ignore NS nodes. - * */ if (!object || (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED)) { - return_VOID; + return; } /* Ensure that we have a valid object */ if (!acpi_ut_valid_internal_object(object)) { - return_VOID; + return; } ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, @@ -703,5 +751,5 @@ void acpi_ut_remove_reference(union acpi_operand_object *object) * of all subobjects!) */ (void)acpi_ut_update_object_reference(object, REF_DECREMENT); - return_VOID; + return; } diff --git a/drivers/acpi/acpica/uterror.c b/drivers/acpi/acpica/uterror.c new file mode 100644 index 00000000000..8e544d4688c --- /dev/null +++ b/drivers/acpi/acpica/uterror.c @@ -0,0 +1,289 @@ +/******************************************************************************* + * + * Module Name: uterror - Various internal error/warning output functions + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("uterror") + +/* + * This module contains internal error functions that may + * be configured out. + */ +#if !defined (ACPI_NO_ERROR_MESSAGES) +/******************************************************************************* + * + * FUNCTION: acpi_ut_predefined_warning + * + * PARAMETERS: module_name - Caller's module name (for error output) + * line_number - Caller's line number (for error output) + * pathname - Full pathname to the node + * node_flags - From Namespace node for the method/object + * format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Warnings for the predefined validation module. Messages are + * only emitted the first time a problem with a particular + * method/object is detected. This prevents a flood of error + * messages for methods that are repeatedly evaluated. + * + ******************************************************************************/ +void ACPI_INTERNAL_VAR_XFACE +acpi_ut_predefined_warning(const char *module_name, + u32 line_number, + char *pathname, + u8 node_flags, const char *format, ...) +{ + va_list arg_list; + + /* + * Warning messages for this method/object will be disabled after the + * first time a validation fails or an object is successfully repaired. + */ + if (node_flags & ANOBJ_EVALUATED) { + return; + } + + acpi_os_printf(ACPI_MSG_WARNING "%s: ", pathname); + + va_start(arg_list, format); + acpi_os_vprintf(format, arg_list); + ACPI_MSG_SUFFIX; + va_end(arg_list); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_predefined_info + * + * PARAMETERS: module_name - Caller's module name (for error output) + * line_number - Caller's line number (for error output) + * pathname - Full pathname to the node + * node_flags - From Namespace node for the method/object + * format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Info messages for the predefined validation module. Messages + * are only emitted the first time a problem with a particular + * method/object is detected. This prevents a flood of + * messages for methods that are repeatedly evaluated. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +acpi_ut_predefined_info(const char *module_name, + u32 line_number, + char *pathname, u8 node_flags, const char *format, ...) +{ + va_list arg_list; + + /* + * Warning messages for this method/object will be disabled after the + * first time a validation fails or an object is successfully repaired. + */ + if (node_flags & ANOBJ_EVALUATED) { + return; + } + + acpi_os_printf(ACPI_MSG_INFO "%s: ", pathname); + + va_start(arg_list, format); + acpi_os_vprintf(format, arg_list); + ACPI_MSG_SUFFIX; + va_end(arg_list); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_predefined_bios_error + * + * PARAMETERS: module_name - Caller's module name (for error output) + * line_number - Caller's line number (for error output) + * pathname - Full pathname to the node + * node_flags - From Namespace node for the method/object + * format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: BIOS error message for predefined names. Messages + * are only emitted the first time a problem with a particular + * method/object is detected. This prevents a flood of + * messages for methods that are repeatedly evaluated. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +acpi_ut_predefined_bios_error(const char *module_name, + u32 line_number, + char *pathname, + u8 node_flags, const char *format, ...) +{ + va_list arg_list; + + /* + * Warning messages for this method/object will be disabled after the + * first time a validation fails or an object is successfully repaired. + */ + if (node_flags & ANOBJ_EVALUATED) { + return; + } + + acpi_os_printf(ACPI_MSG_BIOS_ERROR "%s: ", pathname); + + va_start(arg_list, format); + acpi_os_vprintf(format, arg_list); + ACPI_MSG_SUFFIX; + va_end(arg_list); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_namespace_error + * + * PARAMETERS: module_name - Caller's module name (for error output) + * line_number - Caller's line number (for error output) + * internal_name - Name or path of the namespace node + * lookup_status - Exception code from NS lookup + * + * RETURN: None + * + * DESCRIPTION: Print error message with the full pathname for the NS node. + * + ******************************************************************************/ + +void +acpi_ut_namespace_error(const char *module_name, + u32 line_number, + const char *internal_name, acpi_status lookup_status) +{ + acpi_status status; + u32 bad_name; + char *name = NULL; + + ACPI_MSG_REDIRECT_BEGIN; + acpi_os_printf(ACPI_MSG_ERROR); + + if (lookup_status == AE_BAD_CHARACTER) { + + /* There is a non-ascii character in the name */ + + ACPI_MOVE_32_TO_32(&bad_name, + ACPI_CAST_PTR(u32, internal_name)); + acpi_os_printf("[0x%.8X] (NON-ASCII)", bad_name); + } else { + /* Convert path to external format */ + + status = acpi_ns_externalize_name(ACPI_UINT32_MAX, + internal_name, NULL, &name); + + /* Print target name */ + + if (ACPI_SUCCESS(status)) { + acpi_os_printf("[%s]", name); + } else { + acpi_os_printf("[COULD NOT EXTERNALIZE NAME]"); + } + + if (name) { + ACPI_FREE(name); + } + } + + acpi_os_printf(" Namespace lookup failure, %s", + acpi_format_exception(lookup_status)); + + ACPI_MSG_SUFFIX; + ACPI_MSG_REDIRECT_END; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_method_error + * + * PARAMETERS: module_name - Caller's module name (for error output) + * line_number - Caller's line number (for error output) + * message - Error message to use on failure + * prefix_node - Prefix relative to the path + * path - Path to the node (optional) + * method_status - Execution status + * + * RETURN: None + * + * DESCRIPTION: Print error message with the full pathname for the method. + * + ******************************************************************************/ + +void +acpi_ut_method_error(const char *module_name, + u32 line_number, + const char *message, + struct acpi_namespace_node *prefix_node, + const char *path, acpi_status method_status) +{ + acpi_status status; + struct acpi_namespace_node *node = prefix_node; + + ACPI_MSG_REDIRECT_BEGIN; + acpi_os_printf(ACPI_MSG_ERROR); + + if (path) { + status = + acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH, + &node); + if (ACPI_FAILURE(status)) { + acpi_os_printf("[Could not get node by pathname]"); + } + } + + acpi_ns_print_node_pathname(node, message); + acpi_os_printf(", %s", acpi_format_exception(method_status)); + + ACPI_MSG_SUFFIX; + ACPI_MSG_REDIRECT_END; +} + +#endif /* ACPI_NO_ERROR_MESSAGES */ diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index 479f32b3341..8fed1482d22 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,7 +53,7 @@ ACPI_MODULE_NAME("uteval") * FUNCTION: acpi_ut_evaluate_object * * PARAMETERS: prefix_node - Starting node - * Path - Path to object from starting node + * path - Path to object from starting node * expected_return_types - Bitmap of allowed return types * return_desc - Where a return value is stored * @@ -87,7 +87,7 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, } info->prefix_node = prefix_node; - info->pathname = path; + info->relative_pathname = path; /* Evaluate the object/method */ @@ -123,22 +123,27 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, switch ((info->return_object)->common.type) { case ACPI_TYPE_INTEGER: + return_btype = ACPI_BTYPE_INTEGER; break; case ACPI_TYPE_BUFFER: + return_btype = ACPI_BTYPE_BUFFER; break; case ACPI_TYPE_STRING: + return_btype = ACPI_BTYPE_STRING; break; case ACPI_TYPE_PACKAGE: + return_btype = ACPI_BTYPE_PACKAGE; break; default: + return_btype = 0; break; } @@ -176,7 +181,7 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, *return_desc = info->return_object; - cleanup: +cleanup: ACPI_FREE(info); return_ACPI_STATUS(status); } @@ -187,7 +192,7 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, * * PARAMETERS: object_name - Object name to be evaluated * device_node - Node for the device - * Value - Where the value is returned + * value - Where the value is returned * * RETURN: Status * @@ -229,12 +234,13 @@ acpi_ut_evaluate_numeric_object(char *object_name, * FUNCTION: acpi_ut_execute_STA * * PARAMETERS: device_node - Node for the device - * Flags - Where the status flags are returned + * flags - Where the status flags are returned * * RETURN: Status * * DESCRIPTION: Executes _STA for selected device and stores results in - * *Flags. + * *Flags. If _STA does not exist, then the device is assumed + * to be present/functional/enabled (as per the ACPI spec). * * NOTE: Internal function, no parameter validation * @@ -252,6 +258,11 @@ acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags) ACPI_BTYPE_INTEGER, &obj_desc); if (ACPI_FAILURE(status)) { if (AE_NOT_FOUND == status) { + /* + * if _STA does not exist, then (as per the ACPI specification), + * the returned flags will indicate that the device is present, + * functional, and enabled. + */ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "_STA on %4.4s was not found, assuming device is present\n", acpi_ut_get_node_name(device_node))); diff --git a/drivers/acpi/acpica/utexcep.c b/drivers/acpi/acpica/utexcep.c new file mode 100644 index 00000000000..0403dcaabaf --- /dev/null +++ b/drivers/acpi/acpica/utexcep.c @@ -0,0 +1,159 @@ +/******************************************************************************* + * + * Module Name: utexcep - Exception code support + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define EXPORT_ACPI_INTERFACES + +#define ACPI_DEFINE_EXCEPTION_TABLE +#include <acpi/acpi.h> +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utexcep") + +/******************************************************************************* + * + * FUNCTION: acpi_format_exception + * + * PARAMETERS: status - The acpi_status code to be formatted + * + * RETURN: A string containing the exception text. A valid pointer is + * always returned. + * + * DESCRIPTION: This function translates an ACPI exception into an ASCII + * string. Returns "unknown status" string for invalid codes. + * + ******************************************************************************/ +const char *acpi_format_exception(acpi_status status) +{ + const struct acpi_exception_info *exception; + + ACPI_FUNCTION_ENTRY(); + + exception = acpi_ut_validate_exception(status); + if (!exception) { + + /* Exception code was not recognized */ + + ACPI_ERROR((AE_INFO, + "Unknown exception code: 0x%8.8X", status)); + + return ("UNKNOWN_STATUS_CODE"); + } + + return (exception->name); +} + +ACPI_EXPORT_SYMBOL(acpi_format_exception) + +/******************************************************************************* + * + * FUNCTION: acpi_ut_validate_exception + * + * PARAMETERS: status - The acpi_status code to be formatted + * + * RETURN: A string containing the exception text. NULL if exception is + * not valid. + * + * DESCRIPTION: This function validates and translates an ACPI exception into + * an ASCII string. + * + ******************************************************************************/ +const struct acpi_exception_info *acpi_ut_validate_exception(acpi_status status) +{ + u32 sub_status; + const struct acpi_exception_info *exception = NULL; + + ACPI_FUNCTION_ENTRY(); + + /* + * Status is composed of two parts, a "type" and an actual code + */ + sub_status = (status & ~AE_CODE_MASK); + + switch (status & AE_CODE_MASK) { + case AE_CODE_ENVIRONMENTAL: + + if (sub_status <= AE_CODE_ENV_MAX) { + exception = &acpi_gbl_exception_names_env[sub_status]; + } + break; + + case AE_CODE_PROGRAMMER: + + if (sub_status <= AE_CODE_PGM_MAX) { + exception = &acpi_gbl_exception_names_pgm[sub_status]; + } + break; + + case AE_CODE_ACPI_TABLES: + + if (sub_status <= AE_CODE_TBL_MAX) { + exception = &acpi_gbl_exception_names_tbl[sub_status]; + } + break; + + case AE_CODE_AML: + + if (sub_status <= AE_CODE_AML_MAX) { + exception = &acpi_gbl_exception_names_aml[sub_status]; + } + break; + + case AE_CODE_CONTROL: + + if (sub_status <= AE_CODE_CTRL_MAX) { + exception = &acpi_gbl_exception_names_ctrl[sub_status]; + } + break; + + default: + + break; + } + + if (!exception || !exception->name) { + return (NULL); + } + + return (exception); +} diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 4153584cf52..d69be3cb3fa 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,9 +41,9 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#define EXPORT_ACPI_INTERFACES #define DEFINE_ACPI_GLOBALS -#include <linux/export.h> #include <acpi/acpi.h> #include "accommon.h" @@ -55,32 +55,7 @@ ACPI_MODULE_NAME("utglobal") * Static global variable initialization. * ******************************************************************************/ -/* - * We want the debug switches statically initialized so they - * are already set when the debugger is entered. - */ -/* Debug switch - level and trace mask */ -u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT; - -/* Debug switch - layer (component) mask */ - -u32 acpi_dbg_layer = 0; -u32 acpi_gbl_nesting_level = 0; - -/* Debugger globals */ - -u8 acpi_gbl_db_terminate_threads = FALSE; -u8 acpi_gbl_abort_method = FALSE; -u8 acpi_gbl_method_executing = FALSE; - -/* System flags */ - -u32 acpi_gbl_startup_flags = 0; - -/* System starts uninitialized */ - -u8 acpi_gbl_shutdown = TRUE; - +/* Various state name strings */ const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = { "\\_S0_", "\\_S1_", @@ -140,6 +115,7 @@ const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = { {NULL, ACPI_TYPE_ANY, NULL} }; +#if (!ACPI_REDUCED_HARDWARE) /****************************************************************************** * * Event and Hardware globals @@ -236,6 +212,7 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] = ACPI_BITMASK_RT_CLOCK_STATUS, ACPI_BITMASK_RT_CLOCK_ENABLE}, }; +#endif /* !ACPI_REDUCED_HARDWARE */ /******************************************************************************* * @@ -245,8 +222,9 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] = * * RETURN: Status * - * DESCRIPTION: Init library globals. All globals that require specific - * initialization should be initialized here! + * DESCRIPTION: Initialize ACPICA globals. All globals that require specific + * initialization should be initialized here. This allows for + * a warm restart. * ******************************************************************************/ @@ -282,27 +260,43 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_owner_id_mask[i] = 0; } - /* Last owner_iD is never valid */ + /* Last owner_ID is never valid */ acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; - /* GPE support */ + /* Event counters */ + + acpi_method_count = 0; + acpi_sci_count = 0; + acpi_gpe_count = 0; + + for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { + acpi_fixed_event_count[i] = 0; + } + +#if (!ACPI_REDUCED_HARDWARE) + /* GPE/SCI support */ + + acpi_gbl_all_gpes_initialized = FALSE; acpi_gbl_gpe_xrupt_list_head = NULL; acpi_gbl_gpe_fadt_blocks[0] = NULL; acpi_gbl_gpe_fadt_blocks[1] = NULL; acpi_current_gpe_count = 0; - acpi_gbl_all_gpes_initialized = FALSE; + + acpi_gbl_global_event_handler = NULL; + acpi_gbl_sci_handler_list = NULL; + +#endif /* !ACPI_REDUCED_HARDWARE */ /* Global handlers */ - acpi_gbl_system_notify.handler = NULL; - acpi_gbl_device_notify.handler = NULL; + acpi_gbl_global_notify[0].handler = NULL; + acpi_gbl_global_notify[1].handler = NULL; acpi_gbl_exception_handler = NULL; acpi_gbl_init_handler = NULL; acpi_gbl_table_handler = NULL; acpi_gbl_interface_handler = NULL; - acpi_gbl_global_event_handler = NULL; /* Global Lock support */ @@ -316,19 +310,16 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_DSDT = NULL; acpi_gbl_cm_single_step = FALSE; - acpi_gbl_db_terminate_threads = FALSE; acpi_gbl_shutdown = FALSE; acpi_gbl_ns_lookup_count = 0; acpi_gbl_ps_find_count = 0; acpi_gbl_acpi_hardware_present = TRUE; acpi_gbl_last_owner_id_index = 0; acpi_gbl_next_owner_id_offset = 0; - acpi_gbl_trace_method_name = 0; acpi_gbl_trace_dbg_level = 0; acpi_gbl_trace_dbg_layer = 0; acpi_gbl_debugger_configuration = DEBUGGER_THREADING; acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; - acpi_gbl_osi_data = 0; acpi_gbl_osi_mutex = NULL; acpi_gbl_reg_methods_executed = FALSE; @@ -349,18 +340,30 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_root_node_struct.peer = NULL; acpi_gbl_root_node_struct.object = NULL; +#ifdef ACPI_DISASSEMBLER + acpi_gbl_external_list = NULL; + acpi_gbl_num_external_methods = 0; + acpi_gbl_resolved_external_methods = 0; +#endif + #ifdef ACPI_DEBUG_OUTPUT acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX); #endif #ifdef ACPI_DBG_TRACK_ALLOCATIONS acpi_gbl_display_final_mem_stats = FALSE; + acpi_gbl_disable_mem_tracking = FALSE; #endif + ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = FALSE); + return_ACPI_STATUS(AE_OK); } +/* Public globals */ + ACPI_EXPORT_SYMBOL(acpi_gbl_FADT) ACPI_EXPORT_SYMBOL(acpi_dbg_level) ACPI_EXPORT_SYMBOL(acpi_dbg_layer) +ACPI_EXPORT_SYMBOL(acpi_gpe_count) ACPI_EXPORT_SYMBOL(acpi_current_gpe_count) diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c index c92eb1d9378..4b12880e5b1 100644 --- a/drivers/acpi/acpica/utids.c +++ b/drivers/acpi/acpica/utids.c @@ -1,11 +1,11 @@ /****************************************************************************** * - * Module Name: utids - support for device IDs - HID, UID, CID + * Module Name: utids - support for device Ids - HID, UID, CID * *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -67,10 +67,10 @@ ACPI_MODULE_NAME("utids") ******************************************************************************/ acpi_status acpi_ut_execute_HID(struct acpi_namespace_node *device_node, - struct acpica_device_id **return_id) + struct acpi_pnp_device_id **return_id) { union acpi_operand_object *obj_desc; - struct acpica_device_id *hid; + struct acpi_pnp_device_id *hid; u32 length; acpi_status status; @@ -94,16 +94,17 @@ acpi_ut_execute_HID(struct acpi_namespace_node *device_node, /* Allocate a buffer for the HID */ hid = - ACPI_ALLOCATE_ZEROED(sizeof(struct acpica_device_id) + + ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) + (acpi_size) length); if (!hid) { status = AE_NO_MEMORY; goto cleanup; } - /* Area for the string starts after DEVICE_ID struct */ + /* Area for the string starts after PNP_DEVICE_ID struct */ - hid->string = ACPI_ADD_PTR(char, hid, sizeof(struct acpica_device_id)); + hid->string = + ACPI_ADD_PTR(char, hid, sizeof(struct acpi_pnp_device_id)); /* Convert EISAID to a string or simply copy existing string */ @@ -126,6 +127,73 @@ cleanup: /******************************************************************************* * + * FUNCTION: acpi_ut_execute_SUB + * + * PARAMETERS: device_node - Node for the device + * return_id - Where the _SUB is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _SUB control method that returns the subsystem + * ID of the device. The _SUB value is always a string containing + * either a valid PNP or ACPI ID. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +acpi_status +acpi_ut_execute_SUB(struct acpi_namespace_node *device_node, + struct acpi_pnp_device_id **return_id) +{ + union acpi_operand_object *obj_desc; + struct acpi_pnp_device_id *sub; + u32 length; + acpi_status status; + + ACPI_FUNCTION_TRACE(ut_execute_SUB); + + status = acpi_ut_evaluate_object(device_node, METHOD_NAME__SUB, + ACPI_BTYPE_STRING, &obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Get the size of the String to be returned, includes null terminator */ + + length = obj_desc->string.length + 1; + + /* Allocate a buffer for the SUB */ + + sub = + ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) + + (acpi_size) length); + if (!sub) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Area for the string starts after PNP_DEVICE_ID struct */ + + sub->string = + ACPI_ADD_PTR(char, sub, sizeof(struct acpi_pnp_device_id)); + + /* Simply copy existing string */ + + ACPI_STRCPY(sub->string, obj_desc->string.pointer); + sub->length = length; + *return_id = sub; + +cleanup: + + /* On exit, we must delete the return object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * * FUNCTION: acpi_ut_execute_UID * * PARAMETERS: device_node - Node for the device @@ -144,10 +212,10 @@ cleanup: acpi_status acpi_ut_execute_UID(struct acpi_namespace_node *device_node, - struct acpica_device_id **return_id) + struct acpi_pnp_device_id **return_id) { union acpi_operand_object *obj_desc; - struct acpica_device_id *uid; + struct acpi_pnp_device_id *uid; u32 length; acpi_status status; @@ -171,16 +239,17 @@ acpi_ut_execute_UID(struct acpi_namespace_node *device_node, /* Allocate a buffer for the UID */ uid = - ACPI_ALLOCATE_ZEROED(sizeof(struct acpica_device_id) + + ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) + (acpi_size) length); if (!uid) { status = AE_NO_MEMORY; goto cleanup; } - /* Area for the string starts after DEVICE_ID struct */ + /* Area for the string starts after PNP_DEVICE_ID struct */ - uid->string = ACPI_ADD_PTR(char, uid, sizeof(struct acpica_device_id)); + uid->string = + ACPI_ADD_PTR(char, uid, sizeof(struct acpi_pnp_device_id)); /* Convert an Integer to string, or just copy an existing string */ @@ -226,11 +295,11 @@ cleanup: acpi_status acpi_ut_execute_CID(struct acpi_namespace_node *device_node, - struct acpica_device_id_list **return_cid_list) + struct acpi_pnp_device_id_list **return_cid_list) { union acpi_operand_object **cid_objects; union acpi_operand_object *obj_desc; - struct acpica_device_id_list *cid_list; + struct acpi_pnp_device_id_list *cid_list; char *next_id_string; u32 string_area_size; u32 length; @@ -272,14 +341,17 @@ acpi_ut_execute_CID(struct acpi_namespace_node *device_node, switch (cid_objects[i]->common.type) { case ACPI_TYPE_INTEGER: + string_area_size += ACPI_EISAID_STRING_SIZE; break; case ACPI_TYPE_STRING: + string_area_size += cid_objects[i]->string.length + 1; break; default: + status = AE_TYPE; goto cleanup; } @@ -288,11 +360,12 @@ acpi_ut_execute_CID(struct acpi_namespace_node *device_node, /* * Now that we know the length of the CIDs, allocate return buffer: * 1) Size of the base structure + - * 2) Size of the CID DEVICE_ID array + + * 2) Size of the CID PNP_DEVICE_ID array + * 3) Size of the actual CID strings */ - cid_list_size = sizeof(struct acpica_device_id_list) + - ((count - 1) * sizeof(struct acpica_device_id)) + string_area_size; + cid_list_size = sizeof(struct acpi_pnp_device_id_list) + + ((count - 1) * sizeof(struct acpi_pnp_device_id)) + + string_area_size; cid_list = ACPI_ALLOCATE_ZEROED(cid_list_size); if (!cid_list) { @@ -300,10 +373,10 @@ acpi_ut_execute_CID(struct acpi_namespace_node *device_node, goto cleanup; } - /* Area for CID strings starts after the CID DEVICE_ID array */ + /* Area for CID strings starts after the CID PNP_DEVICE_ID array */ next_id_string = ACPI_CAST_PTR(char, cid_list->ids) + - ((acpi_size) count * sizeof(struct acpica_device_id)); + ((acpi_size) count * sizeof(struct acpi_pnp_device_id)); /* Copy/convert the CIDs to the return buffer */ diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c index 8359c0c5dc9..5f56fc49021 100644 --- a/drivers/acpi/acpica/utinit.c +++ b/drivers/acpi/acpica/utinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,27 +53,35 @@ ACPI_MODULE_NAME("utinit") /* Local prototypes */ static void acpi_ut_terminate(void); +#if (!ACPI_REDUCED_HARDWARE) + +static void acpi_ut_free_gpe_lists(void); + +#else + +#define acpi_ut_free_gpe_lists() +#endif /* !ACPI_REDUCED_HARDWARE */ + +#if (!ACPI_REDUCED_HARDWARE) /****************************************************************************** * - * FUNCTION: acpi_ut_terminate + * FUNCTION: acpi_ut_free_gpe_lists * * PARAMETERS: none * * RETURN: none * - * DESCRIPTION: Free global memory + * DESCRIPTION: Free global GPE lists * ******************************************************************************/ -static void acpi_ut_terminate(void) +static void acpi_ut_free_gpe_lists(void) { struct acpi_gpe_block_info *gpe_block; struct acpi_gpe_block_info *next_gpe_block; struct acpi_gpe_xrupt_info *gpe_xrupt_info; struct acpi_gpe_xrupt_info *next_gpe_xrupt_info; - ACPI_FUNCTION_TRACE(ut_terminate); - /* Free global GPE blocks and related info structures */ gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head; @@ -91,7 +99,26 @@ static void acpi_ut_terminate(void) ACPI_FREE(gpe_xrupt_info); gpe_xrupt_info = next_gpe_xrupt_info; } +} +#endif /* !ACPI_REDUCED_HARDWARE */ + +/****************************************************************************** + * + * FUNCTION: acpi_ut_terminate + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Free global memory + * + ******************************************************************************/ + +static void acpi_ut_terminate(void) +{ + ACPI_FUNCTION_TRACE(ut_terminate); + acpi_ut_free_gpe_lists(); acpi_ut_delete_address_lists(); return_VOID; } diff --git a/drivers/acpi/acpica/utlock.c b/drivers/acpi/acpica/utlock.c index 155fd786d0f..dc6e96547f1 100644 --- a/drivers/acpi/acpica/utlock.c +++ b/drivers/acpi/acpica/utlock.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,7 +52,7 @@ ACPI_MODULE_NAME("utlock") * FUNCTION: acpi_ut_create_rw_lock * acpi_ut_delete_rw_lock * - * PARAMETERS: Lock - Pointer to a valid RW lock + * PARAMETERS: lock - Pointer to a valid RW lock * * RETURN: Status * @@ -66,11 +66,11 @@ acpi_status acpi_ut_create_rw_lock(struct acpi_rw_lock *lock) lock->num_readers = 0; status = acpi_os_create_mutex(&lock->reader_mutex); if (ACPI_FAILURE(status)) { - return status; + return (status); } status = acpi_os_create_mutex(&lock->writer_mutex); - return status; + return (status); } void acpi_ut_delete_rw_lock(struct acpi_rw_lock *lock) @@ -89,7 +89,7 @@ void acpi_ut_delete_rw_lock(struct acpi_rw_lock *lock) * FUNCTION: acpi_ut_acquire_read_lock * acpi_ut_release_read_lock * - * PARAMETERS: Lock - Pointer to a valid RW lock + * PARAMETERS: lock - Pointer to a valid RW lock * * RETURN: Status * @@ -108,7 +108,7 @@ acpi_status acpi_ut_acquire_read_lock(struct acpi_rw_lock *lock) status = acpi_os_acquire_mutex(lock->reader_mutex, ACPI_WAIT_FOREVER); if (ACPI_FAILURE(status)) { - return status; + return (status); } /* Acquire the write lock only for the first reader */ @@ -121,7 +121,7 @@ acpi_status acpi_ut_acquire_read_lock(struct acpi_rw_lock *lock) } acpi_os_release_mutex(lock->reader_mutex); - return status; + return (status); } acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock) @@ -130,7 +130,7 @@ acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock) status = acpi_os_acquire_mutex(lock->reader_mutex, ACPI_WAIT_FOREVER); if (ACPI_FAILURE(status)) { - return status; + return (status); } /* Release the write lock only for the very last reader */ @@ -141,7 +141,7 @@ acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock) } acpi_os_release_mutex(lock->reader_mutex); - return status; + return (status); } /******************************************************************************* @@ -149,7 +149,7 @@ acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock) * FUNCTION: acpi_ut_acquire_write_lock * acpi_ut_release_write_lock * - * PARAMETERS: Lock - Pointer to a valid RW lock + * PARAMETERS: lock - Pointer to a valid RW lock * * RETURN: Status * @@ -165,7 +165,7 @@ acpi_status acpi_ut_acquire_write_lock(struct acpi_rw_lock *lock) acpi_status status; status = acpi_os_acquire_mutex(lock->writer_mutex, ACPI_WAIT_FOREVER); - return status; + return (status); } void acpi_ut_release_write_lock(struct acpi_rw_lock *lock) diff --git a/drivers/acpi/acpica/utmath.c b/drivers/acpi/acpica/utmath.c index 2491a552b0e..d44dee6ee10 100644 --- a/drivers/acpi/acpica/utmath.c +++ b/drivers/acpi/acpica/utmath.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -73,15 +73,15 @@ typedef union uint64_overlay { * * FUNCTION: acpi_ut_short_divide * - * PARAMETERS: Dividend - 64-bit dividend - * Divisor - 32-bit divisor + * PARAMETERS: dividend - 64-bit dividend + * divisor - 32-bit divisor * out_quotient - Pointer to where the quotient is returned * out_remainder - Pointer to where the remainder is returned * * RETURN: Status (Checks for divide-by-zero) * * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits) - * divide and modulo. The result is a 64-bit quotient and a + * divide and modulo. The result is a 64-bit quotient and a * 32-bit remainder. * ******************************************************************************/ diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c index 86f19db74e0..2e2bb14e109 100644 --- a/drivers/acpi/acpica/utmisc.c +++ b/drivers/acpi/acpica/utmisc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,8 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include <linux/module.h> - #include <acpi/acpi.h> #include "accommon.h" #include "acnamesp.h" @@ -52,84 +50,15 @@ ACPI_MODULE_NAME("utmisc") /******************************************************************************* * - * FUNCTION: acpi_ut_validate_exception - * - * PARAMETERS: Status - The acpi_status code to be formatted - * - * RETURN: A string containing the exception text. NULL if exception is - * not valid. - * - * DESCRIPTION: This function validates and translates an ACPI exception into - * an ASCII string. - * - ******************************************************************************/ -const char *acpi_ut_validate_exception(acpi_status status) -{ - u32 sub_status; - const char *exception = NULL; - - ACPI_FUNCTION_ENTRY(); - - /* - * Status is composed of two parts, a "type" and an actual code - */ - sub_status = (status & ~AE_CODE_MASK); - - switch (status & AE_CODE_MASK) { - case AE_CODE_ENVIRONMENTAL: - - if (sub_status <= AE_CODE_ENV_MAX) { - exception = acpi_gbl_exception_names_env[sub_status]; - } - break; - - case AE_CODE_PROGRAMMER: - - if (sub_status <= AE_CODE_PGM_MAX) { - exception = acpi_gbl_exception_names_pgm[sub_status]; - } - break; - - case AE_CODE_ACPI_TABLES: - - if (sub_status <= AE_CODE_TBL_MAX) { - exception = acpi_gbl_exception_names_tbl[sub_status]; - } - break; - - case AE_CODE_AML: - - if (sub_status <= AE_CODE_AML_MAX) { - exception = acpi_gbl_exception_names_aml[sub_status]; - } - break; - - case AE_CODE_CONTROL: - - if (sub_status <= AE_CODE_CTRL_MAX) { - exception = acpi_gbl_exception_names_ctrl[sub_status]; - } - break; - - default: - break; - } - - return (ACPI_CAST_PTR(const char, exception)); -} - -/******************************************************************************* - * * FUNCTION: acpi_ut_is_pci_root_bridge * - * PARAMETERS: Id - The HID/CID in string format + * PARAMETERS: id - The HID/CID in string format * * RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge * * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID. * ******************************************************************************/ - u8 acpi_ut_is_pci_root_bridge(char *id) { @@ -150,7 +79,7 @@ u8 acpi_ut_is_pci_root_bridge(char *id) * * FUNCTION: acpi_ut_is_aml_table * - * PARAMETERS: Table - An ACPI table + * PARAMETERS: table - An ACPI table * * RETURN: TRUE if table contains executable AML; FALSE otherwise * @@ -176,298 +105,9 @@ u8 acpi_ut_is_aml_table(struct acpi_table_header *table) /******************************************************************************* * - * FUNCTION: acpi_ut_allocate_owner_id - * - * PARAMETERS: owner_id - Where the new owner ID is returned - * - * RETURN: Status - * - * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to - * track objects created by the table or method, to be deleted - * when the method exits or the table is unloaded. - * - ******************************************************************************/ - -acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) -{ - u32 i; - u32 j; - u32 k; - acpi_status status; - - ACPI_FUNCTION_TRACE(ut_allocate_owner_id); - - /* Guard against multiple allocations of ID to the same location */ - - if (*owner_id) { - ACPI_ERROR((AE_INFO, "Owner ID [0x%2.2X] already exists", - *owner_id)); - return_ACPI_STATUS(AE_ALREADY_EXISTS); - } - - /* Mutex for the global ID mask */ - - status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Find a free owner ID, cycle through all possible IDs on repeated - * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have - * to be scanned twice. - */ - for (i = 0, j = acpi_gbl_last_owner_id_index; - i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) { - if (j >= ACPI_NUM_OWNERID_MASKS) { - j = 0; /* Wraparound to start of mask array */ - } - - for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) { - if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) { - - /* There are no free IDs in this mask */ - - break; - } - - if (!(acpi_gbl_owner_id_mask[j] & (1 << k))) { - /* - * Found a free ID. The actual ID is the bit index plus one, - * making zero an invalid Owner ID. Save this as the last ID - * allocated and update the global ID mask. - */ - acpi_gbl_owner_id_mask[j] |= (1 << k); - - acpi_gbl_last_owner_id_index = (u8) j; - acpi_gbl_next_owner_id_offset = (u8) (k + 1); - - /* - * Construct encoded ID from the index and bit position - * - * Note: Last [j].k (bit 255) is never used and is marked - * permanently allocated (prevents +1 overflow) - */ - *owner_id = - (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j)); - - ACPI_DEBUG_PRINT((ACPI_DB_VALUES, - "Allocated OwnerId: %2.2X\n", - (unsigned int)*owner_id)); - goto exit; - } - } - - acpi_gbl_next_owner_id_offset = 0; - } - - /* - * All owner_ids have been allocated. This typically should - * not happen since the IDs are reused after deallocation. The IDs are - * allocated upon table load (one per table) and method execution, and - * they are released when a table is unloaded or a method completes - * execution. - * - * If this error happens, there may be very deep nesting of invoked control - * methods, or there may be a bug where the IDs are not released. - */ - status = AE_OWNER_ID_LIMIT; - ACPI_ERROR((AE_INFO, - "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT")); - - exit: - (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_release_owner_id - * - * PARAMETERS: owner_id_ptr - Pointer to a previously allocated owner_iD - * - * RETURN: None. No error is returned because we are either exiting a - * control method or unloading a table. Either way, we would - * ignore any error anyway. - * - * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255 - * - ******************************************************************************/ - -void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) -{ - acpi_owner_id owner_id = *owner_id_ptr; - acpi_status status; - u32 index; - u32 bit; - - ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id); - - /* Always clear the input owner_id (zero is an invalid ID) */ - - *owner_id_ptr = 0; - - /* Zero is not a valid owner_iD */ - - if (owner_id == 0) { - ACPI_ERROR((AE_INFO, "Invalid OwnerId: 0x%2.2X", owner_id)); - return_VOID; - } - - /* Mutex for the global ID mask */ - - status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); - if (ACPI_FAILURE(status)) { - return_VOID; - } - - /* Normalize the ID to zero */ - - owner_id--; - - /* Decode ID to index/offset pair */ - - index = ACPI_DIV_32(owner_id); - bit = 1 << ACPI_MOD_32(owner_id); - - /* Free the owner ID only if it is valid */ - - if (acpi_gbl_owner_id_mask[index] & bit) { - acpi_gbl_owner_id_mask[index] ^= bit; - } else { - ACPI_ERROR((AE_INFO, - "Release of non-allocated OwnerId: 0x%2.2X", - owner_id + 1)); - } - - (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_strupr (strupr) - * - * PARAMETERS: src_string - The source string to convert - * - * RETURN: None - * - * DESCRIPTION: Convert string to uppercase - * - * NOTE: This is not a POSIX function, so it appears here, not in utclib.c - * - ******************************************************************************/ - -void acpi_ut_strupr(char *src_string) -{ - char *string; - - ACPI_FUNCTION_ENTRY(); - - if (!src_string) { - return; - } - - /* Walk entire string, uppercasing the letters */ - - for (string = src_string; *string; string++) { - *string = (char)ACPI_TOUPPER(*string); - } - - return; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_print_string - * - * PARAMETERS: String - Null terminated ASCII string - * max_length - Maximum output length - * - * RETURN: None - * - * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape - * sequences. - * - ******************************************************************************/ - -void acpi_ut_print_string(char *string, u8 max_length) -{ - u32 i; - - if (!string) { - acpi_os_printf("<\"NULL STRING PTR\">"); - return; - } - - acpi_os_printf("\""); - for (i = 0; string[i] && (i < max_length); i++) { - - /* Escape sequences */ - - switch (string[i]) { - case 0x07: - acpi_os_printf("\\a"); /* BELL */ - break; - - case 0x08: - acpi_os_printf("\\b"); /* BACKSPACE */ - break; - - case 0x0C: - acpi_os_printf("\\f"); /* FORMFEED */ - break; - - case 0x0A: - acpi_os_printf("\\n"); /* LINEFEED */ - break; - - case 0x0D: - acpi_os_printf("\\r"); /* CARRIAGE RETURN */ - break; - - case 0x09: - acpi_os_printf("\\t"); /* HORIZONTAL TAB */ - break; - - case 0x0B: - acpi_os_printf("\\v"); /* VERTICAL TAB */ - break; - - case '\'': /* Single Quote */ - case '\"': /* Double Quote */ - case '\\': /* Backslash */ - acpi_os_printf("\\%c", (int)string[i]); - break; - - default: - - /* Check for printable character or hex escape */ - - if (ACPI_IS_PRINT(string[i])) { - /* This is a normal character */ - - acpi_os_printf("%c", (int)string[i]); - } else { - /* All others will be Hex escapes */ - - acpi_os_printf("\\x%2.2X", (s32) string[i]); - } - break; - } - } - acpi_os_printf("\""); - - if (i == max_length && string[i]) { - acpi_os_printf("..."); - } -} - -/******************************************************************************* - * * FUNCTION: acpi_ut_dword_byte_swap * - * PARAMETERS: Value - Value to be converted + * PARAMETERS: value - Value to be converted * * RETURN: u32 integer with bytes swapped * @@ -507,8 +147,8 @@ u32 acpi_ut_dword_byte_swap(u32 value) * RETURN: None * * DESCRIPTION: Set the global integer bit width based upon the revision - * of the DSDT. For Revision 1 and 0, Integers are 32 bits. - * For Revision 2 and above, Integers are 64 bits. Yes, this + * of the DSDT. For Revision 1 and 0, Integers are 32 bits. + * For Revision 2 and above, Integers are 64 bits. Yes, this * makes a difference. * ******************************************************************************/ @@ -532,354 +172,12 @@ void acpi_ut_set_integer_width(u8 revision) } } -#ifdef ACPI_DEBUG_OUTPUT -/******************************************************************************* - * - * FUNCTION: acpi_ut_display_init_pathname - * - * PARAMETERS: Type - Object type of the node - * obj_handle - Handle whose pathname will be displayed - * Path - Additional path string to be appended. - * (NULL if no extra path) - * - * RETURN: acpi_status - * - * DESCRIPTION: Display full pathname of an object, DEBUG ONLY - * - ******************************************************************************/ - -void -acpi_ut_display_init_pathname(u8 type, - struct acpi_namespace_node *obj_handle, - char *path) -{ - acpi_status status; - struct acpi_buffer buffer; - - ACPI_FUNCTION_ENTRY(); - - /* Only print the path if the appropriate debug level is enabled */ - - if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { - return; - } - - /* Get the full pathname to the node */ - - buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_ns_handle_to_pathname(obj_handle, &buffer); - if (ACPI_FAILURE(status)) { - return; - } - - /* Print what we're doing */ - - switch (type) { - case ACPI_TYPE_METHOD: - acpi_os_printf("Executing "); - break; - - default: - acpi_os_printf("Initializing "); - break; - } - - /* Print the object type and pathname */ - - acpi_os_printf("%-12s %s", - acpi_ut_get_type_name(type), (char *)buffer.pointer); - - /* Extra path is used to append names like _STA, _INI, etc. */ - - if (path) { - acpi_os_printf(".%s", path); - } - acpi_os_printf("\n"); - - ACPI_FREE(buffer.pointer); -} -#endif - -/******************************************************************************* - * - * FUNCTION: acpi_ut_valid_acpi_char - * - * PARAMETERS: Char - The character to be examined - * Position - Byte position (0-3) - * - * RETURN: TRUE if the character is valid, FALSE otherwise - * - * DESCRIPTION: Check for a valid ACPI character. Must be one of: - * 1) Upper case alpha - * 2) numeric - * 3) underscore - * - * We allow a '!' as the last character because of the ASF! table - * - ******************************************************************************/ - -u8 acpi_ut_valid_acpi_char(char character, u32 position) -{ - - if (!((character >= 'A' && character <= 'Z') || - (character >= '0' && character <= '9') || (character == '_'))) { - - /* Allow a '!' in the last position */ - - if (character == '!' && position == 3) { - return (TRUE); - } - - return (FALSE); - } - - return (TRUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_valid_acpi_name - * - * PARAMETERS: Name - The name to be examined - * - * RETURN: TRUE if the name is valid, FALSE otherwise - * - * DESCRIPTION: Check for a valid ACPI name. Each character must be one of: - * 1) Upper case alpha - * 2) numeric - * 3) underscore - * - ******************************************************************************/ - -u8 acpi_ut_valid_acpi_name(u32 name) -{ - u32 i; - - ACPI_FUNCTION_ENTRY(); - - for (i = 0; i < ACPI_NAME_SIZE; i++) { - if (!acpi_ut_valid_acpi_char - ((ACPI_CAST_PTR(char, &name))[i], i)) { - return (FALSE); - } - } - - return (TRUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_repair_name - * - * PARAMETERS: Name - The ACPI name to be repaired - * - * RETURN: Repaired version of the name - * - * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and - * return the new name. - * - ******************************************************************************/ - -acpi_name acpi_ut_repair_name(char *name) -{ - u32 i; - char new_name[ACPI_NAME_SIZE]; - - for (i = 0; i < ACPI_NAME_SIZE; i++) { - new_name[i] = name[i]; - - /* - * Replace a bad character with something printable, yet technically - * still invalid. This prevents any collisions with existing "good" - * names in the namespace. - */ - if (!acpi_ut_valid_acpi_char(name[i], i)) { - new_name[i] = '*'; - } - } - - return (*(u32 *) new_name); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_strtoul64 - * - * PARAMETERS: String - Null terminated string - * Base - Radix of the string: 16 or ACPI_ANY_BASE; - * ACPI_ANY_BASE means 'in behalf of to_integer' - * ret_integer - Where the converted integer is returned - * - * RETURN: Status and Converted value - * - * DESCRIPTION: Convert a string into an unsigned value. Performs either a - * 32-bit or 64-bit conversion, depending on the current mode - * of the interpreter. - * NOTE: Does not support Octal strings, not needed. - * - ******************************************************************************/ - -acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer) -{ - u32 this_digit = 0; - u64 return_value = 0; - u64 quotient; - u64 dividend; - u32 to_integer_op = (base == ACPI_ANY_BASE); - u32 mode32 = (acpi_gbl_integer_byte_width == 4); - u8 valid_digits = 0; - u8 sign_of0x = 0; - u8 term = 0; - - ACPI_FUNCTION_TRACE_STR(ut_stroul64, string); - - switch (base) { - case ACPI_ANY_BASE: - case 16: - break; - - default: - /* Invalid Base */ - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - if (!string) { - goto error_exit; - } - - /* Skip over any white space in the buffer */ - - while ((*string) && (ACPI_IS_SPACE(*string) || *string == '\t')) { - string++; - } - - if (to_integer_op) { - /* - * Base equal to ACPI_ANY_BASE means 'to_integer operation case'. - * We need to determine if it is decimal or hexadecimal. - */ - if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { - sign_of0x = 1; - base = 16; - - /* Skip over the leading '0x' */ - string += 2; - } else { - base = 10; - } - } - - /* Any string left? Check that '0x' is not followed by white space. */ - - if (!(*string) || ACPI_IS_SPACE(*string) || *string == '\t') { - if (to_integer_op) { - goto error_exit; - } else { - goto all_done; - } - } - - /* - * Perform a 32-bit or 64-bit conversion, depending upon the current - * execution mode of the interpreter - */ - dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX; - - /* Main loop: convert the string to a 32- or 64-bit integer */ - - while (*string) { - if (ACPI_IS_DIGIT(*string)) { - - /* Convert ASCII 0-9 to Decimal value */ - - this_digit = ((u8) * string) - '0'; - } else if (base == 10) { - - /* Digit is out of range; possible in to_integer case only */ - - term = 1; - } else { - this_digit = (u8) ACPI_TOUPPER(*string); - if (ACPI_IS_XDIGIT((char)this_digit)) { - - /* Convert ASCII Hex char to value */ - - this_digit = this_digit - 'A' + 10; - } else { - term = 1; - } - } - - if (term) { - if (to_integer_op) { - goto error_exit; - } else { - break; - } - } else if ((valid_digits == 0) && (this_digit == 0) - && !sign_of0x) { - - /* Skip zeros */ - string++; - continue; - } - - valid_digits++; - - if (sign_of0x && ((valid_digits > 16) - || ((valid_digits > 8) && mode32))) { - /* - * This is to_integer operation case. - * No any restrictions for string-to-integer conversion, - * see ACPI spec. - */ - goto error_exit; - } - - /* Divide the digit into the correct position */ - - (void)acpi_ut_short_divide((dividend - (u64) this_digit), - base, "ient, NULL); - - if (return_value > quotient) { - if (to_integer_op) { - goto error_exit; - } else { - break; - } - } - - return_value *= base; - return_value += this_digit; - string++; - } - - /* All done, normal exit */ - - all_done: - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(return_value))); - - *ret_integer = return_value; - return_ACPI_STATUS(AE_OK); - - error_exit: - /* Base was set/validated above */ - - if (base == 10) { - return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT); - } else { - return_ACPI_STATUS(AE_BAD_HEX_CONSTANT); - } -} - /******************************************************************************* * * FUNCTION: acpi_ut_create_update_state_and_push * - * PARAMETERS: Object - Object to be added to the new state - * Action - Increment/Decrement + * PARAMETERS: object - Object to be added to the new state + * action - Increment/Decrement * state_list - List the state will be added to * * RETURN: Status @@ -919,7 +217,7 @@ acpi_ut_create_update_state_and_push(union acpi_operand_object *object, * PARAMETERS: source_object - The package to walk * target_object - Target object (if package is being copied) * walk_callback - Called once for each package element - * Context - Passed to the callback function + * context - Passed to the callback function * * RETURN: Status * @@ -928,7 +226,7 @@ acpi_ut_create_update_state_and_push(union acpi_operand_object *object, ******************************************************************************/ acpi_status -acpi_ut_walk_package_tree(union acpi_operand_object * source_object, +acpi_ut_walk_package_tree(union acpi_operand_object *source_object, void *target_object, acpi_pkg_callback walk_callback, void *context) { @@ -955,10 +253,10 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object, /* * Check for: - * 1) An uninitialized package element. It is completely + * 1) An uninitialized package element. It is completely * legal to declare a package and leave it uninitialized * 2) Not an internal object - can be a namespace node instead - * 3) Any type other than a package. Packages are handled in else + * 3) Any type other than a package. Packages are handled in else * case below. */ if ((!this_source_obj) || @@ -977,7 +275,7 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object, state->pkg.source_object->package.count) { /* * We've handled all of the objects at this level, This means - * that we have just completed a package. That package may + * that we have just completed a package. That package may * have contained one or more packages itself. * * Delete this state and pop the previous state (package). @@ -1039,3 +337,73 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object, return_ACPI_STATUS(AE_AML_INTERNAL); } + +#ifdef ACPI_DEBUG_OUTPUT +/******************************************************************************* + * + * FUNCTION: acpi_ut_display_init_pathname + * + * PARAMETERS: type - Object type of the node + * obj_handle - Handle whose pathname will be displayed + * path - Additional path string to be appended. + * (NULL if no extra path) + * + * RETURN: acpi_status + * + * DESCRIPTION: Display full pathname of an object, DEBUG ONLY + * + ******************************************************************************/ + +void +acpi_ut_display_init_pathname(u8 type, + struct acpi_namespace_node *obj_handle, + char *path) +{ + acpi_status status; + struct acpi_buffer buffer; + + ACPI_FUNCTION_ENTRY(); + + /* Only print the path if the appropriate debug level is enabled */ + + if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { + return; + } + + /* Get the full pathname to the node */ + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_ns_handle_to_pathname(obj_handle, &buffer); + if (ACPI_FAILURE(status)) { + return; + } + + /* Print what we're doing */ + + switch (type) { + case ACPI_TYPE_METHOD: + + acpi_os_printf("Executing "); + break; + + default: + + acpi_os_printf("Initializing "); + break; + } + + /* Print the object type and pathname */ + + acpi_os_printf("%-12s %s", + acpi_ut_get_type_name(type), (char *)buffer.pointer); + + /* Extra path is used to append names like _STA, _INI, etc. */ + + if (path) { + acpi_os_printf(".%s", path); + } + acpi_os_printf("\n"); + + ACPI_FREE(buffer.pointer); +} +#endif diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c index 43174df3312..82717fff9ff 100644 --- a/drivers/acpi/acpica/utmutex.c +++ b/drivers/acpi/acpica/utmutex.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -81,7 +81,7 @@ acpi_status acpi_ut_mutex_initialize(void) } } - /* Create the spinlocks for use at interrupt level */ + /* Create the spinlocks for use at interrupt level or for speed */ status = acpi_os_create_lock (&acpi_gbl_gpe_lock); if (ACPI_FAILURE (status)) { @@ -93,7 +93,13 @@ acpi_status acpi_ut_mutex_initialize(void) return_ACPI_STATUS (status); } + status = acpi_os_create_lock(&acpi_gbl_reference_count_lock); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + /* Mutex for _OSI support */ + status = acpi_os_create_mutex(&acpi_gbl_osi_mutex); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -136,6 +142,7 @@ void acpi_ut_mutex_terminate(void) acpi_os_delete_lock(acpi_gbl_gpe_lock); acpi_os_delete_lock(acpi_gbl_hardware_lock); + acpi_os_delete_lock(acpi_gbl_reference_count_lock); /* Delete the reader/writer lock */ @@ -147,7 +154,7 @@ void acpi_ut_mutex_terminate(void) * * FUNCTION: acpi_ut_create_mutex * - * PARAMETERS: mutex_iD - ID of the mutex to be created + * PARAMETERS: mutex_ID - ID of the mutex to be created * * RETURN: Status * @@ -176,7 +183,7 @@ static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id) * * FUNCTION: acpi_ut_delete_mutex * - * PARAMETERS: mutex_iD - ID of the mutex to be deleted + * PARAMETERS: mutex_ID - ID of the mutex to be deleted * * RETURN: Status * @@ -193,13 +200,15 @@ static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id) acpi_gbl_mutex_info[mutex_id].mutex = NULL; acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED; + + return_VOID; } /******************************************************************************* * * FUNCTION: acpi_ut_acquire_mutex * - * PARAMETERS: mutex_iD - ID of the mutex to be acquired + * PARAMETERS: mutex_ID - ID of the mutex to be acquired * * RETURN: Status * @@ -226,9 +235,9 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) /* * Mutex debug code, for internal debugging only. * - * Deadlock prevention. Check if this thread owns any mutexes of value - * greater than or equal to this one. If so, the thread has violated - * the mutex ordering rule. This indicates a coding error somewhere in + * Deadlock prevention. Check if this thread owns any mutexes of value + * greater than or equal to this one. If so, the thread has violated + * the mutex ordering rule. This indicates a coding error somewhere in * the ACPI subsystem code. */ for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) { @@ -283,7 +292,7 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) * * FUNCTION: acpi_ut_release_mutex * - * PARAMETERS: mutex_iD - ID of the mutex to be released + * PARAMETERS: mutex_ID - ID of the mutex to be released * * RETURN: Status * @@ -319,9 +328,9 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) /* * Mutex debug code, for internal debugging only. * - * Deadlock prevention. Check if this thread owns any mutexes of value - * greater than this one. If so, the thread has violated the mutex - * ordering rule. This indicates a coding error somewhere in + * Deadlock prevention. Check if this thread owns any mutexes of value + * greater than this one. If so, the thread has violated the mutex + * ordering rule. This indicates a coding error somewhere in * the ACPI subsystem code. */ for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) { diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c index b112744fc9a..dfa9009bfc8 100644 --- a/drivers/acpi/acpica/utobject.c +++ b/drivers/acpi/acpica/utobject.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -69,7 +69,7 @@ acpi_ut_get_element_length(u8 object_type, * PARAMETERS: module_name - Source file name of caller * line_number - Line number of caller * component_id - Component type of caller - * Type - ACPI Type of the new object + * type - ACPI Type of the new object * * RETURN: A new internal object, null on failure * @@ -77,7 +77,7 @@ acpi_ut_get_element_length(u8 object_type, * * NOTE: We always allocate the worst-case object descriptor because * these objects are cached, and we want them to be - * one-size-satisifies-any-request. This in itself may not be + * one-size-satisifies-any-request. This in itself may not be * the most memory efficient, but the efficiency of the object * cache should more than make up for this! * @@ -129,6 +129,7 @@ union acpi_operand_object *acpi_ut_create_internal_object_dbg(const char break; default: + /* All others have no secondary object */ break; } @@ -150,7 +151,7 @@ union acpi_operand_object *acpi_ut_create_internal_object_dbg(const char * * FUNCTION: acpi_ut_create_package_object * - * PARAMETERS: Count - Number of package elements + * PARAMETERS: count - Number of package elements * * RETURN: Pointer to a new Package object, null on failure * @@ -179,7 +180,7 @@ union acpi_operand_object *acpi_ut_create_package_object(u32 count) package_elements = ACPI_ALLOCATE_ZEROED(((acpi_size) count + 1) * sizeof(void *)); if (!package_elements) { - acpi_ut_remove_reference(package_desc); + ACPI_FREE(package_desc); return_PTR(NULL); } @@ -323,11 +324,11 @@ union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size) * * FUNCTION: acpi_ut_valid_internal_object * - * PARAMETERS: Object - Object to be validated + * PARAMETERS: object - Object to be validated * * RETURN: TRUE if object is valid, FALSE otherwise * - * DESCRIPTION: Validate a pointer to be a union acpi_operand_object + * DESCRIPTION: Validate a pointer to be of type union acpi_operand_object * ******************************************************************************/ @@ -348,13 +349,14 @@ u8 acpi_ut_valid_internal_object(void *object) switch (ACPI_GET_DESCRIPTOR_TYPE(object)) { case ACPI_DESC_TYPE_OPERAND: - /* The object appears to be a valid union acpi_operand_object */ + /* The object appears to be a valid union acpi_operand_object */ return (TRUE); default: + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "%p is not not an ACPI operand obj [%s]\n", + "%p is not an ACPI operand obj [%s]\n", object, acpi_ut_get_descriptor_name(object))); break; } @@ -370,9 +372,9 @@ u8 acpi_ut_valid_internal_object(void *object) * line_number - Caller's line number (for error output) * component_id - Caller's component ID (for error output) * - * RETURN: Pointer to newly allocated object descriptor. Null on error + * RETURN: Pointer to newly allocated object descriptor. Null on error * - * DESCRIPTION: Allocate a new object descriptor. Gracefully handle + * DESCRIPTION: Allocate a new object descriptor. Gracefully handle * error conditions. * ******************************************************************************/ @@ -394,7 +396,6 @@ void *acpi_ut_allocate_object_desc_dbg(const char *module_name, /* Mark the descriptor type */ - memset(object, 0, sizeof(union acpi_operand_object)); ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_OPERAND); ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p Size %X\n", @@ -407,7 +408,7 @@ void *acpi_ut_allocate_object_desc_dbg(const char *module_name, * * FUNCTION: acpi_ut_delete_object_desc * - * PARAMETERS: Object - An Acpi internal object to be deleted + * PARAMETERS: object - An Acpi internal object to be deleted * * RETURN: None. * @@ -419,7 +420,7 @@ void acpi_ut_delete_object_desc(union acpi_operand_object *object) { ACPI_FUNCTION_TRACE_PTR(ut_delete_object_desc, object); - /* Object must be a union acpi_operand_object */ + /* Object must be of type union acpi_operand_object */ if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) { ACPI_ERROR((AE_INFO, @@ -459,25 +460,28 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, ACPI_FUNCTION_TRACE_PTR(ut_get_simple_object_size, internal_object); + /* Start with the length of the (external) Acpi object */ + + length = sizeof(union acpi_object); + + /* A NULL object is allowed, can be a legal uninitialized package element */ + + if (!internal_object) { /* - * Handle a null object (Could be a uninitialized package - * element -- which is legal) + * Object is NULL, just return the length of union acpi_object + * (A NULL union acpi_object is an object of all zeroes.) */ - if (!internal_object) { - *obj_length = sizeof(union acpi_object); + *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length); return_ACPI_STATUS(AE_OK); } - /* Start with the length of the Acpi object */ - - length = sizeof(union acpi_object); + /* A Namespace Node should never appear here */ if (ACPI_GET_DESCRIPTOR_TYPE(internal_object) == ACPI_DESC_TYPE_NAMED) { - /* Object is a named object (reference), just return the length */ + /* A namespace node should never get here */ - *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length); - return_ACPI_STATUS(status); + return_ACPI_STATUS(AE_AML_INTERNAL); } /* @@ -509,7 +513,6 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, switch (internal_object->reference.class) { case ACPI_REFCLASS_NAME: - /* * Get the actual length of the full pathname to this object. * The reference will be converted to the pathname to the object @@ -525,7 +528,6 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, break; default: - /* * No other reference opcodes are supported. * Notably, Locals and Args are not supported, but this may be @@ -554,7 +556,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, /* * Account for the space required by the object rounded up to the next - * multiple of the machine word size. This keeps each object aligned + * multiple of the machine word size. This keeps each object aligned * on a machine word boundary. (preventing alignment faults on some * machines.) */ @@ -585,7 +587,6 @@ acpi_ut_get_element_length(u8 object_type, switch (object_type) { case ACPI_COPY_TYPE_SIMPLE: - /* * Simple object - just get the size (Null object/entry is handled * here also) and sum it into the running package length diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c index 2360cf70c18..685766fc6ca 100644 --- a/drivers/acpi/acpica/utosi.c +++ b/drivers/acpi/acpica/utosi.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,6 +47,31 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utosi") +/****************************************************************************** + * + * ACPICA policy for new _OSI strings: + * + * It is the stated policy of ACPICA that new _OSI strings will be integrated + * into this module as soon as possible after they are defined. It is strongly + * recommended that all ACPICA hosts mirror this policy and integrate any + * changes to this module as soon as possible. There are several historical + * reasons behind this policy: + * + * 1) New BIOSs tend to test only the case where the host responds TRUE to + * the latest version of Windows, which would respond to the latest/newest + * _OSI string. Not responding TRUE to the latest version of Windows will + * risk executing untested code paths throughout the DSDT and SSDTs. + * + * 2) If a new _OSI string is recognized only after a significant delay, this + * has the potential to cause problems on existing working machines because + * of the possibility that a new and different path through the ASL code + * will be executed. + * + * 3) New _OSI strings are tending to come out about once per year. A delay + * in recognizing a new string for a significant amount of time risks the + * release of another string which only compounds the initial problem. + * + *****************************************************************************/ /* * Strings supported by the _OSI predefined control method (which is * implemented internally within this module.) @@ -68,29 +93,30 @@ static struct acpi_interface_info acpi_default_supported_interfaces[] = { {"Windows 2001.1", NULL, 0, ACPI_OSI_WINSRV_2003}, /* Windows Server 2003 */ {"Windows 2001 SP2", NULL, 0, ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */ {"Windows 2001.1 SP1", NULL, 0, ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */ - {"Windows 2006", NULL, 0, ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */ + {"Windows 2006", NULL, 0, ACPI_OSI_WIN_VISTA}, /* Windows vista - Added 03/2006 */ {"Windows 2006.1", NULL, 0, ACPI_OSI_WINSRV_2008}, /* Windows Server 2008 - Added 09/2009 */ {"Windows 2006 SP1", NULL, 0, ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */ {"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2}, /* Windows Vista SP2 - Added 09/2010 */ {"Windows 2009", NULL, 0, ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */ + {"Windows 2012", NULL, 0, ACPI_OSI_WIN_8}, /* Windows 8 and Server 2012 - Added 08/2012 */ + {"Windows 2013", NULL, 0, ACPI_OSI_WIN_8}, /* Windows 8.1 and Server 2012 R2 - Added 01/2014 */ /* Feature Group Strings */ - {"Extended Address Space Descriptor", NULL, 0, 0} + {"Extended Address Space Descriptor", NULL, ACPI_OSI_FEATURE, 0}, /* * All "optional" feature group strings (features that are implemented - * by the host) should be dynamically added by the host via - * acpi_install_interface and should not be manually added here. - * - * Examples of optional feature group strings: - * - * "Module Device" - * "Processor Device" - * "3.0 Thermal Model" - * "3.0 _SCP Extensions" - * "Processor Aggregator Device" + * by the host) should be dynamically modified to VALID by the host via + * acpi_install_interface or acpi_update_interfaces. Such optional feature + * group strings are set as INVALID by default here. */ + + {"Module Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, + {"Processor Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, + {"3.0 Thermal Model", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, + {"3.0 _SCP Extensions", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, + {"Processor Aggregator Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0} }; /******************************************************************************* @@ -107,9 +133,14 @@ static struct acpi_interface_info acpi_default_supported_interfaces[] = { acpi_status acpi_ut_initialize_interfaces(void) { + acpi_status status; u32 i; - (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); + status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + return (status); + } + acpi_gbl_supported_interfaces = acpi_default_supported_interfaces; /* Link the static list of supported interfaces */ @@ -131,34 +162,48 @@ acpi_status acpi_ut_initialize_interfaces(void) * * PARAMETERS: None * - * RETURN: None + * RETURN: Status * * DESCRIPTION: Delete all interfaces in the global list. Sets * acpi_gbl_supported_interfaces to NULL. * ******************************************************************************/ -void acpi_ut_interface_terminate(void) +acpi_status acpi_ut_interface_terminate(void) { + acpi_status status; struct acpi_interface_info *next_interface; - (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); - next_interface = acpi_gbl_supported_interfaces; + status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + return (status); + } + next_interface = acpi_gbl_supported_interfaces; while (next_interface) { acpi_gbl_supported_interfaces = next_interface->next; - /* Only interfaces added at runtime can be freed */ - if (next_interface->flags & ACPI_OSI_DYNAMIC) { + + /* Only interfaces added at runtime can be freed */ + ACPI_FREE(next_interface->name); ACPI_FREE(next_interface); + } else { + /* Interface is in static list. Reset it to invalid or valid. */ + + if (next_interface->flags & ACPI_OSI_DEFAULT_INVALID) { + next_interface->flags |= ACPI_OSI_INVALID; + } else { + next_interface->flags &= ~ACPI_OSI_INVALID; + } } next_interface = acpi_gbl_supported_interfaces; } acpi_os_release_mutex(acpi_gbl_osi_mutex); + return (AE_OK); } /******************************************************************************* @@ -267,6 +312,49 @@ acpi_status acpi_ut_remove_interface(acpi_string interface_name) /******************************************************************************* * + * FUNCTION: acpi_ut_update_interfaces + * + * PARAMETERS: action - Actions to be performed during the + * update + * + * RETURN: Status + * + * DESCRIPTION: Update _OSI interface strings, disabling or enabling OS vendor + * strings or/and feature group strings. + * Caller MUST hold acpi_gbl_osi_mutex + * + ******************************************************************************/ + +acpi_status acpi_ut_update_interfaces(u8 action) +{ + struct acpi_interface_info *next_interface; + + next_interface = acpi_gbl_supported_interfaces; + while (next_interface) { + if (((next_interface->flags & ACPI_OSI_FEATURE) && + (action & ACPI_FEATURE_STRINGS)) || + (!(next_interface->flags & ACPI_OSI_FEATURE) && + (action & ACPI_VENDOR_STRINGS))) { + if (action & ACPI_DISABLE_INTERFACES) { + + /* Mark the interfaces as invalid */ + + next_interface->flags |= ACPI_OSI_INVALID; + } else { + /* Mark the interfaces as valid */ + + next_interface->flags &= ~ACPI_OSI_INVALID; + } + } + + next_interface = next_interface->next; + } + + return (AE_OK); +} + +/******************************************************************************* + * * FUNCTION: acpi_ut_get_interface * * PARAMETERS: interface_name - The interface to find @@ -314,6 +402,7 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state * walk_state) union acpi_operand_object *return_desc; struct acpi_interface_info *interface_info; acpi_interface_handler interface_handler; + acpi_status status; u32 return_value; ACPI_FUNCTION_TRACE(ut_osi_implementation); @@ -335,7 +424,11 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state * walk_state) /* Default return value is 0, NOT SUPPORTED */ return_value = 0; - (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); + status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + acpi_ut_remove_reference(return_desc); + return_ACPI_STATUS(status); + } /* Lookup the interface in the global _OSI list */ diff --git a/drivers/acpi/acpica/utownerid.c b/drivers/acpi/acpica/utownerid.c new file mode 100644 index 00000000000..36bec57ebd2 --- /dev/null +++ b/drivers/acpi/acpica/utownerid.c @@ -0,0 +1,218 @@ +/******************************************************************************* + * + * Module Name: utownerid - Support for Table/Method Owner IDs + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utownerid") + +/******************************************************************************* + * + * FUNCTION: acpi_ut_allocate_owner_id + * + * PARAMETERS: owner_id - Where the new owner ID is returned + * + * RETURN: Status + * + * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to + * track objects created by the table or method, to be deleted + * when the method exits or the table is unloaded. + * + ******************************************************************************/ +acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) +{ + u32 i; + u32 j; + u32 k; + acpi_status status; + + ACPI_FUNCTION_TRACE(ut_allocate_owner_id); + + /* Guard against multiple allocations of ID to the same location */ + + if (*owner_id) { + ACPI_ERROR((AE_INFO, "Owner ID [0x%2.2X] already exists", + *owner_id)); + return_ACPI_STATUS(AE_ALREADY_EXISTS); + } + + /* Mutex for the global ID mask */ + + status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Find a free owner ID, cycle through all possible IDs on repeated + * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have + * to be scanned twice. + */ + for (i = 0, j = acpi_gbl_last_owner_id_index; + i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) { + if (j >= ACPI_NUM_OWNERID_MASKS) { + j = 0; /* Wraparound to start of mask array */ + } + + for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) { + if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) { + + /* There are no free IDs in this mask */ + + break; + } + + if (!(acpi_gbl_owner_id_mask[j] & (1 << k))) { + /* + * Found a free ID. The actual ID is the bit index plus one, + * making zero an invalid Owner ID. Save this as the last ID + * allocated and update the global ID mask. + */ + acpi_gbl_owner_id_mask[j] |= (1 << k); + + acpi_gbl_last_owner_id_index = (u8)j; + acpi_gbl_next_owner_id_offset = (u8)(k + 1); + + /* + * Construct encoded ID from the index and bit position + * + * Note: Last [j].k (bit 255) is never used and is marked + * permanently allocated (prevents +1 overflow) + */ + *owner_id = + (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j)); + + ACPI_DEBUG_PRINT((ACPI_DB_VALUES, + "Allocated OwnerId: %2.2X\n", + (unsigned int)*owner_id)); + goto exit; + } + } + + acpi_gbl_next_owner_id_offset = 0; + } + + /* + * All owner_ids have been allocated. This typically should + * not happen since the IDs are reused after deallocation. The IDs are + * allocated upon table load (one per table) and method execution, and + * they are released when a table is unloaded or a method completes + * execution. + * + * If this error happens, there may be very deep nesting of invoked control + * methods, or there may be a bug where the IDs are not released. + */ + status = AE_OWNER_ID_LIMIT; + ACPI_ERROR((AE_INFO, + "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT")); + +exit: + (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_release_owner_id + * + * PARAMETERS: owner_id_ptr - Pointer to a previously allocated owner_ID + * + * RETURN: None. No error is returned because we are either exiting a + * control method or unloading a table. Either way, we would + * ignore any error anyway. + * + * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255 + * + ******************************************************************************/ + +void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) +{ + acpi_owner_id owner_id = *owner_id_ptr; + acpi_status status; + u32 index; + u32 bit; + + ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id); + + /* Always clear the input owner_id (zero is an invalid ID) */ + + *owner_id_ptr = 0; + + /* Zero is not a valid owner_ID */ + + if (owner_id == 0) { + ACPI_ERROR((AE_INFO, "Invalid OwnerId: 0x%2.2X", owner_id)); + return_VOID; + } + + /* Mutex for the global ID mask */ + + status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); + if (ACPI_FAILURE(status)) { + return_VOID; + } + + /* Normalize the ID to zero */ + + owner_id--; + + /* Decode ID to index/offset pair */ + + index = ACPI_DIV_32(owner_id); + bit = 1 << ACPI_MOD_32(owner_id); + + /* Free the owner ID only if it is valid */ + + if (acpi_gbl_owner_id_mask[index] & bit) { + acpi_gbl_owner_id_mask[index] ^= bit; + } else { + ACPI_ERROR((AE_INFO, + "Release of non-allocated OwnerId: 0x%2.2X", + owner_id + 1)); + } + + (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); + return_VOID; +} diff --git a/drivers/acpi/acpica/utpredef.c b/drivers/acpi/acpica/utpredef.c new file mode 100644 index 00000000000..db30caff130 --- /dev/null +++ b/drivers/acpi/acpica/utpredef.c @@ -0,0 +1,399 @@ +/****************************************************************************** + * + * Module Name: utpredef - support functions for predefined names + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acpredef.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utpredef") + +/* + * Names for the types that can be returned by the predefined objects. + * Used for warning messages. Must be in the same order as the ACPI_RTYPEs + */ +static const char *ut_rtype_names[] = { + "/Integer", + "/String", + "/Buffer", + "/Package", + "/Reference", +}; + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_next_predefined_method + * + * PARAMETERS: this_name - Entry in the predefined method/name table + * + * RETURN: Pointer to next entry in predefined table. + * + * DESCRIPTION: Get the next entry in the predefine method table. Handles the + * cases where a package info entry follows a method name that + * returns a package. + * + ******************************************************************************/ + +const union acpi_predefined_info *acpi_ut_get_next_predefined_method(const union + acpi_predefined_info + *this_name) +{ + + /* + * Skip next entry in the table if this name returns a Package + * (next entry contains the package info) + */ + if ((this_name->info.expected_btypes & ACPI_RTYPE_PACKAGE) && + (this_name->info.expected_btypes != ACPI_RTYPE_ALL)) { + this_name++; + } + + this_name++; + return (this_name); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_match_predefined_method + * + * PARAMETERS: name - Name to find + * + * RETURN: Pointer to entry in predefined table. NULL indicates not found. + * + * DESCRIPTION: Check an object name against the predefined object list. + * + ******************************************************************************/ + +const union acpi_predefined_info *acpi_ut_match_predefined_method(char *name) +{ + const union acpi_predefined_info *this_name; + + /* Quick check for a predefined name, first character must be underscore */ + + if (name[0] != '_') { + return (NULL); + } + + /* Search info table for a predefined method/object name */ + + this_name = acpi_gbl_predefined_methods; + while (this_name->info.name[0]) { + if (ACPI_COMPARE_NAME(name, this_name->info.name)) { + return (this_name); + } + + this_name = acpi_ut_get_next_predefined_method(this_name); + } + + return (NULL); /* Not found */ +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_expected_return_types + * + * PARAMETERS: buffer - Where the formatted string is returned + * expected_Btypes - Bitfield of expected data types + * + * RETURN: Formatted string in Buffer. + * + * DESCRIPTION: Format the expected object types into a printable string. + * + ******************************************************************************/ + +void acpi_ut_get_expected_return_types(char *buffer, u32 expected_btypes) +{ + u32 this_rtype; + u32 i; + u32 j; + + if (!expected_btypes) { + ACPI_STRCPY(buffer, "NONE"); + return; + } + + j = 1; + buffer[0] = 0; + this_rtype = ACPI_RTYPE_INTEGER; + + for (i = 0; i < ACPI_NUM_RTYPES; i++) { + + /* If one of the expected types, concatenate the name of this type */ + + if (expected_btypes & this_rtype) { + ACPI_STRCAT(buffer, &ut_rtype_names[i][j]); + j = 0; /* Use name separator from now on */ + } + + this_rtype <<= 1; /* Next Rtype */ + } +} + +/******************************************************************************* + * + * The remaining functions are used by iASL and acpi_help only + * + ******************************************************************************/ + +#if (defined ACPI_ASL_COMPILER || defined ACPI_HELP_APP) +#include <stdio.h> +#include <string.h> + +/* Local prototypes */ + +static u32 acpi_ut_get_argument_types(char *buffer, u16 argument_types); + +/* Types that can be returned externally by a predefined name */ + +static const char *ut_external_type_names[] = /* Indexed by ACPI_TYPE_* */ +{ + ", UNSUPPORTED-TYPE", + ", Integer", + ", String", + ", Buffer", + ", Package" +}; + +/* Bit widths for resource descriptor predefined names */ + +static const char *ut_resource_type_names[] = { + "/1", + "/2", + "/3", + "/8", + "/16", + "/32", + "/64", + "/variable", +}; + +/******************************************************************************* + * + * FUNCTION: acpi_ut_match_resource_name + * + * PARAMETERS: name - Name to find + * + * RETURN: Pointer to entry in the resource table. NULL indicates not + * found. + * + * DESCRIPTION: Check an object name against the predefined resource + * descriptor object list. + * + ******************************************************************************/ + +const union acpi_predefined_info *acpi_ut_match_resource_name(char *name) +{ + const union acpi_predefined_info *this_name; + + /* Quick check for a predefined name, first character must be underscore */ + + if (name[0] != '_') { + return (NULL); + } + + /* Search info table for a predefined method/object name */ + + this_name = acpi_gbl_resource_names; + while (this_name->info.name[0]) { + if (ACPI_COMPARE_NAME(name, this_name->info.name)) { + return (this_name); + } + + this_name++; + } + + return (NULL); /* Not found */ +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_display_predefined_method + * + * PARAMETERS: buffer - Scratch buffer for this function + * this_name - Entry in the predefined method/name table + * multi_line - TRUE if output should be on >1 line + * + * RETURN: None + * + * DESCRIPTION: Display information about a predefined method. Number and + * type of the input arguments, and expected type(s) for the + * return value, if any. + * + ******************************************************************************/ + +void +acpi_ut_display_predefined_method(char *buffer, + const union acpi_predefined_info *this_name, + u8 multi_line) +{ + u32 arg_count; + + /* + * Get the argument count and the string buffer + * containing all argument types + */ + arg_count = acpi_ut_get_argument_types(buffer, + this_name->info.argument_list); + + if (multi_line) { + printf(" "); + } + + printf("%4.4s Requires %s%u argument%s", + this_name->info.name, + (this_name->info.argument_list & ARG_COUNT_IS_MINIMUM) ? + "(at least) " : "", arg_count, arg_count != 1 ? "s" : ""); + + /* Display the types for any arguments */ + + if (arg_count > 0) { + printf(" (%s)", buffer); + } + + if (multi_line) { + printf("\n "); + } + + /* Get the return value type(s) allowed */ + + if (this_name->info.expected_btypes) { + acpi_ut_get_expected_return_types(buffer, + this_name->info. + expected_btypes); + printf(" Return value types: %s\n", buffer); + } else { + printf(" No return value\n"); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_argument_types + * + * PARAMETERS: buffer - Where to return the formatted types + * argument_types - Types field for this method + * + * RETURN: count - the number of arguments required for this method + * + * DESCRIPTION: Format the required data types for this method (Integer, + * String, Buffer, or Package) and return the required argument + * count. + * + ******************************************************************************/ + +static u32 acpi_ut_get_argument_types(char *buffer, u16 argument_types) +{ + u16 this_argument_type; + u16 sub_index; + u16 arg_count; + u32 i; + + *buffer = 0; + sub_index = 2; + + /* First field in the types list is the count of args to follow */ + + arg_count = METHOD_GET_ARG_COUNT(argument_types); + if (arg_count > METHOD_PREDEF_ARGS_MAX) { + printf("**** Invalid argument count (%u) " + "in predefined info structure\n", arg_count); + return (arg_count); + } + + /* Get each argument from the list, convert to ascii, store to buffer */ + + for (i = 0; i < arg_count; i++) { + this_argument_type = METHOD_GET_NEXT_TYPE(argument_types); + + if (!this_argument_type + || (this_argument_type > METHOD_MAX_ARG_TYPE)) { + printf("**** Invalid argument type (%u) " + "in predefined info structure\n", + this_argument_type); + return (arg_count); + } + + strcat(buffer, + ut_external_type_names[this_argument_type] + sub_index); + sub_index = 0; + } + + return (arg_count); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_resource_bit_width + * + * PARAMETERS: buffer - Where the formatted string is returned + * types - Bitfield of expected data types + * + * RETURN: Count of return types. Formatted string in Buffer. + * + * DESCRIPTION: Format the resource bit widths into a printable string. + * + ******************************************************************************/ + +u32 acpi_ut_get_resource_bit_width(char *buffer, u16 types) +{ + u32 i; + u16 sub_index; + u32 found; + + *buffer = 0; + sub_index = 1; + found = 0; + + for (i = 0; i < NUM_RESOURCE_WIDTHS; i++) { + if (types & 1) { + strcat(buffer, &(ut_resource_type_names[i][sub_index])); + sub_index = 0; + found++; + } + + types >>= 1; + } + + return (found); +} +#endif diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c index 9d441ea7030..14cb6c0c8be 100644 --- a/drivers/acpi/acpica/utresrc.c +++ b/drivers/acpi/acpica/utresrc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,7 +47,8 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utresrc") -#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) + +#if defined(ACPI_DEBUG_OUTPUT) || defined (ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) /* * Strings used to decode resource descriptors. * Used by both the disassembler and the debugger resource dump routines @@ -127,7 +128,9 @@ const char *acpi_gbl_rw_decode[] = { const char *acpi_gbl_shr_decode[] = { "Exclusive", - "Shared" + "Shared", + "ExclusiveAndWake", /* ACPI 5.0 */ + "SharedAndWake" /* ACPI 5.0 */ }; const char *acpi_gbl_siz_decode[] = { @@ -356,13 +359,13 @@ static const u8 acpi_gbl_resource_types[] = { ACPI_SMALL_VARIABLE_LENGTH, /* 06 start_dependent_functions */ ACPI_FIXED_LENGTH, /* 07 end_dependent_functions */ ACPI_FIXED_LENGTH, /* 08 IO */ - ACPI_FIXED_LENGTH, /* 09 fixed_iO */ - ACPI_FIXED_LENGTH, /* 0_a fixed_dMA */ + ACPI_FIXED_LENGTH, /* 09 fixed_IO */ + ACPI_FIXED_LENGTH, /* 0A fixed_DMA */ 0, 0, 0, - ACPI_VARIABLE_LENGTH, /* 0_e vendor_short */ - ACPI_FIXED_LENGTH, /* 0_f end_tag */ + ACPI_VARIABLE_LENGTH, /* 0E vendor_short */ + ACPI_FIXED_LENGTH, /* 0F end_tag */ /* Large descriptors */ @@ -375,34 +378,24 @@ static const u8 acpi_gbl_resource_types[] = { ACPI_FIXED_LENGTH, /* 06 memory32_fixed */ ACPI_VARIABLE_LENGTH, /* 07 Dword* address */ ACPI_VARIABLE_LENGTH, /* 08 Word* address */ - ACPI_VARIABLE_LENGTH, /* 09 extended_iRQ */ - ACPI_VARIABLE_LENGTH, /* 0_a Qword* address */ - ACPI_FIXED_LENGTH, /* 0_b Extended* address */ - ACPI_VARIABLE_LENGTH, /* 0_c Gpio* */ + ACPI_VARIABLE_LENGTH, /* 09 extended_IRQ */ + ACPI_VARIABLE_LENGTH, /* 0A Qword* address */ + ACPI_FIXED_LENGTH, /* 0B Extended* address */ + ACPI_VARIABLE_LENGTH, /* 0C Gpio* */ 0, - ACPI_VARIABLE_LENGTH /* 0_e *serial_bus */ + ACPI_VARIABLE_LENGTH /* 0E *serial_bus */ }; -/* - * For the i_aSL compiler/disassembler, we don't want any error messages - * because the disassembler uses the resource validation code to determine - * if Buffer objects are actually Resource Templates. - */ -#ifdef ACPI_ASL_COMPILER -#define ACPI_RESOURCE_ERROR(plist) -#else -#define ACPI_RESOURCE_ERROR(plist) ACPI_ERROR(plist) -#endif - /******************************************************************************* * * FUNCTION: acpi_ut_walk_aml_resources * - * PARAMETERS: Aml - Pointer to the raw AML resource template - * aml_length - Length of the entire template - * user_function - Called once for each descriptor found. If - * NULL, a pointer to the end_tag is returned - * Context - Passed to user_function + * PARAMETERS: walk_state - Current walk info + * PARAMETERS: aml - Pointer to the raw AML resource template + * aml_length - Length of the entire template + * user_function - Called once for each descriptor found. If + * NULL, a pointer to the end_tag is returned + * context - Passed to user_function * * RETURN: Status * @@ -412,7 +405,8 @@ static const u8 acpi_gbl_resource_types[] = { ******************************************************************************/ acpi_status -acpi_ut_walk_aml_resources(u8 * aml, +acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state, + u8 *aml, acpi_size aml_length, acpi_walk_aml_callback user_function, void **context) { @@ -441,7 +435,8 @@ acpi_ut_walk_aml_resources(u8 * aml, /* Validate the Resource Type and Resource Length */ - status = acpi_ut_validate_resource(aml, &resource_index); + status = + acpi_ut_validate_resource(walk_state, aml, &resource_index); if (ACPI_FAILURE(status)) { /* * Exit on failure. Cannot continue because the descriptor length @@ -498,7 +493,8 @@ acpi_ut_walk_aml_resources(u8 * aml, /* Insert an end_tag anyway. acpi_rs_get_list_length always leaves room */ - (void)acpi_ut_validate_resource(end_tag, &resource_index); + (void)acpi_ut_validate_resource(walk_state, end_tag, + &resource_index); status = user_function(end_tag, 2, offset, resource_index, context); if (ACPI_FAILURE(status)) { @@ -513,9 +509,10 @@ acpi_ut_walk_aml_resources(u8 * aml, * * FUNCTION: acpi_ut_validate_resource * - * PARAMETERS: Aml - Pointer to the raw AML resource descriptor - * return_index - Where the resource index is returned. NULL - * if the index is not required. + * PARAMETERS: walk_state - Current walk info + * aml - Pointer to the raw AML resource descriptor + * return_index - Where the resource index is returned. NULL + * if the index is not required. * * RETURN: Status, and optionally the Index into the global resource tables * @@ -525,7 +522,9 @@ acpi_ut_walk_aml_resources(u8 * aml, * ******************************************************************************/ -acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) +acpi_status +acpi_ut_validate_resource(struct acpi_walk_state *walk_state, + void *aml, u8 *return_index) { union aml_resource *aml_resource; u8 resource_type; @@ -627,10 +626,12 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) if ((aml_resource->common_serial_bus.type == 0) || (aml_resource->common_serial_bus.type > AML_RESOURCE_MAX_SERIALBUSTYPE)) { - ACPI_RESOURCE_ERROR((AE_INFO, - "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X", - aml_resource->common_serial_bus. - type)); + if (walk_state) { + ACPI_ERROR((AE_INFO, + "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X", + aml_resource->common_serial_bus. + type)); + } return (AE_AML_INVALID_RESOURCE_TYPE); } } @@ -643,20 +644,24 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) return (AE_OK); - invalid_resource: +invalid_resource: - ACPI_RESOURCE_ERROR((AE_INFO, - "Invalid/unsupported resource descriptor: Type 0x%2.2X", - resource_type)); + if (walk_state) { + ACPI_ERROR((AE_INFO, + "Invalid/unsupported resource descriptor: Type 0x%2.2X", + resource_type)); + } return (AE_AML_INVALID_RESOURCE_TYPE); - bad_resource_length: +bad_resource_length: - ACPI_RESOURCE_ERROR((AE_INFO, - "Invalid resource descriptor length: Type " - "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X", - resource_type, resource_length, - minimum_resource_length)); + if (walk_state) { + ACPI_ERROR((AE_INFO, + "Invalid resource descriptor length: Type " + "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X", + resource_type, resource_length, + minimum_resource_length)); + } return (AE_AML_BAD_RESOURCE_LENGTH); } @@ -664,7 +669,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) * * FUNCTION: acpi_ut_get_resource_type * - * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * PARAMETERS: aml - Pointer to the raw AML resource descriptor * * RETURN: The Resource Type with no extraneous bits (except the * Large/Small descriptor bit -- this is left alone) @@ -698,7 +703,7 @@ u8 acpi_ut_get_resource_type(void *aml) * * FUNCTION: acpi_ut_get_resource_length * - * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * PARAMETERS: aml - Pointer to the raw AML resource descriptor * * RETURN: Byte Length * @@ -738,7 +743,7 @@ u16 acpi_ut_get_resource_length(void *aml) * * FUNCTION: acpi_ut_get_resource_header_length * - * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * PARAMETERS: aml - Pointer to the raw AML resource descriptor * * RETURN: Length of the AML header (depends on large/small descriptor) * @@ -763,7 +768,7 @@ u8 acpi_ut_get_resource_header_length(void *aml) * * FUNCTION: acpi_ut_get_descriptor_length * - * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * PARAMETERS: aml - Pointer to the raw AML resource descriptor * * RETURN: Byte length * @@ -800,8 +805,7 @@ u32 acpi_ut_get_descriptor_length(void *aml) ******************************************************************************/ acpi_status -acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc, - u8 ** end_tag) +acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 **end_tag) { acpi_status status; @@ -816,7 +820,7 @@ acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc, /* Validate the template and get a pointer to the end_tag */ - status = acpi_ut_walk_aml_resources(obj_desc->buffer.pointer, + status = acpi_ut_walk_aml_resources(NULL, obj_desc->buffer.pointer, obj_desc->buffer.length, NULL, (void **)end_tag); diff --git a/drivers/acpi/acpica/utstate.c b/drivers/acpi/acpica/utstate.c index 4267477c279..1cc97a752c1 100644 --- a/drivers/acpi/acpica/utstate.c +++ b/drivers/acpi/acpica/utstate.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,8 +51,8 @@ ACPI_MODULE_NAME("utstate") * * FUNCTION: acpi_ut_create_pkg_state_and_push * - * PARAMETERS: Object - Object to be added to the new state - * Action - Increment/Decrement + * PARAMETERS: object - Object to be added to the new state + * action - Increment/Decrement * state_list - List the state will be added to * * RETURN: Status @@ -85,7 +85,7 @@ acpi_ut_create_pkg_state_and_push(void *internal_object, * FUNCTION: acpi_ut_push_generic_state * * PARAMETERS: list_head - Head of the state stack - * State - State object to push + * state - State object to push * * RETURN: None * @@ -97,14 +97,13 @@ void acpi_ut_push_generic_state(union acpi_generic_state **list_head, union acpi_generic_state *state) { - ACPI_FUNCTION_TRACE(ut_push_generic_state); + ACPI_FUNCTION_ENTRY(); /* Push the state object onto the front of the list (stack) */ state->common.next = *list_head; *list_head = state; - - return_VOID; + return; } /******************************************************************************* @@ -124,7 +123,7 @@ union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE(ut_pop_generic_state); + ACPI_FUNCTION_ENTRY(); /* Remove the state object at the head of the list (stack) */ @@ -136,7 +135,7 @@ union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state *list_head = state->common.next; } - return_PTR(state); + return (state); } /******************************************************************************* @@ -147,7 +146,7 @@ union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state * * RETURN: The new state object. NULL on failure. * - * DESCRIPTION: Create a generic state object. Attempt to obtain one from + * DESCRIPTION: Create a generic state object. Attempt to obtain one from * the global state cache; If none available, create a new one. * ******************************************************************************/ @@ -162,7 +161,6 @@ union acpi_generic_state *acpi_ut_create_generic_state(void) if (state) { /* Initialize */ - memset(state, 0, sizeof(union acpi_generic_state)); state->common.descriptor_type = ACPI_DESC_TYPE_STATE; } @@ -186,13 +184,13 @@ struct acpi_thread_state *acpi_ut_create_thread_state(void) { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE(ut_create_thread_state); + ACPI_FUNCTION_ENTRY(); /* Create the generic state object */ state = acpi_ut_create_generic_state(); if (!state) { - return_PTR(NULL); + return (NULL); } /* Init fields specific to the update struct */ @@ -207,15 +205,15 @@ struct acpi_thread_state *acpi_ut_create_thread_state(void) state->thread.thread_id = (acpi_thread_id) 1; } - return_PTR((struct acpi_thread_state *)state); + return ((struct acpi_thread_state *)state); } /******************************************************************************* * * FUNCTION: acpi_ut_create_update_state * - * PARAMETERS: Object - Initial Object to be installed in the state - * Action - Update action to be performed + * PARAMETERS: object - Initial Object to be installed in the state + * action - Update action to be performed * * RETURN: New state object, null on failure * @@ -230,13 +228,13 @@ union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE_PTR(ut_create_update_state, object); + ACPI_FUNCTION_ENTRY(); /* Create the generic state object */ state = acpi_ut_create_generic_state(); if (!state) { - return_PTR(NULL); + return (NULL); } /* Init fields specific to the update struct */ @@ -244,16 +242,15 @@ union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object state->common.descriptor_type = ACPI_DESC_TYPE_STATE_UPDATE; state->update.object = object; state->update.value = action; - - return_PTR(state); + return (state); } /******************************************************************************* * * FUNCTION: acpi_ut_create_pkg_state * - * PARAMETERS: Object - Initial Object to be installed in the state - * Action - Update action to be performed + * PARAMETERS: object - Initial Object to be installed in the state + * action - Update action to be performed * * RETURN: New state object, null on failure * @@ -267,13 +264,13 @@ union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object, { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE_PTR(ut_create_pkg_state, internal_object); + ACPI_FUNCTION_ENTRY(); /* Create the generic state object */ state = acpi_ut_create_generic_state(); if (!state) { - return_PTR(NULL); + return (NULL); } /* Init fields specific to the update struct */ @@ -283,8 +280,7 @@ union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object, state->pkg.dest_object = external_object; state->pkg.index = index; state->pkg.num_packages = 1; - - return_PTR(state); + return (state); } /******************************************************************************* @@ -304,28 +300,27 @@ union acpi_generic_state *acpi_ut_create_control_state(void) { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE(ut_create_control_state); + ACPI_FUNCTION_ENTRY(); /* Create the generic state object */ state = acpi_ut_create_generic_state(); if (!state) { - return_PTR(NULL); + return (NULL); } /* Init fields specific to the control struct */ state->common.descriptor_type = ACPI_DESC_TYPE_STATE_CONTROL; state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING; - - return_PTR(state); + return (state); } /******************************************************************************* * * FUNCTION: acpi_ut_delete_generic_state * - * PARAMETERS: State - The state object to be deleted + * PARAMETERS: state - The state object to be deleted * * RETURN: None * @@ -336,12 +331,12 @@ union acpi_generic_state *acpi_ut_create_control_state(void) void acpi_ut_delete_generic_state(union acpi_generic_state *state) { - ACPI_FUNCTION_TRACE(ut_delete_generic_state); + ACPI_FUNCTION_ENTRY(); /* Ignore null state */ if (state) { (void)acpi_os_release_object(acpi_gbl_state_cache, state); } - return_VOID; + return; } diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c new file mode 100644 index 00000000000..6dc54b3c28b --- /dev/null +++ b/drivers/acpi/acpica/utstring.c @@ -0,0 +1,648 @@ +/******************************************************************************* + * + * Module Name: utstring - Common functions for strings and characters + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utstring") + +/* + * Non-ANSI C library functions - strlwr, strupr, stricmp, and a 64-bit + * version of strtoul. + */ +#ifdef ACPI_ASL_COMPILER +/******************************************************************************* + * + * FUNCTION: acpi_ut_strlwr (strlwr) + * + * PARAMETERS: src_string - The source string to convert + * + * RETURN: None + * + * DESCRIPTION: Convert string to lowercase + * + * NOTE: This is not a POSIX function, so it appears here, not in utclib.c + * + ******************************************************************************/ +void acpi_ut_strlwr(char *src_string) +{ + char *string; + + ACPI_FUNCTION_ENTRY(); + + if (!src_string) { + return; + } + + /* Walk entire string, lowercasing the letters */ + + for (string = src_string; *string; string++) { + *string = (char)ACPI_TOLOWER(*string); + } + + return; +} + +/****************************************************************************** + * + * FUNCTION: acpi_ut_stricmp (stricmp) + * + * PARAMETERS: string1 - first string to compare + * string2 - second string to compare + * + * RETURN: int that signifies string relationship. Zero means strings + * are equal. + * + * DESCRIPTION: Implementation of the non-ANSI stricmp function (compare + * strings with no case sensitivity) + * + ******************************************************************************/ + +int acpi_ut_stricmp(char *string1, char *string2) +{ + int c1; + int c2; + + do { + c1 = tolower((int)*string1); + c2 = tolower((int)*string2); + + string1++; + string2++; + } + while ((c1 == c2) && (c1)); + + return (c1 - c2); +} +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_ut_strupr (strupr) + * + * PARAMETERS: src_string - The source string to convert + * + * RETURN: None + * + * DESCRIPTION: Convert string to uppercase + * + * NOTE: This is not a POSIX function, so it appears here, not in utclib.c + * + ******************************************************************************/ + +void acpi_ut_strupr(char *src_string) +{ + char *string; + + ACPI_FUNCTION_ENTRY(); + + if (!src_string) { + return; + } + + /* Walk entire string, uppercasing the letters */ + + for (string = src_string; *string; string++) { + *string = (char)ACPI_TOUPPER(*string); + } + + return; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_strtoul64 + * + * PARAMETERS: string - Null terminated string + * base - Radix of the string: 16 or ACPI_ANY_BASE; + * ACPI_ANY_BASE means 'in behalf of to_integer' + * ret_integer - Where the converted integer is returned + * + * RETURN: Status and Converted value + * + * DESCRIPTION: Convert a string into an unsigned value. Performs either a + * 32-bit or 64-bit conversion, depending on the current mode + * of the interpreter. + * NOTE: Does not support Octal strings, not needed. + * + ******************************************************************************/ + +acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) +{ + u32 this_digit = 0; + u64 return_value = 0; + u64 quotient; + u64 dividend; + u32 to_integer_op = (base == ACPI_ANY_BASE); + u32 mode32 = (acpi_gbl_integer_byte_width == 4); + u8 valid_digits = 0; + u8 sign_of0x = 0; + u8 term = 0; + + ACPI_FUNCTION_TRACE_STR(ut_stroul64, string); + + switch (base) { + case ACPI_ANY_BASE: + case 16: + + break; + + default: + + /* Invalid Base */ + + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (!string) { + goto error_exit; + } + + /* Skip over any white space in the buffer */ + + while ((*string) && (ACPI_IS_SPACE(*string) || *string == '\t')) { + string++; + } + + if (to_integer_op) { + /* + * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'. + * We need to determine if it is decimal or hexadecimal. + */ + if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { + sign_of0x = 1; + base = 16; + + /* Skip over the leading '0x' */ + string += 2; + } else { + base = 10; + } + } + + /* Any string left? Check that '0x' is not followed by white space. */ + + if (!(*string) || ACPI_IS_SPACE(*string) || *string == '\t') { + if (to_integer_op) { + goto error_exit; + } else { + goto all_done; + } + } + + /* + * Perform a 32-bit or 64-bit conversion, depending upon the current + * execution mode of the interpreter + */ + dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX; + + /* Main loop: convert the string to a 32- or 64-bit integer */ + + while (*string) { + if (ACPI_IS_DIGIT(*string)) { + + /* Convert ASCII 0-9 to Decimal value */ + + this_digit = ((u8)*string) - '0'; + } else if (base == 10) { + + /* Digit is out of range; possible in to_integer case only */ + + term = 1; + } else { + this_digit = (u8)ACPI_TOUPPER(*string); + if (ACPI_IS_XDIGIT((char)this_digit)) { + + /* Convert ASCII Hex char to value */ + + this_digit = this_digit - 'A' + 10; + } else { + term = 1; + } + } + + if (term) { + if (to_integer_op) { + goto error_exit; + } else { + break; + } + } else if ((valid_digits == 0) && (this_digit == 0) + && !sign_of0x) { + + /* Skip zeros */ + string++; + continue; + } + + valid_digits++; + + if (sign_of0x + && ((valid_digits > 16) + || ((valid_digits > 8) && mode32))) { + /* + * This is to_integer operation case. + * No any restrictions for string-to-integer conversion, + * see ACPI spec. + */ + goto error_exit; + } + + /* Divide the digit into the correct position */ + + (void)acpi_ut_short_divide((dividend - (u64)this_digit), + base, "ient, NULL); + + if (return_value > quotient) { + if (to_integer_op) { + goto error_exit; + } else { + break; + } + } + + return_value *= base; + return_value += this_digit; + string++; + } + + /* All done, normal exit */ + +all_done: + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64(return_value))); + + *ret_integer = return_value; + return_ACPI_STATUS(AE_OK); + +error_exit: + /* Base was set/validated above */ + + if (base == 10) { + return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT); + } else { + return_ACPI_STATUS(AE_BAD_HEX_CONSTANT); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_print_string + * + * PARAMETERS: string - Null terminated ASCII string + * max_length - Maximum output length. Used to constrain the + * length of strings during debug output only. + * + * RETURN: None + * + * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape + * sequences. + * + ******************************************************************************/ + +void acpi_ut_print_string(char *string, u16 max_length) +{ + u32 i; + + if (!string) { + acpi_os_printf("<\"NULL STRING PTR\">"); + return; + } + + acpi_os_printf("\""); + for (i = 0; (i < max_length) && string[i]; i++) { + + /* Escape sequences */ + + switch (string[i]) { + case 0x07: + + acpi_os_printf("\\a"); /* BELL */ + break; + + case 0x08: + + acpi_os_printf("\\b"); /* BACKSPACE */ + break; + + case 0x0C: + + acpi_os_printf("\\f"); /* FORMFEED */ + break; + + case 0x0A: + + acpi_os_printf("\\n"); /* LINEFEED */ + break; + + case 0x0D: + + acpi_os_printf("\\r"); /* CARRIAGE RETURN */ + break; + + case 0x09: + + acpi_os_printf("\\t"); /* HORIZONTAL TAB */ + break; + + case 0x0B: + + acpi_os_printf("\\v"); /* VERTICAL TAB */ + break; + + case '\'': /* Single Quote */ + case '\"': /* Double Quote */ + case '\\': /* Backslash */ + + acpi_os_printf("\\%c", (int)string[i]); + break; + + default: + + /* Check for printable character or hex escape */ + + if (ACPI_IS_PRINT(string[i])) { + /* This is a normal character */ + + acpi_os_printf("%c", (int)string[i]); + } else { + /* All others will be Hex escapes */ + + acpi_os_printf("\\x%2.2X", (s32) string[i]); + } + break; + } + } + acpi_os_printf("\""); + + if (i == max_length && string[i]) { + acpi_os_printf("..."); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_valid_acpi_char + * + * PARAMETERS: char - The character to be examined + * position - Byte position (0-3) + * + * RETURN: TRUE if the character is valid, FALSE otherwise + * + * DESCRIPTION: Check for a valid ACPI character. Must be one of: + * 1) Upper case alpha + * 2) numeric + * 3) underscore + * + * We allow a '!' as the last character because of the ASF! table + * + ******************************************************************************/ + +u8 acpi_ut_valid_acpi_char(char character, u32 position) +{ + + if (!((character >= 'A' && character <= 'Z') || + (character >= '0' && character <= '9') || (character == '_'))) { + + /* Allow a '!' in the last position */ + + if (character == '!' && position == 3) { + return (TRUE); + } + + return (FALSE); + } + + return (TRUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_valid_acpi_name + * + * PARAMETERS: name - The name to be examined. Does not have to + * be NULL terminated string. + * + * RETURN: TRUE if the name is valid, FALSE otherwise + * + * DESCRIPTION: Check for a valid ACPI name. Each character must be one of: + * 1) Upper case alpha + * 2) numeric + * 3) underscore + * + ******************************************************************************/ + +u8 acpi_ut_valid_acpi_name(char *name) +{ + u32 i; + + ACPI_FUNCTION_ENTRY(); + + for (i = 0; i < ACPI_NAME_SIZE; i++) { + if (!acpi_ut_valid_acpi_char(name[i], i)) { + return (FALSE); + } + } + + return (TRUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_repair_name + * + * PARAMETERS: name - The ACPI name to be repaired + * + * RETURN: Repaired version of the name + * + * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and + * return the new name. NOTE: the Name parameter must reside in + * read/write memory, cannot be a const. + * + * An ACPI Name must consist of valid ACPI characters. We will repair the name + * if necessary because we don't want to abort because of this, but we want + * all namespace names to be printable. A warning message is appropriate. + * + * This issue came up because there are in fact machines that exhibit + * this problem, and we want to be able to enable ACPI support for them, + * even though there are a few bad names. + * + ******************************************************************************/ + +void acpi_ut_repair_name(char *name) +{ + u32 i; + u8 found_bad_char = FALSE; + u32 original_name; + + ACPI_FUNCTION_NAME(ut_repair_name); + + ACPI_MOVE_NAME(&original_name, name); + + /* Check each character in the name */ + + for (i = 0; i < ACPI_NAME_SIZE; i++) { + if (acpi_ut_valid_acpi_char(name[i], i)) { + continue; + } + + /* + * Replace a bad character with something printable, yet technically + * still invalid. This prevents any collisions with existing "good" + * names in the namespace. + */ + name[i] = '*'; + found_bad_char = TRUE; + } + + if (found_bad_char) { + + /* Report warning only if in strict mode or debug mode */ + + if (!acpi_gbl_enable_interpreter_slack) { + ACPI_WARNING((AE_INFO, + "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]", + original_name, name)); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]", + original_name, name)); + } + } +} + +#if defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP +/******************************************************************************* + * + * FUNCTION: ut_convert_backslashes + * + * PARAMETERS: pathname - File pathname string to be converted + * + * RETURN: Modifies the input Pathname + * + * DESCRIPTION: Convert all backslashes (0x5C) to forward slashes (0x2F) within + * the entire input file pathname string. + * + ******************************************************************************/ + +void ut_convert_backslashes(char *pathname) +{ + + if (!pathname) { + return; + } + + while (*pathname) { + if (*pathname == '\\') { + *pathname = '/'; + } + + pathname++; + } +} +#endif + +#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION) +/******************************************************************************* + * + * FUNCTION: acpi_ut_safe_strcpy, acpi_ut_safe_strcat, acpi_ut_safe_strncat + * + * PARAMETERS: Adds a "DestSize" parameter to each of the standard string + * functions. This is the size of the Destination buffer. + * + * RETURN: TRUE if the operation would overflow the destination buffer. + * + * DESCRIPTION: Safe versions of standard Clib string functions. Ensure that + * the result of the operation will not overflow the output string + * buffer. + * + * NOTE: These functions are typically only helpful for processing + * user input and command lines. For most ACPICA code, the + * required buffer length is precisely calculated before buffer + * allocation, so the use of these functions is unnecessary. + * + ******************************************************************************/ + +u8 acpi_ut_safe_strcpy(char *dest, acpi_size dest_size, char *source) +{ + + if (ACPI_STRLEN(source) >= dest_size) { + return (TRUE); + } + + ACPI_STRCPY(dest, source); + return (FALSE); +} + +u8 acpi_ut_safe_strcat(char *dest, acpi_size dest_size, char *source) +{ + + if ((ACPI_STRLEN(dest) + ACPI_STRLEN(source)) >= dest_size) { + return (TRUE); + } + + ACPI_STRCAT(dest, source); + return (FALSE); +} + +u8 +acpi_ut_safe_strncat(char *dest, + acpi_size dest_size, + char *source, acpi_size max_transfer_length) +{ + acpi_size actual_transfer_length; + + actual_transfer_length = + ACPI_MIN(max_transfer_length, ACPI_STRLEN(source)); + + if ((ACPI_STRLEN(dest) + actual_transfer_length) >= dest_size) { + return (TRUE); + } + + ACPI_STRNCAT(dest, source, max_transfer_length); + return (FALSE); +} +#endif diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c new file mode 100644 index 00000000000..7d0ee969d78 --- /dev/null +++ b/drivers/acpi/acpica/uttrack.c @@ -0,0 +1,722 @@ +/****************************************************************************** + * + * Module Name: uttrack - Memory allocation tracking routines (debug only) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +/* + * These procedures are used for tracking memory leaks in the subsystem, and + * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set. + * + * Each memory allocation is tracked via a doubly linked list. Each + * element contains the caller's component, module name, function name, and + * line number. acpi_ut_allocate and acpi_ut_allocate_zeroed call + * acpi_ut_track_allocation to add an element to the list; deletion + * occurs in the body of acpi_ut_free. + */ + +#include <acpi/acpi.h> +#include "accommon.h" + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("uttrack") + +/* Local prototypes */ +static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct + acpi_debug_mem_block + *allocation); + +static acpi_status +acpi_ut_track_allocation(struct acpi_debug_mem_block *address, + acpi_size size, + u8 alloc_type, + u32 component, const char *module, u32 line); + +static acpi_status +acpi_ut_remove_allocation(struct acpi_debug_mem_block *address, + u32 component, const char *module, u32 line); + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_list + * + * PARAMETERS: cache_name - Ascii name for the cache + * object_size - Size of each cached object + * return_cache - Where the new cache object is returned + * + * RETURN: Status + * + * DESCRIPTION: Create a local memory list for tracking purposed + * + ******************************************************************************/ + +acpi_status +acpi_ut_create_list(char *list_name, + u16 object_size, struct acpi_memory_list **return_cache) +{ + struct acpi_memory_list *cache; + + cache = acpi_os_allocate(sizeof(struct acpi_memory_list)); + if (!cache) { + return (AE_NO_MEMORY); + } + + ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list)); + + cache->list_name = list_name; + cache->object_size = object_size; + + *return_cache = cache; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_allocate_and_track + * + * PARAMETERS: size - Size of the allocation + * component - Component type of caller + * module - Source file name of caller + * line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: The subsystem's equivalent of malloc. + * + ******************************************************************************/ + +void *acpi_ut_allocate_and_track(acpi_size size, + u32 component, const char *module, u32 line) +{ + struct acpi_debug_mem_block *allocation; + acpi_status status; + + /* Check for an inadvertent size of zero bytes */ + + if (!size) { + ACPI_WARNING((module, line, + "Attempt to allocate zero bytes, allocating 1 byte")); + size = 1; + } + + allocation = + acpi_os_allocate(size + sizeof(struct acpi_debug_mem_header)); + if (!allocation) { + + /* Report allocation error */ + + ACPI_WARNING((module, line, + "Could not allocate size %u", (u32)size)); + + return (NULL); + } + + status = acpi_ut_track_allocation(allocation, size, + ACPI_MEM_MALLOC, component, module, + line); + if (ACPI_FAILURE(status)) { + acpi_os_free(allocation); + return (NULL); + } + + acpi_gbl_global_list->total_allocated++; + acpi_gbl_global_list->total_size += (u32)size; + acpi_gbl_global_list->current_total_size += (u32)size; + if (acpi_gbl_global_list->current_total_size > + acpi_gbl_global_list->max_occupied) { + acpi_gbl_global_list->max_occupied = + acpi_gbl_global_list->current_total_size; + } + + return ((void *)&allocation->user_space); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_allocate_zeroed_and_track + * + * PARAMETERS: size - Size of the allocation + * component - Component type of caller + * module - Source file name of caller + * line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: Subsystem equivalent of calloc. + * + ******************************************************************************/ + +void *acpi_ut_allocate_zeroed_and_track(acpi_size size, + u32 component, + const char *module, u32 line) +{ + struct acpi_debug_mem_block *allocation; + acpi_status status; + + /* Check for an inadvertent size of zero bytes */ + + if (!size) { + ACPI_WARNING((module, line, + "Attempt to allocate zero bytes, allocating 1 byte")); + size = 1; + } + + allocation = + acpi_os_allocate_zeroed(size + + sizeof(struct acpi_debug_mem_header)); + if (!allocation) { + + /* Report allocation error */ + + ACPI_ERROR((module, line, + "Could not allocate size %u", (u32)size)); + return (NULL); + } + + status = acpi_ut_track_allocation(allocation, size, + ACPI_MEM_CALLOC, component, module, + line); + if (ACPI_FAILURE(status)) { + acpi_os_free(allocation); + return (NULL); + } + + acpi_gbl_global_list->total_allocated++; + acpi_gbl_global_list->total_size += (u32)size; + acpi_gbl_global_list->current_total_size += (u32)size; + if (acpi_gbl_global_list->current_total_size > + acpi_gbl_global_list->max_occupied) { + acpi_gbl_global_list->max_occupied = + acpi_gbl_global_list->current_total_size; + } + + return ((void *)&allocation->user_space); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_free_and_track + * + * PARAMETERS: allocation - Address of the memory to deallocate + * component - Component type of caller + * module - Source file name of caller + * line - Line number of caller + * + * RETURN: None + * + * DESCRIPTION: Frees the memory at Allocation + * + ******************************************************************************/ + +void +acpi_ut_free_and_track(void *allocation, + u32 component, const char *module, u32 line) +{ + struct acpi_debug_mem_block *debug_block; + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ut_free, allocation); + + if (NULL == allocation) { + ACPI_ERROR((module, line, "Attempt to delete a NULL address")); + + return_VOID; + } + + debug_block = ACPI_CAST_PTR(struct acpi_debug_mem_block, + (((char *)allocation) - + sizeof(struct acpi_debug_mem_header))); + + acpi_gbl_global_list->total_freed++; + acpi_gbl_global_list->current_total_size -= debug_block->size; + + status = acpi_ut_remove_allocation(debug_block, + component, module, line); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "Could not free memory")); + } + + acpi_os_free(debug_block); + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed (block %p)\n", + allocation, debug_block)); + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_find_allocation + * + * PARAMETERS: allocation - Address of allocated memory + * + * RETURN: Three cases: + * 1) List is empty, NULL is returned. + * 2) Element was found. Returns Allocation parameter. + * 3) Element was not found. Returns position where it should be + * inserted into the list. + * + * DESCRIPTION: Searches for an element in the global allocation tracking list. + * If the element is not found, returns the location within the + * list where the element should be inserted. + * + * Note: The list is ordered by larger-to-smaller addresses. + * + * This global list is used to detect memory leaks in ACPICA as + * well as other issues such as an attempt to release the same + * internal object more than once. Although expensive as far + * as cpu time, this list is much more helpful for finding these + * types of issues than using memory leak detectors outside of + * the ACPICA code. + * + ******************************************************************************/ + +static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct + acpi_debug_mem_block + *allocation) +{ + struct acpi_debug_mem_block *element; + + element = acpi_gbl_global_list->list_head; + if (!element) { + return (NULL); + } + + /* + * Search for the address. + * + * Note: List is ordered by larger-to-smaller addresses, on the + * assumption that a new allocation usually has a larger address + * than previous allocations. + */ + while (element > allocation) { + + /* Check for end-of-list */ + + if (!element->next) { + return (element); + } + + element = element->next; + } + + if (element == allocation) { + return (element); + } + + return (element->previous); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_track_allocation + * + * PARAMETERS: allocation - Address of allocated memory + * size - Size of the allocation + * alloc_type - MEM_MALLOC or MEM_CALLOC + * component - Component type of caller + * module - Source file name of caller + * line - Line number of caller + * + * RETURN: Status + * + * DESCRIPTION: Inserts an element into the global allocation tracking list. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation, + acpi_size size, + u8 alloc_type, + u32 component, const char *module, u32 line) +{ + struct acpi_memory_list *mem_list; + struct acpi_debug_mem_block *element; + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE_PTR(ut_track_allocation, allocation); + + if (acpi_gbl_disable_mem_tracking) { + return_ACPI_STATUS(AE_OK); + } + + mem_list = acpi_gbl_global_list; + status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Search the global list for this address to make sure it is not + * already present. This will catch several kinds of problems. + */ + element = acpi_ut_find_allocation(allocation); + if (element == allocation) { + ACPI_ERROR((AE_INFO, + "UtTrackAllocation: Allocation (%p) already present in global list!", + allocation)); + goto unlock_and_exit; + } + + /* Fill in the instance data */ + + allocation->size = (u32)size; + allocation->alloc_type = alloc_type; + allocation->component = component; + allocation->line = line; + + ACPI_STRNCPY(allocation->module, module, ACPI_MAX_MODULE_NAME); + allocation->module[ACPI_MAX_MODULE_NAME - 1] = 0; + + if (!element) { + + /* Insert at list head */ + + if (mem_list->list_head) { + ((struct acpi_debug_mem_block *)(mem_list->list_head))-> + previous = allocation; + } + + allocation->next = mem_list->list_head; + allocation->previous = NULL; + + mem_list->list_head = allocation; + } else { + /* Insert after element */ + + allocation->next = element->next; + allocation->previous = element; + + if (element->next) { + (element->next)->previous = allocation; + } + + element->next = allocation; + } + +unlock_and_exit: + status = acpi_ut_release_mutex(ACPI_MTX_MEMORY); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_remove_allocation + * + * PARAMETERS: allocation - Address of allocated memory + * component - Component type of caller + * module - Source file name of caller + * line - Line number of caller + * + * RETURN: Status + * + * DESCRIPTION: Deletes an element from the global allocation tracking list. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation, + u32 component, const char *module, u32 line) +{ + struct acpi_memory_list *mem_list; + acpi_status status; + + ACPI_FUNCTION_NAME(ut_remove_allocation); + + if (acpi_gbl_disable_mem_tracking) { + return (AE_OK); + } + + mem_list = acpi_gbl_global_list; + if (NULL == mem_list->list_head) { + + /* No allocations! */ + + ACPI_ERROR((module, line, + "Empty allocation list, nothing to free!")); + + return (AE_OK); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Unlink */ + + if (allocation->previous) { + (allocation->previous)->next = allocation->next; + } else { + mem_list->list_head = allocation->next; + } + + if (allocation->next) { + (allocation->next)->previous = allocation->previous; + } + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n", + &allocation->user_space, allocation->size)); + + /* Mark the segment as deleted */ + + ACPI_MEMSET(&allocation->user_space, 0xEA, allocation->size); + + status = acpi_ut_release_mutex(ACPI_MTX_MEMORY); + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_dump_allocation_info + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Print some info about the outstanding allocations. + * + ******************************************************************************/ + +void acpi_ut_dump_allocation_info(void) +{ +/* + struct acpi_memory_list *mem_list; +*/ + + ACPI_FUNCTION_TRACE(ut_dump_allocation_info); + +/* + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Current allocations", + mem_list->current_count, + ROUND_UP_TO_1K (mem_list->current_size))); + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations", + mem_list->max_concurrent_count, + ROUND_UP_TO_1K (mem_list->max_concurrent_size))); + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects", + running_object_count, + ROUND_UP_TO_1K (running_object_size))); + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Total (all) allocations", + running_alloc_count, + ROUND_UP_TO_1K (running_alloc_size))); + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Current Nodes", + acpi_gbl_current_node_count, + ROUND_UP_TO_1K (acpi_gbl_current_node_size))); + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Max Nodes", + acpi_gbl_max_concurrent_node_count, + ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count * + sizeof (struct acpi_namespace_node))))); +*/ + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_dump_allocations + * + * PARAMETERS: component - Component(s) to dump info for. + * module - Module to dump info for. NULL means all. + * + * RETURN: None + * + * DESCRIPTION: Print a list of all outstanding allocations. + * + ******************************************************************************/ + +void acpi_ut_dump_allocations(u32 component, const char *module) +{ + struct acpi_debug_mem_block *element; + union acpi_descriptor *descriptor; + u32 num_outstanding = 0; + u8 descriptor_type; + + ACPI_FUNCTION_TRACE(ut_dump_allocations); + + if (acpi_gbl_disable_mem_tracking) { + return_VOID; + } + + /* + * Walk the allocation list. + */ + if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) { + return_VOID; + } + + element = acpi_gbl_global_list->list_head; + while (element) { + if ((element->component & component) && + ((module == NULL) + || (0 == ACPI_STRCMP(module, element->module)))) { + descriptor = + ACPI_CAST_PTR(union acpi_descriptor, + &element->user_space); + + if (element->size < + sizeof(struct acpi_common_descriptor)) { + acpi_os_printf("%p Length 0x%04X %9.9s-%u " + "[Not a Descriptor - too small]\n", + descriptor, element->size, + element->module, element->line); + } else { + /* Ignore allocated objects that are in a cache */ + + if (ACPI_GET_DESCRIPTOR_TYPE(descriptor) != + ACPI_DESC_TYPE_CACHED) { + acpi_os_printf + ("%p Length 0x%04X %9.9s-%u [%s] ", + descriptor, element->size, + element->module, element->line, + acpi_ut_get_descriptor_name + (descriptor)); + + /* Validate the descriptor type using Type field and length */ + + descriptor_type = 0; /* Not a valid descriptor type */ + + switch (ACPI_GET_DESCRIPTOR_TYPE + (descriptor)) { + case ACPI_DESC_TYPE_OPERAND: + + if (element->size == + sizeof(union + acpi_operand_object)) + { + descriptor_type = + ACPI_DESC_TYPE_OPERAND; + } + break; + + case ACPI_DESC_TYPE_PARSER: + + if (element->size == + sizeof(union + acpi_parse_object)) { + descriptor_type = + ACPI_DESC_TYPE_PARSER; + } + break; + + case ACPI_DESC_TYPE_NAMED: + + if (element->size == + sizeof(struct + acpi_namespace_node)) + { + descriptor_type = + ACPI_DESC_TYPE_NAMED; + } + break; + + default: + + break; + } + + /* Display additional info for the major descriptor types */ + + switch (descriptor_type) { + case ACPI_DESC_TYPE_OPERAND: + + acpi_os_printf + ("%12.12s RefCount 0x%04X\n", + acpi_ut_get_type_name + (descriptor->object.common. + type), + descriptor->object.common. + reference_count); + break; + + case ACPI_DESC_TYPE_PARSER: + + acpi_os_printf + ("AmlOpcode 0x%04hX\n", + descriptor->op.asl. + aml_opcode); + break; + + case ACPI_DESC_TYPE_NAMED: + + acpi_os_printf("%4.4s\n", + acpi_ut_get_node_name + (&descriptor-> + node)); + break; + + default: + + acpi_os_printf("\n"); + break; + } + } + } + + num_outstanding++; + } + + element = element->next; + } + + (void)acpi_ut_release_mutex(ACPI_MTX_MEMORY); + + /* Print summary */ + + if (!num_outstanding) { + ACPI_INFO((AE_INFO, "No outstanding allocations")); + } else { + ACPI_ERROR((AE_INFO, "%u(0x%X) Outstanding allocations", + num_outstanding, num_outstanding)); + } + + return_VOID; +} + +#endif /* ACPI_DBG_TRACK_ALLOCATIONS */ diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index 644e8c8ebc4..502a8492dc8 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c @@ -1,11 +1,11 @@ /****************************************************************************** * - * Module Name: utxface - External interfaces for "global" ACPI functions + * Module Name: utxface - External interfaces, miscellaneous utility functions * *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,279 +41,15 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include <linux/export.h> +#define EXPORT_ACPI_INTERFACES + #include <acpi/acpi.h> #include "accommon.h" -#include "acevents.h" -#include "acnamesp.h" #include "acdebug.h" -#include "actables.h" -#include "acinterp.h" #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utxface") -#ifndef ACPI_ASL_COMPILER -/******************************************************************************* - * - * FUNCTION: acpi_initialize_subsystem - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Initializes all global variables. This is the first function - * called, so any early initialization belongs here. - * - ******************************************************************************/ -acpi_status __init acpi_initialize_subsystem(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_initialize_subsystem); - - acpi_gbl_startup_flags = ACPI_SUBSYSTEM_INITIALIZE; - ACPI_DEBUG_EXEC(acpi_ut_init_stack_ptr_trace()); - - /* Initialize the OS-Dependent layer */ - - status = acpi_os_initialize(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During OSL initialization")); - return_ACPI_STATUS(status); - } - - /* Initialize all globals used by the subsystem */ - - status = acpi_ut_init_globals(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "During initialization of globals")); - return_ACPI_STATUS(status); - } - - /* Create the default mutex objects */ - - status = acpi_ut_mutex_initialize(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "During Global Mutex creation")); - return_ACPI_STATUS(status); - } - - /* - * Initialize the namespace manager and - * the root of the namespace tree - */ - status = acpi_ns_root_initialize(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "During Namespace initialization")); - return_ACPI_STATUS(status); - } - - /* Initialize the global OSI interfaces list with the static names */ - - status = acpi_ut_initialize_interfaces(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "During OSI interfaces initialization")); - return_ACPI_STATUS(status); - } - - /* If configured, initialize the AML debugger */ - - ACPI_DEBUGGER_EXEC(status = acpi_db_initialize()); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_enable_subsystem - * - * PARAMETERS: Flags - Init/enable Options - * - * RETURN: Status - * - * DESCRIPTION: Completes the subsystem initialization including hardware. - * Puts system into ACPI mode if it isn't already. - * - ******************************************************************************/ -acpi_status acpi_enable_subsystem(u32 flags) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(acpi_enable_subsystem); - - /* Enable ACPI mode */ - - if (!(flags & ACPI_NO_ACPI_ENABLE)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Init] Going into ACPI mode\n")); - - acpi_gbl_original_mode = acpi_hw_get_mode(); - - status = acpi_enable(); - if (ACPI_FAILURE(status)) { - ACPI_WARNING((AE_INFO, "AcpiEnable failed")); - return_ACPI_STATUS(status); - } - } - - /* - * Obtain a permanent mapping for the FACS. This is required for the - * Global Lock and the Firmware Waking Vector - */ - status = acpi_tb_initialize_facs(); - if (ACPI_FAILURE(status)) { - ACPI_WARNING((AE_INFO, "Could not map the FACS table")); - return_ACPI_STATUS(status); - } - - /* - * Install the default op_region handlers. These are installed unless - * other handlers have already been installed via the - * install_address_space_handler interface. - */ - if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Init] Installing default address space handlers\n")); - - status = acpi_ev_install_region_handlers(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* - * Initialize ACPI Event handling (Fixed and General Purpose) - * - * Note1: We must have the hardware and events initialized before we can - * execute any control methods safely. Any control method can require - * ACPI hardware support, so the hardware must be fully initialized before - * any method execution! - * - * Note2: Fixed events are initialized and enabled here. GPEs are - * initialized, but cannot be enabled until after the hardware is - * completely initialized (SCI and global_lock activated) - */ - if (!(flags & ACPI_NO_EVENT_INIT)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Init] Initializing ACPI events\n")); - - status = acpi_ev_initialize_events(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* - * Install the SCI handler and Global Lock handler. This completes the - * hardware initialization. - */ - if (!(flags & ACPI_NO_HANDLER_INIT)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Init] Installing SCI/GL handlers\n")); - - status = acpi_ev_install_xrupt_handlers(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_enable_subsystem) - -/******************************************************************************* - * - * FUNCTION: acpi_initialize_objects - * - * PARAMETERS: Flags - Init/enable Options - * - * RETURN: Status - * - * DESCRIPTION: Completes namespace initialization by initializing device - * objects and executing AML code for Regions, buffers, etc. - * - ******************************************************************************/ -acpi_status acpi_initialize_objects(u32 flags) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(acpi_initialize_objects); - - /* - * Run all _REG methods - * - * Note: Any objects accessed by the _REG methods will be automatically - * initialized, even if they contain executable AML (see the call to - * acpi_ns_initialize_objects below). - */ - if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Init] Executing _REG OpRegion methods\n")); - - status = acpi_ev_initialize_op_regions(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* - * Execute any module-level code that was detected during the table load - * phase. Although illegal since ACPI 2.0, there are many machines that - * contain this type of code. Each block of detected executable AML code - * outside of any control method is wrapped with a temporary control - * method object and placed on a global list. The methods on this list - * are executed below. - */ - acpi_ns_exec_module_code_list(); - - /* - * Initialize the objects that remain uninitialized. This runs the - * executable AML that may be part of the declaration of these objects: - * operation_regions, buffer_fields, Buffers, and Packages. - */ - if (!(flags & ACPI_NO_OBJECT_INIT)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Init] Completing Initialization of ACPI Objects\n")); - - status = acpi_ns_initialize_objects(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* - * Initialize all device objects in the namespace. This runs the device - * _STA and _INI methods. - */ - if (!(flags & ACPI_NO_DEVICE_INIT)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Init] Initializing ACPI Devices\n")); - - status = acpi_ns_initialize_devices(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* - * Empty the caches (delete the cached objects) on the assumption that - * the table load filled them up more than they will be at runtime -- - * thus wasting non-paged memory. - */ - status = acpi_purge_cached_objects(); - - acpi_gbl_startup_flags |= ACPI_INITIALIZED_OK; - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_initialize_objects) - -#endif /******************************************************************************* * * FUNCTION: acpi_terminate @@ -325,7 +61,7 @@ ACPI_EXPORT_SYMBOL(acpi_initialize_objects) * DESCRIPTION: Shutdown the ACPICA subsystem and release all resources. * ******************************************************************************/ -acpi_status acpi_terminate(void) +acpi_status __init acpi_terminate(void) { acpi_status status; @@ -369,7 +105,7 @@ acpi_status acpi_terminate(void) return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_terminate) +ACPI_EXPORT_SYMBOL_INIT(acpi_terminate) #ifndef ACPI_ASL_COMPILER #ifdef ACPI_FUTURE_USAGE @@ -405,10 +141,10 @@ ACPI_EXPORT_SYMBOL(acpi_subsystem_status) * PARAMETERS: out_buffer - A buffer to receive the resources for the * device * - * RETURN: Status - the status of the call + * RETURN: status - the status of the call * * DESCRIPTION: This function is called to get information about the current - * state of the ACPI subsystem. It will return system information + * state of the ACPI subsystem. It will return system information * in the out_buffer. * * If the function fails an appropriate status will be returned @@ -472,12 +208,50 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer) ACPI_EXPORT_SYMBOL(acpi_get_system_info) +/******************************************************************************* + * + * FUNCTION: acpi_get_statistics + * + * PARAMETERS: stats - Where the statistics are returned + * + * RETURN: status - the status of the call + * + * DESCRIPTION: Get the contents of the various system counters + * + ******************************************************************************/ +acpi_status acpi_get_statistics(struct acpi_statistics *stats) +{ + ACPI_FUNCTION_TRACE(acpi_get_statistics); + + /* Parameter validation */ + + if (!stats) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Various interrupt-based event counters */ + + stats->sci_count = acpi_sci_count; + stats->gpe_count = acpi_gpe_count; + + ACPI_MEMCPY(stats->fixed_event_count, acpi_fixed_event_count, + sizeof(acpi_fixed_event_count)); + + /* Other counters */ + + stats->method_count = acpi_method_count; + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_get_statistics) + /***************************************************************************** * * FUNCTION: acpi_install_initialization_handler * - * PARAMETERS: Handler - Callback procedure - * Function - Not (currently) used, see below + * PARAMETERS: handler - Callback procedure + * function - Not (currently) used, see below * * RETURN: Status * @@ -499,7 +273,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function) } acpi_gbl_init_handler = handler; - return AE_OK; + return (AE_OK); } ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler) @@ -524,6 +298,7 @@ acpi_status acpi_purge_cached_objects(void) (void)acpi_os_purge_cache(acpi_gbl_operand_cache); (void)acpi_os_purge_cache(acpi_gbl_ps_node_cache); (void)acpi_os_purge_cache(acpi_gbl_ps_node_ext_cache); + return_ACPI_STATUS(AE_OK); } @@ -551,7 +326,10 @@ acpi_status acpi_install_interface(acpi_string interface_name) return (AE_BAD_PARAMETER); } - (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); + status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + return (status); + } /* Check if the interface name is already in the global list */ @@ -600,7 +378,10 @@ acpi_status acpi_remove_interface(acpi_string interface_name) return (AE_BAD_PARAMETER); } - (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); + status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + return (status); + } status = acpi_ut_remove_interface(interface_name); @@ -614,7 +395,7 @@ ACPI_EXPORT_SYMBOL(acpi_remove_interface) * * FUNCTION: acpi_install_interface_handler * - * PARAMETERS: Handler - The _OSI interface handler to install + * PARAMETERS: handler - The _OSI interface handler to install * NULL means "remove existing handler" * * RETURN: Status @@ -626,9 +407,12 @@ ACPI_EXPORT_SYMBOL(acpi_remove_interface) ****************************************************************************/ acpi_status acpi_install_interface_handler(acpi_interface_handler handler) { - acpi_status status = AE_OK; + acpi_status status; - (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); + status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + return (status); + } if (handler && acpi_gbl_interface_handler) { status = AE_ALREADY_EXISTS; @@ -644,12 +428,40 @@ ACPI_EXPORT_SYMBOL(acpi_install_interface_handler) /***************************************************************************** * + * FUNCTION: acpi_update_interfaces + * + * PARAMETERS: action - Actions to be performed during the + * update + * + * RETURN: Status + * + * DESCRIPTION: Update _OSI interface strings, disabling or enabling OS vendor + * string or/and feature group strings. + * + ****************************************************************************/ +acpi_status acpi_update_interfaces(u8 action) +{ + acpi_status status; + + status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + return (status); + } + + status = acpi_ut_update_interfaces(action); + + acpi_os_release_mutex(acpi_gbl_osi_mutex); + return (status); +} + +/***************************************************************************** + * * FUNCTION: acpi_check_address_range * * PARAMETERS: space_id - Address space ID - * Address - Start address - * Length - Length - * Warn - TRUE if warning on overlap desired + * address - Start address + * length - Length + * warn - TRUE if warning on overlap desired * * RETURN: Count of the number of conflicts detected. * @@ -657,6 +469,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_interface_handler) * ASL operation region address ranges. * ****************************************************************************/ + u32 acpi_check_address_range(acpi_adr_space_type space_id, acpi_physical_address address, @@ -679,3 +492,90 @@ acpi_check_address_range(acpi_adr_space_type space_id, ACPI_EXPORT_SYMBOL(acpi_check_address_range) #endif /* !ACPI_ASL_COMPILER */ +/******************************************************************************* + * + * FUNCTION: acpi_decode_pld_buffer + * + * PARAMETERS: in_buffer - Buffer returned by _PLD method + * length - Length of the in_buffer + * return_buffer - Where the decode buffer is returned + * + * RETURN: Status and the decoded _PLD buffer. User must deallocate + * the buffer via ACPI_FREE. + * + * DESCRIPTION: Decode the bit-packed buffer returned by the _PLD method into + * a local struct that is much more useful to an ACPI driver. + * + ******************************************************************************/ +acpi_status +acpi_decode_pld_buffer(u8 *in_buffer, + acpi_size length, struct acpi_pld_info ** return_buffer) +{ + struct acpi_pld_info *pld_info; + u32 *buffer = ACPI_CAST_PTR(u32, in_buffer); + u32 dword; + + /* Parameter validation */ + + if (!in_buffer || !return_buffer || (length < 16)) { + return (AE_BAD_PARAMETER); + } + + pld_info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pld_info)); + if (!pld_info) { + return (AE_NO_MEMORY); + } + + /* First 32-bit DWord */ + + ACPI_MOVE_32_TO_32(&dword, &buffer[0]); + pld_info->revision = ACPI_PLD_GET_REVISION(&dword); + pld_info->ignore_color = ACPI_PLD_GET_IGNORE_COLOR(&dword); + pld_info->color = ACPI_PLD_GET_COLOR(&dword); + + /* Second 32-bit DWord */ + + ACPI_MOVE_32_TO_32(&dword, &buffer[1]); + pld_info->width = ACPI_PLD_GET_WIDTH(&dword); + pld_info->height = ACPI_PLD_GET_HEIGHT(&dword); + + /* Third 32-bit DWord */ + + ACPI_MOVE_32_TO_32(&dword, &buffer[2]); + pld_info->user_visible = ACPI_PLD_GET_USER_VISIBLE(&dword); + pld_info->dock = ACPI_PLD_GET_DOCK(&dword); + pld_info->lid = ACPI_PLD_GET_LID(&dword); + pld_info->panel = ACPI_PLD_GET_PANEL(&dword); + pld_info->vertical_position = ACPI_PLD_GET_VERTICAL(&dword); + pld_info->horizontal_position = ACPI_PLD_GET_HORIZONTAL(&dword); + pld_info->shape = ACPI_PLD_GET_SHAPE(&dword); + pld_info->group_orientation = ACPI_PLD_GET_ORIENTATION(&dword); + pld_info->group_token = ACPI_PLD_GET_TOKEN(&dword); + pld_info->group_position = ACPI_PLD_GET_POSITION(&dword); + pld_info->bay = ACPI_PLD_GET_BAY(&dword); + + /* Fourth 32-bit DWord */ + + ACPI_MOVE_32_TO_32(&dword, &buffer[3]); + pld_info->ejectable = ACPI_PLD_GET_EJECTABLE(&dword); + pld_info->ospm_eject_required = ACPI_PLD_GET_OSPM_EJECT(&dword); + pld_info->cabinet_number = ACPI_PLD_GET_CABINET(&dword); + pld_info->card_cage_number = ACPI_PLD_GET_CARD_CAGE(&dword); + pld_info->reference = ACPI_PLD_GET_REFERENCE(&dword); + pld_info->rotation = ACPI_PLD_GET_ROTATION(&dword); + pld_info->order = ACPI_PLD_GET_ORDER(&dword); + + if (length >= ACPI_PLD_BUFFER_SIZE) { + + /* Fifth 32-bit DWord (Revision 2 of _PLD) */ + + ACPI_MOVE_32_TO_32(&dword, &buffer[4]); + pld_info->vertical_offset = ACPI_PLD_GET_VERT_OFFSET(&dword); + pld_info->horizontal_offset = ACPI_PLD_GET_HORIZ_OFFSET(&dword); + } + + *return_buffer = pld_info; + return (AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_decode_pld_buffer) diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c index 52b568af181..88ef77f3cf8 100644 --- a/drivers/acpi/acpica/utxferror.c +++ b/drivers/acpi/acpica/utxferror.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,10 +41,10 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include <linux/export.h> +#define EXPORT_ACPI_INTERFACES + #include <acpi/acpi.h> #include "accommon.h" -#include "acnamesp.h" #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utxferror") @@ -52,48 +52,15 @@ ACPI_MODULE_NAME("utxferror") /* * This module is used for the in-kernel ACPICA as well as the ACPICA * tools/applications. - * - * For the i_aSL compiler case, the output is redirected to stderr so that - * any of the various ACPI errors and warnings do not appear in the output - * files, for either the compiler or disassembler portions of the tool. - */ -#ifdef ACPI_ASL_COMPILER -#include <stdio.h> -extern FILE *acpi_gbl_output_file; - -#define ACPI_MSG_REDIRECT_BEGIN \ - FILE *output_file = acpi_gbl_output_file; \ - acpi_os_redirect_output (stderr); - -#define ACPI_MSG_REDIRECT_END \ - acpi_os_redirect_output (output_file); - -#else -/* - * non-i_aSL case - no redirection, nothing to do */ -#define ACPI_MSG_REDIRECT_BEGIN -#define ACPI_MSG_REDIRECT_END -#endif -/* - * Common message prefixes - */ -#define ACPI_MSG_ERROR "ACPI Error: " -#define ACPI_MSG_EXCEPTION "ACPI Exception: " -#define ACPI_MSG_WARNING "ACPI Warning: " -#define ACPI_MSG_INFO "ACPI: " -/* - * Common message suffix - */ -#define ACPI_MSG_SUFFIX \ - acpi_os_printf (" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, module_name, line_number) +#ifndef ACPI_NO_ERROR_MESSAGES /* Entire module */ /******************************************************************************* * * FUNCTION: acpi_error * * PARAMETERS: module_name - Caller's module name (for error output) * line_number - Caller's line number (for error output) - * Format - Printf format string + additional args + * format - Printf format string + additional args * * RETURN: None * @@ -124,8 +91,8 @@ ACPI_EXPORT_SYMBOL(acpi_error) * * PARAMETERS: module_name - Caller's module name (for error output) * line_number - Caller's line number (for error output) - * Status - Status to be formatted - * Format - Printf format string + additional args + * status - Status to be formatted + * format - Printf format string + additional args * * RETURN: None * @@ -159,7 +126,7 @@ ACPI_EXPORT_SYMBOL(acpi_exception) * * PARAMETERS: module_name - Caller's module name (for error output) * line_number - Caller's line number (for error output) - * Format - Printf format string + additional args + * format - Printf format string + additional args * * RETURN: None * @@ -190,7 +157,7 @@ ACPI_EXPORT_SYMBOL(acpi_warning) * * PARAMETERS: module_name - Caller's module name (for error output) * line_number - Caller's line number (for error output) - * Format - Printf format string + additional args + * format - Printf format string + additional args * * RETURN: None * @@ -218,199 +185,69 @@ acpi_info(const char *module_name, u32 line_number, const char *format, ...) ACPI_EXPORT_SYMBOL(acpi_info) -/* - * The remainder of this module contains internal error functions that may - * be configured out. - */ -#if !defined (ACPI_NO_ERROR_MESSAGES) && !defined (ACPI_BIN_APP) /******************************************************************************* * - * FUNCTION: acpi_ut_predefined_warning + * FUNCTION: acpi_bios_error * - * PARAMETERS: module_name - Caller's module name (for error output) - * line_number - Caller's line number (for error output) - * Pathname - Full pathname to the node - * node_flags - From Namespace node for the method/object - * Format - Printf format string + additional args + * PARAMETERS: module_name - Caller's module name (for error output) + * line_number - Caller's line number (for error output) + * format - Printf format string + additional args * * RETURN: None * - * DESCRIPTION: Warnings for the predefined validation module. Messages are - * only emitted the first time a problem with a particular - * method/object is detected. This prevents a flood of error - * messages for methods that are repeatedly evaluated. + * DESCRIPTION: Print "ACPI Firmware Error" message with module/line/version + * info * ******************************************************************************/ void ACPI_INTERNAL_VAR_XFACE -acpi_ut_predefined_warning(const char *module_name, - u32 line_number, - char *pathname, - u8 node_flags, const char *format, ...) +acpi_bios_error(const char *module_name, + u32 line_number, const char *format, ...) { va_list arg_list; - /* - * Warning messages for this method/object will be disabled after the - * first time a validation fails or an object is successfully repaired. - */ - if (node_flags & ANOBJ_EVALUATED) { - return; - } - - acpi_os_printf(ACPI_MSG_WARNING "For %s: ", pathname); + ACPI_MSG_REDIRECT_BEGIN; + acpi_os_printf(ACPI_MSG_BIOS_ERROR); va_start(arg_list, format); acpi_os_vprintf(format, arg_list); ACPI_MSG_SUFFIX; va_end(arg_list); + + ACPI_MSG_REDIRECT_END; } +ACPI_EXPORT_SYMBOL(acpi_bios_error) + /******************************************************************************* * - * FUNCTION: acpi_ut_predefined_info + * FUNCTION: acpi_bios_warning * - * PARAMETERS: module_name - Caller's module name (for error output) - * line_number - Caller's line number (for error output) - * Pathname - Full pathname to the node - * node_flags - From Namespace node for the method/object - * Format - Printf format string + additional args + * PARAMETERS: module_name - Caller's module name (for error output) + * line_number - Caller's line number (for error output) + * format - Printf format string + additional args * * RETURN: None * - * DESCRIPTION: Info messages for the predefined validation module. Messages - * are only emitted the first time a problem with a particular - * method/object is detected. This prevents a flood of - * messages for methods that are repeatedly evaluated. + * DESCRIPTION: Print "ACPI Firmware Warning" message with module/line/version + * info * ******************************************************************************/ - void ACPI_INTERNAL_VAR_XFACE -acpi_ut_predefined_info(const char *module_name, - u32 line_number, - char *pathname, u8 node_flags, const char *format, ...) +acpi_bios_warning(const char *module_name, + u32 line_number, const char *format, ...) { va_list arg_list; - /* - * Warning messages for this method/object will be disabled after the - * first time a validation fails or an object is successfully repaired. - */ - if (node_flags & ANOBJ_EVALUATED) { - return; - } - - acpi_os_printf(ACPI_MSG_INFO "For %s: ", pathname); + ACPI_MSG_REDIRECT_BEGIN; + acpi_os_printf(ACPI_MSG_BIOS_WARNING); va_start(arg_list, format); acpi_os_vprintf(format, arg_list); ACPI_MSG_SUFFIX; va_end(arg_list); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_namespace_error - * - * PARAMETERS: module_name - Caller's module name (for error output) - * line_number - Caller's line number (for error output) - * internal_name - Name or path of the namespace node - * lookup_status - Exception code from NS lookup - * - * RETURN: None - * - * DESCRIPTION: Print error message with the full pathname for the NS node. - * - ******************************************************************************/ -void -acpi_ut_namespace_error(const char *module_name, - u32 line_number, - const char *internal_name, acpi_status lookup_status) -{ - acpi_status status; - u32 bad_name; - char *name = NULL; - - ACPI_MSG_REDIRECT_BEGIN; - acpi_os_printf(ACPI_MSG_ERROR); - - if (lookup_status == AE_BAD_CHARACTER) { - - /* There is a non-ascii character in the name */ - - ACPI_MOVE_32_TO_32(&bad_name, - ACPI_CAST_PTR(u32, internal_name)); - acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name); - } else { - /* Convert path to external format */ - - status = acpi_ns_externalize_name(ACPI_UINT32_MAX, - internal_name, NULL, &name); - - /* Print target name */ - - if (ACPI_SUCCESS(status)) { - acpi_os_printf("[%s]", name); - } else { - acpi_os_printf("[COULD NOT EXTERNALIZE NAME]"); - } - - if (name) { - ACPI_FREE(name); - } - } - - acpi_os_printf(" Namespace lookup failure, %s", - acpi_format_exception(lookup_status)); - - ACPI_MSG_SUFFIX; - ACPI_MSG_REDIRECT_END; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_method_error - * - * PARAMETERS: module_name - Caller's module name (for error output) - * line_number - Caller's line number (for error output) - * Message - Error message to use on failure - * prefix_node - Prefix relative to the path - * Path - Path to the node (optional) - * method_status - Execution status - * - * RETURN: None - * - * DESCRIPTION: Print error message with the full pathname for the method. - * - ******************************************************************************/ - -void -acpi_ut_method_error(const char *module_name, - u32 line_number, - const char *message, - struct acpi_namespace_node *prefix_node, - const char *path, acpi_status method_status) -{ - acpi_status status; - struct acpi_namespace_node *node = prefix_node; - - ACPI_MSG_REDIRECT_BEGIN; - acpi_os_printf(ACPI_MSG_ERROR); - - if (path) { - status = - acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH, - &node); - if (ACPI_FAILURE(status)) { - acpi_os_printf("[Could not get node by pathname]"); - } - } - - acpi_ns_print_node_pathname(node, message); - acpi_os_printf(", %s", acpi_format_exception(method_status)); - - ACPI_MSG_SUFFIX; ACPI_MSG_REDIRECT_END; } +ACPI_EXPORT_SYMBOL(acpi_bios_warning) #endif /* ACPI_NO_ERROR_MESSAGES */ diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c new file mode 100644 index 00000000000..13380d81846 --- /dev/null +++ b/drivers/acpi/acpica/utxfinit.c @@ -0,0 +1,329 @@ +/****************************************************************************** + * + * Module Name: utxfinit - External interfaces for ACPICA initialization + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define EXPORT_ACPI_INTERFACES + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acevents.h" +#include "acnamesp.h" +#include "acdebug.h" +#include "actables.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utxfinit") + +/******************************************************************************* + * + * FUNCTION: acpi_initialize_subsystem + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initializes all global variables. This is the first function + * called, so any early initialization belongs here. + * + ******************************************************************************/ +acpi_status __init acpi_initialize_subsystem(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_initialize_subsystem); + + acpi_gbl_startup_flags = ACPI_SUBSYSTEM_INITIALIZE; + ACPI_DEBUG_EXEC(acpi_ut_init_stack_ptr_trace()); + + /* Initialize the OS-Dependent layer */ + + status = acpi_os_initialize(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "During OSL initialization")); + return_ACPI_STATUS(status); + } + + /* Initialize all globals used by the subsystem */ + + status = acpi_ut_init_globals(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "During initialization of globals")); + return_ACPI_STATUS(status); + } + + /* Create the default mutex objects */ + + status = acpi_ut_mutex_initialize(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "During Global Mutex creation")); + return_ACPI_STATUS(status); + } + + /* + * Initialize the namespace manager and + * the root of the namespace tree + */ + status = acpi_ns_root_initialize(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "During Namespace initialization")); + return_ACPI_STATUS(status); + } + + /* Initialize the global OSI interfaces list with the static names */ + + status = acpi_ut_initialize_interfaces(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "During OSI interfaces initialization")); + return_ACPI_STATUS(status); + } + + /* If configured, initialize the AML debugger */ + +#ifdef ACPI_DEBUGGER + status = acpi_db_initialize(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "During Debugger initialization")); + return_ACPI_STATUS(status); + } +#endif + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_subsystem) + +/******************************************************************************* + * + * FUNCTION: acpi_enable_subsystem + * + * PARAMETERS: flags - Init/enable Options + * + * RETURN: Status + * + * DESCRIPTION: Completes the subsystem initialization including hardware. + * Puts system into ACPI mode if it isn't already. + * + ******************************************************************************/ +acpi_status __init acpi_enable_subsystem(u32 flags) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(acpi_enable_subsystem); + +#if (!ACPI_REDUCED_HARDWARE) + + /* Enable ACPI mode */ + + if (!(flags & ACPI_NO_ACPI_ENABLE)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[Init] Going into ACPI mode\n")); + + acpi_gbl_original_mode = acpi_hw_get_mode(); + + status = acpi_enable(); + if (ACPI_FAILURE(status)) { + ACPI_WARNING((AE_INFO, "AcpiEnable failed")); + return_ACPI_STATUS(status); + } + } + + /* + * Obtain a permanent mapping for the FACS. This is required for the + * Global Lock and the Firmware Waking Vector + */ + status = acpi_tb_initialize_facs(); + if (ACPI_FAILURE(status)) { + ACPI_WARNING((AE_INFO, "Could not map the FACS table")); + return_ACPI_STATUS(status); + } +#endif /* !ACPI_REDUCED_HARDWARE */ + + /* + * Install the default op_region handlers. These are installed unless + * other handlers have already been installed via the + * install_address_space_handler interface. + */ + if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[Init] Installing default address space handlers\n")); + + status = acpi_ev_install_region_handlers(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } +#if (!ACPI_REDUCED_HARDWARE) + /* + * Initialize ACPI Event handling (Fixed and General Purpose) + * + * Note1: We must have the hardware and events initialized before we can + * execute any control methods safely. Any control method can require + * ACPI hardware support, so the hardware must be fully initialized before + * any method execution! + * + * Note2: Fixed events are initialized and enabled here. GPEs are + * initialized, but cannot be enabled until after the hardware is + * completely initialized (SCI and global_lock activated) and the various + * initialization control methods are run (_REG, _STA, _INI) on the + * entire namespace. + */ + if (!(flags & ACPI_NO_EVENT_INIT)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[Init] Initializing ACPI events\n")); + + status = acpi_ev_initialize_events(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* + * Install the SCI handler and Global Lock handler. This completes the + * hardware initialization. + */ + if (!(flags & ACPI_NO_HANDLER_INIT)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[Init] Installing SCI/GL handlers\n")); + + status = acpi_ev_install_xrupt_handlers(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } +#endif /* !ACPI_REDUCED_HARDWARE */ + + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL_INIT(acpi_enable_subsystem) + +/******************************************************************************* + * + * FUNCTION: acpi_initialize_objects + * + * PARAMETERS: flags - Init/enable Options + * + * RETURN: Status + * + * DESCRIPTION: Completes namespace initialization by initializing device + * objects and executing AML code for Regions, buffers, etc. + * + ******************************************************************************/ +acpi_status __init acpi_initialize_objects(u32 flags) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(acpi_initialize_objects); + + /* + * Run all _REG methods + * + * Note: Any objects accessed by the _REG methods will be automatically + * initialized, even if they contain executable AML (see the call to + * acpi_ns_initialize_objects below). + */ + if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[Init] Executing _REG OpRegion methods\n")); + + status = acpi_ev_initialize_op_regions(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* + * Execute any module-level code that was detected during the table load + * phase. Although illegal since ACPI 2.0, there are many machines that + * contain this type of code. Each block of detected executable AML code + * outside of any control method is wrapped with a temporary control + * method object and placed on a global list. The methods on this list + * are executed below. + */ + acpi_ns_exec_module_code_list(); + + /* + * Initialize the objects that remain uninitialized. This runs the + * executable AML that may be part of the declaration of these objects: + * operation_regions, buffer_fields, Buffers, and Packages. + */ + if (!(flags & ACPI_NO_OBJECT_INIT)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[Init] Completing Initialization of ACPI Objects\n")); + + status = acpi_ns_initialize_objects(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* + * Initialize all device objects in the namespace. This runs the device + * _STA and _INI methods. + */ + if (!(flags & ACPI_NO_DEVICE_INIT)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[Init] Initializing ACPI Devices\n")); + + status = acpi_ns_initialize_devices(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* + * Empty the caches (delete the cached objects) on the assumption that + * the table load filled them up more than they will be at runtime -- + * thus wasting non-paged memory. + */ + status = acpi_purge_cached_objects(); + + acpi_gbl_startup_flags |= ACPI_INITIALIZED_OK; + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_objects) diff --git a/drivers/acpi/acpica/utxfmutex.c b/drivers/acpi/acpica/utxfmutex.c index 1427d191d15..2a0f9e04d3a 100644 --- a/drivers/acpi/acpica/utxfmutex.c +++ b/drivers/acpi/acpica/utxfmutex.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,8 +58,8 @@ acpi_ut_get_mutex_object(acpi_handle handle, * * FUNCTION: acpi_ut_get_mutex_object * - * PARAMETERS: Handle - Mutex or prefix handle (optional) - * Pathname - Mutex pathname (optional) + * PARAMETERS: handle - Mutex or prefix handle (optional) + * pathname - Mutex pathname (optional) * ret_obj - Where the mutex object is returned * * RETURN: Status @@ -118,9 +118,9 @@ acpi_ut_get_mutex_object(acpi_handle handle, * * FUNCTION: acpi_acquire_mutex * - * PARAMETERS: Handle - Mutex or prefix handle (optional) - * Pathname - Mutex pathname (optional) - * Timeout - Max time to wait for the lock (millisec) + * PARAMETERS: handle - Mutex or prefix handle (optional) + * pathname - Mutex pathname (optional) + * timeout - Max time to wait for the lock (millisec) * * RETURN: Status * @@ -155,8 +155,8 @@ acpi_acquire_mutex(acpi_handle handle, acpi_string pathname, u16 timeout) * * FUNCTION: acpi_release_mutex * - * PARAMETERS: Handle - Mutex or prefix handle (optional) - * Pathname - Mutex pathname (optional) + * PARAMETERS: handle - Mutex or prefix handle (optional) + * pathname - Mutex pathname (optional) * * RETURN: Status * |
