]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ACPI: EC: Evaluate _REG outside the EC scope more carefully
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Sun, 12 Apr 2026 01:02:30 +0000 (21:02 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 18 Apr 2026 08:35:57 +0000 (10:35 +0200)
[ Upstream commit 71bf41b8e913ec9fc91f0d39ab8fb320229ec604 ]

Commit 60fa6ae6e6d0 ("ACPI: EC: Install address space handler at the
namespace root") caused _REG methods for EC operation regions outside
the EC device scope to be evaluated which on some systems leads to the
evaluation of _REG methods in the scopes of device objects representing
devices that are not present and not functional according to the _STA
return values. Some of those device objects represent EC "alternatives"
and if _REG is evaluated for their operation regions, the platform
firmware may be confused and the platform may start to behave
incorrectly.

To avoid this problem, only evaluate _REG for EC operation regions
located in the scopes of device objects representing known-to-be-present
devices.

For this purpose, partially revert commit 60fa6ae6e6d0 and trigger the
evaluation of _REG for EC operation regions from acpi_bus_attach() for
the known-valid devices.

Fixes: 60fa6ae6e6d0 ("ACPI: EC: Install address space handler at the namespace root")
Link: https://lore.kernel.org/linux-acpi/1f76b7e2-1928-4598-8037-28a1785c2d13@redhat.com
Link: https://bugzilla.redhat.com/show_bug.cgi?id=2298938
Link: https://bugzilla.redhat.com/show_bug.cgi?id=2302253
Reported-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Cc: All applicable <stable@vger.kernel.org>
Link: https://patch.msgid.link/23612351.6Emhk5qWAg@rjwysocki.net
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/acpi/ec.c
drivers/acpi/internal.h
drivers/acpi/scan.c

index d0ce8ec19df5a2e79f5397de6e652204d93bba0b..d00fd26c274f21ee409fd028b067336511051515 100644 (file)
@@ -1512,12 +1512,13 @@ static bool install_gpio_irq_event_handler(struct acpi_ec *ec)
 static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device,
                               bool call_reg)
 {
-       acpi_handle scope_handle = ec == first_ec ? ACPI_ROOT_OBJECT : ec->handle;
        acpi_status status;
 
        acpi_ec_start(ec, false);
 
        if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
+               acpi_handle scope_handle = ec == first_ec ? ACPI_ROOT_OBJECT : ec->handle;
+
                acpi_ec_enter_noirq(ec);
                status = acpi_install_address_space_handler_no_reg(scope_handle,
                                                                   ACPI_ADR_SPACE_EC,
@@ -1531,7 +1532,7 @@ 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_UINT32_MAX, ACPI_ADR_SPACE_EC);
+               acpi_execute_reg_methods(ec->handle, ACPI_UINT32_MAX, ACPI_ADR_SPACE_EC);
                set_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags);
        }
 
@@ -1749,6 +1750,12 @@ static int acpi_ec_remove(struct acpi_device *device)
        return 0;
 }
 
+void acpi_ec_register_opregions(struct acpi_device *adev)
+{
+       if (first_ec && first_ec->handle != adev->handle)
+               acpi_execute_reg_methods(adev->handle, 1, ACPI_ADR_SPACE_EC);
+}
+
 static acpi_status
 ec_parse_io_ports(struct acpi_resource *resource, void *context)
 {
index 219c02df9a08c720dcca32559f47d3770b0507c2..4e742b5ee67900545a4bc7962fd7a608876f5781 100644 (file)
@@ -210,6 +210,7 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
                              acpi_handle handle, acpi_ec_query_func func,
                              void *data);
 void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit);
+void acpi_ec_register_opregions(struct acpi_device *adev);
 
 #ifdef CONFIG_PM_SLEEP
 void acpi_ec_flush_work(void);
index 9e8f38e525893fcad0ce06ccc4457934fb502e21..d1c81ad9b2f6791aa6b0d5bd82b30ad75ffe22ae 100644 (file)
@@ -2198,6 +2198,8 @@ static int acpi_bus_attach(struct acpi_device *device, void *first_pass)
        if (device->handler)
                goto ok;
 
+       acpi_ec_register_opregions(device);
+
        if (!device->flags.initialized) {
                device->flags.power_manageable =
                        device->power.states[ACPI_STATE_D0].flags.valid;