summaryrefslogtreecommitdiff
path: root/drivers/acpi/events
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2005-11-02 08:00:00 +0300
committerLen Brown <len.brown@intel.com>2005-12-10 08:26:05 +0300
commit96db255c8f014ae3497507104e8df809785a619f (patch)
tree79d2c506644370fd6c10d94bd40c419cd3bad148 /drivers/acpi/events
parent0897831bb54eb36fd9e2a22da7f0f64be1b20d09 (diff)
downloadlinux-96db255c8f014ae3497507104e8df809785a619f.tar.xz
[ACPI] ACPICA 20051102
Modified the subsystem initialization sequence to improve GPE support. The GPE initialization has been split into two parts in order to defer execution of the _PRW methods (Power Resources for Wake) until after the hardware is fully initialized and the SCI handler is installed. This allows the _PRW methods to access fields protected by the Global Lock. This will fix systems where a NO_GLOBAL_LOCK exception has been seen during initialization. Fixed a regression with the ConcatenateResTemplate() ASL operator introduced in the 20051021 release. Implemented support for "local" internal ACPI object types within the debugger "Object" command and the acpi_walk_namespace() external interfaces. These local types include RegionFields, BankFields, IndexFields, Alias, and reference objects. Moved common AML resource handling code into a new file, "utresrc.c". This code is shared by both the Resource Manager and the AML Debugger. Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/events')
-rw-r--r--drivers/acpi/events/evevent.c42
-rw-r--r--drivers/acpi/events/evgpeblk.c159
-rw-r--r--drivers/acpi/events/evxfevnt.c7
3 files changed, 150 insertions, 58 deletions
diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c
index 842d1e3fb37b..9522c643b88b 100644
--- a/drivers/acpi/events/evevent.c
+++ b/drivers/acpi/events/evevent.c
@@ -100,6 +100,48 @@ acpi_status acpi_ev_initialize_events(void)
/*******************************************************************************
*
+ * FUNCTION: acpi_ev_install_fadt_gpes
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Completes initialization of the FADT-defined GPE blocks
+ * (0 and 1). This causes the _PRW methods to be run, so the HW
+ * must be fully initialized at this point, including global lock
+ * support.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ev_install_fadt_gpes(void)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE("ev_install_fadt_gpes");
+
+ /* Namespace must be locked */
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* FADT GPE Block 0 */
+
+ (void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device,
+ acpi_gbl_gpe_fadt_blocks[0]);
+
+ /* FADT GPE Block 1 */
+
+ (void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device,
+ acpi_gbl_gpe_fadt_blocks[1]);
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(AE_OK);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_ev_install_xrupt_handlers
*
* PARAMETERS: None
diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c
index 7ca10c5f2914..8efca2eac27e 100644
--- a/drivers/acpi/events/evgpeblk.c
+++ b/drivers/acpi/events/evgpeblk.c
@@ -78,7 +78,7 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block);
*
* RETURN: TRUE if the gpe_event is valid
*
- * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL.
+ * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL.
* Should be called only when the GPE lists are semaphore locked
* and not subject to change.
*
@@ -264,7 +264,7 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
* 2) Edge/Level determination is based on the 2nd character
* of the method name
*
- * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE
+ * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE
* if a _PRW object is found that points to this GPE.
*/
switch (name[1]) {
@@ -313,14 +313,14 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
/*
* Now we can add this information to the gpe_event_info block
- * for use during dispatch of this GPE. Default type is RUNTIME, although
+ * for use during dispatch of this GPE. Default type is RUNTIME, although
* this may change when the _PRW methods are executed later.
*/
gpe_event_info =
&gpe_block->event_info[gpe_number - gpe_block->block_base_number];
- gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD |
- ACPI_GPE_TYPE_RUNTIME);
+ gpe_event_info->flags = (u8)
+ (type | ACPI_GPE_DISPATCH_METHOD | ACPI_GPE_TYPE_RUNTIME);
gpe_event_info->dispatch.method_node =
(struct acpi_namespace_node *)obj_handle;
@@ -341,11 +341,11 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
*
* PARAMETERS: Callback from walk_namespace
*
- * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is
+ * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is
* not aborted on a single _PRW failure.
*
* DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a
- * Device. Run the _PRW method. If present, extract the GPE
+ * Device. Run the _PRW method. If present, extract the GPE
* number and mark the GPE as a WAKE GPE.
*
******************************************************************************/
@@ -443,6 +443,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
gpe_event_info->flags &=
~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);
+
status =
acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE);
if (ACPI_FAILURE(status)) {
@@ -466,7 +467,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
*
* RETURN: A GPE interrupt block
*
- * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
+ * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
* block per unique interrupt level used for GPEs.
* Should be called only when the GPE lists are semaphore locked
* and not subject to change.
@@ -566,8 +567,9 @@ acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt)
/* Disable this interrupt */
- status = acpi_os_remove_interrupt_handler(gpe_xrupt->interrupt_number,
- acpi_ev_gpe_xrupt_handler);
+ status =
+ acpi_os_remove_interrupt_handler(gpe_xrupt->interrupt_number,
+ acpi_ev_gpe_xrupt_handler);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
@@ -750,7 +752,7 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
/*
* Allocate the GPE event_info block. There are eight distinct GPEs
- * per register. Initialization to zeros is sufficient.
+ * per register. Initialization to zeros is sufficient.
*/
gpe_event_info = ACPI_MEM_CALLOCATE(((acpi_size) gpe_block->
register_count *
@@ -769,9 +771,9 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
gpe_block->event_info = gpe_event_info;
/*
- * Initialize the GPE Register and Event structures. A goal of these
+ * Initialize the GPE Register and Event structures. A goal of these
* tables is to hide the fact that there are two separate GPE register sets
- * in a given gpe hardware block, the status registers occupy the first half,
+ * in a given GPE hardware block, the status registers occupy the first half,
* and the enable registers occupy the second half.
*/
this_register = gpe_register_info;
@@ -812,11 +814,8 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
this_event++;
}
- /*
- * Clear the status/enable registers. Note that status registers
- * are cleared by writing a '1', while enable registers are cleared
- * by writing a '0'.
- */
+ /* Disable all GPEs within this register */
+
status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, 0x00,
&this_register->
enable_address);
@@ -824,6 +823,8 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
goto error_exit;
}
+ /* Clear any pending GPE events within this register */
+
status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, 0xFF,
&this_register->
status_address);
@@ -860,7 +861,9 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
*
* RETURN: Status
*
- * DESCRIPTION: Create and Install a block of GPE registers
+ * DESCRIPTION: Create and Install a block of GPE registers. All GPEs within
+ * the block are disabled at exit.
+ * Note: Assumes namespace is locked.
*
******************************************************************************/
@@ -872,14 +875,8 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
u32 interrupt_number,
struct acpi_gpe_block_info **return_gpe_block)
{
- struct acpi_gpe_block_info *gpe_block;
- struct acpi_gpe_event_info *gpe_event_info;
- acpi_native_uint i;
- acpi_native_uint j;
- u32 wake_gpe_count;
- u32 gpe_enabled_count;
acpi_status status;
- struct acpi_gpe_walk_info gpe_info;
+ struct acpi_gpe_block_info *gpe_block;
ACPI_FUNCTION_TRACE("ev_create_gpe_block");
@@ -896,22 +893,24 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
/* Initialize the new GPE block */
+ gpe_block->node = gpe_device;
gpe_block->register_count = register_count;
gpe_block->block_base_number = gpe_block_base_number;
- gpe_block->node = gpe_device;
ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address,
sizeof(struct acpi_generic_address));
- /* Create the register_info and event_info sub-structures */
-
+ /*
+ * Create the register_info and event_info sub-structures
+ * Note: disables and clears all GPEs in the block
+ */
status = acpi_ev_create_gpe_info_blocks(gpe_block);
if (ACPI_FAILURE(status)) {
ACPI_MEM_FREE(gpe_block);
return_ACPI_STATUS(status);
}
- /* Install the new block in the global list(s) */
+ /* Install the new block in the global lists */
status = acpi_ev_install_gpe_block(gpe_block, interrupt_number);
if (ACPI_FAILURE(status)) {
@@ -926,16 +925,70 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
acpi_ev_save_method_info, gpe_block,
NULL);
+ /* Return the new block */
+
+ if (return_gpe_block) {
+ (*return_gpe_block) = gpe_block;
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INIT,
+ "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n",
+ (u32) gpe_block->block_base_number,
+ (u32) (gpe_block->block_base_number +
+ ((gpe_block->register_count *
+ ACPI_GPE_REGISTER_WIDTH) - 1)),
+ gpe_device->name.ascii, gpe_block->register_count,
+ interrupt_number));
+
+ return_ACPI_STATUS(AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ev_initialize_gpe_block
+ *
+ * PARAMETERS: gpe_device - Handle to the parent GPE block
+ * gpe_block - Gpe Block info
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Initialize and enable a GPE block. First find and run any
+ * _PRT methods associated with the block, then enable the
+ * appropriate GPEs.
+ * Note: Assumes namespace is locked.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
+ struct acpi_gpe_block_info *gpe_block)
+{
+ acpi_status status;
+ struct acpi_gpe_event_info *gpe_event_info;
+ struct acpi_gpe_walk_info gpe_info;
+ u32 wake_gpe_count;
+ u32 gpe_enabled_count;
+ acpi_native_uint i;
+ acpi_native_uint j;
+
+ ACPI_FUNCTION_TRACE("ev_initialize_gpe_block");
+
+ /* Ignore a null GPE block (e.g., if no GPE block 1 exists) */
+
+ if (!gpe_block) {
+ return_ACPI_STATUS(AE_OK);
+ }
+
/*
- * Runtime option: Should Wake GPEs be enabled at runtime? The default
- * is No, they should only be enabled just as the machine goes to sleep.
+ * Runtime option: Should wake GPEs be enabled at runtime? The default
+ * is no, they should only be enabled just as the machine goes to sleep.
*/
if (acpi_gbl_leave_wake_gpes_disabled) {
/*
- * Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods.
- * (Each GPE that has one or more _PRWs that reference it is by
- * definition a WAKE GPE and will not be enabled while the machine
- * is running.)
+ * Differentiate runtime vs wake GPEs, via the _PRW control methods.
+ * Each GPE that has one or more _PRWs that reference it is by
+ * definition a wake GPE and will not be enabled while the machine
+ * is running.
*/
gpe_info.gpe_block = gpe_block;
gpe_info.gpe_device = gpe_device;
@@ -948,9 +1001,12 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
}
/*
- * Enable all GPEs in this block that are 1) "runtime" or "run/wake" GPEs,
- * and 2) have a corresponding _Lxx or _Exx method. All other GPEs must
- * be enabled via the acpi_enable_gpe() external interface.
+ * Enable all GPEs in this block that have these attributes:
+ * 1) are "runtime" or "run/wake" GPEs, and
+ * 2) have a corresponding _Lxx or _Exx method
+ *
+ * Any other GPEs within this block must be enabled via the acpi_enable_gpe()
+ * external interface.
*/
wake_gpe_count = 0;
gpe_enabled_count = 0;
@@ -976,32 +1032,19 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
}
}
- /* Dump info about this GPE block */
-
- ACPI_DEBUG_PRINT((ACPI_DB_INIT,
- "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n",
- (u32) gpe_block->block_base_number,
- (u32) (gpe_block->block_base_number +
- ((gpe_block->register_count *
- ACPI_GPE_REGISTER_WIDTH) - 1)),
- gpe_device->name.ascii, gpe_block->register_count,
- interrupt_number));
-
- /* Enable all valid GPEs found above */
-
- status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block);
-
ACPI_DEBUG_PRINT((ACPI_DB_INIT,
"Found %u Wake, Enabled %u Runtime GPEs in this block\n",
wake_gpe_count, gpe_enabled_count));
- /* Return the new block */
+ /* Enable all valid runtime GPEs found above */
- if (return_gpe_block) {
- (*return_gpe_block) = gpe_block;
+ status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block);
+ if (ACPI_FAILURE(status)) {
+ ACPI_REPORT_ERROR(("Could not enable GPEs in gpe_block %p\n",
+ gpe_block));
}
- return_ACPI_STATUS(AE_OK);
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c
index 887ff9f28a0d..c1b898928256 100644
--- a/drivers/acpi/events/evxfevnt.c
+++ b/drivers/acpi/events/evxfevnt.c
@@ -626,6 +626,13 @@ acpi_install_gpe_block(acpi_handle gpe_device,
goto unlock_and_exit;
}
+ /* Run the _PRW methods and enable the GPEs */
+
+ status = acpi_ev_initialize_gpe_block(node, gpe_block);
+ if (ACPI_FAILURE(status)) {
+ goto unlock_and_exit;
+ }
+
/* Get the device_object attached to the node */
obj_desc = acpi_ns_get_attached_object(node);