@@ -27,6 +27,7 @@ ACPI_MODULE_NAME("evxfregn")
* handler - Address of the handler
* setup - Address of the setup function
* context - Value passed to the handler on each access
+ * flags - Flags
*
* RETURN: Status
*
@@ -37,13 +38,18 @@ 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 the ACPI_NO_EXEC__REG flag and
+ * later call this function again with ACPI_NO_INSTALL_SPACE_HANDLER to
+ * execute _REG.
*
******************************************************************************/
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)
+acpi_install_address_space_handler_flags(acpi_handle device,
+ acpi_adr_space_type space_id,
+ acpi_adr_space_handler handler,
+ acpi_adr_space_setup setup,
+ void *context,
+ u32 flags)
{
struct acpi_namespace_node *node;
acpi_status status;
@@ -70,24 +76,24 @@ acpi_install_address_space_handler(acpi_handle device,
}
/* Install the handler for all Regions for this Space ID */
-
- status =
- acpi_ev_install_space_handler(node, space_id, handler, setup,
- context);
- if (ACPI_FAILURE(status)) {
- goto unlock_and_exit;
+ if (!(flags & ACPI_NO_INSTALL_SPACE_HANDLER)) {
+ status =
+ acpi_ev_install_space_handler(node, space_id, handler, setup,
+ context);
+ if (ACPI_FAILURE(status))
+ goto unlock_and_exit;
}
/* Run all _REG methods for this address space */
-
- acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
+ if (!(flags & ACPI_NO_EXEC__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_EXPORT_SYMBOL(acpi_install_address_space_handler)
+ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler_flags)
/*******************************************************************************
*
@@ -645,15 +645,30 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_notify_handler
handler))
ACPI_EXTERNAL_RETURN_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))
+ acpi_install_address_space_handler_flags(acpi_handle
+ device,
+ acpi_adr_space_type
+ space_id,
+ acpi_adr_space_handler
+ handler,
+ acpi_adr_space_setup
+ setup,
+ void *context,
+ u32 flags))
+static ACPI_INLINE 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_flags(
+ device, space_id, handler, setup, context,
+ ACPI_FULL_INITIALIZATION);
+}
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_remove_address_space_handler(acpi_handle
device,
@@ -567,6 +567,8 @@ typedef u64 acpi_integer;
#define ACPI_NO_DEVICE_INIT 0x0040
#define ACPI_NO_EARLY_DEVICE_INIT 0x0080
#define ACPI_NO_ADDRESS_SPACE_INIT 0x0100
+#define ACPI_NO_INSTALL_SPACE_HANDLER 0x0200
+#define ACPI_NO_EXEC__REG 0x0400
/*
* Initialization state
ACPI-2.0 says that the EC OpRegion handler must be available immediately (like the standard default OpRegion handlers). So the OS must probe the ECDT described EC and install the OpRegion handler before calling acpi_enable_subsystem() and acpi_initialize_objects(). This is a problem because calling acpi_install_address_space_handler() does not just install the OpRegion handler, it also runs the EC's _REG method. This _REG method may rely on initialization done by the _INI methods of one of the PCI / _SB root devices. This _REG depends on _INI problem can be fixed by calling the new acpi_early_initialize_objects() function before probing the EC. But on some boards (e.g. Lenovo X1C8) the root devices _INI method relies on the EC OpRegion so executing the _INI methods before registering the EC OpRegion handler leads to errors there. For the default OpRegion handlers the ACPICA code solves these ordering issues by splitting the Opregion handler install and the _REG execution into 2 separate steps: 1. acpi_ev_install_region_handlers(), called early from acpi_load_tables() 2. acpi_ev_initialize_op_regions(), called from acpi_initialize_objects() To fix the similar EC OpRegion issues, add a new flags parameter to acpi_install_address_space_handler() to allow doing things in 2 steps for the EC OpRegion handler too. This will allow using the following initialization order to fix things: 1. acpi_load_tables() 2. probe EC, call acpi_install_address_space_handler(ACPI_NO_EXEC__REG) 3. acpi_enable_subsystem() 4. acpi_early_initialize_objects() 5. call acpi_install_address_space_handler(ACPI_NO_INSTALL_SPACE_HANDLER) to run the EC's _REG method 6. acpi_initialize_objects(ACPI_NO_EARLY_DEVICE_INIT) To avoid having to modify all acpi_install_address_space_handler() callers, the function is renamed to acpi_install_address_space_handler_flags() and a static inline acpi_install_address_space_handler() is provided. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=214899 Signed-off-by: Hans de Goede <hdegoede@redhat.com> --- drivers/acpi/acpica/evxfregn.c | 32 +++++++++++++++++++------------- include/acpi/acpixf.h | 33 ++++++++++++++++++++++++--------- include/acpi/actypes.h | 2 ++ 3 files changed, 45 insertions(+), 22 deletions(-)