diff options
Diffstat (limited to 'drivers/acpi/battery.c')
-rw-r--r-- | drivers/acpi/battery.c | 131 |
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 | ||
103 | struct acpi_battery { | 102 | struct 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 | ||
145 | static int acpi_battery_technology(struct acpi_battery *battery) | 142 | static 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 | ||
253 | static enum power_supply_property charge_battery_props[] = { | 269 | static 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 |
287 | inline char *acpi_battery_units(struct acpi_battery *battery) | 302 | inline 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 | ||
496 | static ssize_t acpi_battery_alarm_show(struct device *dev, | 516 | static 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 | ||
557 | static void acpi_battery_quirks(struct acpi_battery *battery) | 576 | static 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 | */ | ||
595 | static 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 | |||
564 | static int acpi_battery_update(struct acpi_battery *battery) | 610 | static 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 | |||
636 | static 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) | |||
867 | static void acpi_battery_notify(struct acpi_device *device, u32 event) | 924 | static 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 | |||
945 | static 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 | ||
892 | static int acpi_battery_add(struct acpi_device *device) | 960 | static 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; |