:p
atchew
Login
This patch series fixes some issues around the battery hook handling inside the ACPI battery driver and the dell-laptop driver. The first patch simplifies the locking during battery hook removal as a preparation for the second patch which fixes a possible crash when unregistering a battery hook. The third patch allows the dell-laptop driver to handle systems with multiple batteries. All patches where tested on a Dell Inspiron 3505 and appear to work. Chnages since v2: - drop boolean flag and use list head instead in patch 2 - drop mjg59@srcf.ucam.org from the CC list since the underlying adress seems to trigger random errors in proccessing (help?) Changes since v1: - fix the underlying issue inside the ACPI battery driver - reword patch for dell-laptop Armin Wolf (3): ACPI: battery: Simplify battery hook locking ACPI: battery: Fix possible crash when unregistering a battery hook platform/x86: dell-laptop: Do not fail when encountering unsupported batteries drivers/acpi/battery.c | 28 +++++++++++++++---------- drivers/platform/x86/dell/dell-laptop.c | 15 ++++++++++--- 2 files changed, 29 insertions(+), 14 deletions(-) -- 2.39.5
Move the conditional locking from __battery_hook_unregister() into battery_hook_unregister() and rename the low-level function to simplify the locking during battery hook removal. Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Reviewed-by: Rafael J. Wysocki <rafael@kernel.org> Reviewed-by: Pali Rohár <pali@kernel.org> Signed-off-by: Armin Wolf <W_Armin@gmx.de> --- drivers/acpi/battery.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -XXX,XX +XXX,XX @@ static LIST_HEAD(acpi_battery_list); static LIST_HEAD(battery_hook_list); static DEFINE_MUTEX(hook_mutex); -static void __battery_hook_unregister(struct acpi_battery_hook *hook, int lock) +static void battery_hook_unregister_unlocked(struct acpi_battery_hook *hook) { struct acpi_battery *battery; + /* * In order to remove a hook, we first need to * de-register all the batteries that are registered. */ - if (lock) - mutex_lock(&hook_mutex); list_for_each_entry(battery, &acpi_battery_list, list) { if (!hook->remove_battery(battery->bat, hook)) power_supply_changed(battery->bat); } list_del(&hook->list); - if (lock) - mutex_unlock(&hook_mutex); + pr_info("extension unregistered: %s\n", hook->name); } void battery_hook_unregister(struct acpi_battery_hook *hook) { - __battery_hook_unregister(hook, 1); + mutex_lock(&hook_mutex); + battery_hook_unregister_unlocked(hook); + mutex_unlock(&hook_mutex); } EXPORT_SYMBOL_GPL(battery_hook_unregister); @@ -XXX,XX +XXX,XX @@ void battery_hook_register(struct acpi_battery_hook *hook) * hooks. */ pr_err("extension failed to load: %s", hook->name); - __battery_hook_unregister(hook, 0); + battery_hook_unregister_unlocked(hook); goto end; } @@ -XXX,XX +XXX,XX @@ static void battery_hook_add_battery(struct acpi_battery *battery) */ pr_err("error in extension, unloading: %s", hook_node->name); - __battery_hook_unregister(hook_node, 0); + battery_hook_unregister_unlocked(hook_node); } } mutex_unlock(&hook_mutex); @@ -XXX,XX +XXX,XX @@ static void __exit battery_hook_exit(void) * need to remove the hooks. */ list_for_each_entry_safe(hook, ptr, &battery_hook_list, list) { - __battery_hook_unregister(hook, 1); + battery_hook_unregister(hook); } mutex_destroy(&hook_mutex); } -- 2.39.5
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 the list head to mark already unregistered battery hooks as already being unregistered 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 | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -XXX,XX +XXX,XX @@ static void battery_hook_unregister_unlocked(struct acpi_battery_hook *hook) if (!hook->remove_battery(battery->bat, hook)) power_supply_changed(battery->bat); } - list_del(&hook->list); + list_del_init(&hook->list); pr_info("extension unregistered: %s\n", hook->name); } @@ -XXX,XX +XXX,XX @@ 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 (!list_empty(&hook->list)) + battery_hook_unregister_unlocked(hook); + mutex_unlock(&hook_mutex); } EXPORT_SYMBOL_GPL(battery_hook_unregister); @@ -XXX,XX +XXX,XX @@ void battery_hook_register(struct acpi_battery_hook *hook) struct acpi_battery *battery; mutex_lock(&hook_mutex); - INIT_LIST_HEAD(&hook->list); list_add(&hook->list, &battery_hook_list); /* * Now that the driver is registered, we need -- 2.39.5
If the battery hook encounters a unsupported battery, it will return an error. This in turn will cause the battery driver to automatically unregister the battery hook. On machines with multiple batteries however, this will prevent the battery hook from handling the primary battery, since it will always get unregistered upon encountering one of the unsupported batteries. Fix this by simply ignoring unsupported batteries. Reviewed-by: Pali Rohár <pali@kernel.org> Fixes: ab58016c68cc ("platform/x86:dell-laptop: Add knobs to change battery charge settings") Signed-off-by: Armin Wolf <W_Armin@gmx.de> --- drivers/platform/x86/dell/dell-laptop.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c index XXXXXXX..XXXXXXX 100644 --- a/drivers/platform/x86/dell/dell-laptop.c +++ b/drivers/platform/x86/dell/dell-laptop.c @@ -XXX,XX +XXX,XX @@ static struct attribute *dell_battery_attrs[] = { }; ATTRIBUTE_GROUPS(dell_battery); +static bool dell_battery_supported(struct power_supply *battery) +{ + /* We currently only support the primary battery */ + return strcmp(battery->desc->name, "BAT0") == 0; +} + static int dell_battery_add(struct power_supply *battery, struct acpi_battery_hook *hook) { - /* this currently only supports the primary battery */ - if (strcmp(battery->desc->name, "BAT0") != 0) - return -ENODEV; + /* Return 0 instead of an error to avoid being unloaded */ + if (!dell_battery_supported(battery)) + return 0; return device_add_groups(&battery->dev, dell_battery_groups); } @@ -XXX,XX +XXX,XX @@ static int dell_battery_add(struct power_supply *battery, static int dell_battery_remove(struct power_supply *battery, struct acpi_battery_hook *hook) { + if (!dell_battery_supported(battery)) + return 0; + device_remove_groups(&battery->dev, dell_battery_groups); return 0; } -- 2.39.5
This patch series fixes some issues around the battery hook handling inside the ACPI battery driver and the dell-laptop driver. The first patch simplifies the locking during battery hook removal as a preparation for the second patch which fixes a possible crash when unregistering a battery hook. The third patch allows the dell-laptop driver to handle systems with multiple batteries. All patches where tested on a Dell Inspiron 3505 and appear to work. Changes since v2: - drop boolean flag and use list head instead in patch 2 Changes since v1: - fix the underlying issue inside the ACPI battery driver - reword patch for dell-laptop Armin Wolf (3): ACPI: battery: Simplify battery hook locking ACPI: battery: Fix possible crash when unregistering a battery hook platform/x86: dell-laptop: Do not fail when encountering unsupported batteries drivers/acpi/battery.c | 28 +++++++++++++++---------- drivers/platform/x86/dell/dell-laptop.c | 15 ++++++++++--- 2 files changed, 29 insertions(+), 14 deletions(-) -- 2.39.5