ACPI: EC: Evaluate orphan _REG under EC device
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 12 Jun 2024 14:15:55 +0000 (16:15 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 13 Jun 2024 09:28:54 +0000 (11:28 +0200)
After starting to install the EC address space handler at the ACPI
namespace root, if there is an "orphan" _REG method in the EC device's
scope, it will not be evaluated any more.  This breaks EC operation
regions on some systems, like Asus gu605.

To address this, use a wrapper around an existing ACPICA function to
look for an "orphan" _REG method in the EC device scope and evaluate
it if present.

Fixes: 60fa6ae6e6d0 ("ACPI: EC: Install address space handler at the namespace root")
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218945
Reported-by: VitaliiT <vitaly.torshyn@gmail.com>
Tested-by: VitaliiT <vitaly.torshyn@gmail.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/acpi/acpica/acevents.h
drivers/acpi/acpica/evregion.c
drivers/acpi/acpica/evxfregn.c
drivers/acpi/ec.c
include/acpi/acpixf.h

index ddd072c..2133085 100644 (file)
@@ -191,6 +191,10 @@ void
 acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
                            acpi_adr_space_type space_id, u32 function);
 
+void
+acpi_ev_execute_orphan_reg_method(struct acpi_namespace_node *node,
+                                 acpi_adr_space_type space_id);
+
 acpi_status
 acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function);
 
index 18fdf2b..dc6004d 100644 (file)
@@ -20,10 +20,6 @@ extern u8 acpi_gbl_default_address_spaces[];
 
 /* Local prototypes */
 
-static void
-acpi_ev_execute_orphan_reg_method(struct acpi_namespace_node *device_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);
@@ -818,7 +814,7 @@ acpi_ev_reg_run(acpi_handle obj_handle,
  *
  ******************************************************************************/
 
-static void
+void
 acpi_ev_execute_orphan_reg_method(struct acpi_namespace_node *device_node,
                                  acpi_adr_space_type space_id)
 {
index 3197e63..624361a 100644 (file)
@@ -306,3 +306,57 @@ acpi_execute_reg_methods(acpi_handle device, acpi_adr_space_type space_id)
 }
 
 ACPI_EXPORT_SYMBOL(acpi_execute_reg_methods)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_execute_orphan_reg_method
+ *
+ * PARAMETERS:  device          - Handle for the device
+ *              space_id        - The address space ID
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Execute an "orphan" _REG method that appears under an ACPI
+ *              device. This is a _REG method that has no corresponding region
+ *              within the device's scope.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_execute_orphan_reg_method(acpi_handle device, acpi_adr_space_type space_id)
+{
+       struct acpi_namespace_node *node;
+       acpi_status status;
+
+       ACPI_FUNCTION_TRACE(acpi_execute_orphan_reg_method);
+
+       /* 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) {
+
+               /*
+                * If an "orphan" _REG method is present in the device's scope
+                * for the given address space ID, run it.
+                */
+
+               acpi_ev_execute_orphan_reg_method(node, space_id);
+       } else {
+               status = AE_BAD_PARAMETER;
+       }
+
+       (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+       return_ACPI_STATUS(status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_execute_orphan_reg_method)
index 68dd17f..299ec65 100644 (file)
@@ -1507,6 +1507,9 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device,
 
        if (call_reg && !test_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags)) {
                acpi_execute_reg_methods(scope_handle, ACPI_ADR_SPACE_EC);
+               if (scope_handle != ec->handle)
+                       acpi_execute_orphan_reg_method(ec->handle, ACPI_ADR_SPACE_EC);
+
                set_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags);
        }
 
index 94d0fc3..80dc36f 100644 (file)
@@ -662,6 +662,10 @@ 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_execute_orphan_reg_method(acpi_handle device,
+                                                          acpi_adr_space_type
+                                                          space_id))
 ACPI_EXTERNAL_RETURN_STATUS(acpi_status
                            acpi_remove_address_space_handler(acpi_handle
                                                              device,