Bug 13802

Summary: kacpid & kacpi_notify use CPU cycles when lid closed on Acer Aspire One
Product: ACPI Reporter: Jonathan (dzhonw)
Component: BIOSAssignee: acpi_bios
Status: REJECTED WILL_NOT_FIX    
Severity: normal CC: lenb
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 2.6.30.1 Subsystem:
Regression: No Bisected commit-id:
Attachments: acpidump
"grep . /sys/firmware/acpi/interrupts/*" with lid open
"grep . /sys/firmware/acpi/interrupts/*" with lid closed
customized DSDT: invert GPIO 0x0D correctly

Description Jonathan 2009-07-20 07:42:24 UTC
Created attachment 22408 [details]
acpidump

When the lid is closed on my Acer Aspire One (D150-1577), kacpid and kacpi_notify both make very active use of the CPU.

I cannot find any evidence of a repeating lid event in my logs as suggested by similar problems had by others.  Also, my DSDT appears to have the relevant clause to prevent this.

This happens with 2.6.29 and 2.6.30 images from debian unstable, as well as with a home-compiled version of the 2.6.30.1 source release.  I have the latest acpi packages from debian, and it was happening with slightly older kernels too.

Also posted as a debian bug:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=536240

And notified kernel.org originally/incorrectly at:
http://bugzilla.kernel.org/show_bug.cgi?id=13013
Comment 1 Jonathan 2009-07-20 07:43:45 UTC
Created attachment 22409 [details]
"grep . /sys/firmware/acpi/interrupts/*" with lid open
Comment 2 Jonathan 2009-07-20 07:44:27 UTC
Created attachment 22410 [details]
"grep . /sys/firmware/acpi/interrupts/*" with lid closed
Comment 3 Zhang Rui 2009-07-20 08:07:44 UTC
Created attachment 22411 [details]
customized DSDT: invert GPIO 0x0D correctly

please apply this customized DSDT and see if it helps.

one question:
does "/proc/acpi/button/lid/LID0/state" always report the correct lid status on your laptop?
Comment 4 Jonathan 2009-07-20 09:05:03 UTC
/proc/acpi/button/lid/LID0/state always reports closed, whether the lid is open or closed.  But *something's* letting acpi know the lid's closed.

I'll try the DSDT a little later and report on it.
Comment 5 Jonathan 2009-07-20 09:06:28 UTC
Btw, what DSDT did you base this one on?  I just worry that this DSDT will break other things.  Wouldn't it be better to modify my current DSDT?
Comment 6 Len Brown 2009-07-20 15:23:01 UTC
I think it is a safe assumption that Rui based the test on the acpidump
in the 1st attachment of this report.  When I compile the original,
(likely with a different version of the compiler than Rui) the new one
is only 45 bytes larger than the original.

However, Rui, when you hack a DSDT, it would be helpful if you show
the source diff in addition to providing the .hex -- since it is
difficult to discover that source from the C .hex file.

Jonathan,
The lid state is different from the lid event.
Lid state is discovered by evaluating the _LID method.

On this box, _LID reads a hardware pin/register LPDL:
        Device (LID0)
        {
            Name (_HID, EisaId ("PNP0C0D"))
            Method (_LID, 0, NotSerialized)
            {
                Return (LPDL)
            }
        }

    OperationRegion (GPIO, SystemIO, 0x0500, 0x3C)
    Field (GPIO, ByteAcc, NoLock, Preserve)
    {
                Offset (0x2C),
                Offset (0x2D),
            ,   1,
        INV9,   1,
        INVA,   1,
            ,   18,
        LPDL,   1,
                Offset (0x38),
            ,   1,
            ,   1,
        CPEN,   1
    }

You could read the same address via inb(1) and get the same value.


The GPE 1D is 
        Method (_L1D, 0, NotSerialized)
        {
            Not (LPDL, LPDL)
            Notify (\_SB.LID0, 0x80)
        }

Not() is an integer bitwise NOT -- so presumably writing the not
of the current value on this hardware will clear the event source...

Of course if there are every any garbage bits in LPDL, then
Not(LPDL, LPDL) isn't going to work -- assuming that any
bits in the byte would provoke an interrupt.

Notify(0x80) just says that there is a lid event.
Somebody has to read _LID to figure out what the state is --
or assume that lid events are in sequence open/closed/open/closed etc,
which would be generally be a bad idea.
Comment 7 Jonathan 2009-07-20 20:37:16 UTC
The DSDT did indeed make the problem go away, and it also seems to've made /proc report the right state of the lid.

So this is a BIOS bug and not a kernel bug?  If that's the case, then maybe the kernel should default to behaving differently when there's this particular BIOS bug?  Having the kernel eat CPU cycles when the lid is closed (which uses power and makes the device get hot) seems not good, whether it's really the kernel's fault or not.  I'm not sure how easy/possible this is for you guys to change, but that would be what I'd naïvely opt for.

From a more self-serving and personal point-of-view: thanks for the quick response and work-around!
Comment 8 Jonathan 2009-07-20 21:00:15 UTC
Though I see the following in dmesg:

[  779.985047] ACPI: EC: missing confirmations, switch off interrupt mode.
[  780.489074] ACPI Exception (evregion-0422): AE_TIME, Returned by Handler for [EmbeddedControl] [20090320]
[  780.489105] ACPI Error (psparse-0537): Method parse/execution failed [\_SB_.PCI0.LPC_.BAT0._BST] (Node f7036c84), AE_TIME
[  780.489255] ACPI Exception (battery-0385): AE_TIME, Evaluating _BST [20090320]
Comment 9 Zhang Rui 2009-07-21 00:58:33 UTC
well, this is a BIOS bug.

The lid GPE (0x1D) uses GPIO 0x0D.
And we need to invert the GPI_INV register every time a lid event occurs.
The DSDT tries to do this by "Not (LPDL, LPDL)" in _L1D method.
but unfortunately the stupid BIOS doesn't set the correct bit of GPI_INV register, i.e. it inverts the GPIO 0x1D bit instead of 0x0D...

here is the output of "diff -pNur DSDT.dsl DSDT-new.dsl".
@@ -94,8 +94,9 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, 
             ,   1, 
         INV9,   1, 
         INVA,   1, 
-            ,   18, 
-        LPDL,   1, 
+	    ,	1,
+	    ,	1,
+	LPDL,	1,
                 Offset (0x38), 
             ,   1, 
             ,   1,
Comment 10 Zhang Rui 2009-07-21 01:01:30 UTC
Jonathan,
this is a BIOS bug that we can not fix in Linux kernel.
I think windows are also affected by this BIOS.
IMO, a BIOS upgrade is worth trying. :)
Comment 11 Anonymous Emailer 2009-09-15 01:37:24 UTC
Reply-To: jcapote@gmail.com

I am also having this exact same bug on my Acer Aspire One.

To answer your question,

/proc/acpi/button/lid/LID0/state

reports "closed" even though it is open...

hope this helps

-- Julio Capote