Commit 057b40f4 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'acpi-6.2-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

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
...@@ -389,9 +389,11 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) ...@@ -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 * 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 */ /* Resolve all operands */
......
...@@ -20,13 +20,14 @@ ACPI_MODULE_NAME("evxfregn") ...@@ -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 * PARAMETERS: device - Handle for the device
* space_id - The address space ID * space_id - The address space ID
* handler - Address of the handler * handler - Address of the handler
* setup - Address of the setup function * setup - Address of the setup function
* context - Value passed to the handler on each access * context - Value passed to the handler on each access
* Run_reg - Run _REG methods for this address space?
* *
* RETURN: Status * RETURN: Status
* *
...@@ -37,13 +38,16 @@ ACPI_MODULE_NAME("evxfregn") ...@@ -37,13 +38,16 @@ ACPI_MODULE_NAME("evxfregn")
* are executed here, and these methods can only be safely executed after * are executed here, and these methods can only be safely executed after
* the default handlers have been installed and the hardware has been * the default handlers have been installed and the hardware has been
* initialized (via acpi_enable_subsystem.) * 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 static acpi_status
acpi_install_address_space_handler(acpi_handle device, acpi_install_address_space_handler_internal(acpi_handle device,
acpi_adr_space_type space_id, acpi_adr_space_type space_id,
acpi_adr_space_handler handler, 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; struct acpi_namespace_node *node;
acpi_status status; acpi_status status;
...@@ -80,14 +84,40 @@ acpi_install_address_space_handler(acpi_handle device, ...@@ -80,14 +84,40 @@ acpi_install_address_space_handler(acpi_handle device,
/* Run all _REG methods for this address space */ /* Run all _REG methods for this address space */
acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT); if (run_reg) {
acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
}
unlock_and_exit: unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_ACPI_STATUS(status); 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_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, ...@@ -228,3 +258,51 @@ acpi_remove_address_space_handler(acpi_handle device,
} }
ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler) 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)
...@@ -94,6 +94,7 @@ enum { ...@@ -94,6 +94,7 @@ enum {
EC_FLAGS_QUERY_ENABLED, /* Query is enabled */ EC_FLAGS_QUERY_ENABLED, /* Query is enabled */
EC_FLAGS_EVENT_HANDLER_INSTALLED, /* Event handler installed */ EC_FLAGS_EVENT_HANDLER_INSTALLED, /* Event handler installed */
EC_FLAGS_EC_HANDLER_INSTALLED, /* OpReg 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_QUERY_METHODS_INSTALLED, /* _Qxx handlers installed */
EC_FLAGS_STARTED, /* Driver is started */ EC_FLAGS_STARTED, /* Driver is started */
EC_FLAGS_STOPPED, /* Driver is stopped */ EC_FLAGS_STOPPED, /* Driver is stopped */
...@@ -1446,6 +1447,7 @@ static bool install_gpio_irq_event_handler(struct acpi_ec *ec) ...@@ -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_install_handlers - Install service callbacks and register query methods.
* @ec: Target EC. * @ec: Target EC.
* @device: ACPI device object corresponding to @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 * 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 * 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) ...@@ -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, * -EPROBE_DEFER if GPIO IRQ acquisition needs to be deferred,
* or 0 (success) otherwise. * 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; acpi_status status;
...@@ -1466,15 +1469,21 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device) ...@@ -1466,15 +1469,21 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) { if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
acpi_ec_enter_noirq(ec); 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_ADR_SPACE_EC,
&acpi_ec_space_handler, &acpi_ec_space_handler,
NULL, ec); NULL, ec);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
acpi_ec_stop(ec, false); acpi_ec_stop(ec, false);
return -ENODEV; return -ENODEV;
} }
set_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags); 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) if (!device)
...@@ -1526,7 +1535,8 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *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) static void ec_remove_handlers(struct acpi_ec *ec)
{ {
if (test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) { 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))) ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
pr_err("failed to remove space handler\n"); pr_err("failed to remove space handler\n");
clear_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags); clear_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
...@@ -1562,11 +1572,11 @@ static void ec_remove_handlers(struct acpi_ec *ec) ...@@ -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; int ret;
ret = ec_install_handlers(ec, device); ret = ec_install_handlers(ec, device, call_reg);
if (ret) if (ret)
return ret; return ret;
...@@ -1631,7 +1641,7 @@ static int acpi_ec_add(struct acpi_device *device) ...@@ -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) if (ret)
goto err; goto err;
...@@ -1750,7 +1760,7 @@ void __init acpi_ec_dsdt_probe(void) ...@@ -1750,7 +1760,7 @@ void __init acpi_ec_dsdt_probe(void)
* At this point, the GPE is not fully initialized, so do not to * At this point, the GPE is not fully initialized, so do not to
* handle the events. * handle the events.
*/ */
ret = acpi_ec_setup(ec, NULL); ret = acpi_ec_setup(ec, NULL, true);
if (ret) { if (ret) {
acpi_ec_free(ec); acpi_ec_free(ec);
return; return;
...@@ -1944,7 +1954,7 @@ void __init acpi_ec_ecdt_probe(void) ...@@ -1944,7 +1954,7 @@ void __init acpi_ec_ecdt_probe(void)
* At this point, the namespace is not initialized, so do not find * At this point, the namespace is not initialized, so do not find
* the namespace objects, or handle the events. * the namespace objects, or handle the events.
*/ */
ret = acpi_ec_setup(ec, NULL); ret = acpi_ec_setup(ec, NULL, false);
if (ret) { if (ret) {
acpi_ec_free(ec); acpi_ec_free(ec);
goto out; goto out;
......
...@@ -173,6 +173,7 @@ enum acpi_ec_event_state { ...@@ -173,6 +173,7 @@ enum acpi_ec_event_state {
struct acpi_ec { struct acpi_ec {
acpi_handle handle; acpi_handle handle;
acpi_handle address_space_handler_holder;
int gpe; int gpe;
int irq; int irq;
unsigned long command_addr; unsigned long command_addr;
......
...@@ -589,82 +589,92 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status ...@@ -589,82 +589,92 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_install_initialization_handler acpi_install_initialization_handler
(acpi_init_handler handler, u32 function)) (acpi_init_handler handler, u32 function))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_install_sci_handler(acpi_sci_handler acpi_install_sci_handler(acpi_sci_handler
address, address,
void *context)) void *context))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_remove_sci_handler(acpi_sci_handler
address))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_install_global_event_handler acpi_remove_sci_handler(acpi_sci_handler
(acpi_gbl_event_handler handler, address))
void *context))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_install_fixed_event_handler(u32 acpi_install_global_event_handler
acpi_event, (acpi_gbl_event_handler handler,
acpi_event_handler void *context))
handler,
void
*context))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_remove_fixed_event_handler(u32 acpi_event, acpi_install_fixed_event_handler(u32
acpi_event,
acpi_event_handler acpi_event_handler
handler)) handler,
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status void
acpi_install_gpe_handler(acpi_handle *context))
gpe_device,
u32 gpe_number,
u32 type,
acpi_gpe_handler
address,
void *context))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_install_gpe_raw_handler(acpi_handle acpi_remove_fixed_event_handler(u32 acpi_event,
gpe_device, acpi_event_handler
u32 gpe_number, handler))
u32 type,
acpi_gpe_handler
address,
void *context))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_remove_gpe_handler(acpi_handle gpe_device, acpi_install_gpe_handler(acpi_handle
gpe_device,
u32 gpe_number, u32 gpe_number,
u32 type,
acpi_gpe_handler acpi_gpe_handler
address)) address,
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_install_notify_handler(acpi_handle device,
u32 handler_type,
acpi_notify_handler
handler,
void *context)) void *context))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_install_gpe_raw_handler(acpi_handle
gpe_device,
u32 gpe_number,
u32 type,
acpi_gpe_handler
address,
void *context))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_remove_gpe_handler(acpi_handle gpe_device,
u32 gpe_number,
acpi_gpe_handler
address))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_remove_notify_handler(acpi_handle device, acpi_install_notify_handler(acpi_handle device,
u32 handler_type, u32 handler_type,
acpi_notify_handler acpi_notify_handler
handler)) handler,
ACPI_EXTERNAL_RETURN_STATUS(acpi_status void *context))
acpi_install_address_space_handler(acpi_handle ACPI_EXTERNAL_RETURN_STATUS(acpi_status
device, acpi_remove_notify_handler(acpi_handle device,
acpi_adr_space_type u32 handler_type,
space_id, acpi_notify_handler
acpi_adr_space_handler handler))
handler, ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_adr_space_setup acpi_install_address_space_handler(acpi_handle
setup,
void *context))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_remove_address_space_handler(acpi_handle
device, device,
acpi_adr_space_type acpi_adr_space_type
space_id, space_id,
acpi_adr_space_handler acpi_adr_space_handler
handler)) handler,
ACPI_EXTERNAL_RETURN_STATUS(acpi_status acpi_adr_space_setup
acpi_install_exception_handler setup,
(acpi_exception_handler handler)) void *context))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_install_interface_handler acpi_install_address_space_handler_no_reg
(acpi_interface_handler handler)) (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,
acpi_adr_space_type
space_id,
acpi_adr_space_handler
handler))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_install_exception_handler
(acpi_exception_handler handler))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_install_interface_handler
(acpi_interface_handler handler))
/* /*
* Global Lock interfaces * Global Lock interfaces
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment