On Sat, Oct 08, 2022 at 03:10:18PM +0300, Mikhail wrote:
> I'm troubleshooting battery status for my Lenovo IdeaPad 3 14ITL05, on
> latest -current it shows that battery is absent and AC not connected:
> 
> Battery state: absent, 0% remaining, unknown life estimate
> AC adapter state: not connected
> Performance adjustment mode: manual (2900 MHz)

Digging further, third attempt.

The sequence of actions is following:

first acpi_attach_common() tries to attach EC through ECDT with the
following code:

1206         /*
1207          * Attach table-defined devices
1208          */
1209         SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
1210                 struct acpi_attach_args aaa;
1211 
1212                 memset(&aaa, 0, sizeof(aaa));
1213                 aaa.aaa_iot = sc->sc_iot;
1214                 aaa.aaa_memt = sc->sc_memt;
1215                 aaa.aaa_dmat = sc->sc_ci_dmat;
1216                 aaa.aaa_table = entry->q_table;
1217                 config_found_sm(&sc->sc_dev, &aaa, acpi_print, 
acpi_submatch);
1218         }

I see no way how we can set aaa.aaa_node with this code, so it's zero
after memset().

config_found_sm eventually calls acpiec_match for ECDT table, since ECDT
table is presented on my laptop, acpiec_match wins with this probe:

261         /* Check for early ECDT table attach */
262         if (ecdt && 
263             !memcmp(ecdt->hdr.signature, ECDT_SIG, sizeof(ECDT_SIG) - 1))
264                 return (1);


then acpiec_attach() is called, and we have following line there:

281         sc->sc_devnode = aa->aaa_node;

and we can't properly eval expressions with NULL as devnode (as I noted,
aaa_node was memset() to zero in acpi_attach_common()).

Since we can't eval the expressions, we can't eval _REG method, which in
turns means that we can't access EC memory region and ECAV (Embedded
Controll AVailable - spent long time deciphering) won't be set in AML,
and from ASL for DSDT, it means that battery status will be returned as
'not present' and plus all other oddities. 

I was interested why this "early ECDT" attach procedure isn't working
for me, and found the following:

430         /* Check if this is ECDT initialization */
431         if (ecdt) {
                [...]
447                 /* Get devnode from header */
448                 sc->sc_devnode = aml_searchname(sc->sc_acpi->sc_root,
449                     ecdt->ec_id);
450 
451                 goto ecdtdone;
452         }

The reason for the fail is my ECDT, it has wrong ec_id attribute:

Namepath : "\_SB.PC00.LPCB.H_EC"

there is no such device, proper path is "\_SB.PC00.LPCB.EC0"

So, if I remove ecdt table matching code from acpiec_match(), then loop
from acpi_attach_common() will fail to attach it, and actual setup will
be made by this line further down:

1231         aml_find_node(sc->sc_root, "_HID", acpi_foundec, sc);

which works perfectly fine, since it looks for _HID and strcmp() it with
EC Device ID in acpi_foundec(), finding correct node.

If ecdt table match stays, then the line won't take affect, since there
is logic in acpi_foundec() which prevents double attach.

Currently I have no idea how to properly fix this, without breaking
other devices (if you look in 4cfbe39155 why this early ECDT attach was
added).

I've asked for the ACPI fix in Lenovo support forum, to work on this
further, but I suspect such kind of support is like a unicorn - no such
thing.

Reply via email to