battery: don't assume we are fully charged when not charging or discharging

On hardware like the T61 it can take a couple of seconds for the battery
to start charging after the power is connected, and we incorrectly tell
userspace that we are fully charged, and then go back to charging.

Only mark a battery as fully charged when the preset charge matches either
the last full charge, or the design charge.

http://bugzilla.kernel.org/show_bug.cgi?id=12632

Signed-off-by: Richard Hughes <hughsient@gmail.com>
Acked-by: Alexey Starikovskiy <astarikovskiy@suse.de>
Acked-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Len Brown <len.brown@intel.com>

authored by Richard Hughes and committed by Len Brown 56f382a0 e83102ca

+24 -1
+24 -1
drivers/acpi/battery.c
··· 138 139 static int acpi_battery_get_state(struct acpi_battery *battery); 140 141 static int acpi_battery_get_property(struct power_supply *psy, 142 enum power_supply_property psp, 143 union power_supply_propval *val) ··· 178 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 179 else if (battery->state & 0x02) 180 val->intval = POWER_SUPPLY_STATUS_CHARGING; 181 - else if (battery->state == 0) 182 val->intval = POWER_SUPPLY_STATUS_FULL; 183 else 184 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
··· 138 139 static int acpi_battery_get_state(struct acpi_battery *battery); 140 141 + static int acpi_battery_is_charged(struct acpi_battery *battery) 142 + { 143 + /* either charging or discharging */ 144 + if (battery->state != 0) 145 + return 0; 146 + 147 + /* battery not reporting charge */ 148 + if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN || 149 + battery->capacity_now == 0) 150 + return 0; 151 + 152 + /* good batteries update full_charge as the batteries degrade */ 153 + if (battery->full_charge_capacity == battery->capacity_now) 154 + return 1; 155 + 156 + /* fallback to using design values for broken batteries */ 157 + if (battery->design_capacity == battery->capacity_now) 158 + return 1; 159 + 160 + /* we don't do any sort of metric based on percentages */ 161 + return 0; 162 + } 163 + 164 static int acpi_battery_get_property(struct power_supply *psy, 165 enum power_supply_property psp, 166 union power_supply_propval *val) ··· 155 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 156 else if (battery->state & 0x02) 157 val->intval = POWER_SUPPLY_STATUS_CHARGING; 158 + else if (acpi_battery_is_charged(battery)) 159 val->intval = POWER_SUPPLY_STATUS_FULL; 160 else 161 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;