Commit 057b40f4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull more ACPI updates from Rafael Wysocki:
 "These fix an AML byte code execution issue in ACPICA and two issues in
  the ACPI EC driver which requires rearranging ACPICA code.

  Specifics:

   - Avoid trying to resolve operands in AML when there are none
     (Amadeusz Sławiński)

   - Fix indentation in include/acpi/acpixf.h to help applying patches
     from the upstream ACPICA git (Hans de Goede)

   - Make it possible to install an address space handler without
     evaluating _REG for Operation Regions in the given address space
     (Hans de Goede)

   - Defer the evaluation of _REG for ECDT described ECs till the
     matching EC device in the DSDT gets parsed and acpi_ec_add() gets
     called for it (Hans de Goede)

   - Fix EC address space handler unregistration (Hans de Goede)"

* tag 'acpi-6.2-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  ACPI: EC: Fix ECDT probe ordering issues
  ACPI: EC: Fix EC address space handler unregistration
  ACPICA: Allow address_space_handler Install and _REG execution as 2 separate steps
  ACPICA: include/acpi/acpixf.h: Fix indentation
  ACPICA: Fix operand resolution
parents 601c1aa8 3d03140c
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -389,9 +389,11 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)

		/*
		 * All opcodes require operand resolution, with the only exceptions
		 * being the object_type and size_of operators.
		 * being the object_type and size_of operators as well as opcodes that
		 * take no arguments.
		 */
		if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE)) {
		if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE) &&
		    (walk_state->op_info->flags & AML_HAS_ARGS)) {

			/* Resolve all operands */

+85 −7
Original line number Diff line number Diff line
@@ -20,13 +20,14 @@ ACPI_MODULE_NAME("evxfregn")

/*******************************************************************************
 *
 * FUNCTION:    acpi_install_address_space_handler
 * FUNCTION:    acpi_install_address_space_handler_internal
 *
 * PARAMETERS:  device          - Handle for the device
 *              space_id        - The address space ID
 *              handler         - Address of the handler
 *              setup           - Address of the setup function
 *              context         - Value passed to the handler on each access
 *              Run_reg         - Run _REG methods for this address space?
 *
 * RETURN:      Status
 *
@@ -37,13 +38,16 @@ ACPI_MODULE_NAME("evxfregn")
 * are executed here, and these methods can only be safely executed after
 * the default handlers have been installed and the hardware has been
 * initialized (via acpi_enable_subsystem.)
 * To avoid this problem pass FALSE for Run_Reg and later on call
 * acpi_execute_reg_methods() to execute _REG.
 *
 ******************************************************************************/
acpi_status
acpi_install_address_space_handler(acpi_handle device,
static acpi_status
acpi_install_address_space_handler_internal(acpi_handle device,
					    acpi_adr_space_type space_id,
					    acpi_adr_space_handler handler,
				   acpi_adr_space_setup setup, void *context)
					    acpi_adr_space_setup setup,
					    void *context, u8 run_reg)
{
	struct acpi_namespace_node *node;
	acpi_status status;
@@ -80,14 +84,40 @@ acpi_install_address_space_handler(acpi_handle device,

	/* Run all _REG methods for this address space */

	if (run_reg) {
		acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
	}

unlock_and_exit:
	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
	return_ACPI_STATUS(status);
}

acpi_status
acpi_install_address_space_handler(acpi_handle device,
				   acpi_adr_space_type space_id,
				   acpi_adr_space_handler handler,
				   acpi_adr_space_setup setup, void *context)
{
	return acpi_install_address_space_handler_internal(device, space_id,
							   handler, setup,
							   context, TRUE);
}

ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler)
acpi_status
acpi_install_address_space_handler_no_reg(acpi_handle device,
					  acpi_adr_space_type space_id,
					  acpi_adr_space_handler handler,
					  acpi_adr_space_setup setup,
					  void *context)
{
	return acpi_install_address_space_handler_internal(device, space_id,
							   handler, setup,
							   context, FALSE);
}

ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler_no_reg)

/*******************************************************************************
 *
@@ -228,3 +258,51 @@ acpi_remove_address_space_handler(acpi_handle device,
}

ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler)
/*******************************************************************************
 *
 * FUNCTION:    acpi_execute_reg_methods
 *
 * PARAMETERS:  device          - Handle for the device
 *              space_id        - The address space ID
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Execute _REG for all op_regions of a given space_id.
 *
 ******************************************************************************/
acpi_status
acpi_execute_reg_methods(acpi_handle device, acpi_adr_space_type space_id)
{
	struct acpi_namespace_node *node;
	acpi_status status;

	ACPI_FUNCTION_TRACE(acpi_execute_reg_methods);

	/* Parameter validation */

	if (!device) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Convert and validate the device handle */

	node = acpi_ns_validate_handle(device);
	if (node) {

		/* Run all _REG methods for this address space */

		acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
	} else {
		status = AE_BAD_PARAMETER;
	}

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

ACPI_EXPORT_SYMBOL(acpi_execute_reg_methods)
+21 −11
Original line number Diff line number Diff line
@@ -94,6 +94,7 @@ enum {
	EC_FLAGS_QUERY_ENABLED,		/* Query is enabled */
	EC_FLAGS_EVENT_HANDLER_INSTALLED,	/* Event handler installed */
	EC_FLAGS_EC_HANDLER_INSTALLED,	/* OpReg handler installed */
	EC_FLAGS_EC_REG_CALLED,		/* OpReg ACPI _REG method called */
	EC_FLAGS_QUERY_METHODS_INSTALLED, /* _Qxx handlers installed */
	EC_FLAGS_STARTED,		/* Driver is started */
	EC_FLAGS_STOPPED,		/* Driver is stopped */
@@ -1446,6 +1447,7 @@ static bool install_gpio_irq_event_handler(struct acpi_ec *ec)
 * ec_install_handlers - Install service callbacks and register query methods.
 * @ec: Target EC.
 * @device: ACPI device object corresponding to @ec.
 * @call_reg: If _REG should be called to notify OpRegion availability
 *
 * Install a handler for the EC address space type unless it has been installed
 * already.  If @device is not NULL, also look for EC query methods in the
@@ -1458,7 +1460,8 @@ static bool install_gpio_irq_event_handler(struct acpi_ec *ec)
 * -EPROBE_DEFER if GPIO IRQ acquisition needs to be deferred,
 * or 0 (success) otherwise.
 */
static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device,
			       bool call_reg)
{
	acpi_status status;

@@ -1466,7 +1469,7 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)

	if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
		acpi_ec_enter_noirq(ec);
		status = acpi_install_address_space_handler(ec->handle,
		status = acpi_install_address_space_handler_no_reg(ec->handle,
								   ACPI_ADR_SPACE_EC,
								   &acpi_ec_space_handler,
								   NULL, ec);
@@ -1475,6 +1478,12 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
			return -ENODEV;
		}
		set_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
		ec->address_space_handler_holder = ec->handle;
	}

	if (call_reg && !test_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags)) {
		acpi_execute_reg_methods(ec->handle, ACPI_ADR_SPACE_EC);
		set_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags);
	}

	if (!device)
@@ -1526,7 +1535,8 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
static void ec_remove_handlers(struct acpi_ec *ec)
{
	if (test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
		if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
		if (ACPI_FAILURE(acpi_remove_address_space_handler(
					ec->address_space_handler_holder,
					ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
			pr_err("failed to remove space handler\n");
		clear_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
@@ -1562,11 +1572,11 @@ static void ec_remove_handlers(struct acpi_ec *ec)
	}
}

static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device)
static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device, bool call_reg)
{
	int ret;

	ret = ec_install_handlers(ec, device);
	ret = ec_install_handlers(ec, device, call_reg);
	if (ret)
		return ret;

@@ -1631,7 +1641,7 @@ static int acpi_ec_add(struct acpi_device *device)
		}
	}

	ret = acpi_ec_setup(ec, device);
	ret = acpi_ec_setup(ec, device, true);
	if (ret)
		goto err;

@@ -1750,7 +1760,7 @@ void __init acpi_ec_dsdt_probe(void)
	 * At this point, the GPE is not fully initialized, so do not to
	 * handle the events.
	 */
	ret = acpi_ec_setup(ec, NULL);
	ret = acpi_ec_setup(ec, NULL, true);
	if (ret) {
		acpi_ec_free(ec);
		return;
@@ -1944,7 +1954,7 @@ void __init acpi_ec_ecdt_probe(void)
	 * At this point, the namespace is not initialized, so do not find
	 * the namespace objects, or handle the events.
	 */
	ret = acpi_ec_setup(ec, NULL);
	ret = acpi_ec_setup(ec, NULL, false);
	if (ret) {
		acpi_ec_free(ec);
		goto out;
+1 −0
Original line number Diff line number Diff line
@@ -173,6 +173,7 @@ enum acpi_ec_event_state {

struct acpi_ec {
	acpi_handle handle;
	acpi_handle address_space_handler_holder;
	int gpe;
	int irq;
	unsigned long command_addr;
+70 −60
Original line number Diff line number Diff line
@@ -652,6 +652,16 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
							       acpi_adr_space_setup
							       setup,
							       void *context))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
			    acpi_install_address_space_handler_no_reg
			    (acpi_handle device, acpi_adr_space_type space_id,
			     acpi_adr_space_handler handler,
			     acpi_adr_space_setup setup,
			     void *context))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
			    acpi_execute_reg_methods(acpi_handle device,
						     acpi_adr_space_type
						     space_id))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
			    acpi_remove_address_space_handler(acpi_handle
							      device,