diff options
Diffstat (limited to 'drivers/acpi/acpica')
172 files changed, 23767 insertions, 13485 deletions
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index a7e1d1aa410..8bb43f06e11 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -8,41 +8,172 @@ ccflags-$(CONFIG_ACPI_DEBUG)	+= -DACPI_DEBUG_OUTPUT  # use acpi.o to put all files here into acpi.o modparam namespace  obj-y	+= acpi.o -acpi-y := dsfield.o   dsmthdat.o  dsopcode.o  dswexec.o  dswscope.o \ -	 dsmethod.o  dsobject.o  dsutils.o   dswload.o  dswstate.o \ -	 dsinit.o +acpi-y :=		\ +	dsargs.o	\ +	dscontrol.o	\ +	dsfield.o	\ +	dsinit.o	\ +	dsmethod.o	\ +	dsmthdat.o	\ +	dsobject.o	\ +	dsopcode.o	\ +	dsutils.o	\ +	dswexec.o	\ +	dswload.o	\ +	dswload2.o	\ +	dswscope.o	\ +	dswstate.o -acpi-y += evevent.o  evregion.o  evsci.o    evxfevnt.o \ -	 evmisc.o   evrgnini.o  evxface.o  evxfregn.o \ -	 evgpe.o    evgpeblk.o evgpeinit.o  evgpeutil.o +acpi-y +=		\ +	evevent.o	\ +	evgpe.o		\ +	evgpeblk.o	\ +	evgpeinit.o	\ +	evgpeutil.o	\ +	evglock.o	\ +	evhandler.o	\ +	evmisc.o	\ +	evregion.o	\ +	evrgnini.o	\ +	evsci.o		\ +	evxface.o	\ +	evxfevnt.o	\ +	evxfgpe.o	\ +	evxfregn.o -acpi-y += exconfig.o  exfield.o  exnames.o   exoparg6.o  exresolv.o  exstorob.o\ -	 exconvrt.o  exfldio.o  exoparg1.o  exprep.o    exresop.o   exsystem.o\ -	 excreate.o  exmisc.o   exoparg2.o  exregion.o  exstore.o   exutils.o \ -	 exdump.o    exmutex.o  exoparg3.o  exresnte.o  exstoren.o  exdebug.o +acpi-y +=		\ +	exconfig.o	\ +	exconvrt.o	\ +	excreate.o	\ +	exdebug.o	\ +	exdump.o	\ +	exfield.o	\ +	exfldio.o	\ +	exmutex.o	\ +	exnames.o	\ +	exoparg1.o	\ +	exoparg2.o	\ +	exoparg3.o	\ +	exoparg6.o	\ +	exprep.o	\ +	exmisc.o	\ +	exregion.o	\ +	exresnte.o	\ +	exresolv.o	\ +	exresop.o	\ +	exstore.o	\ +	exstoren.o	\ +	exstorob.o	\ +	exsystem.o	\ +	exutils.o -acpi-y += hwacpi.o  hwgpe.o  hwregs.o  hwsleep.o hwxface.o hwvalid.o hwpci.o +acpi-y +=		\ +	hwacpi.o	\ +	hwesleep.o	\ +	hwgpe.o		\ +	hwpci.o		\ +	hwregs.o	\ +	hwsleep.o	\ +	hwvalid.o	\ +	hwxface.o	\ +	hwxfsleep.o  acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o -acpi-y += nsaccess.o  nsload.o    nssearch.o  nsxfeval.o \ -	 nsalloc.o   nseval.o    nsnames.o   nsutils.o   nsxfname.o \ -	 nsdump.o    nsinit.o    nsobject.o  nswalk.o    nsxfobj.o  \ -	 nsparse.o   nspredef.o  nsrepair.o  nsrepair2.o +acpi-y +=		\ +	nsaccess.o	\ +	nsalloc.o	\ +	nsarguments.o	\ +	nsconvert.o	\ +	nsdump.o	\ +	nseval.o	\ +	nsinit.o	\ +	nsload.o	\ +	nsnames.o	\ +	nsobject.o	\ +	nsparse.o	\ +	nspredef.o	\ +	nsprepkg.o	\ +	nsrepair.o	\ +	nsrepair2.o	\ +	nssearch.o	\ +	nsutils.o	\ +	nswalk.o	\ +	nsxfeval.o	\ +	nsxfname.o	\ +	nsxfobj.o  acpi-$(ACPI_FUTURE_USAGE) += nsdumpdv.o -acpi-y += psargs.o    psparse.o  psloop.o pstree.o   pswalk.o  \ -	 psopcode.o  psscope.o  psutils.o  psxface.o +acpi-y +=		\ +	psargs.o	\ +	psloop.o	\ +	psobject.o	\ +	psopcode.o	\ +	psopinfo.o	\ +	psparse.o	\ +	psscope.o	\ +	pstree.o	\ +	psutils.o	\ +	pswalk.o	\ +	psxface.o -acpi-y += rsaddr.o rscreate.o rsinfo.o rsio.o rslist.o rsmisc.o rsxface.o \ -	 rscalc.o  rsirq.o  rsmemory.o  rsutils.o +acpi-y +=		\ +	rsaddr.o	\ +	rscalc.o	\ +	rscreate.o	\ +	rsdump.o	\ +	rsdumpinfo.o	\ +	rsinfo.o	\ +	rsio.o		\ +	rsirq.o		\ +	rslist.o	\ +	rsmemory.o	\ +	rsmisc.o	\ +	rsserial.o	\ +	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 += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.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		\ +	utinit.o	\ +	utlock.o	\ +	utmath.o	\ +	utmisc.o	\ +	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 -acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \ -		utcopy.o utdelete.o utglobal.o utmath.o utobject.o \ -		utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o \ -		utosi.o utxferror.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 3e50c74ed4a..6f1c616910a 100644 --- a/drivers/acpi/acpica/accommon.h +++ b/drivers/acpi/acpica/accommon.h @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 b17d8de9f6f..00000000000 --- a/drivers/acpi/acpica/acconfig.h +++ /dev/null @@ -1,227 +0,0 @@ -/****************************************************************************** - * - * Name: acconfig.h - Global configuration constants - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2010, 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                  20000	/* Two seconds */ - -/****************************************************************************** - * - * 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_NUM_PREDEFINED_REGIONS     9 -#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 and IPMI bidirectional buffer size */ - -#define ACPI_SMBUS_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 72e9d5eb083..68a91eb0fa4 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 894a0ff2a94..d3e2cc395d7 100644 --- a/drivers/acpi/acpica/acdispat.h +++ b/drivers/acpi/acpica/acdispat.h @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 NAMEOF_ARG_NTE      "__A0"  /* - * dsopcode - support for late evaluation + * dsargs - execution of dynamic arguments for static objects   */  acpi_status  acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc); @@ -62,6 +62,20 @@ acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc);  acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc); +/* + * dscontrol - support for execution control opcodes + */ +acpi_status +acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, +			      union acpi_parse_object *op); + +acpi_status +acpi_ds_exec_end_control_op(struct acpi_walk_state *walk_state, +			    union acpi_parse_object *op); + +/* + * dsopcode - support for late operand evaluation + */  acpi_status  acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,  				   union acpi_parse_object *op); @@ -86,17 +100,6 @@ acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state,  acpi_status acpi_ds_initialize_region(acpi_handle obj_handle);  /* - * dsctrl - Parser/Interpreter interface, control stack routines - */ -acpi_status -acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, -			      union acpi_parse_object *op); - -acpi_status -acpi_ds_exec_end_control_op(struct acpi_walk_state *walk_state, -			    union acpi_parse_object *op); - -/*   * dsexec - Parser/Interpreter interface, method execution callbacks   */  acpi_status @@ -136,23 +139,27 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,  			   struct acpi_walk_state *walk_state);  /* - * dsload - Parser/Interpreter interface, 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 - pass 2 namespace load callbacks */ +  acpi_status  acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,  		       union acpi_parse_object **out_op);  acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state); -acpi_status -acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number); -  /*   * dsmthdat - method data (locals/args)   */ @@ -194,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, @@ -303,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 a6f99cc37a1..7a7811a9fc2 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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,6 @@ acpi_status acpi_ev_initialize_events(void);  acpi_status acpi_ev_install_xrupt_handlers(void); -acpi_status acpi_ev_install_fadt_gpes(void); -  u32 acpi_ev_fixed_event_detect(void);  /* @@ -60,12 +58,6 @@ u32 acpi_ev_fixed_event_detect(void);   */  u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node); -acpi_status acpi_ev_acquire_global_lock(u16 timeout); - -acpi_status acpi_ev_release_global_lock(void); - -acpi_status acpi_ev_init_global_lock_handler(void); -  u32 acpi_ev_get_gpe_number_index(u32 gpe_number);  acpi_status @@ -73,6 +65,16 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node *node,  			     u32 notify_value);  /* + * evglock - Global Lock support + */ +acpi_status acpi_ev_init_global_lock_handler(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); + +/*   * evgpe - Low-level GPE support   */  u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list); @@ -82,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_raw_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_raw_disable_gpe(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); @@ -93,26 +97,32 @@ struct acpi_gpe_event_info *acpi_ev_low_get_gpe_info(u32 gpe_number,  						     struct acpi_gpe_block_info  						     *gpe_block); +acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info); +  /*   * evgpeblk - Upper-level GPE block support   */  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);  acpi_status  acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,  			     struct acpi_gpe_block_info *gpe_block, -			     void *ignored); +			     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_gpe_event_info *gpe_event_info, +acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, +		     struct acpi_gpe_event_info *gpe_event_info,  		     u32 gpe_number);  /* @@ -120,16 +130,13 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info,   */  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,  			 u32 level, void *context, void **return_value); -acpi_status -acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, -			  u32 level, void *context, void **return_value); -  /*   * evgpeutil - GPE utilities   */ @@ -138,7 +145,13 @@ acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback, void *context);  u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info); -struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 interrupt_number); +acpi_status +acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, +		       struct acpi_gpe_block_info *gpe_block, void *context); + +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); @@ -148,14 +161,28 @@ 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  acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, +			       union acpi_operand_object *field_obj,  			       u32 function,  			       u32 region_offset, u32 bit_width, u64 *value); @@ -169,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); @@ -224,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 ad88fcae4eb..115eedcade1 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -44,161 +44,46 @@  #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) - * - ****************************************************************************/ - -/* - * 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); - -/* - * 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); - -/* - * 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. - */ -u32 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); - -/* 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; - -#endif -  /*****************************************************************************   * - * Debug support + * Globals related to the ACPI tables   *   ****************************************************************************/ -/* Procedure nesting level for debug output */ +/* Master list of all ACPI tables that were found in the RSDT/XSDT */ -extern u32 acpi_gbl_nesting_level; +ACPI_GLOBAL(struct acpi_table_list, acpi_gbl_root_table_list); -/* Support for dynamic control method tracing mechanism */ +/* DSDT information. Used to check for DSDT corruption */ -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_GLOBAL(struct acpi_table_header *, acpi_gbl_DSDT); +ACPI_GLOBAL(struct acpi_table_header, acpi_gbl_original_dsdt_header); -/***************************************************************************** - * - * ACPI Table globals - * - ****************************************************************************/ +#if (!ACPI_REDUCED_HARDWARE) +ACPI_GLOBAL(struct acpi_table_facs *, acpi_gbl_FACS); -/* - * 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_GLOBAL(struct acpi_generic_address, acpi_gbl_xpm1a_status); +ACPI_GLOBAL(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_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);  /*****************************************************************************   * - * Mutual exlusion within ACPICA subsystem + * Mutual exclusion within ACPICA subsystem   *   ****************************************************************************/ @@ -207,26 +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 HW global lock + * 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 u16 acpi_gbl_global_lock_handle; -ACPI_EXTERN u8 acpi_gbl_global_lock_acquired; -ACPI_EXTERN u8 acpi_gbl_global_lock_present; +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 spinlock_t _acpi_gbl_gpe_lock;	/* For GPE data structs and registers */ -ACPI_EXTERN spinlock_t _acpi_gbl_hardware_lock;	/* For ACPI H/W except GPE registers */ -#define acpi_gbl_gpe_lock	&_acpi_gbl_gpe_lock -#define acpi_gbl_hardware_lock	&_acpi_gbl_hardware_lock +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);  /*****************************************************************************   * @@ -234,75 +129,70 @@ ACPI_EXTERN spinlock_t _acpi_gbl_hardware_lock;	/* For ACPI H/W except GPE regis   *   ****************************************************************************/ -#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); -/* Misc */ +/* Initialization sequencing */ -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_GLOBAL(u8, acpi_gbl_reg_methods_executed); -#ifndef DEFINE_ACPI_GLOBALS +/* Misc */ + +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 */ +/* Other miscellaneous, declared and initialized in utglobal */ -extern u8 acpi_gbl_shutdown; -extern u32 acpi_gbl_startup_flags;  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  /*****************************************************************************   * @@ -316,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  /***************************************************************************** @@ -340,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);  /*****************************************************************************   * @@ -354,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);  /*****************************************************************************   * @@ -363,66 +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_all_gpes_initialized; + +#endif				/* !ACPI_REDUCED_HARDWARE */ + +/***************************************************************************** + * + * Debug support + * + ****************************************************************************/ + +/* 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 globals + * Debugger and Disassembler globals   *   ****************************************************************************/ -ACPI_EXTERN u8 acpi_gbl_db_output_flags; +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 167470ad2d2..2ad2351a983 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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,11 +110,10 @@ 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, u8 action); +acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action);  acpi_status  acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, @@ -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 049e203bd62..b01f71ce052 100644 --- a/drivers/acpi/acpica/acinterp.h +++ b/drivers/acpi/acpica/acinterp.h @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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); @@ -468,6 +468,8 @@ void acpi_ex_eisa_id_to_string(char *dest, u64 compressed_id);  void acpi_ex_integer_to_string(char *dest, u64 value); +u8 acpi_is_valid_space_id(u8 space_id); +  /*   * exregion - default op_region handlers   */ diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 2ceb0c05b2d..91f801a2e68 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 @@ typedef u32 acpi_mutex_handle;  /* Total number of aml opcodes defined */ -#define AML_NUM_OPCODES                 0x7F +#define AML_NUM_OPCODES                 0x81  /* Forward declarations */ @@ -89,25 +89,6 @@ union acpi_parse_object;  #define ACPI_MAX_MUTEX                  7  #define ACPI_NUM_MUTEX                  ACPI_MAX_MUTEX+1 -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) -#ifdef DEFINE_ACPI_GLOBALS - -/* Debug names for the mutexes above */ - -static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = { -	"ACPI_MTX_Interpreter", -	"ACPI_MTX_Namespace", -	"ACPI_MTX_Tables", -	"ACPI_MTX_Events", -	"ACPI_MTX_Caches", -	"ACPI_MTX_Memory", -	"ACPI_MTX_CommandComplete", -	"ACPI_MTX_CommandReady" -}; - -#endif -#endif -  /* Lock structure for reader/writer interfaces */  struct acpi_rw_lock { @@ -208,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 */ @@ -268,19 +248,23 @@ struct acpi_create_field_info {  	struct acpi_namespace_node *field_node;  	struct acpi_namespace_node *register_node;  	struct acpi_namespace_node *data_register_node; +	struct acpi_namespace_node *connection_node; +	u8 *resource_buffer;  	u32 bank_value;  	u32 field_bit_position;  	u32 field_bit_length; +	u16 resource_length;  	u8 field_flags;  	u8 attribute;  	u8 field_type; +	u8 access_length;  };  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 @@ -310,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;  }; @@ -334,7 +320,8 @@ struct acpi_name_info {  /*   * Used for ACPI_PTYPE1_FIXED, ACPI_PTYPE1_VAR, ACPI_PTYPE2, - * ACPI_PTYPE2_MIN, ACPI_PTYPE2_PKG_COUNT, ACPI_PTYPE2_COUNT + * ACPI_PTYPE2_MIN, ACPI_PTYPE2_PKG_COUNT, ACPI_PTYPE2_COUNT, + * ACPI_PTYPE2_FIX_VAR   */  struct acpi_package_info {  	u8 type; @@ -342,7 +329,7 @@ struct acpi_package_info {  	u8 count1;  	u8 object_type2;  	u8 count2; -	u8 reserved; +	u16 reserved;  };  /* Used for ACPI_PTYPE2_FIXED */ @@ -351,6 +338,7 @@ struct acpi_package_info2 {  	u8 type;  	u8 count;  	u8 object_type[4]; +	u8 reserved;  };  /* Used for ACPI_PTYPE1_OPTION */ @@ -360,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 { @@ -370,19 +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; -	u32 flags; -	u8 node_flags; -}; +#pragma pack() + +/* Return object auto-repair info */ -/* Defines for Flags field above */ +typedef acpi_status(*acpi_object_converter) (union acpi_operand_object +					     *original_object, +					     union acpi_operand_object +					     **converted_object); -#define ACPI_OBJECT_REPAIRED    1 +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 @@ -406,19 +398,39 @@ 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_handler_info { -	acpi_event_handler address;	/* Address of handler, if any */ +struct acpi_gpe_handler_info { +	acpi_gpe_handler address;	/* Address of handler, if any */  	void *context;		/* Context to be passed to handler */  	struct acpi_namespace_node *method_node;	/* Method node for this GPE level (saved) */ -	u8 orig_flags;		/* Original misc info about this GPE */ -	u8 orig_enabled;	/* Set if the GPE was originally enabled */ +	u8 original_flags;      /* Original (pre-handler) GPE info */ +	u8 originally_enabled;  /* True if GPE was originally enabled */  }; +/* 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_handler_info *handler; +	struct acpi_gpe_handler_info *handler;  /* Installed GPE handler */ +	struct acpi_gpe_notify_info *notify_list;	/* List of _PRW devices for implicit notifies */  };  /* @@ -426,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 */ @@ -438,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 */  };  /* @@ -454,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;         /* If set, the GPE block has been 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 */ @@ -485,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 */ @@ -581,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 { @@ -606,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 */ @@ -635,7 +659,16 @@ 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 */ + +struct acpi_address_range { +	struct acpi_address_range *next; +	struct acpi_namespace_node *region_node; +	acpi_physical_address start_address; +	acpi_physical_address end_address; +};  /*****************************************************************************   * @@ -658,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 */ @@ -688,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) @@ -715,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 @@ -784,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  /***************************************************************************** @@ -901,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 { @@ -924,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; @@ -963,7 +994,7 @@ struct acpi_port_info {  #define ACPI_RESOURCE_NAME_END_DEPENDENT        0x38  #define ACPI_RESOURCE_NAME_IO                   0x40  #define ACPI_RESOURCE_NAME_FIXED_IO             0x48 -#define ACPI_RESOURCE_NAME_RESERVED_S1          0x50 +#define ACPI_RESOURCE_NAME_FIXED_DMA            0x50  #define ACPI_RESOURCE_NAME_RESERVED_S2          0x58  #define ACPI_RESOURCE_NAME_RESERVED_S3          0x60  #define ACPI_RESOURCE_NAME_RESERVED_S4          0x68 @@ -985,7 +1016,9 @@ struct acpi_port_info {  #define ACPI_RESOURCE_NAME_EXTENDED_IRQ         0x89  #define ACPI_RESOURCE_NAME_ADDRESS64            0x8A  #define ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64   0x8B -#define ACPI_RESOURCE_NAME_LARGE_MAX            0x8B +#define ACPI_RESOURCE_NAME_GPIO                 0x8C +#define ACPI_RESOURCE_NAME_SERIAL_BUS           0x8E +#define ACPI_RESOURCE_NAME_LARGE_MAX            0x8E  /*****************************************************************************   * @@ -997,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; @@ -1012,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 @@ -1033,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 @@ -1070,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 8d5c9e0a495..4bceb11c738 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 d44d3bc5b84..ee1c040f321 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 bdbfaf22bd1..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 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -93,12 +92,10 @@  #define AOPOBJ_AML_CONSTANT         0x01	/* Integer is an AML constant */  #define AOPOBJ_STATIC_POINTER       0x02	/* Data is part of an ACPI table, don't delete */ -#define AOPOBJ_DATA_VALID           0x04	/* Object is intialized and data is valid */ +#define AOPOBJ_DATA_VALID           0x04	/* Object is initialized and data is valid */  #define AOPOBJ_OBJECT_INITIALIZED   0x08	/* Region is initialized, _REG was run */  #define AOPOBJ_SETUP_COMPLETE       0x10	/* Region setup is complete */  #define AOPOBJ_INVALID              0x20	/* Host OS won't allow a Region address */ -#define AOPOBJ_MODULE_LEVEL         0x40	/* Method is actually module-level code */ -#define AOPOBJ_MODIFIED_NAMESPACE   0x80	/* Method modified the namespace */  /******************************************************************************   * @@ -115,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   */ @@ -175,24 +172,33 @@ struct acpi_object_region {  };  struct acpi_object_method { -	ACPI_OBJECT_COMMON_HEADER u8 method_flags; +	ACPI_OBJECT_COMMON_HEADER u8 info_flags;  	u8 param_count;  	u8 sync_level;  	union acpi_operand_object *mutex;  	u8 *aml_start;  	union { -		ACPI_INTERNAL_METHOD implementation; +		acpi_internal_method implementation;  		union acpi_operand_object *handler; -	} extra; +	} dispatch;  	u32 aml_length;  	u8 thread_count;  	acpi_owner_id owner_id;  }; +/* Flags for info_flags field above */ + +#define ACPI_METHOD_MODULE_LEVEL        0x01	/* Method is actually module-level code */ +#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_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.   *   *****************************************************************************/ @@ -200,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 */ @@ -230,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.   *   *****************************************************************************/ @@ -248,6 +253,7 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};  	u32                             base_byte_offset;   /* Byte offset within containing object */\  	u32                             value;              /* Value to store into the Bank or Index register */\  	u8                              start_field_bit_offset;/* Bit offset within first field datum (0-63) */\ +	u8                              access_length;	/* For serial regions/fields */  struct acpi_object_field_common {	/* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */ @@ -255,7 +261,9 @@ struct acpi_object_field_common {	/* COMMON FIELD (for BUFFER, REGION, BANK, and  };  struct acpi_object_region_field { -	ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj;	/* Containing op_region object */ +	ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u16 resource_length; +	union acpi_operand_object *region_obj;	/* Containing op_region object */ +	u8 *resource_buffer;	/* resource_template for serial regions/fields */  };  struct acpi_object_bank_field { @@ -287,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 { @@ -300,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;  }; @@ -352,6 +360,7 @@ typedef enum {   */  struct acpi_object_extra {  	ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *method_REG;	/* _REG method for this region (if any) */ +	struct acpi_namespace_node *scope_node;  	void *region_context;	/* Region-specific data */  	u8 *aml_start;  	u32 aml_length; @@ -372,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 8c15ff43f42..dda0e6affcf 100644 --- a/drivers/acpi/acpica/acopcode.h +++ b/drivers/acpi/acpica/acopcode.h @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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).   */ @@ -93,6 +93,7 @@  #define ARGP_CONCAT_OP                  ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TARGET)  #define ARGP_CONCAT_RES_OP              ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TARGET)  #define ARGP_COND_REF_OF_OP             ARGP_LIST2 (ARGP_SUPERNAME,  ARGP_SUPERNAME) +#define ARGP_CONNECTFIELD_OP            ARGP_LIST1 (ARGP_NAMESTRING)  #define ARGP_CONTINUE_OP                ARG_NONE  #define ARGP_COPY_OP                    ARGP_LIST2 (ARGP_TERMARG,    ARGP_SIMPLENAME)  #define ARGP_CREATE_BIT_FIELD_OP        ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_NAME) @@ -164,6 +165,7 @@  #define ARGP_RETURN_OP                  ARGP_LIST1 (ARGP_TERMARG)  #define ARGP_REVISION_OP                ARG_NONE  #define ARGP_SCOPE_OP                   ARGP_LIST3 (ARGP_PKGLENGTH,  ARGP_NAME,          ARGP_TERMLIST) +#define ARGP_SERIALFIELD_OP             ARGP_LIST1 (ARGP_NAMESTRING)  #define ARGP_SHIFT_LEFT_OP              ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TARGET)  #define ARGP_SHIFT_RIGHT_OP             ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TARGET)  #define ARGP_SIGNAL_OP                  ARGP_LIST1 (ARGP_SUPERNAME) @@ -191,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).   * @@ -223,6 +225,7 @@  #define ARGI_CONCAT_OP                  ARGI_LIST3 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA,   ARGI_TARGETREF)  #define ARGI_CONCAT_RES_OP              ARGI_LIST3 (ARGI_BUFFER,     ARGI_BUFFER,        ARGI_TARGETREF)  #define ARGI_COND_REF_OF_OP             ARGI_LIST2 (ARGI_OBJECT_REF, ARGI_TARGETREF) +#define ARGI_CONNECTFIELD_OP            ARGI_INVALID_OPCODE  #define ARGI_CONTINUE_OP                ARGI_INVALID_OPCODE  #define ARGI_COPY_OP                    ARGI_LIST2 (ARGI_ANYTYPE,    ARGI_SIMPLE_TARGET)  #define ARGI_CREATE_BIT_FIELD_OP        ARGI_LIST3 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_REFERENCE) @@ -294,6 +297,7 @@  #define ARGI_RETURN_OP                  ARGI_INVALID_OPCODE  #define ARGI_REVISION_OP                ARG_NONE  #define ARGI_SCOPE_OP                   ARGI_INVALID_OPCODE +#define ARGI_SERIALFIELD_OP             ARGI_INVALID_OPCODE  #define ARGI_SHIFT_LEFT_OP              ARGI_LIST3 (ARGI_INTEGER,    ARGI_INTEGER,       ARGI_TARGETREF)  #define ARGI_SHIFT_RIGHT_OP             ARGI_LIST3 (ARGI_INTEGER,    ARGI_INTEGER,       ARGI_TARGETREF)  #define ARGI_SIGNAL_OP                  ARGI_LIST1 (ARGI_EVENT) diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h index d0bb0fd3e57..6168b85463e 100644 --- a/drivers/acpi/acpica/acparser.h +++ b/drivers/acpi/acpica/acparser.h @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 10998d369ad..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 - 2010, 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,15 +86,25 @@   *      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. Zero-length parent package is allowed. + *      object type + *      count + *      object type + *      count = 0 (optional) + *      (Used for _DLM) + *   *****************************************************************************/  enum acpi_return_package_types { @@ -105,34 +116,76 @@ enum acpi_return_package_types {  	ACPI_PTYPE2_PKG_COUNT = 6,  	ACPI_PTYPE2_FIXED = 7,  	ACPI_PTYPE2_MIN = 8, -	ACPI_PTYPE2_REV_FIXED = 9 +	ACPI_PTYPE2_REV_FIXED = 9, +	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.   * @@ -140,231 +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}}, -	{{"_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}}, - -	{{"_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}}, - -	{{"_DCK", 1, ACPI_RTYPE_INTEGER}}, -	{{"_DCS", 0, ACPI_RTYPE_INTEGER}}, -	{{"_DDC", 1, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER}}, -	{{"_DDN", 0, ACPI_RTYPE_STRING}}, -	{{"_DGS", 0, ACPI_RTYPE_INTEGER}}, -	{{"_DIS", 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}}, -	{{"_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}}, -	{{"_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 */ -	{{"_GSB", 0, ACPI_RTYPE_INTEGER}}, -	{{"_GTF", 0, ACPI_RTYPE_BUFFER}}, -	{{"_GTM", 0, ACPI_RTYPE_BUFFER}}, -	{{"_GTS", 1, 0}}, -	{{"_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}}, - -	{{"_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}}, - -	{{"_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 @@ -374,46 +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}}, - -	{{"_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 @@ -421,106 +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}}, -	{{"_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}}, -	{{"_SUN", 0, ACPI_RTYPE_INTEGER}}, -	{{"_SWS", 0, ACPI_RTYPE_INTEGER}}, -	{{"_TC1", 0, ACPI_RTYPE_INTEGER}}, -	{{"_TC2", 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 528bcbaf4ce..4b008e8884a 100644 --- a/drivers/acpi/acpica/acresrc.h +++ b/drivers/acpi/acpica/acresrc.h @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -73,28 +73,40 @@ typedef const struct acpi_rsconvert_info {  /* Resource conversion opcodes */ -#define ACPI_RSC_INITGET                0 -#define ACPI_RSC_INITSET                1 -#define ACPI_RSC_FLAGINIT               2 -#define ACPI_RSC_1BITFLAG               3 -#define ACPI_RSC_2BITFLAG               4 -#define ACPI_RSC_COUNT                  5 -#define ACPI_RSC_COUNT16                6 -#define ACPI_RSC_LENGTH                 7 -#define ACPI_RSC_MOVE8                  8 -#define ACPI_RSC_MOVE16                 9 -#define ACPI_RSC_MOVE32                 10 -#define ACPI_RSC_MOVE64                 11 -#define ACPI_RSC_SET8                   12 -#define ACPI_RSC_DATA8                  13 -#define ACPI_RSC_ADDRESS                14 -#define ACPI_RSC_SOURCE                 15 -#define ACPI_RSC_SOURCEX                16 -#define ACPI_RSC_BITMASK                17 -#define ACPI_RSC_BITMASK16              18 -#define ACPI_RSC_EXIT_NE                19 -#define ACPI_RSC_EXIT_LE                20 -#define ACPI_RSC_EXIT_EQ                21 +typedef enum { +	ACPI_RSC_INITGET = 0, +	ACPI_RSC_INITSET, +	ACPI_RSC_FLAGINIT, +	ACPI_RSC_1BITFLAG, +	ACPI_RSC_2BITFLAG, +	ACPI_RSC_3BITFLAG, +	ACPI_RSC_ADDRESS, +	ACPI_RSC_BITMASK, +	ACPI_RSC_BITMASK16, +	ACPI_RSC_COUNT, +	ACPI_RSC_COUNT16, +	ACPI_RSC_COUNT_GPIO_PIN, +	ACPI_RSC_COUNT_GPIO_RES, +	ACPI_RSC_COUNT_GPIO_VEN, +	ACPI_RSC_COUNT_SERIAL_RES, +	ACPI_RSC_COUNT_SERIAL_VEN, +	ACPI_RSC_DATA8, +	ACPI_RSC_EXIT_EQ, +	ACPI_RSC_EXIT_LE, +	ACPI_RSC_EXIT_NE, +	ACPI_RSC_LENGTH, +	ACPI_RSC_MOVE_GPIO_PIN, +	ACPI_RSC_MOVE_GPIO_RES, +	ACPI_RSC_MOVE_SERIAL_RES, +	ACPI_RSC_MOVE_SERIAL_VEN, +	ACPI_RSC_MOVE8, +	ACPI_RSC_MOVE16, +	ACPI_RSC_MOVE32, +	ACPI_RSC_MOVE64, +	ACPI_RSC_SET8, +	ACPI_RSC_SOURCE, +	ACPI_RSC_SOURCEX +} ACPI_RSCONVERT_OPCODES;  /* Resource Conversion sub-opcodes */ @@ -106,6 +118,9 @@ typedef const struct acpi_rsconvert_info {  #define ACPI_RS_OFFSET(f)               (u8) ACPI_OFFSET (struct acpi_resource,f)  #define AML_OFFSET(f)                   (u8) ACPI_OFFSET (union aml_resource,f) +/* + * Individual entry for the resource dump tables + */  typedef const struct acpi_rsdump_info {  	u8 opcode;  	u8 offset; @@ -116,20 +131,25 @@ typedef const struct acpi_rsdump_info {  /* Values for the Opcode field above */ -#define ACPI_RSD_TITLE                  0 -#define ACPI_RSD_LITERAL                1 -#define ACPI_RSD_STRING                 2 -#define ACPI_RSD_UINT8                  3 -#define ACPI_RSD_UINT16                 4 -#define ACPI_RSD_UINT32                 5 -#define ACPI_RSD_UINT64                 6 -#define ACPI_RSD_1BITFLAG               7 -#define ACPI_RSD_2BITFLAG               8 -#define ACPI_RSD_SHORTLIST              9 -#define ACPI_RSD_LONGLIST               10 -#define ACPI_RSD_DWORDLIST              11 -#define ACPI_RSD_ADDRESS                12 -#define ACPI_RSD_SOURCE                 13 +typedef enum { +	ACPI_RSD_TITLE = 0, +	ACPI_RSD_1BITFLAG, +	ACPI_RSD_2BITFLAG, +	ACPI_RSD_3BITFLAG, +	ACPI_RSD_ADDRESS, +	ACPI_RSD_DWORDLIST, +	ACPI_RSD_LITERAL, +	ACPI_RSD_LONGLIST, +	ACPI_RSD_SHORTLIST, +	ACPI_RSD_SHORTLISTX, +	ACPI_RSD_SOURCE, +	ACPI_RSD_STRING, +	ACPI_RSD_UINT8, +	ACPI_RSD_UINT16, +	ACPI_RSD_UINT32, +	ACPI_RSD_UINT64, +	ACPI_RSD_WORDLIST +} ACPI_RSDUMP_OPCODES;  /* restore default alignment */ @@ -138,13 +158,18 @@ typedef const struct acpi_rsdump_info {  /* Resource tables indexed by internal resource type */  extern const u8 acpi_gbl_aml_resource_sizes[]; +extern const u8 acpi_gbl_aml_resource_serial_bus_sizes[];  extern struct acpi_rsconvert_info *acpi_gbl_set_resource_dispatch[];  /* Resource tables indexed by raw AML resource descriptor type */  extern const u8 acpi_gbl_resource_struct_sizes[]; +extern const u8 acpi_gbl_resource_struct_serial_bus_sizes[];  extern struct acpi_rsconvert_info *acpi_gbl_get_resource_dispatch[]; +extern struct acpi_rsconvert_info +    *acpi_gbl_convert_resource_serial_bus_dispatch[]; +  struct acpi_vendor_walk_info {  	struct acpi_vendor_uuid *uuid;  	struct acpi_buffer *buffer; @@ -159,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 @@ -190,6 +215,10 @@ acpi_status  acpi_rs_set_srs_method_data(struct acpi_namespace_node *node,  			    struct acpi_buffer *ret_buffer); +acpi_status +acpi_rs_get_aei_method_data(struct acpi_namespace_node *node, +			    struct acpi_buffer *ret_buffer); +  /*   * rscalc   */ @@ -198,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, @@ -293,6 +322,11 @@ extern struct acpi_rsconvert_info acpi_rs_convert_address16[];  extern struct acpi_rsconvert_info acpi_rs_convert_ext_irq[];  extern struct acpi_rsconvert_info acpi_rs_convert_address64[];  extern struct acpi_rsconvert_info acpi_rs_convert_ext_address64[]; +extern struct acpi_rsconvert_info acpi_rs_convert_gpio[]; +extern struct acpi_rsconvert_info acpi_rs_convert_fixed_dma[]; +extern struct acpi_rsconvert_info acpi_rs_convert_i2c_serial_bus[]; +extern struct acpi_rsconvert_info acpi_rs_convert_spi_serial_bus[]; +extern struct acpi_rsconvert_info acpi_rs_convert_uart_serial_bus[];  /* These resources require separate get/set tables */ @@ -310,20 +344,24 @@ extern struct acpi_rsconvert_info acpi_rs_set_vendor[];   * rsinfo   */  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[]; @@ -331,6 +369,13 @@ extern struct acpi_rsdump_info acpi_rs_dump_address64[];  extern struct acpi_rsdump_info acpi_rs_dump_ext_address64[];  extern struct acpi_rsdump_info acpi_rs_dump_ext_irq[];  extern struct acpi_rsdump_info acpi_rs_dump_generic_reg[]; +extern struct acpi_rsdump_info acpi_rs_dump_gpio[]; +extern struct acpi_rsdump_info acpi_rs_dump_fixed_dma[]; +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 6e5dd97949f..cf7346110bd 100644 --- a/drivers/acpi/acpica/acstruct.h +++ b/drivers/acpi/acpica/acstruct.h @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 62a576e3436..f14882788ee 100644 --- a/drivers/acpi/acpica/actables.h +++ b/drivers/acpi/acpica/actables.h @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 72e4183c193..1e256c5bda2 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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,11 @@  #define _ACUTILS_H  extern const u8 acpi_gbl_resource_aml_sizes[]; +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[]; @@ -68,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 @@ -78,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); @@ -96,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 */ @@ -116,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); @@ -201,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 @@ -209,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, @@ -286,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); @@ -336,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 @@ -397,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 @@ -459,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 @@ -502,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); @@ -521,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 @@ -548,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); @@ -579,6 +687,24 @@ acpi_ut_create_list(char *list_name,  #endif				/* ACPI_DBG_TRACK_ALLOCATIONS */  /* + * utaddress - address range check + */ +acpi_status +acpi_ut_add_address_range(acpi_adr_space_type space_id, +			  acpi_physical_address address, +			  u32 length, struct acpi_namespace_node *region_node); + +void +acpi_ut_remove_address_range(acpi_adr_space_type space_id, +			     struct acpi_namespace_node *region_node); + +u32 +acpi_ut_check_address_range(acpi_adr_space_type space_id, +			    acpi_physical_address address, u32 length, u8 warn); + +void acpi_ut_delete_address_lists(void); + +/*   * utxferror - various error/warning output functions   */  void ACPI_INTERNAL_VAR_XFACE @@ -592,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, @@ -604,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 1f484ba228f..5908ccec6ae 100644 --- a/drivers/acpi/acpica/amlcode.h +++ b/drivers/acpi/acpica/amlcode.h @@ -7,7 +7,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -182,13 +182,21 @@  /*   * 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  #define AML_LNOTEQUAL_OP            (u16) 0x9293  /* + * Opcodes for "Field" operators + */ +#define AML_FIELD_OFFSET_OP         (u8) 0x00 +#define AML_FIELD_ACCESS_OP         (u8) 0x01 +#define AML_FIELD_CONNECTION_OP     (u8) 0x02	/* ACPI 5.0 */ +#define AML_FIELD_EXT_ACCESS_OP     (u8) 0x03	/* ACPI 5.0 */ + +/*   * Internal opcodes   * Use only "Unknown" AML opcodes, don't attempt to use   * any valid ACPI ASCII values (A-Z, 0-9, '-') @@ -202,6 +210,8 @@  #define AML_INT_METHODCALL_OP       (u16) 0x0035  #define AML_INT_RETURN_VALUE_OP     (u16) 0x0036  #define AML_INT_EVAL_SUBTREE_OP     (u16) 0x0037 +#define AML_INT_CONNECTION_OP       (u16) 0x0038 +#define AML_INT_EXTACCESSFIELD_OP   (u16) 0x0039  #define ARG_NONE                    0x0 @@ -270,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 */ @@ -394,21 +404,6 @@  #define AML_CLASS_METHOD_CALL       0x09  #define AML_CLASS_UNKNOWN           0x0A -/* Predefined Operation Region space_iDs */ - -typedef enum { -	REGION_MEMORY = 0, -	REGION_IO, -	REGION_PCI_CONFIG, -	REGION_EC, -	REGION_SMBUS, -	REGION_CMOS, -	REGION_PCI_BAR, -	REGION_IPMI, -	REGION_DATA_TABLE,	/* Internal use only */ -	REGION_FIXED_HW = 0x7F -} AML_REGION_TYPES; -  /* Comparison operation codes for match_op operator */  typedef enum { @@ -471,25 +466,22 @@ typedef enum {   * access_as keyword   */  typedef enum { -	AML_FIELD_ATTRIB_SMB_QUICK = 0x02, -	AML_FIELD_ATTRIB_SMB_SEND_RCV = 0x04, -	AML_FIELD_ATTRIB_SMB_BYTE = 0x06, -	AML_FIELD_ATTRIB_SMB_WORD = 0x08, -	AML_FIELD_ATTRIB_SMB_BLOCK = 0x0A, -	AML_FIELD_ATTRIB_SMB_WORD_CALL = 0x0C, -	AML_FIELD_ATTRIB_SMB_BLOCK_CALL = 0x0D +	AML_FIELD_ATTRIB_QUICK = 0x02, +	AML_FIELD_ATTRIB_SEND_RCV = 0x04, +	AML_FIELD_ATTRIB_BYTE = 0x06, +	AML_FIELD_ATTRIB_WORD = 0x08, +	AML_FIELD_ATTRIB_BLOCK = 0x0A, +	AML_FIELD_ATTRIB_MULTIBYTE = 0x0B, +	AML_FIELD_ATTRIB_WORD_CALL = 0x0C, +	AML_FIELD_ATTRIB_BLOCK_CALL = 0x0D, +	AML_FIELD_ATTRIB_RAW_BYTES = 0x0E, +	AML_FIELD_ATTRIB_RAW_PROCESS = 0x0F  } AML_ACCESS_ATTRIBUTE; -/* Bit fields in method_flags byte */ +/* Bit fields in the AML method_flags byte */  #define AML_METHOD_ARG_COUNT        0x07  #define AML_METHOD_SERIALIZED       0x08  #define AML_METHOD_SYNC_LEVEL       0xF0 -/* METHOD_FLAGS_ARG_COUNT is not used internally, define additional flags */ - -#define AML_METHOD_INTERNAL_ONLY    0x01 -#define AML_METHOD_RESERVED1        0x02 -#define AML_METHOD_RESERVED2        0x04 -  #endif				/* __AMLCODE_H__ */ diff --git a/drivers/acpi/acpica/amlresrc.h b/drivers/acpi/acpica/amlresrc.h index 0e5798fcbb1..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 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -58,29 +57,48 @@  #define ACPI_RESTAG_TYPESPECIFICATTRIBUTES      "_ATT"  #define ACPI_RESTAG_BASEADDRESS                 "_BAS"  #define ACPI_RESTAG_BUSMASTER                   "_BM_"	/* Master(1), Slave(0) */ +#define ACPI_RESTAG_DEBOUNCETIME                "_DBT"  #define ACPI_RESTAG_DECODE                      "_DEC" +#define ACPI_RESTAG_DEVICEPOLARITY              "_DPL"  #define ACPI_RESTAG_DMA                         "_DMA"  #define ACPI_RESTAG_DMATYPE                     "_TYP"	/* Compatible(0), A(1), B(2), F(3) */ +#define ACPI_RESTAG_DRIVESTRENGTH               "_DRS" +#define ACPI_RESTAG_ENDIANNESS                  "_END" +#define ACPI_RESTAG_FLOWCONTROL                 "_FLC"  #define ACPI_RESTAG_GRANULARITY                 "_GRA"  #define ACPI_RESTAG_INTERRUPT                   "_INT"  #define ACPI_RESTAG_INTERRUPTLEVEL              "_LL_"	/* active_lo(1), active_hi(0) */  #define ACPI_RESTAG_INTERRUPTSHARE              "_SHR"	/* Shareable(1), no_share(0) */  #define ACPI_RESTAG_INTERRUPTTYPE               "_HE_"	/* Edge(1), Level(0) */ +#define ACPI_RESTAG_IORESTRICTION               "_IOR"  #define ACPI_RESTAG_LENGTH                      "_LEN" +#define ACPI_RESTAG_LINE                        "_LIN"  #define ACPI_RESTAG_MEMATTRIBUTES               "_MTP"	/* Memory(0), Reserved(1), ACPI(2), NVS(3) */  #define ACPI_RESTAG_MEMTYPE                     "_MEM"	/* non_cache(0), Cacheable(1) Cache+combine(2), Cache+prefetch(3) */  #define ACPI_RESTAG_MAXADDR                     "_MAX"  #define ACPI_RESTAG_MINADDR                     "_MIN"  #define ACPI_RESTAG_MAXTYPE                     "_MAF"  #define ACPI_RESTAG_MINTYPE                     "_MIF" +#define ACPI_RESTAG_MODE                        "_MOD" +#define ACPI_RESTAG_PARITY                      "_PAR" +#define ACPI_RESTAG_PHASE                       "_PHA" +#define ACPI_RESTAG_PIN                         "_PIN" +#define ACPI_RESTAG_PINCONFIG                   "_PPI" +#define ACPI_RESTAG_POLARITY                    "_POL"  #define ACPI_RESTAG_REGISTERBITOFFSET           "_RBO"  #define ACPI_RESTAG_REGISTERBITWIDTH            "_RBW"  #define ACPI_RESTAG_RANGETYPE                   "_RNG"  #define ACPI_RESTAG_READWRITETYPE               "_RW_"	/* read_only(0), Writeable (1) */ +#define ACPI_RESTAG_LENGTH_RX                   "_RXL" +#define ACPI_RESTAG_LENGTH_TX                   "_TXL" +#define ACPI_RESTAG_SLAVEMODE                   "_SLV" +#define ACPI_RESTAG_SPEED                       "_SPE" +#define ACPI_RESTAG_STOPBITS                    "_STB"  #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 */ @@ -90,6 +108,7 @@  #define ASL_RDESC_END_DEPEND_SIZE               0x00  #define ASL_RDESC_IO_SIZE                       0x07  #define ASL_RDESC_FIXED_IO_SIZE                 0x03 +#define ASL_RDESC_FIXED_DMA_SIZE                0x05  #define ASL_RDESC_END_TAG_SIZE                  0x01  struct asl_resource_node { @@ -164,6 +183,12 @@ struct aml_resource_end_tag {  	AML_RESOURCE_SMALL_HEADER_COMMON u8 checksum;  }; +struct aml_resource_fixed_dma { +	AML_RESOURCE_SMALL_HEADER_COMMON u16 request_lines; +	u16 channels; +	u8 width; +}; +  /*   * LARGE descriptors   */ @@ -174,6 +199,12 @@ struct aml_resource_end_tag {  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; @@ -209,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; @@ -263,6 +294,110 @@ struct aml_resource_generic_register {  	u64 address;  }; +/* Common descriptor for gpio_int and gpio_io (ACPI 5.0) */ + +struct aml_resource_gpio { +	AML_RESOURCE_LARGE_HEADER_COMMON u8 revision_id; +	u8 connection_type; +	u16 flags; +	u16 int_flags; +	u8 pin_config; +	u16 drive_strength; +	u16 debounce_timeout; +	u16 pin_table_offset; +	u8 res_source_index; +	u16 res_source_offset; +	u16 vendor_offset; +	u16 vendor_length; +	/* +	 * Optional fields follow immediately: +	 * 1) PIN list (Words) +	 * 2) Resource Source String +	 * 3) Vendor Data bytes +	 */ +}; + +#define AML_RESOURCE_GPIO_REVISION              1	/* ACPI 5.0 */ + +/* Values for connection_type above */ + +#define AML_RESOURCE_GPIO_TYPE_INT              0 +#define AML_RESOURCE_GPIO_TYPE_IO               1 +#define AML_RESOURCE_MAX_GPIOTYPE               1 + +/* Common preamble for all serial descriptors (ACPI 5.0) */ + +#define AML_RESOURCE_SERIAL_COMMON \ +	u8                              revision_id; \ +	u8                              res_source_index; \ +	u8                              type; \ +	u8                              flags; \ +	u16                             type_specific_flags; \ +	u8                              type_revision_id; \ +	u16                             type_data_length; \ + +/* Values for the type field above */ + +#define AML_RESOURCE_I2C_SERIALBUSTYPE          1 +#define AML_RESOURCE_SPI_SERIALBUSTYPE          2 +#define AML_RESOURCE_UART_SERIALBUSTYPE         3 +#define AML_RESOURCE_MAX_SERIALBUSTYPE          3 +#define AML_RESOURCE_VENDOR_SERIALBUSTYPE       192	/* Vendor defined is 0xC0-0xFF (NOT SUPPORTED) */ + +struct aml_resource_common_serialbus { +AML_RESOURCE_LARGE_HEADER_COMMON AML_RESOURCE_SERIAL_COMMON}; + +struct aml_resource_i2c_serialbus { +	AML_RESOURCE_LARGE_HEADER_COMMON +	    AML_RESOURCE_SERIAL_COMMON u32 connection_speed; +	u16 slave_address; +	/* +	 * Optional fields follow immediately: +	 * 1) Vendor Data bytes +	 * 2) Resource Source String +	 */ +}; + +#define AML_RESOURCE_I2C_REVISION               1	/* ACPI 5.0 */ +#define AML_RESOURCE_I2C_TYPE_REVISION          1	/* ACPI 5.0 */ +#define AML_RESOURCE_I2C_MIN_DATA_LEN           6 + +struct aml_resource_spi_serialbus { +	AML_RESOURCE_LARGE_HEADER_COMMON +	    AML_RESOURCE_SERIAL_COMMON u32 connection_speed; +	u8 data_bit_length; +	u8 clock_phase; +	u8 clock_polarity; +	u16 device_selection; +	/* +	 * Optional fields follow immediately: +	 * 1) Vendor Data bytes +	 * 2) Resource Source String +	 */ +}; + +#define AML_RESOURCE_SPI_REVISION               1	/* ACPI 5.0 */ +#define AML_RESOURCE_SPI_TYPE_REVISION          1	/* ACPI 5.0 */ +#define AML_RESOURCE_SPI_MIN_DATA_LEN           9 + +struct aml_resource_uart_serialbus { +	AML_RESOURCE_LARGE_HEADER_COMMON +	    AML_RESOURCE_SERIAL_COMMON u32 default_baud_rate; +	u16 rx_fifo_size; +	u16 tx_fifo_size; +	u8 parity; +	u8 lines_enabled; +	/* +	 * Optional fields follow immediately: +	 * 1) Vendor Data bytes +	 * 2) Resource Source String +	 */ +}; + +#define AML_RESOURCE_UART_REVISION              1	/* ACPI 5.0 */ +#define AML_RESOURCE_UART_TYPE_REVISION         1	/* ACPI 5.0 */ +#define AML_RESOURCE_UART_MIN_DATA_LEN          10 +  /* restore default alignment */  #pragma pack() @@ -284,6 +419,7 @@ union aml_resource {  	struct aml_resource_end_dependent end_dpf;  	struct aml_resource_io io;  	struct aml_resource_fixed_io fixed_io; +	struct aml_resource_fixed_dma fixed_dma;  	struct aml_resource_vendor_small vendor_small;  	struct aml_resource_end_tag end_tag; @@ -299,6 +435,11 @@ union aml_resource {  	struct aml_resource_address64 address64;  	struct aml_resource_extended_address64 ext_address64;  	struct aml_resource_extended_irq extended_irq; +	struct aml_resource_gpio gpio; +	struct aml_resource_i2c_serialbus i2c_serial_bus; +	struct aml_resource_spi_serialbus spi_serial_bus; +	struct aml_resource_uart_serialbus uart_serial_bus; +	struct aml_resource_common_serialbus common_serial_bus;  	/* Utility overlays */ diff --git a/drivers/acpi/acpica/dsargs.c b/drivers/acpi/acpica/dsargs.c new file mode 100644 index 00000000000..720b1cdda71 --- /dev/null +++ b/drivers/acpi/acpica/dsargs.c @@ -0,0 +1,405 @@ +/****************************************************************************** + * + * Module Name: dsargs - Support for execution of dynamic arguments for static + *                       objects (regions, fields, buffer fields, etc.) + * + *****************************************************************************/ + +/* + * 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" +#include "acdispat.h" +#include "acnamesp.h" + +#define _COMPONENT          ACPI_DISPATCHER +ACPI_MODULE_NAME("dsargs") + +/* Local prototypes */ +static acpi_status +acpi_ds_execute_arguments(struct acpi_namespace_node *node, +			  struct acpi_namespace_node *scope_node, +			  u32 aml_length, u8 *aml_start); + +/******************************************************************************* + * + * FUNCTION:    acpi_ds_execute_arguments + * + * PARAMETERS:  node                - Object NS node + *              scope_node          - Parent NS node + *              aml_length          - Length of executable AML + *              aml_start           - Pointer to the AML + * + * RETURN:      Status. + * + * DESCRIPTION: Late (deferred) execution of region or field arguments + * + ******************************************************************************/ + +static acpi_status +acpi_ds_execute_arguments(struct acpi_namespace_node *node, +			  struct acpi_namespace_node *scope_node, +			  u32 aml_length, u8 *aml_start) +{ +	acpi_status status; +	union acpi_parse_object *op; +	struct acpi_walk_state *walk_state; + +	ACPI_FUNCTION_TRACE(ds_execute_arguments); + +	/* Allocate a new parser op to be the root of the parsed tree */ + +	op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); +	if (!op) { +		return_ACPI_STATUS(AE_NO_MEMORY); +	} + +	/* Save the Node for use in acpi_ps_parse_aml */ + +	op->common.node = scope_node; + +	/* Create and initialize a new parser state */ + +	walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); +	if (!walk_state) { +		status = AE_NO_MEMORY; +		goto cleanup; +	} + +	status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, +				       aml_length, NULL, ACPI_IMODE_LOAD_PASS1); +	if (ACPI_FAILURE(status)) { +		acpi_ds_delete_walk_state(walk_state); +		goto cleanup; +	} + +	/* Mark this parse as a deferred opcode */ + +	walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP; +	walk_state->deferred_node = node; + +	/* Pass1: Parse the entire declaration */ + +	status = acpi_ps_parse_aml(walk_state); +	if (ACPI_FAILURE(status)) { +		goto cleanup; +	} + +	/* Get and init the Op created above */ + +	op->common.node = node; +	acpi_ps_delete_parse_tree(op); + +	/* Evaluate the deferred arguments */ + +	op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); +	if (!op) { +		return_ACPI_STATUS(AE_NO_MEMORY); +	} + +	op->common.node = scope_node; + +	/* Create and initialize a new parser state */ + +	walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); +	if (!walk_state) { +		status = AE_NO_MEMORY; +		goto cleanup; +	} + +	/* Execute the opcode and arguments */ + +	status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, +				       aml_length, NULL, ACPI_IMODE_EXECUTE); +	if (ACPI_FAILURE(status)) { +		acpi_ds_delete_walk_state(walk_state); +		goto cleanup; +	} + +	/* Mark this execution as a deferred opcode */ + +	walk_state->deferred_node = node; +	status = acpi_ps_parse_aml(walk_state); + +cleanup: +	acpi_ps_delete_parse_tree(op); +	return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ds_get_buffer_field_arguments + * + * PARAMETERS:  obj_desc        - A valid buffer_field object + * + * RETURN:      Status. + * + * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late + *              evaluation of these field attributes. + * + ******************************************************************************/ + +acpi_status +acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) +{ +	union acpi_operand_object *extra_desc; +	struct acpi_namespace_node *node; +	acpi_status status; + +	ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc); + +	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { +		return_ACPI_STATUS(AE_OK); +	} + +	/* Get the AML pointer (method object) and buffer_field node */ + +	extra_desc = acpi_ns_get_secondary_object(obj_desc); +	node = obj_desc->buffer_field.node; + +	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_BUFFER_FIELD, +						      node, NULL)); + +	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n", +			  acpi_ut_get_node_name(node))); + +	/* Execute the AML code for the term_arg arguments */ + +	status = acpi_ds_execute_arguments(node, node->parent, +					   extra_desc->extra.aml_length, +					   extra_desc->extra.aml_start); +	return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ds_get_bank_field_arguments + * + * PARAMETERS:  obj_desc        - A valid bank_field object + * + * RETURN:      Status. + * + * DESCRIPTION: Get bank_field bank_value. This implements the late + *              evaluation of these field attributes. + * + ******************************************************************************/ + +acpi_status +acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc) +{ +	union acpi_operand_object *extra_desc; +	struct acpi_namespace_node *node; +	acpi_status status; + +	ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc); + +	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { +		return_ACPI_STATUS(AE_OK); +	} + +	/* Get the AML pointer (method object) and bank_field node */ + +	extra_desc = acpi_ns_get_secondary_object(obj_desc); +	node = obj_desc->bank_field.node; + +	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname +			(ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL)); + +	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", +			  acpi_ut_get_node_name(node))); + +	/* Execute the AML code for the term_arg arguments */ + +	status = acpi_ds_execute_arguments(node, node->parent, +					   extra_desc->extra.aml_length, +					   extra_desc->extra.aml_start); +	if (ACPI_FAILURE(status)) { +		return_ACPI_STATUS(status); +	} + +	status = acpi_ut_add_address_range(obj_desc->region.space_id, +					   obj_desc->region.address, +					   obj_desc->region.length, node); +	return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ds_get_buffer_arguments + * + * PARAMETERS:  obj_desc        - A valid Buffer object + * + * RETURN:      Status. + * + * DESCRIPTION: Get Buffer length and initializer byte list. This implements + *              the late evaluation of these attributes. + * + ******************************************************************************/ + +acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc) +{ +	struct acpi_namespace_node *node; +	acpi_status status; + +	ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc); + +	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { +		return_ACPI_STATUS(AE_OK); +	} + +	/* Get the Buffer node */ + +	node = obj_desc->buffer.node; +	if (!node) { +		ACPI_ERROR((AE_INFO, +			    "No pointer back to namespace node in buffer object %p", +			    obj_desc)); +		return_ACPI_STATUS(AE_AML_INTERNAL); +	} + +	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n")); + +	/* Execute the AML code for the term_arg arguments */ + +	status = acpi_ds_execute_arguments(node, node, +					   obj_desc->buffer.aml_length, +					   obj_desc->buffer.aml_start); +	return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ds_get_package_arguments + * + * PARAMETERS:  obj_desc        - A valid Package object + * + * RETURN:      Status. + * + * DESCRIPTION: Get Package length and initializer byte list. This implements + *              the late evaluation of these attributes. + * + ******************************************************************************/ + +acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc) +{ +	struct acpi_namespace_node *node; +	acpi_status status; + +	ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc); + +	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { +		return_ACPI_STATUS(AE_OK); +	} + +	/* Get the Package node */ + +	node = obj_desc->package.node; +	if (!node) { +		ACPI_ERROR((AE_INFO, +			    "No pointer back to namespace node in package %p", +			    obj_desc)); +		return_ACPI_STATUS(AE_AML_INTERNAL); +	} + +	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n")); + +	/* Execute the AML code for the term_arg arguments */ + +	status = acpi_ds_execute_arguments(node, node, +					   obj_desc->package.aml_length, +					   obj_desc->package.aml_start); +	return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ds_get_region_arguments + * + * PARAMETERS:  obj_desc        - A valid region object + * + * RETURN:      Status. + * + * DESCRIPTION: Get region address and length. This implements the late + *              evaluation of these region attributes. + * + ******************************************************************************/ + +acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) +{ +	struct acpi_namespace_node *node; +	acpi_status status; +	union acpi_operand_object *extra_desc; + +	ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc); + +	if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { +		return_ACPI_STATUS(AE_OK); +	} + +	extra_desc = acpi_ns_get_secondary_object(obj_desc); +	if (!extra_desc) { +		return_ACPI_STATUS(AE_NOT_EXIST); +	} + +	/* Get the Region node */ + +	node = obj_desc->region.node; + +	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname +			(ACPI_TYPE_REGION, node, NULL)); + +	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n", +			  acpi_ut_get_node_name(node), +			  extra_desc->extra.aml_start)); + +	/* Execute the argument AML */ + +	status = acpi_ds_execute_arguments(node, extra_desc->extra.scope_node, +					   extra_desc->extra.aml_length, +					   extra_desc->extra.aml_start); +	if (ACPI_FAILURE(status)) { +		return_ACPI_STATUS(status); +	} + +	status = acpi_ut_add_address_range(obj_desc->region.space_id, +					   obj_desc->region.address, +					   obj_desc->region.length, node); +	return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c new file mode 100644 index 00000000000..8daf9de82b7 --- /dev/null +++ b/drivers/acpi/acpica/dscontrol.c @@ -0,0 +1,410 @@ +/****************************************************************************** + * + * Module Name: dscontrol - Support for execution control opcodes - + *                          if/else/while/return + * + *****************************************************************************/ + +/* + * 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 "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" + +#define _COMPONENT          ACPI_DISPATCHER +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 + * + * RETURN:      Status + * + * DESCRIPTION: Handles all control ops encountered during control method + *              execution. + * + ******************************************************************************/ +acpi_status +acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, +			      union acpi_parse_object *op) +{ +	acpi_status status = AE_OK; +	union acpi_generic_state *control_state; + +	ACPI_FUNCTION_NAME(ds_exec_begin_control_op); + +	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", +			  op, op->common.aml_opcode, 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. +		 */ +		if (walk_state->control_state) { +			if (walk_state->control_state->control. +			    aml_predicate_start == +			    (walk_state->parser_state.aml - 1)) { + +				/* Reset the state to start-of-loop */ + +				walk_state->control_state->common.state = +				    ACPI_CONTROL_CONDITIONAL_EXECUTING; +				break; +			} +		} + +		/*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 +		 * to handle nesting. +		 */ +		control_state = acpi_ut_create_control_state(); +		if (!control_state) { +			status = AE_NO_MEMORY; +			break; +		} +		/* +		 * Save a pointer to the predicate for multiple executions +		 * of a loop +		 */ +		control_state->control.aml_predicate_start = +		    walk_state->parser_state.aml - 1; +		control_state->control.package_end = +		    walk_state->parser_state.pkg_end; +		control_state->control.opcode = op->common.aml_opcode; + +		/* Push the control state on this walk's control stack */ + +		acpi_ut_push_generic_state(&walk_state->control_state, +					   control_state); +		break; + +	case AML_ELSE_OP: + +		/* Predicate is in the state object */ +		/* If predicate is true, the IF was executed, ignore ELSE part */ + +		if (walk_state->last_predicate) { +			status = AE_CTRL_TRUE; +		} + +		break; + +	case AML_RETURN_OP: + +		break; + +	default: + +		break; +	} + +	return (status); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ds_exec_end_control_op + * + * PARAMETERS:  walk_list       - The list that owns the walk stack + *              op              - The control Op + * + * RETURN:      Status + * + * DESCRIPTION: Handles all control ops encountered during control method + *              execution. + * + ******************************************************************************/ + +acpi_status +acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, +			    union acpi_parse_object * op) +{ +	acpi_status status = AE_OK; +	union acpi_generic_state *control_state; + +	ACPI_FUNCTION_NAME(ds_exec_end_control_op); + +	switch (op->common.aml_opcode) { +	case AML_IF_OP: + +		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op)); + +		/* +		 * Save the result of the predicate in case there is an +		 * ELSE to come +		 */ +		walk_state->last_predicate = +		    (u8)walk_state->control_state->common.value; + +		/* +		 * Pop the control state that was created at the start +		 * of the IF and free it +		 */ +		control_state = +		    acpi_ut_pop_generic_state(&walk_state->control_state); +		acpi_ut_delete_generic_state(control_state); +		break; + +	case AML_ELSE_OP: + +		break; + +	case AML_WHILE_OP: + +		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op)); + +		control_state = walk_state->control_state; +		if (control_state->common.value) { + +			/* Predicate was true, the body of the loop was just executed */ + +			/* +			 * This loop counter mechanism allows the interpreter to escape +			 * possibly infinite loops. This can occur in poorly written AML +			 * when the hardware does not respond within a while loop and the +			 * loop does not implement a timeout. +			 */ +			control_state->control.loop_count++; +			if (control_state->control.loop_count > +			    ACPI_MAX_LOOP_ITERATIONS) { +				status = AE_AML_INFINITE_LOOP; +				break; +			} + +			/* +			 * Go back and evaluate the predicate and maybe execute the loop +			 * another time +			 */ +			status = AE_CTRL_PENDING; +			walk_state->aml_last_while = +			    control_state->control.aml_predicate_start; +			break; +		} + +		/* Predicate was false, terminate this while loop */ + +		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, +				  "[WHILE_OP] termination! Op=%p\n", op)); + +		/* Pop this control state and free it */ + +		control_state = +		    acpi_ut_pop_generic_state(&walk_state->control_state); +		acpi_ut_delete_generic_state(control_state); +		break; + +	case AML_RETURN_OP: + +		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, +				  "[RETURN_OP] Op=%p Arg=%p\n", op, +				  op->common.value.arg)); + +		/* +		 * One optional operand -- the return value +		 * It can be either an immediate operand or a result that +		 * has been bubbled up the tree +		 */ +		if (op->common.value.arg) { + +			/* Since we have a real Return(), delete any implicit return */ + +			acpi_ds_clear_implicit_return(walk_state); + +			/* Return statement has an immediate operand */ + +			status = +			    acpi_ds_create_operands(walk_state, +						    op->common.value.arg); +			if (ACPI_FAILURE(status)) { +				return (status); +			} + +			/* +			 * If value being returned is a Reference (such as +			 * an arg or local), resolve it now because it may +			 * cease to exist at the end of the method. +			 */ +			status = +			    acpi_ex_resolve_to_value(&walk_state->operands[0], +						     walk_state); +			if (ACPI_FAILURE(status)) { +				return (status); +			} + +			/* +			 * Get the return value and save as the last result +			 * 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]; +		} else if (walk_state->result_count) { + +			/* Since we have a real Return(), delete any implicit return */ + +			acpi_ds_clear_implicit_return(walk_state); + +			/* +			 * The return value has come from a previous calculation. +			 * +			 * If value being returned is a Reference (such as +			 * an arg or local), resolve it now because it may +			 * cease to exist at the end of the method. +			 * +			 * Allow references created by the Index operator to return +			 * unchanged. +			 */ +			if ((ACPI_GET_DESCRIPTOR_TYPE +			     (walk_state->results->results.obj_desc[0]) == +			     ACPI_DESC_TYPE_OPERAND) +			    && ((walk_state->results->results.obj_desc[0])-> +				common.type == ACPI_TYPE_LOCAL_REFERENCE) +			    && ((walk_state->results->results.obj_desc[0])-> +				reference.class != ACPI_REFCLASS_INDEX)) { +				status = +				    acpi_ex_resolve_to_value(&walk_state-> +							     results->results. +							     obj_desc[0], +							     walk_state); +				if (ACPI_FAILURE(status)) { +					return (status); +				} +			} + +			walk_state->return_desc = +			    walk_state->results->results.obj_desc[0]; +		} else { +			/* No return operand */ + +			if (walk_state->num_operands) { +				acpi_ut_remove_reference(walk_state-> +							 operands[0]); +			} + +			walk_state->operands[0] = NULL; +			walk_state->num_operands = 0; +			walk_state->return_desc = NULL; +		} + +		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, +				  "Completed RETURN_OP State=%p, RetVal=%p\n", +				  walk_state, walk_state->return_desc)); + +		/* End the control method execution right now */ + +		status = AE_CTRL_TERMINATE; +		break; + +	case AML_NOOP_OP: + +		/* Just do nothing! */ + +		break; + +	case AML_BREAK_POINT_OP: + +		/* +		 * Set the single-step flag. This will cause the debugger (if present) +		 * to break to the console within the AML debugger at the start of the +		 * next AML instruction. +		 */ +		ACPI_DEBUGGER_EXEC(acpi_gbl_cm_single_step = TRUE); +		ACPI_DEBUGGER_EXEC(acpi_os_printf +				   ("**break** Executed AML BreakPoint opcode\n")); + +		/* Call to the OSL in case OS wants a piece of the action */ + +		status = acpi_os_signal(ACPI_SIGNAL_BREAKPOINT, +					"Executed AML Breakpoint opcode"); +		break; + +	case AML_BREAK_OP: +	case AML_CONTINUE_OP:	/* ACPI 2.0 */ + +		/* Pop and delete control states until we find a while */ + +		while (walk_state->control_state && +		       (walk_state->control_state->control.opcode != +			AML_WHILE_OP)) { +			control_state = +			    acpi_ut_pop_generic_state(&walk_state-> +						      control_state); +			acpi_ut_delete_generic_state(control_state); +		} + +		/* No while found? */ + +		if (!walk_state->control_state) { +			return (AE_AML_NO_WHILE); +		} + +		/* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */ + +		walk_state->aml_last_while = +		    walk_state->control_state->control.package_end; + +		/* Return status depending on opcode */ + +		if (op->common.aml_opcode == AML_BREAK_OP) { +			status = AE_CTRL_BREAK; +		} else { +			status = AE_CTRL_CONTINUE; +		} +		break; + +	default: + +		ACPI_ERROR((AE_INFO, "Unknown control opcode=0x%X Op=%p", +			    op->common.aml_opcode, op)); + +		status = AE_AML_BAD_OPCODE; +		break; +	} + +	return (status); +} diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c index 347bee1726f..3661c8e9054 100644 --- a/drivers/acpi/acpica/dsfield.c +++ b/drivers/acpi/acpica/dsfield.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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.   *   ******************************************************************************/ @@ -221,6 +289,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,  {  	acpi_status status;  	u64 position; +	union acpi_parse_object *child;  	ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info); @@ -232,10 +301,11 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,  	while (arg) {  		/* -		 * Three types of field elements are handled: -		 * 1) Offset - specifies a bit offset -		 * 2) access_as - changes the access mode -		 * 3) Name - Enters a new named field into the namespace +		 * Four types of field elements are handled: +		 * 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  		 */  		switch (arg->common.aml_opcode) {  		case AML_INT_RESERVEDFIELD_OP: @@ -253,21 +323,70 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,  			break;  		case AML_INT_ACCESSFIELD_OP: - +		case AML_INT_EXTACCESSFIELD_OP:  			/* -			 * Get a new access_type and access_attribute -- to be used for all -			 * field units that follow, until field end or another access_as -			 * keyword. +			 * Get new access_type, access_attribute, and access_length fields +			 * -- to be used for all field units that follow, until the +			 * end-of-field or another access_as keyword is encountered. +			 * NOTE. These three bytes are encoded in the integer value +			 * of the parseop for convenience.  			 *  			 * In field_flags, preserve the flag bits other than the -			 * ACCESS_TYPE bits +			 * ACCESS_TYPE bits.  			 */ + +			/* access_type (byte_acc, word_acc, etc.) */ +  			info->field_flags = (u8)  			    ((info->  			      field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) | -			     ((u8) ((u32) arg->common.value.integer >> 8))); +			     ((u8)((u32)(arg->common.value.integer & 0x07)))); + +			/* access_attribute (attrib_quick, attrib_byte, etc.) */ + +			info->attribute = +			    (u8)((arg->common.value.integer >> 8) & 0xFF); -			info->attribute = (u8) (arg->common.value.integer); +			/* access_length (for serial/buffer protocols) */ + +			info->access_length = +			    (u8)((arg->common.value.integer >> 16) & 0xFF); +			break; + +		case AML_INT_CONNECTION_OP: +			/* +			 * Clear any previous connection. New connection is used for all +			 * fields that follow, similar to access_as +			 */ +			info->resource_buffer = NULL; +			info->connection_node = NULL; + +			/* +			 * A Connection() is either an actual resource descriptor (buffer) +			 * or a named reference to a resource template +			 */ +			child = arg->common.value.arg; +			if (child->common.aml_opcode == AML_INT_BYTELIST_OP) { +				info->resource_buffer = child->named.data; +				info->resource_length = +				    (u16)child->named.value.integer; +			} else { +				/* Lookup the Connection() namepath, it should already exist */ + +				status = acpi_ns_lookup(walk_state->scope_info, +							child->common.value. +							name, ACPI_TYPE_ANY, +							ACPI_IMODE_EXECUTE, +							ACPI_NS_DONT_OPEN_SCOPE, +							walk_state, +							&info->connection_node); +				if (ACPI_FAILURE(status)) { +					ACPI_ERROR_NAMESPACE(child->common. +							     value.name, +							     status); +					return_ACPI_STATUS(status); +				} +			}  			break;  		case AML_INT_NAMEDFIELD_OP: @@ -338,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   * @@ -362,18 +481,27 @@ 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);  		}  	} +	ACPI_MEMSET(&info, 0, sizeof(struct acpi_create_field_info)); +  	/* Second arg is the field flags */  	arg = arg->common.next; @@ -386,7 +514,6 @@ acpi_ds_create_field(union acpi_parse_object *op,  	info.region_node = region_node;  	status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); -  	return_ACPI_STATUS(status);  } @@ -394,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 @@ -436,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);  	} @@ -474,8 +605,8 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,  	 */  	while (arg) {  		/* -		 * Ignore OFFSET and ACCESSAS terms here; we are only interested in the -		 * field names in order to enter them into the namespace. +		 * Ignore OFFSET/ACCESSAS/CONNECTION terms here; we are only interested +		 * in the field names in order to enter them into the namespace.  		 */  		if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {  			status = acpi_ns_lookup(walk_state->scope_info, @@ -509,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   * @@ -539,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); @@ -593,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   * @@ -651,6 +788,5 @@ acpi_ds_create_index_field(union acpi_parse_object *op,  	info.region_node = region_node;  	status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); -  	return_ACPI_STATUS(status);  } diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c index cc4a38c5755..aee5e45f6d3 100644 --- a/drivers/acpi/acpica/dsinit.c +++ b/drivers/acpi/acpica/dsinit.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 d94dd8974b5..3c7f7378b94 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -43,26 +43,164 @@  #include <acpi/acpi.h>  #include "accommon.h" -#include "amlcode.h"  #include "acdispat.h"  #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 @@ -75,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(); @@ -152,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);  	} @@ -171,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.   * @@ -201,7 +340,7 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,  	/*  	 * If this method is serialized, we need to acquire the method mutex.  	 */ -	if (obj_desc->method.method_flags & AML_METHOD_SERIALIZED) { +	if (obj_desc->method.info_flags & ACPI_METHOD_SERIALIZED) {  		/*  		 * Create a mutex for the method if it is defined to be Serialized  		 * and a mutex has not already been created. We defer the mutex creation @@ -217,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), @@ -292,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) { @@ -307,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   * @@ -379,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]; @@ -413,8 +560,9 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,  	/* Invoke an internal method if necessary */ -	if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { -		status = obj_desc->method.extra.implementation(next_walk_state); +	if (obj_desc->method.info_flags & ACPI_METHOD_INTERNAL_ONLY) { +		status = +		    obj_desc->method.dispatch.implementation(next_walk_state);  		if (status == AE_OK) {  			status = AE_CTRL_TERMINATE;  		} @@ -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.   * @@ -579,11 +727,14 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,  		/*  		 * Delete any namespace objects created anywhere within the -		 * namespace by the execution of this method. Unless this method -		 * is a module-level executable code method, in which case we -		 * want make the objects permanent. +		 * namespace by the execution of this method. Unless: +		 * 1) This method is a module-level executable code method, in which +		 *    case we want make the objects permanent. +		 * 2) There are other threads executing the method, in which case we +		 *    will wait until the last thread has completed.  		 */ -		if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) { +		if (!(method_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) +		    && (method_desc->method.thread_count == 1)) {  			/* Delete any direct children of (created by) this method */ @@ -593,12 +744,17 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,  			/*  			 * Delete any objects that were created by this method  			 * elsewhere in the namespace (if any were created). +			 * Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the +			 * deletion such that we don't have to perform an entire +			 * namespace walk for every control method execution.  			 */  			if (method_desc->method. -			    flags & AOPOBJ_MODIFIED_NAMESPACE) { +			    info_flags & ACPI_METHOD_MODIFIED_NAMESPACE) {  				acpi_ns_delete_namespace_by_owner(method_desc->  								  method.  								  owner_id); +				method_desc->method.info_flags &= +				    ~ACPI_METHOD_MODIFIED_NAMESPACE;  			}  		}  	} @@ -629,19 +785,44 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,  		 * Serialized if it appears that the method is incorrectly written and  		 * does not support multiple thread execution. The best example of this  		 * is if such a method creates namespace objects and blocks. A second -		 * thread will fail with an AE_ALREADY_EXISTS exception +		 * thread will fail with an AE_ALREADY_EXISTS exception.  		 *  		 * This code is here because we must wait until the last thread exits -		 * before creating the synchronization semaphore. +		 * before marking the method as serialized.  		 */ -		if ((method_desc->method.method_flags & AML_METHOD_SERIALIZED) -		    && (!method_desc->method.mutex)) { -			(void)acpi_ds_create_method_mutex(method_desc); +		if (method_desc->method. +		    info_flags & ACPI_METHOD_SERIALIZED_PENDING) { +			if (walk_state) { +				ACPI_INFO((AE_INFO, +					   "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error", +					   walk_state->method_node->name. +					   ascii)); +			} + +			/* +			 * Method tried to create an object twice and was marked as +			 * "pending serialized". The probable cause is that the method +			 * cannot handle reentrancy. +			 * +			 * The method was created as not_serialized, but it tried to create +			 * a named object and then blocked, causing the second thread +			 * entrance to begin and then fail. Workaround this problem by +			 * marking the method permanently as Serialized when the last +			 * thread exits here. +			 */ +			method_desc->method.info_flags &= +			    ~ACPI_METHOD_SERIALIZED_PENDING; +			method_desc->method.info_flags |= +			    (ACPI_METHOD_SERIALIZED | +			     ACPI_METHOD_IGNORE_SYNC_LEVEL); +			method_desc->method.sync_level = 0;  		}  		/* No more threads, we can free the owner_id */ -		if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) { +		if (! +		    (method_desc->method. +		     info_flags & ACPI_METHOD_MODULE_LEVEL)) {  			acpi_ut_release_owner_id(&method_desc->method.owner_id);  		}  	} diff --git a/drivers/acpi/acpica/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c index 8095306fcd8..b67522df01a 100644 --- a/drivers/acpi/acpica/dsmthdat.c +++ b/drivers/acpi/acpica/dsmthdat.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 8e85f54a8e0..a1e7e6b6fcf 100644 --- a/drivers/acpi/acpica/dsobject.c +++ b/drivers/acpi/acpica/dsobject.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 7c0e7422717..6c0759c0db4 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -1,12 +1,11 @@  /******************************************************************************   * - * Module Name: dsopcode - Dispatcher Op Region support and handling of - *                         "control" opcodes + * Module Name: dsopcode - Dispatcher support for regions and fields   *   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -57,11 +56,6 @@ ACPI_MODULE_NAME("dsopcode")  /* Local prototypes */  static acpi_status -acpi_ds_execute_arguments(struct acpi_namespace_node *node, -			  struct acpi_namespace_node *scope_node, -			  u32 aml_length, u8 * aml_start); - -static acpi_status  acpi_ds_init_buffer_field(u16 aml_opcode,  			  union acpi_operand_object *obj_desc,  			  union acpi_operand_object *buffer_desc, @@ -71,361 +65,6 @@ acpi_ds_init_buffer_field(u16 aml_opcode,  /*******************************************************************************   * - * FUNCTION:    acpi_ds_execute_arguments - * - * PARAMETERS:  Node                - Object NS node - *              scope_node          - Parent NS node - *              aml_length          - Length of executable AML - *              aml_start           - Pointer to the AML - * - * RETURN:      Status. - * - * DESCRIPTION: Late (deferred) execution of region or field arguments - * - ******************************************************************************/ - -static acpi_status -acpi_ds_execute_arguments(struct acpi_namespace_node *node, -			  struct acpi_namespace_node *scope_node, -			  u32 aml_length, u8 * aml_start) -{ -	acpi_status status; -	union acpi_parse_object *op; -	struct acpi_walk_state *walk_state; - -	ACPI_FUNCTION_TRACE(ds_execute_arguments); - -	/* -	 * Allocate a new parser op to be the root of the parsed tree -	 */ -	op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); -	if (!op) { -		return_ACPI_STATUS(AE_NO_MEMORY); -	} - -	/* Save the Node for use in acpi_ps_parse_aml */ - -	op->common.node = scope_node; - -	/* Create and initialize a new parser state */ - -	walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); -	if (!walk_state) { -		status = AE_NO_MEMORY; -		goto cleanup; -	} - -	status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, -				       aml_length, NULL, ACPI_IMODE_LOAD_PASS1); -	if (ACPI_FAILURE(status)) { -		acpi_ds_delete_walk_state(walk_state); -		goto cleanup; -	} - -	/* Mark this parse as a deferred opcode */ - -	walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP; -	walk_state->deferred_node = node; - -	/* Pass1: Parse the entire declaration */ - -	status = acpi_ps_parse_aml(walk_state); -	if (ACPI_FAILURE(status)) { -		goto cleanup; -	} - -	/* Get and init the Op created above */ - -	op->common.node = node; -	acpi_ps_delete_parse_tree(op); - -	/* Evaluate the deferred arguments */ - -	op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); -	if (!op) { -		return_ACPI_STATUS(AE_NO_MEMORY); -	} - -	op->common.node = scope_node; - -	/* Create and initialize a new parser state */ - -	walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); -	if (!walk_state) { -		status = AE_NO_MEMORY; -		goto cleanup; -	} - -	/* Execute the opcode and arguments */ - -	status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, -				       aml_length, NULL, ACPI_IMODE_EXECUTE); -	if (ACPI_FAILURE(status)) { -		acpi_ds_delete_walk_state(walk_state); -		goto cleanup; -	} - -	/* Mark this execution as a deferred opcode */ - -	walk_state->deferred_node = node; -	status = acpi_ps_parse_aml(walk_state); - -      cleanup: -	acpi_ps_delete_parse_tree(op); -	return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_ds_get_buffer_field_arguments - * - * PARAMETERS:  obj_desc        - A valid buffer_field object - * - * RETURN:      Status. - * - * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late - *              evaluation of these field attributes. - * - ******************************************************************************/ - -acpi_status -acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) -{ -	union acpi_operand_object *extra_desc; -	struct acpi_namespace_node *node; -	acpi_status status; - -	ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc); - -	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { -		return_ACPI_STATUS(AE_OK); -	} - -	/* Get the AML pointer (method object) and buffer_field node */ - -	extra_desc = acpi_ns_get_secondary_object(obj_desc); -	node = obj_desc->buffer_field.node; - -	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname -			(ACPI_TYPE_BUFFER_FIELD, node, NULL)); -	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n", -			  acpi_ut_get_node_name(node))); - -	/* Execute the AML code for the term_arg arguments */ - -	status = acpi_ds_execute_arguments(node, node->parent, -					   extra_desc->extra.aml_length, -					   extra_desc->extra.aml_start); -	return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_ds_get_bank_field_arguments - * - * PARAMETERS:  obj_desc        - A valid bank_field object - * - * RETURN:      Status. - * - * DESCRIPTION: Get bank_field bank_value. This implements the late - *              evaluation of these field attributes. - * - ******************************************************************************/ - -acpi_status -acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc) -{ -	union acpi_operand_object *extra_desc; -	struct acpi_namespace_node *node; -	acpi_status status; - -	ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc); - -	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { -		return_ACPI_STATUS(AE_OK); -	} - -	/* Get the AML pointer (method object) and bank_field node */ - -	extra_desc = acpi_ns_get_secondary_object(obj_desc); -	node = obj_desc->bank_field.node; - -	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname -			(ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL)); -	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", -			  acpi_ut_get_node_name(node))); - -	/* Execute the AML code for the term_arg arguments */ - -	status = acpi_ds_execute_arguments(node, node->parent, -					   extra_desc->extra.aml_length, -					   extra_desc->extra.aml_start); -	return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_ds_get_buffer_arguments - * - * PARAMETERS:  obj_desc        - A valid Buffer object - * - * RETURN:      Status. - * - * DESCRIPTION: Get Buffer length and initializer byte list.  This implements - *              the late evaluation of these attributes. - * - ******************************************************************************/ - -acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc) -{ -	struct acpi_namespace_node *node; -	acpi_status status; - -	ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc); - -	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { -		return_ACPI_STATUS(AE_OK); -	} - -	/* Get the Buffer node */ - -	node = obj_desc->buffer.node; -	if (!node) { -		ACPI_ERROR((AE_INFO, -			    "No pointer back to namespace node in buffer object %p", -			    obj_desc)); -		return_ACPI_STATUS(AE_AML_INTERNAL); -	} - -	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n")); - -	/* Execute the AML code for the term_arg arguments */ - -	status = acpi_ds_execute_arguments(node, node, -					   obj_desc->buffer.aml_length, -					   obj_desc->buffer.aml_start); -	return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_ds_get_package_arguments - * - * PARAMETERS:  obj_desc        - A valid Package object - * - * RETURN:      Status. - * - * DESCRIPTION: Get Package length and initializer byte list.  This implements - *              the late evaluation of these attributes. - * - ******************************************************************************/ - -acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc) -{ -	struct acpi_namespace_node *node; -	acpi_status status; - -	ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc); - -	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { -		return_ACPI_STATUS(AE_OK); -	} - -	/* Get the Package node */ - -	node = obj_desc->package.node; -	if (!node) { -		ACPI_ERROR((AE_INFO, -			    "No pointer back to namespace node in package %p", -			    obj_desc)); -		return_ACPI_STATUS(AE_AML_INTERNAL); -	} - -	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n")); - -	/* Execute the AML code for the term_arg arguments */ - -	status = acpi_ds_execute_arguments(node, node, -					   obj_desc->package.aml_length, -					   obj_desc->package.aml_start); -	return_ACPI_STATUS(status); -} - -/***************************************************************************** - * - * FUNCTION:    acpi_ds_get_region_arguments - * - * PARAMETERS:  obj_desc        - A valid region object - * - * RETURN:      Status. - * - * DESCRIPTION: Get region address and length.  This implements the late - *              evaluation of these region attributes. - * - ****************************************************************************/ - -acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) -{ -	struct acpi_namespace_node *node; -	acpi_status status; -	union acpi_operand_object *extra_desc; - -	ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc); - -	if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { -		return_ACPI_STATUS(AE_OK); -	} - -	extra_desc = acpi_ns_get_secondary_object(obj_desc); -	if (!extra_desc) { -		return_ACPI_STATUS(AE_NOT_EXIST); -	} - -	/* Get the Region node */ - -	node = obj_desc->region.node; - -	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname -			(ACPI_TYPE_REGION, node, NULL)); - -	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n", -			  acpi_ut_get_node_name(node), -			  extra_desc->extra.aml_start)); - -	/* Execute the argument AML */ - -	status = acpi_ds_execute_arguments(node, node->parent, -					   extra_desc->extra.aml_length, -					   extra_desc->extra.aml_start); -	if (ACPI_FAILURE(status)) { -		return_ACPI_STATUS(status); -	} - -	/* Validate the region address/length via the host OS */ - -	status = acpi_os_validate_address(obj_desc->region.space_id, -					  obj_desc->region.address, -					  (acpi_size) obj_desc->region.length, -					  acpi_ut_get_node_name(node)); - -	if (ACPI_FAILURE(status)) { -		/* -		 * Invalid address/length. We will emit an error message and mark -		 * the region as invalid, so that it will cause an additional error if -		 * it is ever used. Then return AE_OK. -		 */ -		ACPI_EXCEPTION((AE_INFO, status, -				"During address validation of OpRegion [%4.4s]", -				node->name.ascii)); -		obj_desc->common.flags |= AOPOBJ_INVALID; -		status = AE_OK; -	} - -	return_ACPI_STATUS(status); -} - -/******************************************************************************* - *   * FUNCTION:    acpi_ds_initialize_region   *   * PARAMETERS:  obj_handle      - Region namespace node @@ -618,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 */ @@ -647,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   * @@ -731,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   * @@ -758,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; @@ -822,12 +461,13 @@ 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   * - * DESCRIPTION: Get region address and length - *              Called from acpi_ds_exec_end_op during data_table_region parse tree walk + * DESCRIPTION: Get region address and length. + *              Called from acpi_ds_exec_end_op during data_table_region parse + *              tree walk.   *   ******************************************************************************/ @@ -846,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)) { @@ -865,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); @@ -920,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 @@ -996,6 +636,7 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,  		break;  	default: +  		return_ACPI_STATUS(AE_AML_BAD_OPCODE);  	} @@ -1009,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;  		}  	} @@ -1022,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   * @@ -1114,360 +756,3 @@ acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state,  	acpi_ut_remove_reference(operand_desc);  	return_ACPI_STATUS(status);  } - -/******************************************************************************* - * - * FUNCTION:    acpi_ds_exec_begin_control_op - * - * PARAMETERS:  walk_list       - The list that owns the walk stack - *              Op              - The control Op - * - * RETURN:      Status - * - * DESCRIPTION: Handles all control ops encountered during control method - *              execution. - * - ******************************************************************************/ - -acpi_status -acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, -			      union acpi_parse_object *op) -{ -	acpi_status status = AE_OK; -	union acpi_generic_state *control_state; - -	ACPI_FUNCTION_NAME(ds_exec_begin_control_op); - -	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op, -			  op->common.aml_opcode, 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. -		 */ -		if (walk_state->control_state) { -			if (walk_state->control_state->control.aml_predicate_start -				== (walk_state->parser_state.aml - 1)) { - -				/* Reset the state to start-of-loop */ - -				walk_state->control_state->common.state = -				    ACPI_CONTROL_CONDITIONAL_EXECUTING; -				break; -			} -		} - -		/*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 -		 * to handle nesting. -		 */ -		control_state = acpi_ut_create_control_state(); -		if (!control_state) { -			status = AE_NO_MEMORY; -			break; -		} -		/* -		 * Save a pointer to the predicate for multiple executions -		 * of a loop -		 */ -		control_state->control.aml_predicate_start = -		    walk_state->parser_state.aml - 1; -		control_state->control.package_end = -		    walk_state->parser_state.pkg_end; -		control_state->control.opcode = op->common.aml_opcode; - -		/* Push the control state on this walk's control stack */ - -		acpi_ut_push_generic_state(&walk_state->control_state, -					   control_state); -		break; - -	case AML_ELSE_OP: - -		/* Predicate is in the state object */ -		/* If predicate is true, the IF was executed, ignore ELSE part */ - -		if (walk_state->last_predicate) { -			status = AE_CTRL_TRUE; -		} - -		break; - -	case AML_RETURN_OP: - -		break; - -	default: -		break; -	} - -	return (status); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_ds_exec_end_control_op - * - * PARAMETERS:  walk_list       - The list that owns the walk stack - *              Op              - The control Op - * - * RETURN:      Status - * - * DESCRIPTION: Handles all control ops encountered during control method - *              execution. - * - ******************************************************************************/ - -acpi_status -acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, -			    union acpi_parse_object * op) -{ -	acpi_status status = AE_OK; -	union acpi_generic_state *control_state; - -	ACPI_FUNCTION_NAME(ds_exec_end_control_op); - -	switch (op->common.aml_opcode) { -	case AML_IF_OP: - -		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op)); - -		/* -		 * Save the result of the predicate in case there is an -		 * ELSE to come -		 */ -		walk_state->last_predicate = -		    (u8) walk_state->control_state->common.value; - -		/* -		 * Pop the control state that was created at the start -		 * of the IF and free it -		 */ -		control_state = -		    acpi_ut_pop_generic_state(&walk_state->control_state); -		acpi_ut_delete_generic_state(control_state); -		break; - -	case AML_ELSE_OP: - -		break; - -	case AML_WHILE_OP: - -		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op)); - -		control_state = walk_state->control_state; -		if (control_state->common.value) { - -			/* Predicate was true, the body of the loop was just executed */ - -			/* -			 * This loop counter mechanism allows the interpreter to escape -			 * possibly infinite loops. This can occur in poorly written AML -			 * when the hardware does not respond within a while loop and the -			 * loop does not implement a timeout. -			 */ -			control_state->control.loop_count++; -			if (control_state->control.loop_count > -				ACPI_MAX_LOOP_ITERATIONS) { -				status = AE_AML_INFINITE_LOOP; -				break; -			} - -			/* -			 * Go back and evaluate the predicate and maybe execute the loop -			 * another time -			 */ -			status = AE_CTRL_PENDING; -			walk_state->aml_last_while = -			    control_state->control.aml_predicate_start; -			break; -		} - -		/* Predicate was false, terminate this while loop */ - -		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, -				  "[WHILE_OP] termination! Op=%p\n", op)); - -		/* Pop this control state and free it */ - -		control_state = -		    acpi_ut_pop_generic_state(&walk_state->control_state); -		acpi_ut_delete_generic_state(control_state); -		break; - -	case AML_RETURN_OP: - -		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, -				  "[RETURN_OP] Op=%p Arg=%p\n", op, -				  op->common.value.arg)); - -		/* -		 * One optional operand -- the return value -		 * It can be either an immediate operand or a result that -		 * has been bubbled up the tree -		 */ -		if (op->common.value.arg) { - -			/* Since we have a real Return(), delete any implicit return */ - -			acpi_ds_clear_implicit_return(walk_state); - -			/* Return statement has an immediate operand */ - -			status = -			    acpi_ds_create_operands(walk_state, -						    op->common.value.arg); -			if (ACPI_FAILURE(status)) { -				return (status); -			} - -			/* -			 * If value being returned is a Reference (such as -			 * an arg or local), resolve it now because it may -			 * cease to exist at the end of the method. -			 */ -			status = -			    acpi_ex_resolve_to_value(&walk_state->operands[0], -						     walk_state); -			if (ACPI_FAILURE(status)) { -				return (status); -			} - -			/* -			 * Get the return value and save as the last result -			 * 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]; -		} else if (walk_state->result_count) { - -			/* Since we have a real Return(), delete any implicit return */ - -			acpi_ds_clear_implicit_return(walk_state); - -			/* -			 * The return value has come from a previous calculation. -			 * -			 * If value being returned is a Reference (such as -			 * an arg or local), resolve it now because it may -			 * cease to exist at the end of the method. -			 * -			 * Allow references created by the Index operator to return unchanged. -			 */ -			if ((ACPI_GET_DESCRIPTOR_TYPE -			     (walk_state->results->results.obj_desc[0]) == -			     ACPI_DESC_TYPE_OPERAND) -			    && ((walk_state->results->results.obj_desc[0])-> -				common.type == ACPI_TYPE_LOCAL_REFERENCE) -			    && ((walk_state->results->results.obj_desc[0])-> -				reference.class != ACPI_REFCLASS_INDEX)) { -				status = -				    acpi_ex_resolve_to_value(&walk_state-> -							     results->results. -							     obj_desc[0], -							     walk_state); -				if (ACPI_FAILURE(status)) { -					return (status); -				} -			} - -			walk_state->return_desc = -			    walk_state->results->results.obj_desc[0]; -		} else { -			/* No return operand */ - -			if (walk_state->num_operands) { -				acpi_ut_remove_reference(walk_state-> -							 operands[0]); -			} - -			walk_state->operands[0] = NULL; -			walk_state->num_operands = 0; -			walk_state->return_desc = NULL; -		} - -		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, -				  "Completed RETURN_OP State=%p, RetVal=%p\n", -				  walk_state, walk_state->return_desc)); - -		/* End the control method execution right now */ - -		status = AE_CTRL_TERMINATE; -		break; - -	case AML_NOOP_OP: - -		/* Just do nothing! */ -		break; - -	case AML_BREAK_POINT_OP: - -		/* -		 * Set the single-step flag. This will cause the debugger (if present) -		 * to break to the console within the AML debugger at the start of the -		 * next AML instruction. -		 */ -		ACPI_DEBUGGER_EXEC(acpi_gbl_cm_single_step = TRUE); -		ACPI_DEBUGGER_EXEC(acpi_os_printf -				   ("**break** Executed AML BreakPoint opcode\n")); - -		/* Call to the OSL in case OS wants a piece of the action */ - -		status = acpi_os_signal(ACPI_SIGNAL_BREAKPOINT, -					"Executed AML Breakpoint opcode"); -		break; - -	case AML_BREAK_OP: -	case AML_CONTINUE_OP:	/* ACPI 2.0 */ - -		/* Pop and delete control states until we find a while */ - -		while (walk_state->control_state && -		       (walk_state->control_state->control.opcode != -			AML_WHILE_OP)) { -			control_state = -			    acpi_ut_pop_generic_state(&walk_state-> -						      control_state); -			acpi_ut_delete_generic_state(control_state); -		} - -		/* No while found? */ - -		if (!walk_state->control_state) { -			return (AE_AML_NO_WHILE); -		} - -		/* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */ - -		walk_state->aml_last_while = -		    walk_state->control_state->control.package_end; - -		/* Return status depending on opcode */ - -		if (op->common.aml_opcode == AML_BREAK_OP) { -			status = AE_CTRL_BREAK; -		} else { -			status = AE_CTRL_CONTINUE; -		} -		break; - -	default: - -		ACPI_ERROR((AE_INFO, "Unknown control opcode=0x%X Op=%p", -			    op->common.aml_opcode, op)); - -		status = AE_AML_BAD_OPCODE; -		break; -	} - -	return (status); -} diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c index 15135c25aa9..9f74795e226 100644 --- a/drivers/acpi/acpica/dsutils.c +++ b/drivers/acpi/acpica/dsutils.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 6b0b5d08d97..f7f5107e754 100644 --- a/drivers/acpi/acpica/dswexec.c +++ b/drivers/acpi/acpica/dswexec.c @@ -6,7 +6,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 140a9d00295..15623da2620 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c @@ -1,11 +1,11 @@  /******************************************************************************   * - * Module Name: dswload - Dispatcher namespace load callbacks + * Module Name: dswload - Dispatcher first pass namespace load callbacks   *   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -48,10 +48,9 @@  #include "acdispat.h"  #include "acinterp.h"  #include "acnamesp.h" -#include "acevents.h"  #ifdef ACPI_ASL_COMPILER -#include <acpi/acdisasm.h> +#include "acdisasm.h"  #endif  #define _COMPONENT          ACPI_DISPATCHER @@ -74,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; @@ -82,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; @@ -89,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; @@ -98,6 +116,7 @@ acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number)  		break;  	default: +  		return (AE_BAD_PARAMETER);  	} @@ -162,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. @@ -179,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, @@ -210,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: @@ -231,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 */ @@ -451,7 +482,7 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)  			status =  			    acpi_ex_create_region(op->named.data,  						  op->named.length, -						  REGION_DATA_TABLE, +						  ACPI_ADR_SPACE_DATA_TABLE,  						  walk_state);  			if (ACPI_FAILURE(status)) {  				return_ACPI_STATUS(status); @@ -537,670 +568,3 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)  	return_ACPI_STATUS(status);  } - -/******************************************************************************* - * - * FUNCTION:    acpi_ds_load2_begin_op - * - * PARAMETERS:  walk_state      - Current state of the parse tree walk - *              out_op          - Wher to return op if a new one is created - * - * RETURN:      Status - * - * DESCRIPTION: Descending callback used during the loading of ACPI tables. - * - ******************************************************************************/ - -acpi_status -acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, -		       union acpi_parse_object **out_op) -{ -	union acpi_parse_object *op; -	struct acpi_namespace_node *node; -	acpi_status status; -	acpi_object_type object_type; -	char *buffer_ptr; -	u32 flags; - -	ACPI_FUNCTION_TRACE(ds_load2_begin_op); - -	op = walk_state->op; -	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, -			  walk_state)); - -	if (op) { -		if ((walk_state->control_state) && -		    (walk_state->control_state->common.state == -		     ACPI_CONTROL_CONDITIONAL_EXECUTING)) { - -			/* We are executing a while loop outside of a method */ - -			status = acpi_ds_exec_begin_op(walk_state, out_op); -			return_ACPI_STATUS(status); -		} - -		/* We only care about Namespace opcodes here */ - -		if ((!(walk_state->op_info->flags & AML_NSOPCODE) && -		     (walk_state->opcode != AML_INT_NAMEPATH_OP)) || -		    (!(walk_state->op_info->flags & AML_NAMED))) { -			return_ACPI_STATUS(AE_OK); -		} - -		/* Get the name we are going to enter or lookup in the namespace */ - -		if (walk_state->opcode == AML_INT_NAMEPATH_OP) { - -			/* For Namepath op, get the path string */ - -			buffer_ptr = op->common.value.string; -			if (!buffer_ptr) { - -				/* No name, just exit */ - -				return_ACPI_STATUS(AE_OK); -			} -		} else { -			/* Get name from the op */ - -			buffer_ptr = ACPI_CAST_PTR(char, &op->named.name); -		} -	} else { -		/* Get the namestring from the raw AML */ - -		buffer_ptr = -		    acpi_ps_get_next_namestring(&walk_state->parser_state); -	} - -	/* Map the opcode into an internal object type */ - -	object_type = walk_state->op_info->object_type; - -	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, -			  "State=%p Op=%p Type=%X\n", walk_state, op, -			  object_type)); - -	switch (walk_state->opcode) { -	case AML_FIELD_OP: -	case AML_BANK_FIELD_OP: -	case AML_INDEX_FIELD_OP: - -		node = NULL; -		status = AE_OK; -		break; - -	case AML_INT_NAMEPATH_OP: -		/* -		 * The name_path is an object reference to an existing object. -		 * Don't enter the name into the namespace, but look it up -		 * for use later. -		 */ -		status = -		    acpi_ns_lookup(walk_state->scope_info, buffer_ptr, -				   object_type, ACPI_IMODE_EXECUTE, -				   ACPI_NS_SEARCH_PARENT, walk_state, &(node)); -		break; - -	case AML_SCOPE_OP: - -		/* Special case for Scope(\) -> refers to the Root node */ - -		if (op && (op->named.node == acpi_gbl_root_node)) { -			node = op->named.node; - -			status = -			    acpi_ds_scope_stack_push(node, object_type, -						     walk_state); -			if (ACPI_FAILURE(status)) { -				return_ACPI_STATUS(status); -			} -		} else { -			/* -			 * The Path is an object reference to an existing object. -			 * Don't enter the name into the namespace, but look it up -			 * for use later. -			 */ -			status = -			    acpi_ns_lookup(walk_state->scope_info, buffer_ptr, -					   object_type, ACPI_IMODE_EXECUTE, -					   ACPI_NS_SEARCH_PARENT, walk_state, -					   &(node)); -			if (ACPI_FAILURE(status)) { -#ifdef ACPI_ASL_COMPILER -				if (status == AE_NOT_FOUND) { -					status = AE_OK; -				} else { -					ACPI_ERROR_NAMESPACE(buffer_ptr, -							     status); -				} -#else -				ACPI_ERROR_NAMESPACE(buffer_ptr, status); -#endif -				return_ACPI_STATUS(status); -			} -		} - -		/* -		 * We must check to make sure that the target is -		 * one of the opcodes that actually opens a scope -		 */ -		switch (node->type) { -		case ACPI_TYPE_ANY: -		case ACPI_TYPE_LOCAL_SCOPE:	/* Scope */ -		case ACPI_TYPE_DEVICE: -		case ACPI_TYPE_POWER: -		case ACPI_TYPE_PROCESSOR: -		case ACPI_TYPE_THERMAL: - -			/* These are acceptable types */ -			break; - -		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: -			 * -			 *  Name (DEB, 0) -			 *  Scope (DEB) { ... } -			 */ -			ACPI_WARNING((AE_INFO, -				      "Type override - [%4.4s] had invalid type (%s) " -				      "for Scope operator, changed to type ANY\n", -				      acpi_ut_get_node_name(node), -				      acpi_ut_get_type_name(node->type))); - -			node->type = ACPI_TYPE_ANY; -			walk_state->scope_info->common.value = ACPI_TYPE_ANY; -			break; - -		default: - -			/* All other types are an error */ - -			ACPI_ERROR((AE_INFO, -				    "Invalid type (%s) for target of " -				    "Scope operator [%4.4s] (Cannot override)", -				    acpi_ut_get_type_name(node->type), -				    acpi_ut_get_node_name(node))); - -			return (AE_AML_OPERAND_TYPE); -		} -		break; - -	default: - -		/* All other opcodes */ - -		if (op && op->common.node) { - -			/* This op/node was previously entered into the namespace */ - -			node = op->common.node; - -			if (acpi_ns_opens_scope(object_type)) { -				status = -				    acpi_ds_scope_stack_push(node, object_type, -							     walk_state); -				if (ACPI_FAILURE(status)) { -					return_ACPI_STATUS(status); -				} -			} - -			return_ACPI_STATUS(AE_OK); -		} - -		/* -		 * Enter the named type into the internal namespace. We enter the name -		 * as we go downward in the parse tree. Any necessary subobjects that -		 * involve arguments to the opcode must be created as we go back up the -		 * parse tree later. -		 * -		 * Note: Name may already exist if we are executing a deferred opcode. -		 */ -		if (walk_state->deferred_node) { - -			/* This name is already in the namespace, get the node */ - -			node = walk_state->deferred_node; -			status = AE_OK; -			break; -		} - -		flags = ACPI_NS_NO_UPSEARCH; -		if (walk_state->pass_number == ACPI_IMODE_EXECUTE) { - -			/* Execution mode, node cannot already exist, node is temporary */ - -			flags |= ACPI_NS_ERROR_IF_FOUND; - -			if (! -			    (walk_state-> -			     parse_flags & ACPI_PARSE_MODULE_LEVEL)) { -				flags |= ACPI_NS_TEMPORARY; -			} -		} - -		/* Add new entry or lookup existing entry */ - -		status = -		    acpi_ns_lookup(walk_state->scope_info, buffer_ptr, -				   object_type, ACPI_IMODE_LOAD_PASS2, flags, -				   walk_state, &node); - -		if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) { -			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, -					  "***New Node [%4.4s] %p is temporary\n", -					  acpi_ut_get_node_name(node), node)); -		} -		break; -	} - -	if (ACPI_FAILURE(status)) { -		ACPI_ERROR_NAMESPACE(buffer_ptr, status); -		return_ACPI_STATUS(status); -	} - -	if (!op) { - -		/* Create a new op */ - -		op = acpi_ps_alloc_op(walk_state->opcode); -		if (!op) { -			return_ACPI_STATUS(AE_NO_MEMORY); -		} - -		/* Initialize the new op */ - -		if (node) { -			op->named.name = node->name.integer; -		} -		*out_op = op; -	} - -	/* -	 * Put the Node in the "op" object that the parser uses, so we -	 * can get it again quickly when this scope is closed -	 */ -	op->common.node = node; -	return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_ds_load2_end_op - * - * PARAMETERS:  walk_state      - Current state of the parse tree walk - * - * RETURN:      Status - * - * DESCRIPTION: Ascending callback used during the loading of the namespace, - *              both control methods and everything else. - * - ******************************************************************************/ - -acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) -{ -	union acpi_parse_object *op; -	acpi_status status = AE_OK; -	acpi_object_type object_type; -	struct acpi_namespace_node *node; -	union acpi_parse_object *arg; -	struct acpi_namespace_node *new_node; -#ifndef ACPI_NO_METHOD_EXECUTION -	u32 i; -	u8 region_space; -#endif - -	ACPI_FUNCTION_TRACE(ds_load2_end_op); - -	op = walk_state->op; -	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n", -			  walk_state->op_info->name, op, walk_state)); - -	/* Check if opcode had an associated namespace object */ - -	if (!(walk_state->op_info->flags & AML_NSOBJECT)) { -		return_ACPI_STATUS(AE_OK); -	} - -	if (op->common.aml_opcode == AML_SCOPE_OP) { -		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, -				  "Ending scope Op=%p State=%p\n", op, -				  walk_state)); -	} - -	object_type = walk_state->op_info->object_type; - -	/* -	 * Get the Node/name from the earlier lookup -	 * (It was saved in the *op structure) -	 */ -	node = op->common.node; - -	/* -	 * Put the Node on the object stack (Contains the ACPI Name of -	 * this object) -	 */ -	walk_state->operands[0] = (void *)node; -	walk_state->num_operands = 1; - -	/* Pop the scope stack */ - -	if (acpi_ns_opens_scope(object_type) && -	    (op->common.aml_opcode != AML_INT_METHODCALL_OP)) { -		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, -				  "(%s) Popping scope for Op %p\n", -				  acpi_ut_get_type_name(object_type), op)); - -		status = acpi_ds_scope_stack_pop(walk_state); -		if (ACPI_FAILURE(status)) { -			goto cleanup; -		} -	} - -	/* -	 * Named operations are as follows: -	 * -	 * AML_ALIAS -	 * AML_BANKFIELD -	 * AML_CREATEBITFIELD -	 * AML_CREATEBYTEFIELD -	 * AML_CREATEDWORDFIELD -	 * AML_CREATEFIELD -	 * AML_CREATEQWORDFIELD -	 * AML_CREATEWORDFIELD -	 * AML_DATA_REGION -	 * AML_DEVICE -	 * AML_EVENT -	 * AML_FIELD -	 * AML_INDEXFIELD -	 * AML_METHOD -	 * AML_METHODCALL -	 * AML_MUTEX -	 * AML_NAME -	 * AML_NAMEDFIELD -	 * AML_OPREGION -	 * AML_POWERRES -	 * AML_PROCESSOR -	 * AML_SCOPE -	 * AML_THERMALZONE -	 */ - -	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, -			  "Create-Load [%s] State=%p Op=%p NamedObj=%p\n", -			  acpi_ps_get_opcode_name(op->common.aml_opcode), -			  walk_state, op, node)); - -	/* Decode the opcode */ - -	arg = op->common.value.arg; - -	switch (walk_state->op_info->type) { -#ifndef ACPI_NO_METHOD_EXECUTION - -	case AML_TYPE_CREATE_FIELD: -		/* -		 * Create the field object, but the field buffer and index must -		 * be evaluated later during the execution phase -		 */ -		status = acpi_ds_create_buffer_field(op, walk_state); -		break; - -	case AML_TYPE_NAMED_FIELD: -		/* -		 * If we are executing a method, initialize the field -		 */ -		if (walk_state->method_node) { -			status = acpi_ds_init_field_objects(op, walk_state); -		} - -		switch (op->common.aml_opcode) { -		case AML_INDEX_FIELD_OP: - -			status = -			    acpi_ds_create_index_field(op, -						       (acpi_handle) arg-> -						       common.node, walk_state); -			break; - -		case AML_BANK_FIELD_OP: - -			status = -			    acpi_ds_create_bank_field(op, arg->common.node, -						      walk_state); -			break; - -		case AML_FIELD_OP: - -			status = -			    acpi_ds_create_field(op, arg->common.node, -						 walk_state); -			break; - -		default: -			/* All NAMED_FIELD opcodes must be handled above */ -			break; -		} -		break; - -	case AML_TYPE_NAMED_SIMPLE: - -		status = acpi_ds_create_operands(walk_state, arg); -		if (ACPI_FAILURE(status)) { -			goto cleanup; -		} - -		switch (op->common.aml_opcode) { -		case AML_PROCESSOR_OP: - -			status = acpi_ex_create_processor(walk_state); -			break; - -		case AML_POWER_RES_OP: - -			status = acpi_ex_create_power_resource(walk_state); -			break; - -		case AML_MUTEX_OP: - -			status = acpi_ex_create_mutex(walk_state); -			break; - -		case AML_EVENT_OP: - -			status = acpi_ex_create_event(walk_state); -			break; - -		case AML_ALIAS_OP: - -			status = acpi_ex_create_alias(walk_state); -			break; - -		default: -			/* Unknown opcode */ - -			status = AE_OK; -			goto cleanup; -		} - -		/* Delete operands */ - -		for (i = 1; i < walk_state->num_operands; i++) { -			acpi_ut_remove_reference(walk_state->operands[i]); -			walk_state->operands[i] = NULL; -		} - -		break; -#endif				/* ACPI_NO_METHOD_EXECUTION */ - -	case AML_TYPE_NAMED_COMPLEX: - -		switch (op->common.aml_opcode) { -#ifndef ACPI_NO_METHOD_EXECUTION -		case AML_REGION_OP: -		case AML_DATA_REGION_OP: - -			if (op->common.aml_opcode == AML_REGION_OP) { -				region_space = (acpi_adr_space_type) -				    ((op->common.value.arg)->common.value. -				     integer); -			} else { -				region_space = REGION_DATA_TABLE; -			} - -			/* -			 * The op_region is not fully parsed at this time. The only valid -			 * argument is the space_id. (We must save the address of the -			 * AML of the address and length operands) -			 * -			 * If we have a valid region, initialize it. The namespace is -			 * unlocked at this point. -			 * -			 * Need to unlock interpreter if it is locked (if we are running -			 * a control method), in order to allow _REG methods to be run -			 * during acpi_ev_initialize_region. -			 */ -			if (walk_state->method_node) { -				/* -				 * Executing a method: initialize the region and unlock -				 * the interpreter -				 */ -				status = -				    acpi_ex_create_region(op->named.data, -							  op->named.length, -							  region_space, -							  walk_state); -				if (ACPI_FAILURE(status)) { -					return (status); -				} - -				acpi_ex_exit_interpreter(); -			} - -			status = -			    acpi_ev_initialize_region -			    (acpi_ns_get_attached_object(node), FALSE); -			if (walk_state->method_node) { -				acpi_ex_enter_interpreter(); -			} - -			if (ACPI_FAILURE(status)) { -				/* -				 *  If AE_NOT_EXIST is returned, it is not fatal -				 *  because many regions get created before a handler -				 *  is installed for said region. -				 */ -				if (AE_NOT_EXIST == status) { -					status = AE_OK; -				} -			} -			break; - -		case AML_NAME_OP: - -			status = acpi_ds_create_node(walk_state, node, op); -			break; - -		case AML_METHOD_OP: -			/* -			 * method_op pkg_length name_string method_flags term_list -			 * -			 * Note: We must create the method node/object pair as soon as we -			 * see the method declaration. This allows later pass1 parsing -			 * of invocations of the method (need to know the number of -			 * arguments.) -			 */ -			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, -					  "LOADING-Method: State=%p Op=%p NamedObj=%p\n", -					  walk_state, op, op->named.node)); - -			if (!acpi_ns_get_attached_object(op->named.node)) { -				walk_state->operands[0] = -				    ACPI_CAST_PTR(void, op->named.node); -				walk_state->num_operands = 1; - -				status = -				    acpi_ds_create_operands(walk_state, -							    op->common.value. -							    arg); -				if (ACPI_SUCCESS(status)) { -					status = -					    acpi_ex_create_method(op->named. -								  data, -								  op->named. -								  length, -								  walk_state); -				} -				walk_state->operands[0] = NULL; -				walk_state->num_operands = 0; - -				if (ACPI_FAILURE(status)) { -					return_ACPI_STATUS(status); -				} -			} -			break; - -#endif				/* ACPI_NO_METHOD_EXECUTION */ - -		default: -			/* All NAMED_COMPLEX opcodes must be handled above */ -			break; -		} -		break; - -	case AML_CLASS_INTERNAL: - -		/* case AML_INT_NAMEPATH_OP: */ -		break; - -	case AML_CLASS_METHOD_CALL: - -		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, -				  "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n", -				  walk_state, op, node)); - -		/* -		 * Lookup the method name and save the Node -		 */ -		status = -		    acpi_ns_lookup(walk_state->scope_info, -				   arg->common.value.string, ACPI_TYPE_ANY, -				   ACPI_IMODE_LOAD_PASS2, -				   ACPI_NS_SEARCH_PARENT | -				   ACPI_NS_DONT_OPEN_SCOPE, walk_state, -				   &(new_node)); -		if (ACPI_SUCCESS(status)) { -			/* -			 * Make sure that what we found is indeed a method -			 * We didn't search for a method on purpose, to see if the name -			 * would resolve -			 */ -			if (new_node->type != ACPI_TYPE_METHOD) { -				status = AE_AML_OPERAND_TYPE; -			} - -			/* We could put the returned object (Node) on the object stack for -			 * later, but for now, we will put it in the "op" object that the -			 * parser uses, so we can get it again at the end of this scope -			 */ -			op->common.node = new_node; -		} else { -			ACPI_ERROR_NAMESPACE(arg->common.value.string, status); -		} -		break; - -	default: -		break; -	} - -      cleanup: - -	/* Remove the Node pushed at the very beginning */ - -	walk_state->operands[0] = NULL; -	walk_state->num_operands = 0; -	return_ACPI_STATUS(status); -} diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c new file mode 100644 index 00000000000..2ac28d29730 --- /dev/null +++ b/drivers/acpi/acpica/dswload2.c @@ -0,0 +1,738 @@ +/****************************************************************************** + * + * Module Name: dswload2 - Dispatcher second pass namespace load callbacks + * + *****************************************************************************/ + +/* + * 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" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acevents.h" + +#define _COMPONENT          ACPI_DISPATCHER +ACPI_MODULE_NAME("dswload2") + +/******************************************************************************* + * + * FUNCTION:    acpi_ds_load2_begin_op + * + * PARAMETERS:  walk_state      - Current state of the parse tree walk + *              out_op          - Wher to return op if a new one is created + * + * RETURN:      Status + * + * DESCRIPTION: Descending callback used during the loading of ACPI tables. + * + ******************************************************************************/ +acpi_status +acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, +		       union acpi_parse_object **out_op) +{ +	union acpi_parse_object *op; +	struct acpi_namespace_node *node; +	acpi_status status; +	acpi_object_type object_type; +	char *buffer_ptr; +	u32 flags; + +	ACPI_FUNCTION_TRACE(ds_load2_begin_op); + +	op = walk_state->op; +	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, +			  walk_state)); + +	if (op) { +		if ((walk_state->control_state) && +		    (walk_state->control_state->common.state == +		     ACPI_CONTROL_CONDITIONAL_EXECUTING)) { + +			/* We are executing a while loop outside of a method */ + +			status = acpi_ds_exec_begin_op(walk_state, out_op); +			return_ACPI_STATUS(status); +		} + +		/* We only care about Namespace opcodes here */ + +		if ((!(walk_state->op_info->flags & AML_NSOPCODE) && +		     (walk_state->opcode != AML_INT_NAMEPATH_OP)) || +		    (!(walk_state->op_info->flags & AML_NAMED))) { +			return_ACPI_STATUS(AE_OK); +		} + +		/* Get the name we are going to enter or lookup in the namespace */ + +		if (walk_state->opcode == AML_INT_NAMEPATH_OP) { + +			/* For Namepath op, get the path string */ + +			buffer_ptr = op->common.value.string; +			if (!buffer_ptr) { + +				/* No name, just exit */ + +				return_ACPI_STATUS(AE_OK); +			} +		} else { +			/* Get name from the op */ + +			buffer_ptr = ACPI_CAST_PTR(char, &op->named.name); +		} +	} else { +		/* Get the namestring from the raw AML */ + +		buffer_ptr = +		    acpi_ps_get_next_namestring(&walk_state->parser_state); +	} + +	/* Map the opcode into an internal object type */ + +	object_type = walk_state->op_info->object_type; + +	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, +			  "State=%p Op=%p Type=%X\n", walk_state, op, +			  object_type)); + +	switch (walk_state->opcode) { +	case AML_FIELD_OP: +	case AML_BANK_FIELD_OP: +	case AML_INDEX_FIELD_OP: + +		node = NULL; +		status = AE_OK; +		break; + +	case AML_INT_NAMEPATH_OP: +		/* +		 * The name_path is an object reference to an existing object. +		 * Don't enter the name into the namespace, but look it up +		 * for use later. +		 */ +		status = +		    acpi_ns_lookup(walk_state->scope_info, buffer_ptr, +				   object_type, ACPI_IMODE_EXECUTE, +				   ACPI_NS_SEARCH_PARENT, walk_state, &(node)); +		break; + +	case AML_SCOPE_OP: + +		/* Special case for Scope(\) -> refers to the Root node */ + +		if (op && (op->named.node == acpi_gbl_root_node)) { +			node = op->named.node; + +			status = +			    acpi_ds_scope_stack_push(node, object_type, +						     walk_state); +			if (ACPI_FAILURE(status)) { +				return_ACPI_STATUS(status); +			} +		} else { +			/* +			 * The Path is an object reference to an existing object. +			 * Don't enter the name into the namespace, but look it up +			 * for use later. +			 */ +			status = +			    acpi_ns_lookup(walk_state->scope_info, buffer_ptr, +					   object_type, ACPI_IMODE_EXECUTE, +					   ACPI_NS_SEARCH_PARENT, walk_state, +					   &(node)); +			if (ACPI_FAILURE(status)) { +#ifdef ACPI_ASL_COMPILER +				if (status == AE_NOT_FOUND) { +					status = AE_OK; +				} else { +					ACPI_ERROR_NAMESPACE(buffer_ptr, +							     status); +				} +#else +				ACPI_ERROR_NAMESPACE(buffer_ptr, status); +#endif +				return_ACPI_STATUS(status); +			} +		} + +		/* +		 * We must check to make sure that the target is +		 * one of the opcodes that actually opens a scope +		 */ +		switch (node->type) { +		case ACPI_TYPE_ANY: +		case ACPI_TYPE_LOCAL_SCOPE:	/* Scope */ +		case ACPI_TYPE_DEVICE: +		case ACPI_TYPE_POWER: +		case ACPI_TYPE_PROCESSOR: +		case ACPI_TYPE_THERMAL: + +			/* These are acceptable types */ +			break; + +		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: +			 * +			 *  Name (DEB, 0) +			 *  Scope (DEB) { ... } +			 */ +			ACPI_WARNING((AE_INFO, +				      "Type override - [%4.4s] had invalid type (%s) " +				      "for Scope operator, changed to type ANY", +				      acpi_ut_get_node_name(node), +				      acpi_ut_get_type_name(node->type))); + +			node->type = ACPI_TYPE_ANY; +			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 */ + +			ACPI_ERROR((AE_INFO, +				    "Invalid type (%s) for target of " +				    "Scope operator [%4.4s] (Cannot override)", +				    acpi_ut_get_type_name(node->type), +				    acpi_ut_get_node_name(node))); + +			return_ACPI_STATUS(AE_AML_OPERAND_TYPE); +		} +		break; + +	default: + +		/* All other opcodes */ + +		if (op && op->common.node) { + +			/* This op/node was previously entered into the namespace */ + +			node = op->common.node; + +			if (acpi_ns_opens_scope(object_type)) { +				status = +				    acpi_ds_scope_stack_push(node, object_type, +							     walk_state); +				if (ACPI_FAILURE(status)) { +					return_ACPI_STATUS(status); +				} +			} + +			return_ACPI_STATUS(AE_OK); +		} + +		/* +		 * Enter the named type into the internal namespace. We enter the name +		 * as we go downward in the parse tree. Any necessary subobjects that +		 * involve arguments to the opcode must be created as we go back up the +		 * parse tree later. +		 * +		 * Note: Name may already exist if we are executing a deferred opcode. +		 */ +		if (walk_state->deferred_node) { + +			/* This name is already in the namespace, get the node */ + +			node = walk_state->deferred_node; +			status = AE_OK; +			break; +		} + +		flags = ACPI_NS_NO_UPSEARCH; +		if (walk_state->pass_number == ACPI_IMODE_EXECUTE) { + +			/* Execution mode, node cannot already exist, node is temporary */ + +			flags |= ACPI_NS_ERROR_IF_FOUND; + +			if (! +			    (walk_state-> +			     parse_flags & ACPI_PARSE_MODULE_LEVEL)) { +				flags |= ACPI_NS_TEMPORARY; +			} +		} + +		/* Add new entry or lookup existing entry */ + +		status = +		    acpi_ns_lookup(walk_state->scope_info, buffer_ptr, +				   object_type, ACPI_IMODE_LOAD_PASS2, flags, +				   walk_state, &node); + +		if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) { +			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, +					  "***New Node [%4.4s] %p is temporary\n", +					  acpi_ut_get_node_name(node), node)); +		} +		break; +	} + +	if (ACPI_FAILURE(status)) { +		ACPI_ERROR_NAMESPACE(buffer_ptr, status); +		return_ACPI_STATUS(status); +	} + +	if (!op) { + +		/* Create a new op */ + +		op = acpi_ps_alloc_op(walk_state->opcode); +		if (!op) { +			return_ACPI_STATUS(AE_NO_MEMORY); +		} + +		/* Initialize the new op */ + +		if (node) { +			op->named.name = node->name.integer; +		} +		*out_op = op; +	} + +	/* +	 * Put the Node in the "op" object that the parser uses, so we +	 * can get it again quickly when this scope is closed +	 */ +	op->common.node = node; +	return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ds_load2_end_op + * + * PARAMETERS:  walk_state      - Current state of the parse tree walk + * + * RETURN:      Status + * + * DESCRIPTION: Ascending callback used during the loading of the namespace, + *              both control methods and everything else. + * + ******************************************************************************/ + +acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) +{ +	union acpi_parse_object *op; +	acpi_status status = AE_OK; +	acpi_object_type object_type; +	struct acpi_namespace_node *node; +	union acpi_parse_object *arg; +	struct acpi_namespace_node *new_node; +#ifndef ACPI_NO_METHOD_EXECUTION +	u32 i; +	u8 region_space; +#endif + +	ACPI_FUNCTION_TRACE(ds_load2_end_op); + +	op = walk_state->op; +	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n", +			  walk_state->op_info->name, op, walk_state)); + +	/* Check if opcode had an associated namespace object */ + +	if (!(walk_state->op_info->flags & AML_NSOBJECT)) { +		return_ACPI_STATUS(AE_OK); +	} + +	if (op->common.aml_opcode == AML_SCOPE_OP) { +		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, +				  "Ending scope Op=%p State=%p\n", op, +				  walk_state)); +	} + +	object_type = walk_state->op_info->object_type; + +	/* +	 * Get the Node/name from the earlier lookup +	 * (It was saved in the *op structure) +	 */ +	node = op->common.node; + +	/* +	 * Put the Node on the object stack (Contains the ACPI Name of +	 * this object) +	 */ +	walk_state->operands[0] = (void *)node; +	walk_state->num_operands = 1; + +	/* Pop the scope stack */ + +	if (acpi_ns_opens_scope(object_type) && +	    (op->common.aml_opcode != AML_INT_METHODCALL_OP)) { +		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, +				  "(%s) Popping scope for Op %p\n", +				  acpi_ut_get_type_name(object_type), op)); + +		status = acpi_ds_scope_stack_pop(walk_state); +		if (ACPI_FAILURE(status)) { +			goto cleanup; +		} +	} + +	/* +	 * Named operations are as follows: +	 * +	 * AML_ALIAS +	 * AML_BANKFIELD +	 * AML_CREATEBITFIELD +	 * AML_CREATEBYTEFIELD +	 * AML_CREATEDWORDFIELD +	 * AML_CREATEFIELD +	 * AML_CREATEQWORDFIELD +	 * AML_CREATEWORDFIELD +	 * AML_DATA_REGION +	 * AML_DEVICE +	 * AML_EVENT +	 * AML_FIELD +	 * AML_INDEXFIELD +	 * AML_METHOD +	 * AML_METHODCALL +	 * AML_MUTEX +	 * AML_NAME +	 * AML_NAMEDFIELD +	 * AML_OPREGION +	 * AML_POWERRES +	 * AML_PROCESSOR +	 * AML_SCOPE +	 * AML_THERMALZONE +	 */ + +	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, +			  "Create-Load [%s] State=%p Op=%p NamedObj=%p\n", +			  acpi_ps_get_opcode_name(op->common.aml_opcode), +			  walk_state, op, node)); + +	/* Decode the opcode */ + +	arg = op->common.value.arg; + +	switch (walk_state->op_info->type) { +#ifndef ACPI_NO_METHOD_EXECUTION + +	case AML_TYPE_CREATE_FIELD: +		/* +		 * Create the field object, but the field buffer and index must +		 * be evaluated later during the execution phase +		 */ +		status = acpi_ds_create_buffer_field(op, walk_state); +		break; + +	case AML_TYPE_NAMED_FIELD: +		/* +		 * If we are executing a method, initialize the field +		 */ +		if (walk_state->method_node) { +			status = acpi_ds_init_field_objects(op, walk_state); +		} + +		switch (op->common.aml_opcode) { +		case AML_INDEX_FIELD_OP: + +			status = +			    acpi_ds_create_index_field(op, +						       (acpi_handle) arg-> +						       common.node, walk_state); +			break; + +		case AML_BANK_FIELD_OP: + +			status = +			    acpi_ds_create_bank_field(op, arg->common.node, +						      walk_state); +			break; + +		case AML_FIELD_OP: + +			status = +			    acpi_ds_create_field(op, arg->common.node, +						 walk_state); +			break; + +		default: + +			/* All NAMED_FIELD opcodes must be handled above */ +			break; +		} +		break; + +	case AML_TYPE_NAMED_SIMPLE: + +		status = acpi_ds_create_operands(walk_state, arg); +		if (ACPI_FAILURE(status)) { +			goto cleanup; +		} + +		switch (op->common.aml_opcode) { +		case AML_PROCESSOR_OP: + +			status = acpi_ex_create_processor(walk_state); +			break; + +		case AML_POWER_RES_OP: + +			status = acpi_ex_create_power_resource(walk_state); +			break; + +		case AML_MUTEX_OP: + +			status = acpi_ex_create_mutex(walk_state); +			break; + +		case AML_EVENT_OP: + +			status = acpi_ex_create_event(walk_state); +			break; + +		case AML_ALIAS_OP: + +			status = acpi_ex_create_alias(walk_state); +			break; + +		default: + +			/* Unknown opcode */ + +			status = AE_OK; +			goto cleanup; +		} + +		/* Delete operands */ + +		for (i = 1; i < walk_state->num_operands; i++) { +			acpi_ut_remove_reference(walk_state->operands[i]); +			walk_state->operands[i] = NULL; +		} + +		break; +#endif				/* ACPI_NO_METHOD_EXECUTION */ + +	case AML_TYPE_NAMED_COMPLEX: + +		switch (op->common.aml_opcode) { +#ifndef ACPI_NO_METHOD_EXECUTION +		case AML_REGION_OP: +		case AML_DATA_REGION_OP: + +			if (op->common.aml_opcode == AML_REGION_OP) { +				region_space = (acpi_adr_space_type) +				    ((op->common.value.arg)->common.value. +				     integer); +			} else { +				region_space = ACPI_ADR_SPACE_DATA_TABLE; +			} + +			/* +			 * The op_region is not fully parsed at this time. The only valid +			 * argument is the space_id. (We must save the address of the +			 * AML of the address and length operands) +			 * +			 * If we have a valid region, initialize it. The namespace is +			 * unlocked at this point. +			 * +			 * Need to unlock interpreter if it is locked (if we are running +			 * a control method), in order to allow _REG methods to be run +			 * during acpi_ev_initialize_region. +			 */ +			if (walk_state->method_node) { +				/* +				 * Executing a method: initialize the region and unlock +				 * the interpreter +				 */ +				status = +				    acpi_ex_create_region(op->named.data, +							  op->named.length, +							  region_space, +							  walk_state); +				if (ACPI_FAILURE(status)) { +					return_ACPI_STATUS(status); +				} + +				acpi_ex_exit_interpreter(); +			} + +			status = +			    acpi_ev_initialize_region +			    (acpi_ns_get_attached_object(node), FALSE); +			if (walk_state->method_node) { +				acpi_ex_enter_interpreter(); +			} + +			if (ACPI_FAILURE(status)) { +				/* +				 *  If AE_NOT_EXIST is returned, it is not fatal +				 *  because many regions get created before a handler +				 *  is installed for said region. +				 */ +				if (AE_NOT_EXIST == status) { +					status = AE_OK; +				} +			} +			break; + +		case AML_NAME_OP: + +			status = acpi_ds_create_node(walk_state, node, op); +			break; + +		case AML_METHOD_OP: +			/* +			 * method_op pkg_length name_string method_flags term_list +			 * +			 * Note: We must create the method node/object pair as soon as we +			 * see the method declaration. This allows later pass1 parsing +			 * of invocations of the method (need to know the number of +			 * arguments.) +			 */ +			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, +					  "LOADING-Method: State=%p Op=%p NamedObj=%p\n", +					  walk_state, op, op->named.node)); + +			if (!acpi_ns_get_attached_object(op->named.node)) { +				walk_state->operands[0] = +				    ACPI_CAST_PTR(void, op->named.node); +				walk_state->num_operands = 1; + +				status = +				    acpi_ds_create_operands(walk_state, +							    op->common.value. +							    arg); +				if (ACPI_SUCCESS(status)) { +					status = +					    acpi_ex_create_method(op->named. +								  data, +								  op->named. +								  length, +								  walk_state); +				} +				walk_state->operands[0] = NULL; +				walk_state->num_operands = 0; + +				if (ACPI_FAILURE(status)) { +					return_ACPI_STATUS(status); +				} +			} +			break; + +#endif				/* ACPI_NO_METHOD_EXECUTION */ + +		default: + +			/* All NAMED_COMPLEX opcodes must be handled above */ +			break; +		} +		break; + +	case AML_CLASS_INTERNAL: + +		/* case AML_INT_NAMEPATH_OP: */ +		break; + +	case AML_CLASS_METHOD_CALL: + +		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, +				  "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n", +				  walk_state, op, node)); + +		/* +		 * Lookup the method name and save the Node +		 */ +		status = +		    acpi_ns_lookup(walk_state->scope_info, +				   arg->common.value.string, ACPI_TYPE_ANY, +				   ACPI_IMODE_LOAD_PASS2, +				   ACPI_NS_SEARCH_PARENT | +				   ACPI_NS_DONT_OPEN_SCOPE, walk_state, +				   &(new_node)); +		if (ACPI_SUCCESS(status)) { +			/* +			 * Make sure that what we found is indeed a method +			 * We didn't search for a method on purpose, to see if the name +			 * would resolve +			 */ +			if (new_node->type != ACPI_TYPE_METHOD) { +				status = AE_AML_OPERAND_TYPE; +			} + +			/* We could put the returned object (Node) on the object stack for +			 * later, but for now, we will put it in the "op" object that the +			 * parser uses, so we can get it again at the end of this scope +			 */ +			op->common.node = new_node; +		} else { +			ACPI_ERROR_NAMESPACE(arg->common.value.string, status); +		} +		break; + +	default: + +		break; +	} + +cleanup: + +	/* Remove the Node pushed at the very beginning */ + +	walk_state->operands[0] = NULL; +	walk_state->num_operands = 0; +	return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/dswscope.c b/drivers/acpi/acpica/dswscope.c index d1e701709da..9d6e2c1de1f 100644 --- a/drivers/acpi/acpica/dswscope.c +++ b/drivers/acpi/acpica/dswscope.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 83155dd8671..24f7d5ea678 100644 --- a/drivers/acpi/acpica/dswstate.c +++ b/drivers/acpi/acpica/dswstate.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 c61c3039c31..c7bffff9ed3 100644 --- a/drivers/acpi/acpica/evevent.c +++ b/drivers/acpi/acpica/evevent.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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); @@ -71,6 +71,12 @@ acpi_status acpi_ev_initialize_events(void)  	ACPI_FUNCTION_TRACE(ev_initialize_events); +	/* If Hardware Reduced flag is set, there are no fixed events */ + +	if (acpi_gbl_reduced_hardware) { +		return_ACPI_STATUS(AE_OK); +	} +  	/*  	 * Initialize the Fixed and General Purpose Events. This is done prior to  	 * enabling SCIs to prevent interrupts from occurring before the handlers @@ -111,6 +117,12 @@ acpi_status acpi_ev_install_xrupt_handlers(void)  	ACPI_FUNCTION_TRACE(ev_install_xrupt_handlers); +	/* If Hardware Reduced flag is set, there is no ACPI h/w */ + +	if (acpi_gbl_reduced_hardware) { +		return_ACPI_STATUS(AE_OK); +	} +  	/* Install the SCI handler */  	status = acpi_ev_install_sci_handler(); @@ -217,9 +229,17 @@ u32 acpi_ev_fixed_event_detect(void)  		     status_bit_mask)  		    && (fixed_enable & acpi_gbl_fixed_event_info[i].  			enable_bit_mask)) { +			/* +			 * Found an active (signalled) event. Invoke global event +			 * handler if present. +			 */ +			acpi_fixed_event_count[i]++; +			if (acpi_gbl_global_event_handler) { +				acpi_gbl_global_event_handler +				    (ACPI_EVENT_TYPE_FIXED, NULL, i, +				     acpi_gbl_global_event_handler_context); +			} -			/* Found an active (signalled) event */ -			acpi_os_fixed_event_count(i);  			int_status |= acpi_ev_fixed_event_dispatch(i);  		}  	} @@ -231,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.   *   ******************************************************************************/ @@ -251,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);  	} @@ -271,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 new file mode 100644 index 00000000000..3393a73ca0d --- /dev/null +++ b/drivers/acpi/acpica/evglock.c @@ -0,0 +1,344 @@ +/****************************************************************************** + * + * Module Name: evglock - Global Lock 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. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acevents.h" +#include "acinterp.h" + +#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); + +/******************************************************************************* + * + * FUNCTION:    acpi_ev_init_global_lock_handler + * + * PARAMETERS:  None + * + * RETURN:      Status + * + * DESCRIPTION: Install a handler for the global lock release event + * + ******************************************************************************/ + +acpi_status acpi_ev_init_global_lock_handler(void) +{ +	acpi_status status; + +	ACPI_FUNCTION_TRACE(ev_init_global_lock_handler); + +	/* If Hardware Reduced flag is set, there is no global lock */ + +	if (acpi_gbl_reduced_hardware) { +		return_ACPI_STATUS(AE_OK); +	} + +	/* Attempt installation of the global lock handler */ + +	status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL, +						  acpi_ev_global_lock_handler, +						  NULL); + +	/* +	 * If the global lock does not exist on this platform, the attempt to +	 * enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick). +	 * Map to AE_OK, but mark global lock as not present. Any attempt to +	 * actually use the global lock will be flagged with an error. +	 */ +	acpi_gbl_global_lock_present = FALSE; +	if (status == AE_NO_HARDWARE_RESPONSE) { +		ACPI_ERROR((AE_INFO, +			    "No response from Global Lock hardware, disabling lock")); + +		return_ACPI_STATUS(AE_OK); +	} + +	status = acpi_os_create_lock(&acpi_gbl_global_lock_pending_lock); +	if (ACPI_FAILURE(status)) { +		return_ACPI_STATUS(status); +	} + +	acpi_gbl_global_lock_pending = FALSE; +	acpi_gbl_global_lock_present = TRUE; +	return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ev_remove_global_lock_handler + * + * PARAMETERS:  None + * + * RETURN:      Status + * + * DESCRIPTION: Remove the handler for the Global Lock + * + ******************************************************************************/ + +acpi_status acpi_ev_remove_global_lock_handler(void) +{ +	acpi_status status; + +	ACPI_FUNCTION_TRACE(ev_remove_global_lock_handler); + +	acpi_gbl_global_lock_present = FALSE; +	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); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ev_global_lock_handler + * + * PARAMETERS:  context         - From thread interface, not used + * + * RETURN:      ACPI_INTERRUPT_HANDLED + * + * DESCRIPTION: Invoked directly from the SCI handler when a global lock + *              release interrupt occurs. If there is actually a pending + *              request for the lock, signal the waiting thread. + * + ******************************************************************************/ + +static u32 acpi_ev_global_lock_handler(void *context) +{ +	acpi_status status; +	acpi_cpu_flags flags; + +	flags = acpi_os_acquire_lock(acpi_gbl_global_lock_pending_lock); + +	/* +	 * If a request for the global lock is not actually pending, +	 * we are done. This handles "spurious" global lock interrupts +	 * which are possible (and have been seen) with bad BIOSs. +	 */ +	if (!acpi_gbl_global_lock_pending) { +		goto cleanup_and_exit; +	} + +	/* +	 * Send a unit to the global lock semaphore. The actual acquisition +	 * of the global lock will be performed by the waiting thread. +	 */ +	status = acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore, 1); +	if (ACPI_FAILURE(status)) { +		ACPI_ERROR((AE_INFO, "Could not signal Global Lock semaphore")); +	} + +	acpi_gbl_global_lock_pending = FALSE; + +cleanup_and_exit: + +	acpi_os_release_lock(acpi_gbl_global_lock_pending_lock, flags); +	return (ACPI_INTERRUPT_HANDLED); +} + +/****************************************************************************** + * + * FUNCTION:    acpi_ev_acquire_global_lock + * + * PARAMETERS:  timeout         - Max time to wait for the lock, in millisec. + * + * RETURN:      Status + * + * DESCRIPTION: Attempt to gain ownership of the Global Lock. + * + * MUTEX:       Interpreter must be locked + * + * Note: The original implementation allowed multiple threads to "acquire" the + * Global Lock, and the OS would hold the lock until the last thread had + * released it. However, this could potentially starve the BIOS out of the + * lock, especially in the case where there is a tight handshake between the + * Embedded Controller driver and the BIOS. Therefore, this implementation + * allows only one thread to acquire the HW Global Lock at a time, and makes + * the global lock appear as a standard mutex on the OS side. + * + *****************************************************************************/ + +acpi_status acpi_ev_acquire_global_lock(u16 timeout) +{ +	acpi_cpu_flags flags; +	acpi_status status; +	u8 acquired = FALSE; + +	ACPI_FUNCTION_TRACE(ev_acquire_global_lock); + +	/* +	 * Only one thread can acquire the GL at a time, the global_lock_mutex +	 * enforces this. This interface releases the interpreter if we must wait. +	 */ +	status = +	    acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex->mutex. +				      os_mutex, timeout); +	if (ACPI_FAILURE(status)) { +		return_ACPI_STATUS(status); +	} + +	/* +	 * Update the global lock handle and check for wraparound. The handle is +	 * only used for the external global lock interfaces, but it is updated +	 * here to properly handle the case where a single thread may acquire the +	 * lock via both the AML and the acpi_acquire_global_lock interfaces. The +	 * handle is therefore updated on the first acquire from a given thread +	 * regardless of where the acquisition request originated. +	 */ +	acpi_gbl_global_lock_handle++; +	if (acpi_gbl_global_lock_handle == 0) { +		acpi_gbl_global_lock_handle = 1; +	} + +	/* +	 * Make sure that a global lock actually exists. If not, just +	 * treat the lock as a standard mutex. +	 */ +	if (!acpi_gbl_global_lock_present) { +		acpi_gbl_global_lock_acquired = TRUE; +		return_ACPI_STATUS(AE_OK); +	} + +	flags = acpi_os_acquire_lock(acpi_gbl_global_lock_pending_lock); + +	do { + +		/* Attempt to acquire the actual hardware lock */ + +		ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired); +		if (acquired) { +			acpi_gbl_global_lock_acquired = TRUE; +			ACPI_DEBUG_PRINT((ACPI_DB_EXEC, +					  "Acquired hardware Global Lock\n")); +			break; +		} + +		/* +		 * Did not get the lock. The pending bit was set above, and +		 * we must now wait until we receive the global lock +		 * released interrupt. +		 */ +		acpi_gbl_global_lock_pending = TRUE; +		acpi_os_release_lock(acpi_gbl_global_lock_pending_lock, flags); + +		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, +				  "Waiting for hardware Global Lock\n")); + +		/* +		 * Wait for handshake with the global lock interrupt handler. +		 * This interface releases the interpreter if we must wait. +		 */ +		status = +		    acpi_ex_system_wait_semaphore +		    (acpi_gbl_global_lock_semaphore, ACPI_WAIT_FOREVER); + +		flags = acpi_os_acquire_lock(acpi_gbl_global_lock_pending_lock); + +	} while (ACPI_SUCCESS(status)); + +	acpi_gbl_global_lock_pending = FALSE; +	acpi_os_release_lock(acpi_gbl_global_lock_pending_lock, flags); + +	return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ev_release_global_lock + * + * PARAMETERS:  None + * + * RETURN:      Status + * + * DESCRIPTION: Releases ownership of the Global Lock. + * + ******************************************************************************/ + +acpi_status acpi_ev_release_global_lock(void) +{ +	u8 pending = FALSE; +	acpi_status status = AE_OK; + +	ACPI_FUNCTION_TRACE(ev_release_global_lock); + +	/* Lock must be already acquired */ + +	if (!acpi_gbl_global_lock_acquired) { +		ACPI_WARNING((AE_INFO, +			      "Cannot release the ACPI Global Lock, it has not been acquired")); +		return_ACPI_STATUS(AE_NOT_ACQUIRED); +	} + +	if (acpi_gbl_global_lock_present) { + +		/* Allow any thread to release the lock */ + +		ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_FACS, pending); + +		/* +		 * If the pending bit was set, we must write GBL_RLS to the control +		 * register +		 */ +		if (pending) { +			status = +			    acpi_write_bit_register +			    (ACPI_BITREG_GLOBAL_LOCK_RELEASE, +			     ACPI_ENABLE_EVENT); +		} + +		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, +				  "Released hardware Global Lock\n")); +	} + +	acpi_gbl_global_lock_acquired = FALSE; + +	/* Release the local GL mutex */ + +	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 f226eac314d..48f70013b48 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -48,10 +48,12 @@  #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); +static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context); +  /*******************************************************************************   *   * FUNCTION:    acpi_ev_update_gpe_enable_mask @@ -78,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 */ @@ -88,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); @@ -102,23 +104,23 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info)   *   * RETURN:      Status   * - * DESCRIPTION: Clear the given GPE from stale events and enable it. + * 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;  	ACPI_FUNCTION_TRACE(ev_enable_gpe);  	/* -	 * We will only allow a GPE to be enabled if it has either an -	 * associated method (_Lxx/_Exx) or a handler. Otherwise, the -	 * GPE will be immediately disabled by acpi_ev_gpe_dispatch the -	 * first time it fires. +	 * We will only allow a GPE to be enabled if it has either an associated +	 * method (_Lxx/_Exx) or a handler, or is using the implicit notify +	 * feature. Otherwise, the GPE will be immediately disabled by +	 * acpi_ev_gpe_dispatch the first time it fires.  	 */ -	if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) { +	if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == +	    ACPI_GPE_DISPATCH_NONE) {  		return_ACPI_STATUS(AE_NO_HANDLER);  	} @@ -129,17 +131,17 @@ 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);  }  /*******************************************************************************   * - * FUNCTION:    acpi_raw_enable_gpe + * FUNCTION:    acpi_ev_add_gpe_reference   * - * PARAMETERS:  gpe_event_info  - GPE to enable + * PARAMETERS:  gpe_event_info          - Add a reference to this GPE   *   * RETURN:      Status   * @@ -148,16 +150,22 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)   *   ******************************************************************************/ -acpi_status acpi_raw_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 status = AE_OK; +	ACPI_FUNCTION_TRACE(ev_add_gpe_reference); +  	if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) {  		return_ACPI_STATUS(AE_LIMIT);  	}  	gpe_event_info->runtime_count++;  	if (gpe_event_info->runtime_count == 1) { + +		/* Enable on first reference */ +  		status = acpi_ev_update_gpe_enable_mask(gpe_event_info);  		if (ACPI_SUCCESS(status)) {  			status = acpi_ev_enable_gpe(gpe_event_info); @@ -173,9 +181,9 @@ acpi_status acpi_raw_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)  /*******************************************************************************   * - * FUNCTION:    acpi_raw_disable_gpe + * FUNCTION:    acpi_ev_remove_gpe_reference   * - * PARAMETERS:  gpe_event_info  - GPE to disable + * PARAMETERS:  gpe_event_info          - Remove a reference to this GPE   *   * RETURN:      Status   * @@ -184,19 +192,26 @@ acpi_status acpi_raw_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)   *   ******************************************************************************/ -acpi_status acpi_raw_disable_gpe(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; +	ACPI_FUNCTION_TRACE(ev_remove_gpe_reference); +  	if (!gpe_event_info->runtime_count) {  		return_ACPI_STATUS(AE_LIMIT);  	}  	gpe_event_info->runtime_count--;  	if (!gpe_event_info->runtime_count) { + +		/* Disable on last reference */ +  		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);  		} @@ -294,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); @@ -360,6 +376,27 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)  			gpe_register_info = &gpe_block->register_info[i]; +			/* +			 * Optimization: If there are no GPEs enabled within this +			 * register, we can safely ignore the entire register. +			 */ +			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; +			} +  			/* Read the Status Register */  			status = @@ -379,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%X: 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 */ @@ -405,7 +447,9 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)  					 * or method.  					 */  					int_status |= -					    acpi_ev_gpe_dispatch(&gpe_block-> +					    acpi_ev_gpe_dispatch(gpe_block-> +								 node, +								 &gpe_block->  						event_info[((acpi_size) i * ACPI_GPE_REGISTER_WIDTH) + j], j + gpe_register_info->base_gpe_number);  				}  			} @@ -414,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); @@ -435,19 +479,29 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)   *              an interrupt handler.   *   ******************************************************************************/ -static void acpi_ev_asynch_enable_gpe(void *context);  static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)  { -	struct acpi_gpe_event_info *gpe_event_info = (void *)context; +	struct acpi_gpe_event_info *gpe_event_info = context;  	acpi_status status; -	struct acpi_gpe_event_info local_gpe_event_info; +	struct acpi_gpe_event_info *local_gpe_event_info;  	struct acpi_evaluate_info *info; +	struct acpi_gpe_notify_info *notify;  	ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method); +	/* Allocate a local GPE block */ + +	local_gpe_event_info = +	    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_event_info)); +	if (!local_gpe_event_info) { +		ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "while handling a GPE")); +		return_VOID; +	} +  	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);  	if (ACPI_FAILURE(status)) { +		ACPI_FREE(local_gpe_event_info);  		return_VOID;  	} @@ -455,6 +509,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)  	if (!acpi_ev_valid_gpe_event(gpe_event_info)) {  		status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); +		ACPI_FREE(local_gpe_event_info);  		return_VOID;  	} @@ -462,20 +517,42 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)  	 * Take a snapshot of the GPE info for this level - we copy the info to  	 * prevent a race condition with remove_handler/remove_block.  	 */ -	ACPI_MEMCPY(&local_gpe_event_info, gpe_event_info, +	ACPI_MEMCPY(local_gpe_event_info, gpe_event_info,  		    sizeof(struct acpi_gpe_event_info));  	status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);  	if (ACPI_FAILURE(status)) { +		ACPI_FREE(local_gpe_event_info);  		return_VOID;  	} -	/* -	 * Must check for control method type dispatch one more time to avoid a -	 * race with ev_gpe_install_handler -	 */ -	if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) == -	    ACPI_GPE_DISPATCH_METHOD) { +	/* Do the correct dispatch - normal method or implicit notify */ + +	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. +		 * NOTE: the request is queued for execution after this method +		 * 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. +		 */ +		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; + +	case ACPI_GPE_DISPATCH_METHOD:  		/* Allocate the evaluation information block */ @@ -484,11 +561,11 @@ 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; +			    local_gpe_event_info->dispatch.method_node;  			info->flags = ACPI_IGNORE_RETURN_VALUE;  			status = acpi_ns_evaluate(info); @@ -499,46 +576,98 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)  			ACPI_EXCEPTION((AE_INFO, status,  					"while evaluating GPE method [%4.4s]",  					acpi_ut_get_node_name -					(local_gpe_event_info.dispatch. +					(local_gpe_event_info->dispatch.  					 method_node)));  		} +		break; + +	default: + +		return_VOID;	/* Should never happen */  	} +  	/* Defer enabling of GPE until all notify handlers are done */ -	acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_asynch_enable_gpe, -				gpe_event_info); + +	status = acpi_os_execute(OSL_NOTIFY_HANDLER, +				 acpi_ev_asynch_enable_gpe, +				 local_gpe_event_info); +	if (ACPI_FAILURE(status)) { +		ACPI_FREE(local_gpe_event_info); +	}  	return_VOID;  } -static void acpi_ev_asynch_enable_gpe(void *context) + +/******************************************************************************* + * + * FUNCTION:    acpi_ev_asynch_enable_gpe + * + * PARAMETERS:  Context (gpe_event_info) - Info for this GPE + *              Callback from acpi_os_execute + * + * RETURN:      None + * + * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to + *              complete (i.e., finish execution of Notify) + * + ******************************************************************************/ + +static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context)  {  	struct acpi_gpe_event_info *gpe_event_info = context; + +	(void)acpi_ev_finish_gpe(gpe_event_info); + +	ACPI_FREE(gpe_event_info); +	return; +} + + +/******************************************************************************* + * + * FUNCTION:    acpi_ev_finish_gpe + * + * PARAMETERS:  gpe_event_info      - Info for this GPE + * + * RETURN:      Status + * + * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution + *              of a GPE method or a synchronous or asynchronous GPE handler. + * + ******************************************************************************/ + +acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info) +{  	acpi_status status; +  	if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==  	    ACPI_GPE_LEVEL_TRIGGERED) {  		/* -		 * GPE is level-triggered, we clear the GPE status bit after handling -		 * the event. +		 * GPE is level-triggered, we clear the GPE status bit after +		 * handling the event.  		 */  		status = acpi_hw_clear_gpe(gpe_event_info);  		if (ACPI_FAILURE(status)) { -			return_VOID; +			return (status);  		}  	}  	/* -	 * Enable this GPE, conditionally. This means that the GPE will only be -	 * physically enabled if the enable_for_run bit is set in the event_info +	 * Enable this GPE, conditionally. This means that the GPE will +	 * only be physically enabled if the enable_for_run bit is set +	 * in the event_info.  	 */ -	(void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_COND_ENABLE); - -	return_VOID; +	(void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE); +	return (AE_OK);  } +  /*******************************************************************************   *   * FUNCTION:    acpi_ev_gpe_dispatch   * - * PARAMETERS:  gpe_event_info  - Info for this GPE + * PARAMETERS:  gpe_device      - Device node. NULL for GPE0/GPE1 + *              gpe_event_info  - Info for this GPE   *              gpe_number      - Number relative to the parent GPE block   *   * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED @@ -551,13 +680,22 @@ static void acpi_ev_asynch_enable_gpe(void *context)   ******************************************************************************/  u32 -acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) +acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, +		    struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)  {  	acpi_status status; +	u32 return_value;  	ACPI_FUNCTION_TRACE(ev_gpe_dispatch); -	acpi_os_gpe_count(gpe_number); +	/* Invoke global event handler if present */ + +	acpi_gpe_count++; +	if (acpi_gbl_global_event_handler) { +		acpi_gbl_global_event_handler(ACPI_EVENT_TYPE_GPE, gpe_device, +					      gpe_number, +					      acpi_gbl_global_event_handler_context); +	}  	/*  	 * If edge-triggered, clear the GPE status bit now. Note that @@ -568,60 +706,56 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)  		status = acpi_hw_clear_gpe(gpe_event_info);  		if (ACPI_FAILURE(status)) {  			ACPI_EXCEPTION((AE_INFO, status, -					"Unable to clear GPE[0x%2X]", +					"Unable to clear GPE %02X",  					gpe_number));  			return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);  		}  	}  	/* -	 * Dispatch the GPE to either an installed handler, or the control method -	 * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke -	 * it and do not attempt to run the method. If there is neither a handler -	 * nor a method, we disable this GPE to prevent further such pointless -	 * events from firing. +	 * Always disable the GPE so that it does not keep firing before +	 * any asynchronous activity completes (either from the execution +	 * of a GPE method or an asynchronous GPE handler.) +	 * +	 * If there is no handler or method to run, just disable the +	 * GPE and leave it disabled permanently to prevent further such +	 * pointless events from firing. +	 */ +	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)); +		return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); +	} + +	/* +	 * Dispatch the GPE to either an installed handler or the control +	 * method associated with this GPE (_Lxx or _Exx). If a handler +	 * exists, we invoke it and do not attempt to run the method. +	 * If there is neither a handler nor a method, leave the GPE +	 * disabled.  	 */  	switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) {  	case ACPI_GPE_DISPATCH_HANDLER: -		/* -		 * Invoke the installed handler (at interrupt level) -		 * Ignore return status for now. -		 * TBD: leave GPE disabled on error? -		 */ -		(void)gpe_event_info->dispatch.handler->address(gpe_event_info-> -								dispatch. -								handler-> -								context); +		/* Invoke the installed handler (at interrupt level) */ -		/* It is now safe to clear level-triggered events. */ +		return_value = +		    gpe_event_info->dispatch.handler->address(gpe_device, +							      gpe_number, +							      gpe_event_info-> +							      dispatch.handler-> +							      context); -		if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == -		    ACPI_GPE_LEVEL_TRIGGERED) { -			status = acpi_hw_clear_gpe(gpe_event_info); -			if (ACPI_FAILURE(status)) { -				ACPI_EXCEPTION((AE_INFO, status, -					"Unable to clear GPE[0x%2X]", -						gpe_number)); -				return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); -			} +		/* If requested, clear (if level-triggered) and reenable the GPE */ + +		if (return_value & ACPI_REENABLE_GPE) { +			(void)acpi_ev_finish_gpe(gpe_event_info);  		}  		break;  	case ACPI_GPE_DISPATCH_METHOD: - -		/* -		 * Disable the GPE, so it doesn't keep firing before the method has a -		 * chance to run (it runs asynchronously with interrupts enabled). -		 */ -		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[0x%2X]", -					gpe_number)); -			return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); -		} - +	case ACPI_GPE_DISPATCH_NOTIFY:  		/*  		 * Execute the method associated with the GPE  		 * NOTE: Level-triggered GPEs are cleared after the method completes. @@ -631,35 +765,25 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)  					 gpe_event_info);  		if (ACPI_FAILURE(status)) {  			ACPI_EXCEPTION((AE_INFO, status, -					"Unable to queue handler for GPE[0x%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[0x%2X], disabling event", +			    "No handler or method for GPE %02X, disabling event",  			    gpe_number)); -		/* -		 * Disable the GPE. The GPE will remain disabled a handler -		 * is installed or ACPICA is restarted. -		 */ -		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[0x%2X]", -					gpe_number)); -			return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); -		}  		break;  	}  	return_UINT32(ACPI_INTERRUPT_HANDLED);  } + +#endif				/* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index 020add3eee1..d86699eea33 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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,14 +356,13 @@ 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; -	gpe_block->initialized = FALSE; - -	ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address, -		    sizeof(struct acpi_generic_address));  	/*  	 * Create the register_info and event_info sub-structures @@ -382,11 +378,13 @@ 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);  	} -	acpi_all_gpes_initialized = FALSE; +	acpi_gbl_all_gpes_initialized = FALSE;  	/* Find all GPE methods (_Lxx or_Exx) for this block */ @@ -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 */ @@ -423,14 +423,12 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,   *   * FUNCTION:    acpi_ev_initialize_gpe_block   * - * PARAMETERS:  gpe_device          - Handle to the parent GPE block - *              gpe_block           - Gpe Block info + * PARAMETERS:  acpi_gpe_callback   *   * RETURN:      Status   * - * DESCRIPTION: Initialize and enable a GPE block. First find and run any - *              _PRT methods associated with the block, then enable the - *              appropriate GPEs. + * DESCRIPTION: Initialize and enable a GPE block. Enable GPEs that have + *              associated methods.   *              Note: Assumes namespace is locked.   *   ******************************************************************************/ @@ -450,8 +448,8 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,  	ACPI_FUNCTION_TRACE(ev_initialize_gpe_block);  	/* -	 * Ignore a null GPE block (e.g., if no GPE block 1 exists) and -	 * GPE blocks that have been initialized already. +	 * Ignore a null GPE block (e.g., if no GPE block 1 exists), and +	 * any GPE blocks that have been initialized already.  	 */  	if (!gpe_block || gpe_block->initialized) {  		return_ACPI_STATUS(AE_OK); @@ -459,8 +457,8 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,  	/*  	 * Enable all GPEs that have a corresponding method and have the -	 * ACPI_GPE_CAN_WAKE flag unset.  Any other GPEs within this block must -	 * be enabled via the acpi_enable_gpe() interface. +	 * ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block +	 * must be enabled via the acpi_enable_gpe() interface.  	 */  	gpe_enabled_count = 0; @@ -472,18 +470,24 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,  			gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;  			gpe_event_info = &gpe_block->event_info[gpe_index]; -			/* Ignore GPEs that have no corresponding _Lxx/_Exx method */ - -			if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) +			/* +			 * Ignore GPEs that have no corresponding _Lxx/_Exx method +			 * and GPEs that are used to wake the system +			 */ +			if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == +			     ACPI_GPE_DISPATCH_NONE) +			    || ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) +				== ACPI_GPE_DISPATCH_HANDLER)  			    || (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {  				continue;  			} -			status = acpi_raw_enable_gpe(gpe_event_info); +			status = acpi_ev_add_gpe_reference(gpe_event_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;  			} @@ -492,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 2c7def95f72..49fc7effd96 100644 --- a/drivers/acpi/acpica/evgpeinit.c +++ b/drivers/acpi/acpica/evgpeinit.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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,26 @@  #include "accommon.h"  #include "acevents.h"  #include "acnamesp.h" -#include "acinterp.h"  #define _COMPONENT          ACPI_EVENTS  ACPI_MODULE_NAME("evgpeinit") +#if (!ACPI_REDUCED_HARDWARE)	/* Entire module */ +/* + * Note: History of _PRW support in ACPICA + * + * Originally (2000 - 2010), the GPE initialization code performed a walk of + * the entire namespace to execute the _PRW methods and detect all GPEs + * capable of waking the system. + * + * As of 10/2010, the _PRW method execution has been removed since it is + * actually unnecessary. The host OS must in fact execute all _PRW methods + * in order to identify the device/power-resource dependencies. We now put + * the onus on the host OS to identify the wake GPEs as part of this process + * and to inform ACPICA of these GPEs via the acpi_setup_gpe_for_wake interface. This + * not only reduces the complexity of the ACPICA initialization code, but in + * some cases (on systems with very large namespaces) it should reduce the + * kernel boot time as well. + */  /*******************************************************************************   * @@ -70,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); @@ -106,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]); @@ -151,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, @@ -185,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);  } @@ -222,7 +234,7 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)  	acpi_status status = AE_OK;  	/* -	 * 2) Find any _Lxx/_Exx GPE methods that have just been loaded. +	 * Find any _Lxx/_Exx GPE methods that have just been loaded.  	 *  	 * Any GPEs that correspond to new _Lxx/_Exx methods are immediately  	 * enabled. @@ -235,9 +247,9 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)  		return;  	} +	walk_info.count = 0;  	walk_info.owner_id = table_owner_id;  	walk_info.execute_by_owner_id = TRUE; -	walk_info.count = 0;  	/* Walk the interrupt level descriptor list */ @@ -298,7 +310,7 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)   *                  xx     - is the GPE number [in HEX]   *   * If walk_info->execute_by_owner_id is TRUE, we only execute examine GPE methods - *    with that owner. + * with that owner.   *   ******************************************************************************/ @@ -344,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, @@ -408,10 +423,14 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,  		return_ACPI_STATUS(AE_OK);  	} +	/* Disable the GPE in case it's been enabled already. */ +	(void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); +  	/*  	 * Add the GPE information from above to the gpe_event_info block for  	 * use during dispatch of this GPE.  	 */ +	gpe_event_info->flags &= ~(ACPI_GPE_DISPATCH_MASK);  	gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD);  	gpe_event_info->dispatch.method_node = method_node; @@ -420,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 19a0e513ea4..17e4bbfdb09 100644 --- a/drivers/acpi/acpica/evgpeutil.c +++ b/drivers/acpi/acpica/evgpeutil.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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);  } @@ -154,11 +155,51 @@ u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info)  /*******************************************************************************   * + * FUNCTION:    acpi_ev_get_gpe_device + * + * PARAMETERS:  GPE_WALK_CALLBACK + * + * RETURN:      Status + * + * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE + *              block device. NULL if the GPE is one of the FADT-defined GPEs. + * + ******************************************************************************/ + +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_device_info *info = context; + +	/* Increment Index by the number of GPEs in this block */ + +	info->next_block_base_index += gpe_block->gpe_count; + +	if (info->index < info->next_block_base_index) { +		/* +		 * The GPE index is within this block, get the node. Leave the node +		 * NULL for the FADT-defined GPEs +		 */ +		if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) { +			info->gpe_device = gpe_block->node; +		} + +		info->status = AE_OK; +		return (AE_CTRL_END); +	} + +	return (AE_OK); +} + +/******************************************************************************* + *   * 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 @@ -167,7 +208,9 @@ u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_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; @@ -181,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; @@ -191,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; @@ -210,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 */ @@ -219,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);  }  /******************************************************************************* @@ -307,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; @@ -325,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 fcaed9fb44f..24ea3424981 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -45,7 +45,6 @@  #include "accommon.h"  #include "acevents.h"  #include "acnamesp.h" -#include "acinterp.h"  #define _COMPONENT          ACPI_EVENTS  ACPI_MODULE_NAME("evmisc") @@ -53,15 +52,11 @@ ACPI_MODULE_NAME("evmisc")  /* Local prototypes */  static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context); -static u32 acpi_ev_global_lock_handler(void *context); - -static acpi_status acpi_ev_remove_global_lock_handler(void); -  /*******************************************************************************   *   * FUNCTION:    acpi_ev_is_notify_object   * - * PARAMETERS:  Node            - Node to check + * PARAMETERS:  node            - Node to check   *   * RETURN:      TRUE if notifies allowed on this object   * @@ -83,6 +78,7 @@ u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node)  		return (TRUE);  	default: +  		return (FALSE);  	}  } @@ -91,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 @@ -106,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))); - -	/* Get the notify object attached to the NS Node */ +	/* Are Notifies allowed on this object? */ -	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); @@ -208,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.   * @@ -219,346 +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 the system handler first, if present */ +	/* Invoke a global notify handler if installed */ -	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); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_ev_global_lock_handler - * - * PARAMETERS:  Context         - From thread interface, not used - * - * RETURN:      ACPI_INTERRUPT_HANDLED - * - * DESCRIPTION: Invoked directly from the SCI handler when a global lock - *              release interrupt occurs. Attempt to acquire the global lock, - *              if successful, signal the thread waiting for the lock. - * - * NOTE: Assumes that the semaphore can be signaled from interrupt level. If - * this is not possible for some reason, a separate thread will have to be - * scheduled to do this. - * - ******************************************************************************/ - -static u32 acpi_ev_global_lock_handler(void *context) -{ -	u8 acquired = FALSE; - -	/* -	 * Attempt to get the lock. -	 * -	 * If we don't get it now, it will be marked pending and we will -	 * take another interrupt when it becomes free. -	 */ -	ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired); -	if (acquired) { - -		/* Got the lock, now wake all threads waiting for it */ - -		acpi_gbl_global_lock_acquired = TRUE; -		/* Send a unit to the semaphore */ - -		if (ACPI_FAILURE -		    (acpi_os_signal_semaphore -		     (acpi_gbl_global_lock_semaphore, 1))) { -			ACPI_ERROR((AE_INFO, -				    "Could not signal Global Lock semaphore")); -		} -	} - -	return (ACPI_INTERRUPT_HANDLED); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_ev_init_global_lock_handler - * - * PARAMETERS:  None - * - * RETURN:      Status - * - * DESCRIPTION: Install a handler for the global lock release event - * - ******************************************************************************/ - -acpi_status acpi_ev_init_global_lock_handler(void) -{ -	acpi_status status; - -	ACPI_FUNCTION_TRACE(ev_init_global_lock_handler); - -	/* Attempt installation of the global lock handler */ - -	status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL, -						  acpi_ev_global_lock_handler, -						  NULL); - -	/* -	 * If the global lock does not exist on this platform, the attempt to -	 * enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick). -	 * Map to AE_OK, but mark global lock as not present. Any attempt to -	 * actually use the global lock will be flagged with an error. -	 */ -	if (status == AE_NO_HARDWARE_RESPONSE) { -		ACPI_ERROR((AE_INFO, -			    "No response from Global Lock hardware, disabling lock")); - -		acpi_gbl_global_lock_present = FALSE; -		return_ACPI_STATUS(AE_OK); -	} - -	acpi_gbl_global_lock_present = TRUE; -	return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_ev_remove_global_lock_handler - * - * PARAMETERS:  None - * - * RETURN:      Status - * - * DESCRIPTION: Remove the handler for the Global Lock - * - ******************************************************************************/ - -static acpi_status acpi_ev_remove_global_lock_handler(void) -{ -	acpi_status status; - -	ACPI_FUNCTION_TRACE(ev_remove_global_lock_handler); - -	acpi_gbl_global_lock_present = FALSE; -	status = acpi_remove_fixed_event_handler(ACPI_EVENT_GLOBAL, -						 acpi_ev_global_lock_handler); - -	return_ACPI_STATUS(status); -} - -/****************************************************************************** - * - * FUNCTION:    acpi_ev_acquire_global_lock - * - * PARAMETERS:  Timeout         - Max time to wait for the lock, in millisec. - * - * RETURN:      Status - * - * DESCRIPTION: Attempt to gain ownership of the Global Lock. - * - * MUTEX:       Interpreter must be locked - * - * Note: The original implementation allowed multiple threads to "acquire" the - * Global Lock, and the OS would hold the lock until the last thread had - * released it. However, this could potentially starve the BIOS out of the - * lock, especially in the case where there is a tight handshake between the - * Embedded Controller driver and the BIOS. Therefore, this implementation - * allows only one thread to acquire the HW Global Lock at a time, and makes - * the global lock appear as a standard mutex on the OS side. - * - *****************************************************************************/ -static acpi_thread_id acpi_ev_global_lock_thread_id; -static int acpi_ev_global_lock_acquired; - -acpi_status acpi_ev_acquire_global_lock(u16 timeout) -{ -	acpi_status status = AE_OK; -	u8 acquired = FALSE; - -	ACPI_FUNCTION_TRACE(ev_acquire_global_lock); - -	/* -	 * Only one thread can acquire the GL at a time, the global_lock_mutex -	 * enforces this. This interface releases the interpreter if we must wait. -	 */ -	status = acpi_ex_system_wait_mutex( -			acpi_gbl_global_lock_mutex->mutex.os_mutex, 0); -	if (status == AE_TIME) { -		if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) { -			acpi_ev_global_lock_acquired++; -			return AE_OK; -		} -	} - -	if (ACPI_FAILURE(status)) { -		status = acpi_ex_system_wait_mutex( -				acpi_gbl_global_lock_mutex->mutex.os_mutex, -				timeout); -	} -	if (ACPI_FAILURE(status)) { -		return_ACPI_STATUS(status); -	} - -	acpi_ev_global_lock_thread_id = acpi_os_get_thread_id(); -	acpi_ev_global_lock_acquired++; - -	/* -	 * Update the global lock handle and check for wraparound. The handle is -	 * only used for the external global lock interfaces, but it is updated -	 * here to properly handle the case where a single thread may acquire the -	 * lock via both the AML and the acpi_acquire_global_lock interfaces. The -	 * handle is therefore updated on the first acquire from a given thread -	 * regardless of where the acquisition request originated. -	 */ -	acpi_gbl_global_lock_handle++; -	if (acpi_gbl_global_lock_handle == 0) { -		acpi_gbl_global_lock_handle = 1; -	} - -	/* -	 * Make sure that a global lock actually exists. If not, just treat the -	 * lock as a standard mutex. -	 */ -	if (!acpi_gbl_global_lock_present) { -		acpi_gbl_global_lock_acquired = TRUE; -		return_ACPI_STATUS(AE_OK); -	} - -	/* Attempt to acquire the actual hardware lock */ - -	ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired); -	if (acquired) { - -		/* We got the lock */ - -		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, -				  "Acquired hardware Global Lock\n")); - -		acpi_gbl_global_lock_acquired = TRUE; -		return_ACPI_STATUS(AE_OK); -	} - -	/* -	 * Did not get the lock. The pending bit was set above, and we must now -	 * wait until we get the global lock released interrupt. -	 */ -	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for hardware Global Lock\n")); - -	/* -	 * Wait for handshake with the global lock interrupt handler. -	 * This interface releases the interpreter if we must wait. -	 */ -	status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore, -					       ACPI_WAIT_FOREVER); - -	return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_ev_release_global_lock - * - * PARAMETERS:  None - * - * RETURN:      Status - * - * DESCRIPTION: Releases ownership of the Global Lock. - * - ******************************************************************************/ - -acpi_status acpi_ev_release_global_lock(void) -{ -	u8 pending = FALSE; -	acpi_status status = AE_OK; - -	ACPI_FUNCTION_TRACE(ev_release_global_lock); - -	/* Lock must be already acquired */ - -	if (!acpi_gbl_global_lock_acquired) { -		ACPI_WARNING((AE_INFO, -			      "Cannot release the ACPI Global Lock, it has not been acquired")); -		return_ACPI_STATUS(AE_NOT_ACQUIRED); -	} - -	acpi_ev_global_lock_acquired--; -	if (acpi_ev_global_lock_acquired > 0) { -		return AE_OK; -	} - -	if (acpi_gbl_global_lock_present) { - -		/* Allow any thread to release the lock */ - -		ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_FACS, pending); - -		/* -		 * If the pending bit was set, we must write GBL_RLS to the control -		 * register -		 */ -		if (pending) { -			status = -			    acpi_write_bit_register -			    (ACPI_BITREG_GLOBAL_LOCK_RELEASE, -			     ACPI_ENABLE_EVENT); -		} - -		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, -				  "Released hardware Global Lock\n")); -	} - -	acpi_gbl_global_lock_acquired = FALSE; - -	/* Release the local GL mutex */ -	acpi_ev_global_lock_thread_id = 0; -	acpi_ev_global_lock_acquired = 0; -	acpi_os_release_mutex(acpi_gbl_global_lock_mutex->mutex.os_mutex); -	return_ACPI_STATUS(status); +	acpi_ut_delete_generic_state(info);  } +#if (!ACPI_REDUCED_HARDWARE)  /******************************************************************************   *   * FUNCTION:    acpi_ev_terminate @@ -599,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 */ @@ -627,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 98fd210e87b..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 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -50,144 +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(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 @@ -231,92 +104,9 @@ acpi_status acpi_ev_initialize_op_regions(void)  		}  	} -	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); -	return_ACPI_STATUS(status); -} +	acpi_gbl_reg_methods_executed = TRUE; -/******************************************************************************* - * - * 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); +	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);  	return_ACPI_STATUS(status);  } @@ -325,10 +115,11 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)   * FUNCTION:    acpi_ev_address_space_dispatch   *   * PARAMETERS:  region_obj          - Internal region object - *              Function            - Read or Write operation + *              field_obj           - Corresponding field. Can be NULL. + *              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 @@ -340,6 +131,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)  acpi_status  acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, +			       union acpi_operand_object *field_obj,  			       u32 function,  			       u32 region_offset, u32 bit_width, u64 *value)  { @@ -349,6 +141,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,  	union acpi_operand_object *handler_desc;  	union acpi_operand_object *region_obj2;  	void *region_context = NULL; +	struct acpi_connection_info *context;  	ACPI_FUNCTION_TRACE(ev_address_space_dispatch); @@ -371,6 +164,8 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,  		return_ACPI_STATUS(AE_NOT_EXIST);  	} +	context = handler_desc->address_space.context; +  	/*  	 * It may be the case that the region has never been initialized.  	 * Some types of regions require special init code @@ -400,8 +195,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,  		acpi_ex_exit_interpreter();  		status = region_setup(region_obj, ACPI_REGION_ACTIVATE, -				      handler_desc->address_space.context, -				      ®ion_context); +				      context, ®ion_context);  		/* Re-enter the interpreter */ @@ -423,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;  			} @@ -451,6 +240,25 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,  			  acpi_ut_get_region_name(region_obj->region.  						  space_id))); +	/* +	 * Special handling for generic_serial_bus and general_purpose_io: +	 * There are three extra parameters that must be passed to the +	 * handler via the context: +	 *   1) Connection buffer, a resource template from Connection() op. +	 *   2) Length of the above buffer. +	 *   3) Actual access length from the access_as() op. +	 */ +	if (((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) || +	     (region_obj->region.space_id == ACPI_ADR_SPACE_GPIO)) && +	    context && field_obj) { + +		/* Get the Connection (resource_template) buffer */ + +		context->connection = field_obj->field.resource_buffer; +		context->length = field_obj->field.resource_length; +		context->access_length = field_obj->field.access_length; +	} +  	if (!(handler_desc->address_space.handler_flags &  	      ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {  		/* @@ -465,7 +273,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,  	status = handler(function,  			 (region_obj->region.address + region_offset), -			 bit_width, value, handler_desc->address_space.context, +			 bit_width, value, context,  			 region_obj2->extra.region_context);  	if (ACPI_FAILURE(status)) { @@ -506,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; @@ -533,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) { @@ -559,7 +369,9 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj,  			/* Now stop region accesses by executing the _REG method */ -			status = acpi_ev_execute_reg_method(region_obj, 0); +			status = +			    acpi_ev_execute_reg_method(region_obj, +						       ACPI_REG_DISCONNECT);  			if (ACPI_FAILURE(status)) {  				ACPI_EXCEPTION((AE_INFO, status,  						"from region _REG, [%s]", @@ -587,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)) { @@ -620,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 */ @@ -680,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: +	 * +	 * arg0 - Integer: +	 *  Operation region space ID Same value as region_obj->Region.space_id  	 * -	 * At this point there is no existing handler. Just allocate the object -	 * for the handler and link it into the list. +	 * 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);  } @@ -1032,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 @@ -1060,6 +624,12 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,  					ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,  					NULL, &space_id, NULL); +	/* Special case for EC: handle "orphan" _REG methods with no region */ + +	if (space_id == ACPI_ADR_SPACE_EC) { +		acpi_ev_orphan_ec_reg_method(node); +	} +  	return_ACPI_STATUS(status);  } @@ -1069,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   *   ******************************************************************************/ @@ -1118,6 +688,93 @@ acpi_ev_reg_run(acpi_handle obj_handle,  		return (AE_OK);  	} -	status = acpi_ev_execute_reg_method(obj_desc, 1); +	status = acpi_ev_execute_reg_method(obj_desc, ACPI_REG_CONNECT);  	return (status);  } + +/******************************************************************************* + * + * FUNCTION:    acpi_ev_orphan_ec_reg_method + * + * PARAMETERS:  ec_device_node      - Namespace node for an EC device + * + * RETURN:      None + * + * DESCRIPTION: Execute an "orphan" _REG method that appears under the EC + *              device. This is a _REG method that has no corresponding region + *              within the EC device scope. The orphan _REG method appears to + *              have been enabled by the description of the ECDT in the ACPI + *              specification: "The availability of the region space can be + *              detected by providing a _REG method object underneath the + *              Embedded Controller 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(struct acpi_namespace_node *ec_device_node) +{ +	acpi_handle reg_method; +	struct acpi_namespace_node *next_node; +	acpi_status status; +	struct acpi_object_list args; +	union acpi_object objects[2]; + +	ACPI_FUNCTION_TRACE(ev_orphan_ec_reg_method); + +	if (!ec_device_node) { +		return_VOID; +	} + +	/* Namespace is currently locked, must release */ + +	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + +	/* Get a handle to a _REG method immediately under the EC device */ + +	status = acpi_get_handle(ec_device_node, METHOD_NAME__REG, ®_method); +	if (ACPI_FAILURE(status)) { +		goto exit;	/* There is no _REG method present */ +	} + +	/* +	 * Execute the _REG method only if there is no Operation Region in +	 * 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 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 the _REG */ +		} + +		next_node = acpi_ns_get_next_node(ec_device_node, next_node); +	} + +	/* Evaluate the _REG(embedded_control,Connect) method */ + +	args.count = 2; +	args.pointer = objects; +	objects[0].type = ACPI_TYPE_INTEGER; +	objects[0].integer.value = ACPI_ADR_SPACE_EC; +	objects[1].type = ACPI_TYPE_INTEGER; +	objects[1].integer.value = ACPI_REG_CONNECT; + +	status = acpi_evaluate_object(reg_method, NULL, &args, NULL); + +exit: +	/* We ignore all errors from above, don't care */ + +	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); +	return_VOID; +} diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index 0b47a6dc929..1b148a440d6 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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   * @@ -590,14 +589,16 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,  				 * See acpi_ns_exec_module_code  				 */  				if (obj_desc->method. -				    flags & AOPOBJ_MODULE_LEVEL) { +				    info_flags & ACPI_METHOD_MODULE_LEVEL) {  					handler_obj = -					    obj_desc->method.extra.handler; +					    obj_desc->method.dispatch.handler;  				}  				break;  			default: +  				/* Ignore other objects */ +  				break;  			} @@ -637,7 +638,7 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,  					status =  					    acpi_ev_execute_reg_method -					    (region_obj, 1); +					    (region_obj, ACPI_REG_CONNECT);  					if (acpi_ns_locked) {  						status = diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c index 8dfbaa96e42..29630e30382 100644 --- a/drivers/acpi/acpica/evsci.c +++ b/drivers/acpi/acpica/evsci.c @@ -6,7 +6,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 36af222cac6..11e5803b8b4 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -41,6 +41,8 @@   * POSSIBILITY OF SUCH DAMAGES.   */ +#define EXPORT_ACPI_INTERFACES +  #include <acpi/acpi.h>  #include "accommon.h"  #include "acnamesp.h" @@ -50,606 +52,668 @@  #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); -	return_ACPI_STATUS(status); -} +	if (!acpi_ev_is_notify_object(node)) { +		status = AE_TYPE; +		goto unlock_and_exit; +	} -ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) -#endif				/*  ACPI_FUTURE_USAGE  */ -/******************************************************************************* - * - * FUNCTION:    acpi_install_fixed_event_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: Saves the pointer to the handler function and then enables the - *              event. - * - ******************************************************************************/ -acpi_status -acpi_install_fixed_event_handler(u32 event, -				 acpi_event_handler handler, void *context) -{ -	acpi_status status; +	/* Check for an existing internal object, might not exist */ -	ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler); +	obj_desc = acpi_ns_get_attached_object(node); +	if (!obj_desc) { -	/* Parameter validation */ +		/* Create a new object */ -	if (event > ACPI_EVENT_MAX) { -		return_ACPI_STATUS(AE_BAD_PARAMETER); +		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; +		}  	} -	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); -	if (ACPI_FAILURE(status)) { -		return_ACPI_STATUS(status); +	/* 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]; +			} +		}  	} -	/* Don't allow two handlers. */ +	/* Create and populate a new notify handler object */ -	if (NULL != acpi_gbl_fixed_event_handlers[event].handler) { -		status = AE_ALREADY_EXISTS; -		goto cleanup; +	handler_obj = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY); +	if (!handler_obj) { +		status = AE_NO_MEMORY; +		goto unlock_and_exit;  	} -	/* Install the handler before enabling the event */ +	handler_obj->notify.node = node; +	handler_obj->notify.handler_type = handler_type; +	handler_obj->notify.handler = handler; +	handler_obj->notify.context = context; -	acpi_gbl_fixed_event_handlers[event].handler = handler; -	acpi_gbl_fixed_event_handlers[event].context = context; +	/* Install the handler at the list head(s) */ -	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)); +	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]; -		/* Remove the handler */ +			obj_desc->common_notify.notify_list[i] = handler_obj; +		} +	} -		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)); +	/* Add an extra reference if handler was installed in both lists */ + +	if (handler_type == ACPI_ALL_NOTIFY) { +		acpi_ut_add_reference(handler_obj);  	} -      cleanup: -	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); +unlock_and_exit: +	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);  	return_ACPI_STATUS(status);  } -ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler) +ACPI_EXPORT_SYMBOL(acpi_install_notify_handler)  /*******************************************************************************   * - * FUNCTION:    acpi_remove_fixed_event_handler + * FUNCTION:    acpi_remove_notify_handler   * - * PARAMETERS:  Event           - Event type to disable. - *              Handler         - Address of the handler + * 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: Disables the event and unregisters the event handler. + * DESCRIPTION: Remove a handler for notifies on an ACPI device   *   ******************************************************************************/  acpi_status -acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler) +acpi_remove_notify_handler(acpi_handle device, +			   u32 handler_type, acpi_notify_handler handler)  { +	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_remove_fixed_event_handler); +	ACPI_FUNCTION_TRACE(acpi_remove_notify_handler);  	/* Parameter validation */ -	if (event > ACPI_EVENT_MAX) { +	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);  	} -	/* Disable the event before removing the handler */ +	/* All other objects: Are Notifies allowed on this object? */ -	status = acpi_disable_event(event, 0); +	if (!acpi_ev_is_notify_object(node)) { +		return_ACPI_STATUS(AE_TYPE); +	} -	/* Always Remove the handler */ +	/* Must have an existing internal object */ -	acpi_gbl_fixed_event_handlers[event].handler = NULL; -	acpi_gbl_fixed_event_handlers[event].context = NULL; +	obj_desc = acpi_ns_get_attached_object(node); +	if (!obj_desc) { +		return_ACPI_STATUS(AE_NOT_EXIST); +	} -	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)); +	/* 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); +		}  	} -	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);  	return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_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 - * - * 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; +unlock_and_exit: +	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); +	return_ACPI_STATUS(status);  } +ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler) +  /*******************************************************************************   * - * FUNCTION:    acpi_add_handler_object + * FUNCTION:    acpi_install_exception_handler   * - * PARAMETERS:  parent_obj         - Parent of the new object - *              handler            - Address of the handler - *              context            - Value passed to the handler on each GPE + * PARAMETERS:  handler         - Pointer to the handler function for the + *                                event   *   * RETURN:      Status   * - * DESCRIPTION: Create a new handler object and populate it. + * DESCRIPTION: Saves the pointer to the handler function   *   ******************************************************************************/ -static acpi_status -acpi_add_handler_object(struct acpi_object_notify_handler *parent_obj, -			acpi_notify_handler handler, void *context) +#ifdef ACPI_FUTURE_USAGE +acpi_status acpi_install_exception_handler(acpi_exception_handler handler)  { -	struct acpi_object_notify_handler *handler_obj; +	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; +	ACPI_FUNCTION_TRACE(acpi_install_exception_handler); -	handler_obj = ACPI_ALLOCATE_ZEROED(sizeof(*handler_obj)); -	if (!handler_obj) -		return AE_NO_MEMORY; +	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); +	if (ACPI_FAILURE(status)) { +		return_ACPI_STATUS(status); +	} + +	/* Don't allow two handlers. */ + +	if (acpi_gbl_exception_handler) { +		status = AE_ALREADY_EXISTS; +		goto cleanup; +	} -	acpi_populate_handler_object(handler_obj, -					ACPI_SYSTEM_NOTIFY, -					handler, context, -					parent_obj->next); -	parent_obj->next = handler_obj; +	/* Install the handler */ -	return AE_OK; +	acpi_gbl_exception_handler = handler; + +cleanup: +	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); +	return_ACPI_STATUS(status);  } +ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) +#endif				/*  ACPI_FUTURE_USAGE  */ + +#if (!ACPI_REDUCED_HARDWARE)  /*******************************************************************************   * - * FUNCTION:    acpi_install_notify_handler + * FUNCTION:    acpi_install_sci_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:  address             - Address of the handler + *              context             - Value passed to the handler on each SCI   *   * RETURN:      Status   * - * DESCRIPTION: Install a handler for notifies on an ACPI device + * DESCRIPTION: Install a handler for a System Control Interrupt.   *   ******************************************************************************/ -acpi_status -acpi_install_notify_handler(acpi_handle device, -			    u32 handler_type, -			    acpi_notify_handler handler, void *context) +acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context)  { -	union acpi_operand_object *obj_desc; -	union acpi_operand_object *notify_obj; -	struct acpi_namespace_node *node; +	struct acpi_sci_handler_info *new_sci_handler; +	struct acpi_sci_handler_info *sci_handler; +	acpi_cpu_flags flags;  	acpi_status status; -	ACPI_FUNCTION_TRACE(acpi_install_notify_handler); - -	/* Parameter validation */ +	ACPI_FUNCTION_TRACE(acpi_install_sci_handler); -	if ((!device) || -	    (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { +	if (!address) {  		return_ACPI_STATUS(AE_BAD_PARAMETER);  	} -	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); -	if (ACPI_FAILURE(status)) { -		return_ACPI_STATUS(status); +	/* 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);  	} -	/* Convert and validate the device handle */ +	new_sci_handler->address = address; +	new_sci_handler->context = context; -	node = acpi_ns_validate_handle(device); -	if (!node) { -		status = AE_BAD_PARAMETER; -		goto unlock_and_exit; +	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); +	if (ACPI_FAILURE(status)) { +		goto 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) { +	/* Lock list during installation */ + +	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); +	sci_handler = acpi_gbl_sci_handler_list; -		/* Make sure the handler is not already installed */ +	/* Ensure handler does not already exist */ -		if (((handler_type & ACPI_SYSTEM_NOTIFY) && -		     acpi_gbl_system_notify.handler) || -		    ((handler_type & ACPI_DEVICE_NOTIFY) && -		     acpi_gbl_device_notify.handler)) { +	while (sci_handler) { +		if (address == sci_handler->address) {  			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; -		} - -		/* Global notify handler installed */ +		sci_handler = sci_handler->next;  	} -	/* -	 * 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? */ +	/* Install the new handler into the global list (at head) */ -		if (!acpi_ev_is_notify_object(node)) { -			status = AE_TYPE; -			goto unlock_and_exit; -		} +	new_sci_handler->next = acpi_gbl_sci_handler_list; +	acpi_gbl_sci_handler_list = new_sci_handler; -		/* Check for an existing internal object */ +unlock_and_exit: -		obj_desc = acpi_ns_get_attached_object(node); -		if (obj_desc) { +	acpi_os_release_lock(acpi_gbl_gpe_lock, flags); +	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); -			/* Object exists. */ +exit: +	if (ACPI_FAILURE(status)) { +		ACPI_FREE(new_sci_handler); +	} +	return_ACPI_STATUS(status); +} -			/* 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; -			} +ACPI_EXPORT_SYMBOL(acpi_install_sci_handler) -			/* System notifies may have more handlers installed. */ -			notify_obj = obj_desc->common_notify.system_notify; +/******************************************************************************* + * + * FUNCTION:    acpi_remove_sci_handler + * + * PARAMETERS:  address             - Address of the handler + * + * RETURN:      Status + * + * DESCRIPTION: Remove a handler for a System Control Interrupt. + * + ******************************************************************************/ +acpi_status acpi_remove_sci_handler(acpi_sci_handler address) +{ +	struct acpi_sci_handler_info *prev_sci_handler; +	struct acpi_sci_handler_info *next_sci_handler; +	acpi_cpu_flags flags; +	acpi_status status; -			if ((handler_type & ACPI_SYSTEM_NOTIFY) && notify_obj) { -				struct acpi_object_notify_handler *parent_obj; +	ACPI_FUNCTION_TRACE(acpi_remove_sci_handler); -				if (handler_type & ACPI_DEVICE_NOTIFY) { -					status = AE_ALREADY_EXISTS; -					goto unlock_and_exit; -				} +	if (!address) { +		return_ACPI_STATUS(AE_BAD_PARAMETER); +	} -				parent_obj = ¬ify_obj->notify; -				status = acpi_add_handler_object(parent_obj, -								 handler, -								 context); -				goto unlock_and_exit; -			} -		} else { -			/* Create a new object */ +	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); +	if (ACPI_FAILURE(status)) { +		return_ACPI_STATUS(status); +	} -			obj_desc = acpi_ut_create_internal_object(node->type); -			if (!obj_desc) { -				status = AE_NO_MEMORY; -				goto unlock_and_exit; -			} +	/* Remove the SCI handler with lock */ -			/* Attach new object to the Node */ +	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); -			status = -			    acpi_ns_attach_object(device, obj_desc, node->type); +	prev_sci_handler = NULL; +	next_sci_handler = acpi_gbl_sci_handler_list; +	while (next_sci_handler) { +		if (next_sci_handler->address == address) { -			/* Remove local reference to the object */ +			/* Unlink and free the SCI handler info block */ -			acpi_ut_remove_reference(obj_desc); -			if (ACPI_FAILURE(status)) { -				goto unlock_and_exit; +			if (prev_sci_handler) { +				prev_sci_handler->next = next_sci_handler->next; +			} else { +				acpi_gbl_sci_handler_list = +				    next_sci_handler->next;  			} -		} - -		/* Install the handler */ -		notify_obj = -		    acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY); -		if (!notify_obj) { -			status = AE_NO_MEMORY; +			acpi_os_release_lock(acpi_gbl_gpe_lock, flags); +			ACPI_FREE(next_sci_handler);  			goto unlock_and_exit;  		} -		acpi_populate_handler_object(¬ify_obj->notify, -						handler_type, -						handler, context, -						NULL); +		prev_sci_handler = next_sci_handler; +		next_sci_handler = next_sci_handler->next; +	} -		if (handler_type & ACPI_SYSTEM_NOTIFY) { -			obj_desc->common_notify.system_notify = notify_obj; -		} +	acpi_os_release_lock(acpi_gbl_gpe_lock, flags); +	status = AE_NOT_EXIST; -		if (handler_type & ACPI_DEVICE_NOTIFY) { -			obj_desc->common_notify.device_notify = notify_obj; -		} +unlock_and_exit: +	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); +	return_ACPI_STATUS(status); +} -		if (handler_type == ACPI_ALL_NOTIFY) { +ACPI_EXPORT_SYMBOL(acpi_remove_sci_handler) -			/* Extra ref if installed in both */ +/******************************************************************************* + * + * FUNCTION:    acpi_install_global_event_handler + * + * PARAMETERS:  handler         - Pointer to the global event handler function + *              context         - Value passed to the handler on each event + * + * 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. + * + ******************************************************************************/ +acpi_status +acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context) +{ +	acpi_status status; -			acpi_ut_add_reference(notify_obj); -		} +	ACPI_FUNCTION_TRACE(acpi_install_global_event_handler); + +	/* Parameter validation */ + +	if (!handler) { +		return_ACPI_STATUS(AE_BAD_PARAMETER);  	} -      unlock_and_exit: -	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); +	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); +	if (ACPI_FAILURE(status)) { +		return_ACPI_STATUS(status); +	} + +	/* Don't allow two handlers. */ + +	if (acpi_gbl_global_event_handler) { +		status = AE_ALREADY_EXISTS; +		goto cleanup; +	} + +	acpi_gbl_global_event_handler = handler; +	acpi_gbl_global_event_handler_context = context; + +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)  /*******************************************************************************   * @@ -658,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   * @@ -671,10 +735,10 @@ ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler)  acpi_status  acpi_install_gpe_handler(acpi_handle gpe_device,  			 u32 gpe_number, -			 u32 type, acpi_event_handler address, void *context) +			 u32 type, acpi_gpe_handler address, void *context)  {  	struct acpi_gpe_event_info *gpe_event_info; -	struct acpi_handler_info *handler; +	struct acpi_gpe_handler_info *handler;  	acpi_status status;  	acpi_cpu_flags flags; @@ -691,9 +755,9 @@ 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_handler_info)); +	handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info));  	if (!handler) {  		status = AE_NO_MEMORY;  		goto unlock_and_exit; @@ -717,31 +781,30 @@ 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->orig_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.  	 */ -	if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD) +	if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD)  	    && gpe_event_info->runtime_count) { -		handler->orig_enabled = 1; -		(void)acpi_raw_disable_gpe(gpe_event_info); +		handler->originally_enabled = 1; +		(void)acpi_ev_remove_gpe_reference(gpe_event_info);  	}  	/* Install the handler */  	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); @@ -768,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   * @@ -777,10 +840,10 @@ ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler)   ******************************************************************************/  acpi_status  acpi_remove_gpe_handler(acpi_handle gpe_device, -			u32 gpe_number, acpi_event_handler address) +			u32 gpe_number, acpi_gpe_handler address)  {  	struct acpi_gpe_event_info *gpe_event_info; -	struct acpi_handler_info *handler; +	struct acpi_gpe_handler_info *handler;  	acpi_status status;  	acpi_cpu_flags flags; @@ -792,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); @@ -835,21 +894,29 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,  	gpe_event_info->dispatch.method_node = handler->method_node;  	gpe_event_info->flags &=  		~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); -	gpe_event_info->flags |= handler->orig_flags; +	gpe_event_info->flags |= handler->original_flags;  	/*  	 * If the GPE was previously associated with a method and it was  	 * 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) { +		(void)acpi_ev_add_gpe_reference(gpe_event_info); +	} -	if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD) -	    && handler->orig_enabled) -		(void)acpi_raw_enable_gpe(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); @@ -864,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 @@ -912,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   * @@ -932,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 a1dabe3fd8a..e286640ad4f 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -41,20 +41,16 @@   * POSSIBILITY OF SUCH DAMAGES.   */ +#define EXPORT_ACPI_INTERFACES +  #include <acpi/acpi.h>  #include "accommon.h" -#include "acevents.h" -#include "acnamesp.h"  #include "actables.h"  #define _COMPONENT          ACPI_EVENTS  ACPI_MODULE_NAME("evxfevnt") -/* Local prototypes */ -static acpi_status -acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, -		       struct acpi_gpe_block_info *gpe_block, void *context); - +#if (!ACPI_REDUCED_HARDWARE)	/* Entire module */  /*******************************************************************************   *   * FUNCTION:    acpi_enable @@ -66,7 +62,6 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,   * DESCRIPTION: Transfers the system into ACPI mode.   *   ******************************************************************************/ -  acpi_status acpi_enable(void)  {  	acpi_status status; @@ -80,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) { @@ -132,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")); @@ -158,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   * @@ -213,189 +220,10 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event)  /*******************************************************************************   * - * FUNCTION:    acpi_gpe_wakeup - * - * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1 - *              gpe_number      - GPE level within the GPE block - *              Action          - Enable or Disable - * - * RETURN:      Status - * - * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. - * - ******************************************************************************/ -acpi_status acpi_gpe_wakeup(acpi_handle gpe_device, u32 gpe_number, u8 action) -{ -	acpi_status status = AE_OK; -	struct acpi_gpe_event_info *gpe_event_info; -	struct acpi_gpe_register_info *gpe_register_info; -	acpi_cpu_flags flags; -	u32 register_bit; - -	ACPI_FUNCTION_TRACE(acpi_gpe_wakeup); - -	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 || !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { -		status = AE_BAD_PARAMETER; -		goto unlock_and_exit; -	} - -	gpe_register_info = gpe_event_info->register_info; -	if (!gpe_register_info) { -		status = AE_NOT_EXIST; -		goto unlock_and_exit; -	} - -	register_bit = -	    acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_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; -	} - -unlock_and_exit: -	acpi_os_release_lock(acpi_gbl_gpe_lock, flags); -	return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_gpe_wakeup) - -/******************************************************************************* - * - * FUNCTION:    acpi_enable_gpe - * - * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1 - *              gpe_number      - GPE level within the GPE block - * - * RETURN:      Status - * - * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is - *              hardware-enabled. - * - ******************************************************************************/ -acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) -{ -	acpi_status status = AE_BAD_PARAMETER; -	struct acpi_gpe_event_info *gpe_event_info; -	acpi_cpu_flags flags; - -	ACPI_FUNCTION_TRACE(acpi_enable_gpe); - -	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 = acpi_raw_enable_gpe(gpe_event_info); -	} - -	acpi_os_release_lock(acpi_gbl_gpe_lock, flags); -	return_ACPI_STATUS(status); -} -ACPI_EXPORT_SYMBOL(acpi_enable_gpe) - -/******************************************************************************* - * - * FUNCTION:    acpi_disable_gpe - * - * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1 - *              gpe_number      - GPE level within the GPE block - * - * RETURN:      Status - * - * DESCRIPTION: Remove a reference to a GPE. When the last reference is - *              removed, only then is the GPE disabled (for runtime GPEs), or - *              the GPE mask bit disabled (for wake GPEs) - * - ******************************************************************************/ -acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) -{ -	acpi_status status = AE_BAD_PARAMETER; -	struct acpi_gpe_event_info *gpe_event_info; -	acpi_cpu_flags flags; - -	ACPI_FUNCTION_TRACE(acpi_disable_gpe); - -	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 = acpi_raw_disable_gpe(gpe_event_info) ; -	} - -	acpi_os_release_lock(acpi_gbl_gpe_lock, flags); -	return_ACPI_STATUS(status); -} -ACPI_EXPORT_SYMBOL(acpi_disable_gpe) - -/******************************************************************************* - * - * FUNCTION:    acpi_gpe_can_wake - * - * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1 - *              gpe_number      - GPE level within the GPE block - * - * RETURN:      Status - * - * DESCRIPTION: Set the ACPI_GPE_CAN_WAKE flag for the given GPE.  If the GPE - *              has a corresponding method and is currently enabled, disable it - *              (GPEs with corresponding methods are enabled unconditionally - *              during initialization, but GPEs that can wake up are expected - *              to be initially disabled). - * - ******************************************************************************/ -acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number) -{ -	acpi_status status = AE_OK; -	struct acpi_gpe_event_info *gpe_event_info; -	acpi_cpu_flags flags; - -	ACPI_FUNCTION_TRACE(acpi_gpe_can_wake); - -	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) { -		gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; -	} else { -		status = AE_BAD_PARAMETER; -	} - -	acpi_os_release_lock(acpi_gbl_gpe_lock, flags); -	return_ACPI_STATUS(status); -} -ACPI_EXPORT_SYMBOL(acpi_gpe_can_wake) - -/******************************************************************************* - *   * 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   * @@ -449,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   * @@ -483,47 +311,9 @@ ACPI_EXPORT_SYMBOL(acpi_clear_event)  /*******************************************************************************   * - * FUNCTION:    acpi_clear_gpe - * - * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1 - *              gpe_number      - GPE level within the GPE block - * - * RETURN:      Status - * - * DESCRIPTION: Clear an ACPI event (general purpose) - * - ******************************************************************************/ -acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number) -{ -	acpi_status status = AE_OK; -	struct acpi_gpe_event_info *gpe_event_info; -	acpi_cpu_flags flags; - -	ACPI_FUNCTION_TRACE(acpi_clear_gpe); - -	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; -	} - -	status = acpi_hw_clear_gpe(gpe_event_info); - -      unlock_and_exit: -	acpi_os_release_lock(acpi_gbl_gpe_lock, flags); -	return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_clear_gpe) -/******************************************************************************* - *   * 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   * @@ -575,379 +365,4 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)  }  ACPI_EXPORT_SYMBOL(acpi_get_event_status) - -/******************************************************************************* - * - * FUNCTION:    acpi_get_gpe_status - * - * 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 - * - * RETURN:      Status - * - * DESCRIPTION: Get status of an event (general purpose) - * - ******************************************************************************/ -acpi_status -acpi_get_gpe_status(acpi_handle gpe_device, -		    u32 gpe_number, acpi_event_status *event_status) -{ -	acpi_status status = AE_OK; -	struct acpi_gpe_event_info *gpe_event_info; -	acpi_cpu_flags flags; - -	ACPI_FUNCTION_TRACE(acpi_get_gpe_status); - -	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; -	} - -	/* Obtain status on the requested GPE number */ - -	status = acpi_hw_get_gpe_status(gpe_event_info, event_status); - -	if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) -		*event_status |= ACPI_EVENT_FLAG_HANDLE; - -      unlock_and_exit: -	acpi_os_release_lock(acpi_gbl_gpe_lock, flags); -	return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) -/******************************************************************************* - * - * FUNCTION:    acpi_install_gpe_block - * - * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device - *              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 - * - * RETURN:      Status - * - * DESCRIPTION: Create and Install a block of GPE registers - * - ******************************************************************************/ -acpi_status -acpi_install_gpe_block(acpi_handle gpe_device, -		       struct acpi_generic_address *gpe_block_address, -		       u32 register_count, u32 interrupt_number) -{ -	acpi_status status = AE_OK; -	union acpi_operand_object *obj_desc; -	struct acpi_namespace_node *node; -	struct acpi_gpe_block_info *gpe_block; - -	ACPI_FUNCTION_TRACE(acpi_install_gpe_block); - -	if ((!gpe_device) || (!gpe_block_address) || (!register_count)) { -		return_ACPI_STATUS(AE_BAD_PARAMETER); -	} - -	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); -	if (ACPI_FAILURE(status)) { -		return (status); -	} - -	node = acpi_ns_validate_handle(gpe_device); -	if (!node) { -		status = AE_BAD_PARAMETER; -		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); -	if (ACPI_FAILURE(status)) { -		goto unlock_and_exit; -	} - -	/* Install block in the device_object attached to the node */ - -	obj_desc = acpi_ns_get_attached_object(node); -	if (!obj_desc) { - -		/* -		 * No object, create a new one (Device nodes do not always have -		 * an attached object) -		 */ -		obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE); -		if (!obj_desc) { -			status = AE_NO_MEMORY; -			goto unlock_and_exit; -		} - -		status = -		    acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE); - -		/* Remove local reference to the object */ - -		acpi_ut_remove_reference(obj_desc); - -		if (ACPI_FAILURE(status)) { -			goto unlock_and_exit; -		} -	} - -	/* Now install the GPE block in the device_object */ - -	obj_desc->device.gpe_block = gpe_block; - -      unlock_and_exit: -	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); -	return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_install_gpe_block) - -/******************************************************************************* - * - * FUNCTION:    acpi_remove_gpe_block - * - * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device - * - * RETURN:      Status - * - * DESCRIPTION: Remove a previously installed block of GPE registers - * - ******************************************************************************/ -acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) -{ -	union acpi_operand_object *obj_desc; -	acpi_status status; -	struct acpi_namespace_node *node; - -	ACPI_FUNCTION_TRACE(acpi_remove_gpe_block); - -	if (!gpe_device) { -		return_ACPI_STATUS(AE_BAD_PARAMETER); -	} - -	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); -	if (ACPI_FAILURE(status)) { -		return (status); -	} - -	node = acpi_ns_validate_handle(gpe_device); -	if (!node) { -		status = AE_BAD_PARAMETER; -		goto unlock_and_exit; -	} - -	/* Get the device_object attached to the node */ - -	obj_desc = acpi_ns_get_attached_object(node); -	if (!obj_desc || !obj_desc->device.gpe_block) { -		return_ACPI_STATUS(AE_NULL_OBJECT); -	} - -	/* Delete the GPE block (but not the device_object) */ - -	status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block); -	if (ACPI_SUCCESS(status)) { -		obj_desc->device.gpe_block = NULL; -	} - -      unlock_and_exit: -	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); -	return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block) - -/******************************************************************************* - * - * FUNCTION:    acpi_get_gpe_device - * - * PARAMETERS:  Index               - System GPE index (0-current_gpe_count) - *              gpe_device          - Where the parent GPE Device is returned - * - * RETURN:      Status - * - * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL - *              gpe device indicates that the gpe number is contained in one of - *              the FADT-defined gpe blocks. Otherwise, the GPE block device. - * - ******************************************************************************/ -acpi_status -acpi_get_gpe_device(u32 index, acpi_handle *gpe_device) -{ -	struct acpi_gpe_device_info info; -	acpi_status status; - -	ACPI_FUNCTION_TRACE(acpi_get_gpe_device); - -	if (!gpe_device) { -		return_ACPI_STATUS(AE_BAD_PARAMETER); -	} - -	if (index >= acpi_current_gpe_count) { -		return_ACPI_STATUS(AE_NOT_EXIST); -	} - -	/* Setup and walk the GPE list */ - -	info.index = index; -	info.status = AE_NOT_EXIST; -	info.gpe_device = NULL; -	info.next_block_base_index = 0; - -	status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info); -	if (ACPI_FAILURE(status)) { -		return_ACPI_STATUS(status); -	} - -	*gpe_device = info.gpe_device; -	return_ACPI_STATUS(info.status); -} - -ACPI_EXPORT_SYMBOL(acpi_get_gpe_device) - -/******************************************************************************* - * - * FUNCTION:    acpi_ev_get_gpe_device - * - * PARAMETERS:  GPE_WALK_CALLBACK - * - * RETURN:      Status - * - * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE - *              block device. NULL if the GPE is one of the FADT-defined GPEs. - * - ******************************************************************************/ -static 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_device_info *info = context; - -	/* Increment Index by the number of GPEs in this block */ - -	info->next_block_base_index += gpe_block->gpe_count; - -	if (info->index < info->next_block_base_index) { -		/* -		 * The GPE index is within this block, get the node. Leave the node -		 * NULL for the FADT-defined GPEs -		 */ -		if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) { -			info->gpe_device = gpe_block->node; -		} - -		info->status = AE_OK; -		return (AE_CTRL_END); -	} - -	return (AE_OK); -} - -/****************************************************************************** - * - * FUNCTION:    acpi_disable_all_gpes - * - * PARAMETERS:  None - * - * RETURN:      Status - * - * DESCRIPTION: Disable and clear all GPEs in all GPE blocks - * - ******************************************************************************/ - -acpi_status acpi_disable_all_gpes(void) -{ -	acpi_status status; - -	ACPI_FUNCTION_TRACE(acpi_disable_all_gpes); - -	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); -	if (ACPI_FAILURE(status)) { -		return_ACPI_STATUS(status); -	} - -	status = acpi_hw_disable_all_gpes(); -	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - -	return_ACPI_STATUS(status); -} - -/****************************************************************************** - * - * FUNCTION:    acpi_enable_all_runtime_gpes - * - * PARAMETERS:  None - * - * RETURN:      Status - * - * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks - * - ******************************************************************************/ - -acpi_status acpi_enable_all_runtime_gpes(void) -{ -	acpi_status status; - -	ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes); - -	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); -	if (ACPI_FAILURE(status)) { -		return_ACPI_STATUS(status); -	} - -	status = acpi_hw_enable_all_runtime_gpes(); -	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - -	return_ACPI_STATUS(status); -} - -/****************************************************************************** - * - * FUNCTION:    acpi_update_gpes - * - * PARAMETERS:  None - * - * RETURN:      None - * - * DESCRIPTION: Enable all GPEs that have associated _Lxx or _Exx methods and - *              are not pointed to by any device _PRW methods indicating that - *              these GPEs are generally intended for system or device wakeup - *              (such GPEs have to be enabled directly when the devices whose - *              _PRW methods point to them are set up for wakeup signaling). - * - ******************************************************************************/ - -acpi_status acpi_update_gpes(void) -{ -	acpi_status status; - -	ACPI_FUNCTION_TRACE(acpi_update_gpes); - -	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); -	if (ACPI_FAILURE(status)) { -		return_ACPI_STATUS(status); -	} else if (acpi_all_gpes_initialized) { -		goto unlock; -	} - -	status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL); -	if (ACPI_SUCCESS(status)) { -		acpi_all_gpes_initialized = TRUE; -	} - -unlock: -	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - -	return_ACPI_STATUS(status); -} +#endif				/* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c new file mode 100644 index 00000000000..cb534faf536 --- /dev/null +++ b/drivers/acpi/acpica/evxfgpe.c @@ -0,0 +1,756 @@ +/****************************************************************************** + * + * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs) + * + *****************************************************************************/ + +/* + * 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" + +#define _COMPONENT          ACPI_EVENTS +ACPI_MODULE_NAME("evxfgpe") + +#if (!ACPI_REDUCED_HARDWARE)	/* Entire module */ +/******************************************************************************* + * + * FUNCTION:    acpi_update_all_gpes + * + * PARAMETERS:  None + * + * RETURN:      Status + * + * DESCRIPTION: Complete GPE initialization and enable all GPEs that have + *              associated _Lxx or _Exx methods and are not pointed to by any + *              device _PRW methods (this indicates that these GPEs are + *              generally intended for system or device wakeup. Such GPEs + *              have to be enabled directly when the devices whose _PRW + *              methods point to them are set up for wakeup signaling.) + * + * NOTE: Should be called after any GPEs are added to the system. Primarily, + * after the system _PRW methods have been run, but also after a GPE Block + * Device has been added or if any new GPE methods have been added via a + * dynamic table load. + * + ******************************************************************************/ + +acpi_status acpi_update_all_gpes(void) +{ +	acpi_status status; + +	ACPI_FUNCTION_TRACE(acpi_update_all_gpes); + +	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); +	if (ACPI_FAILURE(status)) { +		return_ACPI_STATUS(status); +	} + +	if (acpi_gbl_all_gpes_initialized) { +		goto unlock_and_exit; +	} + +	status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL); +	if (ACPI_SUCCESS(status)) { +		acpi_gbl_all_gpes_initialized = TRUE; +	} + +unlock_and_exit: +	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + +	return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_update_all_gpes) + +/******************************************************************************* + * + * FUNCTION:    acpi_enable_gpe + * + * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1 + *              gpe_number      - GPE level within the GPE block + * + * RETURN:      Status + * + * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is + *              hardware-enabled. + * + ******************************************************************************/ + +acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) +{ +	acpi_status status = AE_BAD_PARAMETER; +	struct acpi_gpe_event_info *gpe_event_info; +	acpi_cpu_flags flags; + +	ACPI_FUNCTION_TRACE(acpi_enable_gpe); + +	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 = acpi_ev_add_gpe_reference(gpe_event_info); +	} + +	acpi_os_release_lock(acpi_gbl_gpe_lock, flags); +	return_ACPI_STATUS(status); +} +ACPI_EXPORT_SYMBOL(acpi_enable_gpe) + +/******************************************************************************* + * + * FUNCTION:    acpi_disable_gpe + * + * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1 + *              gpe_number      - GPE level within the GPE block + * + * RETURN:      Status + * + * DESCRIPTION: Remove a reference to a GPE. When the last reference is + *              removed, only then is the GPE disabled (for runtime GPEs), or + *              the GPE mask bit disabled (for wake GPEs) + * + ******************************************************************************/ + +acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) +{ +	acpi_status status = AE_BAD_PARAMETER; +	struct acpi_gpe_event_info *gpe_event_info; +	acpi_cpu_flags flags; + +	ACPI_FUNCTION_TRACE(acpi_disable_gpe); + +	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 = acpi_ev_remove_gpe_reference(gpe_event_info) ; +	} + +	acpi_os_release_lock(acpi_gbl_gpe_lock, flags); +	return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_disable_gpe) + + +/******************************************************************************* + * + * FUNCTION:    acpi_setup_gpe_for_wake + * + * PARAMETERS:  wake_device         - Device associated with the GPE (via _PRW) + *              gpe_device          - Parent GPE Device. NULL for GPE0/GPE1 + *              gpe_number          - GPE level within the GPE block + * + * RETURN:      Status + * + * DESCRIPTION: Mark a GPE as having the ability to wake the system. This + *              interface is intended to be used as the host executes the + *              _PRW methods (Power Resources for Wake) in the system tables. + *              Each _PRW appears under a Device Object (The wake_device), and + *              contains the info for the wake GPE associated with the + *              wake_device. + * + ******************************************************************************/ +acpi_status +acpi_setup_gpe_for_wake(acpi_handle wake_device, +			acpi_handle gpe_device, u32 gpe_number) +{ +	acpi_status status; +	struct acpi_gpe_event_info *gpe_event_info; +	struct acpi_namespace_node *device_node; +	struct acpi_gpe_notify_info *notify; +	struct acpi_gpe_notify_info *new_notify; +	acpi_cpu_flags flags; + +	ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake); + +	/* Parameter Validation */ + +	if (!wake_device) { +		/* +		 * By forcing wake_device to be valid, we automatically enable the +		 * implicit notify feature on all hosts. +		 */ +		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 there is no method or handler for this GPE, then the +	 * 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). +	 */ +	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 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; +		} + +		/* 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; +	} + +	/* Mark the GPE as a possible wake event */ + +	gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; +	status = AE_OK; + +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) + +/******************************************************************************* + * + * FUNCTION:    acpi_set_gpe_wake_mask + * + * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1 + *              gpe_number      - GPE level within the GPE block + *              action              - Enable or Disable + * + * RETURN:      Status + * + * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must + *              already be marked as a WAKE GPE. + * + ******************************************************************************/ + +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; +	struct acpi_gpe_register_info *gpe_register_info; +	acpi_cpu_flags flags; +	u32 register_bit; + +	ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask); + +	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + +	/* +	 * Ensure that we have a valid GPE number and that this GPE is in +	 * fact a wake GPE +	 */ +	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 (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { +		status = AE_TYPE; +		goto unlock_and_exit; +	} + +	gpe_register_info = gpe_event_info->register_info; +	if (!gpe_register_info) { +		status = AE_NOT_EXIST; +		goto unlock_and_exit; +	} + +	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; +	} + +unlock_and_exit: +	acpi_os_release_lock(acpi_gbl_gpe_lock, flags); +	return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask) + +/******************************************************************************* + * + * FUNCTION:    acpi_clear_gpe + * + * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1 + *              gpe_number      - GPE level within the GPE block + * + * RETURN:      Status + * + * DESCRIPTION: Clear an ACPI event (general purpose) + * + ******************************************************************************/ +acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number) +{ +	acpi_status status = AE_OK; +	struct acpi_gpe_event_info *gpe_event_info; +	acpi_cpu_flags flags; + +	ACPI_FUNCTION_TRACE(acpi_clear_gpe); + +	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; +	} + +	status = acpi_hw_clear_gpe(gpe_event_info); + +      unlock_and_exit: +	acpi_os_release_lock(acpi_gbl_gpe_lock, flags); +	return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_clear_gpe) + +/******************************************************************************* + * + * FUNCTION:    acpi_get_gpe_status + * + * 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 + * + * RETURN:      Status + * + * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled) + * + ******************************************************************************/ +acpi_status +acpi_get_gpe_status(acpi_handle gpe_device, +		    u32 gpe_number, acpi_event_status *event_status) +{ +	acpi_status status = AE_OK; +	struct acpi_gpe_event_info *gpe_event_info; +	acpi_cpu_flags flags; + +	ACPI_FUNCTION_TRACE(acpi_get_gpe_status); + +	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; +	} + +	/* Obtain status on the requested GPE number */ + +	status = acpi_hw_get_gpe_status(gpe_event_info, event_status); + +	if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) +		*event_status |= ACPI_EVENT_FLAG_HANDLE; + +unlock_and_exit: +	acpi_os_release_lock(acpi_gbl_gpe_lock, flags); +	return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) + +/****************************************************************************** + * + * FUNCTION:    acpi_disable_all_gpes + * + * PARAMETERS:  None + * + * RETURN:      Status + * + * DESCRIPTION: Disable and clear all GPEs in all GPE blocks + * + ******************************************************************************/ + +acpi_status acpi_disable_all_gpes(void) +{ +	acpi_status status; + +	ACPI_FUNCTION_TRACE(acpi_disable_all_gpes); + +	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); +	if (ACPI_FAILURE(status)) { +		return_ACPI_STATUS(status); +	} + +	status = acpi_hw_disable_all_gpes(); +	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + +	return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes) + +/****************************************************************************** + * + * FUNCTION:    acpi_enable_all_runtime_gpes + * + * PARAMETERS:  None + * + * RETURN:      Status + * + * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks + * + ******************************************************************************/ + +acpi_status acpi_enable_all_runtime_gpes(void) +{ +	acpi_status status; + +	ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes); + +	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); +	if (ACPI_FAILURE(status)) { +		return_ACPI_STATUS(status); +	} + +	status = acpi_hw_enable_all_runtime_gpes(); +	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + +	return_ACPI_STATUS(status); +} + +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 + *              register_count      - Number of GPE register pairs in the block + *              interrupt_number    - H/W interrupt for the block + * + * RETURN:      Status + * + * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not + *              enabled here. + * + ******************************************************************************/ +acpi_status +acpi_install_gpe_block(acpi_handle gpe_device, +		       struct acpi_generic_address *gpe_block_address, +		       u32 register_count, u32 interrupt_number) +{ +	acpi_status status; +	union acpi_operand_object *obj_desc; +	struct acpi_namespace_node *node; +	struct acpi_gpe_block_info *gpe_block; + +	ACPI_FUNCTION_TRACE(acpi_install_gpe_block); + +	if ((!gpe_device) || (!gpe_block_address) || (!register_count)) { +		return_ACPI_STATUS(AE_BAD_PARAMETER); +	} + +	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); +	if (ACPI_FAILURE(status)) { +		return_ACPI_STATUS(status); +	} + +	node = acpi_ns_validate_handle(gpe_device); +	if (!node) { +		status = AE_BAD_PARAMETER; +		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->address, +					  gpe_block_address->space_id, +					  register_count, 0, interrupt_number, +					  &gpe_block); +	if (ACPI_FAILURE(status)) { +		goto unlock_and_exit; +	} + +	/* Install block in the device_object attached to the node */ + +	obj_desc = acpi_ns_get_attached_object(node); +	if (!obj_desc) { + +		/* +		 * No object, create a new one (Device nodes do not always have +		 * an attached object) +		 */ +		obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE); +		if (!obj_desc) { +			status = AE_NO_MEMORY; +			goto unlock_and_exit; +		} + +		status = +		    acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE); + +		/* Remove local reference to the object */ + +		acpi_ut_remove_reference(obj_desc); + +		if (ACPI_FAILURE(status)) { +			goto unlock_and_exit; +		} +	} + +	/* Now install the GPE block in the device_object */ + +	obj_desc->device.gpe_block = gpe_block; + +unlock_and_exit: +	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); +	return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_install_gpe_block) + +/******************************************************************************* + * + * FUNCTION:    acpi_remove_gpe_block + * + * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device + * + * RETURN:      Status + * + * DESCRIPTION: Remove a previously installed block of GPE registers + * + ******************************************************************************/ +acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) +{ +	union acpi_operand_object *obj_desc; +	acpi_status status; +	struct acpi_namespace_node *node; + +	ACPI_FUNCTION_TRACE(acpi_remove_gpe_block); + +	if (!gpe_device) { +		return_ACPI_STATUS(AE_BAD_PARAMETER); +	} + +	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); +	if (ACPI_FAILURE(status)) { +		return_ACPI_STATUS(status); +	} + +	node = acpi_ns_validate_handle(gpe_device); +	if (!node) { +		status = AE_BAD_PARAMETER; +		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); +	if (!obj_desc || !obj_desc->device.gpe_block) { +		return_ACPI_STATUS(AE_NULL_OBJECT); +	} + +	/* Delete the GPE block (but not the device_object) */ + +	status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block); +	if (ACPI_SUCCESS(status)) { +		obj_desc->device.gpe_block = NULL; +	} + +unlock_and_exit: +	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); +	return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block) + +/******************************************************************************* + * + * FUNCTION:    acpi_get_gpe_device + * + * PARAMETERS:  index               - System GPE index (0-current_gpe_count) + *              gpe_device          - Where the parent GPE Device is returned + * + * RETURN:      Status + * + * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL + *              gpe device indicates that the gpe number is contained in one of + *              the FADT-defined gpe blocks. Otherwise, the GPE block device. + * + ******************************************************************************/ +acpi_status acpi_get_gpe_device(u32 index, acpi_handle * gpe_device) +{ +	struct acpi_gpe_device_info info; +	acpi_status status; + +	ACPI_FUNCTION_TRACE(acpi_get_gpe_device); + +	if (!gpe_device) { +		return_ACPI_STATUS(AE_BAD_PARAMETER); +	} + +	if (index >= acpi_current_gpe_count) { +		return_ACPI_STATUS(AE_NOT_EXIST); +	} + +	/* Setup and walk the GPE list */ + +	info.index = index; +	info.status = AE_NOT_EXIST; +	info.gpe_device = NULL; +	info.next_block_base_index = 0; + +	status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info); +	if (ACPI_FAILURE(status)) { +		return_ACPI_STATUS(status); +	} + +	*gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device); +	return_ACPI_STATUS(info.status); +} + +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 ce9314f7945..2d6f187939c 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -6,7 +6,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -42,6 +42,8 @@   * POSSIBILITY OF SUCH DAMAGES.   */ +#define EXPORT_ACPI_INTERFACES +  #include <acpi/acpi.h>  #include "accommon.h"  #include "acnamesp.h" @@ -54,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   * @@ -110,11 +112,43 @@ acpi_install_address_space_handler(acpi_handle device,  		goto unlock_and_exit;  	} +	/* +	 * 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 +	 * 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. +	 * This means that for IDs like embedded_controller, this function should be called +	 * only after acpi_enable_subsystem has been called. +	 */ +	switch (space_id) { +	case ACPI_ADR_SPACE_SYSTEM_MEMORY: +	case ACPI_ADR_SPACE_SYSTEM_IO: +	case ACPI_ADR_SPACE_PCI_CONFIG: +	case ACPI_ADR_SPACE_DATA_TABLE: + +		if (!acpi_gbl_reg_methods_executed) { + +			/* We will defer execution of the _REG methods for this space */ +			goto unlock_and_exit; +		} +		break; + +	default: + +		break; +	} +  	/* Run all _REG methods for this address space */  	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);  } @@ -125,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   * @@ -253,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 18832205b63..7d2949420db 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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   * @@ -297,11 +301,11 @@ acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer)  	/* Bytewise reads */  	for (i = 0; i < length; i++) { -		status = acpi_ev_address_space_dispatch(obj_desc, ACPI_READ, -							region_offset, 8, -							&value); +		status = +		    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); +		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);  	} -	/* Complete the table descriptor */ +	/* Install the new table into the local data structures */ -	table_desc.length = length; -	table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; +	ACPI_INFO((AE_INFO, "Dynamic OEM Table Load:")); +	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); -	/* Install the new table into the local data structures */ +	status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table), +						ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, +						TRUE, TRUE, &table_index); -	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 b73bc50c5b7..c545386fee9 100644 --- a/drivers/acpi/acpica/exconvrt.c +++ b/drivers/acpi/acpica/exconvrt.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 3c61b48c73f..95d23dabcfb 100644 --- a/drivers/acpi/acpica/excreate.c +++ b/drivers/acpi/acpica/excreate.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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.) @@ -267,7 +263,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)   *   * PARAMETERS:  aml_start           - Pointer to the region declaration AML   *              aml_length          - Max length of the declaration AML - *              region_space        - space_iD for the region + *              space_id            - Address space ID for the region   *              walk_state          - Current state   *   * RETURN:      Status @@ -279,7 +275,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)  acpi_status  acpi_ex_create_region(u8 * aml_start,  		      u32 aml_length, -		      u8 region_space, struct acpi_walk_state *walk_state) +		      u8 space_id, struct acpi_walk_state *walk_state)  {  	acpi_status status;  	union acpi_operand_object *obj_desc; @@ -304,15 +300,19 @@ acpi_ex_create_region(u8 * aml_start,  	 * Space ID must be one of the predefined IDs, or in the user-defined  	 * range  	 */ -	if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) && -	    (region_space < ACPI_USER_REGION_BEGIN)) { -		ACPI_ERROR((AE_INFO, "Invalid AddressSpace type 0x%X", -			    region_space)); -		return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); +	if (!acpi_is_valid_space_id(space_id)) { +		/* +		 * Print an error message, but continue. We don't want to abort +		 * a table load for this exception. Instead, if the region is +		 * actually used at runtime, abort the executing method. +		 */ +		ACPI_ERROR((AE_INFO, +			    "Invalid/unknown Address Space ID: 0x%2.2X", +			    space_id));  	}  	ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Region Type - %s (0x%X)\n", -			  acpi_ut_get_region_name(region_space), region_space)); +			  acpi_ut_get_region_name(space_id), space_id));  	/* Create the region descriptor */ @@ -329,10 +329,16 @@ acpi_ex_create_region(u8 * aml_start,  	region_obj2 = obj_desc->common.next_object;  	region_obj2->extra.aml_start = aml_start;  	region_obj2->extra.aml_length = aml_length; +	if (walk_state->scope_info) { +		region_obj2->extra.scope_node = +		    walk_state->scope_info->scope.node; +	} else { +		region_obj2->extra.scope_node = node; +	}  	/* Init the region from the operands */ -	obj_desc->region.space_id = region_space; +	obj_desc->region.space_id = space_id;  	obj_desc->region.address = 0;  	obj_desc->region.length = 0;  	obj_desc->region.node = node; @@ -341,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 */ @@ -359,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])   *   ******************************************************************************/ @@ -482,13 +488,11 @@ acpi_ex_create_method(u8 * aml_start,  	obj_desc->method.aml_length = aml_length;  	/* -	 * Disassemble the method flags. Split off the Arg Count -	 * for efficiency +	 * Disassemble the method flags. Split off the arg_count, Serialized +	 * flag, and sync_level for efficiency.  	 */  	method_flags = (u8) operand[1]->integer.value; -	obj_desc->method.method_flags = -	    (u8) (method_flags & ~AML_METHOD_ARG_COUNT);  	obj_desc->method.param_count =  	    (u8) (method_flags & AML_METHOD_ARG_COUNT); @@ -497,6 +501,8 @@ acpi_ex_create_method(u8 * aml_start,  	 * created for this method when it is parsed.  	 */  	if (method_flags & AML_METHOD_SERIALIZED) { +		obj_desc->method.info_flags = ACPI_METHOD_SERIALIZED; +  		/*  		 * ACPI 1.0: sync_level = 0  		 * ACPI 2.0: sync_level = sync_level in method declaration @@ -514,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 be8c98b480d..4cfc3d3b5c9 100644 --- a/drivers/acpi/acpica/exdebug.c +++ b/drivers/acpi/acpica/exdebug.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 f067bbb0d96..925202acc3e 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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] = { @@ -122,7 +123,7 @@ static struct acpi_exdump_info acpi_ex_dump_event[2] = {  static struct acpi_exdump_info acpi_ex_dump_method[9] = {  	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_method), NULL}, -	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.method_flags), "Method Flags"}, +	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.info_flags), "Info Flags"},  	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count),  	 "Parameter Count"},  	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.sync_level), "Sync Level"}, @@ -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"}  }; @@ -192,10 +197,13 @@ static struct acpi_exdump_info acpi_ex_dump_buffer_field[3] = {  	 "Buffer Object"}  }; -static struct acpi_exdump_info acpi_ex_dump_region_field[3] = { +static struct acpi_exdump_info acpi_ex_dump_region_field[5] = {  	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_region_field), NULL},  	{ACPI_EXD_FIELD, 0, NULL}, -	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(field.region_obj), "Region Object"} +	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(field.access_length), "AccessLength"}, +	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(field.region_obj), "Region Object"}, +	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(field.resource_buffer), +	 "ResourceBuffer"}  };  static struct acpi_exdump_info acpi_ex_dump_bank_field[5] = { @@ -222,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}  }; @@ -231,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] = { @@ -266,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 */ @@ -307,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  };  /******************************************************************************* @@ -315,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 @@ -330,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 @@ -349,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: @@ -417,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", @@ -441,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   * @@ -456,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;  	} @@ -710,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); @@ -723,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   * @@ -766,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.   * @@ -789,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   * @@ -802,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); @@ -822,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   * @@ -879,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   * @@ -923,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; @@ -934,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");  		} @@ -974,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.   * @@ -990,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;  		}  	} @@ -1004,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); @@ -1027,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 f17d2ff0031..12878e1982f 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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); @@ -100,18 +163,38 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,  		   (obj_desc->field.region_obj->region.space_id ==  		    ACPI_ADR_SPACE_SMBUS  		    || obj_desc->field.region_obj->region.space_id == +		    ACPI_ADR_SPACE_GSBUS +		    || obj_desc->field.region_obj->region.space_id ==  		    ACPI_ADR_SPACE_IPMI)) {  		/* -		 * This is an SMBus or IPMI read. We must create a buffer to hold +		 * This is an SMBus, GSBus or IPMI read. We must create a buffer to hold  		 * the data and then directly access the region handler.  		 * -		 * Note: Smbus protocol value is passed in upper 16-bits of Function +		 * Note: SMBus and GSBus protocol value is passed in upper 16-bits of Function  		 */  		if (obj_desc->field.region_obj->region.space_id ==  		    ACPI_ADR_SPACE_SMBUS) {  			length = ACPI_SMBUS_BUFFER_SIZE;  			function =  			    ACPI_READ | (obj_desc->field.attribute << 16); +		} else if (obj_desc->field.region_obj->region.space_id == +			   ACPI_ADR_SPACE_GSBUS) { +			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; @@ -142,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.  	 * @@ -190,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 { @@ -224,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); @@ -248,21 +332,23 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,  		   (obj_desc->field.region_obj->region.space_id ==  		    ACPI_ADR_SPACE_SMBUS  		    || obj_desc->field.region_obj->region.space_id == +		    ACPI_ADR_SPACE_GSBUS +		    || obj_desc->field.region_obj->region.space_id ==  		    ACPI_ADR_SPACE_IPMI)) {  		/* -		 * This is an SMBus or IPMI write. We will bypass the entire field +		 * This is an SMBus, GSBus or IPMI write. We will bypass the entire field  		 * mechanism and handoff the buffer directly to the handler. For  		 * these address spaces, the buffer is bi-directional; on a write,  		 * return data is returned in the same buffer.  		 *  		 * Source must be a buffer of sufficient size: -		 * ACPI_SMBUS_BUFFER_SIZE or ACPI_IPMI_BUFFER_SIZE. +		 * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE.  		 * -		 * Note: SMBus protocol type is passed in upper 16-bits of Function +		 * Note: SMBus and GSBus protocol type is passed in upper 16-bits of Function  		 */  		if (source_desc->common.type != ACPI_TYPE_BUFFER) {  			ACPI_ERROR((AE_INFO, -				    "SMBus or IPMI write requires Buffer, found type %s", +				    "SMBus/IPMI/GenericSerialBus write requires Buffer, found type %s",  				    acpi_ut_get_object_type_name(source_desc)));  			return_ACPI_STATUS(AE_AML_OPERAND_TYPE); @@ -273,6 +359,24 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,  			length = ACPI_SMBUS_BUFFER_SIZE;  			function =  			    ACPI_WRITE | (obj_desc->field.attribute << 16); +		} else if (obj_desc->field.region_obj->region.space_id == +			   ACPI_ADR_SPACE_GSBUS) { +			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; @@ -281,7 +385,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,  		if (source_desc->buffer.length < length) {  			ACPI_ERROR((AE_INFO, -				    "SMBus or IPMI write requires Buffer of length %u, found length %u", +				    "SMBus/IPMI/GenericSerialBus write requires Buffer of length %u, found length %u",  				    length, source_desc->buffer.length));  			return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); @@ -317,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 38293fd3e08..1d1b27a96c5 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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); @@ -86,6 +85,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,  {  	acpi_status status = AE_OK;  	union acpi_operand_object *rgn_desc; +	u8 space_id;  	ACPI_FUNCTION_TRACE_U32(ex_setup_region, field_datum_byte_offset); @@ -101,6 +101,17 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,  		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);  	} +	space_id = rgn_desc->region.space_id; + +	/* Validate the Space ID */ + +	if (!acpi_is_valid_space_id(space_id)) { +		ACPI_ERROR((AE_INFO, +			    "Invalid/unknown Address Space ID: 0x%2.2X", +			    space_id)); +		return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); +	} +  	/*  	 * If the Region Address and Length have not been previously evaluated,  	 * evaluate them now and save the results. @@ -112,18 +123,13 @@ 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 or IPMI address space, it has a non-linear +	 * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear  	 * address space and the request cannot be directly validated  	 */ -	if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS || -	    rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) { +	if (space_id == ACPI_ADR_SPACE_SMBUS || +	    space_id == ACPI_ADR_SPACE_GSBUS || +	    space_id == ACPI_ADR_SPACE_IPMI) {  		/* SMBus or IPMI has a non-linear address space */ @@ -142,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)  	 */ @@ -170,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, @@ -209,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 @@ -271,22 +277,23 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,  	/* Invoke the appropriate address_space/op_region handler */ -	status = -	    acpi_ev_address_space_dispatch(rgn_desc, function, region_offset, -					   ACPI_MUL_8(obj_desc->common_field. -						      access_byte_width), -					   value); +	status = acpi_ev_address_space_dispatch(rgn_desc, obj_desc, +						function, region_offset, +						ACPI_MUL_8(obj_desc-> +							   common_field. +							   access_byte_width), +						value);  	if (ACPI_FAILURE(status)) {  		if (status == AE_NOT_IMPLEMENTED) {  			ACPI_ERROR((AE_INFO, -				    "Region %s(0x%X) not implemented", +				    "Region %s (ID=%u) not implemented",  				    acpi_ut_get_region_name(rgn_desc->region.  							    space_id),  				    rgn_desc->region.space_id));  		} else if (status == AE_NOT_EXIST) {  			ACPI_ERROR((AE_INFO, -				    "Region %s(0x%X) has no handler", +				    "Region %s (ID=%u) has no handler",  				    acpi_ut_get_region_name(rgn_desc->region.  							    space_id),  				    rgn_desc->region.space_id)); @@ -301,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,6 +337,11 @@ acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value)  		 * The Value is larger than the maximum value that can fit into  		 * the register.  		 */ +		ACPI_ERROR((AE_INFO, +			    "Index value 0x%8.8X%8.8X overflows field width 0x%X", +			    ACPI_FORMAT_UINT64(value), +			    obj_desc->common_field.bit_length)); +  		return (TRUE);  	} @@ -345,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)   * @@ -428,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 @@ -470,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 @@ -554,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   * @@ -658,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 @@ -702,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);  	} @@ -803,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 @@ -840,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.  	 */ @@ -855,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); @@ -974,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 95db4be0877..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 - 2010, 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 6af14e43f83..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 - 2010, 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 d11e539ef76..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 - 2010, 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 84e4d185aa2..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 - 2010, 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 10e104cf0fb..2ede656ee26 100644 --- a/drivers/acpi/acpica/exoparg2.c +++ b/drivers/acpi/acpica/exoparg2.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 7a08d23befc..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 - 2010, 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 4b50730cf9a..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 - 2010, 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 7aae29f73d3..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 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -47,6 +46,7 @@  #include "acinterp.h"  #include "amlcode.h"  #include "acnamesp.h" +#include "acdispat.h"  #define _COMPONENT          ACPI_EXECUTER  ACPI_MODULE_NAME("exprep") @@ -77,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.   * @@ -253,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)); @@ -307,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.   * @@ -335,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. @@ -362,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.)  	 * @@ -390,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.   *   ******************************************************************************/ @@ -455,6 +460,30 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)  		obj_desc->field.region_obj =  		    acpi_ns_get_attached_object(info->region_node); +		/* Fields specific to generic_serial_bus fields */ + +		obj_desc->field.access_length = info->access_length; + +		if (info->connection_node) { +			second_desc = info->connection_node->object; +			if (!(second_desc->common.flags & AOPOBJ_DATA_VALID)) { +				status = +				    acpi_ds_get_buffer_arguments(second_desc); +				if (ACPI_FAILURE(status)) { +					acpi_ut_delete_object_desc(obj_desc); +					return_ACPI_STATUS(status); +				} +			} + +			obj_desc->field.resource_buffer = +			    second_desc->buffer.pointer; +			obj_desc->field.resource_length = +			    (u16)second_desc->buffer.length; +		} else if (info->resource_buffer) { +			obj_desc->field.resource_buffer = info->resource_buffer; +			obj_desc->field.resource_length = info->resource_length; +		} +  		/* Allow full data read from EC address space */  		if ((obj_desc->field.region_obj->region.space_id == @@ -574,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 de17e10da0e..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 - 2010, 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 1fa4289a687..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 - 2010, 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 7ca35ea8ace..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 - 2010, 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 8c97cfd6a0f..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 - 2010, 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 1624436ba4c..daf49f7ea31 100644 --- a/drivers/acpi/acpica/exstore.c +++ b/drivers/acpi/acpica/exstore.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 d4af684620c..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 - 2010, 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 e972b667b09..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 - 2010, 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 675aaa91a77..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 - 2010, 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 4093522eed4..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 - 2010, 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   * @@ -435,4 +378,29 @@ void acpi_ex_integer_to_string(char *out_string, u64 value)  	}  } +/******************************************************************************* + * + * FUNCTION:    acpi_is_valid_space_id + * + * PARAMETERS:  space_id            - ID to be validated + * + * RETURN:      TRUE if valid/supported ID. + * + * DESCRIPTION: Validate an operation region space_ID. + * + ******************************************************************************/ + +u8 acpi_is_valid_space_id(u8 space_id) +{ + +	if ((space_id >= ACPI_NUM_PREDEFINED_REGIONS) && +	    (space_id < ACPI_USER_REGION_BEGIN) && +	    (space_id != ACPI_ADR_SPACE_DATA_TABLE) && +	    (space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) { +		return (FALSE); +	} + +	return (TRUE); +} +  #endif diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c index b44274a0b62..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 - 2010, 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 14750db2a1b..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 - 2010, 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,20 +59,20 @@ 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:	Status + * RETURN:	Register mask with a one in the GPE bit position   * - * DESCRIPTION:	Compute GPE enable mask with one bit corresponding to the given - *		GPE set. + * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the + *              correct position for the input GPE.   *   ******************************************************************************/ -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));  }  /****************************************************************************** @@ -85,12 +84,12 @@ u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info,   *   * RETURN:	Status   * - * DESCRIPTION: Enable or disable a single GPE in its enable register. + * DESCRIPTION: Enable or disable a single GPE in the parent enable register.   *   ******************************************************************************/  acpi_status -acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action) +acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)  {  	struct acpi_gpe_register_info *gpe_register_info;  	acpi_status status; @@ -113,25 +112,33 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action)  		return (status);  	} -	/* Set ot clear just the bit that corresponds to this GPE */ +	/* 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_COND_ENABLE: -		if (!(register_bit & gpe_register_info->enable_for_run)) +	case ACPI_GPE_CONDITIONAL_ENABLE: + +		/* Only enable if the enable_for_run bit is set */ + +		if (!(register_bit & gpe_register_info->enable_for_run)) {  			return (AE_BAD_PARAMETER); +		} + +		/*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 action\n")); + +		ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u", action));  		return (AE_BAD_PARAMETER);  	} @@ -168,13 +175,12 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)  		return (AE_NOT_EXIST);  	} -	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info, -						gpe_register_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); +  	status = acpi_hw_write(register_bit,  			       &gpe_register_info->status_address); @@ -201,8 +207,8 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,  	u32 in_byte;  	u32 register_bit;  	struct acpi_gpe_register_info *gpe_register_info; -	acpi_status status;  	acpi_event_status local_event_status = 0; +	acpi_status status;  	ACPI_FUNCTION_ENTRY(); @@ -216,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?) */ @@ -338,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; @@ -473,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 ad21c7d8bf4..6aade8e1d2a 100644 --- a/drivers/acpi/acpica/hwpci.c +++ b/drivers/acpi/acpica/hwpci.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 5d1273b660a..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 - 2010, 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 @@ -269,22 +275,23 @@ acpi_status acpi_hw_clear_acpi_status(void)  	status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,  					ACPI_BITMASK_ALL_FIXED_STATUS); -	if (ACPI_FAILURE(status)) { -		goto unlock_and_exit; -	} + +	acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); + +	if (ACPI_FAILURE(status)) +		goto exit;  	/* Clear the GPE Bits in all GPE registers in all GPE blocks */  	status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL); -      unlock_and_exit: -	acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); +exit:  	return_ACPI_STATUS(status);  }  /*******************************************************************************   * - * FUNCTION:    acpi_hw_get_register_bit_mask + * FUNCTION:    acpi_hw_get_bit_register_info   *   * PARAMETERS:  register_id         - Index of ACPI Register to access   * @@ -356,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; @@ -413,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; @@ -430,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   * @@ -477,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, @@ -485,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 @@ -514,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. @@ -549,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);  } @@ -562,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)   * @@ -615,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)   * @@ -657,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 3796811276a..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 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -43,212 +43,35 @@   */  #include <acpi/acpi.h> +#include <linux/acpi.h>  #include "accommon.h" -#include "actables.h" -#include <linux/tboot.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); @@ -285,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, @@ -343,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); @@ -364,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-> @@ -374,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. @@ -524,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   * @@ -552,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 @@ -590,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 1ef8e0bb250..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 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -42,17 +41,20 @@   * POSSIBILITY OF SUCH DAMAGES.   */ +#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   * @@ -82,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)   * @@ -99,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);  } @@ -127,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:   * @@ -148,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. @@ -176,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 e1d9c777b21..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 - 2010, 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 @@ -134,7 +133,9 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)  	/* Supported widths are 8/16/32 */  	if ((bit_width != 8) && (bit_width != 16) && (bit_width != 32)) { -		return AE_BAD_PARAMETER; +		ACPI_ERROR((AE_INFO, +			    "Bad BitWidth parameter: %8.8X", bit_width)); +		return (AE_BAD_PARAMETER);  	}  	port_info = acpi_protected_ports; @@ -233,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);  	}  	/* @@ -252,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); @@ -261,7 +262,7 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width)  		address++;  	} -	return AE_OK; +	return (AE_OK);  }  /****************************************************************************** @@ -296,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);  	}  	/* @@ -316,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 50cc3be7772..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 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -42,6 +41,8 @@   * POSSIBILITY OF SUCH DAMAGES.   */ +#define EXPORT_ACPI_INTERFACES +  #include <acpi/acpi.h>  #include "accommon.h"  #include "acnamesp.h" @@ -83,11 +84,17 @@ acpi_status acpi_reset(void)  		 * 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, -				       reset_reg->bit_width); +				       ACPI_RESET_REGISTER_WIDTH);  	} else {  		/* Write the reset value to the reset register */ @@ -103,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   * @@ -112,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; @@ -137,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, @@ -198,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) @@ -207,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   * @@ -230,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), @@ -285,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 @@ -354,8 +342,8 @@ 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 - *                                position zero. The bit is automaticallly + *              value           - Value to write to the register, in bit + *                                position zero. The bit is automatically   *                                shifted to the correct position.   *   * RETURN:      Status @@ -452,7 +440,7 @@ unlock_and_exit:  }  ACPI_EXPORT_SYMBOL(acpi_write_bit_register) - +#endif				/* !ACPI_REDUCED_HARDWARE */  /*******************************************************************************   *   * FUNCTION:    acpi_get_sleep_type_data @@ -461,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); @@ -488,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;  	} @@ -507,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 0cd925be5fc..f1249e3463b 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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,21 +151,22 @@ 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  				/* Mark this as a very SPECIAL method */ -				obj_desc->method.method_flags = -				    AML_METHOD_INTERNAL_ONLY; -				obj_desc->method.extra.implementation = +				obj_desc->method.info_flags = +				    ACPI_METHOD_INTERNAL_ONLY; +				obj_desc->method.dispatch.implementation =  				    acpi_ut_osi_implementation;  #endif  				break; @@ -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 1e5ff803d9a..607eb9e5150 100644 --- a/drivers/acpi/acpica/nsalloc.c +++ b/drivers/acpi/acpica/nsalloc.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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   * @@ -234,8 +244,8 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp  			 * modified the namespace. This is used for cleanup when the  			 * method exits.  			 */ -			walk_state->method_desc->method.flags |= -			    AOPOBJ_MODIFIED_NAMESPACE; +			walk_state->method_desc->method.info_flags |= +			    ACPI_METHOD_MODIFIED_NAMESPACE;  		}  	} @@ -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.   *   ******************************************************************************/ @@ -341,6 +351,7 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node)  {  	struct acpi_namespace_node *child_node = NULL;  	u32 level = 1; +	acpi_status status;  	ACPI_FUNCTION_TRACE(ns_delete_namespace_subtree); @@ -348,6 +359,13 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node)  		return_VOID;  	} +	/* Lock namespace for possible update */ + +	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); +	if (ACPI_FAILURE(status)) { +		return_VOID; +	} +  	/*  	 * Traverse the tree of objects until we bubble back up  	 * to where we started. @@ -397,6 +415,7 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node)  		}  	} +	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);  	return_VOID;  } @@ -409,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 a54dc39e304..3d88ef4a3e0 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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. @@ -624,9 +652,22 @@ acpi_ns_dump_objects(acpi_object_type type,  		     acpi_owner_id owner_id, acpi_handle start_handle)  {  	struct acpi_walk_info info; +	acpi_status status;  	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; +	} +  	info.debug_level = ACPI_LV_TABLES;  	info.owner_id = owner_id;  	info.display_type = display_type; @@ -636,6 +677,138 @@ acpi_ns_dump_objects(acpi_object_type type,  				     ACPI_NS_WALK_TEMP_NODES,  				     acpi_ns_dump_one_object, NULL,  				     (void *)&info, NULL); + +	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); +} +#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 */ @@ -643,7 +816,7 @@ acpi_ns_dump_objects(acpi_object_type type,   *   * FUNCTION:    acpi_ns_dump_entry   * - * PARAMETERS:  Handle              - Node to be dumped + * PARAMETERS:  handle              - Node to be dumped   *              debug_level         - Output level   *   * RETURN:      None @@ -672,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 @@ -709,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 d2a97921e24..42d37109aa5 100644 --- a/drivers/acpi/acpica/nsdumpdv.c +++ b/drivers/acpi/acpica/nsdumpdv.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 f52829cc294..e634a05974d 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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. @@ -389,7 +430,7 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj,  	 * acpi_gbl_root_node->Object is NULL at PASS1.  	 */  	if ((type == ACPI_TYPE_DEVICE) && parent_node->object) { -		method_obj->method.extra.handler = +		method_obj->method.dispatch.handler =  		    parent_node->object->device.handler;  	} @@ -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 660a2728908..a3fb7e4c080 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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,35 +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: -	 */ -	acpi_nmi_disable();  	status = acpi_ns_evaluate(info); -	acpi_nmi_enable();  	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 df18be94fef..7c9d0181f34 100644 --- a/drivers/acpi/acpica/nsload.c +++ b/drivers/acpi/acpica/nsload.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 d3104af57e1..7eee0a6f02f 100644 --- a/drivers/acpi/acpica/nsnames.c +++ b/drivers/acpi/acpica/nsnames.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 41a9213dd5a..fe54a8c73b8 100644 --- a/drivers/acpi/acpica/nsobject.c +++ b/drivers/acpi/acpica/nsobject.c @@ -6,7 +6,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 5808c89e9fa..e83cff31754 100644 --- a/drivers/acpi/acpica/nsparse.c +++ b/drivers/acpi/acpica/nsparse.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 7096bcda0c7..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 - 2010, 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,56 +117,33 @@ 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; +		return (AE_OK);  	}  	/* -	 * 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. +	 * Return value validation and possible repair.  	 * -	 * 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; -	} - -	/* -	 * 1) We have a return value, but if one wasn't expected, just exit, this is -	 * not a problem. For example, if the "Implicit Return" feature is -	 * enabled, methods will always return a value. +	 * 1) Don't perform return value validation/repair if this feature +	 * has been disabled via a global option.  	 * -	 * 2) If the return value can be of any type, then we cannot perform any -	 * validation, exit. +	 * 2) We have a return value, but if one wasn't expected, just exit, +	 * this is not a problem. For example, if the "Implicit Return" +	 * feature is enabled, methods will always return a value. +	 * +	 * 3) If the return value can be of any type, then we cannot perform +	 * any validation, just exit.  	 */ -	if ((!predefined->info.expected_btypes) || +	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_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)) { @@ -227,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; +			}  		}  	} @@ -246,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:  	/* @@ -254,685 +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: - -		/* -		 * 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_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) @@ -947,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. @@ -992,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; - -	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; +	info->return_btype = acpi_ns_get_bitmapped_type(return_object); +	if (info->return_btype == ACPI_RTYPE_ANY) { -	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 @@ -1066,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   * @@ -1079,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)  { @@ -1092,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)); @@ -1102,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 d1c13669266..7e417aa5c91 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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,35 +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   * - * Optional/unnecessary NULL package elements removed + * 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 @@ -116,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_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)) { -	ACPI_FUNCTION_NAME(ns_repair_object); +			/* 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 @@ -133,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)) { @@ -152,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);  		}  	} @@ -162,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)));  	} @@ -198,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; +	const struct acpi_simple_repair_info *this_name; -	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); -		} +	/* Search info table for a repairable predefined method/object 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. -		 */ - -		/* 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); -		} - -		/* 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_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); +			return (NULL);  		} - -		/* 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); +		this_name++;  	} -	*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 @@ -530,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) @@ -554,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 { @@ -580,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);  } @@ -597,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)  { @@ -623,25 +484,25 @@ acpi_ns_remove_null_elements(struct acpi_predefined_data *data,  	ACPI_FUNCTION_NAME(ns_remove_null_elements);  	/* -	 * PTYPE1 packages contain no subpackages. -	 * PTYPE2 packages contain a variable number of sub-packages. We can -	 * safely remove all NULL elements from the PTYPE2 packages. +	 * 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 subpackages.  	 */  	switch (package_type) { -	case ACPI_PTYPE1_FIXED:  	case ACPI_PTYPE1_VAR: -	case ACPI_PTYPE1_OPTION: -		return; -  	case ACPI_PTYPE2:  	case ACPI_PTYPE2_COUNT:  	case ACPI_PTYPE2_PKG_COUNT:  	case ACPI_PTYPE2_FIXED:  	case ACPI_PTYPE2_MIN:  	case ACPI_PTYPE2_REV_FIXED: +	case ACPI_PTYPE2_FIX_VAR: +  		break;  	default: +	case ACPI_PTYPE1_FIXED: +	case ACPI_PTYPE1_OPTION:  		return;  	} @@ -668,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 */ @@ -679,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 4ef9f43ea92..b09e6bef72b 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -6,7 +6,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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,15 +568,16 @@ 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));  	}  	/* -	 * Copy and uppercase the string. From the ACPI specification: +	 * Copy and uppercase the string. From the ACPI 5.0 specification:  	 *  	 * A valid PNP ID must be of the form "AAA####" where A is an uppercase  	 * letter and # is a hex digit. A valid ACPI ID must be of the form -	 * "ACPI####" where # is a hex digit. +	 * "NNNN####" where N is an uppercase letter or decimal digit, and +	 * # is a hex digit.  	 */  	for (dest = new_string->string.pointer; *source; dest++, source++) {  		*dest = (char)ACPI_TOUPPER(*source); @@ -484,38 +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; +	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; -	status = acpi_ns_check_sorted_list(data, return_object, 5, 1, -					   ACPI_SORT_DESCENDING, -					   "PowerDissipation"); +	/* Each element in the _PRT package is a subpackage */ -	return (status); +	top_object_list = package_object->package.elements; +	element_count = package_object->package.count; + +	/* 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   * @@ -529,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; @@ -542,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)) { @@ -567,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));  		} @@ -582,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   * @@ -600,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) @@ -622,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; @@ -647,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); @@ -668,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);  		} @@ -691,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 @@ -735,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 41102a84272..af1cc42a8aa 100644 --- a/drivers/acpi/acpica/nssearch.c +++ b/drivers/acpi/acpica/nssearch.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 a7d6ad9c111..4a5e3f5c0ff 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c @@ -6,7 +6,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 2cd5be8fe10..4758a1f2ce2 100644 --- a/drivers/acpi/acpica/nswalk.c +++ b/drivers/acpi/acpica/nswalk.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 ebef8a7fd70..4bd558bf10d 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -6,7 +6,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -42,6 +42,8 @@   * POSSIBILITY OF SUCH DAMAGES.   */ +#define EXPORT_ACPI_INTERFACES +  #include <acpi/acpi.h>  #include "accommon.h"  #include "acnamesp.h" @@ -57,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)   *   ******************************************************************************/ @@ -82,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); @@ -93,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);  	} @@ -133,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;  	} @@ -151,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)   *   ******************************************************************************/ @@ -186,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); @@ -197,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; @@ -216,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], @@ -226,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. @@ -342,7 +445,7 @@ acpi_evaluate_object(acpi_handle handle,  		acpi_ex_exit_interpreter();  	} -      cleanup: +cleanup:  	/* Free the input parameter list (if we created one) */ @@ -363,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   * @@ -412,6 +515,7 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)  		break;  	default: +  		return;  	} @@ -430,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   * @@ -463,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; @@ -474,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);  	} @@ -491,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);  	}  	/* @@ -505,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);  } @@ -541,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; @@ -601,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); +			}  		}  	} @@ -645,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   * @@ -655,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.   * @@ -715,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   * @@ -751,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);  } @@ -763,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   * @@ -797,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);  } @@ -806,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; @@ -843,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 b01e45a415e..8c6c11ce976 100644 --- a/drivers/acpi/acpica/nsxfname.c +++ b/drivers/acpi/acpica/nsxfname.c @@ -6,7 +6,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -42,6 +42,8 @@   * POSSIBILITY OF SUCH DAMAGES.   */ +#define EXPORT_ACPI_INTERFACES +  #include <acpi/acpi.h>  #include "accommon.h"  #include "acnamesp.h" @@ -52,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.   *   ******************************************************************************/ @@ -106,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 '\') */ @@ -141,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.   *   ******************************************************************************/ @@ -157,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 */ @@ -201,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); @@ -218,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; @@ -246,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 @@ -255,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.   * @@ -268,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; @@ -288,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); @@ -315,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 @@ -338,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); @@ -347,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;  		}  	} @@ -369,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 */ @@ -417,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.  	 */ @@ -444,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; @@ -473,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);  	} @@ -492,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   * @@ -520,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 */ @@ -535,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 */ @@ -553,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 */ @@ -603,10 +630,9 @@ acpi_status acpi_install_method(u8 *buffer)  	method_obj->method.param_count = (u8)  	    (method_flags & AML_METHOD_ARG_COUNT); -	method_obj->method.method_flags = (u8) -	    (method_flags & ~AML_METHOD_ARG_COUNT); -  	if (method_flags & AML_METHOD_SERIALIZED) { +		method_obj->method.info_flags = ACPI_METHOD_SERIALIZED; +  		method_obj->method.sync_level = (u8)  		    ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4);  	} @@ -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 a1f04e9b803..dae9401be7a 100644 --- a/drivers/acpi/acpica/nsxfobj.c +++ b/drivers/acpi/acpica/nsxfobj.c @@ -6,7 +6,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -42,6 +42,8 @@   * POSSIBILITY OF SUCH DAMAGES.   */ +#define EXPORT_ACPI_INTERFACES +  #include <acpi/acpi.h>  #include "accommon.h"  #include "acnamesp.h" @@ -97,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 @@ -150,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 @@ -199,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); @@ -211,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.   *   ******************************************************************************/ @@ -279,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 7df1a4c9527..314d314340a 100644 --- a/drivers/acpi/acpica/psargs.c +++ b/drivers/acpi/acpica/psargs.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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   * @@ -484,34 +484,54 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,  static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state  						       *parser_state)  { -	u32 aml_offset = (u32) -	    ACPI_PTR_DIFF(parser_state->aml, -			  parser_state->aml_start); +	u32 aml_offset;  	union acpi_parse_object *field; +	union acpi_parse_object *arg = NULL;  	u16 opcode;  	u32 name; +	u8 access_type; +	u8 access_attribute; +	u8 access_length; +	u32 pkg_length; +	u8 *pkg_end; +	u32 buffer_length;  	ACPI_FUNCTION_TRACE(ps_get_next_field); +	aml_offset = +	    (u32)ACPI_PTR_DIFF(parser_state->aml, parser_state->aml_start); +  	/* Determine field type */  	switch (ACPI_GET8(parser_state->aml)) { -	default: +	case AML_FIELD_OFFSET_OP: -		opcode = AML_INT_NAMEDFIELD_OP; +		opcode = AML_INT_RESERVEDFIELD_OP; +		parser_state->aml++;  		break; -	case 0x00: +	case AML_FIELD_ACCESS_OP: -		opcode = AML_INT_RESERVEDFIELD_OP; +		opcode = AML_INT_ACCESSFIELD_OP;  		parser_state->aml++;  		break; -	case 0x01: +	case AML_FIELD_CONNECTION_OP: -		opcode = AML_INT_ACCESSFIELD_OP; +		opcode = AML_INT_CONNECTION_OP; +		parser_state->aml++; +		break; + +	case AML_FIELD_EXT_ACCESS_OP: + +		opcode = AML_INT_EXTACCESSFIELD_OP;  		parser_state->aml++;  		break; + +	default: + +		opcode = AML_INT_NAMEDFIELD_OP; +		break;  	}  	/* Allocate a new field op */ @@ -549,16 +569,117 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state  		break;  	case AML_INT_ACCESSFIELD_OP: +	case AML_INT_EXTACCESSFIELD_OP:  		/*  		 * Get access_type and access_attrib and merge into the field Op -		 * access_type is first operand, access_attribute is second +		 * access_type is first operand, access_attribute is second. stuff +		 * these bytes into the node integer value for convenience.  		 */ -		field->common.value.integer = -		    (((u32) ACPI_GET8(parser_state->aml) << 8)); + +		/* Get the two bytes (Type/Attribute) */ + +		access_type = ACPI_GET8(parser_state->aml);  		parser_state->aml++; -		field->common.value.integer |= ACPI_GET8(parser_state->aml); +		access_attribute = ACPI_GET8(parser_state->aml);  		parser_state->aml++; + +		field->common.value.integer = (u8)access_type; +		field->common.value.integer |= (u16)(access_attribute << 8); + +		/* This opcode has a third byte, access_length */ + +		if (opcode == AML_INT_EXTACCESSFIELD_OP) { +			access_length = ACPI_GET8(parser_state->aml); +			parser_state->aml++; + +			field->common.value.integer |= +			    (u32)(access_length << 16); +		} +		break; + +	case AML_INT_CONNECTION_OP: + +		/* +		 * Argument for Connection operator can be either a Buffer +		 * (resource descriptor), or a name_string. +		 */ +		if (ACPI_GET8(parser_state->aml) == AML_BUFFER_OP) { +			parser_state->aml++; + +			pkg_end = parser_state->aml; +			pkg_length = +			    acpi_ps_get_next_package_length(parser_state); +			pkg_end += pkg_length; + +			if (parser_state->aml < pkg_end) { + +				/* Non-empty list */ + +				arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP); +				if (!arg) { +					acpi_ps_free_op(field); +					return_PTR(NULL); +				} + +				/* Get the actual buffer length argument */ + +				opcode = ACPI_GET8(parser_state->aml); +				parser_state->aml++; + +				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; +				} + +				/* Fill in bytelist data */ + +				arg->named.value.size = buffer_length; +				arg->named.data = parser_state->aml; +			} + +			/* Skip to End of byte data */ + +			parser_state->aml = pkg_end; +		} else { +			arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP); +			if (!arg) { +				acpi_ps_free_op(field); +				return_PTR(NULL); +			} + +			/* Get the Namestring argument */ + +			arg->common.value.name = +			    acpi_ps_get_next_namestring(parser_state); +		} + +		/* Link the buffer/namestring to parent (CONNECTION_OP) */ + +		acpi_ps_append_arg(field, arg);  		break;  	default: @@ -681,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 2f2e7760938..b058e2390fd 100644 --- a/drivers/acpi/acpica/psloop.c +++ b/drivers/acpi/acpica/psloop.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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;  		} @@ -655,7 +355,7 @@ acpi_ps_link_module_code(union acpi_parse_object *parent_op,  		method_obj->method.aml_start = aml_start;  		method_obj->method.aml_length = aml_length;  		method_obj->method.owner_id = owner_id; -		method_obj->method.flags |= AOPOBJ_MODULE_LEVEL; +		method_obj->method.info_flags |= ACPI_METHOD_MODULE_LEVEL;  		/*  		 * Save the parent node in next_object. This is cheating, but we @@ -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 2b0c3be2b1b..1755d2ac565 100644 --- a/drivers/acpi/acpica/psopcode.c +++ b/drivers/acpi/acpica/psopcode.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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,179 +630,23 @@ 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 */  /* 7E */ ACPI_OP("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY,  		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R, -		 AML_FLAGS_EXEC_0A_0T_1R) +			 AML_FLAGS_EXEC_0A_0T_1R), -/*! [End] no source code translation !*/ -}; +/* ACPI 5.0 opcodes */ -/* - * 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 */ _UNK, _UNK, _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, -}; +/* 7F */ ACPI_OP("-ConnectField-", ARGP_CONNECTFIELD_OP, +			 ARGI_CONNECTFIELD_OP, ACPI_TYPE_ANY, +			 AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS), +/* 80 */ ACPI_OP("-ExtAccessField-", ARGP_CONNECTFIELD_OP, +			 ARGI_CONNECTFIELD_OP, ACPI_TYPE_ANY, +			 AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0) -/* - * 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, +/*! [End] no source code translation !*/  }; - -/******************************************************************************* - * - * 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 8d81542194d..6d27b597394 100644 --- a/drivers/acpi/acpica/psparse.c +++ b/drivers/acpi/acpica/psparse.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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[]   */ @@ -55,7 +55,6 @@  #include "acparser.h"  #include "acdispat.h"  #include "amlcode.h" -#include "acnamesp.h"  #include "acinterp.h"  #define _COMPONENT          ACPI_PARSER @@ -65,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)   * @@ -122,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   * @@ -177,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 @@ -193,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 @@ -299,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 */ @@ -312,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 @@ -380,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. @@ -460,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); @@ -488,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)); @@ -539,24 +538,16 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)  			/* Check for possible multi-thread reentrancy problem */  			if ((status == AE_ALREADY_EXISTS) && -			    (!walk_state->method_desc->method.mutex)) { -				ACPI_INFO((AE_INFO, -					   "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error", -					   walk_state->method_node->name. -					   ascii)); - +			    (!(walk_state->method_desc->method. +			       info_flags & ACPI_METHOD_SERIALIZED))) {  				/* -				 * Method tried to create an object twice. The probable cause is -				 * that the method cannot handle reentrancy. -				 * -				 * The method is marked not_serialized, but it tried to create -				 * a named object, causing the second thread entrance to fail. -				 * Workaround this problem by marking the method permanently -				 * as Serialized. +				 * Method is not serialized and tried to create an object +				 * twice. The probable cause is that the method cannot +				 * handle reentrancy. Mark as "pending serialized" now, and +				 * then mark "serialized" when the last thread exits.  				 */ -				walk_state->method_desc->method.method_flags |= -				    AML_METHOD_SERIALIZED; -				walk_state->method_desc->method.sync_level = 0; +				walk_state->method_desc->method.info_flags |= +				    ACPI_METHOD_SERIALIZED_PENDING;  			}  		} diff --git a/drivers/acpi/acpica/psscope.c b/drivers/acpi/acpica/psscope.c index 40e2b279ea1..32d250feea2 100644 --- a/drivers/acpi/acpica/psscope.c +++ b/drivers/acpi/acpica/psscope.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 d4b970c3630..0b64181e772 100644 --- a/drivers/acpi/acpica/pstree.c +++ b/drivers/acpi/acpica/pstree.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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   * @@ -74,6 +74,12 @@ union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn)  	ACPI_FUNCTION_ENTRY(); +/* +	if (Op->Common.aml_opcode == AML_INT_CONNECTION_OP) +	{ +		return (Op->Common.Value.Arg); +	} +*/  	/* Get the info structure for this opcode */  	op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); @@ -108,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.   * @@ -182,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.   * @@ -255,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.   * @@ -302,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 fe29eee5adb..3cd48802eed 100644 --- a/drivers/acpi/acpica/psutils.c +++ b/drivers/acpi/acpica/psutils.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 8abb9629443..9cb07e1e76d 100644 --- a/drivers/acpi/acpica/pswalk.c +++ b/drivers/acpi/acpica/pswalk.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 c42f067cff9..e135acaa5e1 100644 --- a/drivers/acpi/acpica/psxface.c +++ b/drivers/acpi/acpica/psxface.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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,6 @@  #include "acdispat.h"  #include "acinterp.h"  #include "actables.h" -#include "amlcode.h"  #define _COMPONENT          ACPI_PARSER  ACPI_MODULE_NAME("psxface") @@ -67,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   * @@ -106,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   * @@ -126,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;  	} @@ -143,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);  } @@ -151,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   * @@ -171,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;  	} @@ -186,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);  } @@ -194,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 @@ -227,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);  	} @@ -254,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 */ @@ -276,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); @@ -285,15 +282,15 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)  		goto cleanup;  	} -	if (info->obj_desc->method.flags & AOPOBJ_MODULE_LEVEL) { +	if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) {  		walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;  	}  	/* Invoke an internal method if necessary */ -	if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { +	if (info->obj_desc->method.info_flags & ACPI_METHOD_INTERNAL_ONLY) {  		status = -		    info->obj_desc->method.extra.implementation(walk_state); +		    info->obj_desc->method.dispatch.implementation(walk_state);  		info->return_object = walk_state->return_desc;  		/* Cleanup states */ @@ -326,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 */ @@ -362,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 226c806ae98..916fd095ff3 100644 --- a/drivers/acpi/acpica/rsaddr.c +++ b/drivers/acpi/acpica/rsaddr.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 d6ebf7ec622..689556744b0 100644 --- a/drivers/acpi/acpica/rscalc.c +++ b/drivers/acpi/acpica/rscalc.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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]; @@ -313,7 +324,40 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed)  							  resource_source));  			break; +		case ACPI_RESOURCE_TYPE_GPIO: + +			total_size = +			    (acpi_rs_length) (total_size + +					      (resource->data.gpio. +					       pin_table_length * 2) + +					      resource->data.gpio. +					      resource_source.string_length + +					      resource->data.gpio. +					      vendor_length); + +			break; + +		case ACPI_RESOURCE_TYPE_SERIAL_BUS: + +			total_size = +			    acpi_gbl_aml_resource_serial_bus_sizes[resource-> +								   data. +								   common_serial_bus. +								   type]; + +			total_size = (acpi_rs_length) (total_size + +						       resource->data. +						       i2c_serial_bus. +						       resource_source. +						       string_length + +						       resource->data. +						       i2c_serial_bus. +						       vendor_length); + +			break; +  		default: +  			break;  		} @@ -362,10 +406,11 @@ acpi_rs_get_list_length(u8 * aml_buffer,  	u32 extra_struct_bytes;  	u8 resource_index;  	u8 minimum_aml_resource_length; +	union aml_resource *aml_resource;  	ACPI_FUNCTION_TRACE(rs_get_list_length); -	*size_needed = 0; +	*size_needed = ACPI_RS_SIZE_MIN;	/* Minimum size is one end_tag */  	end_aml = aml_buffer + aml_buffer_length;  	/* Walk the list of AML resource descriptors */ @@ -374,11 +419,19 @@ 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 +			 * may be bogus also. +			 */  			return_ACPI_STATUS(status);  		} +		aml_resource = (void *)aml_buffer; +  		/* Get the resource length and base (minimum) AML size */  		resource_length = acpi_ut_get_resource_length(aml_buffer); @@ -418,14 +471,21 @@ 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:  			/* -			 * End Tag: -			 * This is the normal exit, add size of end_tag +			 * End Tag: This is the normal exit  			 */ -			*size_needed += ACPI_RS_SIZE_MIN;  			return_ACPI_STATUS(AE_OK);  		case ACPI_RESOURCE_NAME_ADDRESS32: @@ -457,7 +517,35 @@ acpi_rs_get_list_length(u8 * aml_buffer,  							 minimum_aml_resource_length);  			break; +		case ACPI_RESOURCE_NAME_GPIO: + +			/* Vendor data is optional */ + +			if (aml_resource->gpio.vendor_length) { +				extra_struct_bytes += +				    aml_resource->gpio.vendor_offset - +				    aml_resource->gpio.pin_table_offset + +				    aml_resource->gpio.vendor_length; +			} else { +				extra_struct_bytes += +				    aml_resource->large_header.resource_length + +				    sizeof(struct aml_resource_large_header) - +				    aml_resource->gpio.pin_table_offset; +			} +			break; + +		case ACPI_RESOURCE_NAME_SERIAL_BUS: + +			minimum_aml_resource_length = +			    acpi_gbl_resource_aml_serial_bus_sizes +			    [aml_resource->common_serial_bus.type]; +			extra_struct_bytes += +			    aml_resource->common_serial_bus.resource_length - +			    minimum_aml_resource_length; +			break; +  		default: +  			break;  		} @@ -467,9 +555,18 @@ acpi_rs_get_list_length(u8 * aml_buffer,  		 * Important: Round the size up for the appropriate alignment. This  		 * is a requirement on IA64.  		 */ -		buffer_size = acpi_gbl_resource_struct_sizes[resource_index] + -		    extra_struct_bytes; -		buffer_size = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size); +		if (acpi_ut_get_resource_type(aml_buffer) == +		    ACPI_RESOURCE_NAME_SERIAL_BUS) { +			buffer_size = +			    acpi_gbl_resource_struct_serial_bus_sizes +			    [aml_resource->common_serial_bus.type] + +			    extra_struct_bytes; +		} else { +			buffer_size = +			    acpi_gbl_resource_struct_sizes[resource_index] + +			    extra_struct_bytes; +		} +		buffer_size = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);  		*size_needed += buffer_size; @@ -528,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.  	 * @@ -539,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; @@ -560,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) || @@ -591,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 c80a2eea3a0..049d9c22a0f 100644 --- a/drivers/acpi/acpica/rscreate.c +++ b/drivers/acpi/acpica/rscreate.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -51,6 +51,74 @@ ACPI_MODULE_NAME("rscreate")  /*******************************************************************************   * + * FUNCTION:    acpi_buffer_to_resource + * + * PARAMETERS:  aml_buffer          - Pointer to the resource byte stream + *              aml_buffer_length   - Length of the aml_buffer + *              resource_ptr        - Where the converted resource is returned + * + * RETURN:      Status + * + * DESCRIPTION: Convert a raw AML buffer to a resource list + * + ******************************************************************************/ +acpi_status +acpi_buffer_to_resource(u8 *aml_buffer, +			u16 aml_buffer_length, +			struct acpi_resource **resource_ptr) +{ +	acpi_status status; +	acpi_size list_size_needed; +	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. +	 */ + +	/* Get the required length for the converted resource */ + +	status = acpi_rs_get_list_length(aml_buffer, aml_buffer_length, +					 &list_size_needed); +	if (status == AE_AML_NO_RESOURCE_END_TAG) { +		status = AE_OK; +	} +	if (ACPI_FAILURE(status)) { +		return_ACPI_STATUS(status); +	} + +	/* Allocate a buffer for the converted resource */ + +	resource = ACPI_ALLOCATE_ZEROED(list_size_needed); +	current_resource_ptr = resource; +	if (!resource) { +		return_ACPI_STATUS(AE_NO_MEMORY); +	} + +	/* Perform the AML-to-Resource conversion */ + +	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) { +		status = AE_OK; +	} +	if (ACPI_FAILURE(status)) { +		ACPI_FREE(resource); +	} else { +		*resource_ptr = resource; +	} + +	return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_buffer_to_resource) + +/******************************************************************************* + *   * FUNCTION:    acpi_rs_create_resource_list   *   * PARAMETERS:  aml_buffer          - Pointer to the resource byte stream @@ -109,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)) { @@ -125,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. @@ -134,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 @@ -208,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, @@ -229,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]  		 */ @@ -238,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, @@ -251,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, @@ -262,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  		 */ @@ -356,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, @@ -380,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; @@ -403,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);  	} @@ -430,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 f859b0386fe..c3c56b5a978 100644 --- a/drivers/acpi/acpica/rsdump.c +++ b/drivers/acpi/acpica/rsdump.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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); @@ -61,11 +62,13 @@ static void acpi_rs_out_integer64(char *title, u64 value);  static void acpi_rs_out_title(char *title); -static void acpi_rs_dump_byte_list(u16 length, u8 * data); +static void acpi_rs_dump_byte_list(u16 length, u8 *data); + +static void acpi_rs_dump_word_list(u16 length, u16 *data); -static void acpi_rs_dump_dword_list(u8 length, u32 * data); +static void acpi_rs_dump_dword_list(u8 length, u32 *data); -static void acpi_rs_dump_short_byte_list(u8 length, u8 * data); +static void acpi_rs_dump_short_byte_list(u8 length, u8 *data);  static void  acpi_rs_dump_resource_source(struct acpi_resource_source *resource_source); @@ -75,300 +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} -}; - -/* - * 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.   *   ******************************************************************************/ @@ -402,35 +121,49 @@ 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: -			acpi_rs_out_integer8(name, ACPI_GET8(target)); + +			if (table->pointer) { +				acpi_rs_out_string(name, ACPI_CAST_PTR(char, +								       table-> +								       pointer +								       [*target])); +			} else { +				acpi_rs_out_integer8(name, ACPI_GET8(target)); +			}  			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 & @@ -438,12 +171,21 @@ 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 &  								       0x03]));  			break; +		case ACPI_RSD_3BITFLAG: + +			acpi_rs_out_string(name, ACPI_CAST_PTR(char, +							       table-> +							       pointer[*target & +								       0x07])); +			break; +  		case ACPI_RSD_SHORTLIST:  			/*  			 * Short byte list (single line output) for DMA and IRQ resources @@ -456,6 +198,20 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table)  			}  			break; +		case ACPI_RSD_SHORTLISTX: +			/* +			 * Short byte list (single line output) for GPIO vendor data +			 * Note: The list length is obtained from the previous table entry +			 */ +			if (previous_target) { +				acpi_rs_out_title(name); +				acpi_rs_dump_short_byte_list(*previous_target, +							     * +							     (ACPI_CAST_INDIRECT_PTR +							      (u8, target))); +			} +			break; +  		case ACPI_RSD_LONGLIST:  			/*  			 * Long byte list for Vendor resource data @@ -480,6 +236,18 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table)  			}  			break; +		case ACPI_RSD_WORDLIST: +			/* +			 * Word list for GPIO Pin Table +			 * Note: The list length is obtained from the previous table entry +			 */ +			if (previous_target) { +				acpi_rs_dump_word_list(*previous_target, +						       *(ACPI_CAST_INDIRECT_PTR +							 (u16, target))); +			} +			break; +  		case ACPI_RSD_ADDRESS:  			/*  			 * Common flags for all Address resources @@ -493,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; @@ -542,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   * @@ -604,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;  	} @@ -625,16 +396,30 @@ 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 */ -		acpi_rs_dump_descriptor(&resource_list->data, -					acpi_gbl_dump_resource_dispatch[type]); +		if (type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { +			acpi_rs_dump_descriptor(&resource_list->data, +						acpi_gbl_dump_serial_bus_dispatch +						[resource_list->data. +						 common_serial_bus.type]); +		} else { +			acpi_rs_dump_descriptor(&resource_list->data, +						acpi_gbl_dump_resource_dispatch +						[type]); +		}  		/* Point to the next resource structure */ -		resource_list = -		    ACPI_ADD_PTR(struct acpi_resource, resource_list, -				 resource_list->length); +		resource_list = ACPI_NEXT_RESOURCE(resource_list);  		/* Exit when END_TAG descriptor is reached */ @@ -660,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;  	} @@ -683,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   * @@ -731,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   * @@ -768,4 +554,13 @@ static void acpi_rs_dump_dword_list(u8 length, u32 * data)  	}  } +static void acpi_rs_dump_word_list(u16 length, u16 *data) +{ +	u16 i; + +	for (i = 0; i < length; i++) { +		acpi_os_printf("%25s%2.2X : %4.4X\n", "Word", i, data[i]); +	} +} +  #endif 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 1fd868b964f..9d3f8a9a24b 100644 --- a/drivers/acpi/acpica/rsinfo.c +++ b/drivers/acpi/acpica/rsinfo.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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,10 @@ struct acpi_rsconvert_info *acpi_gbl_set_resource_dispatch[] = {  	acpi_rs_convert_address64,	/* 0x0D, ACPI_RESOURCE_TYPE_ADDRESS64 */  	acpi_rs_convert_ext_address64,	/* 0x0E, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */  	acpi_rs_convert_ext_irq,	/* 0x0F, ACPI_RESOURCE_TYPE_EXTENDED_IRQ */ -	acpi_rs_convert_generic_reg	/* 0x10, ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ +	acpi_rs_convert_generic_reg,	/* 0x10, ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ +	acpi_rs_convert_gpio,	/* 0x11, ACPI_RESOURCE_TYPE_GPIO */ +	acpi_rs_convert_fixed_dma,	/* 0x12, ACPI_RESOURCE_TYPE_FIXED_DMA */ +	NULL,			/* 0x13, ACPI_RESOURCE_TYPE_SERIAL_BUS - Use subtype table below */  };  /* Dispatch tables for AML-to-resource (Get Resource) conversion functions */ @@ -94,7 +97,7 @@ struct acpi_rsconvert_info *acpi_gbl_get_resource_dispatch[] = {  	acpi_rs_convert_end_dpf,	/* 0x07, ACPI_RESOURCE_NAME_END_DEPENDENT */  	acpi_rs_convert_io,	/* 0x08, ACPI_RESOURCE_NAME_IO */  	acpi_rs_convert_fixed_io,	/* 0x09, ACPI_RESOURCE_NAME_FIXED_IO */ -	NULL,			/* 0x0A, Reserved */ +	acpi_rs_convert_fixed_dma,	/* 0x0A, ACPI_RESOURCE_NAME_FIXED_DMA */  	NULL,			/* 0x0B, Reserved */  	NULL,			/* 0x0C, Reserved */  	NULL,			/* 0x0D, Reserved */ @@ -114,11 +117,22 @@ struct acpi_rsconvert_info *acpi_gbl_get_resource_dispatch[] = {  	acpi_rs_convert_address16,	/* 0x08, ACPI_RESOURCE_NAME_ADDRESS16 */  	acpi_rs_convert_ext_irq,	/* 0x09, ACPI_RESOURCE_NAME_EXTENDED_IRQ */  	acpi_rs_convert_address64,	/* 0x0A, ACPI_RESOURCE_NAME_ADDRESS64 */ -	acpi_rs_convert_ext_address64	/* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64 */ +	acpi_rs_convert_ext_address64,	/* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64 */ +	acpi_rs_convert_gpio,	/* 0x0C, ACPI_RESOURCE_NAME_GPIO */ +	NULL,			/* 0x0D, Reserved */ +	NULL,			/* 0x0E, ACPI_RESOURCE_NAME_SERIAL_BUS - Use subtype table below */ +}; + +/* Subtype table for serial_bus -- I2C, SPI, and UART */ + +struct acpi_rsconvert_info *acpi_gbl_convert_resource_serial_bus_dispatch[] = { +	NULL, +	acpi_rs_convert_i2c_serial_bus, +	acpi_rs_convert_spi_serial_bus, +	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 */ @@ -140,10 +154,19 @@ struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[] = {  	acpi_rs_dump_ext_address64,	/* ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */  	acpi_rs_dump_ext_irq,	/* ACPI_RESOURCE_TYPE_EXTENDED_IRQ */  	acpi_rs_dump_generic_reg,	/* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ +	acpi_rs_dump_gpio,	/* ACPI_RESOURCE_TYPE_GPIO */ +	acpi_rs_dump_fixed_dma,	/* ACPI_RESOURCE_TYPE_FIXED_DMA */ +	NULL,			/* ACPI_RESOURCE_TYPE_SERIAL_BUS */ +}; + +struct acpi_rsdump_info *acpi_gbl_dump_serial_bus_dispatch[] = { +	NULL, +	acpi_rs_dump_i2c_serial_bus,	/* AML_RESOURCE_I2C_BUS_TYPE */ +	acpi_rs_dump_spi_serial_bus,	/* AML_RESOURCE_SPI_BUS_TYPE */ +	acpi_rs_dump_uart_serial_bus,	/* AML_RESOURCE_UART_BUS_TYPE */  };  #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, @@ -166,7 +189,10 @@ const u8 acpi_gbl_aml_resource_sizes[] = {  	sizeof(struct aml_resource_address64),	/* ACPI_RESOURCE_TYPE_ADDRESS64 */  	sizeof(struct aml_resource_extended_address64),	/*ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */  	sizeof(struct aml_resource_extended_irq),	/* ACPI_RESOURCE_TYPE_EXTENDED_IRQ */ -	sizeof(struct aml_resource_generic_register)	/* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ +	sizeof(struct aml_resource_generic_register),	/* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ +	sizeof(struct aml_resource_gpio),	/* ACPI_RESOURCE_TYPE_GPIO */ +	sizeof(struct aml_resource_fixed_dma),	/* ACPI_RESOURCE_TYPE_FIXED_DMA */ +	sizeof(struct aml_resource_common_serialbus),	/* ACPI_RESOURCE_TYPE_SERIAL_BUS */  };  const u8 acpi_gbl_resource_struct_sizes[] = { @@ -182,7 +208,7 @@ const u8 acpi_gbl_resource_struct_sizes[] = {  	ACPI_RS_SIZE_MIN,  	ACPI_RS_SIZE(struct acpi_resource_io),  	ACPI_RS_SIZE(struct acpi_resource_fixed_io), -	0, +	ACPI_RS_SIZE(struct acpi_resource_fixed_dma),  	0,  	0,  	0, @@ -202,5 +228,21 @@ const u8 acpi_gbl_resource_struct_sizes[] = {  	ACPI_RS_SIZE(struct acpi_resource_address16),  	ACPI_RS_SIZE(struct acpi_resource_extended_irq),  	ACPI_RS_SIZE(struct acpi_resource_address64), -	ACPI_RS_SIZE(struct acpi_resource_extended_address64) +	ACPI_RS_SIZE(struct acpi_resource_extended_address64), +	ACPI_RS_SIZE(struct acpi_resource_gpio), +	ACPI_RS_SIZE(struct acpi_resource_common_serialbus) +}; + +const u8 acpi_gbl_aml_resource_serial_bus_sizes[] = { +	0, +	sizeof(struct aml_resource_i2c_serialbus), +	sizeof(struct aml_resource_spi_serialbus), +	sizeof(struct aml_resource_uart_serialbus), +}; + +const u8 acpi_gbl_resource_struct_serial_bus_sizes[] = { +	0, +	ACPI_RS_SIZE(struct acpi_resource_i2c_serialbus), +	ACPI_RS_SIZE(struct acpi_resource_spi_serialbus), +	ACPI_RS_SIZE(struct acpi_resource_uart_serialbus),  }; diff --git a/drivers/acpi/acpica/rsio.c b/drivers/acpi/acpica/rsio.c index 33bff17c0bb..19d64873290 100644 --- a/drivers/acpi/acpica/rsio.c +++ b/drivers/acpi/acpica/rsio.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 545da40d7fa..3461f7db26d 100644 --- a/drivers/acpi/acpica/rsirq.c +++ b/drivers/acpi/acpica/rsirq.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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) */ @@ -264,3 +276,32 @@ struct acpi_rsconvert_info acpi_rs_convert_dma[6] = {  	 AML_OFFSET(dma.dma_channel_mask),  	 ACPI_RS_OFFSET(data.dma.channel_count)}  }; + +/******************************************************************************* + * + * acpi_rs_convert_fixed_dma + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_convert_fixed_dma[4] = { +	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_FIXED_DMA, +	 ACPI_RS_SIZE(struct acpi_resource_fixed_dma), +	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_fixed_dma)}, + +	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_FIXED_DMA, +	 sizeof(struct aml_resource_fixed_dma), +	 0}, + +	/* +	 * These fields are contiguous in both the source and destination: +	 * request_lines +	 * Channels +	 */ +	{ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.fixed_dma.request_lines), +	 AML_OFFSET(fixed_dma.request_lines), +	 2}, + +	{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 7335f22aac2..77291293af6 100644 --- a/drivers/acpi/acpica/rslist.c +++ b/drivers/acpi/acpica/rslist.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -70,6 +70,8 @@ acpi_rs_convert_aml_to_resources(u8 * aml,  	struct acpi_resource **resource_ptr =  	    ACPI_CAST_INDIRECT_PTR(struct acpi_resource, context);  	struct acpi_resource *resource; +	union aml_resource *aml_resource; +	struct acpi_rsconvert_info *conversion_table;  	acpi_status status;  	ACPI_FUNCTION_TRACE(rs_convert_aml_to_resources); @@ -84,14 +86,37 @@ acpi_rs_convert_aml_to_resources(u8 * aml,  			      "Misaligned resource pointer %p", resource));  	} +	/* Get the appropriate conversion info table */ + +	aml_resource = ACPI_CAST_PTR(union aml_resource, aml); +	if (acpi_ut_get_resource_type(aml) == ACPI_RESOURCE_NAME_SERIAL_BUS) { +		if (aml_resource->common_serial_bus.type > +		    AML_RESOURCE_MAX_SERIALBUSTYPE) { +			conversion_table = NULL; +		} else { +			/* This is an I2C, SPI, or UART serial_bus descriptor */ + +			conversion_table = +			    acpi_gbl_convert_resource_serial_bus_dispatch +			    [aml_resource->common_serial_bus.type]; +		} +	} else { +		conversion_table = +		    acpi_gbl_get_resource_dispatch[resource_index]; +	} + +	if (!conversion_table) { +		ACPI_ERROR((AE_INFO, +			    "Invalid/unsupported resource descriptor: Type 0x%2.2X", +			    resource_index)); +		return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); +	} +  	/* Convert the AML byte stream resource to a local resource struct */  	status = -	    acpi_rs_convert_aml_to_resource(resource, -					    ACPI_CAST_PTR(union aml_resource, -							  aml), -					    acpi_gbl_get_resource_dispatch -					    [resource_index]); +	    acpi_rs_convert_aml_to_resource(resource, aml_resource, +					    conversion_table);  	if (ACPI_FAILURE(status)) {  		ACPI_EXCEPTION((AE_INFO, status,  				"Could not convert AML resource (Type 0x%X)", @@ -106,7 +131,7 @@ acpi_rs_convert_aml_to_resources(u8 * aml,  	/* Point to the next structure in the output buffer */ -	*resource_ptr = ACPI_ADD_PTR(void, resource, resource->length); +	*resource_ptr = ACPI_NEXT_RESOURCE(resource);  	return_ACPI_STATUS(AE_OK);  } @@ -114,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 @@ -135,6 +160,7 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,  {  	u8 *aml = output_buffer;  	u8 *end_aml = output_buffer + aml_size_needed; +	struct acpi_rsconvert_info *conversion_table;  	acpi_status status;  	ACPI_FUNCTION_TRACE(rs_convert_resources_to_aml); @@ -152,13 +178,44 @@ 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 */ -		status = acpi_rs_convert_resource_to_aml(resource, ACPI_CAST_PTR(union -										 aml_resource, -										 aml), -							 acpi_gbl_set_resource_dispatch -							 [resource->type]); +		if (resource->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { +			if (resource->data.common_serial_bus.type > +			    AML_RESOURCE_MAX_SERIALBUSTYPE) { +				conversion_table = NULL; +			} else { +				/* This is an I2C, SPI, or UART serial_bus descriptor */ + +				conversion_table = +				    acpi_gbl_convert_resource_serial_bus_dispatch +				    [resource->data.common_serial_bus.type]; +			} +		} else { +			conversion_table = +			    acpi_gbl_set_resource_dispatch[resource->type]; +		} + +		if (!conversion_table) { +			ACPI_ERROR((AE_INFO, +				    "Invalid/unsupported resource descriptor: Type 0x%2.2X", +				    resource->type)); +			return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); +		} + +		status = acpi_rs_convert_resource_to_aml(resource, +						         ACPI_CAST_PTR(union +								       aml_resource, +								       aml), +							 conversion_table);  		if (ACPI_FAILURE(status)) {  			ACPI_EXCEPTION((AE_INFO, status,  					"Could not convert resource (type 0x%X) to AML", @@ -168,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);  		} @@ -192,9 +250,7 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,  		/* Point to the next input resource descriptor */ -		resource = -		    ACPI_ADD_PTR(struct acpi_resource, resource, -				 resource->length); +		resource = ACPI_NEXT_RESOURCE(resource);  	}  	/* Completed buffer, but did not find an end_tag resource descriptor */ diff --git a/drivers/acpi/acpica/rsmemory.c b/drivers/acpi/acpica/rsmemory.c index 887b8ba8c43..eab4483ff5f 100644 --- a/drivers/acpi/acpica/rsmemory.c +++ b/drivers/acpi/acpica/rsmemory.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 f8cd9e87d98..41eea4bc089 100644 --- a/drivers/acpi/acpica/rsmisc.c +++ b/drivers/acpi/acpica/rsmisc.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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   * @@ -83,6 +83,10 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,  	ACPI_FUNCTION_TRACE(rs_convert_aml_to_resource); +	if (!info) { +		return_ACPI_STATUS(AE_BAD_PARAMETER); +	} +  	if (((acpi_size) resource) & 0x3) {  		/* Each internal resource struct is expected to be 32-bit aligned */ @@ -101,7 +105,6 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,  	 * table length (# of table entries)  	 */  	count = INIT_TABLE_LENGTH(info); -  	while (count) {  		/*  		 * Source is the external AML byte stream buffer, @@ -133,22 +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, +				  ((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)); @@ -157,12 +168,74 @@ 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));  			break; +		case ACPI_RSC_COUNT_GPIO_PIN: + +			target = ACPI_ADD_PTR(void, aml, info->value); +			item_count = ACPI_GET16(target) - ACPI_GET16(source); + +			resource->length = resource->length + item_count; +			item_count = item_count / 2; +			ACPI_SET16(destination, item_count); +			break; + +		case ACPI_RSC_COUNT_GPIO_VEN: + +			item_count = ACPI_GET8(source); +			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 +			 */ +			target = ACPI_ADD_PTR(void, aml, (info->value + 2)); +			if (ACPI_GET16(target)) { + +				/* Use vendor offset to get resource source length */ + +				target = ACPI_ADD_PTR(void, aml, info->value); +				item_count = +				    ACPI_GET16(target) - ACPI_GET16(source); +			} else { +				/* No vendor data to worry about */ + +				item_count = aml->large_header.resource_length + +				    sizeof(struct aml_resource_large_header) - +				    ACPI_GET16(source); +			} + +			resource->length = resource->length + item_count; +			ACPI_SET16(destination, item_count); +			break; + +		case ACPI_RSC_COUNT_SERIAL_VEN: + +			item_count = ACPI_GET16(source) - info->value; + +			resource->length = resource->length + item_count; +			ACPI_SET16(destination, item_count); +			break; + +		case ACPI_RSC_COUNT_SERIAL_RES: + +			item_count = (aml_resource_length + +				      sizeof(struct aml_resource_large_header)) +			    - ACPI_GET16(source) - info->value; + +			resource->length = resource->length + item_count; +			ACPI_SET16(destination, item_count); +			break; +  		case ACPI_RSC_LENGTH:  			resource->length = resource->length + info->value; @@ -183,6 +256,72 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,  					  info->opcode);  			break; +		case ACPI_RSC_MOVE_GPIO_PIN: + +			/* Generate and set the PIN data pointer */ + +			target = (char *)ACPI_ADD_PTR(void, resource, +						      (resource->length - +						       item_count * 2)); +			*(u16 **)destination = ACPI_CAST_PTR(u16, target); + +			/* Copy the PIN data */ + +			source = ACPI_ADD_PTR(void, aml, ACPI_GET16(source)); +			acpi_rs_move_data(target, source, item_count, +					  info->opcode); +			break; + +		case ACPI_RSC_MOVE_GPIO_RES: + +			/* Generate and set the resource_source string pointer */ + +			target = (char *)ACPI_ADD_PTR(void, resource, +						      (resource->length - +						       item_count)); +			*(u8 **)destination = ACPI_CAST_PTR(u8, target); + +			/* Copy the resource_source string */ + +			source = ACPI_ADD_PTR(void, aml, ACPI_GET16(source)); +			acpi_rs_move_data(target, source, item_count, +					  info->opcode); +			break; + +		case ACPI_RSC_MOVE_SERIAL_VEN: + +			/* Generate and set the Vendor Data pointer */ + +			target = (char *)ACPI_ADD_PTR(void, resource, +						      (resource->length - +						       item_count)); +			*(u8 **)destination = ACPI_CAST_PTR(u8, target); + +			/* Copy the Vendor Data */ + +			source = ACPI_ADD_PTR(void, aml, info->value); +			acpi_rs_move_data(target, source, item_count, +					  info->opcode); +			break; + +		case ACPI_RSC_MOVE_SERIAL_RES: + +			/* Generate and set the resource_source string pointer */ + +			target = (char *)ACPI_ADD_PTR(void, resource, +						      (resource->length - +						       item_count)); +			*(u8 **)destination = ACPI_CAST_PTR(u8, target); + +			/* Copy the resource_source string */ + +			source = +			    ACPI_ADD_PTR(void, aml, +					 (ACPI_GET16(source) + info->value)); +			acpi_rs_move_data(target, source, item_count, +					  info->opcode); +			break; +  		case ACPI_RSC_SET8:  			ACPI_MEMSET(destination, info->aml_offset, info->value); @@ -219,13 +358,18 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,  			 * Optional resource_source (Index and String). This is the more  			 * complicated case used by the Interrupt() macro  			 */ -			target = -			    ACPI_ADD_PTR(char, resource, -					 info->aml_offset + (item_count * 4)); +			target = ACPI_ADD_PTR(char, resource, +					      info->aml_offset + +					      (item_count * 4));  			resource->length +=  			    acpi_rs_get_resource_source(aml_resource_length, -							(acpi_rs_length) (((item_count - 1) * sizeof(u32)) + info->value), destination, aml, target); +							(acpi_rs_length) +							(((item_count - +							   1) * sizeof(u32)) + +							 info->value), +							destination, aml, +							target);  			break;  		case ACPI_RSC_BITMASK: @@ -240,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: @@ -256,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;  				} @@ -294,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) */ @@ -309,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   * @@ -327,6 +473,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,  {  	void *source = NULL;  	void *destination; +	char *target;  	acpi_rsdesc_size aml_length = 0;  	u8 count;  	u16 temp16 = 0; @@ -334,6 +481,10 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,  	ACPI_FUNCTION_TRACE(rs_convert_resource_to_aml); +	if (!info) { +		return_ACPI_STATUS(AE_BAD_PARAMETER); +	} +  	/*  	 * First table entry must be ACPI_RSC_INITxxx and must contain the  	 * table length (# of table entries) @@ -364,29 +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_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 + @@ -400,6 +562,63 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,  			acpi_rs_set_resource_length(aml_length, aml);  			break; +		case ACPI_RSC_COUNT_GPIO_PIN: + +			item_count = ACPI_GET16(source); +			ACPI_SET16(destination, aml_length); + +			aml_length = (u16)(aml_length + item_count * 2); +			target = ACPI_ADD_PTR(void, aml, info->value); +			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, item_count); + +			aml_length = +			    (u16)(aml_length + (info->value * item_count)); +			acpi_rs_set_resource_length(aml_length, aml); +			break; + +		case ACPI_RSC_COUNT_GPIO_RES: + +			/* Set resource source string length */ + +			item_count = ACPI_GET16(source); +			ACPI_SET16(destination, aml_length); + +			/* Compute offset for the Vendor Data */ + +			aml_length = (u16)(aml_length + item_count); +			target = ACPI_ADD_PTR(void, aml, info->value); + +			/* Set vendor offset only if there is vendor data */ + +			if (resource->data.gpio.vendor_length) { +				ACPI_SET16(target, aml_length); +			} + +			acpi_rs_set_resource_length(aml_length, aml); +			break; + +		case ACPI_RSC_COUNT_SERIAL_VEN: + +			item_count = ACPI_GET16(source); +			ACPI_SET16(destination, item_count + info->value); +			aml_length = (u16)(aml_length + item_count); +			acpi_rs_set_resource_length(aml_length, aml); +			break; + +		case ACPI_RSC_COUNT_SERIAL_RES: + +			item_count = ACPI_GET16(source); +			aml_length = (u16)(aml_length + item_count); +			acpi_rs_set_resource_length(aml_length, aml); +			break; +  		case ACPI_RSC_LENGTH:  			acpi_rs_set_resource_length(info->value, aml); @@ -417,6 +636,48 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,  					  info->opcode);  			break; +		case ACPI_RSC_MOVE_GPIO_PIN: + +			destination = (char *)ACPI_ADD_PTR(void, aml, +							   ACPI_GET16 +							   (destination)); +			source = *(u16 **)source; +			acpi_rs_move_data(destination, source, item_count, +					  info->opcode); +			break; + +		case ACPI_RSC_MOVE_GPIO_RES: + +			/* Used for both resource_source string and vendor_data */ + +			destination = (char *)ACPI_ADD_PTR(void, aml, +							   ACPI_GET16 +							   (destination)); +			source = *(u8 **)source; +			acpi_rs_move_data(destination, source, item_count, +					  info->opcode); +			break; + +		case ACPI_RSC_MOVE_SERIAL_VEN: + +			destination = (char *)ACPI_ADD_PTR(void, aml, +							   (aml_length - +							    item_count)); +			source = *(u8 **)source; +			acpi_rs_move_data(destination, source, item_count, +					  info->opcode); +			break; + +		case ACPI_RSC_MOVE_SERIAL_RES: + +			destination = (char *)ACPI_ADD_PTR(void, aml, +							   (aml_length - +							    item_count)); +			source = *(u8 **)source; +			acpi_rs_move_data(destination, source, item_count, +					  info->opcode); +			break; +  		case ACPI_RSC_ADDRESS:  			/* Set the Resource Type, General Flags, and Type-Specific Flags */ @@ -429,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; @@ -449,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: @@ -469,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; @@ -478,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: @@ -500,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)) == @@ -519,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 new file mode 100644 index 00000000000..9e8407223d9 --- /dev/null +++ b/drivers/acpi/acpica/rsserial.c @@ -0,0 +1,445 @@ +/******************************************************************************* + * + * Module Name: rsserial - GPIO/serial_bus 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("rsserial") + +/******************************************************************************* + * + * acpi_rs_convert_gpio + * + ******************************************************************************/ +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)}, + +	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_GPIO, +	 sizeof(struct aml_resource_gpio), +	 0}, + +	/* +	 * These fields are contiguous in both the source and destination: +	 * revision_id +	 * connection_type +	 */ +	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.gpio.revision_id), +	 AML_OFFSET(gpio.revision_id), +	 2}, + +	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.gpio.producer_consumer), +	 AML_OFFSET(gpio.flags), +	 0}, + +	{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}, + +	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.gpio.triggering), +	 AML_OFFSET(gpio.int_flags), +	 0}, + +	{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.gpio.polarity), +	 AML_OFFSET(gpio.int_flags), +	 1}, + +	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.gpio.pin_config), +	 AML_OFFSET(gpio.pin_config), +	 1}, + +	/* +	 * These fields are contiguous in both the source and destination: +	 * drive_strength +	 * debounce_timeout +	 */ +	{ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.gpio.drive_strength), +	 AML_OFFSET(gpio.drive_strength), +	 2}, + +	/* Pin Table */ + +	{ACPI_RSC_COUNT_GPIO_PIN, ACPI_RS_OFFSET(data.gpio.pin_table_length), +	 AML_OFFSET(gpio.pin_table_offset), +	 AML_OFFSET(gpio.res_source_offset)}, + +	{ACPI_RSC_MOVE_GPIO_PIN, ACPI_RS_OFFSET(data.gpio.pin_table), +	 AML_OFFSET(gpio.pin_table_offset), +	 0}, + +	/* Resource Source */ + +	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.gpio.resource_source.index), +	 AML_OFFSET(gpio.res_source_index), +	 1}, + +	{ACPI_RSC_COUNT_GPIO_RES, +	 ACPI_RS_OFFSET(data.gpio.resource_source.string_length), +	 AML_OFFSET(gpio.res_source_offset), +	 AML_OFFSET(gpio.vendor_offset)}, + +	{ACPI_RSC_MOVE_GPIO_RES, +	 ACPI_RS_OFFSET(data.gpio.resource_source.string_ptr), +	 AML_OFFSET(gpio.res_source_offset), +	 0}, + +	/* Vendor Data */ + +	{ACPI_RSC_COUNT_GPIO_VEN, ACPI_RS_OFFSET(data.gpio.vendor_length), +	 AML_OFFSET(gpio.vendor_length), +	 1}, + +	{ACPI_RSC_MOVE_GPIO_RES, ACPI_RS_OFFSET(data.gpio.vendor_data), +	 AML_OFFSET(gpio.vendor_offset), +	 0}, +}; + +/******************************************************************************* + * + * acpi_rs_convert_i2c_serial_bus + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_convert_i2c_serial_bus[16] = { +	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS, +	 ACPI_RS_SIZE(struct acpi_resource_i2c_serialbus), +	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_i2c_serial_bus)}, + +	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_SERIAL_BUS, +	 sizeof(struct aml_resource_i2c_serialbus), +	 0}, + +	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.common_serial_bus.revision_id), +	 AML_OFFSET(common_serial_bus.revision_id), +	 1}, + +	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.common_serial_bus.type), +	 AML_OFFSET(common_serial_bus.type), +	 1}, + +	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.common_serial_bus.slave_mode), +	 AML_OFFSET(common_serial_bus.flags), +	 0}, + +	{ACPI_RSC_1BITFLAG, +	 ACPI_RS_OFFSET(data.common_serial_bus.producer_consumer), +	 AML_OFFSET(common_serial_bus.flags), +	 1}, + +	{ACPI_RSC_MOVE8, +	 ACPI_RS_OFFSET(data.common_serial_bus.type_revision_id), +	 AML_OFFSET(common_serial_bus.type_revision_id), +	 1}, + +	{ACPI_RSC_MOVE16, +	 ACPI_RS_OFFSET(data.common_serial_bus.type_data_length), +	 AML_OFFSET(common_serial_bus.type_data_length), +	 1}, + +	/* Vendor data */ + +	{ACPI_RSC_COUNT_SERIAL_VEN, +	 ACPI_RS_OFFSET(data.common_serial_bus.vendor_length), +	 AML_OFFSET(common_serial_bus.type_data_length), +	 AML_RESOURCE_I2C_MIN_DATA_LEN}, + +	{ACPI_RSC_MOVE_SERIAL_VEN, +	 ACPI_RS_OFFSET(data.common_serial_bus.vendor_data), +	 0, +	 sizeof(struct aml_resource_i2c_serialbus)}, + +	/* Resource Source */ + +	{ACPI_RSC_MOVE8, +	 ACPI_RS_OFFSET(data.common_serial_bus.resource_source.index), +	 AML_OFFSET(common_serial_bus.res_source_index), +	 1}, + +	{ACPI_RSC_COUNT_SERIAL_RES, +	 ACPI_RS_OFFSET(data.common_serial_bus.resource_source.string_length), +	 AML_OFFSET(common_serial_bus.type_data_length), +	 sizeof(struct aml_resource_common_serialbus)}, + +	{ACPI_RSC_MOVE_SERIAL_RES, +	 ACPI_RS_OFFSET(data.common_serial_bus.resource_source.string_ptr), +	 AML_OFFSET(common_serial_bus.type_data_length), +	 sizeof(struct aml_resource_common_serialbus)}, + +	/* I2C bus type specific */ + +	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.i2c_serial_bus.access_mode), +	 AML_OFFSET(i2c_serial_bus.type_specific_flags), +	 0}, + +	{ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.i2c_serial_bus.connection_speed), +	 AML_OFFSET(i2c_serial_bus.connection_speed), +	 1}, + +	{ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.i2c_serial_bus.slave_address), +	 AML_OFFSET(i2c_serial_bus.slave_address), +	 1}, +}; + +/******************************************************************************* + * + * acpi_rs_convert_spi_serial_bus + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_convert_spi_serial_bus[20] = { +	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS, +	 ACPI_RS_SIZE(struct acpi_resource_spi_serialbus), +	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_spi_serial_bus)}, + +	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_SERIAL_BUS, +	 sizeof(struct aml_resource_spi_serialbus), +	 0}, + +	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.common_serial_bus.revision_id), +	 AML_OFFSET(common_serial_bus.revision_id), +	 1}, + +	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.common_serial_bus.type), +	 AML_OFFSET(common_serial_bus.type), +	 1}, + +	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.common_serial_bus.slave_mode), +	 AML_OFFSET(common_serial_bus.flags), +	 0}, + +	{ACPI_RSC_1BITFLAG, +	 ACPI_RS_OFFSET(data.common_serial_bus.producer_consumer), +	 AML_OFFSET(common_serial_bus.flags), +	 1}, + +	{ACPI_RSC_MOVE8, +	 ACPI_RS_OFFSET(data.common_serial_bus.type_revision_id), +	 AML_OFFSET(common_serial_bus.type_revision_id), +	 1}, + +	{ACPI_RSC_MOVE16, +	 ACPI_RS_OFFSET(data.common_serial_bus.type_data_length), +	 AML_OFFSET(common_serial_bus.type_data_length), +	 1}, + +	/* Vendor data */ + +	{ACPI_RSC_COUNT_SERIAL_VEN, +	 ACPI_RS_OFFSET(data.common_serial_bus.vendor_length), +	 AML_OFFSET(common_serial_bus.type_data_length), +	 AML_RESOURCE_SPI_MIN_DATA_LEN}, + +	{ACPI_RSC_MOVE_SERIAL_VEN, +	 ACPI_RS_OFFSET(data.common_serial_bus.vendor_data), +	 0, +	 sizeof(struct aml_resource_spi_serialbus)}, + +	/* Resource Source */ + +	{ACPI_RSC_MOVE8, +	 ACPI_RS_OFFSET(data.common_serial_bus.resource_source.index), +	 AML_OFFSET(common_serial_bus.res_source_index), +	 1}, + +	{ACPI_RSC_COUNT_SERIAL_RES, +	 ACPI_RS_OFFSET(data.common_serial_bus.resource_source.string_length), +	 AML_OFFSET(common_serial_bus.type_data_length), +	 sizeof(struct aml_resource_common_serialbus)}, + +	{ACPI_RSC_MOVE_SERIAL_RES, +	 ACPI_RS_OFFSET(data.common_serial_bus.resource_source.string_ptr), +	 AML_OFFSET(common_serial_bus.type_data_length), +	 sizeof(struct aml_resource_common_serialbus)}, + +	/* Spi bus type specific  */ + +	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.spi_serial_bus.wire_mode), +	 AML_OFFSET(spi_serial_bus.type_specific_flags), +	 0}, + +	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.spi_serial_bus.device_polarity), +	 AML_OFFSET(spi_serial_bus.type_specific_flags), +	 1}, + +	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.spi_serial_bus.data_bit_length), +	 AML_OFFSET(spi_serial_bus.data_bit_length), +	 1}, + +	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.spi_serial_bus.clock_phase), +	 AML_OFFSET(spi_serial_bus.clock_phase), +	 1}, + +	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.spi_serial_bus.clock_polarity), +	 AML_OFFSET(spi_serial_bus.clock_polarity), +	 1}, + +	{ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.spi_serial_bus.device_selection), +	 AML_OFFSET(spi_serial_bus.device_selection), +	 1}, + +	{ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.spi_serial_bus.connection_speed), +	 AML_OFFSET(spi_serial_bus.connection_speed), +	 1}, +}; + +/******************************************************************************* + * + * acpi_rs_convert_uart_serial_bus + * + ******************************************************************************/ + +struct acpi_rsconvert_info acpi_rs_convert_uart_serial_bus[22] = { +	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS, +	 ACPI_RS_SIZE(struct acpi_resource_uart_serialbus), +	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_uart_serial_bus)}, + +	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_SERIAL_BUS, +	 sizeof(struct aml_resource_uart_serialbus), +	 0}, + +	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.common_serial_bus.revision_id), +	 AML_OFFSET(common_serial_bus.revision_id), +	 1}, + +	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.common_serial_bus.type), +	 AML_OFFSET(common_serial_bus.type), +	 1}, + +	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.common_serial_bus.slave_mode), +	 AML_OFFSET(common_serial_bus.flags), +	 0}, + +	{ACPI_RSC_1BITFLAG, +	 ACPI_RS_OFFSET(data.common_serial_bus.producer_consumer), +	 AML_OFFSET(common_serial_bus.flags), +	 1}, + +	{ACPI_RSC_MOVE8, +	 ACPI_RS_OFFSET(data.common_serial_bus.type_revision_id), +	 AML_OFFSET(common_serial_bus.type_revision_id), +	 1}, + +	{ACPI_RSC_MOVE16, +	 ACPI_RS_OFFSET(data.common_serial_bus.type_data_length), +	 AML_OFFSET(common_serial_bus.type_data_length), +	 1}, + +	/* Vendor data */ + +	{ACPI_RSC_COUNT_SERIAL_VEN, +	 ACPI_RS_OFFSET(data.common_serial_bus.vendor_length), +	 AML_OFFSET(common_serial_bus.type_data_length), +	 AML_RESOURCE_UART_MIN_DATA_LEN}, + +	{ACPI_RSC_MOVE_SERIAL_VEN, +	 ACPI_RS_OFFSET(data.common_serial_bus.vendor_data), +	 0, +	 sizeof(struct aml_resource_uart_serialbus)}, + +	/* Resource Source */ + +	{ACPI_RSC_MOVE8, +	 ACPI_RS_OFFSET(data.common_serial_bus.resource_source.index), +	 AML_OFFSET(common_serial_bus.res_source_index), +	 1}, + +	{ACPI_RSC_COUNT_SERIAL_RES, +	 ACPI_RS_OFFSET(data.common_serial_bus.resource_source.string_length), +	 AML_OFFSET(common_serial_bus.type_data_length), +	 sizeof(struct aml_resource_common_serialbus)}, + +	{ACPI_RSC_MOVE_SERIAL_RES, +	 ACPI_RS_OFFSET(data.common_serial_bus.resource_source.string_ptr), +	 AML_OFFSET(common_serial_bus.type_data_length), +	 sizeof(struct aml_resource_common_serialbus)}, + +	/* Uart bus type specific  */ + +	{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.uart_serial_bus.flow_control), +	 AML_OFFSET(uart_serial_bus.type_specific_flags), +	 0}, + +	{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.uart_serial_bus.stop_bits), +	 AML_OFFSET(uart_serial_bus.type_specific_flags), +	 2}, + +	{ACPI_RSC_3BITFLAG, ACPI_RS_OFFSET(data.uart_serial_bus.data_bits), +	 AML_OFFSET(uart_serial_bus.type_specific_flags), +	 4}, + +	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.uart_serial_bus.endian), +	 AML_OFFSET(uart_serial_bus.type_specific_flags), +	 7}, + +	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.uart_serial_bus.parity), +	 AML_OFFSET(uart_serial_bus.parity), +	 1}, + +	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.uart_serial_bus.lines_enabled), +	 AML_OFFSET(uart_serial_bus.lines_enabled), +	 1}, + +	{ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.uart_serial_bus.rx_fifo_size), +	 AML_OFFSET(uart_serial_bus.rx_fifo_size), +	 1}, + +	{ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.uart_serial_bus.tx_fifo_size), +	 AML_OFFSET(uart_serial_bus.tx_fifo_size), +	 1}, + +	{ACPI_RSC_MOVE32, +	 ACPI_RS_OFFSET(data.uart_serial_bus.default_baud_rate), +	 AML_OFFSET(uart_serial_bus.default_baud_rate), +	 1}, +}; diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c index 491191e6cf6..897a5ceb042 100644 --- a/drivers/acpi/acpica/rsutils.c +++ b/drivers/acpi/acpica/rsutils.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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   * @@ -144,6 +144,10 @@ acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)  			 * since there are no alignment or endian issues  			 */  		case ACPI_RSC_MOVE8: +		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; @@ -153,21 +157,26 @@ acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)  			 * misaligned memory transfers  			 */  		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;  		}  	} @@ -179,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   * @@ -231,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   * @@ -261,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   * @@ -296,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   * @@ -354,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); @@ -382,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 @@ -441,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   * @@ -490,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   * @@ -530,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); @@ -540,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   * @@ -581,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); @@ -590,10 +601,60 @@ acpi_rs_get_prs_method_data(struct acpi_namespace_node *node,  /*******************************************************************************   * + * FUNCTION:    acpi_rs_get_aei_method_data + * + * PARAMETERS:  node            - Device node + *              ret_buffer      - Pointer to a buffer structure for the + *                                results + * + * RETURN:      Status + * + * DESCRIPTION: This function is called to get the _AEI value of an object + *              contained in an object specified by the handle passed in + * + *              If the function fails an appropriate status will be returned + *              and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +acpi_status +acpi_rs_get_aei_method_data(struct acpi_namespace_node *node, +			    struct acpi_buffer *ret_buffer) +{ +	union acpi_operand_object *obj_desc; +	acpi_status status; + +	ACPI_FUNCTION_TRACE(rs_get_aei_method_data); + +	/* Parameters guaranteed valid by caller */ + +	/* Execute the method, no parameters */ + +	status = acpi_ut_evaluate_object(node, METHOD_NAME__AEI, +					 ACPI_BTYPE_BUFFER, &obj_desc); +	if (ACPI_FAILURE(status)) { +		return_ACPI_STATUS(status); +	} + +	/* +	 * Make the call to create a resource linked list from the +	 * byte stream buffer that comes back from the _CRS method +	 * execution. +	 */ +	status = acpi_rs_create_resource_list(obj_desc, ret_buffer); + +	/* On exit, we must delete the object returned by evaluateObject */ + +	acpi_ut_remove_reference(obj_desc); +	return_ACPI_STATUS(status); +} + +/******************************************************************************* + *   * 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   * @@ -621,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);  	} @@ -643,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   * @@ -678,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; @@ -690,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;  	} @@ -721,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 9f6a6e7e1c8..877ab920213 100644 --- a/drivers/acpi/acpica/rsxface.c +++ b/drivers/acpi/acpica/rsxface.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -41,6 +41,8 @@   * POSSIBILITY OF SUCH DAMAGES.   */ +#define EXPORT_ACPI_INTERFACES +  #include <acpi/acpi.h>  #include "accommon.h"  #include "acresrc.h" @@ -78,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 @@ -306,12 +308,52 @@ acpi_set_current_resources(acpi_handle device_handle,  ACPI_EXPORT_SYMBOL(acpi_set_current_resources) +/******************************************************************************* + * + * FUNCTION:    acpi_get_event_resources + * + * PARAMETERS:  device_handle   - Handle to the device object for the + *                                device we are getting resources + *              in_buffer       - Pointer to a buffer containing the + *                                resources to be set for the device + * + * RETURN:      Status + * + * DESCRIPTION: This function is called to get the event resources for a + *              specific device. The caller must first acquire a handle for + *              the desired device. The resource data is passed to the routine + *              the buffer pointed to by the in_buffer variable. Uses the + *              _AEI method. + * + ******************************************************************************/ +acpi_status +acpi_get_event_resources(acpi_handle device_handle, +			 struct acpi_buffer *ret_buffer) +{ +	acpi_status status; +	struct acpi_namespace_node *node; + +	ACPI_FUNCTION_TRACE(acpi_get_event_resources); + +	/* Validate parameters then dispatch to internal routine */ + +	status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node); +	if (ACPI_FAILURE(status)) { +		return_ACPI_STATUS(status); +	} + +	status = acpi_rs_get_aei_method_data(node, ret_buffer); +	return_ACPI_STATUS(status); +} + +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 @@ -361,6 +403,7 @@ acpi_resource_to_address64(struct acpi_resource *resource,  		break;  	default: +  		return (AE_BAD_PARAMETER);  	} @@ -374,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.   * @@ -481,67 +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 or METHOD_NAME__PRS) + * 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))) { +	if (!buffer || !buffer->pointer || !user_function) {  		return_ACPI_STATUS(AE_BAD_PARAMETER);  	} -	/* Get the _CRS or _PRS 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); @@ -563,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 d2ff4325c42..41519a95808 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -49,30 +49,35 @@  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 {  	char *name; -	u8 address64; -	u8 address32; -	u8 length; +	u16 address64; +	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", @@ -87,7 +92,7 @@ static struct acpi_fadt_info fadt_info_table[] = {  	 ACPI_FADT_OFFSET(pm1b_event_block),  	 ACPI_FADT_OFFSET(pm1_event_length),  	 ACPI_PM1_REGISTER_WIDTH * 2,	/* Enable + Status register */ -	 0}, +	 ACPI_FADT_OPTIONAL},  	{"Pm1aControlBlock",  	 ACPI_FADT_OFFSET(xpm1a_control_block), @@ -101,7 +106,7 @@ static struct acpi_fadt_info fadt_info_table[] = {  	 ACPI_FADT_OFFSET(pm1b_control_block),  	 ACPI_FADT_OFFSET(pm1_control_length),  	 ACPI_PM1_REGISTER_WIDTH, -	 0}, +	 ACPI_FADT_OPTIONAL},  	{"Pm2ControlBlock",  	 ACPI_FADT_OFFSET(xpm2_control_block), @@ -115,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 \ @@ -139,7 +144,7 @@ static struct acpi_fadt_info fadt_info_table[] = {  typedef struct acpi_fadt_pm_info {  	struct acpi_generic_address *target; -	u8 source; +	u16 source;  	u8 register_num;  } acpi_fadt_pm_info; @@ -170,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   * @@ -181,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 @@ -195,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 @@ -250,19 +344,24 @@ 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 */ -	acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs, -			      ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); +	if (!acpi_gbl_reduced_hardware) { +		acpi_tb_install_fixed_table((acpi_physical_address) +					    acpi_gbl_FADT.Xfacs, ACPI_SIG_FACS, +					    ACPI_TABLE_INDEX_FACS); +	}  }  /*******************************************************************************   *   * 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   * @@ -277,15 +376,15 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)  {  	/*  	 * Check if the FADT is larger than the largest table that we expect -	 * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue +	 * (the ACPI 5.0 version). If so, truncate the table, and issue  	 * a warning.  	 */  	if (length > sizeof(struct acpi_table_fadt)) { -		ACPI_WARNING((AE_INFO, -			      "FADT (revision %u) is longer than ACPI 2.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 */ @@ -297,13 +396,16 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)  	ACPI_MEMCPY(&acpi_gbl_FADT, table,  		    ACPI_MIN(length, sizeof(struct acpi_table_fadt))); -	/* Convert the local copy of the FADT to the common internal format */ +	/* Take a copy of the Hardware Reduced flag */ -	acpi_tb_convert_fadt(); +	acpi_gbl_reduced_hardware = FALSE; +	if (acpi_gbl_FADT.flags & ACPI_FADT_HW_REDUCED) { +		acpi_gbl_reduced_hardware = TRUE; +	} -	/* Validate FADT values now, before we make any changes */ +	/* Convert the local copy of the FADT to the common internal format */ -	acpi_tb_validate_fadt(); +	acpi_tb_convert_fadt();  	/* Initialize the global ACPI register structures */ @@ -314,78 +416,67 @@ 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.  	 */ -	if (acpi_gbl_FADT.header.revision < FADT2_REVISION_ID) { +	if (acpi_gbl_FADT.header.length <= ACPI_FADT_V2_SIZE) {  		acpi_gbl_FADT.preferred_profile = 0;  		acpi_gbl_FADT.pstate_control = 0;  		acpi_gbl_FADT.cst_control = 0; @@ -393,168 +484,169 @@ 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); + +	acpi_gbl_FADT.Xdsdt = acpi_tb_select_address("DSDT", +						     acpi_gbl_FADT.dsdt, +						     acpi_gbl_FADT.Xdsdt); -	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))); +	/* If Hardware Reduced flag is set, we are all done */ -		acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt; +	if (acpi_gbl_reduced_hardware) { +		return;  	}  	/* Examine all of the 64-bit extended address fields (X fields) */  	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));  			}  		}  	} @@ -599,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 */ @@ -648,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 989d5c86786..cb947700206 100644 --- a/drivers/acpi/acpica/tbfind.c +++ b/drivers/acpi/acpica/tbfind.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 83d7af8d090..755b90c40dd 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -43,587 +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); -		} -	} - -	/* -	 * Originally, we checked the table signature for "SSDT" or "PSDT" here. -	 * Next, we added support for OEMx tables, signature "OEM". -	 * Valid tables were encountered with a null signature, so we've just -	 * given up on validating the signature, since it seems to be a waste -	 * of code. The original code was removed (05/2008). -	 */ - -	(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); +	is_identical = (u8)((table_desc->length != table_length || +			     ACPI_MEMCMP(table_desc->pointer, table, +					 table_length)) ? FALSE : TRUE); -		/* Setup descriptor for the new table */ +	/* Release the acquired table */ -		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: -	(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 */ - -	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_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.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { -			ACPI_FREE(acpi_gbl_root_table_list.tables); -		} -	} +	acpi_tb_print_table_header(new_table_desc->address, +				   new_table_desc->pointer); -	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; +	/* Set the global integer width (based upon revision of the DSDT) */ -	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); -} - -/******************************************************************************* - * - * 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); +	/* Validate and verify a table before installation */ -	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: + +	/* Release the temporary table descriptor */ -	status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); +	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); -} +	return;			/* There was no override */ -/******************************************************************************* - * - * FUNCTION:    acpi_tb_release_owner_id - * - * PARAMETERS:  table_index         - Table index - * - * RETURN:      Status - * - * DESCRIPTION: Releases owner_id in table_desc - * - ******************************************************************************/ +finish_override: -acpi_status acpi_tb_release_owner_id(u32 table_index) -{ -	acpi_status status = AE_BAD_PARAMETER; - -	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 34f9c2bc5e1..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 - 2010, 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 @@ -135,12 +70,20 @@ acpi_status acpi_tb_initialize_facs(void)  {  	acpi_status status; +	/* If Hardware Reduced flag is set, there is no FACS */ + +	if (acpi_gbl_reduced_hardware) { +		acpi_gbl_FACS = NULL; +		return (AE_OK); +	} +  	status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,  					 ACPI_CAST_INDIRECT_PTR(struct  								acpi_table_header,  								&acpi_gbl_FACS)); -	return status; +	return (status);  } +#endif				/* !ACPI_REDUCED_HARDWARE */  /*******************************************************************************   * @@ -167,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 @@ -368,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); @@ -414,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", @@ -427,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 @@ -553,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 @@ -573,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)); @@ -587,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   * @@ -600,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; @@ -609,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); @@ -628,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;  	}  	/* @@ -654,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)); @@ -672,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);  	} @@ -696,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 4a8b9e6ea57..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 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -42,19 +41,15 @@   * 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("tbxface") -/* Local prototypes */ -static acpi_status acpi_tb_load_namespace(void); - -static int no_auto_ssdt; -  /*******************************************************************************   *   * FUNCTION:    acpi_allocate_root_table @@ -64,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)  { @@ -87,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.   * @@ -114,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); @@ -154,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 @@ -165,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); @@ -184,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 @@ -281,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 */ @@ -308,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)); @@ -323,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, @@ -381,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 @@ -395,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 */ @@ -420,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; @@ -436,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) @@ -445,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)  /******************************************************************************* @@ -452,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; @@ -486,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); @@ -503,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; @@ -686,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);  } @@ -697,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; @@ -727,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 fd2c07d1d3a..65ab8fed3d5 100644 --- a/drivers/acpi/acpica/tbxfroot.c +++ b/drivers/acpi/acpica/tbxfroot.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 new file mode 100644 index 00000000000..a1acec9d2ef --- /dev/null +++ b/drivers/acpi/acpica/utaddress.c @@ -0,0 +1,301 @@ +/****************************************************************************** + * + * Module Name: utaddress - op_region address range check + * + *****************************************************************************/ + +/* + * 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("utaddress") + +/******************************************************************************* + * + * FUNCTION:    acpi_ut_add_address_range + * + * PARAMETERS:  space_id            - Address space ID + *              address             - op_region start address + *              length              - op_region length + *              region_node         - op_region namespace node + * + * RETURN:      Status + * + * DESCRIPTION: Add the Operation Region address range to the global list. + *              The only supported Space IDs are Memory and I/O. Called when + *              the op_region address/length operands are fully evaluated. + * + * MUTEX:       Locks the namespace + * + * NOTE: Because this interface is only called when an op_region argument + * list is evaluated, there cannot be any duplicate region_nodes. + * Duplicate Address/Length values are allowed, however, so that multiple + * address conflicts can be detected. + * + ******************************************************************************/ +acpi_status +acpi_ut_add_address_range(acpi_adr_space_type space_id, +			  acpi_physical_address address, +			  u32 length, struct acpi_namespace_node *region_node) +{ +	struct acpi_address_range *range_info; +	acpi_status status; + +	ACPI_FUNCTION_TRACE(ut_add_address_range); + +	if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) && +	    (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { +		return_ACPI_STATUS(AE_OK); +	} + +	/* Allocate/init a new info block, add it to the appropriate list */ + +	range_info = ACPI_ALLOCATE(sizeof(struct acpi_address_range)); +	if (!range_info) { +		return_ACPI_STATUS(AE_NO_MEMORY); +	} + +	range_info->start_address = address; +	range_info->end_address = (address + length - 1); +	range_info->region_node = region_node; + +	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); +	if (ACPI_FAILURE(status)) { +		ACPI_FREE(range_info); +		return_ACPI_STATUS(status); +	} + +	range_info->next = acpi_gbl_address_range_list[space_id]; +	acpi_gbl_address_range_list[space_id] = range_info; + +	ACPI_DEBUG_PRINT((ACPI_DB_NAMES, +			  "\nAdded [%4.4s] address range: 0x%p-0x%p\n", +			  acpi_ut_get_node_name(range_info->region_node), +			  ACPI_CAST_PTR(void, address), +			  ACPI_CAST_PTR(void, range_info->end_address))); + +	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); +	return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ut_remove_address_range + * + * PARAMETERS:  space_id            - Address space ID + *              region_node         - op_region namespace node + * + * RETURN:      None + * + * DESCRIPTION: Remove the Operation Region from the global list. The only + *              supported Space IDs are Memory and I/O. Called when an + *              op_region is deleted. + * + * MUTEX:       Assumes the namespace is locked + * + ******************************************************************************/ + +void +acpi_ut_remove_address_range(acpi_adr_space_type space_id, +			     struct acpi_namespace_node *region_node) +{ +	struct acpi_address_range *range_info; +	struct acpi_address_range *prev; + +	ACPI_FUNCTION_TRACE(ut_remove_address_range); + +	if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) && +	    (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { +		return_VOID; +	} + +	/* Get the appropriate list head and check the list */ + +	range_info = prev = acpi_gbl_address_range_list[space_id]; +	while (range_info) { +		if (range_info->region_node == region_node) { +			if (range_info == prev) {	/* Found at list head */ +				acpi_gbl_address_range_list[space_id] = +				    range_info->next; +			} else { +				prev->next = range_info->next; +			} + +			ACPI_DEBUG_PRINT((ACPI_DB_NAMES, +					  "\nRemoved [%4.4s] address range: 0x%p-0x%p\n", +					  acpi_ut_get_node_name(range_info-> +								region_node), +					  ACPI_CAST_PTR(void, +							range_info-> +							start_address), +					  ACPI_CAST_PTR(void, +							range_info-> +							end_address))); + +			ACPI_FREE(range_info); +			return_VOID; +		} + +		prev = range_info; +		range_info = range_info->next; +	} + +	return_VOID; +} + +/******************************************************************************* + * + * 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 + * + * RETURN:      Count of the number of conflicts detected. Zero is always + *              returned for Space IDs other than Memory or I/O. + * + * DESCRIPTION: Check if the input address range overlaps any of the + *              ASL operation region address ranges. The only supported + *              Space IDs are Memory and I/O. + * + * MUTEX:       Assumes the namespace is locked. + * + ******************************************************************************/ + +u32 +acpi_ut_check_address_range(acpi_adr_space_type space_id, +			    acpi_physical_address address, u32 length, u8 warn) +{ +	struct acpi_address_range *range_info; +	acpi_physical_address end_address; +	char *pathname; +	u32 overlap_count = 0; + +	ACPI_FUNCTION_TRACE(ut_check_address_range); + +	if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) && +	    (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { +		return_UINT32(0); +	} + +	range_info = acpi_gbl_address_range_list[space_id]; +	end_address = address + length - 1; + +	/* Check entire list for all possible conflicts */ + +	while (range_info) { +		/* +		 * 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 +		 * 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 +		 */ +		if ((address <= range_info->end_address) && +		    (end_address >= range_info->start_address)) { + +			/* Found an address range overlap */ + +			overlap_count++; +			if (warn) {	/* Optional warning message */ +				pathname = +				    acpi_ns_get_external_pathname(range_info-> +								  region_node); + +				ACPI_WARNING((AE_INFO, +					      "%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_CAST_PTR(void, +							    range_info-> +							    start_address), +					      ACPI_CAST_PTR(void, +							    range_info-> +							    end_address), +					      pathname)); +				ACPI_FREE(pathname); +			} +		} + +		range_info = range_info->next; +	} + +	return_UINT32(overlap_count); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ut_delete_address_lists + * + * PARAMETERS:  None + * + * RETURN:      None + * + * DESCRIPTION: Delete all global address range lists (called during + *              subsystem shutdown). + * + ******************************************************************************/ + +void acpi_ut_delete_address_lists(void) +{ +	struct acpi_address_range *next; +	struct acpi_address_range *range_info; +	int i; + +	/* Delete all elements in all address range lists */ + +	for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) { +		next = acpi_gbl_address_range_list[i]; + +		while (next) { +			range_info = next; +			next = range_info->next; +			ACPI_FREE(range_info); +		} + +		acpi_gbl_address_range_list[i] = NULL; +	} +} diff --git a/drivers/acpi/acpica/utalloc.c b/drivers/acpi/acpica/utalloc.c index 8f089628156..efac83c606d 100644 --- a/drivers/acpi/acpica/utalloc.c +++ b/drivers/acpi/acpica/utalloc.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 6fef83f04bc..270c16464dd 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 f21c486929a..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 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -41,13 +41,16 @@   * POSSIBILITY OF SUCH DAMAGES.   */ +#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-"; @@ -108,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.   *   ******************************************************************************/ @@ -144,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 @@ -164,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;  	} @@ -184,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); @@ -216,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.   *   ******************************************************************************/ @@ -234,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;  	} @@ -257,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   *   ******************************************************************************/ @@ -270,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) @@ -285,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   *   ******************************************************************************/ @@ -298,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); +	}  }  /******************************************************************************* @@ -314,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   *   ******************************************************************************/ @@ -332,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); +	}  }  /******************************************************************************* @@ -345,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   *   ******************************************************************************/ @@ -363,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); +	}  }  /******************************************************************************* @@ -379,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   *   ******************************************************************************/ @@ -390,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) @@ -407,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.   *   ******************************************************************************/ @@ -422,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) @@ -448,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.   *   ******************************************************************************/ @@ -462,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) @@ -480,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.   *   ******************************************************************************/ @@ -494,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 new file mode 100644 index 00000000000..90ec37c473c --- /dev/null +++ b/drivers/acpi/acpica/utdecode.c @@ -0,0 +1,571 @@ +/****************************************************************************** + * + * Module Name: utdecode - Utility decoding routines (value-to-string) + * + *****************************************************************************/ + +/* + * 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("utdecode") + +/* + * Properties of the ACPI Object Types, both internal and external. + * The table is indexed by values of acpi_object_type + */ +const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES] = { +	ACPI_NS_NORMAL,		/* 00 Any              */ +	ACPI_NS_NORMAL,		/* 01 Number           */ +	ACPI_NS_NORMAL,		/* 02 String           */ +	ACPI_NS_NORMAL,		/* 03 Buffer           */ +	ACPI_NS_NORMAL,		/* 04 Package          */ +	ACPI_NS_NORMAL,		/* 05 field_unit       */ +	ACPI_NS_NEWSCOPE,	/* 06 Device           */ +	ACPI_NS_NORMAL,		/* 07 Event            */ +	ACPI_NS_NEWSCOPE,	/* 08 Method           */ +	ACPI_NS_NORMAL,		/* 09 Mutex            */ +	ACPI_NS_NORMAL,		/* 10 Region           */ +	ACPI_NS_NEWSCOPE,	/* 11 Power            */ +	ACPI_NS_NEWSCOPE,	/* 12 Processor        */ +	ACPI_NS_NEWSCOPE,	/* 13 Thermal          */ +	ACPI_NS_NORMAL,		/* 14 buffer_field     */ +	ACPI_NS_NORMAL,		/* 15 ddb_handle       */ +	ACPI_NS_NORMAL,		/* 16 Debug Object     */ +	ACPI_NS_NORMAL,		/* 17 def_field        */ +	ACPI_NS_NORMAL,		/* 18 bank_field       */ +	ACPI_NS_NORMAL,		/* 19 index_field      */ +	ACPI_NS_NORMAL,		/* 20 Reference        */ +	ACPI_NS_NORMAL,		/* 21 Alias            */ +	ACPI_NS_NORMAL,		/* 22 method_alias     */ +	ACPI_NS_NORMAL,		/* 23 Notify           */ +	ACPI_NS_NORMAL,		/* 24 Address Handler  */ +	ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL,	/* 25 Resource Desc    */ +	ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL,	/* 26 Resource Field   */ +	ACPI_NS_NEWSCOPE,	/* 27 Scope            */ +	ACPI_NS_NORMAL,		/* 28 Extra            */ +	ACPI_NS_NORMAL,		/* 29 Data             */ +	ACPI_NS_NORMAL		/* 30 Invalid          */ +}; + +/******************************************************************************* + * + * FUNCTION:    acpi_ut_hex_to_ascii_char + * + * PARAMETERS:  integer             - Contains the hex digit + *              position            - bit position of the digit within the + *                                    integer (multiple of 4) + * + * RETURN:      The converted Ascii character + * + * DESCRIPTION: Convert a hex digit to an Ascii character + * + ******************************************************************************/ + +/* Hex to ASCII conversion table */ + +static const char acpi_gbl_hex_to_ascii[] = { +	'0', '1', '2', '3', '4', '5', '6', '7', +	'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' +}; + +char acpi_ut_hex_to_ascii_char(u64 integer, u32 position) +{ + +	return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ut_get_region_name + * + * PARAMETERS:  Space ID            - ID for the region + * + * RETURN:      Decoded region space_id name + * + * DESCRIPTION: Translate a Space ID into a name string (Debug only) + * + ******************************************************************************/ + +/* Region type decoding */ + +const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = { +	"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) +{ + +	if (space_id >= ACPI_USER_REGION_BEGIN) { +		return ("UserDefinedRegion"); +	} else if (space_id == ACPI_ADR_SPACE_DATA_TABLE) { +		return ("DataTable"); +	} else if (space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) { +		return ("FunctionalFixedHW"); +	} else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS) { +		return ("InvalidSpaceId"); +	} + +	return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id])); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ut_get_event_name + * + * PARAMETERS:  event_id            - Fixed event ID + * + * RETURN:      Decoded event ID name + * + * DESCRIPTION: Translate a Event ID into a name string (Debug only) + * + ******************************************************************************/ + +/* Event type decoding */ + +static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = { +	"PM_Timer", +	"GlobalLock", +	"PowerButton", +	"SleepButton", +	"RealTimeClock", +}; + +char *acpi_ut_get_event_name(u32 event_id) +{ + +	if (event_id > ACPI_EVENT_MAX) { +		return ("InvalidEventID"); +	} + +	return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id])); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ut_get_type_name + * + * PARAMETERS:  type                - An ACPI object type + * + * RETURN:      Decoded ACPI object type name + * + * DESCRIPTION: Translate a Type ID into a name string (Debug only) + * + ******************************************************************************/ + +/* + * Elements of acpi_gbl_ns_type_names below must match + * one-to-one with values of acpi_object_type + * + * The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching; + * when stored in a table it really means that we have thus far seen no + * evidence to indicate what type is actually going to be stored for this entry. + */ +static const char acpi_gbl_bad_type[] = "UNDEFINED"; + +/* Printable names of the ACPI object types */ + +static const char *acpi_gbl_ns_type_names[] = { +	/* 00 */ "Untyped", +	/* 01 */ "Integer", +	/* 02 */ "String", +	/* 03 */ "Buffer", +	/* 04 */ "Package", +	/* 05 */ "FieldUnit", +	/* 06 */ "Device", +	/* 07 */ "Event", +	/* 08 */ "Method", +	/* 09 */ "Mutex", +	/* 10 */ "Region", +	/* 11 */ "Power", +	/* 12 */ "Processor", +	/* 13 */ "Thermal", +	/* 14 */ "BufferField", +	/* 15 */ "DdbHandle", +	/* 16 */ "DebugObject", +	/* 17 */ "RegionField", +	/* 18 */ "BankField", +	/* 19 */ "IndexField", +	/* 20 */ "Reference", +	/* 21 */ "Alias", +	/* 22 */ "MethodAlias", +	/* 23 */ "Notify", +	/* 24 */ "AddrHandler", +	/* 25 */ "ResourceDesc", +	/* 26 */ "ResourceFld", +	/* 27 */ "Scope", +	/* 28 */ "Extra", +	/* 29 */ "Data", +	/* 30 */ "Invalid" +}; + +char *acpi_ut_get_type_name(acpi_object_type type) +{ + +	if (type > ACPI_TYPE_INVALID) { +		return (ACPI_CAST_PTR(char, acpi_gbl_bad_type)); +	} + +	return (ACPI_CAST_PTR(char, acpi_gbl_ns_type_names[type])); +} + +char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc) +{ + +	if (!obj_desc) { +		return ("[NULL Object Descriptor]"); +	} + +	return (acpi_ut_get_type_name(obj_desc->common.type)); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ut_get_node_name + * + * PARAMETERS:  object               - A namespace node + * + * RETURN:      ASCII name of the node + * + * DESCRIPTION: Validate the node and return the node's ACPI name. + * + ******************************************************************************/ + +char *acpi_ut_get_node_name(void *object) +{ +	struct acpi_namespace_node *node = (struct acpi_namespace_node *)object; + +	/* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */ + +	if (!object) { +		return ("NULL"); +	} + +	/* Check for Root node */ + +	if ((object == ACPI_ROOT_OBJECT) || (object == acpi_gbl_root_node)) { +		return ("\"\\\" "); +	} + +	/* Descriptor must be a namespace node */ + +	if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { +		return ("####"); +	} + +	/* +	 * Ensure name is valid. The name was validated/repaired when the node +	 * was created, but make sure it has not been corrupted. +	 */ +	acpi_ut_repair_name(node->name.ascii); + +	/* Return the name */ + +	return (node->name.ascii); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ut_get_descriptor_name + * + * PARAMETERS:  object               - An ACPI object + * + * RETURN:      Decoded name of the descriptor type + * + * DESCRIPTION: Validate object and return the descriptor type + * + ******************************************************************************/ + +/* Printable names of object descriptor types */ + +static const char *acpi_gbl_desc_type_names[] = { +	/* 00 */ "Not a Descriptor", +	/* 01 */ "Cached", +	/* 02 */ "State-Generic", +	/* 03 */ "State-Update", +	/* 04 */ "State-Package", +	/* 05 */ "State-Control", +	/* 06 */ "State-RootParseScope", +	/* 07 */ "State-ParseScope", +	/* 08 */ "State-WalkScope", +	/* 09 */ "State-Result", +	/* 10 */ "State-Notify", +	/* 11 */ "State-Thread", +	/* 12 */ "Walk", +	/* 13 */ "Parser", +	/* 14 */ "Operand", +	/* 15 */ "Node" +}; + +char *acpi_ut_get_descriptor_name(void *object) +{ + +	if (!object) { +		return ("NULL OBJECT"); +	} + +	if (ACPI_GET_DESCRIPTOR_TYPE(object) > ACPI_DESC_TYPE_MAX) { +		return ("Not a Descriptor"); +	} + +	return (ACPI_CAST_PTR(char, +			      acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE +						       (object)])); + +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ut_get_reference_name + * + * PARAMETERS:  object               - An ACPI reference object + * + * RETURN:      Decoded name of the type of reference + * + * DESCRIPTION: Decode a reference object sub-type to a string. + * + ******************************************************************************/ + +/* Printable names of reference object sub-types */ + +static const char *acpi_gbl_ref_class_names[] = { +	/* 00 */ "Local", +	/* 01 */ "Argument", +	/* 02 */ "RefOf", +	/* 03 */ "Index", +	/* 04 */ "DdbHandle", +	/* 05 */ "Named Object", +	/* 06 */ "Debug" +}; + +const char *acpi_ut_get_reference_name(union acpi_operand_object *object) +{ + +	if (!object) { +		return ("NULL Object"); +	} + +	if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) { +		return ("Not an Operand object"); +	} + +	if (object->common.type != ACPI_TYPE_LOCAL_REFERENCE) { +		return ("Not a Reference object"); +	} + +	if (object->reference.class > ACPI_REFCLASS_MAX) { +		return ("Unknown Reference class"); +	} + +	return (acpi_gbl_ref_class_names[object->reference.class]); +} + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +/* + * Strings and procedures used for debug only + */ + +/******************************************************************************* + * + * FUNCTION:    acpi_ut_get_mutex_name + * + * PARAMETERS:  mutex_id        - The predefined ID for this mutex. + * + * RETURN:      Decoded name of the internal mutex + * + * DESCRIPTION: Translate a mutex ID into a name string (Debug only) + * + ******************************************************************************/ + +/* Names for internal mutex objects, used for debug output */ + +static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = { +	"ACPI_MTX_Interpreter", +	"ACPI_MTX_Namespace", +	"ACPI_MTX_Tables", +	"ACPI_MTX_Events", +	"ACPI_MTX_Caches", +	"ACPI_MTX_Memory", +	"ACPI_MTX_CommandComplete", +	"ACPI_MTX_CommandReady" +}; + +char *acpi_ut_get_mutex_name(u32 mutex_id) +{ + +	if (mutex_id > ACPI_MAX_MUTEX) { +		return ("Invalid Mutex ID"); +	} + +	return (acpi_gbl_mutex_names[mutex_id]); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_ut_get_notify_name + * + * PARAMETERS:  notify_value    - Value from the Notify() request + * + * RETURN:      Decoded name for the notify value + * + * DESCRIPTION: Translate a Notify Value to a notify namestring. + * + ******************************************************************************/ + +/* Names for Notify() values, used for debug output */ + +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, acpi_object_type type) +{ + +	/* 00 - 0C are common to all object types */ + +	if (notify_value <= ACPI_NOTIFY_MAX) { +		return (acpi_gbl_generic_notify[notify_value]); +	} + +	/* 0D - 7F are reserved */ + +	if (notify_value <= ACPI_MAX_SYS_NOTIFY) { +		return ("Reserved"); +	} + +	/* 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 + +/******************************************************************************* + * + * FUNCTION:    acpi_ut_valid_object_type + * + * PARAMETERS:  type            - Object type to be validated + * + * RETURN:      TRUE if valid object type, FALSE otherwise + * + * DESCRIPTION: Validate an object type + * + ******************************************************************************/ + +u8 acpi_ut_valid_object_type(acpi_object_type type) +{ + +	if (type > ACPI_TYPE_LOCAL_MAX) { + +		/* Note: Assumes all TYPEs are contiguous (external/local) */ + +		return (FALSE); +	} + +	return (TRUE); +} diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c index ed794cd033e..a3516de213f 100644 --- a/drivers/acpi/acpica/utdelete.c +++ b/drivers/acpi/acpica/utdelete.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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) { @@ -215,11 +216,14 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)  		ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,  				  "***** Region %p\n", object)); -		/* Invalidate the region address/length via the host OS */ - -		acpi_os_invalidate_address(object->region.space_id, -					  object->region.address, -					  (acpi_size) object->region.length); +		/* +		 * Update address_range list. However, only permanent regions +		 * are installed in this list. (Not created within a method) +		 */ +		if (!(object->region.node->flags & ANOBJ_TEMPORARY)) { +			acpi_ut_remove_address_range(object->region.space_id, +						     object->region.node); +		}  		second_desc = acpi_ns_get_secondary_object(object);  		if (second_desc) { @@ -232,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) { @@ -244,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 & @@ -300,6 +314,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)  		break;  	default: +  		break;  	} @@ -337,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 */ @@ -348,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); @@ -376,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)); +		/* The current reference count must be non-zero */ -			new_count = 0; -		} else { -			new_count--; - -			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));  	}  } @@ -453,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   * @@ -477,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) { @@ -489,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);  		}  		/* @@ -501,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: @@ -517,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: @@ -583,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 */  		} @@ -606,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")); @@ -620,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 @@ -639,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, @@ -654,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   * @@ -672,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, @@ -700,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 22f59ef604e..8fed1482d22 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 e87bc6760be..d69be3cb3fa 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -41,11 +41,11 @@   * POSSIBILITY OF SUCH DAMAGES.   */ +#define EXPORT_ACPI_INTERFACES  #define DEFINE_ACPI_GLOBALS  #include <acpi/acpi.h>  #include "accommon.h" -#include "acnamesp.h"  #define _COMPONENT          ACPI_UTILITIES  ACPI_MODULE_NAME("utglobal") @@ -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_", @@ -107,43 +82,6 @@ const char *acpi_gbl_highest_dstate_names[ACPI_NUM_sx_d_METHODS] = {  /*******************************************************************************   * - * 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"; -		dump_stack(); -	} - -	return (ACPI_CAST_PTR(const char, exception)); -} - -ACPI_EXPORT_SYMBOL(acpi_format_exception) - -/******************************************************************************* - *   * Namespace globals   *   ******************************************************************************/ @@ -177,71 +115,7 @@ const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = {  	{NULL, ACPI_TYPE_ANY, NULL}  }; -/* - * Properties of the ACPI Object Types, both internal and external. - * The table is indexed by values of acpi_object_type - */ -const u8 acpi_gbl_ns_properties[] = { -	ACPI_NS_NORMAL,		/* 00 Any              */ -	ACPI_NS_NORMAL,		/* 01 Number           */ -	ACPI_NS_NORMAL,		/* 02 String           */ -	ACPI_NS_NORMAL,		/* 03 Buffer           */ -	ACPI_NS_NORMAL,		/* 04 Package          */ -	ACPI_NS_NORMAL,		/* 05 field_unit       */ -	ACPI_NS_NEWSCOPE,	/* 06 Device           */ -	ACPI_NS_NORMAL,		/* 07 Event            */ -	ACPI_NS_NEWSCOPE,	/* 08 Method           */ -	ACPI_NS_NORMAL,		/* 09 Mutex            */ -	ACPI_NS_NORMAL,		/* 10 Region           */ -	ACPI_NS_NEWSCOPE,	/* 11 Power            */ -	ACPI_NS_NEWSCOPE,	/* 12 Processor        */ -	ACPI_NS_NEWSCOPE,	/* 13 Thermal          */ -	ACPI_NS_NORMAL,		/* 14 buffer_field     */ -	ACPI_NS_NORMAL,		/* 15 ddb_handle       */ -	ACPI_NS_NORMAL,		/* 16 Debug Object     */ -	ACPI_NS_NORMAL,		/* 17 def_field        */ -	ACPI_NS_NORMAL,		/* 18 bank_field       */ -	ACPI_NS_NORMAL,		/* 19 index_field      */ -	ACPI_NS_NORMAL,		/* 20 Reference        */ -	ACPI_NS_NORMAL,		/* 21 Alias            */ -	ACPI_NS_NORMAL,		/* 22 method_alias     */ -	ACPI_NS_NORMAL,		/* 23 Notify           */ -	ACPI_NS_NORMAL,		/* 24 Address Handler  */ -	ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL,	/* 25 Resource Desc    */ -	ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL,	/* 26 Resource Field   */ -	ACPI_NS_NEWSCOPE,	/* 27 Scope            */ -	ACPI_NS_NORMAL,		/* 28 Extra            */ -	ACPI_NS_NORMAL,		/* 29 Data             */ -	ACPI_NS_NORMAL		/* 30 Invalid          */ -}; - -/* Hex to ASCII conversion table */ - -static const char acpi_gbl_hex_to_ascii[] = { -	'0', '1', '2', '3', '4', '5', '6', '7', -	'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' -}; - -/******************************************************************************* - * - * FUNCTION:    acpi_ut_hex_to_ascii_char - * - * PARAMETERS:  Integer             - Contains the hex digit - *              Position            - bit position of the digit within the - *                                    integer (multiple of 4) - * - * RETURN:      The converted Ascii character - * - * DESCRIPTION: Convert a hex digit to an Ascii character - * - ******************************************************************************/ - -char acpi_ut_hex_to_ascii_char(u64 integer, u32 position) -{ - -	return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]); -} - +#if (!ACPI_REDUCED_HARDWARE)  /******************************************************************************   *   * Event and Hardware globals @@ -338,386 +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},  }; - -/******************************************************************************* - * - * FUNCTION:    acpi_ut_get_region_name - * - * PARAMETERS:  None. - * - * RETURN:      Status - * - * DESCRIPTION: Translate a Space ID into a name string (Debug only) - * - ******************************************************************************/ - -/* Region type decoding */ - -const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = { -	"SystemMemory", -	"SystemIO", -	"PCI_Config", -	"EmbeddedControl", -	"SMBus", -	"SystemCMOS", -	"PCIBARTarget", -	"IPMI", -	"DataTable" -}; - -char *acpi_ut_get_region_name(u8 space_id) -{ - -	if (space_id >= ACPI_USER_REGION_BEGIN) { -		return ("UserDefinedRegion"); -	} else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS) { -		return ("InvalidSpaceId"); -	} - -	return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id])); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_ut_get_event_name - * - * PARAMETERS:  None. - * - * RETURN:      Status - * - * DESCRIPTION: Translate a Event ID into a name string (Debug only) - * - ******************************************************************************/ - -/* Event type decoding */ - -static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = { -	"PM_Timer", -	"GlobalLock", -	"PowerButton", -	"SleepButton", -	"RealTimeClock", -}; - -char *acpi_ut_get_event_name(u32 event_id) -{ - -	if (event_id > ACPI_EVENT_MAX) { -		return ("InvalidEventID"); -	} - -	return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id])); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_ut_get_type_name - * - * PARAMETERS:  None. - * - * RETURN:      Status - * - * DESCRIPTION: Translate a Type ID into a name string (Debug only) - * - ******************************************************************************/ - -/* - * Elements of acpi_gbl_ns_type_names below must match - * one-to-one with values of acpi_object_type - * - * The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching; - * when stored in a table it really means that we have thus far seen no - * evidence to indicate what type is actually going to be stored for this entry. - */ -static const char acpi_gbl_bad_type[] = "UNDEFINED"; - -/* Printable names of the ACPI object types */ - -static const char *acpi_gbl_ns_type_names[] = { -	/* 00 */ "Untyped", -	/* 01 */ "Integer", -	/* 02 */ "String", -	/* 03 */ "Buffer", -	/* 04 */ "Package", -	/* 05 */ "FieldUnit", -	/* 06 */ "Device", -	/* 07 */ "Event", -	/* 08 */ "Method", -	/* 09 */ "Mutex", -	/* 10 */ "Region", -	/* 11 */ "Power", -	/* 12 */ "Processor", -	/* 13 */ "Thermal", -	/* 14 */ "BufferField", -	/* 15 */ "DdbHandle", -	/* 16 */ "DebugObject", -	/* 17 */ "RegionField", -	/* 18 */ "BankField", -	/* 19 */ "IndexField", -	/* 20 */ "Reference", -	/* 21 */ "Alias", -	/* 22 */ "MethodAlias", -	/* 23 */ "Notify", -	/* 24 */ "AddrHandler", -	/* 25 */ "ResourceDesc", -	/* 26 */ "ResourceFld", -	/* 27 */ "Scope", -	/* 28 */ "Extra", -	/* 29 */ "Data", -	/* 30 */ "Invalid" -}; - -char *acpi_ut_get_type_name(acpi_object_type type) -{ - -	if (type > ACPI_TYPE_INVALID) { -		return (ACPI_CAST_PTR(char, acpi_gbl_bad_type)); -	} - -	return (ACPI_CAST_PTR(char, acpi_gbl_ns_type_names[type])); -} - -char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc) -{ - -	if (!obj_desc) { -		return ("[NULL Object Descriptor]"); -	} - -	return (acpi_ut_get_type_name(obj_desc->common.type)); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_ut_get_node_name - * - * PARAMETERS:  Object               - A namespace node - * - * RETURN:      Pointer to a string - * - * DESCRIPTION: Validate the node and return the node's ACPI name. - * - ******************************************************************************/ - -char *acpi_ut_get_node_name(void *object) -{ -	struct acpi_namespace_node *node = (struct acpi_namespace_node *)object; - -	/* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */ - -	if (!object) { -		return ("NULL"); -	} - -	/* Check for Root node */ - -	if ((object == ACPI_ROOT_OBJECT) || (object == acpi_gbl_root_node)) { -		return ("\"\\\" "); -	} - -	/* Descriptor must be a namespace node */ - -	if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { -		return ("####"); -	} - -	/* Name must be a valid ACPI name */ - -	if (!acpi_ut_valid_acpi_name(node->name.integer)) { -		node->name.integer = acpi_ut_repair_name(node->name.ascii); -	} - -	/* Return the name */ - -	return (node->name.ascii); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_ut_get_descriptor_name - * - * PARAMETERS:  Object               - An ACPI object - * - * RETURN:      Pointer to a string - * - * DESCRIPTION: Validate object and return the descriptor type - * - ******************************************************************************/ - -/* Printable names of object descriptor types */ - -static const char *acpi_gbl_desc_type_names[] = { -	/* 00 */ "Invalid", -	/* 01 */ "Cached", -	/* 02 */ "State-Generic", -	/* 03 */ "State-Update", -	/* 04 */ "State-Package", -	/* 05 */ "State-Control", -	/* 06 */ "State-RootParseScope", -	/* 07 */ "State-ParseScope", -	/* 08 */ "State-WalkScope", -	/* 09 */ "State-Result", -	/* 10 */ "State-Notify", -	/* 11 */ "State-Thread", -	/* 12 */ "Walk", -	/* 13 */ "Parser", -	/* 14 */ "Operand", -	/* 15 */ "Node" -}; - -char *acpi_ut_get_descriptor_name(void *object) -{ - -	if (!object) { -		return ("NULL OBJECT"); -	} - -	if (ACPI_GET_DESCRIPTOR_TYPE(object) > ACPI_DESC_TYPE_MAX) { -		return (ACPI_CAST_PTR(char, acpi_gbl_bad_type)); -	} - -	return (ACPI_CAST_PTR(char, -			      acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE -						       (object)])); - -} - -/******************************************************************************* - * - * FUNCTION:    acpi_ut_get_reference_name - * - * PARAMETERS:  Object               - An ACPI reference object - * - * RETURN:      Pointer to a string - * - * DESCRIPTION: Decode a reference object sub-type to a string. - * - ******************************************************************************/ - -/* Printable names of reference object sub-types */ - -static const char *acpi_gbl_ref_class_names[] = { -	/* 00 */ "Local", -	/* 01 */ "Argument", -	/* 02 */ "RefOf", -	/* 03 */ "Index", -	/* 04 */ "DdbHandle", -	/* 05 */ "Named Object", -	/* 06 */ "Debug" -}; - -const char *acpi_ut_get_reference_name(union acpi_operand_object *object) -{ -	if (!object) -		return "NULL Object"; - -	if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) -		return "Not an Operand object"; - -	if (object->common.type != ACPI_TYPE_LOCAL_REFERENCE) -		return "Not a Reference object"; - -	if (object->reference.class > ACPI_REFCLASS_MAX) -		return "Unknown Reference class"; - -	return acpi_gbl_ref_class_names[object->reference.class]; -} - -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) -/* - * Strings and procedures used for debug only - */ - -/******************************************************************************* - * - * FUNCTION:    acpi_ut_get_mutex_name - * - * PARAMETERS:  mutex_id        - The predefined ID for this mutex. - * - * RETURN:      String containing the name of the mutex. Always returns a valid - *              pointer. - * - * DESCRIPTION: Translate a mutex ID into a name string (Debug only) - * - ******************************************************************************/ - -char *acpi_ut_get_mutex_name(u32 mutex_id) -{ - -	if (mutex_id > ACPI_MAX_MUTEX) { -		return ("Invalid Mutex ID"); -	} - -	return (acpi_gbl_mutex_names[mutex_id]); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_ut_get_notify_name - * - * PARAMETERS:  notify_value    - Value from the Notify() request - * - * RETURN:      String corresponding to the Notify Value. - * - * DESCRIPTION: Translate a Notify Value to a notify namestring. - * - ******************************************************************************/ - -/* 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" -}; - -const char *acpi_ut_get_notify_name(u32 notify_value) -{ - -	if (notify_value <= ACPI_NOTIFY_MAX) { -		return (acpi_gbl_notify_value_names[notify_value]); -	} else if (notify_value <= ACPI_MAX_SYS_NOTIFY) { -		return ("Reserved"); -	} else {		/* Greater or equal to 0x80 */ - -		return ("**Device Specific**"); -	} -} -#endif - -/******************************************************************************* - * - * FUNCTION:    acpi_ut_valid_object_type - * - * PARAMETERS:  Type            - Object type to be validated - * - * RETURN:      TRUE if valid object type, FALSE otherwise - * - * DESCRIPTION: Validate an object type - * - ******************************************************************************/ - -u8 acpi_ut_valid_object_type(acpi_object_type type) -{ - -	if (type > ACPI_TYPE_LOCAL_MAX) { - -		/* Note: Assumes all TYPEs are contiguous (external/local) */ - -		return (FALSE); -	} - -	return (TRUE); -} +#endif				/* !ACPI_REDUCED_HARDWARE */  /*******************************************************************************   * @@ -727,8 +222,9 @@ u8 acpi_ut_valid_object_type(acpi_object_type type)   *   * 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.   *   ******************************************************************************/ @@ -746,6 +242,12 @@ acpi_status acpi_ut_init_globals(void)  		return_ACPI_STATUS(status);  	} +	/* Address Range lists */ + +	for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) { +		acpi_gbl_address_range_list[i] = NULL; +	} +  	/* Mutex locked flags */  	for (i = 0; i < ACPI_NUM_MUTEX; i++) { @@ -758,22 +260,39 @@ 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_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; @@ -791,20 +310,18 @@ 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;  	/* Hardware oriented */ @@ -823,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 d2906328535..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 - 2010, 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 c1b1c803ea9..5f56fc49021 100644 --- a/drivers/acpi/acpica/utinit.c +++ b/drivers/acpi/acpica/utinit.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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,27 @@ 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 b081cd46a15..dc6e96547f1 100644 --- a/drivers/acpi/acpica/utlock.c +++ b/drivers/acpi/acpica/utlock.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 49cf7b7fd81..d44dee6ee10 100644 --- a/drivers/acpi/acpica/utmath.c +++ b/drivers/acpi/acpica/utmath.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 c7d0e05ef5a..2e2bb14e109 100644 --- a/drivers/acpi/acpica/utmisc.c +++ b/drivers/acpi/acpica/utmisc.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 d9efa495b43..82717fff9ff 100644 --- a/drivers/acpi/acpica/utmutex.c +++ b/drivers/acpi/acpica/utmutex.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -81,12 +81,25 @@ 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 */ -	spin_lock_init(acpi_gbl_gpe_lock); -	spin_lock_init(acpi_gbl_hardware_lock); +	status = acpi_os_create_lock (&acpi_gbl_gpe_lock); +	if (ACPI_FAILURE (status)) { +		return_ACPI_STATUS (status); +	} + +	status = acpi_os_create_lock (&acpi_gbl_hardware_lock); +	if (ACPI_FAILURE (status)) { +		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); @@ -129,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 */ @@ -140,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   * @@ -169,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   * @@ -186,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   * @@ -219,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++) { @@ -276,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   * @@ -286,14 +302,10 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)  acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)  { -	acpi_thread_id this_thread_id; -  	ACPI_FUNCTION_NAME(ut_release_mutex); -	this_thread_id = acpi_os_get_thread_id(); -  	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n", -			  (u32)this_thread_id, +			  (u32)acpi_os_get_thread_id(),  			  acpi_ut_get_mutex_name(mutex_id)));  	if (mutex_id > ACPI_MAX_MUTEX) { @@ -316,13 +328,14 @@ 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++) { -			if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) { +			if (acpi_gbl_mutex_info[i].thread_id == +			    acpi_os_get_thread_id()) {  				if (i == mutex_id) {  					continue;  				} diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c index fd1fa2749ea..dfa9009bfc8 100644 --- a/drivers/acpi/acpica/utobject.c +++ b/drivers/acpi/acpica/utobject.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 18c59a85fdc..685766fc6ca 100644 --- a/drivers/acpi/acpica/utosi.c +++ b/drivers/acpi/acpica/utosi.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 7965919000b..14cb6c0c8be 100644 --- a/drivers/acpi/acpica/utresrc.c +++ b/drivers/acpi/acpica/utresrc.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -43,14 +43,15 @@  #include <acpi/acpi.h>  #include "accommon.h" -#include "amlresrc.h" +#include "acresrc.h"  #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 disasssembler and the debugger resource dump routines + * Used by both the disassembler and the debugger resource dump routines   */  const char *acpi_gbl_bm_decode[] = {  	"NotBusMaster", @@ -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[] = { @@ -154,6 +157,138 @@ const char *acpi_gbl_typ_decode[] = {  	"TypeF"  }; +const char *acpi_gbl_ppc_decode[] = { +	"PullDefault", +	"PullUp", +	"PullDown", +	"PullNone" +}; + +const char *acpi_gbl_ior_decode[] = { +	"IoRestrictionNone", +	"IoRestrictionInputOnly", +	"IoRestrictionOutputOnly", +	"IoRestrictionNoneAndPreserve" +}; + +const char *acpi_gbl_dts_decode[] = { +	"Width8bit", +	"Width16bit", +	"Width32bit", +	"Width64bit", +	"Width128bit", +	"Width256bit", +}; + +/* GPIO connection type */ + +const char *acpi_gbl_ct_decode[] = { +	"Interrupt", +	"I/O" +}; + +/* Serial bus type */ + +const char *acpi_gbl_sbt_decode[] = { +	"/* UNKNOWN serial bus type */", +	"I2C", +	"SPI", +	"UART" +}; + +/* I2C serial bus access mode */ + +const char *acpi_gbl_am_decode[] = { +	"AddressingMode7Bit", +	"AddressingMode10Bit" +}; + +/* I2C serial bus slave mode */ + +const char *acpi_gbl_sm_decode[] = { +	"ControllerInitiated", +	"DeviceInitiated" +}; + +/* SPI serial bus wire mode */ + +const char *acpi_gbl_wm_decode[] = { +	"FourWireMode", +	"ThreeWireMode" +}; + +/* SPI serial clock phase */ + +const char *acpi_gbl_cph_decode[] = { +	"ClockPhaseFirst", +	"ClockPhaseSecond" +}; + +/* SPI serial bus clock polarity */ + +const char *acpi_gbl_cpo_decode[] = { +	"ClockPolarityLow", +	"ClockPolarityHigh" +}; + +/* SPI serial bus device polarity */ + +const char *acpi_gbl_dp_decode[] = { +	"PolarityLow", +	"PolarityHigh" +}; + +/* UART serial bus endian */ + +const char *acpi_gbl_ed_decode[] = { +	"LittleEndian", +	"BigEndian" +}; + +/* UART serial bus bits per byte */ + +const char *acpi_gbl_bpb_decode[] = { +	"DataBitsFive", +	"DataBitsSix", +	"DataBitsSeven", +	"DataBitsEight", +	"DataBitsNine", +	"/* UNKNOWN Bits per byte */", +	"/* UNKNOWN Bits per byte */", +	"/* UNKNOWN Bits per byte */" +}; + +/* UART serial bus stop bits */ + +const char *acpi_gbl_sb_decode[] = { +	"StopBitsNone", +	"StopBitsOne", +	"StopBitsOnePlusHalf", +	"StopBitsTwo" +}; + +/* UART serial bus flow control */ + +const char *acpi_gbl_fc_decode[] = { +	"FlowControlNone", +	"FlowControlHardware", +	"FlowControlXON", +	"/* UNKNOWN flow control keyword */" +}; + +/* UART serial bus parity type */ + +const char *acpi_gbl_pt_decode[] = { +	"ParityTypeNone", +	"ParityTypeEven", +	"ParityTypeOdd", +	"ParityTypeMark", +	"ParityTypeSpace", +	"/* UNKNOWN parity keyword */", +	"/* UNKNOWN parity keyword */", +	"/* UNKNOWN parity keyword */" +}; +  #endif  /* @@ -173,7 +308,7 @@ const u8 acpi_gbl_resource_aml_sizes[] = {  	ACPI_AML_SIZE_SMALL(struct aml_resource_end_dependent),  	ACPI_AML_SIZE_SMALL(struct aml_resource_io),  	ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_io), -	0, +	ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_dma),  	0,  	0,  	0, @@ -193,7 +328,17 @@ const u8 acpi_gbl_resource_aml_sizes[] = {  	ACPI_AML_SIZE_LARGE(struct aml_resource_address16),  	ACPI_AML_SIZE_LARGE(struct aml_resource_extended_irq),  	ACPI_AML_SIZE_LARGE(struct aml_resource_address64), -	ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64) +	ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64), +	ACPI_AML_SIZE_LARGE(struct aml_resource_gpio), +	0, +	ACPI_AML_SIZE_LARGE(struct aml_resource_common_serialbus), +}; + +const u8 acpi_gbl_resource_aml_serial_bus_sizes[] = { +	0, +	ACPI_AML_SIZE_LARGE(struct aml_resource_i2c_serialbus), +	ACPI_AML_SIZE_LARGE(struct aml_resource_spi_serialbus), +	ACPI_AML_SIZE_LARGE(struct aml_resource_uart_serialbus),  };  /* @@ -209,44 +354,48 @@ static const u8 acpi_gbl_resource_types[] = {  	0,  	0,  	0, -	ACPI_SMALL_VARIABLE_LENGTH, -	ACPI_FIXED_LENGTH, -	ACPI_SMALL_VARIABLE_LENGTH, -	ACPI_FIXED_LENGTH, -	ACPI_FIXED_LENGTH, -	ACPI_FIXED_LENGTH, +	ACPI_SMALL_VARIABLE_LENGTH,	/* 04 IRQ */ +	ACPI_FIXED_LENGTH,	/* 05 DMA */ +	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,	/* 0A fixed_DMA */  	0,  	0,  	0, -	0, -	ACPI_VARIABLE_LENGTH, -	ACPI_FIXED_LENGTH, +	ACPI_VARIABLE_LENGTH,	/* 0E vendor_short */ +	ACPI_FIXED_LENGTH,	/* 0F end_tag */  	/* Large descriptors */  	0, -	ACPI_FIXED_LENGTH, -	ACPI_FIXED_LENGTH, +	ACPI_FIXED_LENGTH,	/* 01 Memory24 */ +	ACPI_FIXED_LENGTH,	/* 02 generic_register */ +	0, +	ACPI_VARIABLE_LENGTH,	/* 04 vendor_long */ +	ACPI_FIXED_LENGTH,	/* 05 Memory32 */ +	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,	/* 0A Qword* address */ +	ACPI_FIXED_LENGTH,	/* 0B Extended* address */ +	ACPI_VARIABLE_LENGTH,	/* 0C Gpio* */  	0, -	ACPI_VARIABLE_LENGTH, -	ACPI_FIXED_LENGTH, -	ACPI_FIXED_LENGTH, -	ACPI_VARIABLE_LENGTH, -	ACPI_VARIABLE_LENGTH, -	ACPI_VARIABLE_LENGTH, -	ACPI_VARIABLE_LENGTH, -	ACPI_FIXED_LENGTH +	ACPI_VARIABLE_LENGTH	/* 0E *serial_bus */  };  /*******************************************************************************   *   * 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   * @@ -256,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)  { @@ -265,6 +415,7 @@ acpi_ut_walk_aml_resources(u8 * aml,  	u8 resource_index;  	u32 length;  	u32 offset = 0; +	u8 end_tag[2] = { 0x79, 0x00 };  	ACPI_FUNCTION_TRACE(ut_walk_aml_resources); @@ -284,8 +435,13 @@ 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 +			 * may be bogus also. +			 */  			return_ACPI_STATUS(status);  		} @@ -300,7 +456,7 @@ acpi_ut_walk_aml_resources(u8 * aml,  			    user_function(aml, length, offset, resource_index,  					  context);  			if (ACPI_FAILURE(status)) { -				return (status); +				return_ACPI_STATUS(status);  			}  		} @@ -333,16 +489,30 @@ acpi_ut_walk_aml_resources(u8 * aml,  	/* Did not find an end_tag descriptor */ -	return (AE_AML_NO_RESOURCE_END_TAG); +	if (user_function) { + +		/* Insert an end_tag anyway. acpi_rs_get_list_length always leaves room */ + +		(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)) { +			return_ACPI_STATUS(status); +		} +	} + +	return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);  }  /*******************************************************************************   *   * 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   * @@ -352,8 +522,11 @@ 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;  	u8 resource_index;  	acpi_rs_length resource_length; @@ -375,7 +548,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)  		/* Verify the large resource type (name) against the max */  		if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) { -			return (AE_AML_INVALID_RESOURCE_TYPE); +			goto invalid_resource;  		}  		/* @@ -392,15 +565,17 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)  		    ((resource_type & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3);  	} -	/* Check validity of the resource type, zero indicates name is invalid */ - +	/* +	 * Check validity of the resource type, via acpi_gbl_resource_types. Zero +	 * indicates an invalid resource. +	 */  	if (!acpi_gbl_resource_types[resource_index]) { -		return (AE_AML_INVALID_RESOURCE_TYPE); +		goto invalid_resource;  	}  	/* -	 * 2) Validate the resource_length field. This ensures that the length -	 *    is at least reasonable, and guarantees that it is non-zero. +	 * Validate the resource_length field. This ensures that the length +	 * is at least reasonable, and guarantees that it is non-zero.  	 */  	resource_length = acpi_ut_get_resource_length(aml);  	minimum_resource_length = acpi_gbl_resource_aml_sizes[resource_index]; @@ -413,7 +588,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)  		/* Fixed length resource, length must match exactly */  		if (resource_length != minimum_resource_length) { -			return (AE_AML_BAD_RESOURCE_LENGTH); +			goto bad_resource_length;  		}  		break; @@ -422,7 +597,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)  		/* Variable length resource, length must be at least the minimum */  		if (resource_length < minimum_resource_length) { -			return (AE_AML_BAD_RESOURCE_LENGTH); +			goto bad_resource_length;  		}  		break; @@ -432,7 +607,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)  		if ((resource_length > minimum_resource_length) ||  		    (resource_length < (minimum_resource_length - 1))) { -			return (AE_AML_BAD_RESOURCE_LENGTH); +			goto bad_resource_length;  		}  		break; @@ -440,7 +615,25 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)  		/* Shouldn't happen (because of validation earlier), but be sure */ -		return (AE_AML_INVALID_RESOURCE_TYPE); +		goto invalid_resource; +	} + +	aml_resource = ACPI_CAST_PTR(union aml_resource, aml); +	if (resource_type == ACPI_RESOURCE_NAME_SERIAL_BUS) { + +		/* Validate the bus_type field */ + +		if ((aml_resource->common_serial_bus.type == 0) || +		    (aml_resource->common_serial_bus.type > +		     AML_RESOURCE_MAX_SERIALBUSTYPE)) { +			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); +		}  	}  	/* Optionally return the resource table index */ @@ -450,13 +643,33 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)  	}  	return (AE_OK); + +invalid_resource: + +	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: + +	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);  }  /*******************************************************************************   *   * 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) @@ -490,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   * @@ -530,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)   * @@ -555,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   * @@ -592,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; @@ -608,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 d35d109b8da..1cc97a752c1 100644 --- a/drivers/acpi/acpica/utstate.c +++ b/drivers/acpi/acpica/utstate.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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 1f484c9a688..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 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -41,277 +41,15 @@   * 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("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 @@ -323,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; @@ -367,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 @@ -403,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 @@ -470,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   * @@ -497,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) @@ -522,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);  } @@ -549,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 */ @@ -598,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); @@ -612,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 @@ -624,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; @@ -639,4 +425,157 @@ acpi_status acpi_install_interface_handler(acpi_interface_handler handler)  }  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 + * + * RETURN:      Count of the number of conflicts detected. + * + * DESCRIPTION: Check if the input address range overlaps any of the + *              ASL operation region address ranges. + * + ****************************************************************************/ + +u32 +acpi_check_address_range(acpi_adr_space_type space_id, +			 acpi_physical_address address, +			 acpi_size length, u8 warn) +{ +	u32 overlaps; +	acpi_status status; + +	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); +	if (ACPI_FAILURE(status)) { +		return (0); +	} + +	overlaps = acpi_ut_check_address_range(space_id, address, +					       (u32)length, warn); + +	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); +	return (overlaps); +} + +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 6f12e314fba..88ef77f3cf8 100644 --- a/drivers/acpi/acpica/utxferror.c +++ b/drivers/acpi/acpica/utxferror.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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,10 @@   * POSSIBILITY OF SUCH DAMAGES.   */ +#define EXPORT_ACPI_INTERFACES +  #include <acpi/acpi.h>  #include "accommon.h" -#include "acnamesp.h"  #define _COMPONENT          ACPI_UTILITIES  ACPI_MODULE_NAME("utxferror") @@ -51,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   * @@ -123,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   * @@ -158,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   * @@ -189,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   * @@ -217,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 new file mode 100644 index 00000000000..2a0f9e04d3a --- /dev/null +++ b/drivers/acpi/acpica/utxfmutex.c @@ -0,0 +1,187 @@ +/******************************************************************************* + * + * Module Name: utxfmutex - external AML mutex access 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("utxfmutex") + +/* Local prototypes */ +static acpi_status +acpi_ut_get_mutex_object(acpi_handle handle, +			 acpi_string pathname, +			 union acpi_operand_object **ret_obj); + +/******************************************************************************* + * + * FUNCTION:    acpi_ut_get_mutex_object + * + * PARAMETERS:  handle              - Mutex or prefix handle (optional) + *              pathname            - Mutex pathname (optional) + *              ret_obj             - Where the mutex object is returned + * + * RETURN:      Status + * + * DESCRIPTION: Get an AML mutex object. The mutex node is pointed to by + *              Handle:Pathname. Either Handle or Pathname can be NULL, but + *              not both. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_get_mutex_object(acpi_handle handle, +			 acpi_string pathname, +			 union acpi_operand_object **ret_obj) +{ +	struct acpi_namespace_node *mutex_node; +	union acpi_operand_object *mutex_obj; +	acpi_status status; + +	/* Parameter validation */ + +	if (!ret_obj || (!handle && !pathname)) { +		return (AE_BAD_PARAMETER); +	} + +	/* Get a the namespace node for the mutex */ + +	mutex_node = handle; +	if (pathname != NULL) { +		status = acpi_get_handle(handle, pathname, +					 ACPI_CAST_PTR(acpi_handle, +						       &mutex_node)); +		if (ACPI_FAILURE(status)) { +			return (status); +		} +	} + +	/* Ensure that we actually have a Mutex object */ + +	if (!mutex_node || (mutex_node->type != ACPI_TYPE_MUTEX)) { +		return (AE_TYPE); +	} + +	/* Get the low-level mutex object */ + +	mutex_obj = acpi_ns_get_attached_object(mutex_node); +	if (!mutex_obj) { +		return (AE_NULL_OBJECT); +	} + +	*ret_obj = mutex_obj; +	return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_acquire_mutex + * + * PARAMETERS:  handle              - Mutex or prefix handle (optional) + *              pathname            - Mutex pathname (optional) + *              timeout             - Max time to wait for the lock (millisec) + * + * RETURN:      Status + * + * DESCRIPTION: Acquire an AML mutex. This is a device driver interface to + *              AML mutex objects, and allows for transaction locking between + *              drivers and AML code. The mutex node is pointed to by + *              Handle:Pathname. Either Handle or Pathname can be NULL, but + *              not both. + * + ******************************************************************************/ + +acpi_status +acpi_acquire_mutex(acpi_handle handle, acpi_string pathname, u16 timeout) +{ +	acpi_status status; +	union acpi_operand_object *mutex_obj; + +	/* Get the low-level mutex associated with Handle:Pathname */ + +	status = acpi_ut_get_mutex_object(handle, pathname, &mutex_obj); +	if (ACPI_FAILURE(status)) { +		return (status); +	} + +	/* Acquire the OS mutex */ + +	status = acpi_os_acquire_mutex(mutex_obj->mutex.os_mutex, timeout); +	return (status); +} + +/******************************************************************************* + * + * FUNCTION:    acpi_release_mutex + * + * PARAMETERS:  handle              - Mutex or prefix handle (optional) + *              pathname            - Mutex pathname (optional) + * + * RETURN:      Status + * + * DESCRIPTION: Release an AML mutex. This is a device driver interface to + *              AML mutex objects, and allows for transaction locking between + *              drivers and AML code. The mutex node is pointed to by + *              Handle:Pathname. Either Handle or Pathname can be NULL, but + *              not both. + * + ******************************************************************************/ + +acpi_status acpi_release_mutex(acpi_handle handle, acpi_string pathname) +{ +	acpi_status status; +	union acpi_operand_object *mutex_obj; + +	/* Get the low-level mutex associated with Handle:Pathname */ + +	status = acpi_ut_get_mutex_object(handle, pathname, &mutex_obj); +	if (ACPI_FAILURE(status)) { +		return (status); +	} + +	/* Release the OS mutex */ + +	acpi_os_release_mutex(mutex_obj->mutex.os_mutex); +	return (AE_OK); +}  | 
