aboutsummaryrefslogtreecommitdiff
path: root/drivers/acpi/battery.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/battery.c')
-rw-r--r--drivers/acpi/battery.c51
1 files changed, 32 insertions, 19 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 306513fec1e1..9c67ed02d797 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -42,6 +42,8 @@
#define ACPI_BATTERY_STATE_CHARGING 0x2
#define ACPI_BATTERY_STATE_CRITICAL 0x4
+#define MAX_STRING_LENGTH 64
+
MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_AUTHOR("Alexey Starikovskiy <[email protected]>");
MODULE_DESCRIPTION("ACPI Battery Driver");
@@ -118,10 +120,10 @@ struct acpi_battery {
int capacity_granularity_1;
int capacity_granularity_2;
int alarm;
- char model_number[32];
- char serial_number[32];
- char type[32];
- char oem_info[32];
+ char model_number[MAX_STRING_LENGTH];
+ char serial_number[MAX_STRING_LENGTH];
+ char type[MAX_STRING_LENGTH];
+ char oem_info[MAX_STRING_LENGTH];
int state;
int power_unit;
unsigned long flags;
@@ -437,16 +439,25 @@ static int extract_package(struct acpi_battery *battery,
element = &package->package.elements[i];
if (offsets[i].mode) {
u8 *ptr = (u8 *)battery + offsets[i].offset;
+ u32 len = MAX_STRING_LENGTH;
+
+ switch (element->type) {
+ case ACPI_TYPE_BUFFER:
+ if (len > element->buffer.length + 1)
+ len = element->buffer.length + 1;
+
+ fallthrough;
+ case ACPI_TYPE_STRING:
+ strscpy(ptr, element->string.pointer, len);
- if (element->type == ACPI_TYPE_STRING ||
- element->type == ACPI_TYPE_BUFFER)
- strncpy(ptr, element->string.pointer, 32);
- else if (element->type == ACPI_TYPE_INTEGER) {
- strncpy(ptr, (u8 *)&element->integer.value,
- sizeof(u64));
- ptr[sizeof(u64)] = 0;
- } else
+ break;
+ case ACPI_TYPE_INTEGER:
+ strscpy(ptr, (u8 *)&element->integer.value, sizeof(u64) + 1);
+
+ break;
+ default:
*ptr = 0; /* don't have value */
+ }
} else {
int *x = (int *)((u8 *)battery + offsets[i].offset);
*x = (element->type == ACPI_TYPE_INTEGER) ?
@@ -696,7 +707,8 @@ static void __battery_hook_unregister(struct acpi_battery_hook *hook, int lock)
if (lock)
mutex_lock(&hook_mutex);
list_for_each_entry(battery, &acpi_battery_list, list) {
- hook->remove_battery(battery->bat);
+ if (!hook->remove_battery(battery->bat, hook))
+ power_supply_changed(battery->bat);
}
list_del(&hook->list);
if (lock)
@@ -724,7 +736,7 @@ void battery_hook_register(struct acpi_battery_hook *hook)
* its attributes.
*/
list_for_each_entry(battery, &acpi_battery_list, list) {
- if (hook->add_battery(battery->bat)) {
+ if (hook->add_battery(battery->bat, hook)) {
/*
* If a add-battery returns non-zero,
* the registration of the extension has failed,
@@ -735,6 +747,8 @@ void battery_hook_register(struct acpi_battery_hook *hook)
__battery_hook_unregister(hook, 0);
goto end;
}
+
+ power_supply_changed(battery->bat);
}
pr_info("new extension: %s\n", hook->name);
end:
@@ -762,7 +776,7 @@ static void battery_hook_add_battery(struct acpi_battery *battery)
* during the battery module initialization.
*/
list_for_each_entry_safe(hook_node, tmp, &battery_hook_list, list) {
- if (hook_node->add_battery(battery->bat)) {
+ if (hook_node->add_battery(battery->bat, hook_node)) {
/*
* The notification of the extensions has failed, to
* prevent further errors we will unload the extension.
@@ -785,7 +799,7 @@ static void battery_hook_remove_battery(struct acpi_battery *battery)
* custom attributes from the battery.
*/
list_for_each_entry(hook, &battery_hook_list, list) {
- hook->remove_battery(battery->bat);
+ hook->remove_battery(battery->bat, hook);
}
/* Then, just remove the battery from the list */
list_del(&battery->list);
@@ -1208,12 +1222,12 @@ fail:
return result;
}
-static int acpi_battery_remove(struct acpi_device *device)
+static void acpi_battery_remove(struct acpi_device *device)
{
struct acpi_battery *battery = NULL;
if (!device || !acpi_driver_data(device))
- return -EINVAL;
+ return;
device_init_wakeup(&device->dev, 0);
battery = acpi_driver_data(device);
unregister_pm_notifier(&battery->pm_nb);
@@ -1221,7 +1235,6 @@ static int acpi_battery_remove(struct acpi_device *device)
mutex_destroy(&battery->lock);
mutex_destroy(&battery->sysfs_lock);
kfree(battery);
- return 0;
}
#ifdef CONFIG_PM_SLEEP