Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 74d3ec77 authored by Lin Ming's avatar Lin Ming Committed by Len Brown
Browse files

ACPICA: Remove possibility of executing _REG methods twice

If a custom address space handler is installed by the host
before the "initialize operation regions" phase of the ACPICA
initialization, any _REG methods for that address space could
be executed twice. This change fixes the problem.
ACPICA BZ 427.

http://www.acpica.org/bugzilla/show_bug.cgi?id=427



Signed-off-by: default avatarLin Ming <ming.m.lin@intel.com>
Signed-off-by: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 0240d7b4
Loading
Loading
Loading
Loading
+59 −5
Original line number Diff line number Diff line
@@ -51,6 +51,10 @@
ACPI_MODULE_NAME("evregion")

/* Local prototypes */
static u8
acpi_ev_has_default_handler(struct acpi_namespace_node *node,
			    acpi_adr_space_type space_id);

static acpi_status
acpi_ev_reg_run(acpi_handle obj_handle,
		u32 level, void *context, void **return_value);
@@ -140,6 +144,50 @@ acpi_status acpi_ev_install_region_handlers(void)
	return_ACPI_STATUS(status);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ev_has_default_handler
 *
 * PARAMETERS:  Node                - Namespace node for the device
 *              space_id            - The address space ID
 *
 * RETURN:      TRUE if default handler is installed, FALSE otherwise
 *
 * DESCRIPTION: Check if the default handler is installed for the requested
 *              space ID.
 *
 ******************************************************************************/

static u8
acpi_ev_has_default_handler(struct acpi_namespace_node *node,
			    acpi_adr_space_type space_id)
{
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *handler_obj;

	/* Must have an existing internal object */

	obj_desc = acpi_ns_get_attached_object(node);
	if (obj_desc) {
		handler_obj = obj_desc->device.handler;

		/* Walk the linked list of handlers for this object */

		while (handler_obj) {
			if (handler_obj->address_space.space_id == space_id) {
				if (handler_obj->address_space.handler_flags &
				    ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) {
					return (TRUE);
				}
			}

			handler_obj = handler_obj->address_space.next;
		}
	}

	return (FALSE);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ev_initialize_op_regions
@@ -169,13 +217,19 @@ acpi_status acpi_ev_initialize_op_regions(void)

	for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
		/*
		 * TBD: Make sure handler is the DEFAULT handler, otherwise
		 * _REG will have already been run.
		 * Make sure the installed handler is the DEFAULT handler. If not the
		 * default, the _REG methods will have already been run (when the
		 * handler was installed)
		 */
		status = acpi_ev_execute_reg_methods(acpi_gbl_root_node,
		if (acpi_ev_has_default_handler(acpi_gbl_root_node,
						acpi_gbl_default_address_spaces
						[i])) {
			status =
			    acpi_ev_execute_reg_methods(acpi_gbl_root_node,
							acpi_gbl_default_address_spaces
							[i]);
		}
	}

	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
	return_ACPI_STATUS(status);