[Bug 297326] acpi_ec: duplicate attach when the DSDT EC device has no _UID

From: <bugzilla-noreply_at_freebsd.org>
Date: Fri, 07 Aug 2026 04:53:44 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=297326

            Bug ID: 297326
           Summary: acpi_ec: duplicate attach when the DSDT EC device has
                    no _UID
           Product: Base System
           Version: 15.1-RELEASE
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: dr.johannes.bruegmann@gmail.com

Created attachment 273519
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=273519&action=edit
asl ecdt and ec device

I am a FreeBSD user, not a kernel developer. The observations are from my
machine and accurate; the code analysis was done with AI assistance and I
cannot
verify it myself. I am not able to run follow-up experiments beyond simple
commands.

## Summary

On firmware that provides both an ECDT and a `PNP0C09` device in the DSDT,
FreeBSD attaches the EC twice. The second attach fails on the already claimed
I/O ports, and its error path removes the GPE and address space handlers that
the *working* instance installed. Consequences: WMI cannot find the EC, GPE is
disabled, `_PTS` fails and the machine does not power off.

## Observed

FreeBSD 15.1-RELEASE-p2 amd64, Schenker KEY 18 Pro E25 (Clevo X585WNX),
BIOS 1.07.11RTR.

```
acpi_ec1: <Embedded Controller: GPE 0x46, ECDT> port 0x62,0x66 on acpi0
acpi_ec0: <Embedded Controller: GPE 0x46> port 0x62,0x66 on acpi0
acpi_ec0: can't allocate data port
device_attach: acpi_ec0 attach returned 6

acpi_wmi0..4: cannot find EC device
ACPI Error: No handler or method for GPE 46, disabling event (evgpe-1061)

[on shutdown]
ACPI Error: No handler for Region [EC81] [EmbeddedControl] (evregion-292)
acpi0: AcpiEnterSleepStatePrep failed - AE_NOT_EXIST
-> "The operating system has halted", machine stays powered on
```

ECDT: `EC_ID=\_SB.PC00.LPCB.EC`, `UID=0x1`, `GPE_BIT=0x46`.
DSDT: `Device (EC)` under `Scope (_SB.PC00.LPCB)`, `_HID = PNP0C09`, **no
`_UID`**. Exactly one EC device exists in the namespace.

Reading still works (`hw.acpi.battery.life` is correct via `_BST`), only events
and device-tree lookups break — which makes this easy to miss.

## Analysis

`sys/dev/acpica/acpi_ec.c`, `acpi_ec_probe()`:

```c
status = acpi_GetInteger(h, "_UID", &params->uid);
if (ACPI_FAILURE(status))
        params->uid = 0;
...
peer = devclass_get_device(device_get_devclass(dev), params->uid);
if (peer != NULL && device_is_alive(peer)) {
        device_disable(dev); goto out;
}
```

The ECDT child is created as unit 1 (`ecdt->Uid`). The DSDT child finds no
`_UID`, falls back to 0, looks for a peer at unit 0, misses the live unit 1 and
proceeds. The damage happens in the error path of `acpi_ec_attach()`, which
removes the handlers for `sc->ec_handle` — the same namespace node the working
instance registered on.

Linux matches the duplicate on the namespace location of the `PNP0C09` device
rather than on `_UID`, and takes only the GPE from the ECDT.

## Workaround (verified)

```
hint.acpi_ec.0.disabled="1"      # loader.conf
```

Prevents the DSDT device from being probed, so the ECDT instance survives.
Result: one `acpi_ec`, zero ACPI errors, all WMI devices bound, GPE active,
`shutdown -p now` powers the machine off, `Unsafe shutdowns` stays constant.

Disabling the ECDT instance instead (`hint.acpi_ec.1.disabled="1"`) also
removes
the duplicate and restores power-off, but the EC is then only available after
the namespace walk and early methods (`_OSC`, `U4EC`, `DOCM`, `TBTD`) fail with
`AE_NOT_EXIST`.

`debug.acpi.avoid` with the exact path (`_SB.PC00.LPCB.EC__`, from
`dev.acpi_ec.1.%location`) did not prevent the second attach.

Overriding the DSDT to add a `_UID` was also attempted and produced a
non-functional table, but that experiment ran while the machine had unrelated
storage corruption (see the geli/TRIM PR), so the input files and the toolchain
may have been affected — it should not be taken as evidence that the approach
does not work.

## Suggested fix

Match the duplicate on the ACPI handle or on the I/O port addresses instead of
`_UID`. Alternatively, make the error path in `acpi_ec_attach()` remove only
handlers it installed itself.

-- 
You are receiving this mail because:
You are the assignee for the bug.