On some systems we have a native PMIC driver which provides battery monitoring, while the ACPI battery driver is broken on these systems due to bad DSTDs or because of missing vendor specific ACPI opregion (e.g. BMOP opregion) support, which the ACPI battery device in the dsdt relies on. This leads to there being 2 battery power_supply-s registed like this: ~$ acpi Battery 0: Charging, 84%, 00:49:39 until charged Battery 1: Unknown, 0%, rate information unavailable Even if the ACPI battery where to function fine (which on systems where we have a native PMIC driver it often doesn't) we still do not want to export the same battery to userspace twice. This commit adds an acpi_battery_unregister() function which native PMIC drivers can call to tell the ACPI-battery driver to unregister itself so that we do not end up with 2 power_supply-s for the same battery device. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=194811 Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx> Tested-by: Sergei Trusov <t.rus76@xxxxx> --- Changes in v2: -Fix capitalization in commit msg -Minor style cleanups --- drivers/acpi/battery.c | 33 ++++++++++++++++++++++++++++++++- include/linux/power/acpi.h | 18 ++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 include/linux/power/acpi.h diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 4ef1e46..b26a2b7 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -29,6 +29,7 @@ #include <linux/async.h> #include <linux/dmi.h> #include <linux/delay.h> +#include <linux/mutex.h> #include <linux/slab.h> #include <linux/suspend.h> #include <asm/unaligned.h> @@ -40,6 +41,7 @@ #endif #include <linux/acpi.h> +#include <linux/power/acpi.h> #include <linux/power_supply.h> #include "battery.h" @@ -66,6 +68,10 @@ MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@xxxxxxx>"); MODULE_DESCRIPTION("ACPI Battery Driver"); MODULE_LICENSE("GPL"); +enum init_state_enum { BAT_NONE, BAT_INITIALIZED, BAT_EXITED }; + +static enum init_state_enum init_state; +static DEFINE_MUTEX(init_state_mutex); static async_cookie_t async_cookie; static int battery_bix_broken_package; static int battery_notification_delay_ms; @@ -1336,17 +1342,42 @@ static int __init acpi_battery_init(void) if (acpi_disabled) return -ENODEV; + /* Check if acpi_battery_unregister() got called before _init() */ + mutex_lock(&init_state_mutex); + if (init_state != BAT_NONE) + goto out_unlock; + async_cookie = async_schedule(acpi_battery_init_async, NULL); + init_state = BAT_INITIALIZED; + +out_unlock: + mutex_unlock(&init_state_mutex); + return 0; } -static void __exit acpi_battery_exit(void) +void acpi_battery_unregister(void) { + /* Check if _init() is done and only do unregister once */ + mutex_lock(&init_state_mutex); + if (init_state != BAT_INITIALIZED) + goto out_exit; + async_synchronize_cookie(async_cookie + 1); acpi_bus_unregister_driver(&acpi_battery_driver); #ifdef CONFIG_ACPI_PROCFS_POWER acpi_unlock_battery_dir(acpi_battery_dir); #endif + +out_exit: + init_state = BAT_EXITED; + mutex_unlock(&init_state_mutex); +} +EXPORT_SYMBOL_GPL(acpi_battery_unregister); + +static void __exit acpi_battery_exit(void) +{ + acpi_battery_unregister(); } module_init(acpi_battery_init); diff --git a/include/linux/power/acpi.h b/include/linux/power/acpi.h new file mode 100644 index 0000000..83bdfb9 --- /dev/null +++ b/include/linux/power/acpi.h @@ -0,0 +1,18 @@ +/* + * Functions exported by the acpi power_supply drivers + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __LINUX_POWER_ACPI_H_ +#define __LINUX_POWER_ACPI_H_ + +#if IS_ENABLED(CONFIG_ACPI_BATTERY) +void acpi_battery_unregister(void); +#else +static inline void acpi_battery_unregister(void) {} +#endif + +#endif -- 2.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html