|
@@ -211,9 +211,7 @@ acpi_status acpi_ev_gpe_initialize(void)
|
|
|
* DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a
|
|
|
* result of a Load() or load_table() operation. If new GPE
|
|
|
* methods have been installed, register the new methods and
|
|
|
- * enable and runtime GPEs that are associated with them. Also,
|
|
|
- * run any newly loaded _PRW methods in order to discover any
|
|
|
- * new CAN_WAKE GPEs.
|
|
|
+ * enable and runtime GPEs that are associated with them.
|
|
|
*
|
|
|
******************************************************************************/
|
|
|
|
|
@@ -223,49 +221,12 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)
|
|
|
struct acpi_gpe_block_info *gpe_block;
|
|
|
struct acpi_gpe_walk_info walk_info;
|
|
|
acpi_status status = AE_OK;
|
|
|
- u32 new_wake_gpe_count = 0;
|
|
|
-
|
|
|
- /* We will examine only _PRW/_Lxx/_Exx methods owned by this table */
|
|
|
-
|
|
|
- walk_info.owner_id = table_owner_id;
|
|
|
- walk_info.execute_by_owner_id = TRUE;
|
|
|
- walk_info.count = 0;
|
|
|
-
|
|
|
- if (acpi_gbl_leave_wake_gpes_disabled) {
|
|
|
- /*
|
|
|
- * 1) Run any newly-loaded _PRW methods to find any GPEs that
|
|
|
- * can now be marked as CAN_WAKE GPEs. Note: We must run the
|
|
|
- * _PRW methods before we process the _Lxx/_Exx methods because
|
|
|
- * we will enable all runtime GPEs associated with the new
|
|
|
- * _Lxx/_Exx methods at the time we process those methods.
|
|
|
- *
|
|
|
- * Unlock interpreter so that we can run the _PRW methods.
|
|
|
- */
|
|
|
- walk_info.gpe_block = NULL;
|
|
|
- walk_info.gpe_device = NULL;
|
|
|
-
|
|
|
- acpi_ex_exit_interpreter();
|
|
|
-
|
|
|
- status =
|
|
|
- acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
|
|
- ACPI_UINT32_MAX,
|
|
|
- ACPI_NS_WALK_NO_UNLOCK,
|
|
|
- acpi_ev_match_prw_and_gpe, NULL,
|
|
|
- &walk_info, NULL);
|
|
|
- if (ACPI_FAILURE(status)) {
|
|
|
- ACPI_EXCEPTION((AE_INFO, status,
|
|
|
- "While executing _PRW methods"));
|
|
|
- }
|
|
|
-
|
|
|
- acpi_ex_enter_interpreter();
|
|
|
- new_wake_gpe_count = walk_info.count;
|
|
|
- }
|
|
|
|
|
|
/*
|
|
|
* 2) Find any _Lxx/_Exx GPE methods that have just been loaded.
|
|
|
*
|
|
|
- * Any GPEs that correspond to new _Lxx/_Exx methods and are not
|
|
|
- * marked as CAN_WAKE are immediately enabled.
|
|
|
+ * Any GPEs that correspond to new _Lxx/_Exx methods are immediately
|
|
|
+ * enabled.
|
|
|
*
|
|
|
* Examine the namespace underneath each gpe_device within the
|
|
|
* gpe_block lists.
|
|
@@ -275,6 +236,8 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ walk_info.owner_id = table_owner_id;
|
|
|
+ walk_info.execute_by_owner_id = TRUE;
|
|
|
walk_info.count = 0;
|
|
|
walk_info.enable_this_gpe = TRUE;
|
|
|
|
|
@@ -307,10 +270,8 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)
|
|
|
gpe_xrupt_info = gpe_xrupt_info->next;
|
|
|
}
|
|
|
|
|
|
- if (walk_info.count || new_wake_gpe_count) {
|
|
|
- ACPI_INFO((AE_INFO,
|
|
|
- "Enabled %u new runtime GPEs, added %u new wakeup GPEs",
|
|
|
- walk_info.count, new_wake_gpe_count));
|
|
|
+ if (walk_info.count) {
|
|
|
+ ACPI_INFO((AE_INFO, "Enabled %u new GPEs", walk_info.count));
|
|
|
}
|
|
|
|
|
|
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
|
|
@@ -386,9 +347,6 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
|
|
|
/*
|
|
|
* 3) Edge/Level determination is based on the 2nd character
|
|
|
* of the method name
|
|
|
- *
|
|
|
- * 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':
|
|
@@ -471,23 +429,18 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
|
|
|
*/
|
|
|
if (walk_info->enable_this_gpe) {
|
|
|
|
|
|
- /* Ignore GPEs that can wake the system */
|
|
|
+ walk_info->count++;
|
|
|
+ gpe_device = walk_info->gpe_device;
|
|
|
|
|
|
- if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE) ||
|
|
|
- !acpi_gbl_leave_wake_gpes_disabled) {
|
|
|
- walk_info->count++;
|
|
|
- gpe_device = walk_info->gpe_device;
|
|
|
-
|
|
|
- if (gpe_device == acpi_gbl_fadt_gpe_device) {
|
|
|
- gpe_device = NULL;
|
|
|
- }
|
|
|
+ if (gpe_device == acpi_gbl_fadt_gpe_device) {
|
|
|
+ gpe_device = NULL;
|
|
|
+ }
|
|
|
|
|
|
- status = acpi_enable_gpe(gpe_device, gpe_number);
|
|
|
- if (ACPI_FAILURE(status)) {
|
|
|
- ACPI_EXCEPTION((AE_INFO, status,
|
|
|
- "Could not enable GPE 0x%02X",
|
|
|
- gpe_number));
|
|
|
- }
|
|
|
+ status = acpi_enable_gpe(gpe_device, gpe_number);
|
|
|
+ if (ACPI_FAILURE(status)) {
|
|
|
+ ACPI_EXCEPTION((AE_INFO, status,
|
|
|
+ "Could not enable GPE 0x%02X",
|
|
|
+ gpe_number));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -496,157 +449,3 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
|
|
|
name, gpe_number));
|
|
|
return_ACPI_STATUS(AE_OK);
|
|
|
}
|
|
|
-
|
|
|
-/*******************************************************************************
|
|
|
- *
|
|
|
- * FUNCTION: acpi_ev_match_prw_and_gpe
|
|
|
- *
|
|
|
- * PARAMETERS: Callback from walk_namespace
|
|
|
- *
|
|
|
- * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is
|
|
|
- * not aborted on a single _PRW failure.
|
|
|
- *
|
|
|
- * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a
|
|
|
- * Device. Run the _PRW method. If present, extract the GPE
|
|
|
- * number and mark the GPE as a CAN_WAKE GPE. Allows a
|
|
|
- * per-owner_id execution if execute_by_owner_id is TRUE in the
|
|
|
- * walk_info parameter block.
|
|
|
- *
|
|
|
- * If walk_info->execute_by_owner_id is TRUE, we only execute _PRWs with that
|
|
|
- * owner.
|
|
|
- * If walk_info->gpe_device is NULL, we execute every _PRW found. Otherwise,
|
|
|
- * we only execute _PRWs that refer to the input gpe_device.
|
|
|
- *
|
|
|
- ******************************************************************************/
|
|
|
-
|
|
|
-acpi_status
|
|
|
-acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
|
|
|
- u32 level, void *context, void **return_value)
|
|
|
-{
|
|
|
- struct acpi_gpe_walk_info *walk_info =
|
|
|
- ACPI_CAST_PTR(struct acpi_gpe_walk_info, context);
|
|
|
- struct acpi_namespace_node *gpe_device;
|
|
|
- struct acpi_gpe_block_info *gpe_block;
|
|
|
- struct acpi_namespace_node *target_gpe_device;
|
|
|
- struct acpi_namespace_node *prw_node;
|
|
|
- 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_match_prw_and_gpe);
|
|
|
-
|
|
|
- /* Check for a _PRW method under this device */
|
|
|
-
|
|
|
- status = acpi_ns_get_node(obj_handle, METHOD_NAME__PRW,
|
|
|
- ACPI_NS_NO_UPSEARCH, &prw_node);
|
|
|
- if (ACPI_FAILURE(status)) {
|
|
|
- return_ACPI_STATUS(AE_OK);
|
|
|
- }
|
|
|
-
|
|
|
- /* Check if requested owner_id matches this owner_id */
|
|
|
-
|
|
|
- if ((walk_info->execute_by_owner_id) &&
|
|
|
- (prw_node->owner_id != walk_info->owner_id)) {
|
|
|
- return_ACPI_STATUS(AE_OK);
|
|
|
- }
|
|
|
-
|
|
|
- /* Execute the _PRW */
|
|
|
-
|
|
|
- status = acpi_ut_evaluate_object(prw_node, NULL,
|
|
|
- ACPI_BTYPE_PACKAGE, &pkg_desc);
|
|
|
- if (ACPI_FAILURE(status)) {
|
|
|
- return_ACPI_STATUS(AE_OK);
|
|
|
- }
|
|
|
-
|
|
|
- /* 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 = walk_info->gpe_device;
|
|
|
- gpe_block = walk_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 (obj_desc->common.type == ACPI_TYPE_INTEGER) {
|
|
|
-
|
|
|
- /* Use FADT-defined GPE device (from definition of _PRW) */
|
|
|
-
|
|
|
- target_gpe_device = NULL;
|
|
|
- if (gpe_device) {
|
|
|
- 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 (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
|
|
|
-
|
|
|
- /* Package contains a GPE reference and GPE number within a GPE block */
|
|
|
-
|
|
|
- if ((obj_desc->package.count < 2) ||
|
|
|
- ((obj_desc->package.elements[0])->common.type !=
|
|
|
- ACPI_TYPE_LOCAL_REFERENCE) ||
|
|
|
- ((obj_desc->package.elements[1])->common.type !=
|
|
|
- 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;
|
|
|
- }
|
|
|
-
|
|
|
- /* Get the gpe_event_info for this GPE */
|
|
|
-
|
|
|
- if (gpe_device) {
|
|
|
- /*
|
|
|
- * Is this GPE within this block?
|
|
|
- *
|
|
|
- * TRUE if and only if 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) {
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
-
|
|
|
- gpe_event_info =
|
|
|
- acpi_ev_low_get_gpe_info(gpe_number, gpe_block);
|
|
|
- } else {
|
|
|
- /* gpe_device is NULL, just match the target_device and gpe_number */
|
|
|
-
|
|
|
- gpe_event_info =
|
|
|
- acpi_ev_get_gpe_event_info(target_gpe_device, gpe_number);
|
|
|
- }
|
|
|
-
|
|
|
- if (gpe_event_info) {
|
|
|
- if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
|
|
|
-
|
|
|
- /* This GPE can wake the system */
|
|
|
-
|
|
|
- gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
|
|
|
- walk_info->count++;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- cleanup:
|
|
|
- acpi_ut_remove_reference(pkg_desc);
|
|
|
- return_ACPI_STATUS(AE_OK);
|
|
|
-}
|