All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hector Martin <hector@marcansoft.com>
To: Alexey Starikovskiy <astarikovskiy@suse.de>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	lenb@kernel.org, linux-acpi@vger.kernel.org
Subject: Re: [PATCH] Work around negative s16 battery current on Acer
Date: Wed, 01 Jul 2009 22:19:16 +0200	[thread overview]
Message-ID: <4A4BC4C4.1030407@marcansoft.com> (raw)
In-Reply-To: <4A4BAD0C.9020302@suse.de>

[-- Attachment #1: Type: text/plain, Size: 1964 bytes --]

Alexey Starikovskiy wrote:
> Andrew Morton пишет:
>> On Wed, 01 Jul 2009 20:20:41 +0200
>> acpi_battery has no field `current_now' in 2.6.30 or 2.6.31-rc1.  Which
>> kernel version are you patching here?

2.6.29. Guess I got unlucky.

>> Also, I wonder if we need a quirk.  Is a "negative" value _ever_
>> correct?  If not, could we do the negation unconditionally?

> The problem is that the variable is s64 and not "negative" value is
> related to s16 portion of it.
> It's possible to do this only for "current" mode, in "power" mode values
> of "negative" s16 range may be valid positive values.

Exactly. This is why I further qualified the quirk so it operates for
Acer machines in current (mA) mode only. Currents >32767mA are insane,
but powers >32767mW are not.

The value is nominally a signed 32-bit int as follows:
>=0: charge current
-1: unknown

(The spec defines this in unsigned terms but the result is the same).

The problem here is that my laptop erroneously reports charging currents
as (65536 - current). Interpreting this as a signed 16-bit int yields
the correct signed value, which can then be abs()ed.

The only addition that I'd imagine might make sense would be to check
for current_now != -1 before applying the 16-bit trick, since 32-bit
signed -1 is a valid value that means "unknown current". This does not
conflict with 16-bit -1 because the 16-bits are not sign-extended so
-1mA reports as 65535, not -1. Attached new patch with this change.

For reference, the DSDT does something like this:

s32 current_now;

current_now = (EC_BAT_CURRENT_HIGH<<8) | EC_BAT_CURRENT_LOW;
current_now = (0xFFFF - current_now) + 1;

The "homebrew" two's complement negation attempts to make discharge
currents positive but also makes charge currents negative. It's also
completely wrong for 32-bit quantities, which is what we're dealing with
here.


-- 
Hector Martin (hector@marcansoft.com)
Public Key: http://www.marcansoft.com/marcan.asc


[-- Attachment #2: acpi-battery-acer-rate-quirk.patch --]
[-- Type: text/plain, Size: 1514 bytes --]

Signed-off-by: Hector Martin <hector@marcansoft.com>
--- linux/drivers/acpi/battery.c.old	2009-07-01 19:17:33.000000000 +0200
+++ linux/drivers/acpi/battery.c	2009-07-01 19:52:43.000000000 +0200
@@ -84,6 +84,10 @@
 
 MODULE_DEVICE_TABLE(acpi, battery_device_ids);
 
+/* For buggy DSDTs that report negative 16-bit values for either charging
+ * or discharging and/or report 0 as 65536 due to bad math.
+ */
+#define QUIRK_SIGNED16_CURRENT 0x0001
 
 struct acpi_battery {
 	struct mutex lock;
@@ -111,6 +115,7 @@
 	int state;
 	int power_unit;
 	u8 alarm_present;
+	long quirks;
 };
 
 #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
@@ -387,6 +392,10 @@
 				 state_offsets, ARRAY_SIZE(state_offsets));
 	battery->update_time = jiffies;
 	kfree(buffer.pointer);
+
+	if ((battery->quirks & QUIRK_SIGNED16_CURRENT) && battery->current_now != -1)
+		battery->current_now = abs((s16)battery->current_now);
+
 	return result;
 }
 
@@ -492,6 +501,14 @@
 }
 #endif
 
+static void acpi_battery_quirks(struct acpi_battery *battery)
+{
+	battery->quirks = 0;
+	if (dmi_name_in_vendors("Acer") && battery->power_unit) {
+		battery->quirks |= QUIRK_SIGNED16_CURRENT;
+	}
+}
+
 static int acpi_battery_update(struct acpi_battery *battery)
 {
 	int result, old_present = acpi_battery_present(battery);
@@ -510,6 +527,7 @@
 		result = acpi_battery_get_info(battery);
 		if (result)
 			return result;
+		acpi_battery_quirks(battery);
 		acpi_battery_init_alarm(battery);
 	}
 #ifdef CONFIG_ACPI_SYSFS_POWER

  reply	other threads:[~2009-07-01 20:19 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-07-01 18:20 [PATCH] Work around negative s16 battery current on Acer Hector Martin
2009-07-01 18:27 ` Alexey Starikovskiy
2009-07-01 18:29 ` Andrew Morton
2009-07-01 18:38   ` Alexey Starikovskiy
2009-07-01 20:19     ` Hector Martin [this message]
2009-07-02  3:51   ` Hector Martin
2009-07-02 22:56     ` Andrew Morton
2009-07-02 23:46       ` [PATCH] Work around negative s16 battery current on Acer (take 3) Hector Martin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4A4BC4C4.1030407@marcansoft.com \
    --to=hector@marcansoft.com \
    --cc=akpm@linux-foundation.org \
    --cc=astarikovskiy@suse.de \
    --cc=lenb@kernel.org \
    --cc=linux-acpi@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.