summaryrefslogtreecommitdiff
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/Kconfig16
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/acpi_pad.c13
-rw-r--r--drivers/acpi/acpica/Makefile6
-rw-r--r--drivers/acpi/acpica/acconfig.h1
-rw-r--r--drivers/acpi/acpica/acdispat.h38
-rw-r--r--drivers/acpi/acpica/acevents.h17
-rw-r--r--drivers/acpi/acpica/acglobal.h17
-rw-r--r--drivers/acpi/acpica/aclocal.h19
-rw-r--r--drivers/acpi/acpica/amlcode.h15
-rw-r--r--drivers/acpi/acpica/dsargs.c391
-rw-r--r--drivers/acpi/acpica/dscontrol.c410
-rw-r--r--drivers/acpi/acpica/dsopcode.c725
-rw-r--r--drivers/acpi/acpica/dswload.c672
-rw-r--r--drivers/acpi/acpica/dswload2.c720
-rw-r--r--drivers/acpi/acpica/evglock.c335
-rw-r--r--drivers/acpi/acpica/evgpe.c9
-rw-r--r--drivers/acpi/acpica/evmisc.c303
-rw-r--r--drivers/acpi/acpica/evregion.c123
-rw-r--r--drivers/acpi/acpica/evrgnini.c2
-rw-r--r--drivers/acpi/acpica/evxfregn.c31
-rw-r--r--drivers/acpi/acpica/excreate.c3
-rw-r--r--drivers/acpi/acpica/exfldio.c4
-rw-r--r--drivers/acpi/acpica/hwxface.c10
-rw-r--r--drivers/acpi/acpica/nsrepair.c13
-rw-r--r--drivers/acpi/acpica/tbfadt.c5
-rw-r--r--drivers/acpi/acpica/utdecode.c549
-rw-r--r--drivers/acpi/acpica/utglobal.c484
-rw-r--r--drivers/acpi/acpica/utmutex.c12
-rw-r--r--drivers/acpi/apei/Kconfig8
-rw-r--r--drivers/acpi/apei/cper.c18
-rw-r--r--drivers/acpi/apei/erst-dbg.c24
-rw-r--r--drivers/acpi/apei/erst.c371
-rw-r--r--drivers/acpi/apei/ghes.c2
-rw-r--r--drivers/acpi/battery.c22
-rw-r--r--drivers/acpi/bus.c25
-rw-r--r--drivers/acpi/button.c174
-rw-r--r--drivers/acpi/custom_method.c100
-rw-r--r--drivers/acpi/debugfs.c92
-rw-r--r--drivers/acpi/ec.c11
-rw-r--r--drivers/acpi/ec_sys.c4
-rw-r--r--drivers/acpi/internal.h6
-rw-r--r--drivers/acpi/numa.c9
-rw-r--r--drivers/acpi/nvs.c22
-rw-r--r--drivers/acpi/osl.c178
-rw-r--r--drivers/acpi/pci_link.c30
-rw-r--r--drivers/acpi/pci_root.c11
-rw-r--r--drivers/acpi/processor_core.c29
-rw-r--r--drivers/acpi/processor_driver.c4
-rw-r--r--drivers/acpi/processor_throttling.c2
-rw-r--r--drivers/acpi/reboot.c14
-rw-r--r--drivers/acpi/scan.c5
-rw-r--r--drivers/acpi/sleep.c33
-rw-r--r--drivers/acpi/sysfs.c8
-rw-r--r--drivers/acpi/video.c26
55 files changed, 3469 insertions, 2703 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 2aa042a5da6d..d918e130bef3 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -7,7 +7,6 @@ menuconfig ACPI
depends on !IA64_HP_SIM
depends on IA64 || X86
depends on PCI
- depends on PM
select PNP
default y
help
@@ -381,6 +380,21 @@ config ACPI_HED
which is used to report some hardware errors notified via
SCI, mainly the corrected errors.
+config ACPI_CUSTOM_METHOD
+ tristate "Allow ACPI methods to be inserted/replaced at run time"
+ depends on DEBUG_FS
+ default n
+ help
+ This debug facility allows ACPI AML methods to me inserted and/or
+ replaced without rebooting the system. For details refer to:
+ Documentation/acpi/method-customizing.txt.
+
+ NOTE: This option is security sensitive, because it allows arbitrary
+ kernel memory to be written to by root (uid=0) users, allowing them
+ to bypass certain security measures (e.g. if root is not allowed to
+ load additional kernel modules after boot, this feature may be used
+ to override that restriction).
+
source "drivers/acpi/apei/Kconfig"
endif # ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index d113fa5100b2..cba0b2334b9b 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_ACPI_SBS) += sbs.o
obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o
obj-$(CONFIG_ACPI_HED) += hed.o
obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o
+obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
# processor has its own "processor." module_param namespace
processor-y := processor_driver.o processor_throttling.o
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index 6afceb3d4034..a43fa1a57d57 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -298,7 +298,7 @@ static ssize_t acpi_pad_rrtime_store(struct device *dev,
static ssize_t acpi_pad_rrtime_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return scnprintf(buf, PAGE_SIZE, "%d", round_robin_time);
+ return scnprintf(buf, PAGE_SIZE, "%d\n", round_robin_time);
}
static DEVICE_ATTR(rrtime, S_IRUGO|S_IWUSR,
acpi_pad_rrtime_show,
@@ -321,7 +321,7 @@ static ssize_t acpi_pad_idlepct_store(struct device *dev,
static ssize_t acpi_pad_idlepct_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return scnprintf(buf, PAGE_SIZE, "%d", idle_pct);
+ return scnprintf(buf, PAGE_SIZE, "%d\n", idle_pct);
}
static DEVICE_ATTR(idlepct, S_IRUGO|S_IWUSR,
acpi_pad_idlepct_show,
@@ -342,8 +342,11 @@ static ssize_t acpi_pad_idlecpus_store(struct device *dev,
static ssize_t acpi_pad_idlecpus_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return cpumask_scnprintf(buf, PAGE_SIZE,
- to_cpumask(pad_busy_cpus_bits));
+ int n = 0;
+ n = cpumask_scnprintf(buf, PAGE_SIZE-2, to_cpumask(pad_busy_cpus_bits));
+ buf[n++] = '\n';
+ buf[n] = '\0';
+ return n;
}
static DEVICE_ATTR(idlecpus, S_IRUGO|S_IWUSR,
acpi_pad_idlecpus_show,
@@ -453,7 +456,7 @@ static void acpi_pad_notify(acpi_handle handle, u32 event,
dev_name(&device->dev), event, 0);
break;
default:
- printk(KERN_WARNING"Unsupported event [0x%x]\n", event);
+ printk(KERN_WARNING "Unsupported event [0x%x]\n", event);
break;
}
}
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index eec2eadd2431..301bd2d388ad 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -10,11 +10,11 @@ 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
+ dsinit.o dsargs.o dscontrol.o dswload2.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 evxfgpe.o
+ evgpe.o evgpeblk.o evgpeinit.o evgpeutil.o evxfgpe.o evglock.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\
@@ -45,4 +45,4 @@ acpi-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.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
+ utosi.o utxferror.o utdecode.o
diff --git a/drivers/acpi/acpica/acconfig.h b/drivers/acpi/acpica/acconfig.h
index ab87396c2c07..bc533dde16c4 100644
--- a/drivers/acpi/acpica/acconfig.h
+++ b/drivers/acpi/acpica/acconfig.h
@@ -187,7 +187,6 @@
/* Operation regions */
-#define ACPI_NUM_PREDEFINED_REGIONS 9
#define ACPI_USER_REGION_BEGIN 0x80
/* Maximum space_ids for Operation Regions */
diff --git a/drivers/acpi/acpica/acdispat.h b/drivers/acpi/acpica/acdispat.h
index 666271b65418..2d1b7ffa377a 100644
--- a/drivers/acpi/acpica/acdispat.h
+++ b/drivers/acpi/acpica/acdispat.h
@@ -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,26 @@ 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, pass 1 namespace load callbacks
*/
acpi_status
+acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number);
+
+acpi_status
acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state,
union acpi_parse_object **out_op);
acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state);
+/*
+ * dsload - Parser/Interpreter interface, pass 2 namespace load callbacks
+ */
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)
*/
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index 41d247daf461..bea3b4899183 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -58,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
@@ -71,6 +65,17 @@ 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_status acpi_ev_acquire_global_lock(u16 timeout);
+
+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);
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 82a1bd283db8..73863d86f022 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -214,24 +214,23 @@ ACPI_EXTERN 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 acpi_spinlock acpi_gbl_global_lock_pending_lock;
ACPI_EXTERN u16 acpi_gbl_global_lock_handle;
ACPI_EXTERN u8 acpi_gbl_global_lock_acquired;
ACPI_EXTERN u8 acpi_gbl_global_lock_present;
+ACPI_EXTERN u8 acpi_gbl_global_lock_pending;
/*
* 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 */
-ACPI_EXTERN spinlock_t _acpi_ev_global_lock_pending_lock; /* For global lock */
-#define acpi_gbl_gpe_lock &_acpi_gbl_gpe_lock
-#define acpi_gbl_hardware_lock &_acpi_gbl_hardware_lock
-#define acpi_ev_global_lock_pending_lock &_acpi_ev_global_lock_pending_lock
+ACPI_EXTERN acpi_spinlock acpi_gbl_gpe_lock; /* For GPE data structs and registers */
+ACPI_EXTERN acpi_spinlock acpi_gbl_hardware_lock; /* For ACPI H/W except GPE registers */
/*****************************************************************************
*
@@ -273,6 +272,10 @@ 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;
+/* Initialization sequencing */
+
+ACPI_EXTERN u8 acpi_gbl_reg_methods_executed;
+
/* Misc */
ACPI_EXTERN u32 acpi_gbl_original_mode;
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index edc25867ad9d..c7f743ca395b 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -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 {
diff --git a/drivers/acpi/acpica/amlcode.h b/drivers/acpi/acpica/amlcode.h
index f4f0998d3967..1077f17859ed 100644
--- a/drivers/acpi/acpica/amlcode.h
+++ b/drivers/acpi/acpica/amlcode.h
@@ -394,21 +394,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 {
diff --git a/drivers/acpi/acpica/dsargs.c b/drivers/acpi/acpica/dsargs.c
new file mode 100644
index 000000000000..8c7b99728aa2
--- /dev/null
+++ b/drivers/acpi/acpica/dsargs.c
@@ -0,0 +1,391 @@
+/******************************************************************************
+ *
+ * Module Name: dsargs - Support for execution of dynamic arguments for static
+ * objects (regions, fields, buffer fields, etc.)
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2011, 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);
+ 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);
+ return_ACPI_STATUS(status);
+}
diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c
new file mode 100644
index 000000000000..26c49fff58da
--- /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 - 2011, 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/dsopcode.c b/drivers/acpi/acpica/dsopcode.c
index bbecf293aeeb..c627a288e027 100644
--- a/drivers/acpi/acpica/dsopcode.c
+++ b/drivers/acpi/acpica/dsopcode.c
@@ -1,7 +1,6 @@
/******************************************************************************
*
- * Module Name: dsopcode - Dispatcher Op Region support and handling of
- * "control" opcodes
+ * Module Name: dsopcode - Dispatcher suport for regions and fields
*
*****************************************************************************/
@@ -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
@@ -826,8 +465,9 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
*
* 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.
*
******************************************************************************/
@@ -1114,360 +754,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/dswload.c b/drivers/acpi/acpica/dswload.c
index 52566ff5e903..324acec1179a 100644
--- a/drivers/acpi/acpica/dswload.c
+++ b/drivers/acpi/acpica/dswload.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Module Name: dswload - Dispatcher namespace load callbacks
+ * Module Name: dswload - Dispatcher first pass namespace load callbacks
*
*****************************************************************************/
@@ -48,7 +48,6 @@
#include "acdispat.h"
#include "acinterp.h"
#include "acnamesp.h"
-#include "acevents.h"
#ifdef ACPI_ASL_COMPILER
#include <acpi/acdisasm.h>
@@ -451,7 +450,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 +536,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 000000000000..976318138c56
--- /dev/null
+++ b/drivers/acpi/acpica/dswload2.c
@@ -0,0 +1,720 @@
+/******************************************************************************
+ *
+ * Module Name: dswload2 - Dispatcher second pass namespace load callbacks
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2011, 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\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 = 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 (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/evglock.c b/drivers/acpi/acpica/evglock.c
new file mode 100644
index 000000000000..56a562a1e5d7
--- /dev/null
+++ b/drivers/acpi/acpica/evglock.c
@@ -0,0 +1,335 @@
+/******************************************************************************
+ *
+ * Module Name: evglock - Global Lock support
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2011, 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")
+
+/* 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);
+
+ /* 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);
+
+ 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);
+}
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index f4725212eb48..65c79add3b19 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -373,6 +373,15 @@ 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)) {
+ continue;
+ }
+
/* Read the Status Register */
status =
diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c
index 7dc80946f7bd..d0b331844427 100644
--- a/drivers/acpi/acpica/evmisc.c
+++ b/drivers/acpi/acpica/evmisc.c
@@ -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,10 +52,6 @@ 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
@@ -275,304 +270,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)
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. If there's a thread waiting for
- * the global lock, signal it.
- *
- * 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 u8 acpi_ev_global_lock_pending;
-
-static u32 acpi_ev_global_lock_handler(void *context)
-{
- acpi_status status;
- acpi_cpu_flags flags;
-
- flags = acpi_os_acquire_lock(acpi_ev_global_lock_pending_lock);
-
- if (!acpi_ev_global_lock_pending) {
- goto out;
- }
-
- /* Send a unit to the semaphore */
-
- 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_ev_global_lock_pending = FALSE;
-
- out:
- acpi_os_release_lock(acpi_ev_global_lock_pending_lock, flags);
-
- 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_cpu_flags flags;
- 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);
- }
-
- flags = acpi_os_acquire_lock(acpi_ev_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;
- }
-
- acpi_ev_global_lock_pending = TRUE;
-
- acpi_os_release_lock(acpi_ev_global_lock_pending_lock, flags);
-
- /*
- * Did not get the lock. The pending bit was set above, and we
- * must 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);
-
- flags = acpi_os_acquire_lock(acpi_ev_global_lock_pending_lock);
-
- } while (ACPI_SUCCESS(status));
-
- acpi_ev_global_lock_pending = FALSE;
-
- acpi_os_release_lock(acpi_ev_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);
- }
-
- 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);
-}
-
/******************************************************************************
*
* FUNCTION: acpi_ev_terminate
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c
index 785a5ee64585..f0edf5c43c03 100644
--- a/drivers/acpi/acpica/evregion.c
+++ b/drivers/acpi/acpica/evregion.c
@@ -55,6 +55,8 @@ static u8
acpi_ev_has_default_handler(struct acpi_namespace_node *node,
acpi_adr_space_type space_id);
+static void acpi_ev_orphan_ec_reg_method(void);
+
static acpi_status
acpi_ev_reg_run(acpi_handle obj_handle,
u32 level, void *context, void **return_value);
@@ -231,6 +233,8 @@ acpi_status acpi_ev_initialize_op_regions(void)
}
}
+ acpi_gbl_reg_methods_executed = TRUE;
+
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_ACPI_STATUS(status);
}
@@ -559,7 +563,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]",
@@ -1060,6 +1066,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();
+ }
+
return_ACPI_STATUS(status);
}
@@ -1118,6 +1130,113 @@ 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: None
+ *
+ * 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_ID that appears
+ * within the ECDT. Otherwise, we would need to perform a time-
+ * consuming namespace walk, executing _HID methods to find the
+ * EC device.
+ *
+ ******************************************************************************/
+
+static void acpi_ev_orphan_ec_reg_method(void)
+{
+ struct acpi_table_ecdt *table;
+ acpi_status status;
+ struct acpi_object_list args;
+ union acpi_object objects[2];
+ struct acpi_namespace_node *ec_device_node;
+ struct acpi_namespace_node *reg_method;
+ struct acpi_namespace_node *next_node;
+
+ ACPI_FUNCTION_TRACE(ev_orphan_ec_reg_method);
+
+ /* Get the ECDT (if present in system) */
+
+ status = acpi_get_table(ACPI_SIG_ECDT, 0,
+ ACPI_CAST_INDIRECT_PTR(struct acpi_table_header,
+ &table));
+ if (ACPI_FAILURE(status)) {
+ return_VOID;
+ }
+
+ /* We need a valid EC_ID string */
+
+ if (!(*table->id)) {
+ return_VOID;
+ }
+
+ /* Namespace is currently locked, must release */
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+
+ /* Get a handle to the EC device referenced in the ECDT */
+
+ status = acpi_get_handle(NULL,
+ ACPI_CAST_PTR(char, table->id),
+ ACPI_CAST_PTR(acpi_handle, &ec_device_node));
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ /* Get a handle to a _REG method immediately under the EC device */
+
+ status = acpi_get_handle(ec_device_node,
+ METHOD_NAME__REG, ACPI_CAST_PTR(acpi_handle,
+ &reg_method));
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ /*
+ * 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 EC space ID argument.
+ */
+ next_node = acpi_ns_get_next_node(ec_device_node, NULL);
+ while (next_node) {
+ if ((next_node->type == ACPI_TYPE_REGION) &&
+ (next_node->object) &&
+ (next_node->object->region.space_id == ACPI_ADR_SPACE_EC)) {
+ goto exit; /* Do not execute _REG */
+ }
+ next_node = acpi_ns_get_next_node(ec_device_node, next_node);
+ }
+
+ /* Evaluate the _REG(EC,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 9659cee6093e..55a5d35ef34a 100644
--- a/drivers/acpi/acpica/evrgnini.c
+++ b/drivers/acpi/acpica/evrgnini.c
@@ -637,7 +637,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/evxfregn.c b/drivers/acpi/acpica/evxfregn.c
index eb7386763712..00cd95692a91 100644
--- a/drivers/acpi/acpica/evxfregn.c
+++ b/drivers/acpi/acpica/evxfregn.c
@@ -110,6 +110,37 @@ 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);
diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c
index e7b372d17667..110711afada8 100644
--- a/drivers/acpi/acpica/excreate.c
+++ b/drivers/acpi/acpica/excreate.c
@@ -305,7 +305,8 @@ acpi_ex_create_region(u8 * aml_start,
* range
*/
if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) &&
- (region_space < ACPI_USER_REGION_BEGIN)) {
+ (region_space < ACPI_USER_REGION_BEGIN) &&
+ (region_space != ACPI_ADR_SPACE_DATA_TABLE)) {
ACPI_ERROR((AE_INFO, "Invalid AddressSpace type 0x%X",
region_space));
return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c
index 6c79c29f082d..f915a7f3f921 100644
--- a/drivers/acpi/acpica/exfldio.c
+++ b/drivers/acpi/acpica/exfldio.c
@@ -280,13 +280,13 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
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));
diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c
index 6f98d210e71c..f75f81ad15c9 100644
--- a/drivers/acpi/acpica/hwxface.c
+++ b/drivers/acpi/acpica/hwxface.c
@@ -80,14 +80,14 @@ acpi_status acpi_reset(void)
if (reset_reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
/*
- * For I/O space, write directly to the OSL. This bypasses the port
- * validation mechanism, which may block a valid write to the reset
- * register.
+ * For I/O space, write directly to the OSL. This
+ * bypasses the port validation mechanism, which may
+ * block a valid write to the reset register. Spec
+ * section 4.7.3.6 requires register width to be 8.
*/
status =
acpi_os_write_port((acpi_io_address) reset_reg->address,
- acpi_gbl_FADT.reset_value,
- reset_reg->bit_width);
+ acpi_gbl_FADT.reset_value, 8);
} else {
/* Write the reset value to the reset register */
diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c
index 1d76ac85b5e7..ac7b854b0bd7 100644
--- a/drivers/acpi/acpica/nsrepair.c
+++ b/drivers/acpi/acpica/nsrepair.c
@@ -74,7 +74,6 @@ ACPI_MODULE_NAME("nsrepair")
*
* Additional possible repairs:
*
- * Optional/unnecessary NULL package elements removed
* Required package elements that are NULL replaced by Integer/String/Buffer
* Incorrect standalone package wrapped with required outer package
*
@@ -623,16 +622,12 @@ 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 sub-packages.
*/
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:
@@ -642,6 +637,8 @@ acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
break;
default:
+ case ACPI_PTYPE1_FIXED:
+ case ACPI_PTYPE1_OPTION:
return;
}
diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c
index 428d44e2d162..6f5588e62c0a 100644
--- a/drivers/acpi/acpica/tbfadt.c
+++ b/drivers/acpi/acpica/tbfadt.c
@@ -384,8 +384,11 @@ static void acpi_tb_convert_fadt(void)
*
* 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;
diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c
new file mode 100644
index 000000000000..97cb36f85ce9
--- /dev/null
+++ b/drivers/acpi/acpica/utdecode.c
@@ -0,0 +1,549 @@
+/******************************************************************************
+ *
+ * Module Name: utdecode - Utility decoding routines (value-to-string)
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2011, 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")
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_format_exception
+ *
+ * PARAMETERS: Status - The acpi_status code to be formatted
+ *
+ * RETURN: A string containing the exception text. A valid pointer is
+ * always returned.
+ *
+ * DESCRIPTION: This function translates an ACPI exception into an ASCII string
+ * It is here instead of utxface.c so it is always present.
+ *
+ ******************************************************************************/
+const char *acpi_format_exception(acpi_status status)
+{
+ const char *exception = NULL;
+
+ ACPI_FUNCTION_ENTRY();
+
+ exception = acpi_ut_validate_exception(status);
+ if (!exception) {
+
+ /* Exception code was not recognized */
+
+ ACPI_ERROR((AE_INFO,
+ "Unknown exception code: 0x%8.8X", status));
+
+ exception = "UNKNOWN_STATUS_CODE";
+ }
+
+ return (ACPI_CAST_PTR(const char, exception));
+}
+
+ACPI_EXPORT_SYMBOL(acpi_format_exception)
+
+/*
+ * Properties of the ACPI Object Types, both internal and external.
+ * The table is indexed by values of acpi_object_type
+ */
+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",
+ "SystemIO",
+ "PCI_Config",
+ "EmbeddedControl",
+ "SMBus",
+ "SystemCMOS",
+ "PCIBARTarget",
+ "IPMI"
+};
+
+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_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);
+}
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c
index 97dd9bbf055a..833a38a9c905 100644
--- a/drivers/acpi/acpica/utglobal.c
+++ b/drivers/acpi/acpica/utglobal.c
@@ -45,7 +45,6 @@
#include <acpi/acpi.h>
#include "accommon.h"
-#include "acnamesp.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utglobal")
@@ -107,43 +106,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 +139,6 @@ 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]);
-}
-
/******************************************************************************
*
* Event and Hardware globals
@@ -341,386 +238,6 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] =
/*******************************************************************************
*
- * 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);
-}
-
-/*******************************************************************************
- *
* FUNCTION: acpi_ut_init_globals
*
* PARAMETERS: None
@@ -806,6 +323,7 @@ acpi_status acpi_ut_init_globals(void)
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 */
diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c
index a946c689f03b..7d797e2baecd 100644
--- a/drivers/acpi/acpica/utmutex.c
+++ b/drivers/acpi/acpica/utmutex.c
@@ -83,9 +83,15 @@ acpi_status acpi_ut_mutex_initialize(void)
/* Create the spinlocks for use at interrupt level */
- spin_lock_init(acpi_gbl_gpe_lock);
- spin_lock_init(acpi_gbl_hardware_lock);
- spin_lock_init(acpi_ev_global_lock_pending_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);
+ }
/* Mutex for _OSI support */
status = acpi_os_create_mutex(&acpi_gbl_osi_mutex);
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig
index fca34ccfd294..66a03caa2ad9 100644
--- a/drivers/acpi/apei/Kconfig
+++ b/drivers/acpi/apei/Kconfig
@@ -1,5 +1,6 @@
config ACPI_APEI
bool "ACPI Platform Error Interface (APEI)"
+ select PSTORE
depends on X86
help
APEI allows to report errors (for example from the chipset)
@@ -21,6 +22,13 @@ config ACPI_APEI_GHES
by firmware to produce more valuable hardware error
information for Linux.
+config ACPI_APEI_PCIEAER
+ bool "APEI PCIe AER logging/recovering support"
+ depends on ACPI_APEI && PCIEAER
+ help
+ PCIe AER errors may be reported via APEI firmware first mode.
+ Turn on this option to enable the corresponding support.
+
config ACPI_APEI_EINJ
tristate "APEI Error INJection (EINJ)"
depends on ACPI_APEI && DEBUG_FS
diff --git a/drivers/acpi/apei/cper.c b/drivers/acpi/apei/cper.c
index 31464a006d76..5d4189464d63 100644
--- a/drivers/acpi/apei/cper.c
+++ b/drivers/acpi/apei/cper.c
@@ -29,6 +29,7 @@
#include <linux/time.h>
#include <linux/cper.h>
#include <linux/acpi.h>
+#include <linux/aer.h>
/*
* CPER record ID need to be unique even after reboot, because record
@@ -70,8 +71,8 @@ static const char *cper_severity_str(unsigned int severity)
* If the output length is longer than 80, multiple line will be
* printed, with @pfx is printed at the beginning of each line.
*/
-static void cper_print_bits(const char *pfx, unsigned int bits,
- const char *strs[], unsigned int strs_size)
+void cper_print_bits(const char *pfx, unsigned int bits,
+ const char *strs[], unsigned int strs_size)
{
int i, len = 0;
const char *str;
@@ -81,6 +82,8 @@ static void cper_print_bits(const char *pfx, unsigned int bits,
if (!(bits & (1U << i)))
continue;
str = strs[i];
+ if (!str)
+ continue;
if (len && len + strlen(str) + 2 > 80) {
printk("%s\n", buf);
len = 0;
@@ -243,7 +246,8 @@ static const char *cper_pcie_port_type_strs[] = {
"root complex event collector",
};
-static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie)
+static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
+ const struct acpi_hest_generic_data *gdata)
{
if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE)
printk("%s""port_type: %d, %s\n", pfx, pcie->port_type,
@@ -276,6 +280,12 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie)
printk(
"%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n",
pfx, pcie->bridge.secondary_status, pcie->bridge.control);
+#ifdef CONFIG_ACPI_APEI_PCIEAER
+ if (pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) {
+ struct aer_capability_regs *aer_regs = (void *)pcie->aer_info;
+ cper_print_aer(pfx, gdata->error_severity, aer_regs);
+ }
+#endif
}
static const char *apei_estatus_section_flag_strs[] = {
@@ -322,7 +332,7 @@ static void apei_estatus_print_section(
struct cper_sec_pcie *pcie = (void *)(gdata + 1);
printk("%s""section_type: PCIe error\n", pfx);
if (gdata->error_data_length >= sizeof(*pcie))
- cper_print_pcie(pfx, pcie);
+ cper_print_pcie(pfx, pcie, gdata);
else
goto err_section_too_small;
} else
diff --git a/drivers/acpi/apei/erst-dbg.c b/drivers/acpi/apei/erst-dbg.c
index de73caf3cebc..a4cfb64c86a1 100644
--- a/drivers/acpi/apei/erst-dbg.c
+++ b/drivers/acpi/apei/erst-dbg.c
@@ -43,12 +43,27 @@ static DEFINE_MUTEX(erst_dbg_mutex);
static int erst_dbg_open(struct inode *inode, struct file *file)
{
+ int rc, *pos;
+
if (erst_disable)
return -ENODEV;
+ pos = (int *)&file->private_data;
+
+ rc = erst_get_record_id_begin(pos);
+ if (rc)
+ return rc;
+
return nonseekable_open(inode, file);
}
+static int erst_dbg_release(struct inode *inode, struct file *file)
+{
+ erst_get_record_id_end();
+
+ return 0;
+}
+
static long erst_dbg_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
{
int rc;
@@ -79,18 +94,20 @@ static long erst_dbg_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
static ssize_t erst_dbg_read(struct file *filp, char __user *ubuf,
size_t usize, loff_t *off)
{
- int rc;
+ int rc, *pos;
ssize_t len = 0;
u64 id;
- if (*off != 0)
+ if (*off)
return -EINVAL;
if (mutex_lock_interruptible(&erst_dbg_mutex) != 0)
return -EINTR;
+ pos = (int *)&filp->private_data;
+
retry_next:
- rc = erst_get_next_record_id(&id);
+ rc = erst_get_record_id_next(pos, &id);
if (rc)
goto out;
/* no more record */
@@ -181,6 +198,7 @@ out:
static const struct file_operations erst_dbg_ops = {
.owner = THIS_MODULE,
.open = erst_dbg_open,
+ .release = erst_dbg_release,
.read = erst_dbg_read,
.write = erst_dbg_write,
.unlocked_ioctl = erst_dbg_ioctl,
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index cf6db6b7662a..d6cb0ff6988e 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -34,6 +34,7 @@
#include <linux/cper.h>
#include <linux/nmi.h>
#include <linux/hardirq.h>
+#include <linux/pstore.h>
#include <acpi/apei.h>
#include "apei-internal.h"
@@ -429,6 +430,22 @@ ssize_t erst_get_record_count(void)
}
EXPORT_SYMBOL_GPL(erst_get_record_count);
+#define ERST_RECORD_ID_CACHE_SIZE_MIN 16
+#define ERST_RECORD_ID_CACHE_SIZE_MAX 1024
+
+struct erst_record_id_cache {
+ struct mutex lock;
+ u64 *entries;
+ int len;
+ int size;
+ int refcount;
+};
+
+static struct erst_record_id_cache erst_record_id_cache = {
+ .lock = __MUTEX_INITIALIZER(erst_record_id_cache.lock),
+ .refcount = 0,
+};
+
static int __erst_get_next_record_id(u64 *record_id)
{
struct apei_exec_context ctx;
@@ -443,26 +460,179 @@ static int __erst_get_next_record_id(u64 *record_id)
return 0;
}
+int erst_get_record_id_begin(int *pos)
+{
+ int rc;
+
+ if (erst_disable)
+ return -ENODEV;
+
+ rc = mutex_lock_interruptible(&erst_record_id_cache.lock);
+ if (rc)
+ return rc;
+ erst_record_id_cache.refcount++;
+ mutex_unlock(&erst_record_id_cache.lock);
+
+ *pos = 0;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(erst_get_record_id_begin);
+
+/* erst_record_id_cache.lock must be held by caller */
+static int __erst_record_id_cache_add_one(void)
+{
+ u64 id, prev_id, first_id;
+ int i, rc;
+ u64 *entries;
+ unsigned long flags;
+
+ id = prev_id = first_id = APEI_ERST_INVALID_RECORD_ID;
+retry:
+ raw_spin_lock_irqsave(&erst_lock, flags);
+ rc = __erst_get_next_record_id(&id);
+ raw_spin_unlock_irqrestore(&erst_lock, flags);
+ if (rc == -ENOENT)
+ return 0;
+ if (rc)
+ return rc;
+ if (id == APEI_ERST_INVALID_RECORD_ID)
+ return 0;
+ /* can not skip current ID, or loop back to first ID */
+ if (id == prev_id || id == first_id)
+ return 0;
+ if (first_id == APEI_ERST_INVALID_RECORD_ID)
+ first_id = id;
+ prev_id = id;
+
+ entries = erst_record_id_cache.entries;
+ for (i = 0; i < erst_record_id_cache.len; i++) {
+ if (entries[i] == id)
+ break;
+ }
+ /* record id already in cache, try next */
+ if (i < erst_record_id_cache.len)
+ goto retry;
+ if (erst_record_id_cache.len >= erst_record_id_cache.size) {
+ int new_size, alloc_size;
+ u64 *new_entries;
+
+ new_size = erst_record_id_cache.size * 2;
+ new_size = clamp_val(new_size, ERST_RECORD_ID_CACHE_SIZE_MIN,
+ ERST_RECORD_ID_CACHE_SIZE_MAX);
+ if (new_size <= erst_record_id_cache.size) {
+ if (printk_ratelimit())
+ pr_warning(FW_WARN ERST_PFX
+ "too many record ID!\n");
+ return 0;
+ }
+ alloc_size = new_size * sizeof(entries[0]);
+ if (alloc_size < PAGE_SIZE)
+ new_entries = kmalloc(alloc_size, GFP_KERNEL);
+ else
+ new_entries = vmalloc(alloc_size);
+ if (!new_entries)
+ return -ENOMEM;
+ memcpy(new_entries, entries,
+ erst_record_id_cache.len * sizeof(entries[0]));
+ if (erst_record_id_cache.size < PAGE_SIZE)
+ kfree(entries);
+ else
+ vfree(entries);
+ erst_record_id_cache.entries = entries = new_entries;
+ erst_record_id_cache.size = new_size;
+ }
+ entries[i] = id;
+ erst_record_id_cache.len++;
+
+ return 1;
+}
+
/*
* Get the record ID of an existing error record on the persistent
* storage. If there is no error record on the persistent storage, the
* returned record_id is APEI_ERST_INVALID_RECORD_ID.
*/
-int erst_get_next_record_id(u64 *record_id)
+int erst_get_record_id_next(int *pos, u64 *record_id)
{
- int rc;
- unsigned long flags;
+ int rc = 0;
+ u64 *entries;
if (erst_disable)
return -ENODEV;
- raw_spin_lock_irqsave(&erst_lock, flags);
- rc = __erst_get_next_record_id(record_id);
- raw_spin_unlock_irqrestore(&erst_lock, flags);
+ /* must be enclosed by erst_get_record_id_begin/end */
+ BUG_ON(!erst_record_id_cache.refcount);
+ BUG_ON(*pos < 0 || *pos > erst_record_id_cache.len);
+
+ mutex_lock(&erst_record_id_cache.lock);
+ entries = erst_record_id_cache.entries;
+ for (; *pos < erst_record_id_cache.len; (*pos)++)
+ if (entries[*pos] != APEI_ERST_INVALID_RECORD_ID)
+ break;
+ /* found next record id in cache */
+ if (*pos < erst_record_id_cache.len) {
+ *record_id = entries[*pos];
+ (*pos)++;
+ goto out_unlock;
+ }
+
+ /* Try to add one more record ID to cache */
+ rc = __erst_record_id_cache_add_one();
+ if (rc < 0)
+ goto out_unlock;
+ /* successfully add one new ID */
+ if (rc == 1) {
+ *record_id = erst_record_id_cache.entries[*pos];
+ (*pos)++;
+ rc = 0;
+ } else {
+ *pos = -1;
+ *record_id = APEI_ERST_INVALID_RECORD_ID;
+ }
+out_unlock:
+ mutex_unlock(&erst_record_id_cache.lock);
return rc;
}
-EXPORT_SYMBOL_GPL(erst_get_next_record_id);
+EXPORT_SYMBOL_GPL(erst_get_record_id_next);
+
+/* erst_record_id_cache.lock must be held by caller */
+static void __erst_record_id_cache_compact(void)
+{
+ int i, wpos = 0;
+ u64 *entries;
+
+ if (erst_record_id_cache.refcount)
+ return;
+
+ entries = erst_record_id_cache.entries;
+ for (i = 0; i < erst_record_id_cache.len; i++) {
+ if (entries[i] == APEI_ERST_INVALID_RECORD_ID)
+ continue;
+ if (wpos != i)
+ memcpy(&entries[wpos], &entries[i], sizeof(entries[i]));
+ wpos++;
+ }
+ erst_record_id_cache.len = wpos;
+}
+
+void erst_get_record_id_end(void)
+{
+ /*
+ * erst_disable != 0 should be detected by invoker via the
+ * return value of erst_get_record_id_begin/next, so this
+ * function should not be called for erst_disable != 0.
+ */
+ BUG_ON(erst_disable);
+
+ mutex_lock(&erst_record_id_cache.lock);
+ erst_record_id_cache.refcount--;
+ BUG_ON(erst_record_id_cache.refcount < 0);
+ __erst_record_id_cache_compact();
+ mutex_unlock(&erst_record_id_cache.lock);
+}
+EXPORT_SYMBOL_GPL(erst_get_record_id_end);
static int __erst_write_to_storage(u64 offset)
{
@@ -703,56 +873,34 @@ ssize_t erst_read(u64 record_id, struct cper_record_header *record,
}
EXPORT_SYMBOL_GPL(erst_read);
-/*
- * If return value > buflen, the buffer size is not big enough,
- * else if return value = 0, there is no more record to read,
- * else if return value < 0, something goes wrong,
- * else everything is OK, and return value is record length
- */
-ssize_t erst_read_next(struct cper_record_header *record, size_t buflen)
-{
- int rc;
- ssize_t len;
- unsigned long flags;
- u64 record_id;
-
- if (erst_disable)
- return -ENODEV;
-
- raw_spin_lock_irqsave(&erst_lock, flags);
- rc = __erst_get_next_record_id(&record_id);
- if (rc) {
- raw_spin_unlock_irqrestore(&erst_lock, flags);
- return rc;
- }
- /* no more record */
- if (record_id == APEI_ERST_INVALID_RECORD_ID) {
- raw_spin_unlock_irqrestore(&erst_lock, flags);
- return 0;
- }
-
- len = __erst_read(record_id, record, buflen);
- raw_spin_unlock_irqrestore(&erst_lock, flags);
-
- return len;
-}
-EXPORT_SYMBOL_GPL(erst_read_next);
-
int erst_clear(u64 record_id)
{
- int rc;
+ int rc, i;
unsigned long flags;
+ u64 *entries;
if (erst_disable)
return -ENODEV;
+ rc = mutex_lock_interruptible(&erst_record_id_cache.lock);
+ if (rc)
+ return rc;
raw_spin_lock_irqsave(&erst_lock, flags);
if (erst_erange.attr & ERST_RANGE_NVRAM)
rc = __erst_clear_from_nvram(record_id);
else
rc = __erst_clear_from_storage(record_id);
raw_spin_unlock_irqrestore(&erst_lock, flags);
-
+ if (rc)
+ goto out;
+ entries = erst_record_id_cache.entries;
+ for (i = 0; i < erst_record_id_cache.len; i++) {
+ if (entries[i] == record_id)
+ entries[i] = APEI_ERST_INVALID_RECORD_ID;
+ }
+ __erst_record_id_cache_compact();
+out:
+ mutex_unlock(&erst_record_id_cache.lock);
return rc;
}
EXPORT_SYMBOL_GPL(erst_clear);
@@ -781,6 +929,128 @@ static int erst_check_table(struct acpi_table_erst *erst_tab)
return 0;
}
+static size_t erst_reader(u64 *id, enum pstore_type_id *type,
+ struct timespec *time);
+static u64 erst_writer(enum pstore_type_id type, size_t size);
+
+static struct pstore_info erst_info = {
+ .owner = THIS_MODULE,
+ .name = "erst",
+ .read = erst_reader,
+ .write = erst_writer,
+ .erase = erst_clear
+};
+
+#define CPER_CREATOR_PSTORE \
+ UUID_LE(0x75a574e3, 0x5052, 0x4b29, 0x8a, 0x8e, 0xbe, 0x2c, \
+ 0x64, 0x90, 0xb8, 0x9d)
+#define CPER_SECTION_TYPE_DMESG \
+ UUID_LE(0xc197e04e, 0xd545, 0x4a70, 0x9c, 0x17, 0xa5, 0x54, \
+ 0x94, 0x19, 0xeb, 0x12)
+#define CPER_SECTION_TYPE_MCE \
+ UUID_LE(0xfe08ffbe, 0x95e4, 0x4be7, 0xbc, 0x73, 0x40, 0x96, \
+ 0x04, 0x4a, 0x38, 0xfc)
+
+struct cper_pstore_record {
+ struct cper_record_header hdr;
+ struct cper_section_descriptor sec_hdr;
+ char data[];
+} __packed;
+
+static size_t erst_reader(u64 *id, enum pstore_type_id *type,
+ struct timespec *time)
+{
+ int rc;
+ ssize_t len;
+ unsigned long flags;
+ u64 record_id;
+ struct cper_pstore_record *rcd = (struct cper_pstore_record *)
+ (erst_info.buf - sizeof(*rcd));
+
+ if (erst_disable)
+ return -ENODEV;
+
+ raw_spin_lock_irqsave(&erst_lock, flags);
+skip:
+ rc = __erst_get_next_record_id(&record_id);
+ if (rc) {
+ raw_spin_unlock_irqrestore(&erst_lock, flags);
+ return rc;
+ }
+ /* no more record */
+ if (record_id == APEI_ERST_INVALID_RECORD_ID) {
+ raw_spin_unlock_irqrestore(&erst_lock, flags);
+ return 0;
+ }
+
+ len = __erst_read(record_id, &rcd->hdr, sizeof(*rcd) +
+ erst_erange.size);
+ if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0)
+ goto skip;
+ raw_spin_unlock_irqrestore(&erst_lock, flags);
+
+ *id = record_id;
+ if (uuid_le_cmp(rcd->sec_hdr.section_type,
+ CPER_SECTION_TYPE_DMESG) == 0)
+ *type = PSTORE_TYPE_DMESG;
+ else if (uuid_le_cmp(rcd->sec_hdr.section_type,
+ CPER_SECTION_TYPE_MCE) == 0)
+ *type = PSTORE_TYPE_MCE;
+ else
+ *type = PSTORE_TYPE_UNKNOWN;
+
+ if (rcd->hdr.validation_bits & CPER_VALID_TIMESTAMP)
+ time->tv_sec = rcd->hdr.timestamp;
+ else
+ time->tv_sec = 0;
+ time->tv_nsec = 0;
+
+ return len - sizeof(*rcd);
+}
+
+static u64 erst_writer(enum pstore_type_id type, size_t size)
+{
+ struct cper_pstore_record *rcd = (struct cper_pstore_record *)
+ (erst_info.buf - sizeof(*rcd));
+
+ memset(rcd, 0, sizeof(*rcd));
+ memcpy(rcd->hdr.signature, CPER_SIG_RECORD, CPER_SIG_SIZE);
+ rcd->hdr.revision = CPER_RECORD_REV;
+ rcd->hdr.signature_end = CPER_SIG_END;
+ rcd->hdr.section_count = 1;
+ rcd->hdr.error_severity = CPER_SEV_FATAL;
+ /* timestamp valid. platform_id, partition_id are invalid */
+ rcd->hdr.validation_bits = CPER_VALID_TIMESTAMP;
+ rcd->hdr.timestamp = get_seconds();
+ rcd->hdr.record_length = sizeof(*rcd) + size;
+ rcd->hdr.creator_id = CPER_CREATOR_PSTORE;
+ rcd->hdr.notification_type = CPER_NOTIFY_MCE;
+ rcd->hdr.record_id = cper_next_record_id();
+ rcd->hdr.flags = CPER_HW_ERROR_FLAGS_PREVERR;
+
+ rcd->sec_hdr.section_offset = sizeof(*rcd);
+ rcd->sec_hdr.section_length = size;
+ rcd->sec_hdr.revision = CPER_SEC_REV;
+ /* fru_id and fru_text is invalid */
+ rcd->sec_hdr.validation_bits = 0;
+ rcd->sec_hdr.flags = CPER_SEC_PRIMARY;
+ switch (type) {
+ case PSTORE_TYPE_DMESG:
+ rcd->sec_hdr.section_type = CPER_SECTION_TYPE_DMESG;
+ break;
+ case PSTORE_TYPE_MCE:
+ rcd->sec_hdr.section_type = CPER_SECTION_TYPE_MCE;
+ break;
+ default:
+ return -EINVAL;
+ }
+ rcd->sec_hdr.section_severity = CPER_SEV_FATAL;
+
+ erst_write(&rcd->hdr);
+
+ return rcd->hdr.record_id;
+}
+
static int __init erst_init(void)
{
int rc = 0;
@@ -788,6 +1058,7 @@ static int __init erst_init(void)
struct apei_exec_context ctx;
struct apei_resources erst_resources;
struct resource *r;
+ char *buf;
if (acpi_disabled)
goto err;
@@ -854,6 +1125,18 @@ static int __init erst_init(void)
if (!erst_erange.vaddr)
goto err_release_erange;
+ buf = kmalloc(erst_erange.size, GFP_KERNEL);
+ mutex_init(&erst_info.buf_mutex);
+ if (buf) {
+ erst_info.buf = buf + sizeof(struct cper_pstore_record);
+ erst_info.bufsize = erst_erange.size -
+ sizeof(struct cper_pstore_record);
+ if (pstore_register(&erst_info)) {
+ pr_info(ERST_PFX "Could not register with persistent store\n");
+ kfree(buf);
+ }
+ }
+
pr_info(ERST_PFX
"Error Record Serialization Table (ERST) support is initialized.\n");
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index d1d484d4a06a..f703b2881153 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -241,7 +241,7 @@ static inline int ghes_severity(int severity)
case CPER_SEV_FATAL:
return GHES_SEV_PANIC;
default:
- /* Unkown, go panic */
+ /* Unknown, go panic */
return GHES_SEV_PANIC;
}
}
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index ac1a599f5147..fcc13ac0aa18 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -33,6 +33,7 @@
#include <linux/async.h>
#include <linux/dmi.h>
#include <linux/slab.h>
+#include <linux/suspend.h>
#ifdef CONFIG_ACPI_PROCFS_POWER
#include <linux/proc_fs.h>
@@ -102,6 +103,7 @@ struct acpi_battery {
struct mutex lock;
struct power_supply bat;
struct acpi_device *device;
+ struct notifier_block pm_nb;
unsigned long update_time;
int rate_now;
int capacity_now;
@@ -940,6 +942,21 @@ static void acpi_battery_notify(struct acpi_device *device, u32 event)
power_supply_changed(&battery->bat);
}
+static int battery_notify(struct notifier_block *nb,
+ unsigned long mode, void *_unused)
+{
+ struct acpi_battery *battery = container_of(nb, struct acpi_battery,
+ pm_nb);
+ switch (mode) {
+ case PM_POST_SUSPEND:
+ sysfs_remove_battery(battery);
+ sysfs_add_battery(battery);
+ break;
+ }
+
+ return 0;
+}
+
static int acpi_battery_add(struct acpi_device *device)
{
int result = 0;
@@ -972,6 +989,10 @@ static int acpi_battery_add(struct acpi_device *device)
#endif
kfree(battery);
}
+
+ battery->pm_nb.notifier_call = battery_notify;
+ register_pm_notifier(&battery->pm_nb);
+
return result;
}
@@ -982,6 +1003,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
if (!device || !acpi_driver_data(device))
return -EINVAL;
battery = acpi_driver_data(device);
+ unregister_pm_notifier(&battery->pm_nb);
#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_battery_remove_fs(device);
#endif
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 7ced61f39492..d1e06c182cdb 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -40,6 +40,7 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include <linux/dmi.h>
+#include <linux/suspend.h>
#include "internal.h"
@@ -226,7 +227,7 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state)
acpi_status status = AE_OK;
char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' };
- if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
+ if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD))
return -EINVAL;
/* Make sure this is a valid target state */
@@ -1006,8 +1007,7 @@ struct kobject *acpi_kobj;
static int __init acpi_init(void)
{
- int result = 0;
-
+ int result;
if (acpi_disabled) {
printk(KERN_INFO PREFIX "Interpreter disabled.\n");
@@ -1022,29 +1022,18 @@ static int __init acpi_init(void)
init_acpi_device_notify();
result = acpi_bus_init();
-
- if (!result) {
- pci_mmcfg_late_init();
- if (!(pm_flags & PM_APM))
- pm_flags |= PM_ACPI;
- else {
- printk(KERN_INFO PREFIX
- "APM is already active, exiting\n");
- disable_acpi();
- result = -ENODEV;
- }
- } else
+ if (result) {
disable_acpi();
-
- if (acpi_disabled)
return result;
+ }
+ pci_mmcfg_late_init();
acpi_scan_init();
acpi_ec_init();
acpi_debugfs_init();
acpi_sleep_proc_init();
acpi_wakeup_device_init();
- return result;
+ return 0;
}
subsys_initcall(acpi_init);
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 76bbb78a5ad9..d27d072472f9 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -78,8 +78,6 @@ static int acpi_button_add(struct acpi_device *device);
static int acpi_button_remove(struct acpi_device *device, int type);
static int acpi_button_resume(struct acpi_device *device);
static void acpi_button_notify(struct acpi_device *device, u32 event);
-static int acpi_button_info_open_fs(struct inode *inode, struct file *file);
-static int acpi_button_state_open_fs(struct inode *inode, struct file *file);
static struct acpi_driver acpi_button_driver = {
.name = "button",
@@ -98,22 +96,7 @@ struct acpi_button {
struct input_dev *input;
char phys[32]; /* for input device */
unsigned long pushed;
-};
-
-static const struct file_operations acpi_button_info_fops = {
- .owner = THIS_MODULE,
- .open = acpi_button_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations acpi_button_state_fops = {
- .owner = THIS_MODULE,
- .open = acpi_button_state_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
+ bool wakeup_enabled;
};
static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
@@ -124,20 +107,7 @@ static struct acpi_device *lid_device;
-------------------------------------------------------------------------- */
static struct proc_dir_entry *acpi_button_dir;
-
-static int acpi_button_info_seq_show(struct seq_file *seq, void *offset)
-{
- struct acpi_device *device = seq->private;
-
- seq_printf(seq, "type: %s\n",
- acpi_device_name(device));
- return 0;
-}
-
-static int acpi_button_info_open_fs(struct inode *inode, struct file *file)
-{
- return single_open(file, acpi_button_info_seq_show, PDE(inode)->data);
-}
+static struct proc_dir_entry *acpi_lid_dir;
static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
{
@@ -157,77 +127,85 @@ static int acpi_button_state_open_fs(struct inode *inode, struct file *file)
return single_open(file, acpi_button_state_seq_show, PDE(inode)->data);
}
-static struct proc_dir_entry *acpi_power_dir;
-static struct proc_dir_entry *acpi_sleep_dir;
-static struct proc_dir_entry *acpi_lid_dir;
+static const struct file_operations acpi_button_state_fops = {
+ .owner = THIS_MODULE,
+ .open = acpi_button_state_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
static int acpi_button_add_fs(struct acpi_device *device)
{
struct acpi_button *button = acpi_driver_data(device);
struct proc_dir_entry *entry = NULL;
+ int ret = 0;
- switch (button->type) {
- case ACPI_BUTTON_TYPE_POWER:
- if (!acpi_power_dir)
- acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER,
- acpi_button_dir);
- entry = acpi_power_dir;
- break;
- case ACPI_BUTTON_TYPE_SLEEP:
- if (!acpi_sleep_dir)
- acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP,
- acpi_button_dir);
- entry = acpi_sleep_dir;
- break;
- case ACPI_BUTTON_TYPE_LID:
- if (!acpi_lid_dir)
- acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID,
- acpi_button_dir);
- entry = acpi_lid_dir;
- break;
+ /* procfs I/F for ACPI lid device only */
+ if (button->type != ACPI_BUTTON_TYPE_LID)
+ return 0;
+
+ if (acpi_button_dir || acpi_lid_dir) {
+ printk(KERN_ERR PREFIX "More than one Lid device found!\n");
+ return -EEXIST;
}
- if (!entry)
+ /* create /proc/acpi/button */
+ acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
+ if (!acpi_button_dir)
return -ENODEV;
- acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry);
- if (!acpi_device_dir(device))
- return -ENODEV;
+ /* create /proc/acpi/button/lid */
+ acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
+ if (!acpi_lid_dir) {
+ ret = -ENODEV;
+ goto remove_button_dir;
+ }
- /* 'info' [R] */
- entry = proc_create_data(ACPI_BUTTON_FILE_INFO,
- S_IRUGO, acpi_device_dir(device),
- &acpi_button_info_fops, device);
- if (!entry)
- return -ENODEV;
+ /* create /proc/acpi/button/lid/LID/ */
+ acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_lid_dir);
+ if (!acpi_device_dir(device)) {
+ ret = -ENODEV;
+ goto remove_lid_dir;
+ }
- /* show lid state [R] */
- if (button->type == ACPI_BUTTON_TYPE_LID) {
- entry = proc_create_data(ACPI_BUTTON_FILE_STATE,
- S_IRUGO, acpi_device_dir(device),
- &acpi_button_state_fops, device);
- if (!entry)
- return -ENODEV;
+ /* create /proc/acpi/button/lid/LID/state */
+ entry = proc_create_data(ACPI_BUTTON_FILE_STATE,
+ S_IRUGO, acpi_device_dir(device),
+ &acpi_button_state_fops, device);
+ if (!entry) {
+ ret = -ENODEV;
+ goto remove_dev_dir;
}
- return 0;
+done:
+ return ret;
+
+remove_dev_dir:
+ remove_proc_entry(acpi_device_bid(device),
+ acpi_lid_dir);
+ acpi_device_dir(device) = NULL;
+remove_lid_dir:
+ remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
+remove_button_dir:
+ remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
+ goto done;
}
static int acpi_button_remove_fs(struct acpi_device *device)
{
struct acpi_button *button = acpi_driver_data(device);
- if (acpi_device_dir(device)) {
- if (button->type == ACPI_BUTTON_TYPE_LID)
- remove_proc_entry(ACPI_BUTTON_FILE_STATE,
- acpi_device_dir(device));
- remove_proc_entry(ACPI_BUTTON_FILE_INFO,
- acpi_device_dir(device));
+ if (button->type != ACPI_BUTTON_TYPE_LID)
+ return 0;
- remove_proc_entry(acpi_device_bid(device),
- acpi_device_dir(device)->parent);
- acpi_device_dir(device) = NULL;
- }
+ remove_proc_entry(ACPI_BUTTON_FILE_STATE,
+ acpi_device_dir(device));
+ remove_proc_entry(acpi_device_bid(device),
+ acpi_lid_dir);
+ acpi_device_dir(device) = NULL;
+ remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
+ remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
return 0;
}
@@ -430,8 +408,10 @@ static int acpi_button_add(struct acpi_device *device)
/* Button's GPE is run-wake GPE */
acpi_enable_gpe(device->wakeup.gpe_device,
device->wakeup.gpe_number);
- device->wakeup.run_wake_count++;
- device_set_wakeup_enable(&device->dev, true);
+ if (!device_may_wakeup(&device->dev)) {
+ device_set_wakeup_enable(&device->dev, true);
+ button->wakeup_enabled = true;
+ }
}
printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
@@ -453,8 +433,8 @@ static int acpi_button_remove(struct acpi_device *device, int type)
if (device->wakeup.flags.valid) {
acpi_disable_gpe(device->wakeup.gpe_device,
device->wakeup.gpe_number);
- device->wakeup.run_wake_count--;
- device_set_wakeup_enable(&device->dev, false);
+ if (button->wakeup_enabled)
+ device_set_wakeup_enable(&device->dev, false);
}
acpi_button_remove_fs(device);
@@ -465,32 +445,12 @@ static int acpi_button_remove(struct acpi_device *device, int type)
static int __init acpi_button_init(void)
{
- int result;
-
- acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
- if (!acpi_button_dir)
- return -ENODEV;
-
- result = acpi_bus_register_driver(&acpi_button_driver);
- if (result < 0) {
- remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
- return -ENODEV;
- }
-
- return 0;
+ return acpi_bus_register_driver(&acpi_button_driver);
}
static void __exit acpi_button_exit(void)
{
acpi_bus_unregister_driver(&acpi_button_driver);
-
- if (acpi_power_dir)
- remove_proc_entry(ACPI_BUTTON_SUBCLASS_POWER, acpi_button_dir);
- if (acpi_sleep_dir)
- remove_proc_entry(ACPI_BUTTON_SUBCLASS_SLEEP, acpi_button_dir);
- if (acpi_lid_dir)
- remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
- remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
}
module_init(acpi_button_init);
diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c
new file mode 100644
index 000000000000..5d42c2414ae5
--- /dev/null
+++ b/drivers/acpi/custom_method.c
@@ -0,0 +1,100 @@
+/*
+ * debugfs.c - ACPI debugfs interface to userspace.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+#include <acpi/acpi_drivers.h>
+
+#include "internal.h"
+
+#define _COMPONENT ACPI_SYSTEM_COMPONENT
+ACPI_MODULE_NAME("custom_method");
+MODULE_LICENSE("GPL");
+
+static struct dentry *cm_dentry;
+
+/* /sys/kernel/debug/acpi/custom_method */
+
+static ssize_t cm_write(struct file *file, const char __user * user_buf,
+ size_t count, loff_t *ppos)
+{
+ static char *buf;
+ static u32 max_size;
+ static u32 uncopied_bytes;
+
+ struct acpi_table_header table;
+ acpi_status status;
+
+ if (!(*ppos)) {
+ /* parse the table header to get the table length */
+ if (count <= sizeof(struct acpi_table_header))
+ return -EINVAL;
+ if (copy_from_user(&table, user_buf,
+ sizeof(struct acpi_table_header)))
+ return -EFAULT;
+ uncopied_bytes = max_size = table.length;
+ buf = kzalloc(max_size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ }
+
+ if (buf == NULL)
+ return -EINVAL;
+
+ if ((*ppos > max_size) ||
+ (*ppos + count > max_size) ||
+ (*ppos + count < count) ||
+ (count > uncopied_bytes))
+ return -EINVAL;
+
+ if (copy_from_user(buf + (*ppos), user_buf, count)) {
+ kfree(buf);
+ buf = NULL;
+ return -EFAULT;
+ }
+
+ uncopied_bytes -= count;
+ *ppos += count;
+
+ if (!uncopied_bytes) {
+ status = acpi_install_method(buf);
+ kfree(buf);
+ buf = NULL;
+ if (ACPI_FAILURE(status))
+ return -EINVAL;
+ add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
+ }
+
+ return count;
+}
+
+static const struct file_operations cm_fops = {
+ .write = cm_write,
+ .llseek = default_llseek,
+};
+
+static int __init acpi_custom_method_init(void)
+{
+ if (acpi_debugfs_dir == NULL)
+ return -ENOENT;
+
+ cm_dentry = debugfs_create_file("custom_method", S_IWUSR,
+ acpi_debugfs_dir, NULL, &cm_fops);
+ if (cm_dentry == NULL)
+ return -ENODEV;
+
+ return 0;
+}
+
+static void __exit acpi_custom_method_exit(void)
+{
+ if (cm_dentry)
+ debugfs_remove(cm_dentry);
+ }
+
+module_init(acpi_custom_method_init);
+module_exit(acpi_custom_method_exit);
diff --git a/drivers/acpi/debugfs.c b/drivers/acpi/debugfs.c
index 384f7abcff77..182a9fc36355 100644
--- a/drivers/acpi/debugfs.c
+++ b/drivers/acpi/debugfs.c
@@ -3,100 +3,16 @@
*/
#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/uaccess.h>
#include <linux/debugfs.h>
#include <acpi/acpi_drivers.h>
#define _COMPONENT ACPI_SYSTEM_COMPONENT
ACPI_MODULE_NAME("debugfs");
+struct dentry *acpi_debugfs_dir;
+EXPORT_SYMBOL_GPL(acpi_debugfs_dir);
-/* /sys/modules/acpi/parameters/aml_debug_output */
-
-module_param_named(aml_debug_output, acpi_gbl_enable_aml_debug_object,
- bool, 0644);
-MODULE_PARM_DESC(aml_debug_output,
- "To enable/disable the ACPI Debug Object output.");
-
-/* /sys/kernel/debug/acpi/custom_method */
-
-static ssize_t cm_write(struct file *file, const char __user * user_buf,
- size_t count, loff_t *ppos)
+void __init acpi_debugfs_init(void)
{
- static char *buf;
- static u32 max_size;
- static u32 uncopied_bytes;
-
- struct acpi_table_header table;
- acpi_status status;
-
- if (!(*ppos)) {
- /* parse the table header to get the table length */
- if (count <= sizeof(struct acpi_table_header))
- return -EINVAL;
- if (copy_from_user(&table, user_buf,
- sizeof(struct acpi_table_header)))
- return -EFAULT;
- uncopied_bytes = max_size = table.length;
- buf = kzalloc(max_size, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
- }
-
- if (buf == NULL)
- return -EINVAL;
-
- if ((*ppos > max_size) ||
- (*ppos + count > max_size) ||
- (*ppos + count < count) ||
- (count > uncopied_bytes))
- return -EINVAL;
-
- if (copy_from_user(buf + (*ppos), user_buf, count)) {
- kfree(buf);
- buf = NULL;
- return -EFAULT;
- }
-
- uncopied_bytes -= count;
- *ppos += count;
-
- if (!uncopied_bytes) {
- status = acpi_install_method(buf);
- kfree(buf);
- buf = NULL;
- if (ACPI_FAILURE(status))
- return -EINVAL;
- add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
- }
-
- return count;
-}
-
-static const struct file_operations cm_fops = {
- .write = cm_write,
- .llseek = default_llseek,
-};
-
-int __init acpi_debugfs_init(void)
-{
- struct dentry *acpi_dir, *cm_dentry;
-
- acpi_dir = debugfs_create_dir("acpi", NULL);
- if (!acpi_dir)
- goto err;
-
- cm_dentry = debugfs_create_file("custom_method", S_IWUSR,
- acpi_dir, NULL, &cm_fops);
- if (!cm_dentry)
- goto err;
-
- return 0;
-
-err:
- if (acpi_dir)
- debugfs_remove(acpi_dir);
- return -EINVAL;
+ acpi_debugfs_dir = debugfs_create_dir("acpi", NULL);
}
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index ed8cf17cf03c..b19a18dd994f 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -932,8 +932,19 @@ static struct dmi_system_id __initdata ec_dmi_table[] = {
ec_flag_msi, "MSI hardware", {
DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR")}, NULL},
{
+ ec_flag_msi, "Quanta hardware", {
+ DMI_MATCH(DMI_SYS_VENDOR, "Quanta"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TW8/SW8/DW8"),}, NULL},
+ {
+ ec_flag_msi, "Quanta hardware", {
+ DMI_MATCH(DMI_SYS_VENDOR, "Quanta"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TW9/SW9"),}, NULL},
+ {
ec_validate_ecdt, "ASUS hardware", {
DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL},
+ {
+ ec_validate_ecdt, "ASUS hardware", {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc.") }, NULL},
{},
};
diff --git a/drivers/acpi/ec_sys.c b/drivers/acpi/ec_sys.c
index 411620ef84c2..05b44201a614 100644
--- a/drivers/acpi/ec_sys.c
+++ b/drivers/acpi/ec_sys.c
@@ -24,10 +24,6 @@ MODULE_PARM_DESC(write_support, "Dangerous, reboot and removal of battery may "
#define EC_SPACE_SIZE 256
-struct sysdev_class acpi_ec_sysdev_class = {
- .name = "ec",
-};
-
static struct dentry *acpi_ec_debugfs_dir;
static int acpi_ec_open_io(struct inode *i, struct file *f)
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index b1cc81a0431b..ca75b9ce0489 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -21,8 +21,6 @@
#ifndef _ACPI_INTERNAL_H_
#define _ACPI_INTERNAL_H_
-#include <linux/sysdev.h>
-
#define PREFIX "ACPI: "
int init_acpi_device_notify(void);
@@ -30,9 +28,10 @@ int acpi_scan_init(void);
int acpi_sysfs_init(void);
#ifdef CONFIG_DEBUG_FS
+extern struct dentry *acpi_debugfs_dir;
int acpi_debugfs_init(void);
#else
-static inline int acpi_debugfs_init(void) { return 0; }
+static inline void acpi_debugfs_init(void) { return; }
#endif
/* --------------------------------------------------------------------------
@@ -64,7 +63,6 @@ struct acpi_ec {
struct list_head list;
struct transaction *curr;
spinlock_t curr_lock;
- struct sys_device sysdev;
};
extern struct acpi_ec *first_ec;
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 5eb25eb3ea48..3b5c3189fd99 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -274,7 +274,7 @@ acpi_table_parse_srat(enum acpi_srat_type id,
int __init acpi_numa_init(void)
{
- int ret = 0;
+ int cnt = 0;
/*
* Should not limit number with cpu num that is from NR_CPUS or nr_cpus=
@@ -288,7 +288,7 @@ int __init acpi_numa_init(void)
acpi_parse_x2apic_affinity, 0);
acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
acpi_parse_processor_affinity, 0);
- ret = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
+ cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
acpi_parse_memory_affinity,
NR_NODE_MEMBLKS);
}
@@ -297,7 +297,10 @@ int __init acpi_numa_init(void)
acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
acpi_numa_arch_fixup();
- return ret;
+
+ if (cnt <= 0)
+ return cnt ?: -ENOENT;
+ return 0;
}
int acpi_get_pxm(acpi_handle h)
diff --git a/drivers/acpi/nvs.c b/drivers/acpi/nvs.c
index fa5a1df42b79..096787b43c96 100644
--- a/drivers/acpi/nvs.c
+++ b/drivers/acpi/nvs.c
@@ -26,6 +26,7 @@ struct nvs_page {
unsigned int size;
void *kaddr;
void *data;
+ bool unmap;
struct list_head node;
};
@@ -44,6 +45,9 @@ int suspend_nvs_register(unsigned long start, unsigned long size)
{
struct nvs_page *entry, *next;
+ pr_info("PM: Registering ACPI NVS region at %lx (%ld bytes)\n",
+ start, size);
+
while (size > 0) {
unsigned int nr_bytes;
@@ -81,7 +85,13 @@ void suspend_nvs_free(void)
free_page((unsigned long)entry->data);
entry->data = NULL;
if (entry->kaddr) {
- iounmap(entry->kaddr);
+ if (entry->unmap) {
+ iounmap(entry->kaddr);
+ entry->unmap = false;
+ } else {
+ acpi_os_unmap_memory(entry->kaddr,
+ entry->size);
+ }
entry->kaddr = NULL;
}
}
@@ -115,8 +125,14 @@ int suspend_nvs_save(void)
list_for_each_entry(entry, &nvs_list, node)
if (entry->data) {
- entry->kaddr = acpi_os_ioremap(entry->phys_start,
- entry->size);
+ unsigned long phys = entry->phys_start;
+ unsigned int size = entry->size;
+
+ entry->kaddr = acpi_os_get_iomem(phys, size);
+ if (!entry->kaddr) {
+ entry->kaddr = acpi_os_ioremap(phys, size);
+ entry->unmap = !!entry->kaddr;
+ }
if (!entry->kaddr) {
suspend_nvs_free();
return -ENOMEM;
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index c90c76aa7f8b..52ca9649d769 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -76,7 +76,6 @@ EXPORT_SYMBOL(acpi_in_debugger);
extern char line_buf[80];
#endif /*ENABLE_DEBUGGER */
-static unsigned int acpi_irq_irq;
static acpi_osd_handler acpi_irq_handler;
static void *acpi_irq_context;
static struct workqueue_struct *kacpid_wq;
@@ -105,11 +104,11 @@ struct acpi_ioremap {
void __iomem *virt;
acpi_physical_address phys;
acpi_size size;
- struct kref ref;
+ unsigned long refcount;
};
static LIST_HEAD(acpi_ioremaps);
-static DEFINE_SPINLOCK(acpi_ioremap_lock);
+static DEFINE_MUTEX(acpi_ioremap_lock);
static void __init acpi_osi_setup_late(void);
@@ -285,6 +284,22 @@ acpi_map_vaddr_lookup(acpi_physical_address phys, unsigned int size)
return NULL;
}
+void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size)
+{
+ struct acpi_ioremap *map;
+ void __iomem *virt = NULL;
+
+ mutex_lock(&acpi_ioremap_lock);
+ map = acpi_map_lookup(phys, size);
+ if (map) {
+ virt = map->virt + (phys - map->phys);
+ map->refcount++;
+ }
+ mutex_unlock(&acpi_ioremap_lock);
+ return virt;
+}
+EXPORT_SYMBOL_GPL(acpi_os_get_iomem);
+
/* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */
static struct acpi_ioremap *
acpi_map_lookup_virt(void __iomem *virt, acpi_size size)
@@ -302,8 +317,7 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size)
void __iomem *__init_refok
acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
{
- struct acpi_ioremap *map, *tmp_map;
- unsigned long flags;
+ struct acpi_ioremap *map;
void __iomem *virt;
acpi_physical_address pg_off;
acpi_size pg_sz;
@@ -316,14 +330,25 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
if (!acpi_gbl_permanent_mmap)
return __acpi_map_table((unsigned long)phys, size);
+ mutex_lock(&acpi_ioremap_lock);
+ /* Check if there's a suitable mapping already. */
+ map = acpi_map_lookup(phys, size);
+ if (map) {
+ map->refcount++;
+ goto out;
+ }
+
map = kzalloc(sizeof(*map), GFP_KERNEL);
- if (!map)
+ if (!map) {
+ mutex_unlock(&acpi_ioremap_lock);
return NULL;
+ }
pg_off = round_down(phys, PAGE_SIZE);
pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off;
virt = acpi_os_ioremap(pg_off, pg_sz);
if (!virt) {
+ mutex_unlock(&acpi_ioremap_lock);
kfree(map);
return NULL;
}
@@ -332,62 +357,51 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
map->virt = virt;
map->phys = pg_off;
map->size = pg_sz;
- kref_init(&map->ref);
-
- spin_lock_irqsave(&acpi_ioremap_lock, flags);
- /* Check if page has already been mapped. */
- tmp_map = acpi_map_lookup(phys, size);
- if (tmp_map) {
- kref_get(&tmp_map->ref);
- spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
- iounmap(map->virt);
- kfree(map);
- return tmp_map->virt + (phys - tmp_map->phys);
- }
+ map->refcount = 1;
+
list_add_tail_rcu(&map->list, &acpi_ioremaps);
- spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
+ out:
+ mutex_unlock(&acpi_ioremap_lock);
return map->virt + (phys - map->phys);
}
EXPORT_SYMBOL_GPL(acpi_os_map_memory);
-static void acpi_kref_del_iomap(struct kref *ref)
+static void acpi_os_drop_map_ref(struct acpi_ioremap *map)
{
- struct acpi_ioremap *map;
+ if (!--map->refcount)
+ list_del_rcu(&map->list);
+}
- map = container_of(ref, struct acpi_ioremap, ref);
- list_del_rcu(&map->list);
+static void acpi_os_map_cleanup(struct acpi_ioremap *map)
+{
+ if (!map->refcount) {
+ synchronize_rcu();
+ iounmap(map->virt);
+ kfree(map);
+ }
}
void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
{
struct acpi_ioremap *map;
- unsigned long flags;
- int del;
if (!acpi_gbl_permanent_mmap) {
__acpi_unmap_table(virt, size);
return;
}
- spin_lock_irqsave(&acpi_ioremap_lock, flags);
+ mutex_lock(&acpi_ioremap_lock);
map = acpi_map_lookup_virt(virt, size);
if (!map) {
- spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
- printk(KERN_ERR PREFIX "%s: bad address %p\n", __func__, virt);
- dump_stack();
+ mutex_unlock(&acpi_ioremap_lock);
+ WARN(true, PREFIX "%s: bad address %p\n", __func__, virt);
return;
}
+ acpi_os_drop_map_ref(map);
+ mutex_unlock(&acpi_ioremap_lock);
- del = kref_put(&map->ref, acpi_kref_del_iomap);
- spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
-
- if (!del)
- return;
-
- synchronize_rcu();
- iounmap(map->virt);
- kfree(map);
+ acpi_os_map_cleanup(map);
}
EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
@@ -397,7 +411,7 @@ void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
__acpi_unmap_table(virt, size);
}
-int acpi_os_map_generic_address(struct acpi_generic_address *addr)
+static int acpi_os_map_generic_address(struct acpi_generic_address *addr)
{
void __iomem *virt;
@@ -413,13 +427,10 @@ int acpi_os_map_generic_address(struct acpi_generic_address *addr)
return 0;
}
-EXPORT_SYMBOL_GPL(acpi_os_map_generic_address);
-void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
+static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
{
- void __iomem *virt;
- unsigned long flags;
- acpi_size size = addr->bit_width / 8;
+ struct acpi_ioremap *map;
if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
return;
@@ -427,13 +438,17 @@ void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
if (!addr->address || !addr->bit_width)
return;
- spin_lock_irqsave(&acpi_ioremap_lock, flags);
- virt = acpi_map_vaddr_lookup(addr->address, size);
- spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
+ mutex_lock(&acpi_ioremap_lock);
+ map = acpi_map_lookup(addr->address, addr->bit_width / 8);
+ if (!map) {
+ mutex_unlock(&acpi_ioremap_lock);
+ return;
+ }
+ acpi_os_drop_map_ref(map);
+ mutex_unlock(&acpi_ioremap_lock);
- acpi_os_unmap_memory(virt, size);
+ acpi_os_map_cleanup(map);
}
-EXPORT_SYMBOL_GPL(acpi_os_unmap_generic_address);
#ifdef ACPI_FUTURE_USAGE
acpi_status
@@ -516,11 +531,15 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
acpi_irq_stats_init();
/*
- * Ignore the GSI from the core, and use the value in our copy of the
- * FADT. It may not be the same if an interrupt source override exists
- * for the SCI.
+ * ACPI interrupts different from the SCI in our copy of the FADT are
+ * not supported.
*/
- gsi = acpi_gbl_FADT.sci_interrupt;
+ if (gsi != acpi_gbl_FADT.sci_interrupt)
+ return AE_BAD_PARAMETER;
+
+ if (acpi_irq_handler)
+ return AE_ALREADY_ACQUIRED;
+
if (acpi_gsi_to_irq(gsi, &irq) < 0) {
printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n",
gsi);
@@ -531,20 +550,20 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
acpi_irq_context = context;
if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) {
printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq);
+ acpi_irq_handler = NULL;
return AE_NOT_ACQUIRED;
}
- acpi_irq_irq = irq;
return AE_OK;
}
acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
{
- if (irq) {
- free_irq(irq, acpi_irq);
- acpi_irq_handler = NULL;
- acpi_irq_irq = 0;
- }
+ if (irq != acpi_gbl_FADT.sci_interrupt)
+ return AE_BAD_PARAMETER;
+
+ free_irq(irq, acpi_irq);
+ acpi_irq_handler = NULL;
return AE_OK;
}
@@ -883,14 +902,6 @@ void acpi_os_wait_events_complete(void *context)
EXPORT_SYMBOL(acpi_os_wait_events_complete);
-/*
- * Deallocate the memory for a spinlock.
- */
-void acpi_os_delete_lock(acpi_spinlock handle)
-{
- return;
-}
-
acpi_status
acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
{
@@ -1322,6 +1333,31 @@ int acpi_resources_are_enforced(void)
EXPORT_SYMBOL(acpi_resources_are_enforced);
/*
+ * Create and initialize a spinlock.
+ */
+acpi_status
+acpi_os_create_lock(acpi_spinlock *out_handle)
+{
+ spinlock_t *lock;
+
+ lock = ACPI_ALLOCATE(sizeof(spinlock_t));
+ if (!lock)
+ return AE_NO_MEMORY;
+ spin_lock_init(lock);
+ *out_handle = lock;
+
+ return AE_OK;
+}
+
+/*
+ * Deallocate the memory for a spinlock.
+ */
+void acpi_os_delete_lock(acpi_spinlock handle)
+{
+ ACPI_FREE(handle);
+}
+
+/*
* Acquire a spinlock.
*
* handle is a pointer to the spinlock_t.
@@ -1589,9 +1625,9 @@ acpi_status __init acpi_os_initialize(void)
acpi_status __init acpi_os_initialize1(void)
{
- kacpid_wq = create_workqueue("kacpid");
- kacpi_notify_wq = create_workqueue("kacpi_notify");
- kacpi_hotplug_wq = create_workqueue("kacpi_hotplug");
+ kacpid_wq = alloc_workqueue("kacpid", 0, 1);
+ kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1);
+ kacpi_hotplug_wq = alloc_workqueue("kacpi_hotplug", 0, 1);
BUG_ON(!kacpid_wq);
BUG_ON(!kacpi_notify_wq);
BUG_ON(!kacpi_hotplug_wq);
@@ -1603,7 +1639,7 @@ acpi_status __init acpi_os_initialize1(void)
acpi_status acpi_os_terminate(void)
{
if (acpi_irq_handler) {
- acpi_os_remove_interrupt_handler(acpi_irq_irq,
+ acpi_os_remove_interrupt_handler(acpi_gbl_FADT.sci_interrupt,
acpi_irq_handler);
}
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 9ff80a7e9f6a..4a29763b8eb4 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -29,7 +29,7 @@
* for IRQ management (e.g. start()->_SRS).
*/
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -757,14 +757,13 @@ static int acpi_pci_link_resume(struct acpi_pci_link *link)
return 0;
}
-static int irqrouter_resume(struct sys_device *dev)
+static void irqrouter_resume(void)
{
struct acpi_pci_link *link;
list_for_each_entry(link, &acpi_link_list, list) {
acpi_pci_link_resume(link);
}
- return 0;
}
static int acpi_pci_link_remove(struct acpi_device *device, int type)
@@ -871,32 +870,19 @@ static int __init acpi_irq_balance_set(char *str)
__setup("acpi_irq_balance", acpi_irq_balance_set);
-/* FIXME: we will remove this interface after all drivers call pci_disable_device */
-static struct sysdev_class irqrouter_sysdev_class = {
- .name = "irqrouter",
+static struct syscore_ops irqrouter_syscore_ops = {
.resume = irqrouter_resume,
};
-static struct sys_device device_irqrouter = {
- .id = 0,
- .cls = &irqrouter_sysdev_class,
-};
-
-static int __init irqrouter_init_sysfs(void)
+static int __init irqrouter_init_ops(void)
{
- int error;
+ if (!acpi_disabled && !acpi_noirq)
+ register_syscore_ops(&irqrouter_syscore_ops);
- if (acpi_disabled || acpi_noirq)
- return 0;
-
- error = sysdev_class_register(&irqrouter_sysdev_class);
- if (!error)
- error = sysdev_register(&device_irqrouter);
-
- return error;
+ return 0;
}
-device_initcall(irqrouter_init_sysfs);
+device_initcall(irqrouter_init_ops);
static int __init acpi_pci_link_init(void)
{
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 85249395623b..f911a2f8cc34 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -32,6 +32,7 @@
#include <linux/pm_runtime.h>
#include <linux/pci.h>
#include <linux/pci-acpi.h>
+#include <linux/pci-aspm.h>
#include <linux/acpi.h>
#include <linux/slab.h>
#include <acpi/acpi_bus.h>
@@ -564,7 +565,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
/* Indicate support for various _OSC capabilities. */
if (pci_ext_cfg_avail(root->bus->self))
flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
- if (pcie_aspm_enabled())
+ if (pcie_aspm_support_enabled())
flags |= OSC_ACTIVE_STATE_PWR_SUPPORT |
OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
if (pci_msi_enabled())
@@ -591,12 +592,16 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
status = acpi_pci_osc_control_set(device->handle, &flags,
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
- if (ACPI_SUCCESS(status))
+ if (ACPI_SUCCESS(status)) {
dev_info(root->bus->bridge,
"ACPI _OSC control (0x%02x) granted\n", flags);
- else
+ } else {
dev_dbg(root->bus->bridge,
"ACPI _OSC request failed (code %d)\n", status);
+ printk(KERN_INFO "Unable to assume _OSC PCIe control. "
+ "Disabling ASPM\n");
+ pcie_no_aspm();
+ }
}
pci_acpi_add_bus_pm_notifier(device, root->bus);
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 3c1a2fec8cda..02d2a4c9084d 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -19,7 +19,7 @@
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
ACPI_MODULE_NAME("processor_core");
-static int set_no_mwait(const struct dmi_system_id *id)
+static int __init set_no_mwait(const struct dmi_system_id *id)
{
printk(KERN_NOTICE PREFIX "%s detected - "
"disabling mwait for CPU C-states\n", id->ident);
@@ -27,7 +27,7 @@ static int set_no_mwait(const struct dmi_system_id *id)
return 0;
}
-static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
+static struct dmi_system_id __initdata processor_idle_dmi_table[] = {
{
set_no_mwait, "Extensa 5220", {
DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
@@ -37,7 +37,6 @@ static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
{},
};
-#ifdef CONFIG_SMP
static int map_lapic_id(struct acpi_subtable_header *entry,
u32 acpi_id, int *apic_id)
{
@@ -165,7 +164,9 @@ exit:
int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
{
+#ifdef CONFIG_SMP
int i;
+#endif
int apic_id = -1;
apic_id = map_mat_entry(handle, type, acpi_id);
@@ -174,16 +175,21 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
if (apic_id == -1)
return apic_id;
+#ifdef CONFIG_SMP
for_each_possible_cpu(i) {
if (cpu_physical_id(i) == apic_id)
return i;
}
+#else
+ /* In UP kernel, only processor 0 is valid */
+ if (apic_id == 0)
+ return apic_id;
+#endif
return -1;
}
EXPORT_SYMBOL_GPL(acpi_get_cpuid);
-#endif
-static bool processor_physically_present(acpi_handle handle)
+static bool __init processor_physically_present(acpi_handle handle)
{
int cpuid, type;
u32 acpi_id;
@@ -217,13 +223,13 @@ static bool processor_physically_present(acpi_handle handle)
type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
cpuid = acpi_get_cpuid(handle, type, acpi_id);
- if ((cpuid == -1) && (num_possible_cpus() > 1))
+ if (cpuid == -1)
return false;
return true;
}
-static void acpi_set_pdc_bits(u32 *buf)
+static void __cpuinit acpi_set_pdc_bits(u32 *buf)
{
buf[0] = ACPI_PDC_REVISION_ID;
buf[1] = 1;
@@ -235,7 +241,7 @@ static void acpi_set_pdc_bits(u32 *buf)
arch_acpi_set_pdc_bits(buf);
}
-static struct acpi_object_list *acpi_processor_alloc_pdc(void)
+static struct acpi_object_list *__cpuinit acpi_processor_alloc_pdc(void)
{
struct acpi_object_list *obj_list;
union acpi_object *obj;
@@ -278,7 +284,7 @@ static struct acpi_object_list *acpi_processor_alloc_pdc(void)
* _PDC is required for a BIOS-OS handshake for most of the newer
* ACPI processor features.
*/
-static int
+static int __cpuinit
acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
{
acpi_status status = AE_OK;
@@ -306,7 +312,7 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
return status;
}
-void acpi_processor_set_pdc(acpi_handle handle)
+void __cpuinit acpi_processor_set_pdc(acpi_handle handle)
{
struct acpi_object_list *obj_list;
@@ -323,9 +329,8 @@ void acpi_processor_set_pdc(acpi_handle handle)
kfree(obj_list->pointer);
kfree(obj_list);
}
-EXPORT_SYMBOL_GPL(acpi_processor_set_pdc);
-static acpi_status
+static acpi_status __init
early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
{
if (processor_physically_present(handle) == false)
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 360a74e6add0..a4e0f1ba6040 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -635,8 +635,8 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
return 0;
}
-static void __ref acpi_processor_hotplug_notify(acpi_handle handle,
- u32 event, void *data)
+static void acpi_processor_hotplug_notify(acpi_handle handle,
+ u32 event, void *data)
{
struct acpi_processor *pr;
struct acpi_device *device = NULL;
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index fa84e9744330..ad3501739563 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -1164,7 +1164,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
*/
if (!match_pr->flags.throttling) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Throttling Controll is unsupported "
+ "Throttling Control is unsupported "
"on CPU %d\n", i));
continue;
}
diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c
index 93f91142d7ad..a6c77e8b37bd 100644
--- a/drivers/acpi/reboot.c
+++ b/drivers/acpi/reboot.c
@@ -15,9 +15,15 @@ void acpi_reboot(void)
rr = &acpi_gbl_FADT.reset_register;
- /* Is the reset register supported? */
- if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) ||
- rr->bit_width != 8 || rr->bit_offset != 0)
+ /* ACPI reset register was only introduced with v2 of the FADT */
+
+ if (acpi_gbl_FADT.header.revision < 2)
+ return;
+
+ /* Is the reset register supported? The spec says we should be
+ * checking the bit width and bit offset, but Windows ignores
+ * these fields */
+ if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER))
return;
reset_value = acpi_gbl_FADT.reset_value;
@@ -45,6 +51,4 @@ void acpi_reboot(void)
acpi_reset();
break;
}
- /* Wait ten seconds */
- acpi_os_stall(10000000);
}
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index b99e62494607..449c556274c0 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -797,7 +797,6 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
acpi_status status;
acpi_event_status event_status;
- device->wakeup.run_wake_count = 0;
device->wakeup.flags.notifier_present = 0;
/* Power button, Lid switch always enable wakeup */
@@ -944,6 +943,10 @@ static int acpi_bus_get_flags(struct acpi_device *device)
if (ACPI_SUCCESS(status))
device->flags.lockable = 1;
+ /* Power resources cannot be power manageable. */
+ if (device->device_type == ACPI_BUS_TYPE_POWER)
+ return 0;
+
/* Presence of _PS0|_PR0 indicates 'power manageable' */
status = acpi_get_handle(device->handle, "_PS0", &temp);
if (ACPI_FAILURE(status))
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index d6a8cd14de2e..6c949602cbd1 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -16,6 +16,7 @@
#include <linux/device.h>
#include <linux/suspend.h>
#include <linux/reboot.h>
+#include <linux/acpi.h>
#include <asm/io.h>
@@ -199,8 +200,6 @@ static void acpi_pm_end(void)
#endif /* CONFIG_ACPI_SLEEP */
#ifdef CONFIG_SUSPEND
-extern void do_suspend_lowlevel(void);
-
static u32 acpi_suspend_states[] = {
[PM_SUSPEND_ON] = ACPI_STATE_S0,
[PM_SUSPEND_STANDBY] = ACPI_STATE_S1,
@@ -243,20 +242,11 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
static int acpi_suspend_enter(suspend_state_t pm_state)
{
acpi_status status = AE_OK;
- unsigned long flags = 0;
u32 acpi_state = acpi_target_sleep_state;
+ int error;
ACPI_FLUSH_CPU_CACHE();
- /* Do arch specific saving of state. */
- if (acpi_state == ACPI_STATE_S3) {
- int error = acpi_save_state_mem();
-
- if (error)
- return error;
- }
-
- local_irq_save(flags);
switch (acpi_state) {
case ACPI_STATE_S1:
barrier();
@@ -264,7 +254,10 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
break;
case ACPI_STATE_S3:
- do_suspend_lowlevel();
+ error = acpi_suspend_lowlevel();
+ if (error)
+ return error;
+ pr_info(PREFIX "Low-level resume complete\n");
break;
}
@@ -290,13 +283,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
/* Allow EC transactions to happen. */
acpi_ec_unblock_transactions_early();
- local_irq_restore(flags);
- printk(KERN_DEBUG "Back to C!\n");
-
- /* restore processor state */
- if (acpi_state == ACPI_STATE_S3)
- acpi_restore_state_mem();
-
suspend_nvs_restore();
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
@@ -472,16 +458,13 @@ static int acpi_hibernation_begin(void)
static int acpi_hibernation_enter(void)
{
acpi_status status = AE_OK;
- unsigned long flags = 0;
ACPI_FLUSH_CPU_CACHE();
- local_irq_save(flags);
/* This shouldn't return. If it returns, we have a problem */
status = acpi_enter_sleep_state(ACPI_STATE_S4);
/* Reprogram control registers and execute _BFS */
acpi_leave_sleep_state_prep(ACPI_STATE_S4);
- local_irq_restore(flags);
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}
@@ -585,7 +568,7 @@ int acpi_suspend(u32 acpi_state)
return -EINVAL;
}
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
/**
* acpi_pm_device_sleep_state - return preferred power state of ACPI device
* in the system sleep state given by %acpi_target_sleep_state
@@ -671,7 +654,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
*d_min_p = d_min;
return d_max;
}
-#endif /* CONFIG_PM_OPS */
+#endif /* CONFIG_PM */
#ifdef CONFIG_PM_SLEEP
/**
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index 61891e75583d..77255f250dbb 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -220,6 +220,14 @@ module_param_call(trace_state, param_set_trace_state, param_get_trace_state,
NULL, 0644);
#endif /* CONFIG_ACPI_DEBUG */
+
+/* /sys/modules/acpi/parameters/aml_debug_output */
+
+module_param_named(aml_debug_output, acpi_gbl_enable_aml_debug_object,
+ bool, 0644);
+MODULE_PARM_DESC(aml_debug_output,
+ "To enable/disable the ACPI Debug Object output.");
+
/* /sys/module/acpi/parameters/acpica_version */
static int param_get_acpica_version(char *buffer, struct kernel_param *kp)
{
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 90f8f7676d1f..ec574fc8fbc6 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -782,6 +782,9 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
if (acpi_video_backlight_support()) {
struct backlight_properties props;
+ struct pci_dev *pdev;
+ acpi_handle acpi_parent;
+ struct device *parent = NULL;
int result;
static int count = 0;
char *name;
@@ -794,9 +797,20 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
return;
count++;
+ acpi_get_parent(device->dev->handle, &acpi_parent);
+
+ pdev = acpi_get_pci_dev(acpi_parent);
+ if (pdev) {
+ parent = &pdev->dev;
+ pci_dev_put(pdev);
+ }
+
memset(&props, 0, sizeof(struct backlight_properties));
+ props.type = BACKLIGHT_FIRMWARE;
props.max_brightness = device->brightness->count - 3;
- device->backlight = backlight_device_register(name, NULL, device,
+ device->backlight = backlight_device_register(name,
+ parent,
+ device,
&acpi_backlight_ops,
&props);
kfree(name);
@@ -810,11 +824,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
device->backlight->props.brightness =
acpi_video_get_brightness(device->backlight);
- result = sysfs_create_link(&device->backlight->dev.kobj,
- &device->dev->dev.kobj, "device");
- if (result)
- printk(KERN_ERR PREFIX "Create sysfs link\n");
-
device->cooling_dev = thermal_cooling_device_register("LCD",
device->dev, &video_cooling_ops);
if (IS_ERR(device->cooling_dev)) {
@@ -1345,7 +1354,7 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video,
status = acpi_video_bus_get_one_device(dev, video);
if (ACPI_FAILURE(status)) {
printk(KERN_WARNING PREFIX
- "Cant attach device\n");
+ "Can't attach device\n");
continue;
}
}
@@ -1364,10 +1373,9 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
acpi_video_device_notify);
if (ACPI_FAILURE(status)) {
printk(KERN_WARNING PREFIX
- "Cant remove video notify handler\n");
+ "Can't remove video notify handler\n");
}
if (device->backlight) {
- sysfs_remove_link(&device->backlight->dev.kobj, "device");
backlight_device_unregister(device->backlight);
device->backlight = NULL;
}