summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/evgpeblk.c
diff options
context:
space:
mode:
authorLin Ming <ming.m.lin@intel.com>2010-04-06 08:52:37 +0200
committerLen Brown <len.brown@intel.com>2010-04-20 16:43:16 +0200
commit0f849d2cc6863c7874889ea60a871fb71399dd3f (patch)
treec8c14ac12dfc92c7147a049e5374d3a9036247b7 /drivers/acpi/acpica/evgpeblk.c
parentACPI: add boot option acpi=copy_dsdt to fix corrupt DSDT (diff)
downloadlinux-0f849d2cc6863c7874889ea60a871fb71399dd3f.tar.xz
linux-0f849d2cc6863c7874889ea60a871fb71399dd3f.zip
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: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Robert Moore <robert.moore@intel.com> Signed-off-by: Lin Ming <ming.m.lin@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/acpica/evgpeblk.c')
-rw-r--r--drivers/acpi/acpica/evgpeblk.c143
1 files changed, 76 insertions, 67 deletions
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c
index fa47e3522abe..85ded1f2540d 100644
--- a/drivers/acpi/acpica/evgpeblk.c
+++ b/drivers/acpi/acpica/evgpeblk.c
@@ -51,7 +51,7 @@ ACPI_MODULE_NAME("evgpeblk")
/* Local prototypes */
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);
static acpi_status
@@ -104,9 +104,7 @@ u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info)
while (gpe_block) {
if ((&gpe_block->event_info[0] <= gpe_event_info) &&
- (&gpe_block->event_info[((acpi_size)
- gpe_block->
- register_count) * 8] >
+ (&gpe_block->event_info[gpe_block->gpe_count] >
gpe_event_info)) {
return (TRUE);
}
@@ -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
*
@@ -241,8 +239,7 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
* information for quick lookup during GPE dispatch
*
* The name of each GPE control method is of the form:
- * "_Lxx" or "_Exx"
- * Where:
+ * "_Lxx" or "_Exx", where:
* L - means that the GPE is level triggered
* E - means that the GPE is edge triggered
* xx - is the GPE number [in HEX]
@@ -250,9 +247,11 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
******************************************************************************/
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)
{
+ 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_event_info *gpe_event_info;
u32 gpe_number;
@@ -262,21 +261,25 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
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,
- &((struct acpi_namespace_node *)obj_handle)->name.
- integer);
+ ACPI_MOVE_32_TO_32(name, &method_node->name.integer);
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
*
- * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE
- * if a _PRW object is found that points to this GPE.
+ * NOTE: Default GPE type is RUNTIME only. Later, if a _PRW object is
+ * found that points to this GPE, the ACPI_GPE_CAN_WAKE flag is set.
*/
switch (name[1]) {
case 'L':
@@ -288,7 +291,7 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
break;
default:
- /* Unknown method type, just ignore it! */
+ /* Unknown method type, just ignore it */
ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
"Ignoring unknown GPE method type: %s "
@@ -296,7 +299,7 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
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);
if (gpe_number == ACPI_UINT32_MAX) {
@@ -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 */
- if ((gpe_number < gpe_block->block_base_number) ||
- (gpe_number >= (gpe_block->block_base_number +
- (gpe_block->register_count * 8)))) {
+ gpe_event_info = acpi_ev_low_get_gpe_info(gpe_number, gpe_block);
+ if (!gpe_event_info) {
/*
- * Not valid for this GPE block, just ignore it. However, it may be
- * valid for a different GPE block, since GPE0 and GPE1 methods both
- * appear under \_GPE.
+ * This gpe_number is not valid for this GPE block, just ignore it.
+ * However, it may be valid for a different GPE block, since GPE0
+ * and GPE1 methods both appear under \_GPE.
*/
return_ACPI_STATUS(AE_OK);
}
/*
- * Now we can add this information to the gpe_event_info block for use
- * during dispatch of this GPE.
+ * Add the GPE information from above to the gpe_event_info block for
+ * use during dispatch of this GPE.
*/
- gpe_event_info =
- &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
-
- gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD);
-
- gpe_event_info->dispatch.method_node =
- (struct acpi_namespace_node *)obj_handle;
+ gpe_event_info->flags = (u8)(type | ACPI_GPE_DISPATCH_METHOD);
+ gpe_event_info->dispatch.method_node = method_node;
ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
"Registered GPE method %s as GPE number 0x%.2X\n",
@@ -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
* 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,
ACPI_BTYPE_PACKAGE, &pkg_desc);
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);
}
@@ -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
* 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))) {
- gpe_event_info = &gpe_block->event_info[gpe_number -
- gpe_block->
- block_base_number];
+ if (gpe_device != target_gpe_device) {
+ goto cleanup;
+ }
+
+ gpe_event_info = acpi_ev_low_get_gpe_info(gpe_number, gpe_block);
+ if (gpe_event_info) {
+ /* This GPE can wake the system */
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)
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
}
- acpi_current_gpe_count -=
- gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH;
+ acpi_current_gpe_count -= gpe_block->gpe_count;
/* Free the 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
* per register. Initialization to zeros is sufficient.
*/
- gpe_event_info = ACPI_ALLOCATE_ZEROED(((acpi_size) gpe_block->
- register_count *
- ACPI_GPE_REGISTER_WIDTH) *
+ gpe_event_info = ACPI_ALLOCATE_ZEROED((acpi_size) gpe_block->gpe_count *
sizeof(struct
acpi_gpe_event_info));
if (!gpe_event_info) {
@@ -897,6 +891,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
/* Initialize the new GPE block */
gpe_block->node = gpe_device;
+ gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH);
gpe_block->register_count = register_count;
gpe_block->block_base_number = gpe_block_base_number;
@@ -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,
ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
- acpi_ev_save_method_info, NULL,
+ acpi_ev_match_gpe_method, NULL,
gpe_block, NULL);
/* Return the new block */
@@ -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",
(u32) gpe_block->block_base_number,
(u32) (gpe_block->block_base_number +
- ((gpe_block->register_count *
- ACPI_GPE_REGISTER_WIDTH) - 1)),
+ (gpe_block->gpe_count - 1)),
gpe_device->name.ascii, gpe_block->register_count,
interrupt_number));
/* 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);
}
@@ -969,10 +963,13 @@ acpi_status
acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
struct acpi_gpe_block_info *gpe_block)
{
+ acpi_status status;
struct acpi_gpe_event_info *gpe_event_info;
struct acpi_gpe_walk_info gpe_info;
u32 wake_gpe_count;
u32 gpe_enabled_count;
+ u32 gpe_index;
+ u32 gpe_number;
u32 i;
u32 j;
@@ -998,50 +995,62 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
gpe_info.gpe_block = gpe_block;
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_ev_match_prw_and_gpe, 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
- * must be enabled via the acpi_enable_gpe() interface.
+ * must be enabled via the acpi_enable_gpe interface.
*/
wake_gpe_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;
+ }
for (i = 0; i < gpe_block->register_count; i++) {
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 */
- 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];
if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {
wake_gpe_count++;
- if (acpi_gbl_leave_wake_gpes_disabled)
+ if (acpi_gbl_leave_wake_gpes_disabled) {
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;
+ }
+
+ /* Enable this GPE */
gpe_number = gpe_index + gpe_block->block_base_number;
status = acpi_enable_gpe(gpe_device, gpe_number,
- ACPI_GPE_TYPE_RUNTIME);
- if (ACPI_FAILURE(status))
- ACPI_ERROR((AE_INFO,
- "Failed to enable GPE %02X\n",
+ ACPI_GPE_TYPE_RUNTIME);
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not enable GPE 0x%02X",
gpe_number));
- else
- gpe_enabled_count++;
+ continue;
+ }
+
+ gpe_enabled_count++;
}
}