aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouke Witteveen <j.witteveen@gmail.com>2018-07-04 12:27:15 +0200
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2018-07-04 12:36:29 +0200
commit673b4271665a12fa839a12abb50e6f6e9953c081 (patch)
tree2ca1fcd964c3a1b8038840b4a009d5178ba36e9c
parent021c91791a5e7e85c567452f1be3e4c2c6cb6063 (diff)
downloadlinux-lora-673b4271665a12fa839a12abb50e6f6e9953c081.tar.gz
ACPI / battery: Safe unregistering of hooks
A hooking API was implemented for 4.17 in fa93854f7a7ed63d followed by hooks for Thinkpad laptops in 2801b9683f740012. 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: fa93854f7a7e (battery: Add the battery hooking API) Cc: 4.17+ <stable@vger.kernel.org> # 4.17+ Signed-off-by: Jouke Witteveen <j.witteveen@gmail.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/acpi/battery.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index b0113a5802a3c..d79ad844c78fc 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -717,10 +717,11 @@ void battery_hook_register(struct acpi_battery_hook *hook)
*/
pr_err("extension failed to load: %s", hook->name);
__battery_hook_unregister(hook, 0);
- return;
+ goto end;
}
}
pr_info("new extension: %s\n", hook->name);
+end:
mutex_unlock(&hook_mutex);
}
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)
{
- struct acpi_battery_hook *hook_node;
+ struct acpi_battery_hook *hook_node, *tmp;
mutex_lock(&hook_mutex);
INIT_LIST_HEAD(&battery->list);
@@ -744,15 +745,15 @@ static void battery_hook_add_battery(struct acpi_battery *battery)
* when a battery gets hotplugged or initialized
* 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)) {
/*
* The notification of the extensions has failed, to
* prevent further errors we will unload the extension.
*/
- __battery_hook_unregister(hook_node, 0);
pr_err("error in extension, unloading: %s",
hook_node->name);
+ __battery_hook_unregister(hook_node, 0);
}
}
mutex_unlock(&hook_mutex);