aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/battery.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/acpi/battery.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/acpi/battery.c')
-rw-r--r--drivers/acpi/battery.c131
1 files changed, 101 insertions, 30 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 98417201e9ce..fcc13ac0aa18 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -33,6 +33,7 @@
33#include <linux/async.h> 33#include <linux/async.h>
34#include <linux/dmi.h> 34#include <linux/dmi.h>
35#include <linux/slab.h> 35#include <linux/slab.h>
36#include <linux/suspend.h>
36 37
37#ifdef CONFIG_ACPI_PROCFS_POWER 38#ifdef CONFIG_ACPI_PROCFS_POWER
38#include <linux/proc_fs.h> 39#include <linux/proc_fs.h>
@@ -42,10 +43,7 @@
42 43
43#include <acpi/acpi_bus.h> 44#include <acpi/acpi_bus.h>
44#include <acpi/acpi_drivers.h> 45#include <acpi/acpi_drivers.h>
45
46#ifdef CONFIG_ACPI_SYSFS_POWER
47#include <linux/power_supply.h> 46#include <linux/power_supply.h>
48#endif
49 47
50#define PREFIX "ACPI: " 48#define PREFIX "ACPI: "
51 49
@@ -98,14 +96,14 @@ enum {
98 * due to bad math. 96 * due to bad math.
99 */ 97 */
100 ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, 98 ACPI_BATTERY_QUIRK_SIGNED16_CURRENT,
99 ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
101}; 100};
102 101
103struct acpi_battery { 102struct acpi_battery {
104 struct mutex lock; 103 struct mutex lock;
105#ifdef CONFIG_ACPI_SYSFS_POWER
106 struct power_supply bat; 104 struct power_supply bat;
107#endif
108 struct acpi_device *device; 105 struct acpi_device *device;
106 struct notifier_block pm_nb;
109 unsigned long update_time; 107 unsigned long update_time;
110 int rate_now; 108 int rate_now;
111 int capacity_now; 109 int capacity_now;
@@ -141,7 +139,6 @@ inline int acpi_battery_present(struct acpi_battery *battery)
141 return battery->device->status.battery_present; 139 return battery->device->status.battery_present;
142} 140}
143 141
144#ifdef CONFIG_ACPI_SYSFS_POWER
145static int acpi_battery_technology(struct acpi_battery *battery) 142static int acpi_battery_technology(struct acpi_battery *battery)
146{ 143{
147 if (!strcasecmp("NiCd", battery->type)) 144 if (!strcasecmp("NiCd", battery->type))
@@ -186,6 +183,7 @@ static int acpi_battery_get_property(struct power_supply *psy,
186 enum power_supply_property psp, 183 enum power_supply_property psp,
187 union power_supply_propval *val) 184 union power_supply_propval *val)
188{ 185{
186 int ret = 0;
189 struct acpi_battery *battery = to_acpi_battery(psy); 187 struct acpi_battery *battery = to_acpi_battery(psy);
190 188
191 if (acpi_battery_present(battery)) { 189 if (acpi_battery_present(battery)) {
@@ -214,26 +212,44 @@ static int acpi_battery_get_property(struct power_supply *psy,
214 val->intval = battery->cycle_count; 212 val->intval = battery->cycle_count;
215 break; 213 break;
216 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 214 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
217 val->intval = battery->design_voltage * 1000; 215 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
216 ret = -ENODEV;
217 else
218 val->intval = battery->design_voltage * 1000;
218 break; 219 break;
219 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 220 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
220 val->intval = battery->voltage_now * 1000; 221 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
222 ret = -ENODEV;
223 else
224 val->intval = battery->voltage_now * 1000;
221 break; 225 break;
222 case POWER_SUPPLY_PROP_CURRENT_NOW: 226 case POWER_SUPPLY_PROP_CURRENT_NOW:
223 case POWER_SUPPLY_PROP_POWER_NOW: 227 case POWER_SUPPLY_PROP_POWER_NOW:
224 val->intval = battery->rate_now * 1000; 228 if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
229 ret = -ENODEV;
230 else
231 val->intval = battery->rate_now * 1000;
225 break; 232 break;
226 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 233 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
227 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: 234 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
228 val->intval = battery->design_capacity * 1000; 235 if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
236 ret = -ENODEV;
237 else
238 val->intval = battery->design_capacity * 1000;
229 break; 239 break;
230 case POWER_SUPPLY_PROP_CHARGE_FULL: 240 case POWER_SUPPLY_PROP_CHARGE_FULL:
231 case POWER_SUPPLY_PROP_ENERGY_FULL: 241 case POWER_SUPPLY_PROP_ENERGY_FULL:
232 val->intval = battery->full_charge_capacity * 1000; 242 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
243 ret = -ENODEV;
244 else
245 val->intval = battery->full_charge_capacity * 1000;
233 break; 246 break;
234 case POWER_SUPPLY_PROP_CHARGE_NOW: 247 case POWER_SUPPLY_PROP_CHARGE_NOW:
235 case POWER_SUPPLY_PROP_ENERGY_NOW: 248 case POWER_SUPPLY_PROP_ENERGY_NOW:
236 val->intval = battery->capacity_now * 1000; 249 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
250 ret = -ENODEV;
251 else
252 val->intval = battery->capacity_now * 1000;
237 break; 253 break;
238 case POWER_SUPPLY_PROP_MODEL_NAME: 254 case POWER_SUPPLY_PROP_MODEL_NAME:
239 val->strval = battery->model_number; 255 val->strval = battery->model_number;
@@ -245,9 +261,9 @@ static int acpi_battery_get_property(struct power_supply *psy,
245 val->strval = battery->serial_number; 261 val->strval = battery->serial_number;
246 break; 262 break;
247 default: 263 default:
248 return -EINVAL; 264 ret = -EINVAL;
249 } 265 }
250 return 0; 266 return ret;
251} 267}
252 268
253static enum power_supply_property charge_battery_props[] = { 269static enum power_supply_property charge_battery_props[] = {
@@ -281,7 +297,6 @@ static enum power_supply_property energy_battery_props[] = {
281 POWER_SUPPLY_PROP_MANUFACTURER, 297 POWER_SUPPLY_PROP_MANUFACTURER,
282 POWER_SUPPLY_PROP_SERIAL_NUMBER, 298 POWER_SUPPLY_PROP_SERIAL_NUMBER,
283}; 299};
284#endif
285 300
286#ifdef CONFIG_ACPI_PROCFS_POWER 301#ifdef CONFIG_ACPI_PROCFS_POWER
287inline char *acpi_battery_units(struct acpi_battery *battery) 302inline char *acpi_battery_units(struct acpi_battery *battery)
@@ -412,6 +427,8 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
412 result = extract_package(battery, buffer.pointer, 427 result = extract_package(battery, buffer.pointer,
413 info_offsets, ARRAY_SIZE(info_offsets)); 428 info_offsets, ARRAY_SIZE(info_offsets));
414 kfree(buffer.pointer); 429 kfree(buffer.pointer);
430 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
431 battery->full_charge_capacity = battery->design_capacity;
415 return result; 432 return result;
416} 433}
417 434
@@ -448,6 +465,10 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
448 battery->rate_now != -1) 465 battery->rate_now != -1)
449 battery->rate_now = abs((s16)battery->rate_now); 466 battery->rate_now = abs((s16)battery->rate_now);
450 467
468 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
469 && battery->capacity_now >= 0 && battery->capacity_now <= 100)
470 battery->capacity_now = (battery->capacity_now *
471 battery->full_charge_capacity) / 100;
451 return result; 472 return result;
452} 473}
453 474
@@ -492,7 +513,6 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery)
492 return acpi_battery_set_alarm(battery); 513 return acpi_battery_set_alarm(battery);
493} 514}
494 515
495#ifdef CONFIG_ACPI_SYSFS_POWER
496static ssize_t acpi_battery_alarm_show(struct device *dev, 516static ssize_t acpi_battery_alarm_show(struct device *dev,
497 struct device_attribute *attr, 517 struct device_attribute *attr,
498 char *buf) 518 char *buf)
@@ -552,7 +572,6 @@ static void sysfs_remove_battery(struct acpi_battery *battery)
552 power_supply_unregister(&battery->bat); 572 power_supply_unregister(&battery->bat);
553 battery->bat.dev = NULL; 573 battery->bat.dev = NULL;
554} 574}
555#endif
556 575
557static void acpi_battery_quirks(struct acpi_battery *battery) 576static void acpi_battery_quirks(struct acpi_battery *battery)
558{ 577{
@@ -561,6 +580,33 @@ static void acpi_battery_quirks(struct acpi_battery *battery)
561 } 580 }
562} 581}
563 582
583/*
584 * According to the ACPI spec, some kinds of primary batteries can
585 * report percentage battery remaining capacity directly to OS.
586 * In this case, it reports the Last Full Charged Capacity == 100
587 * and BatteryPresentRate == 0xFFFFFFFF.
588 *
589 * Now we found some battery reports percentage remaining capacity
590 * even if it's rechargeable.
591 * https://bugzilla.kernel.org/show_bug.cgi?id=15979
592 *
593 * Handle this correctly so that they won't break userspace.
594 */
595static void acpi_battery_quirks2(struct acpi_battery *battery)
596{
597 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
598 return ;
599
600 if (battery->full_charge_capacity == 100 &&
601 battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
602 battery->capacity_now >=0 && battery->capacity_now <= 100) {
603 set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
604 battery->full_charge_capacity = battery->design_capacity;
605 battery->capacity_now = (battery->capacity_now *
606 battery->full_charge_capacity) / 100;
607 }
608}
609
564static int acpi_battery_update(struct acpi_battery *battery) 610static int acpi_battery_update(struct acpi_battery *battery)
565{ 611{
566 int result, old_present = acpi_battery_present(battery); 612 int result, old_present = acpi_battery_present(battery);
@@ -568,9 +614,7 @@ static int acpi_battery_update(struct acpi_battery *battery)
568 if (result) 614 if (result)
569 return result; 615 return result;
570 if (!acpi_battery_present(battery)) { 616 if (!acpi_battery_present(battery)) {
571#ifdef CONFIG_ACPI_SYSFS_POWER
572 sysfs_remove_battery(battery); 617 sysfs_remove_battery(battery);
573#endif
574 battery->update_time = 0; 618 battery->update_time = 0;
575 return 0; 619 return 0;
576 } 620 }
@@ -582,11 +626,22 @@ static int acpi_battery_update(struct acpi_battery *battery)
582 acpi_battery_quirks(battery); 626 acpi_battery_quirks(battery);
583 acpi_battery_init_alarm(battery); 627 acpi_battery_init_alarm(battery);
584 } 628 }
585#ifdef CONFIG_ACPI_SYSFS_POWER
586 if (!battery->bat.dev) 629 if (!battery->bat.dev)
587 sysfs_add_battery(battery); 630 sysfs_add_battery(battery);
588#endif 631 result = acpi_battery_get_state(battery);
589 return acpi_battery_get_state(battery); 632 acpi_battery_quirks2(battery);
633 return result;
634}
635
636static void acpi_battery_refresh(struct acpi_battery *battery)
637{
638 if (!battery->bat.dev)
639 return;
640
641 acpi_battery_get_info(battery);
642 /* The battery may have changed its reporting units. */
643 sysfs_remove_battery(battery);
644 sysfs_add_battery(battery);
590} 645}
591 646
592/* -------------------------------------------------------------------------- 647/* --------------------------------------------------------------------------
@@ -826,6 +881,8 @@ static int acpi_battery_add_fs(struct acpi_device *device)
826 struct proc_dir_entry *entry = NULL; 881 struct proc_dir_entry *entry = NULL;
827 int i; 882 int i;
828 883
884 printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded,"
885 " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
829 if (!acpi_device_dir(device)) { 886 if (!acpi_device_dir(device)) {
830 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), 887 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
831 acpi_battery_dir); 888 acpi_battery_dir);
@@ -867,26 +924,37 @@ static void acpi_battery_remove_fs(struct acpi_device *device)
867static void acpi_battery_notify(struct acpi_device *device, u32 event) 924static void acpi_battery_notify(struct acpi_device *device, u32 event)
868{ 925{
869 struct acpi_battery *battery = acpi_driver_data(device); 926 struct acpi_battery *battery = acpi_driver_data(device);
870#ifdef CONFIG_ACPI_SYSFS_POWER
871 struct device *old; 927 struct device *old;
872#endif
873 928
874 if (!battery) 929 if (!battery)
875 return; 930 return;
876#ifdef CONFIG_ACPI_SYSFS_POWER
877 old = battery->bat.dev; 931 old = battery->bat.dev;
878#endif 932 if (event == ACPI_BATTERY_NOTIFY_INFO)
933 acpi_battery_refresh(battery);
879 acpi_battery_update(battery); 934 acpi_battery_update(battery);
880 acpi_bus_generate_proc_event(device, event, 935 acpi_bus_generate_proc_event(device, event,
881 acpi_battery_present(battery)); 936 acpi_battery_present(battery));
882 acpi_bus_generate_netlink_event(device->pnp.device_class, 937 acpi_bus_generate_netlink_event(device->pnp.device_class,
883 dev_name(&device->dev), event, 938 dev_name(&device->dev), event,
884 acpi_battery_present(battery)); 939 acpi_battery_present(battery));
885#ifdef CONFIG_ACPI_SYSFS_POWER
886 /* acpi_battery_update could remove power_supply object */ 940 /* acpi_battery_update could remove power_supply object */
887 if (old && battery->bat.dev) 941 if (old && battery->bat.dev)
888 power_supply_changed(&battery->bat); 942 power_supply_changed(&battery->bat);
889#endif 943}
944
945static int battery_notify(struct notifier_block *nb,
946 unsigned long mode, void *_unused)
947{
948 struct acpi_battery *battery = container_of(nb, struct acpi_battery,
949 pm_nb);
950 switch (mode) {
951 case PM_POST_SUSPEND:
952 sysfs_remove_battery(battery);
953 sysfs_add_battery(battery);
954 break;
955 }
956
957 return 0;
890} 958}
891 959
892static int acpi_battery_add(struct acpi_device *device) 960static int acpi_battery_add(struct acpi_device *device)
@@ -921,6 +989,10 @@ static int acpi_battery_add(struct acpi_device *device)
921#endif 989#endif
922 kfree(battery); 990 kfree(battery);
923 } 991 }
992
993 battery->pm_nb.notifier_call = battery_notify;
994 register_pm_notifier(&battery->pm_nb);
995
924 return result; 996 return result;
925} 997}
926 998
@@ -931,12 +1003,11 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
931 if (!device || !acpi_driver_data(device)) 1003 if (!device || !acpi_driver_data(device))
932 return -EINVAL; 1004 return -EINVAL;
933 battery = acpi_driver_data(device); 1005 battery = acpi_driver_data(device);
1006 unregister_pm_notifier(&battery->pm_nb);
934#ifdef CONFIG_ACPI_PROCFS_POWER 1007#ifdef CONFIG_ACPI_PROCFS_POWER
935 acpi_battery_remove_fs(device); 1008 acpi_battery_remove_fs(device);
936#endif 1009#endif
937#ifdef CONFIG_ACPI_SYSFS_POWER
938 sysfs_remove_battery(battery); 1010 sysfs_remove_battery(battery);
939#endif
940 mutex_destroy(&battery->lock); 1011 mutex_destroy(&battery->lock);
941 kfree(battery); 1012 kfree(battery);
942 return 0; 1013 return 0;