Ejemplo n.º 1
0
/*******************************************************************************
 *
 * 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);
}
Ejemplo n.º 2
0
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);
}