Comment 110 for bug 971061

Revision history for this message
Moræus (moraus) wrote : Re: [Bug 971061] Re: acpi reports battery state incorrectly

I can confirm this works on a Samsung NP900x4c.

The same EC port range in DSDT.

Great work! Thanks a lot.

Sent from my iPhone

> On 18 Feb 2014, at 18:49, juanmanuel <email address hidden> wrote:
>
> FINALLY!! I found the exact problem _and_ a SOLUTION!!! (NOTE: see
> attached program)
>
> The problem is that Samsung's embedded controller stops sending GPE
> events if it still is waiting for previous GPE events to be queried from
> it.
>
> It will remain in that state until one hits the reset hole in the back
> of the latop, or flashes a bios, or queries the events.
>
> ---> But how will the OS query the events if the GPE interrupt isn't
> produced anymore? Classic chicken and egg. <----
>
> So I made a small program that does just that -- it queries events from
> the EC until there are no more to query. AND IT WORKED!! This restores
> the normal behavior, and AC, Battery and LID events start to be produced
> again. One would ideally run it after resume from sleep. I based it
> after observing normal behavior in <linuxkernel>/drivers/acpi/ec.c, and
> afterwards behaviour with laptop in "problem state".
>
> Following is the program (I will attach it too). You can either:
>
> 1) Run it by hand after resume from sleep.
>
> 2) Or Automatically run it from /usr/lib/pm-utils/sleep.d/99-your-
> script-here (you can use 95led as basis).
>
> 3) Or Insert this code in the linux kernel at the beginning of the
> acpi_ec_unblock_transactions_early() function in
> "<linuxkernel>/drivers/acpi/ec.c" and recompile the kernel. The cmd and
> data ports are known in ec.c so they don't need to be hardcoded there.
>
> PS: Other things that I already tried that didn't fix it:
> 1) Please note that I already tried commenting "acpi_disable_all_gpes()" from "<linuxkernel>/drivers/acpi/sleep.c" and this didn't have an effect (I guess unreplied events were already accumulated in the EC prior to resume).
> 2) I also tried reverting to calling acpi_enable() on sleep.c instead of setting the ACPI_BITREG_SCI_ENABLE. No effect, issue still resurfaced after some suspends.
> 3) I also tried commenting out the call to acpi_ec_unblock_transactions_early() in sleep.c, but no effect.
>
> PS2: Another way to force the embedded controller to be in a problem state that I discovered, is to:
> 1) echo disable > /sys/firmware/acpi/interrupts/gpe17
> 2) plug, unplug, plug, unplug, plug, unplug, plug, unplug (8 actions)
> 3) echo enable > /sys/firmware/acpi/interrupts/gpe17
>
>
> Following are the two files with fixes which I'll attach too:
>
> NOTE: you must check that embedded controller ports are 0x62 and 0x66
> looking in your DSDT. RUN AT YOUR OWN RISK!!!
>
> ---- samsung_fix_ec_events.c ------------------------------------------
> #include <stdio.h>
> #include <unistd.h>
> #include <sys/io.h>
>
> /* Compile with:
> * gcc -o samsung_fix_ec_events samsung_fix_ec_events.c
> * Run as:
> * sudo ./samsung_fix_ec_events
> * You may copy it to /usr/local/bin and then call it
> * automatically after resume from sleep with a /usr/lib/pm-utils/sleep.d script:
> * sudo cp ./samsung_fix_ec_events /usr/local/bin/
> */
>
> /* Constants: */
> enum ec_command {
> /* Standard command for querying LID, Battery and AC events: */
> ACPI_EC_COMMAND_QUERY = 0x84,
>
> /* ATTENTION: PLEASE edit the following two according to your DSDT.
> * For "Samsung Series 5 NP530U3C", they are 0x62 and 0x66 respectively.
> * They seem to be the same for many other samsung models, but if you don't check
> * them first in the H_EC._CRS section of your DSDT, you run it at YOUR OWN RISK: */
> EC_DATA_PORT = 0x62,
> EC_COMMAND_PORT = 0x66
> };
>
> int main (int argc, char** argv) {
> char status = 0;
> char data = 0;
> int count = 0;
>
> if (iopl(3)) {
> printf("Error: Permission to read/write to EmbeddedController port not granted.\n");
> return 1;
> }
>
> /* Query AC, Battery, LID, etc. events until there are no more.
> * This clears them for the EC so that it can send them again in the future, thus unblocking the EC. */
> do {
> outb(ACPI_EC_COMMAND_QUERY, EC_COMMAND_PORT);
> status = inb(EC_COMMAND_PORT);
> data = inb(EC_DATA_PORT);
> /* printf("CommandQuery 0x84, status=0x%x, data=0x%x\n", status, data); */
> } while (data != 0 && ++count < 10000); /* Note: No less than a thousand max count */
>
> printf("EmbeddedController GPE events flushed. New events can be
> produced now.\n");
>
> return 0;
> }
> ----END samsung_fix_ec_events.c ------------------------------------------
>
>
> ----- 99samsung_fix_ec_events ----------------------------------------------
> #!/bin/sh
> # NOTE: Put this file in: /usr/lib/pm-utils/sleep.d/99samsung_fix_ec_events
> #
> # On some samsung laptops (series 5 2012, series 9 2011, etc) , if many EC
> # GPE events are produced during sleep (AC plugged/unplugged, battery % change
> # change, LID open/close, etc), and they are not queried, the
> # EmbeddedController stops sending them and this creates a chicken and egg
> # situation, that can only be resolved either by hitting the reset button in
> # the back while powered off, or by simply forcing a query for the events here after resume.
>
> case "$1" in
> hibernate|suspend)
> ;;
> thaw|resume)
> #NOTE: edit this path if necessary to point to the program with the fix:
> /usr/local/bin/samsung_fix_ec_events
> ;;
> *) exit $NA
> ;;
> esac
>
> exit 0
>
> ----- END 99samsung_fix_ec_events
> -------------------------------------------
>
> --
> You received this bug notification because you are subscribed to the bug
> report.
> https://bugs.launchpad.net/bugs/971061
>
> Title:
> acpi reports battery state incorrectly
>
> Status in Linux ACPI client:
> Incomplete
> Status in “acpi” package in Ubuntu:
> Confirmed
>
> Bug description:
> I have a new Samsung 9-series laptop (NP900X3B) and the battery state
> is detected incorrectly. Basically the state what was at the time of
> boot stays active all the time - regardless of the ac-adapter state.
>
> Here is output from "acpitool -a -b" in various situations:
>
> When booted with charger connected and charger is still connected:
> Battery #1 : charging, 47.00%, 01:00:43
> AC adapter : on-line
>
> When booted with charger connected and charger is now disconnected:
> Battery #1 : charging, 47.00%, 01:36:59
> AC adapter : off-line
> [The battery couldn't possibly be charging when the AC adapter is offline!]
>
> When booted with charger disconnected and charger is still disconnected:
> Battery #1 : discharging, 47.00%, 01:39:44
> AC adapter : off-line
>
> When booted with charger disconnected and charger is now connected:
> Battery #1 : discharging, 47.00%, 00:53:43
> AC adapter : on-line
> [The battery is actually charging as the AC adapter is online]
>
> The percentage and time are correctly updated when the battery is
> actually charging or discharging - regardless of the reported state.
> So the state is the only thing that is incorrect. However a number of
> applications make their decisions based on this state (battery
> monitor, jupiter, etc.) and therefore behave incorrectly.
>
> "lshal -m" doesn't report anything when I plug the charger in or out.
>
> ProblemType: Bug
> DistroRelease: Ubuntu 12.04
> Package: acpi (not installed)
> ProcVersionSignature: Ubuntu 3.2.0-21.34-generic 3.2.13
> Uname: Linux 3.2.0-21-generic x86_64
> ApportVersion: 2.0-0ubuntu2
> Architecture: amd64
> Date: Sun Apr 1 22:50:35 2012
> EcryptfsInUse: Yes
> InstallationMedia: Ubuntu 12.04 LTS "Precise Pangolin" - Beta amd64 (20120328)
> ProcEnviron:
> LANG=en_US.UTF-8
> SHELL=/bin/bash
> SourcePackage: acpi
> UpgradeStatus: No upgrade log present (probably fresh install)
>
> To manage notifications about this bug go to:
> https://bugs.launchpad.net/acpi/+bug/971061/+subscriptions