Commit 673b4271 authored by Jouke Witteveen's avatar Jouke Witteveen Committed by Rafael J. Wysocki

ACPI / battery: Safe unregistering of hooks

A hooking API was implemented for 4.17 in fa93854f followed
by hooks for Thinkpad laptops in 2801b968. The Thinkpad
drivers did not support the Thinkpad 13 and the hooking API crashes
on unsupported batteries by altering a list of hooks during unsafe
iteration. Thus, Thinkpad 13 laptops could no longer boot.

Additionally, a lock was kept in place and debugging information was
printed out of order.

Fixes: fa93854f (battery: Add the battery hooking API)
Cc: 4.17+ <stable@vger.kernel.org> # 4.17+
Signed-off-by: default avatarJouke Witteveen <j.witteveen@gmail.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 021c9179
...@@ -717,10 +717,11 @@ void battery_hook_register(struct acpi_battery_hook *hook) ...@@ -717,10 +717,11 @@ void battery_hook_register(struct acpi_battery_hook *hook)
*/ */
pr_err("extension failed to load: %s", hook->name); pr_err("extension failed to load: %s", hook->name);
__battery_hook_unregister(hook, 0); __battery_hook_unregister(hook, 0);
return; goto end;
} }
} }
pr_info("new extension: %s\n", hook->name); pr_info("new extension: %s\n", hook->name);
end:
mutex_unlock(&hook_mutex); mutex_unlock(&hook_mutex);
} }
EXPORT_SYMBOL_GPL(battery_hook_register); EXPORT_SYMBOL_GPL(battery_hook_register);
...@@ -732,7 +733,7 @@ EXPORT_SYMBOL_GPL(battery_hook_register); ...@@ -732,7 +733,7 @@ EXPORT_SYMBOL_GPL(battery_hook_register);
*/ */
static void battery_hook_add_battery(struct acpi_battery *battery) static void battery_hook_add_battery(struct acpi_battery *battery)
{ {
struct acpi_battery_hook *hook_node; struct acpi_battery_hook *hook_node, *tmp;
mutex_lock(&hook_mutex); mutex_lock(&hook_mutex);
INIT_LIST_HEAD(&battery->list); INIT_LIST_HEAD(&battery->list);
...@@ -744,15 +745,15 @@ static void battery_hook_add_battery(struct acpi_battery *battery) ...@@ -744,15 +745,15 @@ static void battery_hook_add_battery(struct acpi_battery *battery)
* when a battery gets hotplugged or initialized * when a battery gets hotplugged or initialized
* during the battery module initialization. * during the battery module initialization.
*/ */
list_for_each_entry(hook_node, &battery_hook_list, list) { 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)) {
/* /*
* The notification of the extensions has failed, to * The notification of the extensions has failed, to
* prevent further errors we will unload the extension. * prevent further errors we will unload the extension.
*/ */
__battery_hook_unregister(hook_node, 0);
pr_err("error in extension, unloading: %s", pr_err("error in extension, unloading: %s",
hook_node->name); hook_node->name);
__battery_hook_unregister(hook_node, 0);
} }
} }
mutex_unlock(&hook_mutex); mutex_unlock(&hook_mutex);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment