Re: [PATCH] ACPI: EC: Avoid _REG disconnect on GPIO IRQ defer
"Rafael J. Wysocki (Intel)" <[email protected]>
| Newsgroups | org.kernel.vger.linux-acpi,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <CAJZ5v0jKG_xNjyjEjnQY0yTyNspnPKMiLrtPmYSF_8LnsYQFGQ@mail.gmail.com> |
On Wed, Jul 15, 2026 at 3:26 AM Zhu Ling <[email protected]> wrote: > > EC event delivery uses either a GPE or, on ACPI reduced hardware > platforms, a GpioInt resource. The GPE path does not have a provider > lookup that can defer, but acpi_dev_gpio_irq_get() can return > -EPROBE_DEFER for the GpioInt path. > > ec_install_handlers() currently installs the EC address space handler and > executes _REG before looking up the GPIO IRQ. If the GPIO lookup then > defers, acpi_ec_setup() tears the handlers down again. Removing the EC > address space handler causes ACPICA to execute _REG for disconnect, so > firmware may observe an EC OpRegion connected -> disconnected transition > during one failed probe attempt. > > This is observable when the namespace EC reuses a boot EC that has already > installed the EC address space handler. A deferred namespace EC probe can > disconnect the already usable boot EC OpRegion until a later reprobe > connects it again. AML that gates EC field accesses on _REG state can > then return fallback values to other drivers during that window. > > Prepare the GPIOInt IRQ before publishing EC OpRegion availability to AML. > This leaves the GPE path unchanged, keeps non-deferred GPIO lookup errors > non-fatal as before, and still lets the existing acpi_ec_setup() error > path clean up real handler installation failures. > > Fixes: f6484cadbcaf ("ACPI: EC: clean up handlers on probe failure in acpi_ec_setup()") > Signed-off-by: Zhu Ling <[email protected]> > --- > drivers/acpi/ec.c | 39 +++++++++++++++++++++++++-------------- > 1 file changed, 25 insertions(+), 14 deletions(-) > > diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c > index 64ad4cfa6208..26550879f43c 100644 > --- a/drivers/acpi/ec.c > +++ b/drivers/acpi/ec.c > @@ -1510,6 +1510,23 @@ static bool install_gpio_irq_event_handler(struct acpi_ec *ec) > IRQF_SHARED | IRQF_ONESHOT, "ACPI EC", ec) >= 0; > } > > +static int ec_prepare_gpio_irq(struct acpi_ec *ec, struct acpi_device *device) > +{ > + int irq; > + > + if (!device || ec->gpe >= 0 || ec->irq >= 0) > + return 0; > + > + /* ACPI reduced hardware platforms use a GpioInt from _CRS. */ > + irq = acpi_dev_gpio_irq_get(device, 0); > + if (irq == -EPROBE_DEFER) > + return irq; > + if (irq >= 0) > + ec->irq = irq; > + > + return 0; > +} > + > /** > * ec_install_handlers - Install service callbacks and register query methods. > * @ec: Target EC. > @@ -1524,7 +1541,6 @@ static bool install_gpio_irq_event_handler(struct acpi_ec *ec) > * Return: > * -ENODEV if the address space handler cannot be installed, which means > * "unable to handle transactions", > - * -EPROBE_DEFER if GPIO IRQ acquisition needs to be deferred, > * or 0 (success) otherwise. > */ > static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device, > @@ -1557,19 +1573,6 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device, > if (!device) > return 0; > > - if (ec->gpe < 0) { > - /* ACPI reduced hardware platforms use a GpioInt from _CRS. */ > - int irq = acpi_dev_gpio_irq_get(device, 0); > - /* > - * Bail out right away for deferred probing or complete the > - * initialization regardless of any other errors. > - */ > - if (irq == -EPROBE_DEFER) > - return -EPROBE_DEFER; > - else if (irq >= 0) > - ec->irq = irq; > - } > - > if (!test_bit(EC_FLAGS_QUERY_METHODS_INSTALLED, &ec->flags)) { > /* Find and register all query methods */ > acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1, > @@ -1647,6 +1650,14 @@ static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device, bool ca > { > int ret; > > + /* > + * GPIO IRQ lookup can defer. Do it before publishing the EC > + * OpRegion to AML to avoid a spurious _REG(disconnect). > + */ > + ret = ec_prepare_gpio_irq(ec, device); > + if (ret) > + return ret; > + > /* First EC capable of handling transactions */ > if (!first_ec) > first_ec = ec; Applied as 7.3 material, thanks!