Commit 0f849d2c authored by Lin Ming's avatar Lin Ming Committed by Len Brown

ACPICA: Minimize the differences between linux GPE code and ACPICA code base

We have ported Rafael's major GPE changes
(ACPI: Use GPE reference counting to support shared GPEs) into ACPICA code base.
But the port and Rafael's original patch have some differences, so we made
below patch to make linux GPE code consistent with ACPICA code base.

Most changes are about comments and coding styles.
Other noticeable changes are based on:

Rafael: Reduce code duplication related to GPE lookup
https://patchwork.kernel.org/patch/86237/

Rafael: Always use the same lock for GPE locking
https://patchwork.kernel.org/patch/90471/

A new field gpe_count in struct acpi_gpe_block_info to record the number
of individual GPEs in block.

Rename acpi_ev_save_method_info to acpi_ev_match_gpe_method.
Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: default avatarRobert Moore <robert.moore@intel.com>
Signed-off-by: default avatarLin Ming <ming.m.lin@intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent aa2110cb
...@@ -85,6 +85,10 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info); ...@@ -85,6 +85,10 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info);
struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
u32 gpe_number); u32 gpe_number);
struct acpi_gpe_event_info *acpi_ev_low_get_gpe_info(u32 gpe_number,
struct acpi_gpe_block_info
*gpe_block);
/* /*
* evgpeblk * evgpeblk
*/ */
...@@ -118,9 +122,6 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, ...@@ -118,9 +122,6 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info,
u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list); u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list);
acpi_status
acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info);
acpi_status acpi_ev_gpe_initialize(void); acpi_status acpi_ev_gpe_initialize(void);
/* /*
......
...@@ -427,8 +427,8 @@ struct acpi_gpe_event_info { ...@@ -427,8 +427,8 @@ struct acpi_gpe_event_info {
struct acpi_gpe_register_info *register_info; /* Backpointer to register info */ struct acpi_gpe_register_info *register_info; /* Backpointer to register info */
u8 flags; /* Misc info about this GPE */ u8 flags; /* Misc info about this GPE */
u8 gpe_number; /* This GPE */ u8 gpe_number; /* This GPE */
u8 runtime_count; u8 runtime_count; /* References to a run GPE */
u8 wakeup_count; u8 wakeup_count; /* References to a wake GPE */
}; };
/* Information about a GPE register pair, one per each status/enable pair in an array */ /* Information about a GPE register pair, one per each status/enable pair in an array */
...@@ -454,6 +454,7 @@ struct acpi_gpe_block_info { ...@@ -454,6 +454,7 @@ struct acpi_gpe_block_info {
struct acpi_gpe_event_info *event_info; /* One for each GPE */ struct acpi_gpe_event_info *event_info; /* One for each GPE */
struct acpi_generic_address block_address; /* Base address of the block */ struct acpi_generic_address block_address; /* Base address of the block */
u32 register_count; /* Number of register pairs in block */ u32 register_count; /* Number of register pairs in block */
u16 gpe_count; /* Number of individual GPEs in block */
u8 block_base_number; /* Base GPE number for this block */ u8 block_base_number; /* Base GPE number for this block */
}; };
......
...@@ -60,7 +60,8 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context); ...@@ -60,7 +60,8 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context);
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: Updates GPE register enable masks based on the GPE type * DESCRIPTION: Updates GPE register enable masks based upon whether there are
* references (either wake or run) to this GPE
* *
******************************************************************************/ ******************************************************************************/
...@@ -81,14 +82,20 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info) ...@@ -81,14 +82,20 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
(1 << (1 <<
(gpe_event_info->gpe_number - gpe_register_info->base_gpe_number)); (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number));
/* Clear the wake/run bits up front */
ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, register_bit); ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, register_bit);
ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit); ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);
if (gpe_event_info->runtime_count) /* Set the mask bits only if there are references to this GPE */
if (gpe_event_info->runtime_count) {
ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit); ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit);
}
if (gpe_event_info->wakeup_count) if (gpe_event_info->wakeup_count) {
ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit); ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit);
}
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
} }
...@@ -101,7 +108,10 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info) ...@@ -101,7 +108,10 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: Enable a GPE based on the GPE type * DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless
* of type or number of references.
*
* Note: The GPE lock should be already acquired when this function is called.
* *
******************************************************************************/ ******************************************************************************/
...@@ -109,20 +119,36 @@ acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) ...@@ -109,20 +119,36 @@ acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
{ {
acpi_status status; acpi_status status;
ACPI_FUNCTION_TRACE(ev_enable_gpe); ACPI_FUNCTION_TRACE(ev_enable_gpe);
/* Make sure HW enable masks are updated */
/*
* We will only allow a GPE to be enabled if it has either an
* associated method (_Lxx/_Exx) or a handler. Otherwise, the
* GPE will be immediately disabled by acpi_ev_gpe_dispatch the
* first time it fires.
*/
if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
return_ACPI_STATUS(AE_NO_HANDLER);
}
/* Ensure the HW enable masks are current */
status = acpi_ev_update_gpe_enable_masks(gpe_event_info); status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
}
/* Clear the GPE (of stale events) */
/* Clear the GPE (of stale events), then enable it */
status = acpi_hw_clear_gpe(gpe_event_info); status = acpi_hw_clear_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
}
/* Enable the requested GPE */ /* Enable the requested GPE */
status = acpi_hw_write_gpe_enable_reg(gpe_event_info); status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
...@@ -135,7 +161,10 @@ acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) ...@@ -135,7 +161,10 @@ acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: Disable a GPE based on the GPE type * DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE,
* regardless of the type or number of references.
*
* Note: The GPE lock should be already acquired when this function is called.
* *
******************************************************************************/ ******************************************************************************/
...@@ -145,24 +174,71 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) ...@@ -145,24 +174,71 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
ACPI_FUNCTION_TRACE(ev_disable_gpe); ACPI_FUNCTION_TRACE(ev_disable_gpe);
/* Make sure HW enable masks are updated */
/*
* Note: Always disable the GPE, even if we think that that it is already
* disabled. It is possible that the AML or some other code has enabled
* the GPE behind our back.
*/
/* Ensure the HW enable masks are current */
status = acpi_ev_update_gpe_enable_masks(gpe_event_info); status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
}
/* /*
* Even if we don't know the GPE type, make sure that we always * Always H/W disable this GPE, even if we don't know the GPE type.
* disable it. low_disable_gpe will just clear the enable bit for this * Simply clear the enable bit for this particular GPE, but do not
* GPE and write it. It will not write out the current GPE enable mask, * write out the current GPE enable mask since this may inadvertently
* since this may inadvertently enable GPEs too early, if a rogue GPE has * enable GPEs too early. An example is a rogue GPE that has arrived
* come in during ACPICA initialization - possibly as a result of AML or * during ACPICA initialization - possibly because AML or other code
* other code that has enabled the GPE. * has enabled the GPE.
*/ */
status = acpi_hw_low_disable_gpe(gpe_event_info); status = acpi_hw_low_disable_gpe(gpe_event_info);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
/*******************************************************************************
*
* FUNCTION: acpi_ev_low_get_gpe_info
*
* PARAMETERS: gpe_number - Raw GPE number
* gpe_block - A GPE info block
*
* RETURN: A GPE event_info struct. NULL if not a valid GPE (The gpe_number
* is not within the specified GPE block)
*
* DESCRIPTION: Returns the event_info struct associated with this GPE. This is
* the low-level implementation of ev_get_gpe_event_info.
*
******************************************************************************/
struct acpi_gpe_event_info *acpi_ev_low_get_gpe_info(u32 gpe_number,
struct acpi_gpe_block_info
*gpe_block)
{
u32 gpe_index;
/*
* Validate that the gpe_number is within the specified gpe_block.
* (Two steps)
*/
if (!gpe_block || (gpe_number < gpe_block->block_base_number)) {
return (NULL);
}
gpe_index = gpe_number - gpe_block->block_base_number;
if (gpe_index >= gpe_block->gpe_count) {
return (NULL);
}
return (&gpe_block->event_info[gpe_index]);
}
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_ev_get_gpe_event_info * FUNCTION: acpi_ev_get_gpe_event_info
...@@ -184,7 +260,7 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, ...@@ -184,7 +260,7 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
u32 gpe_number) u32 gpe_number)
{ {
union acpi_operand_object *obj_desc; union acpi_operand_object *obj_desc;
struct acpi_gpe_block_info *gpe_block; struct acpi_gpe_event_info *gpe_info;
u32 i; u32 i;
ACPI_FUNCTION_ENTRY(); ACPI_FUNCTION_ENTRY();
...@@ -196,17 +272,11 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, ...@@ -196,17 +272,11 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
/* Examine GPE Block 0 and 1 (These blocks are permanent) */ /* Examine GPE Block 0 and 1 (These blocks are permanent) */
for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) { for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) {
gpe_block = acpi_gbl_gpe_fadt_blocks[i]; gpe_info = acpi_ev_low_get_gpe_info(gpe_number,
if (gpe_block) { acpi_gbl_gpe_fadt_blocks
if ((gpe_number >= gpe_block->block_base_number) [i]);
&& (gpe_number < if (gpe_info) {
gpe_block->block_base_number + return (gpe_info);
(gpe_block->register_count * 8))) {
return (&gpe_block->
event_info[gpe_number -
gpe_block->
block_base_number]);
}
} }
} }
...@@ -223,16 +293,8 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, ...@@ -223,16 +293,8 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
return (NULL); return (NULL);
} }
gpe_block = obj_desc->device.gpe_block; return (acpi_ev_low_get_gpe_info
(gpe_number, obj_desc->device.gpe_block));
if ((gpe_number >= gpe_block->block_base_number) &&
(gpe_number <
gpe_block->block_base_number + (gpe_block->register_count * 8))) {
return (&gpe_block->
event_info[gpe_number - gpe_block->block_base_number]);
}
return (NULL);
} }
/******************************************************************************* /*******************************************************************************
...@@ -389,7 +451,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) ...@@ -389,7 +451,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
return_VOID; return_VOID;
} }
/* Set the GPE flags for return to enabled state */ /* Update the GPE register masks for return to enabled state */
(void)acpi_ev_update_gpe_enable_masks(gpe_event_info); (void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
...@@ -569,15 +631,18 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) ...@@ -569,15 +631,18 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
default: default:
/* No handler or method to run! */ /*
* No handler or method to run!
* 03/2010: This case should no longer be possible. We will not allow
* a GPE to be enabled if it has no handler or method.
*/
ACPI_ERROR((AE_INFO, ACPI_ERROR((AE_INFO,
"No handler or method for GPE[0x%2X], disabling event", "No handler or method for GPE[0x%2X], disabling event",
gpe_number)); gpe_number));
/* /*
* Disable the GPE. The GPE will remain disabled until the ACPICA * Disable the GPE. The GPE will remain disabled a handler
* Core Subsystem is restarted, or a handler is installed. * is installed or ACPICA is restarted.
*/ */
status = acpi_ev_disable_gpe(gpe_event_info); status = acpi_ev_disable_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
......
...@@ -51,7 +51,7 @@ ACPI_MODULE_NAME("evgpeblk") ...@@ -51,7 +51,7 @@ ACPI_MODULE_NAME("evgpeblk")
/* Local prototypes */ /* Local prototypes */
static acpi_status static acpi_status
acpi_ev_save_method_info(acpi_handle obj_handle, acpi_ev_match_gpe_method(acpi_handle obj_handle,
u32 level, void *obj_desc, void **return_value); u32 level, void *obj_desc, void **return_value);
static acpi_status static acpi_status
...@@ -104,9 +104,7 @@ u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info) ...@@ -104,9 +104,7 @@ u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info)
while (gpe_block) { while (gpe_block) {
if ((&gpe_block->event_info[0] <= gpe_event_info) && if ((&gpe_block->event_info[0] <= gpe_event_info) &&
(&gpe_block->event_info[((acpi_size) (&gpe_block->event_info[gpe_block->gpe_count] >
gpe_block->
register_count) * 8] >
gpe_event_info)) { gpe_event_info)) {
return (TRUE); return (TRUE);
} }
...@@ -229,7 +227,7 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, ...@@ -229,7 +227,7 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_ev_save_method_info * FUNCTION: acpi_ev_match_gpe_method
* *
* PARAMETERS: Callback from walk_namespace * PARAMETERS: Callback from walk_namespace
* *
...@@ -241,8 +239,7 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, ...@@ -241,8 +239,7 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
* 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:
* "_Lxx" or "_Exx" * "_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
* xx - is the GPE number [in HEX] * xx - is the GPE number [in HEX]
...@@ -250,9 +247,11 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, ...@@ -250,9 +247,11 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
******************************************************************************/ ******************************************************************************/
static acpi_status static acpi_status
acpi_ev_save_method_info(acpi_handle obj_handle, acpi_ev_match_gpe_method(acpi_handle obj_handle,
u32 level, void *obj_desc, void **return_value) u32 level, void *obj_desc, void **return_value)
{ {
struct acpi_namespace_node *method_node =
ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
struct acpi_gpe_block_info *gpe_block = (void *)obj_desc; struct acpi_gpe_block_info *gpe_block = (void *)obj_desc;
struct acpi_gpe_event_info *gpe_event_info; struct acpi_gpe_event_info *gpe_event_info;
u32 gpe_number; u32 gpe_number;
...@@ -262,21 +261,25 @@ acpi_ev_save_method_info(acpi_handle obj_handle, ...@@ -262,21 +261,25 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
ACPI_FUNCTION_TRACE(ev_save_method_info); ACPI_FUNCTION_TRACE(ev_save_method_info);
/* /*
* _Lxx and _Exx GPE method support * Match and decode the _Lxx and _Exx GPE method names
* *
* 1) Extract the name from the object and convert to a string * 1) Extract the method name and null terminate it
*/ */
ACPI_MOVE_32_TO_32(name, ACPI_MOVE_32_TO_32(name, &method_node->name.integer);
&((struct acpi_namespace_node *)obj_handle)->name.
integer);
name[ACPI_NAME_SIZE] = 0; name[ACPI_NAME_SIZE] = 0;
/* 2) Name must begin with an underscore */
if (name[0] != '_') {
return_ACPI_STATUS(AE_OK); /* Ignore this method */
}
/* /*
* 2) Edge/Level determination is based on the 2nd character * 3) 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 * NOTE: Default GPE type is RUNTIME only. Later, if a _PRW object is
* if a _PRW object is found that points to this GPE. * found that points to this GPE, the ACPI_GPE_CAN_WAKE flag is set.
*/ */
switch (name[1]) { switch (name[1]) {
case 'L': case 'L':
...@@ -288,7 +291,7 @@ acpi_ev_save_method_info(acpi_handle obj_handle, ...@@ -288,7 +291,7 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
break; break;
default: default:
/* Unknown method type, just ignore it! */ /* Unknown method type, just ignore it */
ACPI_DEBUG_PRINT((ACPI_DB_LOAD, ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
"Ignoring unknown GPE method type: %s " "Ignoring unknown GPE method type: %s "
...@@ -296,7 +299,7 @@ acpi_ev_save_method_info(acpi_handle obj_handle, ...@@ -296,7 +299,7 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
} }
/* Convert the last two characters of the name to the GPE Number */ /* 4) The last two characters of the name are the hex GPE Number */
gpe_number = ACPI_STRTOUL(&name[2], NULL, 16); gpe_number = ACPI_STRTOUL(&name[2], NULL, 16);
if (gpe_number == ACPI_UINT32_MAX) { if (gpe_number == ACPI_UINT32_MAX) {
...@@ -311,28 +314,22 @@ acpi_ev_save_method_info(acpi_handle obj_handle, ...@@ -311,28 +314,22 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
/* Ensure that we have a valid GPE number for this GPE block */ /* Ensure that we have a valid GPE number for this GPE block */
if ((gpe_number < gpe_block->block_base_number) || gpe_event_info = acpi_ev_low_get_gpe_info(gpe_number, gpe_block);
(gpe_number >= (gpe_block->block_base_number + if (!gpe_event_info) {
(gpe_block->register_count * 8)))) {
/* /*
* Not valid for this GPE block, just ignore it. However, it may be * This gpe_number is not valid for this GPE block, just ignore it.
* valid for a different GPE block, since GPE0 and GPE1 methods both * However, it may be valid for a different GPE block, since GPE0
* appear under \_GPE. * and GPE1 methods both appear under \_GPE.
*/ */
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
} }
/* /*
* Now we can add this information to the gpe_event_info block for use * Add the GPE information from above to the gpe_event_info block for
* during dispatch of this GPE. * use during dispatch of this GPE.
*/ */
gpe_event_info = gpe_event_info->flags = (u8)(type | ACPI_GPE_DISPATCH_METHOD);
&gpe_block->event_info[gpe_number - gpe_block->block_base_number]; gpe_event_info->dispatch.method_node = method_node;
gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD);
gpe_event_info->dispatch.method_node =
(struct acpi_namespace_node *)obj_handle;
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",
...@@ -351,7 +348,7 @@ acpi_ev_save_method_info(acpi_handle obj_handle, ...@@ -351,7 +348,7 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
* *
* DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a * 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. * number and mark the GPE as a CAN_WAKE GPE.
* *
******************************************************************************/ ******************************************************************************/
...@@ -377,7 +374,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, ...@@ -377,7 +374,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
ACPI_BTYPE_PACKAGE, &pkg_desc); ACPI_BTYPE_PACKAGE, &pkg_desc);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
/* Ignore all errors from _PRW, we don't want to abort the subsystem */ /* Ignore all errors from _PRW, we don't want to abort the walk */
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
} }
...@@ -439,13 +436,13 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, ...@@ -439,13 +436,13 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
* 2) The GPE index(number) is within the range of the Gpe Block * 2) The GPE index(number) is within the range of the Gpe Block
* associated with the GPE device. * associated with the GPE device.
*/ */
if ((gpe_device == target_gpe_device) && if (gpe_device != target_gpe_device) {
(gpe_number >= gpe_block->block_base_number) && goto cleanup;
(gpe_number < gpe_block->block_base_number + }
(gpe_block->register_count * 8))) {
gpe_event_info = &gpe_block->event_info[gpe_number - gpe_event_info = acpi_ev_low_get_gpe_info(gpe_number, gpe_block);
gpe_block-> if (gpe_event_info) {
block_base_number]; /* This GPE can wake the system */
gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
} }
...@@ -705,8 +702,7 @@ acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block) ...@@ -705,8 +702,7 @@ acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block)
acpi_os_release_lock(acpi_gbl_gpe_lock, flags); acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
} }
acpi_current_gpe_count -= acpi_current_gpe_count -= gpe_block->gpe_count;
gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH;
/* Free the gpe_block */ /* Free the gpe_block */
...@@ -760,9 +756,7 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) ...@@ -760,9 +756,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 * 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_ALLOCATE_ZEROED(((acpi_size) gpe_block-> gpe_event_info = ACPI_ALLOCATE_ZEROED((acpi_size) gpe_block->gpe_count *
register_count *
ACPI_GPE_REGISTER_WIDTH) *
sizeof(struct sizeof(struct
acpi_gpe_event_info)); acpi_gpe_event_info));
if (!gpe_event_info) { if (!gpe_event_info) {
...@@ -897,6 +891,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, ...@@ -897,6 +891,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
/* Initialize the new GPE block */ /* Initialize the new GPE block */
gpe_block->node = gpe_device; gpe_block->node = gpe_device;
gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH);
gpe_block->register_count = register_count; gpe_block->register_count = register_count;
gpe_block->block_base_number = gpe_block_base_number; gpe_block->block_base_number = gpe_block_base_number;
...@@ -925,7 +920,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, ...@@ -925,7 +920,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device, status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device,
ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
acpi_ev_save_method_info, NULL, acpi_ev_match_gpe_method, NULL,
gpe_block, NULL); gpe_block, NULL);
/* Return the new block */ /* Return the new block */
...@@ -938,14 +933,13 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, ...@@ -938,14 +933,13 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
"GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n", "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,
(u32) (gpe_block->block_base_number + (u32) (gpe_block->block_base_number +
((gpe_block->register_count * (gpe_block->gpe_count - 1)),
ACPI_GPE_REGISTER_WIDTH) - 1)),
gpe_device->name.ascii, gpe_block->register_count, gpe_device->name.ascii, gpe_block->register_count,
interrupt_number)); interrupt_number));
/* Update global count of currently available GPEs */ /* Update global count of currently available GPEs */
acpi_current_gpe_count += register_count * ACPI_GPE_REGISTER_WIDTH; acpi_current_gpe_count += gpe_block->gpe_count;
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
} }
...@@ -969,10 +963,13 @@ acpi_status ...@@ -969,10 +963,13 @@ acpi_status
acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
struct acpi_gpe_block_info *gpe_block) struct acpi_gpe_block_info *gpe_block)
{ {
acpi_status status;
struct acpi_gpe_event_info *gpe_event_info; struct acpi_gpe_event_info *gpe_event_info;
struct acpi_gpe_walk_info gpe_info; struct acpi_gpe_walk_info gpe_info;
u32 wake_gpe_count; u32 wake_gpe_count;
u32 gpe_enabled_count; u32 gpe_enabled_count;
u32 gpe_index;
u32 gpe_number;
u32 i; u32 i;
u32 j; u32 j;
...@@ -998,50 +995,62 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, ...@@ -998,50 +995,62 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
gpe_info.gpe_block = gpe_block; gpe_info.gpe_block = gpe_block;
gpe_info.gpe_device = gpe_device; gpe_info.gpe_device = gpe_device;
acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
acpi_ev_match_prw_and_gpe, NULL, acpi_ev_match_prw_and_gpe, NULL,
&gpe_info, NULL); &gpe_info, NULL);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"While executing _PRW methods"));
}
} }
/* /*
* Enable all GPEs that have a corresponding method and aren't * Enable all GPEs that have a corresponding method and are not
* capable of generating wakeups. Any other GPEs within this block * capable of generating wakeups. Any other GPEs within this block
* must be enabled via the acpi_enable_gpe() interface. * must be enabled via the acpi_enable_gpe interface.
*/ */
wake_gpe_count = 0; wake_gpe_count = 0;
gpe_enabled_count = 0; gpe_enabled_count = 0;
if (gpe_device == acpi_gbl_fadt_gpe_device)
if (gpe_device == acpi_gbl_fadt_gpe_device) {
gpe_device = NULL; gpe_device = NULL;
}
for (i = 0; i < gpe_block->register_count; i++) { for (i = 0; i < gpe_block->register_count; i++) {
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
acpi_status status;
acpi_size gpe_index;
int gpe_number;
/* Get the info block for this particular GPE */ /* Get the info block for this particular GPE */
gpe_index = (acpi_size)i * ACPI_GPE_REGISTER_WIDTH + j;
gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
gpe_event_info = &gpe_block->event_info[gpe_index]; gpe_event_info = &gpe_block->event_info[gpe_index];
if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) { if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {
wake_gpe_count++; wake_gpe_count++;
if (acpi_gbl_leave_wake_gpes_disabled) if (acpi_gbl_leave_wake_gpes_disabled) {
continue; continue;
}
} }
if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)) /* Ignore GPEs that have no corresponding _Lxx/_Exx method */
if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)) {
continue; continue;
}
/* Enable this GPE */
gpe_number = gpe_index + gpe_block->block_base_number; gpe_number = gpe_index + gpe_block->block_base_number;
status = acpi_enable_gpe(gpe_device, gpe_number, status = acpi_enable_gpe(gpe_device, gpe_number,
ACPI_GPE_TYPE_RUNTIME); ACPI_GPE_TYPE_RUNTIME);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, ACPI_EXCEPTION((AE_INFO, status,
"Failed to enable GPE %02X\n", "Could not enable GPE 0x%02X",
gpe_number)); gpe_number));
else continue;
gpe_enabled_count++; }
gpe_enabled_count++;
} }
} }
......
...@@ -682,14 +682,13 @@ acpi_install_gpe_handler(acpi_handle gpe_device, ...@@ -682,14 +682,13 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
/* Parameter validation */ /* Parameter validation */
if ((!address) || (type > ACPI_GPE_XRUPT_TYPE_MASK)) { if ((!address) || (type & ~ACPI_GPE_XRUPT_TYPE_MASK)) {
status = AE_BAD_PARAMETER; return_ACPI_STATUS(AE_BAD_PARAMETER);
goto exit;
} }
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
goto exit; return_ACPI_STATUS(status);
} }
/* Ensure that we have a valid GPE number */ /* Ensure that we have a valid GPE number */
...@@ -720,6 +719,13 @@ acpi_install_gpe_handler(acpi_handle gpe_device, ...@@ -720,6 +719,13 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
handler->context = context; handler->context = context;
handler->method_node = gpe_event_info->dispatch.method_node; handler->method_node = gpe_event_info->dispatch.method_node;
/* Disable the GPE before installing the handler */
status = acpi_ev_disable_gpe(gpe_event_info);
if (ACPI_FAILURE (status)) {
goto unlock_and_exit;
}
/* Install the handler */ /* Install the handler */
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
...@@ -733,12 +739,8 @@ acpi_install_gpe_handler(acpi_handle gpe_device, ...@@ -733,12 +739,8 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
acpi_os_release_lock(acpi_gbl_gpe_lock, flags); acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
unlock_and_exit: unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
exit:
if (ACPI_FAILURE(status))
ACPI_EXCEPTION((AE_INFO, status,
"Installing notify handler failed"));
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
......
...@@ -203,21 +203,26 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event) ...@@ -203,21 +203,26 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event)
* *
* FUNCTION: acpi_set_gpe * FUNCTION: acpi_set_gpe
* *
* PARAMETERS: gpe_device - Parent GPE Device * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
* gpe_number - GPE level within the GPE block * gpe_number - GPE level within the GPE block
* action - Enable or disable * action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
* Called from ISR or not
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: Enable or disable an ACPI event (general purpose) * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
* the reference count mechanism used in the acpi_enable_gpe and
* acpi_disable_gpe interfaces -- and should be used with care.
*
* Note: Typically used to disable a runtime GPE for short period of time,
* then re-enable it, without disturbing the existing reference counts. This
* is useful, for example, in the Embedded Controller (EC) driver.
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action) acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
{ {
acpi_status status = AE_OK;
acpi_cpu_flags flags;
struct acpi_gpe_event_info *gpe_event_info; struct acpi_gpe_event_info *gpe_event_info;
acpi_status status;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(acpi_set_gpe); ACPI_FUNCTION_TRACE(acpi_set_gpe);
...@@ -243,7 +248,6 @@ acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action) ...@@ -243,7 +248,6 @@ acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
break; break;
default: default:
ACPI_ERROR((AE_INFO, "Invalid action\n"));
status = AE_BAD_PARAMETER; status = AE_BAD_PARAMETER;
break; break;
} }
...@@ -259,25 +263,31 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe) ...@@ -259,25 +263,31 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe)
* *
* FUNCTION: acpi_enable_gpe * FUNCTION: acpi_enable_gpe
* *
* PARAMETERS: gpe_device - Parent GPE Device * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
* gpe_number - GPE level within the GPE block * gpe_number - GPE level within the GPE block
* type - Purpose the GPE will be used for * gpe_type - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE
* or both
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: Take a reference to a GPE and enable it if necessary * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
* hardware-enabled (for runtime GPEs), or the GPE register mask
* is updated (for wake GPEs).
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type) acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
acpi_cpu_flags flags;
struct acpi_gpe_event_info *gpe_event_info; struct acpi_gpe_event_info *gpe_event_info;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(acpi_enable_gpe); ACPI_FUNCTION_TRACE(acpi_enable_gpe);
if (type & ~ACPI_GPE_TYPE_WAKE_RUN) /* Parameter validation */
if (!gpe_type || (gpe_type & ~ACPI_GPE_TYPE_WAKE_RUN)) {
return_ACPI_STATUS(AE_BAD_PARAMETER); return_ACPI_STATUS(AE_BAD_PARAMETER);
}
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
...@@ -289,26 +299,43 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type) ...@@ -289,26 +299,43 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type)
goto unlock_and_exit; goto unlock_and_exit;
} }
if (type & ACPI_GPE_TYPE_RUNTIME) { if (gpe_type & ACPI_GPE_TYPE_RUNTIME) {
if (++gpe_event_info->runtime_count == 1) { if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) {
status = AE_LIMIT; /* Too many references */
goto unlock_and_exit;
}
gpe_event_info->runtime_count++;
if (gpe_event_info->runtime_count == 1) {
status = acpi_ev_enable_gpe(gpe_event_info); status = acpi_ev_enable_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status)) {
gpe_event_info->runtime_count--; gpe_event_info->runtime_count--;
goto unlock_and_exit;
}
} }
} }
if (type & ACPI_GPE_TYPE_WAKE) { if (gpe_type & ACPI_GPE_TYPE_WAKE) {
/* The GPE must have the ability to wake the system */
if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
status = AE_BAD_PARAMETER; status = AE_TYPE;
goto unlock_and_exit;
}
if (gpe_event_info->wakeup_count == ACPI_UINT8_MAX) {
status = AE_LIMIT; /* Too many references */
goto unlock_and_exit; goto unlock_and_exit;
} }
/* /*
* Wake-up GPEs are only enabled right prior to putting the * Update the enable mask on the first wakeup reference. Wake GPEs
* system into a sleep state. * are only hardware-enabled just before sleeping.
*/ */
if (++gpe_event_info->wakeup_count == 1) gpe_event_info->wakeup_count++;
acpi_ev_update_gpe_enable_masks(gpe_event_info); if (gpe_event_info->wakeup_count == 1) {
(void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
}
} }
unlock_and_exit: unlock_and_exit:
...@@ -321,27 +348,34 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe) ...@@ -321,27 +348,34 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
* *
* FUNCTION: acpi_disable_gpe * FUNCTION: acpi_disable_gpe
* *
* PARAMETERS: gpe_device - Parent GPE Device * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
* gpe_number - GPE level within the GPE block * gpe_number - GPE level within the GPE block
* type - Purpose the GPE won't be used for any more * gpe_type - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE
* or both
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: Release a reference to a GPE and disable it if necessary * DESCRIPTION: Remove a reference to a GPE. When the last reference is
* removed, only then is the GPE disabled (for runtime GPEs), or
* the GPE mask bit disabled (for wake GPEs)
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type) acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
acpi_cpu_flags flags;
struct acpi_gpe_event_info *gpe_event_info; struct acpi_gpe_event_info *gpe_event_info;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(acpi_disable_gpe); ACPI_FUNCTION_TRACE(acpi_disable_gpe);
if (type & ~ACPI_GPE_TYPE_WAKE_RUN) /* Parameter validation */
if (!gpe_type || (gpe_type & ~ACPI_GPE_TYPE_WAKE_RUN)) {
return_ACPI_STATUS(AE_BAD_PARAMETER); return_ACPI_STATUS(AE_BAD_PARAMETER);
}
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/* Ensure that we have a valid GPE number */ /* Ensure that we have a valid GPE number */
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
...@@ -350,18 +384,39 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type) ...@@ -350,18 +384,39 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type)
goto unlock_and_exit; goto unlock_and_exit;
} }
if ((type & ACPI_GPE_TYPE_RUNTIME) && gpe_event_info->runtime_count) { /* Hardware-disable a runtime GPE on removal of the last reference */
if (--gpe_event_info->runtime_count == 0)
if (gpe_type & ACPI_GPE_TYPE_RUNTIME) {
if (!gpe_event_info->runtime_count) {
status = AE_LIMIT; /* There are no references to remove */
goto unlock_and_exit;
}
gpe_event_info->runtime_count--;
if (!gpe_event_info->runtime_count) {
status = acpi_ev_disable_gpe(gpe_event_info); status = acpi_ev_disable_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) {
gpe_event_info->runtime_count++;
goto unlock_and_exit;
}
}
} }
if ((type & ACPI_GPE_TYPE_WAKE) && gpe_event_info->wakeup_count) { /*
/* * Update masks for wake GPE on removal of the last reference.
* Wake-up GPEs are not enabled after leaving system sleep * No need to hardware-disable wake GPEs here, they are not currently
* states, so we don't need to disable them here. * enabled.
*/ */
if (--gpe_event_info->wakeup_count == 0) if (gpe_type & ACPI_GPE_TYPE_WAKE) {
acpi_ev_update_gpe_enable_masks(gpe_event_info); if (!gpe_event_info->wakeup_count) {
status = AE_LIMIT; /* There are no references to remove */
goto unlock_and_exit;
}
gpe_event_info->wakeup_count--;
if (!gpe_event_info->wakeup_count) {
(void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
}
} }
unlock_and_exit: unlock_and_exit:
...@@ -465,30 +520,23 @@ ACPI_EXPORT_SYMBOL(acpi_clear_event) ...@@ -465,30 +520,23 @@ ACPI_EXPORT_SYMBOL(acpi_clear_event)
* *
* FUNCTION: acpi_clear_gpe * FUNCTION: acpi_clear_gpe
* *
* PARAMETERS: gpe_device - Parent GPE Device * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
* gpe_number - GPE level within the GPE block * gpe_number - GPE level within the GPE block
* Flags - Called from an ISR or not
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: Clear an ACPI event (general purpose) * DESCRIPTION: Clear an ACPI event (general purpose)
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info; struct acpi_gpe_event_info *gpe_event_info;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(acpi_clear_gpe); ACPI_FUNCTION_TRACE(acpi_clear_gpe);
/* Use semaphore lock if not executing at interrupt level */ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
if (flags & ACPI_NOT_ISR) {
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
/* Ensure that we have a valid GPE number */ /* Ensure that we have a valid GPE number */
...@@ -501,9 +549,7 @@ acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) ...@@ -501,9 +549,7 @@ acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
status = acpi_hw_clear_gpe(gpe_event_info); status = acpi_hw_clear_gpe(gpe_event_info);
unlock_and_exit: unlock_and_exit:
if (flags & ACPI_NOT_ISR) { acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
}
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
...@@ -569,9 +615,8 @@ ACPI_EXPORT_SYMBOL(acpi_get_event_status) ...@@ -569,9 +615,8 @@ ACPI_EXPORT_SYMBOL(acpi_get_event_status)
* *
* FUNCTION: acpi_get_gpe_status * FUNCTION: acpi_get_gpe_status
* *
* PARAMETERS: gpe_device - Parent GPE Device * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
* gpe_number - GPE level within the GPE block * gpe_number - GPE level within the GPE block
* Flags - Called from an ISR or not
* event_status - Where the current status of the event will * event_status - Where the current status of the event will
* be returned * be returned
* *
...@@ -582,21 +627,15 @@ ACPI_EXPORT_SYMBOL(acpi_get_event_status) ...@@ -582,21 +627,15 @@ ACPI_EXPORT_SYMBOL(acpi_get_event_status)
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_get_gpe_status(acpi_handle gpe_device, acpi_get_gpe_status(acpi_handle gpe_device,
u32 gpe_number, u32 flags, acpi_event_status * event_status) u32 gpe_number, acpi_event_status *event_status)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info; struct acpi_gpe_event_info *gpe_event_info;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(acpi_get_gpe_status); ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
/* Use semaphore lock if not executing at interrupt level */ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
if (flags & ACPI_NOT_ISR) {
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
/* Ensure that we have a valid GPE number */ /* Ensure that we have a valid GPE number */
...@@ -614,9 +653,7 @@ acpi_get_gpe_status(acpi_handle gpe_device, ...@@ -614,9 +653,7 @@ acpi_get_gpe_status(acpi_handle gpe_device,
*event_status |= ACPI_EVENT_FLAG_HANDLE; *event_status |= ACPI_EVENT_FLAG_HANDLE;
unlock_and_exit: unlock_and_exit:
if (flags & ACPI_NOT_ISR) { acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
}
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
...@@ -673,20 +710,15 @@ acpi_install_gpe_block(acpi_handle gpe_device, ...@@ -673,20 +710,15 @@ acpi_install_gpe_block(acpi_handle gpe_device,
goto unlock_and_exit; goto unlock_and_exit;
} }
/* Run the _PRW methods and enable the GPEs */ /* Install block in the device_object attached to the node */
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); obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) { if (!obj_desc) {
/* No object, create a new one */ /*
* No object, create a new one (Device nodes do not always have
* an attached object)
*/
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE); obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
if (!obj_desc) { if (!obj_desc) {
status = AE_NO_MEMORY; status = AE_NO_MEMORY;
...@@ -705,10 +737,14 @@ acpi_install_gpe_block(acpi_handle gpe_device, ...@@ -705,10 +737,14 @@ acpi_install_gpe_block(acpi_handle gpe_device,
} }
} }
/* Install the GPE block in the device_object */ /* Now install the GPE block in the device_object */
obj_desc->device.gpe_block = gpe_block; obj_desc->device.gpe_block = gpe_block;
/* Run the _PRW methods and enable the runtime GPEs in the new block */
status = acpi_ev_initialize_gpe_block(node, gpe_block);
unlock_and_exit: unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
...@@ -839,8 +875,7 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, ...@@ -839,8 +875,7 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
/* Increment Index by the number of GPEs in this block */ /* Increment Index by the number of GPEs in this block */
info->next_block_base_index += info->next_block_base_index += gpe_block->gpe_count;
(gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH);
if (info->index < info->next_block_base_index) { if (info->index < info->next_block_base_index) {
/* /*
......
...@@ -119,33 +119,6 @@ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state) ...@@ -119,33 +119,6 @@ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
status = AE_AML_OPERAND_TYPE; status = AE_AML_OPERAND_TYPE;
break; break;
} }
#ifdef ACPI_GPE_NOTIFY_CHECK
/*
* GPE method wake/notify check. Here, we want to ensure that we
* don't receive any "DeviceWake" Notifies from a GPE _Lxx or _Exx
* GPE method during system runtime. If we do, the GPE is marked
* as "wake-only" and disabled.
*
* 1) Is the Notify() value == device_wake?
* 2) Is this a GPE deferred method? (An _Lxx or _Exx method)
* 3) Did the original GPE happen at system runtime?
* (versus during wake)
*
* If all three cases are true, this is a wake-only GPE that should
* be disabled at runtime.
*/
if (value == 2) { /* device_wake */
status =
acpi_ev_check_for_wake_only_gpe(walk_state->
gpe_event_info);
if (ACPI_FAILURE(status)) {
/* AE_WAKE_ONLY_GPE only error, means ignore this notify */
return_ACPI_STATUS(AE_OK)
}
}
#endif
/* /*
* Dispatch the notify to the appropriate handler * Dispatch the notify to the appropriate handler
......
...@@ -765,7 +765,7 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) ...@@ -765,7 +765,7 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
} }
status = acpi_get_gpe_status(NULL, device->wakeup.gpe_number, status = acpi_get_gpe_status(NULL, device->wakeup.gpe_number,
ACPI_NOT_ISR, &event_status); &event_status);
if (status == AE_OK) if (status == AE_OK)
device->wakeup.flags.run_wake = device->wakeup.flags.run_wake =
!!(event_status & ACPI_EVENT_FLAG_HANDLE); !!(event_status & ACPI_EVENT_FLAG_HANDLE);
......
...@@ -303,8 +303,7 @@ static int get_status(u32 index, acpi_event_status *status, acpi_handle *handle) ...@@ -303,8 +303,7 @@ static int get_status(u32 index, acpi_event_status *status, acpi_handle *handle)
"Invalid GPE 0x%x\n", index)); "Invalid GPE 0x%x\n", index));
goto end; goto end;
} }
result = acpi_get_gpe_status(*handle, index, result = acpi_get_gpe_status(*handle, index, status);
ACPI_NOT_ISR, status);
} else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS)) } else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS))
result = acpi_get_event_status(index - num_gpes, status); result = acpi_get_event_status(index - num_gpes, status);
...@@ -395,7 +394,7 @@ static ssize_t counter_set(struct kobject *kobj, ...@@ -395,7 +394,7 @@ static ssize_t counter_set(struct kobject *kobj,
result = acpi_set_gpe(handle, index, ACPI_GPE_ENABLE); result = acpi_set_gpe(handle, index, ACPI_GPE_ENABLE);
else if (!strcmp(buf, "clear\n") && else if (!strcmp(buf, "clear\n") &&
(status & ACPI_EVENT_FLAG_SET)) (status & ACPI_EVENT_FLAG_SET))
result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR); result = acpi_clear_gpe(handle, index);
else else
all_counters[index].count = strtoul(buf, NULL, 0); all_counters[index].count = strtoul(buf, NULL, 0);
} else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) { } else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) {
......
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
#define AE_NO_GLOBAL_LOCK (acpi_status) (0x0017 | AE_CODE_ENVIRONMENTAL) #define AE_NO_GLOBAL_LOCK (acpi_status) (0x0017 | AE_CODE_ENVIRONMENTAL)
#define AE_ABORT_METHOD (acpi_status) (0x0018 | AE_CODE_ENVIRONMENTAL) #define AE_ABORT_METHOD (acpi_status) (0x0018 | AE_CODE_ENVIRONMENTAL)
#define AE_SAME_HANDLER (acpi_status) (0x0019 | AE_CODE_ENVIRONMENTAL) #define AE_SAME_HANDLER (acpi_status) (0x0019 | AE_CODE_ENVIRONMENTAL)
#define AE_WAKE_ONLY_GPE (acpi_status) (0x001A | AE_CODE_ENVIRONMENTAL) #define AE_NO_HANDLER (acpi_status) (0x001A | AE_CODE_ENVIRONMENTAL)
#define AE_OWNER_ID_LIMIT (acpi_status) (0x001B | AE_CODE_ENVIRONMENTAL) #define AE_OWNER_ID_LIMIT (acpi_status) (0x001B | AE_CODE_ENVIRONMENTAL)
#define AE_CODE_ENV_MAX 0x001B #define AE_CODE_ENV_MAX 0x001B
......
...@@ -285,16 +285,17 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status); ...@@ -285,16 +285,17 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status);
*/ */
acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action); acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action);
acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type); acpi_status
acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type);
acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type); acpi_status
acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type);
acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags); acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number);
acpi_status acpi_status
acpi_get_gpe_status(acpi_handle gpe_device, acpi_get_gpe_status(acpi_handle gpe_device,
u32 gpe_number, u32 gpe_number, acpi_event_status *event_status);
u32 flags, acpi_event_status * event_status);
acpi_status acpi_disable_all_gpes(void); acpi_status acpi_disable_all_gpes(void);
......
...@@ -663,44 +663,42 @@ typedef u32 acpi_event_status; ...@@ -663,44 +663,42 @@ typedef u32 acpi_event_status;
#define ACPI_GPE_MAX 0xFF #define ACPI_GPE_MAX 0xFF
#define ACPI_NUM_GPE 256 #define ACPI_NUM_GPE 256
/* Actions for acpi_set_gpe */
#define ACPI_GPE_ENABLE 0 #define ACPI_GPE_ENABLE 0
#define ACPI_GPE_DISABLE 1 #define ACPI_GPE_DISABLE 1
/* gpe_types for acpi_enable_gpe and acpi_disable_gpe */
#define ACPI_GPE_TYPE_WAKE (u8) 0x01
#define ACPI_GPE_TYPE_RUNTIME (u8) 0x02
#define ACPI_GPE_TYPE_WAKE_RUN (u8) 0x03
/* /*
* GPE info flags - Per GPE * GPE info flags - Per GPE
* +-+-+-+---+-+-+-+ * +-------+---+-+-+
* |7|6|5|4:3|2|1|0| * | 7:4 |3:2|1|0|
* +-+-+-+---+-+-+-+ * +-------+---+-+-+
* | | | | | | | * | | | |
* | | | | | | +--- Interrupt type: Edge or Level Triggered * | | | +--- Interrupt type: edge or level triggered
* | | | | | +--- GPE can wake the system * | | +----- GPE can wake the system
* | | | | +--- Unused * | +-------- Type of dispatch:to method, handler, or none
* | | | +--- Type of dispatch -- to method, handler, or none * +-------------- <Reserved>
* | | +--- Unused
* | +--- Unused
* +--- Unused
*/ */
#define ACPI_GPE_XRUPT_TYPE_MASK (u8) 0x01 #define ACPI_GPE_XRUPT_TYPE_MASK (u8) 0x01
#define ACPI_GPE_LEVEL_TRIGGERED (u8) 0x01 #define ACPI_GPE_LEVEL_TRIGGERED (u8) 0x01
#define ACPI_GPE_EDGE_TRIGGERED (u8) 0x00 #define ACPI_GPE_EDGE_TRIGGERED (u8) 0x00
#define ACPI_GPE_TYPE_MASK (u8) 0x06
#define ACPI_GPE_TYPE_WAKE_RUN (u8) 0x06
#define ACPI_GPE_TYPE_WAKE (u8) 0x02
#define ACPI_GPE_TYPE_RUNTIME (u8) 0x04 /* Default */
#define ACPI_GPE_CAN_WAKE (u8) 0x02 #define ACPI_GPE_CAN_WAKE (u8) 0x02
#define ACPI_GPE_DISPATCH_MASK (u8) 0x18 #define ACPI_GPE_DISPATCH_MASK (u8) 0x0C
#define ACPI_GPE_DISPATCH_HANDLER (u8) 0x08 #define ACPI_GPE_DISPATCH_HANDLER (u8) 0x04
#define ACPI_GPE_DISPATCH_METHOD (u8) 0x10 #define ACPI_GPE_DISPATCH_METHOD (u8) 0x08
#define ACPI_GPE_DISPATCH_NOT_USED (u8) 0x00 /* Default */ #define ACPI_GPE_DISPATCH_NOT_USED (u8) 0x00
/* /*
* Flags for GPE and Lock interfaces * Flags for GPE and Lock interfaces
*/ */
#define ACPI_EVENT_WAKE_ENABLE 0x2 /* acpi_gpe_enable */
#define ACPI_EVENT_WAKE_DISABLE 0x2 /* acpi_gpe_disable */
#define ACPI_NOT_ISR 0x1 #define ACPI_NOT_ISR 0x1
#define ACPI_ISR 0x0 #define ACPI_ISR 0x0
......
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