/******************************************************************************* * * FUNCTION: acpi_set_gpe_type * * PARAMETERS: gpe_device - Parent GPE Device * gpe_number - GPE level within the GPE block * Type - New GPE type * * RETURN: Status * * DESCRIPTION: Set the type of an individual GPE * ******************************************************************************/ acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type) { acpi_status status = AE_OK; struct acpi_gpe_event_info *gpe_event_info; ACPI_FUNCTION_TRACE(acpi_set_gpe_type); /* Ensure that we have a valid GPE number */ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); if (!gpe_event_info) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) { return_ACPI_STATUS(AE_OK); } /* Set the new type (will disable GPE if currently enabled) */ status = acpi_ev_set_gpe_type(gpe_event_info, type); unlock_and_exit: return_ACPI_STATUS(status); }
static acpi_status acpi_ev_match_prw_and_gpe(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_match_prw_and_gpe); /* Check for a _PRW method under this device */ status = acpi_ut_evaluate_object(obj_handle, METHOD_NAME__PRW, ACPI_BTYPE_PACKAGE, &pkg_desc); if (ACPI_FAILURE(status)) { /* Ignore all errors from _PRW, we don't want to abort the subsystem */ 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 = 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))) { gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number]; /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */ gpe_event_info->flags &= ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED); status = acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE); if (ACPI_FAILURE(status)) { goto cleanup; } status = acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_DISABLE); } cleanup: acpi_ut_remove_reference(pkg_desc); return_ACPI_STATUS(AE_OK); }