[PATCH] ACPI: EC: Avoid _REG disconnect on GPIO IRQ defer

Zhu Ling posted 1 patch 1 week, 3 days ago
drivers/acpi/ec.c | 39 +++++++++++++++++++++++++--------------
1 file changed, 25 insertions(+), 14 deletions(-)
[PATCH] ACPI: EC: Avoid _REG disconnect on GPIO IRQ defer
Posted by Zhu Ling 1 week, 3 days ago
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 <zhuling2709@phytium.com.cn>
---
 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;
Re: [PATCH] ACPI: EC: Avoid _REG disconnect on GPIO IRQ defer
Posted by Rafael J. Wysocki (Intel) 4 days, 3 hours ago
On Wed, Jul 15, 2026 at 3:26 AM Zhu Ling <zhuling2709@phytium.com.cn> 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 <zhuling2709@phytium.com.cn>
> ---
>  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!