diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-03 03:17:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-03 03:17:02 -0400 |
commit | c299eba3c5a801657f275d33be588b34831cd30e (patch) | |
tree | 022a2a72604443fa8ce8d3fd040fbda49b04f681 /drivers/acpi/battery.c | |
parent | 1850536b93888e6cc3ee42e63e20e61f35f8b3e2 (diff) | |
parent | 4a8f5058bde15d737abe39b5bed3f21dcb6599d2 (diff) |
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (28 commits)
ACPI: delete stale reference in kernel-parameters.txt
ACPI: add missing _OSI strings
ACPI: remove NID_INVAL
thermal: make THERMAL_HWMON implementation fully internal
thermal: split hwmon lookup to a separate function
thermal: hide CONFIG_THERMAL_HWMON
ACPI print OSI(Linux) warning only once
ACPI: DMI workaround for Asus A8N-SLI Premium and Asus A8N-SLI DELUX
ACPI / Battery: propagate sysfs error in acpi_battery_add()
ACPI / Battery: avoid acpi_battery_add() use-after-free
ACPI: introduce "acpi_rsdp=" parameter for kdump
ACPI: constify ops structs
ACPI: fix CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS
ACPI: fix 80 char overflow
ACPI / Battery: Resolve the race condition in the sysfs_remove_battery()
ACPI / Battery: Add the check before refresh sysfs in the battery_notify()
ACPI / Battery: Add the hibernation process in the battery_notify()
ACPI / Battery: Rename acpi_battery_quirks2 with acpi_battery_quirks
ACPI / Battery: Change 16-bit signed negative battery current into correct value
ACPI / Battery: Add the power unit macro
...
Diffstat (limited to 'drivers/acpi/battery.c')
-rw-r--r-- | drivers/acpi/battery.c | 82 |
1 files changed, 50 insertions, 32 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 2c661353e8f2..87c0a8daa99a 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
@@ -55,6 +55,9 @@ | |||
55 | #define ACPI_BATTERY_NOTIFY_INFO 0x81 | 55 | #define ACPI_BATTERY_NOTIFY_INFO 0x81 |
56 | #define ACPI_BATTERY_NOTIFY_THRESHOLD 0x82 | 56 | #define ACPI_BATTERY_NOTIFY_THRESHOLD 0x82 |
57 | 57 | ||
58 | /* Battery power unit: 0 means mW, 1 means mA */ | ||
59 | #define ACPI_BATTERY_POWER_UNIT_MA 1 | ||
60 | |||
58 | #define _COMPONENT ACPI_BATTERY_COMPONENT | 61 | #define _COMPONENT ACPI_BATTERY_COMPONENT |
59 | 62 | ||
60 | ACPI_MODULE_NAME("battery"); | 63 | ACPI_MODULE_NAME("battery"); |
@@ -91,11 +94,6 @@ MODULE_DEVICE_TABLE(acpi, battery_device_ids); | |||
91 | enum { | 94 | enum { |
92 | ACPI_BATTERY_ALARM_PRESENT, | 95 | ACPI_BATTERY_ALARM_PRESENT, |
93 | ACPI_BATTERY_XINFO_PRESENT, | 96 | ACPI_BATTERY_XINFO_PRESENT, |
94 | /* For buggy DSDTs that report negative 16-bit values for either | ||
95 | * charging or discharging current and/or report 0 as 65536 | ||
96 | * due to bad math. | ||
97 | */ | ||
98 | ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, | ||
99 | ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, | 97 | ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, |
100 | }; | 98 | }; |
101 | 99 | ||
@@ -301,7 +299,8 @@ static enum power_supply_property energy_battery_props[] = { | |||
301 | #ifdef CONFIG_ACPI_PROCFS_POWER | 299 | #ifdef CONFIG_ACPI_PROCFS_POWER |
302 | inline char *acpi_battery_units(struct acpi_battery *battery) | 300 | inline char *acpi_battery_units(struct acpi_battery *battery) |
303 | { | 301 | { |
304 | return (battery->power_unit)?"mA":"mW"; | 302 | return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ? |
303 | "mA" : "mW"; | ||
305 | } | 304 | } |
306 | #endif | 305 | #endif |
307 | 306 | ||
@@ -461,9 +460,17 @@ static int acpi_battery_get_state(struct acpi_battery *battery) | |||
461 | battery->update_time = jiffies; | 460 | battery->update_time = jiffies; |
462 | kfree(buffer.pointer); | 461 | kfree(buffer.pointer); |
463 | 462 | ||
464 | if (test_bit(ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, &battery->flags) && | 463 | /* For buggy DSDTs that report negative 16-bit values for either |
465 | battery->rate_now != -1) | 464 | * charging or discharging current and/or report 0 as 65536 |
465 | * due to bad math. | ||
466 | */ | ||
467 | if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA && | ||
468 | battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN && | ||
469 | (s16)(battery->rate_now) < 0) { | ||
466 | battery->rate_now = abs((s16)battery->rate_now); | 470 | battery->rate_now = abs((s16)battery->rate_now); |
471 | printk_once(KERN_WARNING FW_BUG "battery: (dis)charge rate" | ||
472 | " invalid.\n"); | ||
473 | } | ||
467 | 474 | ||
468 | if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags) | 475 | if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags) |
469 | && battery->capacity_now >= 0 && battery->capacity_now <= 100) | 476 | && battery->capacity_now >= 0 && battery->capacity_now <= 100) |
@@ -544,7 +551,7 @@ static int sysfs_add_battery(struct acpi_battery *battery) | |||
544 | { | 551 | { |
545 | int result; | 552 | int result; |
546 | 553 | ||
547 | if (battery->power_unit) { | 554 | if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) { |
548 | battery->bat.properties = charge_battery_props; | 555 | battery->bat.properties = charge_battery_props; |
549 | battery->bat.num_properties = | 556 | battery->bat.num_properties = |
550 | ARRAY_SIZE(charge_battery_props); | 557 | ARRAY_SIZE(charge_battery_props); |
@@ -566,18 +573,16 @@ static int sysfs_add_battery(struct acpi_battery *battery) | |||
566 | 573 | ||
567 | static void sysfs_remove_battery(struct acpi_battery *battery) | 574 | static void sysfs_remove_battery(struct acpi_battery *battery) |
568 | { | 575 | { |
569 | if (!battery->bat.dev) | 576 | mutex_lock(&battery->lock); |
577 | if (!battery->bat.dev) { | ||
578 | mutex_unlock(&battery->lock); | ||
570 | return; | 579 | return; |
580 | } | ||
581 | |||
571 | device_remove_file(battery->bat.dev, &alarm_attr); | 582 | device_remove_file(battery->bat.dev, &alarm_attr); |
572 | power_supply_unregister(&battery->bat); | 583 | power_supply_unregister(&battery->bat); |
573 | battery->bat.dev = NULL; | 584 | battery->bat.dev = NULL; |
574 | } | 585 | mutex_unlock(&battery->lock); |
575 | |||
576 | static void acpi_battery_quirks(struct acpi_battery *battery) | ||
577 | { | ||
578 | if (dmi_name_in_vendors("Acer") && battery->power_unit) { | ||
579 | set_bit(ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, &battery->flags); | ||
580 | } | ||
581 | } | 586 | } |
582 | 587 | ||
583 | /* | 588 | /* |
@@ -592,7 +597,7 @@ static void acpi_battery_quirks(struct acpi_battery *battery) | |||
592 | * | 597 | * |
593 | * Handle this correctly so that they won't break userspace. | 598 | * Handle this correctly so that they won't break userspace. |
594 | */ | 599 | */ |
595 | static void acpi_battery_quirks2(struct acpi_battery *battery) | 600 | static void acpi_battery_quirks(struct acpi_battery *battery) |
596 | { | 601 | { |
597 | if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) | 602 | if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) |
598 | return ; | 603 | return ; |
@@ -623,13 +628,15 @@ static int acpi_battery_update(struct acpi_battery *battery) | |||
623 | result = acpi_battery_get_info(battery); | 628 | result = acpi_battery_get_info(battery); |
624 | if (result) | 629 | if (result) |
625 | return result; | 630 | return result; |
626 | acpi_battery_quirks(battery); | ||
627 | acpi_battery_init_alarm(battery); | 631 | acpi_battery_init_alarm(battery); |
628 | } | 632 | } |
629 | if (!battery->bat.dev) | 633 | if (!battery->bat.dev) { |
630 | sysfs_add_battery(battery); | 634 | result = sysfs_add_battery(battery); |
635 | if (result) | ||
636 | return result; | ||
637 | } | ||
631 | result = acpi_battery_get_state(battery); | 638 | result = acpi_battery_get_state(battery); |
632 | acpi_battery_quirks2(battery); | 639 | acpi_battery_quirks(battery); |
633 | return result; | 640 | return result; |
634 | } | 641 | } |
635 | 642 | ||
@@ -863,7 +870,7 @@ DECLARE_FILE_FUNCTIONS(alarm); | |||
863 | }, \ | 870 | }, \ |
864 | } | 871 | } |
865 | 872 | ||
866 | static struct battery_file { | 873 | static const struct battery_file { |
867 | struct file_operations ops; | 874 | struct file_operations ops; |
868 | mode_t mode; | 875 | mode_t mode; |
869 | const char *name; | 876 | const char *name; |
@@ -948,9 +955,12 @@ static int battery_notify(struct notifier_block *nb, | |||
948 | struct acpi_battery *battery = container_of(nb, struct acpi_battery, | 955 | struct acpi_battery *battery = container_of(nb, struct acpi_battery, |
949 | pm_nb); | 956 | pm_nb); |
950 | switch (mode) { | 957 | switch (mode) { |
958 | case PM_POST_HIBERNATION: | ||
951 | case PM_POST_SUSPEND: | 959 | case PM_POST_SUSPEND: |
952 | sysfs_remove_battery(battery); | 960 | if (battery->bat.dev) { |
953 | sysfs_add_battery(battery); | 961 | sysfs_remove_battery(battery); |
962 | sysfs_add_battery(battery); | ||
963 | } | ||
954 | break; | 964 | break; |
955 | } | 965 | } |
956 | 966 | ||
@@ -975,25 +985,33 @@ static int acpi_battery_add(struct acpi_device *device) | |||
975 | if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle, | 985 | if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle, |
976 | "_BIX", &handle))) | 986 | "_BIX", &handle))) |
977 | set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags); | 987 | set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags); |
978 | acpi_battery_update(battery); | 988 | result = acpi_battery_update(battery); |
989 | if (result) | ||
990 | goto fail; | ||
979 | #ifdef CONFIG_ACPI_PROCFS_POWER | 991 | #ifdef CONFIG_ACPI_PROCFS_POWER |
980 | result = acpi_battery_add_fs(device); | 992 | result = acpi_battery_add_fs(device); |
981 | #endif | 993 | #endif |
982 | if (!result) { | 994 | if (result) { |
983 | printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", | ||
984 | ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), | ||
985 | device->status.battery_present ? "present" : "absent"); | ||
986 | } else { | ||
987 | #ifdef CONFIG_ACPI_PROCFS_POWER | 995 | #ifdef CONFIG_ACPI_PROCFS_POWER |
988 | acpi_battery_remove_fs(device); | 996 | acpi_battery_remove_fs(device); |
989 | #endif | 997 | #endif |
990 | kfree(battery); | 998 | goto fail; |
991 | } | 999 | } |
992 | 1000 | ||
1001 | printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", | ||
1002 | ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), | ||
1003 | device->status.battery_present ? "present" : "absent"); | ||
1004 | |||
993 | battery->pm_nb.notifier_call = battery_notify; | 1005 | battery->pm_nb.notifier_call = battery_notify; |
994 | register_pm_notifier(&battery->pm_nb); | 1006 | register_pm_notifier(&battery->pm_nb); |
995 | 1007 | ||
996 | return result; | 1008 | return result; |
1009 | |||
1010 | fail: | ||
1011 | sysfs_remove_battery(battery); | ||
1012 | mutex_destroy(&battery->lock); | ||
1013 | kfree(battery); | ||
1014 | return result; | ||
997 | } | 1015 | } |
998 | 1016 | ||
999 | static int acpi_battery_remove(struct acpi_device *device, int type) | 1017 | static int acpi_battery_remove(struct acpi_device *device, int type) |