@@ -719,6 +719,7 @@ static void battery_hook_unregister_unlocked(struct acpi_battery_hook *hook)
power_supply_changed(battery->bat);
}
list_del(&hook->list);
+ hook->dead = true;
pr_info("extension unregistered: %s\n", hook->name);
}
@@ -726,7 +727,14 @@ static void battery_hook_unregister_unlocked(struct acpi_battery_hook *hook)
void battery_hook_unregister(struct acpi_battery_hook *hook)
{
mutex_lock(&hook_mutex);
- battery_hook_unregister_unlocked(hook);
+ /*
+ * Ignore already unregistered battery hooks. This might happen
+ * if a battery hook was previously unloaded due to an error when
+ * adding a new battery.
+ */
+ if (!hook->dead)
+ battery_hook_unregister_unlocked(hook);
+
mutex_unlock(&hook_mutex);
}
EXPORT_SYMBOL_GPL(battery_hook_unregister);
@@ -737,6 +745,7 @@ void battery_hook_register(struct acpi_battery_hook *hook)
mutex_lock(&hook_mutex);
INIT_LIST_HEAD(&hook->list);
+ hook->dead = false;
list_add(&hook->list, &battery_hook_list);
/*
* Now that the driver is registered, we need
@@ -16,6 +16,7 @@ struct acpi_battery_hook {
int (*add_battery)(struct power_supply *battery, struct acpi_battery_hook *hook);
int (*remove_battery)(struct power_supply *battery, struct acpi_battery_hook *hook);
struct list_head list;
+ bool dead;
};
void battery_hook_register(struct acpi_battery_hook *hook);
When a battery hook returns an error when adding a new battery, then the battery hook is automatically unregistered. However the battery hook provider cannot know that, so it will later call battery_hook_unregister() on the already unregistered battery hook, resulting in a crash. Fix this by using a boolean flag to mark already unregistered battery hooks as "dead" so that they can be ignored by battery_hook_unregister(). Fixes: fa93854f7a7e ("battery: Add the battery hooking API") Signed-off-by: Armin Wolf <W_Armin@gmx.de> --- drivers/acpi/battery.c | 11 ++++++++++- include/acpi/battery.h | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) -- 2.39.5