diff options
Diffstat (limited to 'drivers/acpi/battery.c')
-rw-r--r-- | drivers/acpi/battery.c | 95 |
1 files changed, 64 insertions, 31 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index dc58402b0a1..95649d37307 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 | ||
103 | struct acpi_battery { | 101 | struct 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 | ||
145 | static int acpi_battery_technology(struct acpi_battery *battery) | 140 | static 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 | ||
253 | static enum power_supply_property charge_battery_props[] = { | 267 | static enum power_supply_property charge_battery_props[] = { |
@@ -273,7 +287,6 @@ static enum power_supply_property energy_battery_props[] = { | |||
273 | POWER_SUPPLY_PROP_CYCLE_COUNT, | 287 | POWER_SUPPLY_PROP_CYCLE_COUNT, |
274 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, | 288 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, |
275 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | 289 | POWER_SUPPLY_PROP_VOLTAGE_NOW, |
276 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
277 | POWER_SUPPLY_PROP_POWER_NOW, | 290 | POWER_SUPPLY_PROP_POWER_NOW, |
278 | POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, | 291 | POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, |
279 | POWER_SUPPLY_PROP_ENERGY_FULL, | 292 | POWER_SUPPLY_PROP_ENERGY_FULL, |
@@ -282,7 +295,6 @@ static enum power_supply_property energy_battery_props[] = { | |||
282 | POWER_SUPPLY_PROP_MANUFACTURER, | 295 | POWER_SUPPLY_PROP_MANUFACTURER, |
283 | POWER_SUPPLY_PROP_SERIAL_NUMBER, | 296 | POWER_SUPPLY_PROP_SERIAL_NUMBER, |
284 | }; | 297 | }; |
285 | #endif | ||
286 | 298 | ||
287 | #ifdef CONFIG_ACPI_PROCFS_POWER | 299 | #ifdef CONFIG_ACPI_PROCFS_POWER |
288 | inline char *acpi_battery_units(struct acpi_battery *battery) | 300 | inline char *acpi_battery_units(struct acpi_battery *battery) |
@@ -413,6 +425,8 @@ static int acpi_battery_get_info(struct acpi_battery *battery) | |||
413 | result = extract_package(battery, buffer.pointer, | 425 | result = extract_package(battery, buffer.pointer, |
414 | info_offsets, ARRAY_SIZE(info_offsets)); | 426 | info_offsets, ARRAY_SIZE(info_offsets)); |
415 | 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; | ||
416 | return result; | 430 | return result; |
417 | } | 431 | } |
418 | 432 | ||
@@ -449,6 +463,10 @@ static int acpi_battery_get_state(struct acpi_battery *battery) | |||
449 | battery->rate_now != -1) | 463 | battery->rate_now != -1) |
450 | battery->rate_now = abs((s16)battery->rate_now); | 464 | battery->rate_now = abs((s16)battery->rate_now); |
451 | 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; | ||
452 | return result; | 470 | return result; |
453 | } | 471 | } |
454 | 472 | ||
@@ -493,7 +511,6 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery) | |||
493 | return acpi_battery_set_alarm(battery); | 511 | return acpi_battery_set_alarm(battery); |
494 | } | 512 | } |
495 | 513 | ||
496 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
497 | static ssize_t acpi_battery_alarm_show(struct device *dev, | 514 | static ssize_t acpi_battery_alarm_show(struct device *dev, |
498 | struct device_attribute *attr, | 515 | struct device_attribute *attr, |
499 | char *buf) | 516 | char *buf) |
@@ -553,7 +570,6 @@ static void sysfs_remove_battery(struct acpi_battery *battery) | |||
553 | power_supply_unregister(&battery->bat); | 570 | power_supply_unregister(&battery->bat); |
554 | battery->bat.dev = NULL; | 571 | battery->bat.dev = NULL; |
555 | } | 572 | } |
556 | #endif | ||
557 | 573 | ||
558 | static void acpi_battery_quirks(struct acpi_battery *battery) | 574 | static void acpi_battery_quirks(struct acpi_battery *battery) |
559 | { | 575 | { |
@@ -562,6 +578,33 @@ static void acpi_battery_quirks(struct acpi_battery *battery) | |||
562 | } | 578 | } |
563 | } | 579 | } |
564 | 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 | */ | ||
593 | static 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 | |||
565 | static int acpi_battery_update(struct acpi_battery *battery) | 608 | static int acpi_battery_update(struct acpi_battery *battery) |
566 | { | 609 | { |
567 | int result, old_present = acpi_battery_present(battery); | 610 | int result, old_present = acpi_battery_present(battery); |
@@ -569,9 +612,7 @@ static int acpi_battery_update(struct acpi_battery *battery) | |||
569 | if (result) | 612 | if (result) |
570 | return result; | 613 | return result; |
571 | if (!acpi_battery_present(battery)) { | 614 | if (!acpi_battery_present(battery)) { |
572 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
573 | sysfs_remove_battery(battery); | 615 | sysfs_remove_battery(battery); |
574 | #endif | ||
575 | battery->update_time = 0; | 616 | battery->update_time = 0; |
576 | return 0; | 617 | return 0; |
577 | } | 618 | } |
@@ -583,11 +624,11 @@ static int acpi_battery_update(struct acpi_battery *battery) | |||
583 | acpi_battery_quirks(battery); | 624 | acpi_battery_quirks(battery); |
584 | acpi_battery_init_alarm(battery); | 625 | acpi_battery_init_alarm(battery); |
585 | } | 626 | } |
586 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
587 | if (!battery->bat.dev) | 627 | if (!battery->bat.dev) |
588 | sysfs_add_battery(battery); | 628 | sysfs_add_battery(battery); |
589 | #endif | 629 | result = acpi_battery_get_state(battery); |
590 | return acpi_battery_get_state(battery); | 630 | acpi_battery_quirks2(battery); |
631 | return result; | ||
591 | } | 632 | } |
592 | 633 | ||
593 | /* -------------------------------------------------------------------------- | 634 | /* -------------------------------------------------------------------------- |
@@ -868,26 +909,20 @@ static void acpi_battery_remove_fs(struct acpi_device *device) | |||
868 | static void acpi_battery_notify(struct acpi_device *device, u32 event) | 909 | static void acpi_battery_notify(struct acpi_device *device, u32 event) |
869 | { | 910 | { |
870 | struct acpi_battery *battery = acpi_driver_data(device); | 911 | struct acpi_battery *battery = acpi_driver_data(device); |
871 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
872 | struct device *old; | 912 | struct device *old; |
873 | #endif | ||
874 | 913 | ||
875 | if (!battery) | 914 | if (!battery) |
876 | return; | 915 | return; |
877 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
878 | old = battery->bat.dev; | 916 | old = battery->bat.dev; |
879 | #endif | ||
880 | acpi_battery_update(battery); | 917 | acpi_battery_update(battery); |
881 | acpi_bus_generate_proc_event(device, event, | 918 | acpi_bus_generate_proc_event(device, event, |
882 | acpi_battery_present(battery)); | 919 | acpi_battery_present(battery)); |
883 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 920 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
884 | dev_name(&device->dev), event, | 921 | dev_name(&device->dev), event, |
885 | acpi_battery_present(battery)); | 922 | acpi_battery_present(battery)); |
886 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
887 | /* acpi_battery_update could remove power_supply object */ | 923 | /* acpi_battery_update could remove power_supply object */ |
888 | if (old && battery->bat.dev) | 924 | if (old && battery->bat.dev) |
889 | power_supply_changed(&battery->bat); | 925 | power_supply_changed(&battery->bat); |
890 | #endif | ||
891 | } | 926 | } |
892 | 927 | ||
893 | static int acpi_battery_add(struct acpi_device *device) | 928 | static int acpi_battery_add(struct acpi_device *device) |
@@ -935,9 +970,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type) | |||
935 | #ifdef CONFIG_ACPI_PROCFS_POWER | 970 | #ifdef CONFIG_ACPI_PROCFS_POWER |
936 | acpi_battery_remove_fs(device); | 971 | acpi_battery_remove_fs(device); |
937 | #endif | 972 | #endif |
938 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
939 | sysfs_remove_battery(battery); | 973 | sysfs_remove_battery(battery); |
940 | #endif | ||
941 | mutex_destroy(&battery->lock); | 974 | mutex_destroy(&battery->lock); |
942 | kfree(battery); | 975 | kfree(battery); |
943 | return 0; | 976 | return 0; |