Bug 13563 (PatrickVogeli)

Summary: Wrong battery status
Product: ACPI Reporter: Patrick Vögeli (patrick.voegeli)
Component: Power-BatteryAssignee: Zhang Rui (rui.zhang)
Status: CLOSED INVALID    
Severity: normal CC: acpi-bugzilla, lenb, rui.zhang
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: Subsystem:
Regression: No Bisected commit-id:
Attachments: acpidump log
acpi outputs while running on battery or on AC power.
customized DSDT: show battery status correctly

Description Patrick Vögeli 2009-06-18 12:41:55 UTC
Hi there,

I'm having a little problem with laptop: the battery status indication. It doesn't work the way it should. It will always correctly report when it is charging, but once the battery is fully charged, instead of going to the carged state it goes to discharging. The acpi -V command says discharging at zero rate will never fully discharge. Once I unplug the AC source, it will go to Charged. The AC states always is detected fine as online or offline, by both hal and acpi.

I've tried lots of different kernels, 32 or 64 bits, and different distributions, all present this problems. Both acpi and hal are reporting wrong information.

So, to sumarize, the charged and charging states are mixed up.

I attach the output of acpidump.

Thank you.
Comment 1 Patrick Vögeli 2009-06-18 19:24:47 UTC
Created attachment 21999 [details]
acpidump log

Seems I forgot to attach the file
Comment 2 Zhang Rui 2009-06-19 03:31:07 UTC
please attach the output of "grep . /proc/acpi/battery/*/*"
Comment 3 Patrick Vögeli 2009-06-19 23:33:09 UTC
Created attachment 22018 [details]
acpi outputs while running on battery or on AC power.

3 files (on battery, on ac battery charging, on ac battery charged) which have the ouputs of "grep . /proc/acpi/battery/*/*", "grep . /proc/acpi/ac_adapter/*/*" and "acpi -V" for each state.

Hope it helps
Comment 4 Zhang Rui 2009-06-22 02:51:23 UTC
                If (LEqual (Local0, 0x02)) // battery is present
                {
                    And (Local7, One, Local0) // get the AC status
                    If (LEqual (Local0, One)) // if AC is on
                    {
                        And (Local7, 0x80, Local1) // get the Battery status
                        If (LEqual (Local1, 0x80)) // if battery is charging
                        {
                            Or (Local4, 0x02, Local4) // _BST returns charging
                        }
                        Else                       // if battery is not charging
                        {
                            Or (Local4, One, Local4) // _BST returns discharing
                        }
                    }
                }
                // _BST returns Charged if AC is off ?

This is how the Battery state field of _BST is set in the original DSDT.
This is apparently wrong.
I have modified the AML to
                If (LEqual (Local0, 0x02))
                {
                    And (Local7, One, Local0)
                    If (LEqual (Local0, One))
                    {
                        And (Local7, 0x80, Local1)
                        If (LEqual (Local1, 0x80))
                        {
                            Or (Local4, 0x02, Local4) // if AC is on and battery is charging, it's "Charging"
                        }
                        // if AC is on and battery is not charging, it's "Charged"
                    }
                    Else
                    {
                        Or (Local4, One, Local4) // if AC is not on, it's "Discharging"
                    }
                }
Comment 5 Zhang Rui 2009-06-22 02:54:31 UTC
Created attachment 22041 [details]
customized DSDT: show battery status correctly

please try this customized DSDT and see if it helps.

Plus, if my conclusion is true, this is a BIOS bug that we can not fix it in Linux kernel, and Windows should suffer from it as well, could you please verify this if you have a windows partition?
And you'd better try the latest BIOS to see if the problem is fixed.
Comment 6 Patrick Vögeli 2009-06-22 10:08:24 UTC
OK, BIOS BUG found triagged and fix released.

It was definitely as you said: the else statement is in the wrong place, moving it out of that IF solves the problem.

Thank you very much, you've been very kind.