From: Rafael J. Wysocki <[email protected]>
It is reported that _DSM evaluation fails in ucsi_acpi_dsm() on Lenovo
IdeaPad Pro 5 due to a missing address space handler for the EC address
space:
ACPI Error: No handler for Region [ECSI] (000000007b8176ee) [EmbeddedControl] (20230628/evregion-130)
This happens because if there is no ECDT, the EC driver only registers
the EC address space handler for operation regions defined in the EC
device scope of the ACPI namespace while the operation region being
accessed by the _DSM in question is located beyond that scope.
To address this, modify the ACPI EC driver to install the EC address
space handler at the root of the ACPI namespace for the first EC that
can be found regardless of whether or not an ECDT is present.
Note that this change is consistent with some examples in the ACPI
specification in which EC operation regions located outside the EC
device scope are used (for example, see Section 9.17.15 in ACPI 6.5),
so the current behavior of the EC driver is arguably questionable.
Reported-by: webcaptcha <[email protected]>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=218789
Link: https://uefi.org/specs/ACPI/6.5/09_ACPI_Defined_Devices_and_Device_Specific_Objects.html#example-asl-code
Link: https://lore.kernel.org/linux-acpi/[email protected]
Suggested-by: Heikki Krogerus <[email protected]>
Signed-off-by: Rafael J. Wysocki <[email protected]>
---
v1 -> v2:
* Update the changelog to correctly cover the driver behavior
when ECDT is present
* Install the address space handler at the namespace root for
first_ec only
* Set first_ec before calling ec_install_handlers() in
acpi_ec_setup() (Hans)
---
drivers/acpi/ec.c | 25 ++++++++++++++++---------
drivers/acpi/internal.h | 1 -
2 files changed, 16 insertions(+), 10 deletions(-)
Index: linux-pm/drivers/acpi/ec.c
===================================================================
--- linux-pm.orig/drivers/acpi/ec.c
+++ linux-pm/drivers/acpi/ec.c
@@ -1482,13 +1482,14 @@ static bool install_gpio_irq_event_handl
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_ec_enter_noirq(ec);
- status = acpi_install_address_space_handler_no_reg(ec->handle,
+ status = acpi_install_address_space_handler_no_reg(scope_handle,
ACPI_ADR_SPACE_EC,
&acpi_ec_space_handler,
NULL, ec);
@@ -1497,11 +1498,10 @@ static int ec_install_handlers(struct ac
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);
+ acpi_execute_reg_methods(scope_handle, ACPI_ADR_SPACE_EC);
set_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags);
}
@@ -1553,10 +1553,13 @@ static int ec_install_handlers(struct ac
static void ec_remove_handlers(struct acpi_ec *ec)
{
+ acpi_handle scope_handle = ec == first_ec ? ACPI_ROOT_OBJECT : ec->handle;
+
if (test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
if (ACPI_FAILURE(acpi_remove_address_space_handler(
- ec->address_space_handler_holder,
- ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
+ scope_handle,
+ 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);
}
@@ -1595,14 +1598,18 @@ static int acpi_ec_setup(struct acpi_ec
{
int ret;
- ret = ec_install_handlers(ec, device, call_reg);
- if (ret)
- return ret;
-
/* First EC capable of handling transactions */
if (!first_ec)
first_ec = ec;
+ ret = ec_install_handlers(ec, device, call_reg);
+ if (ret) {
+ if (ec == first_ec)
+ first_ec = NULL;
+
+ return ret;
+ }
+
pr_info("EC_CMD/EC_SC=0x%lx, EC_DATA=0x%lx\n", ec->command_addr,
ec->data_addr);
Index: linux-pm/drivers/acpi/internal.h
===================================================================
--- linux-pm.orig/drivers/acpi/internal.h
+++ linux-pm/drivers/acpi/internal.h
@@ -186,7 +186,6 @@ 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;
On Wed, May 15, 2024 at 09:40:54PM +0200, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <[email protected]>
>
> It is reported that _DSM evaluation fails in ucsi_acpi_dsm() on Lenovo
> IdeaPad Pro 5 due to a missing address space handler for the EC address
> space:
>
> ACPI Error: No handler for Region [ECSI] (000000007b8176ee) [EmbeddedControl] (20230628/evregion-130)
>
> This happens because if there is no ECDT, the EC driver only registers
> the EC address space handler for operation regions defined in the EC
> device scope of the ACPI namespace while the operation region being
> accessed by the _DSM in question is located beyond that scope.
>
> To address this, modify the ACPI EC driver to install the EC address
> space handler at the root of the ACPI namespace for the first EC that
> can be found regardless of whether or not an ECDT is present.
>
> Note that this change is consistent with some examples in the ACPI
> specification in which EC operation regions located outside the EC
> device scope are used (for example, see Section 9.17.15 in ACPI 6.5),
> so the current behavior of the EC driver is arguably questionable.
..
> - status = acpi_install_address_space_handler_no_reg(ec->handle,
> + status = acpi_install_address_space_handler_no_reg(scope_handle,
> ACPI_ADR_SPACE_EC,
> &acpi_ec_space_handler,
> NULL, ec);
Looking at this...
> if (ACPI_FAILURE(acpi_remove_address_space_handler(
> + scope_handle,
> + ACPI_ADR_SPACE_EC,
> + &acpi_ec_space_handler)))
..and this, I believe you can move scope_handle to the previous line and align
the rest for the sake of consistency and slightly better readability.
--
With Best Regards,
Andy Shevchenko
On Thu, May 16, 2024 at 12:22 PM Andy Shevchenko
<[email protected]> wrote:
>
> On Wed, May 15, 2024 at 09:40:54PM +0200, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <[email protected]>
> >
> > It is reported that _DSM evaluation fails in ucsi_acpi_dsm() on Lenovo
> > IdeaPad Pro 5 due to a missing address space handler for the EC address
> > space:
> >
> > ACPI Error: No handler for Region [ECSI] (000000007b8176ee) [EmbeddedControl] (20230628/evregion-130)
> >
> > This happens because if there is no ECDT, the EC driver only registers
> > the EC address space handler for operation regions defined in the EC
> > device scope of the ACPI namespace while the operation region being
> > accessed by the _DSM in question is located beyond that scope.
> >
> > To address this, modify the ACPI EC driver to install the EC address
> > space handler at the root of the ACPI namespace for the first EC that
> > can be found regardless of whether or not an ECDT is present.
> >
> > Note that this change is consistent with some examples in the ACPI
> > specification in which EC operation regions located outside the EC
> > device scope are used (for example, see Section 9.17.15 in ACPI 6.5),
> > so the current behavior of the EC driver is arguably questionable.
>
> ...
>
> > - status = acpi_install_address_space_handler_no_reg(ec->handle,
> > + status = acpi_install_address_space_handler_no_reg(scope_handle,
> > ACPI_ADR_SPACE_EC,
> > &acpi_ec_space_handler,
> > NULL, ec);
>
> Looking at this...
>
> > if (ACPI_FAILURE(acpi_remove_address_space_handler(
> > + scope_handle,
> > + ACPI_ADR_SPACE_EC,
> > + &acpi_ec_space_handler)))
>
> ...and this, I believe you can move scope_handle to the previous line and align
> the rest for the sake of consistency and slightly better readability.
Well, I prefer to cut a separate cleanup patch to make this more consistent.