Bug 14824

Summary: dynamic tables aren't loaded early enough
Product: ACPI Reporter: Alex Chiang (achiang)
Component: Config-TablesAssignee: acpi_config-tables
Status: CLOSED CODE_FIX    
Severity: normal CC: bjorn.helgaas, elio.voci, lenb, ming.m.lin, rui.zhang
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: Subsystem:
Regression: No Bisected commit-id:
Attachments: dmesg
acpidump and dynamic tables
CPU0CST.dsl

Description Alex Chiang 2009-12-17 00:43:53 UTC
Created attachment 24211 [details]
dmesg

New HP Envy notebook (core i7) with latest production F.06 BIOS.

Encountering an error while initializing the ambient light sensor on the EC. During initialization, that object references a non-existent method. This method is actually defined in a dynamic table loaded later.

Triaged down to the point where we know that \_PR_.CPU0._PDC is the method that contains the Load statement that then defines the missing method.

http://pastebin.com/f3b00122a

Lines 25--28 indicate the error.

On lines 43,44, and 53,54, we see the dynamic tables get loaded. Those come from a Load in the _PDC method.

The dynamic table named ApIst (line 53) contains the definition of \_PR_.CPU0._PPC.

This bug is very similar to http://bugzilla.kernel.org/show_bug.cgi?id=14710 but the thermal zone and fans actually work on this machine.
Comment 1 Alex Chiang 2009-12-17 00:46:12 UTC
Created attachment 24212 [details]
acpidump and dynamic tables

The dynamic tables were extracted by examining SSDT5 to learn the memory offset and size.

Then I issued: acpidump --address 0xfoo --length 0xbar > dyn-table.out.
Comment 2 Alex Chiang 2009-12-17 00:48:15 UTC
Since Windows 7 runs fine on this machine, perhaps Linux needs to evaluate _PDC earlier to be compatible.

I took a look at doing this, but it seems to be non-trivial.
Comment 3 Zhang Rui 2009-12-23 06:03:52 UTC
patch set has been applied to acpi-test.
http://patchwork.kernel.org/patch/69039/
Comment 4 Len Brown 2009-12-26 04:35:48 UTC
patch series referenced above shipped in linux-2.6.33-rc2
closed.
Comment 5 Len Brown 2010-01-16 08:06:43 UTC
Created attachment 24591 [details]
CPU0CST.dsl

for reference: \_PR.CPU0._CST is contained in CPU0CST.dsl, attached.
Comment 6 Zhang Rui 2010-05-10 06:45:20 UTC
*** Bug 15801 has been marked as a duplicate of this bug. ***
Comment 7 Bjorn Helgaas 2010-09-13 20:51:29 UTC
I know this is fixed and closed already, but I don't like the fact that
we had to add special-case code to evaluate processor _PDC methods in
acpi_bus_init().

I doubt that Windows has a _PDC special case.  It would have to have
been there for a long time, because I'm sure there was no Windows update
just for this laptop, and I don't see anything in the spec that would
suggest such special treatment.  It'd be interesting to use qemu to
figure out whether Windows really does something special here.

I don't have time to really do anything with this now, so these are just
idle thoughts in case I can come back to this later.  If I understand
correctly, the original problem is this:

  1) The \_SB_.PCI0.LPCB.EC0_._REG method references \_PR_.CPU0._PPC
  2) The \_PR_.CPU0._PPC definition is in an SSDT loaded by the CPU0 _PDC method
  3) Linux executes the _REG method before the _PDC method, so _PPC is undefined

The ACPI 4.0 spec, section 6.5.4 (_REG) on p. 276 does say:

  OSPM must make Embedded Controller operation regions, accessed via the
  Embedded Controllers described in ECDT, available before executing any
  control method.

So we clearly have to do *some* EC initialization early.  But I wonder if
we're doing more than is required.  We currently call acpi_boot_ec_enable(),
which uses ec_install_handlers() -> acpi_install_address_space_handler() ->
acpi_ev_execute_reg_methods() to evaluate _REG(1).  But the surrounding
text from the spec suggests that _REG(1) is *not* required at this point:

  Except for the cases shown below, control methods must assume all
  operation regions inaccessible until the _REG(RegionSpace, 1) method
  is executed. ...

  The exceptions for this rule are:
    1. [PCI config, I/O, and memory opregions]
    2. [Embedded Controller opregions via the ECDT controller]

Maybe Windows merely happens to bind the \_PR_.CPU0 driver (and run
its _PDC method) before it binds the \_SB_.PCI0.LPCB.EC0_ driver (and
run its _REG method).  It still seems wrong to me for the BIOS to rely
on that sort of ordering, but it doesn't rely on anything special in
Windows to explain why it works.