From patchwork Wed Jul 1 18:20:41 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hector Martin X-Patchwork-Id: 33542 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n61ITXrK027072 for ; Wed, 1 Jul 2009 18:29:34 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752815AbZGAS32 (ORCPT ); Wed, 1 Jul 2009 14:29:28 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753300AbZGAS32 (ORCPT ); Wed, 1 Jul 2009 14:29:28 -0400 Received: from marcansoft.com ([80.68.93.119]:59188 "EHLO smtp.marcansoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752815AbZGAS31 (ORCPT ); Wed, 1 Jul 2009 14:29:27 -0400 X-Greylist: delayed 526 seconds by postgrey-1.27 at vger.kernel.org; Wed, 01 Jul 2009 14:29:27 EDT Received: from [192.168.3.171] (85.Red-88-24-251.staticIP.rima-tde.net [88.24.251.85]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.marcansoft.com (Postfix) with ESMTPSA id 52B441E8004; Wed, 1 Jul 2009 20:20:43 +0200 (CEST) Message-ID: <4A4BA8F9.9070803@marcansoft.com> Date: Wed, 01 Jul 2009 20:20:41 +0200 From: Hector Martin User-Agent: Thunderbird 2.0.0.21 (X11/20090530) MIME-Version: 1.0 To: Alexey Starikovskiy , Len Brown CC: linux-acpi@vger.kernel.org, Andrew Morton Subject: [PATCH] Work around negative s16 battery current on Acer Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org My Acer Aspire 8930G laptop reports the battery current as a 16-bit signed negative when it is charging. It also reports it as 0x10000 when the current is 0. This patch adds a quirk for this which takes the absolute value of the reported current cast to an s16. This is a DSDT bug present in the latest BIOS revision (the EC register is 16 bits signed and the DSDT attempts to take the 16-bit two's complement of this, which works for discharge but not charge. It also breaks zero values because a 32-bit register is used and the high bits aren't thrown away). I've enabled this for all Acer systems which report in mA units. This should be safe since it won't break compliant systems unless they report a current above 32A, which is insane. --- 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 = 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