[PATCH] ACPI: battery: Fix bogus cycle count values on systems without _BIX

Armin Wolf <[email protected]>
Newsgroups org.kernel.vger.linux-acpi,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Devices supporting only the legacy _BIF ACPI control method cannot
know the cycle count of the associated battery, so cycle_count always
remains 0. Claiming support for POWER_SUPPLY_PROP_CYCLE_COUNT on
such devices can thus mislead userspace applications and prevents
power supply extensions from supplying correct cycle count values.

Fix this by not claiming support for POWER_SUPPLY_PROP_CYCLE_COUNT
on devices without _BIX.

Signed-off-by: Armin Wolf <[email protected]>
---
 drivers/acpi/battery.c | 131 +++++++++++++++++++++++++++++++++++------
 1 file changed, 113 insertions(+), 18 deletions(-)

diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 0084f308b790..b64f876f93cb 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -324,7 +324,9 @@ static int acpi_battery_get_property(struct power_supply *psy,
 	return ret;
 }
 
-static const enum power_supply_property charge_battery_props[] = {
+/* For devices supporting the _BIX ACPI control method */
+
+static const enum power_supply_property charge_battery_extended_props[] = {
 	POWER_SUPPLY_PROP_STATUS,
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_TECHNOLOGY,
@@ -342,7 +344,7 @@ static const enum power_supply_property charge_battery_props[] = {
 	POWER_SUPPLY_PROP_SERIAL_NUMBER,
 };
 
-static const enum power_supply_property charge_battery_full_cap_broken_props[] = {
+static const enum power_supply_property charge_battery_full_cap_broken_extended_props[] = {
 	POWER_SUPPLY_PROP_STATUS,
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_TECHNOLOGY,
@@ -356,7 +358,7 @@ static const enum power_supply_property charge_battery_full_cap_broken_props[] =
 	POWER_SUPPLY_PROP_SERIAL_NUMBER,
 };
 
-static const enum power_supply_property energy_battery_props[] = {
+static const enum power_supply_property energy_battery_extended_props[] = {
 	POWER_SUPPLY_PROP_STATUS,
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_TECHNOLOGY,
@@ -374,7 +376,7 @@ static const enum power_supply_property energy_battery_props[] = {
 	POWER_SUPPLY_PROP_SERIAL_NUMBER,
 };
 
-static const enum power_supply_property energy_battery_full_cap_broken_props[] = {
+static const enum power_supply_property energy_battery_full_cap_broken_extended_props[] = {
 	POWER_SUPPLY_PROP_STATUS,
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_TECHNOLOGY,
@@ -388,6 +390,68 @@ static const enum power_supply_property energy_battery_full_cap_broken_props[] =
 	POWER_SUPPLY_PROP_SERIAL_NUMBER,
 };
 
+/* For devices supporting only the _BIF ACPI control method */
+
+static const enum power_supply_property charge_battery_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
+	POWER_SUPPLY_PROP_CAPACITY,
+	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+	POWER_SUPPLY_PROP_MODEL_NAME,
+	POWER_SUPPLY_PROP_MANUFACTURER,
+	POWER_SUPPLY_PROP_SERIAL_NUMBER,
+};
+
+static const enum power_supply_property charge_battery_full_cap_broken_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
+	POWER_SUPPLY_PROP_MODEL_NAME,
+	POWER_SUPPLY_PROP_MANUFACTURER,
+	POWER_SUPPLY_PROP_SERIAL_NUMBER,
+};
+
+static const enum power_supply_property energy_battery_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_POWER_NOW,
+	POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
+	POWER_SUPPLY_PROP_ENERGY_FULL,
+	POWER_SUPPLY_PROP_ENERGY_NOW,
+	POWER_SUPPLY_PROP_CAPACITY,
+	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+	POWER_SUPPLY_PROP_MODEL_NAME,
+	POWER_SUPPLY_PROP_MANUFACTURER,
+	POWER_SUPPLY_PROP_SERIAL_NUMBER,
+};
+
+static const enum power_supply_property energy_battery_full_cap_broken_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_POWER_NOW,
+	POWER_SUPPLY_PROP_ENERGY_NOW,
+	POWER_SUPPLY_PROP_MODEL_NAME,
+	POWER_SUPPLY_PROP_MANUFACTURER,
+	POWER_SUPPLY_PROP_SERIAL_NUMBER,
+};
+
 /* Battery Management */
 struct acpi_offsets {
 	size_t offset;		/* offset inside struct acpi_sbs_battery */
@@ -875,6 +939,7 @@ static void __exit battery_hook_exit(void)
 
 static int sysfs_add_battery(struct acpi_battery *battery)
 {
+	bool extended_info_available = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
 	struct power_supply_config psy_cfg = {
 		.drv_data = battery,
 		.attr_grp = acpi_battery_groups,
@@ -888,25 +953,55 @@ static int sysfs_add_battery(struct acpi_battery *battery)
 
 	if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
 		if (full_cap_broken) {
-			battery->bat_desc.properties =
-			    charge_battery_full_cap_broken_props;
-			battery->bat_desc.num_properties =
-			    ARRAY_SIZE(charge_battery_full_cap_broken_props);
+			if (extended_info_available) {
+				battery->bat_desc.properties =
+					charge_battery_full_cap_broken_extended_props;
+				battery->bat_desc.num_properties =
+					ARRAY_SIZE(charge_battery_full_cap_broken_extended_props);
+			} else {
+				battery->bat_desc.properties =
+					charge_battery_full_cap_broken_props;
+				battery->bat_desc.num_properties =
+					ARRAY_SIZE(charge_battery_full_cap_broken_props);
+			}
 		} else {
-			battery->bat_desc.properties = charge_battery_props;
-			battery->bat_desc.num_properties =
-			    ARRAY_SIZE(charge_battery_props);
+			if (extended_info_available) {
+				battery->bat_desc.properties =
+					charge_battery_extended_props;
+				battery->bat_desc.num_properties =
+					ARRAY_SIZE(charge_battery_extended_props);
+			} else {
+				battery->bat_desc.properties =
+					charge_battery_props;
+				battery->bat_desc.num_properties =
+					ARRAY_SIZE(charge_battery_props);
+			}
 		}
 	} else {
 		if (full_cap_broken) {
-			battery->bat_desc.properties =
-			    energy_battery_full_cap_broken_props;
-			battery->bat_desc.num_properties =
-			    ARRAY_SIZE(energy_battery_full_cap_broken_props);
+			if (extended_info_available) {
+				battery->bat_desc.properties =
+					energy_battery_full_cap_broken_extended_props;
+				battery->bat_desc.num_properties =
+					ARRAY_SIZE(energy_battery_full_cap_broken_extended_props);
+			} else {
+				battery->bat_desc.properties =
+					energy_battery_full_cap_broken_props;
+				battery->bat_desc.num_properties =
+					ARRAY_SIZE(energy_battery_full_cap_broken_props);
+			}
 		} else {
-			battery->bat_desc.properties = energy_battery_props;
-			battery->bat_desc.num_properties =
-			    ARRAY_SIZE(energy_battery_props);
+			if (extended_info_available) {
+				battery->bat_desc.properties =
+					energy_battery_extended_props;
+				battery->bat_desc.num_properties =
+					ARRAY_SIZE(energy_battery_extended_props);
+			} else {
+				battery->bat_desc.properties =
+					energy_battery_props;
+				battery->bat_desc.num_properties =
+					ARRAY_SIZE(energy_battery_props);
+			}
 		}
 	}
 
-- 
2.39.5
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.