aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/battery.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/battery.c')
-rw-r--r--drivers/acpi/battery.c94
1 files changed, 64 insertions, 30 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 98417201e9ce..95649d373071 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -42,10 +42,7 @@
42 42
43#include <acpi/acpi_bus.h> 43#include <acpi/acpi_bus.h>
44#include <acpi/acpi_drivers.h> 44#include <acpi/acpi_drivers.h>
45
46#ifdef CONFIG_ACPI_SYSFS_POWER
47#include <linux/power_supply.h> 45#include <linux/power_supply.h>
48#endif
49 46
50#define PREFIX "ACPI: " 47#define PREFIX "ACPI: "
51 48
@@ -98,13 +95,12 @@ enum {
98 * due to bad math. 95 * due to bad math.
99 */ 96 */
100 ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, 97 ACPI_BATTERY_QUIRK_SIGNED16_CURRENT,
98 ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
101}; 99};
102 100
103struct acpi_battery { 101struct acpi_battery {
104 struct mutex lock; 102 struct mutex lock;
105#ifdef CONFIG_ACPI_SYSFS_POWER
106 struct power_supply bat; 103 struct power_supply bat;
107#endif
108 struct acpi_device *device; 104 struct acpi_device *device;
109 unsigned long update_time; 105 unsigned long update_time;
110 int rate_now; 106 int rate_now;
@@ -141,7 +137,6 @@ inline int acpi_battery_present(struct acpi_battery *battery)
141 return battery->device->status.battery_present; 137 return battery->device->status.battery_present;
142} 138}
143 139
144#ifdef CONFIG_ACPI_SYSFS_POWER
145static int acpi_battery_technology(struct acpi_battery *battery) 140static int acpi_battery_technology(struct acpi_battery *battery)
146{ 141{
147 if (!strcasecmp("NiCd", battery->type)) 142 if (!strcasecmp("NiCd", battery->type))
@@ -186,6 +181,7 @@ static int acpi_battery_get_property(struct power_supply *psy,
186 enum power_supply_property psp, 181 enum power_supply_property psp,
187 union power_supply_propval *val) 182 union power_supply_propval *val)
188{ 183{
184 int ret = 0;
189 struct acpi_battery *battery = to_acpi_battery(psy); 185 struct acpi_battery *battery = to_acpi_battery(psy);
190 186
191 if (acpi_battery_present(battery)) { 187 if (acpi_battery_present(battery)) {
@@ -214,26 +210,44 @@ static int acpi_battery_get_property(struct power_supply *psy,
214 val->intval = battery->cycle_count; 210 val->intval = battery->cycle_count;
215 break; 211 break;
216 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 212 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
217 val->intval = battery->design_voltage * 1000; 213 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
214 ret = -ENODEV;
215 else
216 val->intval = battery->design_voltage * 1000;
218 break; 217 break;
219 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 218 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
220 val->intval = battery->voltage_now * 1000; 219 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
220 ret = -ENODEV;
221 else
222 val->intval = battery->voltage_now * 1000;
221 break; 223 break;
222 case POWER_SUPPLY_PROP_CURRENT_NOW: 224 case POWER_SUPPLY_PROP_CURRENT_NOW:
223 case POWER_SUPPLY_PROP_POWER_NOW: 225 case POWER_SUPPLY_PROP_POWER_NOW:
224 val->intval = battery->rate_now * 1000; 226 if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
227 ret = -ENODEV;
228 else
229 val->intval = battery->rate_now * 1000;
225 break; 230 break;
226 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 231 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
227 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: 232 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
228 val->intval = battery->design_capacity * 1000; 233 if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
234 ret = -ENODEV;
235 else
236 val->intval = battery->design_capacity * 1000;
229 break; 237 break;
230 case POWER_SUPPLY_PROP_CHARGE_FULL: 238 case POWER_SUPPLY_PROP_CHARGE_FULL:
231 case POWER_SUPPLY_PROP_ENERGY_FULL: 239 case POWER_SUPPLY_PROP_ENERGY_FULL:
232 val->intval = battery->full_charge_capacity * 1000; 240 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
241 ret = -ENODEV;
242 else
243 val->intval = battery->full_charge_capacity * 1000;
233 break; 244 break;
234 case POWER_SUPPLY_PROP_CHARGE_NOW: 245 case POWER_SUPPLY_PROP_CHARGE_NOW:
235 case POWER_SUPPLY_PROP_ENERGY_NOW: 246 case POWER_SUPPLY_PROP_ENERGY_NOW:
236 val->intval = battery->capacity_now * 1000; 247 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
248 ret = -ENODEV;
249 else
250 val->intval = battery->capacity_now * 1000;
237 break; 251 break;
238 case POWER_SUPPLY_PROP_MODEL_NAME: 252 case POWER_SUPPLY_PROP_MODEL_NAME:
239 val->strval = battery->model_number; 253 val->strval = battery->model_number;
@@ -245,9 +259,9 @@ static int acpi_battery_get_property(struct power_supply *psy,
245 val->strval = battery->serial_number; 259 val->strval = battery->serial_number;
246 break; 260 break;
247 default: 261 default:
248 return -EINVAL; 262 ret = -EINVAL;
249 } 263 }
250 return 0; 264 return ret;
251} 265}
252 266
253static enum power_supply_property charge_battery_props[] = { 267static enum power_supply_property charge_battery_props[] = {
@@ -281,7 +295,6 @@ static enum power_supply_property energy_battery_props[] = {
281 POWER_SUPPLY_PROP_MANUFACTURER, 295 POWER_SUPPLY_PROP_MANUFACTURER,
282 POWER_SUPPLY_PROP_SERIAL_NUMBER, 296 POWER_SUPPLY_PROP_SERIAL_NUMBER,
283}; 297};
284#endif
285 298
286#ifdef CONFIG_ACPI_PROCFS_POWER 299#ifdef CONFIG_ACPI_PROCFS_POWER
287inline char *acpi_battery_units(struct acpi_battery *battery) 300inline char *acpi_battery_units(struct acpi_battery *battery)
@@ -412,6 +425,8 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
412 result = extract_package(battery, buffer.pointer, 425 result = extract_package(battery, buffer.pointer,
413 info_offsets, ARRAY_SIZE(info_offsets)); 426 info_offsets, ARRAY_SIZE(info_offsets));
414 kfree(buffer.pointer); 427 kfree(buffer.pointer);
428 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
429 battery->full_charge_capacity = battery->design_capacity;
415 return result; 430 return result;
416} 431}
417 432
@@ -448,6 +463,10 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
448 battery->rate_now != -1) 463 battery->rate_now != -1)
449 battery->rate_now = abs((s16)battery->rate_now); 464 battery->rate_now = abs((s16)battery->rate_now);
450 465
466 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
467 && battery->capacity_now >= 0 && battery->capacity_now <= 100)
468 battery->capacity_now = (battery->capacity_now *
469 battery->full_charge_capacity) / 100;
451 return result; 470 return result;
452} 471}
453 472
@@ -492,7 +511,6 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery)
492 return acpi_battery_set_alarm(battery); 511 return acpi_battery_set_alarm(battery);
493} 512}
494 513
495#ifdef CONFIG_ACPI_SYSFS_POWER
496static ssize_t acpi_battery_alarm_show(struct device *dev, 514static ssize_t acpi_battery_alarm_show(struct device *dev,
497 struct device_attribute *attr, 515 struct device_attribute *attr,
498 char *buf) 516 char *buf)
@@ -552,7 +570,6 @@ static void sysfs_remove_battery(struct acpi_battery *battery)
552 power_supply_unregister(&battery->bat); 570 power_supply_unregister(&battery->bat);
553 battery->bat.dev = NULL; 571 battery->bat.dev = NULL;
554} 572}
555#endif
556 573
557static void acpi_battery_quirks(struct acpi_battery *battery) 574static void acpi_battery_quirks(struct acpi_battery *battery)
558{ 575{
@@ -561,6 +578,33 @@ static void acpi_battery_quirks(struct acpi_battery *battery)
561 } 578 }
562} 579}
563 580
581/*
582 * According to the ACPI spec, some kinds of primary batteries can
583 * report percentage battery remaining capacity directly to OS.
584 * In this case, it reports the Last Full Charged Capacity == 100
585 * and BatteryPresentRate == 0xFFFFFFFF.
586 *
587 * Now we found some battery reports percentage remaining capacity
588 * even if it's rechargeable.
589 * https://bugzilla.kernel.org/show_bug.cgi?id=15979
590 *
591 * Handle this correctly so that they won't break userspace.
592 */
593static void acpi_battery_quirks2(struct acpi_battery *battery)
594{
595 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
596 return ;
597
598 if (battery->full_charge_capacity == 100 &&
599 battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
600 battery->capacity_now >=0 && battery->capacity_now <= 100) {
601 set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
602 battery->full_charge_capacity = battery->design_capacity;
603 battery->capacity_now = (battery->capacity_now *
604 battery->full_charge_capacity) / 100;
605 }
606}
607
564static int acpi_battery_update(struct acpi_battery *battery) 608static int acpi_battery_update(struct acpi_battery *battery)
565{ 609{
566 int result, old_present = acpi_battery_present(battery); 610 int result, old_present = acpi_battery_present(battery);
@@ -568,9 +612,7 @@ static int acpi_battery_update(struct acpi_battery *battery)
568 if (result) 612 if (result)
569 return result; 613 return result;
570 if (!acpi_battery_present(battery)) { 614 if (!acpi_battery_present(battery)) {
571#ifdef CONFIG_ACPI_SYSFS_POWER
572 sysfs_remove_battery(battery); 615 sysfs_remove_battery(battery);
573#endif
574 battery->update_time = 0; 616 battery->update_time = 0;
575 return 0; 617 return 0;
576 } 618 }
@@ -582,11 +624,11 @@ static int acpi_battery_update(struct acpi_battery *battery)
582 acpi_battery_quirks(battery); 624 acpi_battery_quirks(battery);
583 acpi_battery_init_alarm(battery); 625 acpi_battery_init_alarm(battery);
584 } 626 }
585#ifdef CONFIG_ACPI_SYSFS_POWER
586 if (!battery->bat.dev) 627 if (!battery->bat.dev)
587 sysfs_add_battery(battery); 628 sysfs_add_battery(battery);
588#endif 629 result = acpi_battery_get_state(battery);
589 return acpi_battery_get_state(battery); 630 acpi_battery_quirks2(battery);
631 return result;
590} 632}
591 633
592/* -------------------------------------------------------------------------- 634/* --------------------------------------------------------------------------
@@ -867,26 +909,20 @@ static void acpi_battery_remove_fs(struct acpi_device *device)
867static void acpi_battery_notify(struct acpi_device *device, u32 event) 909static void acpi_battery_notify(struct acpi_device *device, u32 event)
868{ 910{
869 struct acpi_battery *battery = acpi_driver_data(device); 911 struct acpi_battery *battery = acpi_driver_data(device);
870#ifdef CONFIG_ACPI_SYSFS_POWER
871 struct device *old; 912 struct device *old;
872#endif
873 913
874 if (!battery) 914 if (!battery)
875 return; 915 return;
876#ifdef CONFIG_ACPI_SYSFS_POWER
877 old = battery->bat.dev; 916 old = battery->bat.dev;
878#endif
879 acpi_battery_update(battery); 917 acpi_battery_update(battery);
880 acpi_bus_generate_proc_event(device, event, 918 acpi_bus_generate_proc_event(device, event,
881 acpi_battery_present(battery)); 919 acpi_battery_present(battery));
882 acpi_bus_generate_netlink_event(device->pnp.device_class, 920 acpi_bus_generate_netlink_event(device->pnp.device_class,
883 dev_name(&device->dev), event, 921 dev_name(&device->dev), event,
884 acpi_battery_present(battery)); 922 acpi_battery_present(battery));
885#ifdef CONFIG_ACPI_SYSFS_POWER
886 /* acpi_battery_update could remove power_supply object */ 923 /* acpi_battery_update could remove power_supply object */
887 if (old && battery->bat.dev) 924 if (old && battery->bat.dev)
888 power_supply_changed(&battery->bat); 925 power_supply_changed(&battery->bat);
889#endif
890} 926}
891 927
892static int acpi_battery_add(struct acpi_device *device) 928static int acpi_battery_add(struct acpi_device *device)
@@ -934,9 +970,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
934#ifdef CONFIG_ACPI_PROCFS_POWER 970#ifdef CONFIG_ACPI_PROCFS_POWER
935 acpi_battery_remove_fs(device); 971 acpi_battery_remove_fs(device);
936#endif 972#endif
937#ifdef CONFIG_ACPI_SYSFS_POWER
938 sysfs_remove_battery(battery); 973 sysfs_remove_battery(battery);
939#endif
940 mutex_destroy(&battery->lock); 974 mutex_destroy(&battery->lock);
941 kfree(battery); 975 kfree(battery);
942 return 0; 976 return 0;