diff options
Diffstat (limited to 'drivers/acpi/battery.c')
-rw-r--r-- | drivers/acpi/battery.c | 59 |
1 files changed, 37 insertions, 22 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index ac74a7ddaaa4..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 | ||
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)) |
@@ -300,7 +295,6 @@ static enum power_supply_property energy_battery_props[] = { | |||
300 | POWER_SUPPLY_PROP_MANUFACTURER, | 295 | POWER_SUPPLY_PROP_MANUFACTURER, |
301 | POWER_SUPPLY_PROP_SERIAL_NUMBER, | 296 | POWER_SUPPLY_PROP_SERIAL_NUMBER, |
302 | }; | 297 | }; |
303 | #endif | ||
304 | 298 | ||
305 | #ifdef CONFIG_ACPI_PROCFS_POWER | 299 | #ifdef CONFIG_ACPI_PROCFS_POWER |
306 | inline char *acpi_battery_units(struct acpi_battery *battery) | 300 | inline char *acpi_battery_units(struct acpi_battery *battery) |
@@ -431,6 +425,8 @@ static int acpi_battery_get_info(struct acpi_battery *battery) | |||
431 | result = extract_package(battery, buffer.pointer, | 425 | result = extract_package(battery, buffer.pointer, |
432 | info_offsets, ARRAY_SIZE(info_offsets)); | 426 | info_offsets, ARRAY_SIZE(info_offsets)); |
433 | 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; | ||
434 | return result; | 430 | return result; |
435 | } | 431 | } |
436 | 432 | ||
@@ -467,6 +463,10 @@ static int acpi_battery_get_state(struct acpi_battery *battery) | |||
467 | battery->rate_now != -1) | 463 | battery->rate_now != -1) |
468 | battery->rate_now = abs((s16)battery->rate_now); | 464 | battery->rate_now = abs((s16)battery->rate_now); |
469 | 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; | ||
470 | return result; | 470 | return result; |
471 | } | 471 | } |
472 | 472 | ||
@@ -511,7 +511,6 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery) | |||
511 | return acpi_battery_set_alarm(battery); | 511 | return acpi_battery_set_alarm(battery); |
512 | } | 512 | } |
513 | 513 | ||
514 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
515 | static ssize_t acpi_battery_alarm_show(struct device *dev, | 514 | static ssize_t acpi_battery_alarm_show(struct device *dev, |
516 | struct device_attribute *attr, | 515 | struct device_attribute *attr, |
517 | char *buf) | 516 | char *buf) |
@@ -571,7 +570,6 @@ static void sysfs_remove_battery(struct acpi_battery *battery) | |||
571 | power_supply_unregister(&battery->bat); | 570 | power_supply_unregister(&battery->bat); |
572 | battery->bat.dev = NULL; | 571 | battery->bat.dev = NULL; |
573 | } | 572 | } |
574 | #endif | ||
575 | 573 | ||
576 | static void acpi_battery_quirks(struct acpi_battery *battery) | 574 | static void acpi_battery_quirks(struct acpi_battery *battery) |
577 | { | 575 | { |
@@ -580,6 +578,33 @@ static void acpi_battery_quirks(struct acpi_battery *battery) | |||
580 | } | 578 | } |
581 | } | 579 | } |
582 | 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 | |||
583 | static int acpi_battery_update(struct acpi_battery *battery) | 608 | static int acpi_battery_update(struct acpi_battery *battery) |
584 | { | 609 | { |
585 | int result, old_present = acpi_battery_present(battery); | 610 | int result, old_present = acpi_battery_present(battery); |
@@ -587,9 +612,7 @@ static int acpi_battery_update(struct acpi_battery *battery) | |||
587 | if (result) | 612 | if (result) |
588 | return result; | 613 | return result; |
589 | if (!acpi_battery_present(battery)) { | 614 | if (!acpi_battery_present(battery)) { |
590 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
591 | sysfs_remove_battery(battery); | 615 | sysfs_remove_battery(battery); |
592 | #endif | ||
593 | battery->update_time = 0; | 616 | battery->update_time = 0; |
594 | return 0; | 617 | return 0; |
595 | } | 618 | } |
@@ -601,11 +624,11 @@ static int acpi_battery_update(struct acpi_battery *battery) | |||
601 | acpi_battery_quirks(battery); | 624 | acpi_battery_quirks(battery); |
602 | acpi_battery_init_alarm(battery); | 625 | acpi_battery_init_alarm(battery); |
603 | } | 626 | } |
604 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
605 | if (!battery->bat.dev) | 627 | if (!battery->bat.dev) |
606 | sysfs_add_battery(battery); | 628 | sysfs_add_battery(battery); |
607 | #endif | 629 | result = acpi_battery_get_state(battery); |
608 | return acpi_battery_get_state(battery); | 630 | acpi_battery_quirks2(battery); |
631 | return result; | ||
609 | } | 632 | } |
610 | 633 | ||
611 | /* -------------------------------------------------------------------------- | 634 | /* -------------------------------------------------------------------------- |
@@ -886,26 +909,20 @@ static void acpi_battery_remove_fs(struct acpi_device *device) | |||
886 | static void acpi_battery_notify(struct acpi_device *device, u32 event) | 909 | static void acpi_battery_notify(struct acpi_device *device, u32 event) |
887 | { | 910 | { |
888 | struct acpi_battery *battery = acpi_driver_data(device); | 911 | struct acpi_battery *battery = acpi_driver_data(device); |
889 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
890 | struct device *old; | 912 | struct device *old; |
891 | #endif | ||
892 | 913 | ||
893 | if (!battery) | 914 | if (!battery) |
894 | return; | 915 | return; |
895 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
896 | old = battery->bat.dev; | 916 | old = battery->bat.dev; |
897 | #endif | ||
898 | acpi_battery_update(battery); | 917 | acpi_battery_update(battery); |
899 | acpi_bus_generate_proc_event(device, event, | 918 | acpi_bus_generate_proc_event(device, event, |
900 | acpi_battery_present(battery)); | 919 | acpi_battery_present(battery)); |
901 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 920 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
902 | dev_name(&device->dev), event, | 921 | dev_name(&device->dev), event, |
903 | acpi_battery_present(battery)); | 922 | acpi_battery_present(battery)); |
904 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
905 | /* acpi_battery_update could remove power_supply object */ | 923 | /* acpi_battery_update could remove power_supply object */ |
906 | if (old && battery->bat.dev) | 924 | if (old && battery->bat.dev) |
907 | power_supply_changed(&battery->bat); | 925 | power_supply_changed(&battery->bat); |
908 | #endif | ||
909 | } | 926 | } |
910 | 927 | ||
911 | static int acpi_battery_add(struct acpi_device *device) | 928 | static int acpi_battery_add(struct acpi_device *device) |
@@ -953,9 +970,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type) | |||
953 | #ifdef CONFIG_ACPI_PROCFS_POWER | 970 | #ifdef CONFIG_ACPI_PROCFS_POWER |
954 | acpi_battery_remove_fs(device); | 971 | acpi_battery_remove_fs(device); |
955 | #endif | 972 | #endif |
956 | #ifdef CONFIG_ACPI_SYSFS_POWER | ||
957 | sysfs_remove_battery(battery); | 973 | sysfs_remove_battery(battery); |
958 | #endif | ||
959 | mutex_destroy(&battery->lock); | 974 | mutex_destroy(&battery->lock); |
960 | kfree(battery); | 975 | kfree(battery); |
961 | return 0; | 976 | return 0; |