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

From: Armin Wolf

Date: Tue Sep 01 2026 - 16:18:34 EST


Am 01.09.26 um 22:16 schrieb Rafael J. Wysocki (Intel):

On Tue, Sep 1, 2026 at 10:11 PM Armin Wolf <W_Armin@xxxxxx> wrote:
Am 07.08.26 um 01:38 schrieb Armin Wolf:

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.
Any thoughts on this? I tested it on my device, and so far everything seems
to work flawlessly.
It looks good overall, but it is quite substantial, which is why it
didn't make it into 7.3-rc1.

I'm planning to apply it for 7.4.

Alright, that works for me.

Thanks,
Armin Wolf

Signed-off-by: Armin Wolf <W_Armin@xxxxxx>
---
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);
+ }
}
}