Commit ef84240d authored by Len Brown's avatar Len Brown Committed by Len Brown

[ACPI] ACPICA 20040326 from Bob Moore

Implemented support for "wake" GPEs via interaction between
GPEs and the _PRW methods.  Every GPE that is pointed to by
one or more _PRWs is identified as a WAKE GPE and by default
will no longer be enabled at runtime.  Previously, we were
blindly enabling all GPEs with a corresponding _Lxx or _Exx
method - but most of these turn out to be WAKE GPEs anyway.
We believe this has been the cause of thousands of
"spurious" GPEs on some systems.

This new GPE behavior is can be reverted to the original
behavior (enable ALL GPEs at runtime) via a runtime flag.

Fixed a problem where aliased control methods could not
access objects properly.  The proper scope within the
namespace was not initialized (transferred to the target of
the aliased method) before executing the target method.

Fixed a potential race condition on internal object
deletion on the return object in AcpiEvaluateObject. 

Integrated a fix for resource descriptors where both
_MEM and _MTP were being extracted instead of just _MEM.
(i.e. bitmask was incorrectly too wide, 0x0F instead of 0x03.)

Added a special case for ACPI_ROOT_OBJECT in AcpiUtGetNodeName,
preventing a fault in some cases.

Updated Notify() values for debug statements in evmisc.c

Return proper status from AcpiUtMutexInitialize,
not just simply AE_OK.
parent d29416fa
...@@ -99,9 +99,8 @@ acpi_ev_get_gpe_event_info ( ...@@ -99,9 +99,8 @@ acpi_ev_get_gpe_event_info (
return (NULL); return (NULL);
} }
/* /* A Non-NULL gpe_device means this is a GPE Block Device */
* A Non-null gpe_device means this is a GPE Block Device.
*/
obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) gpe_device); obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) gpe_device);
if (!obj_desc || if (!obj_desc ||
!obj_desc->device.gpe_block) { !obj_desc->device.gpe_block) {
...@@ -297,7 +296,7 @@ acpi_ev_asynch_execute_gpe_method ( ...@@ -297,7 +296,7 @@ acpi_ev_asynch_execute_gpe_method (
} }
} }
if (local_gpe_event_info.flags & ACPI_EVENT_LEVEL_TRIGGERED) { if ((local_gpe_event_info.flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED) {
/* /*
* GPE is level-triggered, we clear the GPE status bit after handling * GPE is level-triggered, we clear the GPE status bit after handling
* the event. * the event.
...@@ -346,7 +345,7 @@ acpi_ev_gpe_dispatch ( ...@@ -346,7 +345,7 @@ acpi_ev_gpe_dispatch (
* If edge-triggered, clear the GPE status bit now. Note that * If edge-triggered, clear the GPE status bit now. Note that
* level-triggered events are cleared after the GPE is serviced. * level-triggered events are cleared after the GPE is serviced.
*/ */
if (gpe_event_info->flags & ACPI_EVENT_EDGE_TRIGGERED) { if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_EDGE_TRIGGERED) {
status = acpi_hw_clear_gpe (gpe_event_info); status = acpi_hw_clear_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to clear GPE[%2X]\n", ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to clear GPE[%2X]\n",
...@@ -369,7 +368,7 @@ acpi_ev_gpe_dispatch ( ...@@ -369,7 +368,7 @@ acpi_ev_gpe_dispatch (
/* It is now safe to clear level-triggered events. */ /* It is now safe to clear level-triggered events. */
if (gpe_event_info->flags & ACPI_EVENT_LEVEL_TRIGGERED) { if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED) {
status = acpi_hw_clear_gpe (gpe_event_info); status = acpi_hw_clear_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR (( ACPI_REPORT_ERROR ((
......
...@@ -168,11 +168,11 @@ acpi_ev_walk_gpe_list ( ...@@ -168,11 +168,11 @@ acpi_ev_walk_gpe_list (
* information for quick lookup during GPE dispatch * information for quick lookup during GPE dispatch
* *
* The name of each GPE control method is of the form: * The name of each GPE control method is of the form:
* "_Lnn" or "_Enn" * "_Lxx" or "_Exx"
* Where: * Where:
* L - means that the GPE is level triggered * L - means that the GPE is level triggered
* E - means that the GPE is edge triggered * E - means that the GPE is edge triggered
* nn - is the GPE number [in HEX] * xx - is the GPE number [in HEX]
* *
******************************************************************************/ ******************************************************************************/
...@@ -188,36 +188,41 @@ acpi_ev_save_method_info ( ...@@ -188,36 +188,41 @@ acpi_ev_save_method_info (
u32 gpe_number; u32 gpe_number;
char name[ACPI_NAME_SIZE + 1]; char name[ACPI_NAME_SIZE + 1];
u8 type; u8 type;
acpi_status status;
ACPI_FUNCTION_TRACE ("ev_save_method_info"); ACPI_FUNCTION_TRACE ("ev_save_method_info");
/* Extract the name from the object and convert to a string */ /*
* _Lxx and _Exx GPE method support
*
* 1) Extract the name from the object and convert to a string
*/
ACPI_MOVE_32_TO_32 (name, ACPI_MOVE_32_TO_32 (name,
&((struct acpi_namespace_node *) obj_handle)->name.integer); &((struct acpi_namespace_node *) obj_handle)->name.integer);
name[ACPI_NAME_SIZE] = 0; name[ACPI_NAME_SIZE] = 0;
/* /*
* Edge/Level determination is based on the 2nd character * 2) Edge/Level determination is based on the 2nd character
* of the method name * of the method name
*
* 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]) { switch (name[1]) {
case 'L': case 'L':
type = ACPI_EVENT_LEVEL_TRIGGERED; type = ACPI_GPE_LEVEL_TRIGGERED | ACPI_GPE_TYPE_RUNTIME;
break; break;
case 'E': case 'E':
type = ACPI_EVENT_EDGE_TRIGGERED; type = ACPI_GPE_EDGE_TRIGGERED | ACPI_GPE_TYPE_RUNTIME;
break; break;
default: default:
/* Unknown method type, just ignore it! */ /* Unknown method type, just ignore it! */
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
"Unknown GPE method type: %s (name not of form _Lnn or _Enn)\n", "Unknown GPE method type: %s (name not of form _Lxx or _Exx)\n",
name)); name));
return_ACPI_STATUS (AE_OK); return_ACPI_STATUS (AE_OK);
} }
...@@ -229,7 +234,7 @@ acpi_ev_save_method_info ( ...@@ -229,7 +234,7 @@ acpi_ev_save_method_info (
/* Conversion failed; invalid method, just ignore it */ /* Conversion failed; invalid method, just ignore it */
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
"Could not extract GPE number from name: %s (name is not of form _Lnn or _Enn)\n", "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)\n",
name)); name));
return_ACPI_STATUS (AE_OK); return_ACPI_STATUS (AE_OK);
} }
...@@ -255,13 +260,6 @@ acpi_ev_save_method_info ( ...@@ -255,13 +260,6 @@ acpi_ev_save_method_info (
gpe_event_info->flags = type; gpe_event_info->flags = type;
gpe_event_info->method_node = (struct acpi_namespace_node *) obj_handle; gpe_event_info->method_node = (struct acpi_namespace_node *) obj_handle;
/* Enable the GPE (SCIs should be disabled at this point) */
status = acpi_hw_enable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
"Registered GPE method %s as GPE number 0x%.2X\n", "Registered GPE method %s as GPE number 0x%.2X\n",
name, gpe_number)); name, gpe_number));
...@@ -269,6 +267,122 @@ acpi_ev_save_method_info ( ...@@ -269,6 +267,122 @@ acpi_ev_save_method_info (
} }
/*******************************************************************************
*
* FUNCTION: acpi_ev_get_gpe_type
*
* PARAMETERS: Callback from walk_namespace
*
* RETURN: Status
*
* DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a
* Device. Run the _PRW method. If present, extract the GPE
* number and mark the GPE as a WAKE GPE.
*
******************************************************************************/
static acpi_status
acpi_ev_get_gpe_type (
acpi_handle obj_handle,
u32 level,
void *info,
void **return_value)
{
struct acpi_gpe_walk_info *gpe_info = (void *) info;
struct acpi_namespace_node *gpe_device;
struct acpi_gpe_block_info *gpe_block;
struct acpi_namespace_node *target_gpe_device;
struct acpi_gpe_event_info *gpe_event_info;
union acpi_operand_object *pkg_desc;
union acpi_operand_object *obj_desc;
u32 gpe_number;
acpi_status status;
ACPI_FUNCTION_TRACE ("ev_get_gpe_type");
/* Check for a _PRW method under this device */
status = acpi_ut_evaluate_object (obj_handle, METHOD_NAME__PRW,
ACPI_BTYPE_PACKAGE, &pkg_desc);
if (status == AE_NOT_FOUND) {
return_ACPI_STATUS (AE_OK);
}
else if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/* The returned _PRW package must have at least two elements */
if (pkg_desc->package.count < 2) {
goto cleanup;
}
/* Extract pointers from the input context */
gpe_device = gpe_info->gpe_device;
gpe_block = gpe_info->gpe_block;
/*
* The _PRW object must return a package, we are only interested
* in the first element
*/
obj_desc = pkg_desc->package.elements[0];
if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
/* Use FADT-defined GPE device (from definition of _PRW) */
target_gpe_device = acpi_gbl_fadt_gpe_device;
/* Integer is the GPE number in the FADT described GPE blocks */
gpe_number = (u32) obj_desc->integer.value;
}
else if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) {
/* Package contains a GPE reference and GPE number within a GPE block */
if ((obj_desc->package.count < 2) ||
(ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[0]) != ACPI_TYPE_LOCAL_REFERENCE) ||
(ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[1]) != ACPI_TYPE_INTEGER)) {
goto cleanup;
}
/* Get GPE block reference and decode */
target_gpe_device = obj_desc->package.elements[0]->reference.node;
gpe_number = (u32) obj_desc->package.elements[1]->integer.value;
}
else {
/* Unknown type, just ignore it */
goto cleanup;
}
/*
* Is this GPE within this block?
*
* TRUE iff these conditions are true:
* 1) The GPE devices match.
* 2) The GPE index(number) is within the range of the Gpe Block
* associated with the GPE device.
*/
if ((gpe_device == target_gpe_device) &&
(gpe_number >= gpe_block->block_base_number) &&
(gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) {
/* Mark GPE for WAKE but DISABLED (even for wake) */
gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
gpe_event_info->flags |= ACPI_GPE_TYPE_WAKE;
}
cleanup:
acpi_ut_remove_reference (pkg_desc);
return_ACPI_STATUS (status);
}
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_ev_get_gpe_xrupt_block * FUNCTION: acpi_ev_get_gpe_xrupt_block
...@@ -695,8 +809,13 @@ acpi_ev_create_gpe_block ( ...@@ -695,8 +809,13 @@ acpi_ev_create_gpe_block (
struct acpi_gpe_block_info **return_gpe_block) struct acpi_gpe_block_info **return_gpe_block)
{ {
struct acpi_gpe_block_info *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; acpi_status status;
struct acpi_gpe_walk_info gpe_info;
ACPI_FUNCTION_TRACE ("ev_create_gpe_block"); ACPI_FUNCTION_TRACE ("ev_create_gpe_block");
...@@ -737,7 +856,8 @@ acpi_ev_create_gpe_block ( ...@@ -737,7 +856,8 @@ acpi_ev_create_gpe_block (
/* Dump info about this GPE block */ /* Dump info about this GPE block */
ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE %02d to %02d [%4.4s] %d regs at %8.8X%8.8X on int %d\n", ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
"GPE %02d to %02d [%4.4s] %d regs at %8.8X%8.8X on int %d\n",
gpe_block->block_base_number, gpe_block->block_base_number,
(u32) (gpe_block->block_base_number + (u32) (gpe_block->block_base_number +
((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)), ((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)),
...@@ -752,6 +872,58 @@ acpi_ev_create_gpe_block ( ...@@ -752,6 +872,58 @@ acpi_ev_create_gpe_block (
ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, acpi_ev_save_method_info, ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, acpi_ev_save_method_info,
gpe_block, NULL); gpe_block, NULL);
/*
* 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.)
*/
gpe_info.gpe_block = gpe_block;
gpe_info.gpe_device = gpe_device;
status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_get_gpe_type,
&gpe_info, NULL);
}
/*
* Enable all GPEs in this block that are 1) "runtime" GPEs, and 2) have
* a corresponding _Lxx or _Exx method. All other GPEs must be enabled via
* the acpi_enable_gpe() external interface.
*/
wake_gpe_count = 0;
gpe_enabled_count = 0;
for (i = 0; i < gpe_block->register_count; i++) {
for (j = 0; j < 8; j++) {
/* Get the info block for this particular GPE */
gpe_event_info = &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
if ((gpe_event_info->method_node) &&
((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == ACPI_GPE_TYPE_RUNTIME)) {
/* Enable this GPE, it is 1) RUNTIME and 2) has an _Lxx or _Exx method */
status = acpi_hw_enable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
gpe_enabled_count++;
}
if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == ACPI_GPE_TYPE_WAKE) {
wake_gpe_count++;
}
}
}
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 */ /* Return the new block */
if (return_gpe_block) { if (return_gpe_block) {
...@@ -775,27 +947,25 @@ acpi_ev_create_gpe_block ( ...@@ -775,27 +947,25 @@ acpi_ev_create_gpe_block (
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_ev_gpe_initialize (void) acpi_ev_gpe_initialize (
void)
{ {
u32 register_count0 = 0; u32 register_count0 = 0;
u32 register_count1 = 0; u32 register_count1 = 0;
u32 gpe_number_max = 0; u32 gpe_number_max = 0;
acpi_handle gpe_device;
acpi_status status; acpi_status status;
ACPI_FUNCTION_TRACE ("ev_gpe_initialize"); ACPI_FUNCTION_TRACE ("ev_gpe_initialize");
/* Get a handle to the predefined _GPE object */ status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
status = acpi_get_handle (NULL, "\\_GPE", &gpe_device);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
/* /*
* Initialize the GPE Blocks defined in the FADT * Initialize the GPE Block(s) defined in the FADT
* *
* Why the GPE register block lengths are divided by 2: From the ACPI Spec, * Why the GPE register block lengths are divided by 2: From the ACPI Spec,
* section "General-Purpose Event Registers", we have: * section "General-Purpose Event Registers", we have:
...@@ -829,8 +999,9 @@ acpi_ev_gpe_initialize (void) ...@@ -829,8 +999,9 @@ acpi_ev_gpe_initialize (void)
/* Install GPE Block 0 */ /* Install GPE Block 0 */
status = acpi_ev_create_gpe_block (gpe_device, &acpi_gbl_FADT->xgpe0_blk, status = acpi_ev_create_gpe_block (acpi_gbl_fadt_gpe_device, &acpi_gbl_FADT->xgpe0_blk,
register_count0, 0, acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[0]); register_count0, 0, acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[0]);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR (( ACPI_REPORT_ERROR ((
"Could not create GPE Block 0, %s\n", "Could not create GPE Block 0, %s\n",
...@@ -861,9 +1032,10 @@ acpi_ev_gpe_initialize (void) ...@@ -861,9 +1032,10 @@ acpi_ev_gpe_initialize (void)
else { else {
/* Install GPE Block 1 */ /* Install GPE Block 1 */
status = acpi_ev_create_gpe_block (gpe_device, &acpi_gbl_FADT->xgpe1_blk, status = acpi_ev_create_gpe_block (acpi_gbl_fadt_gpe_device, &acpi_gbl_FADT->xgpe1_blk,
register_count1, acpi_gbl_FADT->gpe1_base, register_count1, acpi_gbl_FADT->gpe1_base,
acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[1]); acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[1]);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR (( ACPI_REPORT_ERROR ((
"Could not create GPE Block 1, %s\n", "Could not create GPE Block 1, %s\n",
...@@ -885,7 +1057,8 @@ acpi_ev_gpe_initialize (void) ...@@ -885,7 +1057,8 @@ acpi_ev_gpe_initialize (void)
/* GPEs are not required by ACPI, this is OK */ /* GPEs are not required by ACPI, this is OK */
ACPI_REPORT_INFO (("There are no GPE blocks defined in the FADT\n")); ACPI_REPORT_INFO (("There are no GPE blocks defined in the FADT\n"));
return_ACPI_STATUS (AE_OK); status = AE_OK;
goto cleanup;
} }
/* Check for Max GPE number out-of-range */ /* Check for Max GPE number out-of-range */
...@@ -893,9 +1066,12 @@ acpi_ev_gpe_initialize (void) ...@@ -893,9 +1066,12 @@ acpi_ev_gpe_initialize (void)
if (gpe_number_max > ACPI_GPE_MAX) { if (gpe_number_max > ACPI_GPE_MAX) {
ACPI_REPORT_ERROR (("Maximum GPE number from FADT is too large: 0x%X\n", ACPI_REPORT_ERROR (("Maximum GPE number from FADT is too large: 0x%X\n",
gpe_number_max)); gpe_number_max));
return_ACPI_STATUS (AE_BAD_VALUE); status = AE_BAD_VALUE;
goto cleanup;
} }
cleanup:
(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
return_ACPI_STATUS (AE_OK); return_ACPI_STATUS (AE_OK);
} }
......
...@@ -97,6 +97,20 @@ acpi_ev_is_notify_object ( ...@@ -97,6 +97,20 @@ acpi_ev_is_notify_object (
* *
******************************************************************************/ ******************************************************************************/
#ifdef ACPI_DEBUG_OUTPUT
static const char *acpi_notify_value_names[] =
{
"Bus Check",
"Device Check",
"Device Wake",
"Eject request",
"Device Check Light",
"Frequency Mismatch",
"Bus Mode Mismatch",
"Power Fault"
};
#endif
acpi_status acpi_status
acpi_ev_queue_notify_request ( acpi_ev_queue_notify_request (
struct acpi_namespace_node *node, struct acpi_namespace_node *node,
...@@ -112,7 +126,7 @@ acpi_ev_queue_notify_request ( ...@@ -112,7 +126,7 @@ acpi_ev_queue_notify_request (
/* /*
* For value 1 (Ejection Request), some device method may need to be run. * For value 3 (Ejection Request), some device method may need to be run.
* For value 2 (Device Wake) if _PRW exists, the _PS0 method may need to be run. * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need to be run.
* For value 0x80 (Status Change) on the power button or sleep button, * For value 0x80 (Status Change) on the power button or sleep button,
* initiate soft-off or sleep operation? * initiate soft-off or sleep operation?
...@@ -120,26 +134,13 @@ acpi_ev_queue_notify_request ( ...@@ -120,26 +134,13 @@ acpi_ev_queue_notify_request (
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
"Dispatching Notify(%X) on node %p\n", notify_value, node)); "Dispatching Notify(%X) on node %p\n", notify_value, node));
switch (notify_value) { if (notify_value <= 7) {
case 0: ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: %s\n",
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: Re-enumerate Devices\n")); acpi_notify_value_names[notify_value]));
break; }
else {
case 1: ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "notify value: 0x2.2_x **Device Specific**\n",
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: Ejection Request\n")); notify_value));
break;
case 2:
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: Device Wake\n"));
break;
case 0x80:
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: Status Change\n"));
break;
default:
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Unknown Notify Value: %X \n", notify_value));
break;
} }
/* /*
......
...@@ -247,16 +247,29 @@ acpi_enable_gpe ( ...@@ -247,16 +247,29 @@ acpi_enable_gpe (
goto unlock_and_exit; goto unlock_and_exit;
} }
/* Enable the requested GPE number */ /* Check for Wake vs Runtime GPE */
status = acpi_hw_enable_gpe (gpe_event_info); if (flags & ACPI_EVENT_WAKE_ENABLE) {
/* Ensure the requested wake GPE is disabled */
status = acpi_hw_disable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
goto unlock_and_exit; goto unlock_and_exit;
} }
if (flags & ACPI_EVENT_WAKE_ENABLE) { /* Defer Enable of Wake GPE until sleep time */
acpi_hw_enable_gpe_for_wakeup (gpe_event_info); acpi_hw_enable_gpe_for_wakeup (gpe_event_info);
} }
else {
/* Enable the requested runtime GPE */
status = acpi_hw_enable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
goto unlock_and_exit;
}
}
unlock_and_exit: unlock_and_exit:
if (flags & ACPI_NOT_ISR) { if (flags & ACPI_NOT_ISR) {
......
...@@ -84,14 +84,15 @@ acpi_ex_create_alias ( ...@@ -84,14 +84,15 @@ acpi_ex_create_alias (
alias_node = (struct acpi_namespace_node *) walk_state->operands[0]; alias_node = (struct acpi_namespace_node *) walk_state->operands[0];
target_node = (struct acpi_namespace_node *) walk_state->operands[1]; target_node = (struct acpi_namespace_node *) walk_state->operands[1];
if (target_node->type == ACPI_TYPE_LOCAL_ALIAS) { if ((target_node->type == ACPI_TYPE_LOCAL_ALIAS) ||
(target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
/* /*
* Dereference an existing alias so that we don't create a chain * Dereference an existing alias so that we don't create a chain
* of aliases. With this code, we guarantee that an alias is * of aliases. With this code, we guarantee that an alias is
* always exactly one level of indirection away from the * always exactly one level of indirection away from the
* actual aliased name. * actual aliased name.
*/ */
target_node = (struct acpi_namespace_node *) target_node->object; target_node = ACPI_CAST_PTR (struct acpi_namespace_node, target_node->object);
} }
/* /*
...@@ -117,6 +118,17 @@ acpi_ex_create_alias ( ...@@ -117,6 +118,17 @@ acpi_ex_create_alias (
alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node); alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node);
break; break;
case ACPI_TYPE_METHOD:
/*
* The new alias has the type ALIAS and points to the original
* NS node, not the object itself. This is because for these
* types, the object can change dynamically via a Store.
*/
alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node);
break;
default: default:
/* Attach the original source object to the new Alias Node */ /* Attach the original source object to the new Alias Node */
......
...@@ -774,6 +774,7 @@ acpi_ex_dump_object_descriptor ( ...@@ -774,6 +774,7 @@ acpi_ex_dump_object_descriptor (
case ACPI_TYPE_LOCAL_ALIAS: case ACPI_TYPE_LOCAL_ALIAS:
case ACPI_TYPE_LOCAL_METHOD_ALIAS:
case ACPI_TYPE_LOCAL_EXTRA: case ACPI_TYPE_LOCAL_EXTRA:
case ACPI_TYPE_LOCAL_DATA: case ACPI_TYPE_LOCAL_DATA:
default: default:
......
...@@ -108,10 +108,11 @@ acpi_ex_resolve_node_to_value ( ...@@ -108,10 +108,11 @@ acpi_ex_resolve_node_to_value (
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Entry=%p source_desc=%p [%s]\n", ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Entry=%p source_desc=%p [%s]\n",
node, source_desc, acpi_ut_get_type_name (entry_type))); node, source_desc, acpi_ut_get_type_name (entry_type)));
if (entry_type == ACPI_TYPE_LOCAL_ALIAS) { if ((entry_type == ACPI_TYPE_LOCAL_ALIAS) ||
(entry_type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
/* There is always exactly one level of indirection */ /* There is always exactly one level of indirection */
node = (struct acpi_namespace_node *) node->object; node = ACPI_CAST_PTR (struct acpi_namespace_node, node->object);
source_desc = acpi_ns_get_attached_object (node); source_desc = acpi_ns_get_attached_object (node);
entry_type = acpi_ns_get_type ((acpi_handle) node); entry_type = acpi_ns_get_type ((acpi_handle) node);
*object_ptr = node; *object_ptr = node;
......
...@@ -138,6 +138,7 @@ acpi_ex_resolve_object ( ...@@ -138,6 +138,7 @@ acpi_ex_resolve_object (
case ACPI_TYPE_LOCAL_ALIAS: case ACPI_TYPE_LOCAL_ALIAS:
case ACPI_TYPE_LOCAL_METHOD_ALIAS:
/* /*
* Aliases are resolved by acpi_ex_prep_operands * Aliases are resolved by acpi_ex_prep_operands
......
...@@ -53,9 +53,9 @@ ...@@ -53,9 +53,9 @@
* *
* FUNCTION: acpi_hw_enable_gpe * FUNCTION: acpi_hw_enable_gpe
* *
* PARAMETERS: gpe_number - The GPE * PARAMETERS: gpe_event_info - Info block for the GPE to be enabled
* *
* RETURN: None * RETURN: Status
* *
* DESCRIPTION: Enable a single GPE. * DESCRIPTION: Enable a single GPE.
* *
...@@ -95,7 +95,7 @@ acpi_hw_enable_gpe ( ...@@ -95,7 +95,7 @@ acpi_hw_enable_gpe (
* *
* FUNCTION: acpi_hw_enable_gpe_for_wakeup * FUNCTION: acpi_hw_enable_gpe_for_wakeup
* *
* PARAMETERS: gpe_number - The GPE * PARAMETERS: gpe_event_info - Info block for the GPE to be enabled
* *
* RETURN: None * RETURN: None
* *
...@@ -122,9 +122,11 @@ acpi_hw_enable_gpe_for_wakeup ( ...@@ -122,9 +122,11 @@ acpi_hw_enable_gpe_for_wakeup (
} }
/* /*
* Set the bit so we will not disable this when sleeping * Set the bit so we will not enable this GPE when sleeping (and disable
* it upon wake)
*/ */
gpe_register_info->wake_enable |= gpe_event_info->bit_mask; gpe_register_info->wake_enable |= gpe_event_info->bit_mask;
gpe_event_info->flags |= (ACPI_GPE_TYPE_WAKE | ACPI_GPE_ENABLED);
} }
...@@ -132,9 +134,9 @@ acpi_hw_enable_gpe_for_wakeup ( ...@@ -132,9 +134,9 @@ acpi_hw_enable_gpe_for_wakeup (
* *
* FUNCTION: acpi_hw_disable_gpe * FUNCTION: acpi_hw_disable_gpe
* *
* PARAMETERS: gpe_number - The GPE * PARAMETERS: gpe_event_info - Info block for the GPE to be disabled
* *
* RETURN: None * RETURN: Status
* *
* DESCRIPTION: Disable a single GPE. * DESCRIPTION: Disable a single GPE.
* *
...@@ -177,6 +179,8 @@ acpi_hw_disable_gpe ( ...@@ -177,6 +179,8 @@ acpi_hw_disable_gpe (
return (status); return (status);
} }
/* Make sure this GPE is disabled for wake, also */
acpi_hw_disable_gpe_for_wakeup (gpe_event_info); acpi_hw_disable_gpe_for_wakeup (gpe_event_info);
return (AE_OK); return (AE_OK);
} }
...@@ -186,7 +190,7 @@ acpi_hw_disable_gpe ( ...@@ -186,7 +190,7 @@ acpi_hw_disable_gpe (
* *
* FUNCTION: acpi_hw_disable_gpe_for_wakeup * FUNCTION: acpi_hw_disable_gpe_for_wakeup
* *
* PARAMETERS: gpe_number - The GPE * PARAMETERS: gpe_event_info - Info block for the GPE to be disabled
* *
* RETURN: None * RETURN: None
* *
...@@ -212,9 +216,8 @@ acpi_hw_disable_gpe_for_wakeup ( ...@@ -212,9 +216,8 @@ acpi_hw_disable_gpe_for_wakeup (
return; return;
} }
/* /* Clear the bit so we will disable this when sleeping */
* Clear the bit so we will disable this when sleeping
*/
gpe_register_info->wake_enable &= ~(gpe_event_info->bit_mask); gpe_register_info->wake_enable &= ~(gpe_event_info->bit_mask);
} }
...@@ -223,11 +226,11 @@ acpi_hw_disable_gpe_for_wakeup ( ...@@ -223,11 +226,11 @@ acpi_hw_disable_gpe_for_wakeup (
* *
* FUNCTION: acpi_hw_clear_gpe * FUNCTION: acpi_hw_clear_gpe
* *
* PARAMETERS: gpe_number - The GPE * PARAMETERS: gpe_event_info - Info block for the GPE to be cleared
* *
* RETURN: None * RETURN: status_status
* *
* DESCRIPTION: Clear a single GPE. * DESCRIPTION: Clear the status bit for a single GPE.
* *
******************************************************************************/ ******************************************************************************/
...@@ -256,9 +259,10 @@ acpi_hw_clear_gpe ( ...@@ -256,9 +259,10 @@ acpi_hw_clear_gpe (
* *
* FUNCTION: acpi_hw_get_gpe_status * FUNCTION: acpi_hw_get_gpe_status
* *
* PARAMETERS: gpe_number - The GPE * PARAMETERS: gpe_event_info - Info block for the GPE to queried
* event_status - Where the GPE status is returned
* *
* RETURN: None * RETURN: Status
* *
* DESCRIPTION: Return the status of a single GPE. * DESCRIPTION: Return the status of a single GPE.
* *
...@@ -376,7 +380,7 @@ acpi_hw_disable_gpe_block ( ...@@ -376,7 +380,7 @@ acpi_hw_disable_gpe_block (
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: Clear all GPEs within a GPE block * DESCRIPTION: Clear status bits for all GPEs within a GPE block
* *
******************************************************************************/ ******************************************************************************/
...@@ -392,7 +396,7 @@ acpi_hw_clear_gpe_block ( ...@@ -392,7 +396,7 @@ acpi_hw_clear_gpe_block (
/* Examine each GPE Register within the block */ /* Examine each GPE Register within the block */
for (i = 0; i < gpe_block->register_count; i++) { for (i = 0; i < gpe_block->register_count; i++) {
/* Clear all GPEs in this register */ /* Clear status on all GPEs in this register */
status = acpi_hw_low_level_write (8, 0xFF, status = acpi_hw_low_level_write (8, 0xFF,
&gpe_block->register_info[i].status_address); &gpe_block->register_info[i].status_address);
...@@ -407,19 +411,20 @@ acpi_hw_clear_gpe_block ( ...@@ -407,19 +411,20 @@ acpi_hw_clear_gpe_block (
/****************************************************************************** /******************************************************************************
* *
* FUNCTION: acpi_hw_disable_non_wakeup_gpe_block * FUNCTION: acpi_hw_prepare_gpe_block_for_sleep
* *
* PARAMETERS: gpe_xrupt_info - GPE Interrupt info * PARAMETERS: gpe_xrupt_info - GPE Interrupt info
* gpe_block - Gpe Block info * gpe_block - Gpe Block info
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: Disable all GPEs except wakeup GPEs in a GPE block * DESCRIPTION: Disable all runtime GPEs and enable all wakeup GPEs -- within
* a single GPE block
* *
******************************************************************************/ ******************************************************************************/
static acpi_status static acpi_status
acpi_hw_disable_non_wakeup_gpe_block ( acpi_hw_prepare_gpe_block_for_sleep (
struct acpi_gpe_xrupt_info *gpe_xrupt_info, struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block) struct acpi_gpe_block_info *gpe_block)
{ {
...@@ -437,8 +442,11 @@ acpi_hw_disable_non_wakeup_gpe_block ( ...@@ -437,8 +442,11 @@ acpi_hw_disable_non_wakeup_gpe_block (
for (i = 0; i < gpe_block->register_count; i++) { for (i = 0; i < gpe_block->register_count; i++) {
/* /*
* Read the enabled status of all GPEs. We * Read the enabled/disabled status of all GPEs. We
* will be using it to restore all the GPEs later. * will be using it to restore all the GPEs later.
*
* NOTE: Wake GPEs are are ALL disabled at this time, so when we wake
* and restore this register, they will be automatically disabled.
*/ */
status = acpi_hw_low_level_read (8, &in_value, status = acpi_hw_low_level_read (8, &in_value,
&gpe_register_info->enable_address); &gpe_register_info->enable_address);
...@@ -449,7 +457,8 @@ acpi_hw_disable_non_wakeup_gpe_block ( ...@@ -449,7 +457,8 @@ acpi_hw_disable_non_wakeup_gpe_block (
gpe_register_info->enable = (u8) in_value; gpe_register_info->enable = (u8) in_value;
/* /*
* Disable all GPEs except wakeup GPEs. * 1) Disable all runtime GPEs
* 2) Enable all wakeup GPEs
*/ */
status = acpi_hw_low_level_write (8, gpe_register_info->wake_enable, status = acpi_hw_low_level_write (8, gpe_register_info->wake_enable,
&gpe_register_info->enable_address); &gpe_register_info->enable_address);
...@@ -457,6 +466,8 @@ acpi_hw_disable_non_wakeup_gpe_block ( ...@@ -457,6 +466,8 @@ acpi_hw_disable_non_wakeup_gpe_block (
return (status); return (status);
} }
/* Point to next GPE register */
gpe_register_info++; gpe_register_info++;
} }
...@@ -466,22 +477,22 @@ acpi_hw_disable_non_wakeup_gpe_block ( ...@@ -466,22 +477,22 @@ acpi_hw_disable_non_wakeup_gpe_block (
/****************************************************************************** /******************************************************************************
* *
* FUNCTION: acpi_hw_disable_non_wakeup_gpes * FUNCTION: acpi_hw_prepare_gpes_for_sleep
* *
* PARAMETERS: None * PARAMETERS: None
* *
* RETURN: None * RETURN: Status
* *
* DESCRIPTION: Disable all non-wakeup GPEs * DESCRIPTION: Disable all runtime GPEs, enable all wake GPEs.
* Called with interrupts disabled. The interrupt handler also * Called with interrupts disabled. The interrupt handler also
* modifies gpe_register_info->Enable, so it should not be * modifies gpe_register_info->Enable, so it should not be
* given the chance to run until after non-wake GPEs are * given the chance to run until after the runtime GPEs are
* re-enabled. * re-enabled.
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_hw_disable_non_wakeup_gpes ( acpi_hw_prepare_gpes_for_sleep (
void) void)
{ {
acpi_status status; acpi_status status;
...@@ -490,27 +501,27 @@ acpi_hw_disable_non_wakeup_gpes ( ...@@ -490,27 +501,27 @@ acpi_hw_disable_non_wakeup_gpes (
ACPI_FUNCTION_ENTRY (); ACPI_FUNCTION_ENTRY ();
status = acpi_ev_walk_gpe_list (acpi_hw_disable_non_wakeup_gpe_block); status = acpi_ev_walk_gpe_list (acpi_hw_prepare_gpe_block_for_sleep);
return (status); return (status);
} }
/****************************************************************************** /******************************************************************************
* *
* FUNCTION: acpi_hw_enable_non_wakeup_gpe_block * FUNCTION: acpi_hw_restore_gpe_block_on_wake
* *
* PARAMETERS: gpe_xrupt_info - GPE Interrupt info * PARAMETERS: gpe_xrupt_info - GPE Interrupt info
* gpe_block - Gpe Block info * gpe_block - Gpe Block info
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: Enable a single GPE. * DESCRIPTION: Enable all runtime GPEs and disable all wake GPEs -- in one
* GPE block
* *
******************************************************************************/ ******************************************************************************/
static acpi_status static acpi_status
acpi_hw_enable_non_wakeup_gpe_block ( acpi_hw_restore_gpe_block_on_wake (
struct acpi_gpe_xrupt_info *gpe_xrupt_info, struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block) struct acpi_gpe_block_info *gpe_block)
{ {
...@@ -537,8 +548,12 @@ acpi_hw_enable_non_wakeup_gpe_block ( ...@@ -537,8 +548,12 @@ acpi_hw_enable_non_wakeup_gpe_block (
} }
/* /*
* We previously stored the enabled status of all GPEs. * Restore the GPE Enable register, which will do the following:
* Blast them back in. *
* 1) Disable all wakeup GPEs
* 2) Enable all runtime GPEs
*
* (On sleep, we saved the enabled status of all GPEs)
*/ */
status = acpi_hw_low_level_write (8, gpe_register_info->enable, status = acpi_hw_low_level_write (8, gpe_register_info->enable,
&gpe_register_info->enable_address); &gpe_register_info->enable_address);
...@@ -546,28 +561,30 @@ acpi_hw_enable_non_wakeup_gpe_block ( ...@@ -546,28 +561,30 @@ acpi_hw_enable_non_wakeup_gpe_block (
return (status); return (status);
} }
/* Point to next GPE register */
gpe_register_info++; gpe_register_info++;
} }
return (AE_OK); return (AE_OK);
} }
/****************************************************************************** /******************************************************************************
* *
* FUNCTION: acpi_hw_enable_non_wakeup_gpes * FUNCTION: acpi_hw_restore_gpes_on_wake
* *
* PARAMETERS: None * PARAMETERS: None
* *
* RETURN: None * RETURN: Status
* *
* DESCRIPTION: Enable all non-wakeup GPEs we previously enabled. * DESCRIPTION: Enable all runtime GPEs and disable all wake GPEs -- in all
* GPE blocks
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_hw_enable_non_wakeup_gpes ( acpi_hw_restore_gpes_on_wake (
void) void)
{ {
acpi_status status; acpi_status status;
...@@ -576,7 +593,6 @@ acpi_hw_enable_non_wakeup_gpes ( ...@@ -576,7 +593,6 @@ acpi_hw_enable_non_wakeup_gpes (
ACPI_FUNCTION_ENTRY (); ACPI_FUNCTION_ENTRY ();
status = acpi_ev_walk_gpe_list (acpi_hw_enable_non_wakeup_gpe_block); status = acpi_ev_walk_gpe_list (acpi_hw_restore_gpe_block_on_wake);
return (status); return (status);
} }
...@@ -286,7 +286,11 @@ acpi_enter_sleep_state ( ...@@ -286,7 +286,11 @@ acpi_enter_sleep_state (
} }
} }
status = acpi_hw_disable_non_wakeup_gpes (); /*
* 1) Disable all runtime GPEs
* 2) Enable all wakeup GPEs
*/
status = acpi_hw_prepare_gpes_for_sleep ();
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
...@@ -415,7 +419,11 @@ acpi_enter_sleep_state_s4bios ( ...@@ -415,7 +419,11 @@ acpi_enter_sleep_state_s4bios (
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
status = acpi_hw_disable_non_wakeup_gpes (); /*
* 1) Disable all runtime GPEs
* 2) Enable all wakeup GPEs
*/
status = acpi_hw_prepare_gpes_for_sleep ();
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
...@@ -528,10 +536,14 @@ acpi_leave_sleep_state ( ...@@ -528,10 +536,14 @@ acpi_leave_sleep_state (
if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) { if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
ACPI_REPORT_ERROR (("Method _WAK failed, %s\n", acpi_format_exception (status))); ACPI_REPORT_ERROR (("Method _WAK failed, %s\n", acpi_format_exception (status)));
} }
/* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
/* _WAK returns stuff - do we want to look at it? */ /*
* Restore the GPEs:
status = acpi_hw_enable_non_wakeup_gpes (); * 1) Disable all wakeup GPEs
* 2) Enable all runtime GPEs
*/
status = acpi_hw_restore_gpes_on_wake ();
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
......
...@@ -247,6 +247,14 @@ acpi_ns_root_initialize (void) ...@@ -247,6 +247,14 @@ acpi_ns_root_initialize (void)
unlock_and_exit: unlock_and_exit:
(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
/* Save a handle to "_GPE", it is always present */
if (ACPI_SUCCESS (status)) {
status = acpi_ns_get_node_by_path ("\\_GPE", NULL, ACPI_NS_NO_UPSEARCH,
&acpi_gbl_fadt_gpe_device);
}
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
...@@ -577,6 +585,7 @@ acpi_ns_lookup ( ...@@ -577,6 +585,7 @@ acpi_ns_lookup (
if ((num_segments == 0) && if ((num_segments == 0) &&
(type_to_check_for != ACPI_TYPE_ANY) && (type_to_check_for != ACPI_TYPE_ANY) &&
(type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) && (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) &&
(type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) &&
(type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) && (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) &&
(this_node->type != ACPI_TYPE_ANY) && (this_node->type != ACPI_TYPE_ANY) &&
(this_node->type != type_to_check_for)) { (this_node->type != type_to_check_for)) {
......
...@@ -351,6 +351,7 @@ acpi_ns_dump_one_object ( ...@@ -351,6 +351,7 @@ acpi_ns_dump_one_object (
case ACPI_TYPE_LOCAL_ALIAS: case ACPI_TYPE_LOCAL_ALIAS:
case ACPI_TYPE_LOCAL_METHOD_ALIAS:
acpi_os_printf ("Target %4.4s (%p)\n", acpi_ut_get_node_name (obj_desc), obj_desc); acpi_os_printf ("Target %4.4s (%p)\n", acpi_ut_get_node_name (obj_desc), obj_desc);
break; break;
......
...@@ -310,6 +310,15 @@ acpi_ns_evaluate_by_handle ( ...@@ -310,6 +310,15 @@ acpi_ns_evaluate_by_handle (
return_ACPI_STATUS (AE_BAD_PARAMETER); return_ACPI_STATUS (AE_BAD_PARAMETER);
} }
/*
* For a method alias, we must grab the actual method node
* so that proper scoping context will be established
* before execution.
*/
if (acpi_ns_get_type (node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
node = ACPI_CAST_PTR (struct acpi_namespace_node, node->object);
}
/* /*
* Two major cases here: * Two major cases here:
* 1) The object is an actual control method -- execute it. * 1) The object is an actual control method -- execute it.
......
...@@ -113,6 +113,12 @@ acpi_ns_search_node ( ...@@ -113,6 +113,12 @@ acpi_ns_search_node (
/* Check for match against the name */ /* Check for match against the name */
if (next_node->name.integer == target_name) { if (next_node->name.integer == target_name) {
/* Resolve a control method alias if any */
if (acpi_ns_get_type (next_node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
next_node = ACPI_CAST_PTR (struct acpi_namespace_node, next_node->object);
}
/* /*
* Found matching entry. * Found matching entry.
*/ */
......
...@@ -256,7 +256,7 @@ acpi_ns_get_type ( ...@@ -256,7 +256,7 @@ acpi_ns_get_type (
if (!node) { if (!node) {
ACPI_REPORT_WARNING (("ns_get_type: Null Node ptr")); ACPI_REPORT_WARNING (("ns_get_type: Null Node input pointer\n"));
return_VALUE (ACPI_TYPE_ANY); return_VALUE (ACPI_TYPE_ANY);
} }
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include <acpi/acpi.h> #include <acpi/acpi.h>
#include <acpi/acnamesp.h> #include <acpi/acnamesp.h>
#include <acpi/acinterp.h>
#define _COMPONENT ACPI_NAMESPACE #define _COMPONENT ACPI_NAMESPACE
...@@ -149,11 +150,11 @@ acpi_evaluate_object_typed ( ...@@ -149,11 +150,11 @@ acpi_evaluate_object_typed (
* FUNCTION: acpi_evaluate_object * FUNCTION: acpi_evaluate_object
* *
* PARAMETERS: Handle - Object handle (optional) * PARAMETERS: Handle - Object handle (optional)
* *Pathname - Object pathname (optional) * Pathname - Object pathname (optional)
* **external_params - List of parameters to pass to method, * external_params - List of parameters to pass to method,
* terminated by NULL. May be NULL * terminated by NULL. May be NULL
* if no parameters are being passed. * if no parameters are being passed.
* *return_buffer - Where to put method's return value (if * return_buffer - Where to put method's return value (if
* any). If NULL, no value is returned. * any). If NULL, no value is returned.
* *
* RETURN: Status * RETURN: Status
...@@ -172,6 +173,7 @@ acpi_evaluate_object ( ...@@ -172,6 +173,7 @@ acpi_evaluate_object (
struct acpi_buffer *return_buffer) struct acpi_buffer *return_buffer)
{ {
acpi_status status; acpi_status status;
acpi_status status2;
union acpi_operand_object **internal_params = NULL; union acpi_operand_object **internal_params = NULL;
union acpi_operand_object *internal_return_obj = NULL; union acpi_operand_object *internal_return_obj = NULL;
acpi_size buffer_space_needed; acpi_size buffer_space_needed;
...@@ -321,14 +323,20 @@ acpi_evaluate_object ( ...@@ -321,14 +323,20 @@ acpi_evaluate_object (
} }
} }
/* Delete the return and parameter objects */
if (internal_return_obj) { if (internal_return_obj) {
/*
* Delete the internal return object. NOTE: Interpreter
* must be locked to avoid race condition.
*/
status2 = acpi_ex_enter_interpreter ();
if (ACPI_SUCCESS (status2)) {
/* /*
* Delete the internal return object. (Or at least * Delete the internal return object. (Or at least
* decrement the reference count by one) * decrement the reference count by one)
*/ */
acpi_ut_remove_reference (internal_return_obj); acpi_ut_remove_reference (internal_return_obj);
acpi_ex_exit_interpreter ();
}
} }
/* /*
......
...@@ -88,6 +88,7 @@ acpi_rs_address16_resource ( ...@@ -88,6 +88,7 @@ acpi_rs_address16_resource (
ACPI_FUNCTION_TRACE ("rs_address16_resource"); ACPI_FUNCTION_TRACE ("rs_address16_resource");
/* /*
* Point past the Descriptor to get the number of bytes consumed * Point past the Descriptor to get the number of bytes consumed
*/ */
...@@ -149,7 +150,7 @@ acpi_rs_address16_resource ( ...@@ -149,7 +150,7 @@ acpi_rs_address16_resource (
output_struct->data.address16.attribute.memory.read_write_attribute = output_struct->data.address16.attribute.memory.read_write_attribute =
(u16) (temp8 & 0x01); (u16) (temp8 & 0x01);
output_struct->data.address16.attribute.memory.cache_attribute = output_struct->data.address16.attribute.memory.cache_attribute =
(u16) ((temp8 >> 1) & 0x0F); (u16) ((temp8 >> 1) & 0x03);
} }
else { else {
if (ACPI_IO_RANGE == output_struct->data.address16.resource_type) { if (ACPI_IO_RANGE == output_struct->data.address16.resource_type) {
...@@ -347,7 +348,7 @@ acpi_rs_address16_stream ( ...@@ -347,7 +348,7 @@ acpi_rs_address16_stream (
temp8 |= temp8 |=
(linked_list->data.address16.attribute.memory.cache_attribute & (linked_list->data.address16.attribute.memory.cache_attribute &
0x0F) << 1; 0x03) << 1;
} }
else if (ACPI_IO_RANGE == linked_list->data.address16.resource_type) { else if (ACPI_IO_RANGE == linked_list->data.address16.resource_type) {
temp8 = (u8) temp8 = (u8)
...@@ -539,7 +540,7 @@ acpi_rs_address32_resource ( ...@@ -539,7 +540,7 @@ acpi_rs_address32_resource (
(u16) (temp8 & 0x01); (u16) (temp8 & 0x01);
output_struct->data.address32.attribute.memory.cache_attribute = output_struct->data.address32.attribute.memory.cache_attribute =
(u16) ((temp8 >> 1) & 0x0F); (u16) ((temp8 >> 1) & 0x03);
} }
else { else {
if (ACPI_IO_RANGE == output_struct->data.address32.resource_type) { if (ACPI_IO_RANGE == output_struct->data.address32.resource_type) {
...@@ -735,7 +736,7 @@ acpi_rs_address32_stream ( ...@@ -735,7 +736,7 @@ acpi_rs_address32_stream (
temp8 |= temp8 |=
(linked_list->data.address32.attribute.memory.cache_attribute & (linked_list->data.address32.attribute.memory.cache_attribute &
0x0F) << 1; 0x03) << 1;
} }
else if (ACPI_IO_RANGE == linked_list->data.address32.resource_type) { else if (ACPI_IO_RANGE == linked_list->data.address32.resource_type) {
temp8 = (u8) temp8 = (u8)
...@@ -926,7 +927,7 @@ acpi_rs_address64_resource ( ...@@ -926,7 +927,7 @@ acpi_rs_address64_resource (
(u16) (temp8 & 0x01); (u16) (temp8 & 0x01);
output_struct->data.address64.attribute.memory.cache_attribute = output_struct->data.address64.attribute.memory.cache_attribute =
(u16) ((temp8 >> 1) & 0x0F); (u16) ((temp8 >> 1) & 0x03);
} }
else { else {
if (ACPI_IO_RANGE == output_struct->data.address64.resource_type) { if (ACPI_IO_RANGE == output_struct->data.address64.resource_type) {
...@@ -1124,7 +1125,7 @@ acpi_rs_address64_stream ( ...@@ -1124,7 +1125,7 @@ acpi_rs_address64_stream (
temp8 |= temp8 |=
(linked_list->data.address64.attribute.memory.cache_attribute & (linked_list->data.address64.attribute.memory.cache_attribute &
0x0F) << 1; 0x03) << 1;
} }
else if (ACPI_IO_RANGE == linked_list->data.address64.resource_type) { else if (ACPI_IO_RANGE == linked_list->data.address64.resource_type) {
temp8 = (u8) temp8 = (u8)
......
...@@ -253,14 +253,15 @@ const u8 acpi_gbl_ns_properties[] = ...@@ -253,14 +253,15 @@ const u8 acpi_gbl_ns_properties[] =
ACPI_NS_NORMAL, /* 19 index_field */ ACPI_NS_NORMAL, /* 19 index_field */
ACPI_NS_NORMAL, /* 20 Reference */ ACPI_NS_NORMAL, /* 20 Reference */
ACPI_NS_NORMAL, /* 21 Alias */ ACPI_NS_NORMAL, /* 21 Alias */
ACPI_NS_NORMAL, /* 22 Notify */ ACPI_NS_NORMAL, /* 22 method_alias */
ACPI_NS_NORMAL, /* 23 Address Handler */ ACPI_NS_NORMAL, /* 23 Notify */
ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 24 Resource Desc */ ACPI_NS_NORMAL, /* 24 Address Handler */
ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 25 Resource Field */ ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 25 Resource Desc */
ACPI_NS_NEWSCOPE, /* 26 Scope */ ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 26 Resource Field */
ACPI_NS_NORMAL, /* 27 Extra */ ACPI_NS_NEWSCOPE, /* 27 Scope */
ACPI_NS_NORMAL, /* 28 Data */ ACPI_NS_NORMAL, /* 28 Extra */
ACPI_NS_NORMAL /* 29 Invalid */ ACPI_NS_NORMAL, /* 29 Data */
ACPI_NS_NORMAL /* 30 Invalid */
}; };
...@@ -501,14 +502,15 @@ static const char *acpi_gbl_ns_type_names[] = /* printable nam ...@@ -501,14 +502,15 @@ static const char *acpi_gbl_ns_type_names[] = /* printable nam
/* 19 */ "index_field", /* 19 */ "index_field",
/* 20 */ "Reference", /* 20 */ "Reference",
/* 21 */ "Alias", /* 21 */ "Alias",
/* 22 */ "Notify", /* 22 */ "method_alias",
/* 23 */ "addr_handler", /* 23 */ "Notify",
/* 24 */ "resource_desc", /* 24 */ "addr_handler",
/* 25 */ "resource_fld", /* 25 */ "resource_desc",
/* 26 */ "Scope", /* 26 */ "resource_fld",
/* 27 */ "Extra", /* 27 */ "Scope",
/* 28 */ "Data", /* 28 */ "Extra",
/* 39 */ "Invalid" /* 29 */ "Data",
/* 30 */ "Invalid"
}; };
...@@ -556,7 +558,7 @@ char * ...@@ -556,7 +558,7 @@ char *
acpi_ut_get_node_name ( acpi_ut_get_node_name (
void *object) void *object)
{ {
struct acpi_namespace_node *node; struct acpi_namespace_node *node = (struct acpi_namespace_node *) object;
if (!object) if (!object)
...@@ -564,7 +566,10 @@ acpi_ut_get_node_name ( ...@@ -564,7 +566,10 @@ acpi_ut_get_node_name (
return ("NULL NODE"); return ("NULL NODE");
} }
node = (struct acpi_namespace_node *) object; if (object == ACPI_ROOT_OBJECT)
{
node = acpi_gbl_root_node;
}
if (node->descriptor != ACPI_DESC_TYPE_NAMED) if (node->descriptor != ACPI_DESC_TYPE_NAMED)
{ {
...@@ -782,6 +787,7 @@ acpi_ut_init_globals ( ...@@ -782,6 +787,7 @@ acpi_ut_init_globals (
acpi_gbl_create_osi_method = TRUE; acpi_gbl_create_osi_method = TRUE;
acpi_gbl_all_methods_serialized = FALSE; acpi_gbl_all_methods_serialized = FALSE;
acpi_gbl_leave_wake_gpes_disabled = TRUE;
/* Memory allocation and cache lists */ /* Memory allocation and cache lists */
......
...@@ -529,6 +529,7 @@ acpi_ut_strupr ( ...@@ -529,6 +529,7 @@ acpi_ut_strupr (
return (src_string); return (src_string);
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_ut_mutex_initialize * FUNCTION: acpi_ut_mutex_initialize
...@@ -562,10 +563,8 @@ acpi_ut_mutex_initialize ( ...@@ -562,10 +563,8 @@ acpi_ut_mutex_initialize (
} }
} }
status = acpi_os_create_lock (&acpi_gbl_gpe_lock); status = acpi_os_create_lock (&acpi_gbl_gpe_lock);
return_ACPI_STATUS (status);
return_ACPI_STATUS (AE_OK);
} }
......
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
/* Version string */ /* Version string */
#define ACPI_CA_VERSION 0x20040311 #define ACPI_CA_VERSION 0x20040326
/* Maximum objects in the various object caches */ /* Maximum objects in the various object caches */
......
...@@ -87,6 +87,7 @@ extern u32 acpi_gbl_nesting_level; ...@@ -87,6 +87,7 @@ extern u32 acpi_gbl_nesting_level;
ACPI_EXTERN u8 acpi_gbl_create_osi_method; ACPI_EXTERN u8 acpi_gbl_create_osi_method;
ACPI_EXTERN u8 acpi_gbl_all_methods_serialized; ACPI_EXTERN u8 acpi_gbl_all_methods_serialized;
ACPI_EXTERN u8 acpi_gbl_leave_wake_gpes_disabled;
/***************************************************************************** /*****************************************************************************
* *
...@@ -196,6 +197,7 @@ extern const char *acpi_gbl_valid_osi_strings[ACPI_ ...@@ -196,6 +197,7 @@ extern const char *acpi_gbl_valid_osi_strings[ACPI_
ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct; ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct;
ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node; ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node;
ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device;
extern const u8 acpi_gbl_ns_properties[NUM_NS_TYPES]; extern const u8 acpi_gbl_ns_properties[NUM_NS_TYPES];
extern const struct acpi_predefined_names acpi_gbl_pre_defined_names [NUM_PREDEFINED_NAMES]; extern const struct acpi_predefined_names acpi_gbl_pre_defined_names [NUM_PREDEFINED_NAMES];
......
...@@ -149,11 +149,11 @@ acpi_hw_get_gpe_status ( ...@@ -149,11 +149,11 @@ acpi_hw_get_gpe_status (
acpi_event_status *event_status); acpi_event_status *event_status);
acpi_status acpi_status
acpi_hw_disable_non_wakeup_gpes ( acpi_hw_prepare_gpes_for_sleep (
void); void);
acpi_status acpi_status
acpi_hw_enable_non_wakeup_gpes ( acpi_hw_restore_gpes_on_wake (
void); void);
......
...@@ -360,6 +360,13 @@ struct acpi_gpe_xrupt_info ...@@ -360,6 +360,13 @@ struct acpi_gpe_xrupt_info
}; };
struct acpi_gpe_walk_info
{
struct acpi_namespace_node *gpe_device;
struct acpi_gpe_block_info *gpe_block;
};
typedef acpi_status (*ACPI_GPE_CALLBACK) ( typedef acpi_status (*ACPI_GPE_CALLBACK) (
struct acpi_gpe_xrupt_info *gpe_xrupt_info, struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block); struct acpi_gpe_block_info *gpe_block);
......
...@@ -413,7 +413,7 @@ typedef u32 acpi_table_type; ...@@ -413,7 +413,7 @@ typedef u32 acpi_table_type;
* of the ACPI object_type() operator (See the ACPI Spec). Therefore, * of the ACPI object_type() operator (See the ACPI Spec). Therefore,
* only add to the first group if the spec changes. * only add to the first group if the spec changes.
* *
* Types must be kept in sync with the global acpi_ns_properties * NOTE: Types must be kept in sync with the global acpi_ns_properties
* and acpi_ns_type_names arrays. * and acpi_ns_type_names arrays.
*/ */
typedef u32 acpi_object_type; typedef u32 acpi_object_type;
...@@ -450,26 +450,27 @@ typedef u32 acpi_object_type; ...@@ -450,26 +450,27 @@ typedef u32 acpi_object_type;
#define ACPI_TYPE_LOCAL_INDEX_FIELD 0x13 #define ACPI_TYPE_LOCAL_INDEX_FIELD 0x13
#define ACPI_TYPE_LOCAL_REFERENCE 0x14 /* Arg#, Local#, Name, Debug, ref_of, Index */ #define ACPI_TYPE_LOCAL_REFERENCE 0x14 /* Arg#, Local#, Name, Debug, ref_of, Index */
#define ACPI_TYPE_LOCAL_ALIAS 0x15 #define ACPI_TYPE_LOCAL_ALIAS 0x15
#define ACPI_TYPE_LOCAL_NOTIFY 0x16 #define ACPI_TYPE_LOCAL_METHOD_ALIAS 0x16
#define ACPI_TYPE_LOCAL_ADDRESS_HANDLER 0x17 #define ACPI_TYPE_LOCAL_NOTIFY 0x17
#define ACPI_TYPE_LOCAL_RESOURCE 0x18 #define ACPI_TYPE_LOCAL_ADDRESS_HANDLER 0x18
#define ACPI_TYPE_LOCAL_RESOURCE_FIELD 0x19 #define ACPI_TYPE_LOCAL_RESOURCE 0x19
#define ACPI_TYPE_LOCAL_SCOPE 0x1A /* 1 Name, multiple object_list Nodes */ #define ACPI_TYPE_LOCAL_RESOURCE_FIELD 0x1A
#define ACPI_TYPE_LOCAL_SCOPE 0x1B /* 1 Name, multiple object_list Nodes */
#define ACPI_TYPE_NS_NODE_MAX 0x1A /* Last typecode used within a NS Node */ #define ACPI_TYPE_NS_NODE_MAX 0x1B /* Last typecode used within a NS Node */
/* /*
* These are special object types that never appear in * These are special object types that never appear in
* a Namespace node, only in an union acpi_operand_object * a Namespace node, only in an union acpi_operand_object
*/ */
#define ACPI_TYPE_LOCAL_EXTRA 0x1B #define ACPI_TYPE_LOCAL_EXTRA 0x1C
#define ACPI_TYPE_LOCAL_DATA 0x1C #define ACPI_TYPE_LOCAL_DATA 0x1D
#define ACPI_TYPE_LOCAL_MAX 0x1C #define ACPI_TYPE_LOCAL_MAX 0x1D
/* All types above here are invalid */ /* All types above here are invalid */
#define ACPI_TYPE_INVALID 0x1D #define ACPI_TYPE_INVALID 0x1E
#define ACPI_TYPE_NOT_FOUND 0xFF #define ACPI_TYPE_NOT_FOUND 0xFF
...@@ -511,9 +512,8 @@ typedef u32 acpi_object_type; ...@@ -511,9 +512,8 @@ typedef u32 acpi_object_type;
#define ACPI_WRITE 1 #define ACPI_WRITE 1
#define ACPI_IO_MASK 1 #define ACPI_IO_MASK 1
/* /*
* Acpi Event Types: Fixed & General Purpose * Event Types: Fixed & General Purpose
*/ */
typedef u32 acpi_event_type; typedef u32 acpi_event_type;
...@@ -528,25 +528,8 @@ typedef u32 acpi_event_type; ...@@ -528,25 +528,8 @@ typedef u32 acpi_event_type;
#define ACPI_EVENT_MAX 4 #define ACPI_EVENT_MAX 4
#define ACPI_NUM_FIXED_EVENTS ACPI_EVENT_MAX + 1 #define ACPI_NUM_FIXED_EVENTS ACPI_EVENT_MAX + 1
#define ACPI_GPE_INVALID 0xFF
#define ACPI_GPE_MAX 0xFF
#define ACPI_NUM_GPE 256
#define ACPI_EVENT_LEVEL_TRIGGERED 1
#define ACPI_EVENT_EDGE_TRIGGERED 2
/* /*
* Flags for GPE and Lock interfaces * Event Status - Per event
*/
#define ACPI_EVENT_WAKE_ENABLE 0x2
#define ACPI_EVENT_WAKE_DISABLE 0x2
#define ACPI_NOT_ISR 0x1
#define ACPI_ISR 0x0
/*
* acpi_event Status:
* ------------- * -------------
* The encoding of acpi_event_status is illustrated below. * The encoding of acpi_event_status is illustrated below.
* Note that a set bit (1) indicates the property is TRUE * Note that a set bit (1) indicates the property is TRUE
...@@ -567,6 +550,45 @@ typedef u32 acpi_event_status; ...@@ -567,6 +550,45 @@ typedef u32 acpi_event_status;
#define ACPI_EVENT_FLAG_WAKE_ENABLED (acpi_event_status) 0x02 #define ACPI_EVENT_FLAG_WAKE_ENABLED (acpi_event_status) 0x02
#define ACPI_EVENT_FLAG_SET (acpi_event_status) 0x04 #define ACPI_EVENT_FLAG_SET (acpi_event_status) 0x04
/*
* General Purpose Events (GPE)
*/
#define ACPI_GPE_INVALID 0xFF
#define ACPI_GPE_MAX 0xFF
#define ACPI_NUM_GPE 256
/*
* GPE info flags - Per GPE
* +---------+-+-+-+
* |Bits 8:3 |2|1|0|
* +---------+-+-+-+
* | | | |
* | | | +- Edge or Level Triggered
* | | +--- Type: Wake or Runtime
* | +----- Enabled for wake?
* +--------<Reserved>
*/
#define ACPI_GPE_XRUPT_TYPE_MASK (u8) 1
#define ACPI_GPE_LEVEL_TRIGGERED (u8) 1
#define ACPI_GPE_EDGE_TRIGGERED (u8) 0
#define ACPI_GPE_TYPE_MASK (u8) 2
#define ACPI_GPE_TYPE_WAKE (u8) 2
#define ACPI_GPE_TYPE_RUNTIME (u8) 0 /* Default */
#define ACPI_GPE_ENABLE_MASK (u8) 4
#define ACPI_GPE_ENABLED (u8) 4
#define ACPI_GPE_DISABLED (u8) 0 /* Default */
/*
* Flags for GPE and Lock interfaces
*/
#define ACPI_EVENT_WAKE_ENABLE 0x2
#define ACPI_EVENT_WAKE_DISABLE 0x2
#define ACPI_NOT_ISR 0x1
#define ACPI_ISR 0x0
/* Notify types */ /* Notify types */
......
...@@ -471,6 +471,7 @@ acpi_ut_delete_internal_object_list ( ...@@ -471,6 +471,7 @@ acpi_ut_delete_internal_object_list (
#define METHOD_NAME__PRT "_PRT" #define METHOD_NAME__PRT "_PRT"
#define METHOD_NAME__CRS "_CRS" #define METHOD_NAME__CRS "_CRS"
#define METHOD_NAME__PRS "_PRS" #define METHOD_NAME__PRS "_PRS"
#define METHOD_NAME__PRW "_PRW"
acpi_status acpi_status
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment