| From ff3154d1d89a2343fd5f82e65bc0cf1d4e6659b3 Mon Sep 17 00:00:00 2001 |
| From: Hans de Goede <hdegoede@redhat.com> |
| Date: Tue, 10 Dec 2019 10:57:52 +0100 |
| Subject: ACPI / battery: Deal better with neither design nor full capacity not being reported |
| |
| From: Hans de Goede <hdegoede@redhat.com> |
| |
| commit ff3154d1d89a2343fd5f82e65bc0cf1d4e6659b3 upstream. |
| |
| Commit b41901a2cf06 ("ACPI / battery: Do not export energy_full[_design] on |
| devices without full_charge_capacity") added support for some (broken) |
| devices which always report 0 for both design_capacity and |
| full_charge_capacity. |
| |
| Since the device that commit was written as a fix for is not reporting any |
| form of "full" capacity we cannot calculate the value for the |
| POWER_SUPPLY_PROP_CAPACITY, this is worked around by using an alternative |
| array of available properties which does not contain this property. |
| |
| This is necessary because userspace (upower) treats us returning -ENODEV |
| as 0 and then typically will trigger an emergency shutdown because of that. |
| Userspace does not do this if the capacity sysfs attribute is not present |
| at all. |
| |
| There are two potential problems with that commit: |
| 1) It assumes that both full_charge- and design-capacity are broken at the |
| same time and only checks if full_charge- is broken. |
| 2) It assumes that this only ever happens for devices which report energy |
| units rather then charge units. |
| |
| This commit fixes both issues by only using the alternative |
| array of available properties if both full_charge- and design-capacity are |
| broken and by also adding an alternative array of available properties for |
| devices using mA units. |
| |
| Fixes: b41901a2cf06 ("ACPI / battery: Do not export energy_full[_design] on devices without full_charge_capacity") |
| Cc: 4.19+ <stable@vger.kernel.org> # 4.19+ |
| Signed-off-by: Hans de Goede <hdegoede@redhat.com> |
| Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/acpi/battery.c | 51 +++++++++++++++++++++++++++++++++++++------------ |
| 1 file changed, 39 insertions(+), 12 deletions(-) |
| |
| --- a/drivers/acpi/battery.c |
| +++ b/drivers/acpi/battery.c |
| @@ -355,6 +355,20 @@ static enum power_supply_property charge |
| POWER_SUPPLY_PROP_SERIAL_NUMBER, |
| }; |
| |
| +static 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_CYCLE_COUNT, |
| + 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 enum power_supply_property energy_battery_props[] = { |
| POWER_SUPPLY_PROP_STATUS, |
| POWER_SUPPLY_PROP_PRESENT, |
| @@ -816,21 +830,34 @@ static void __exit battery_hook_exit(voi |
| static int sysfs_add_battery(struct acpi_battery *battery) |
| { |
| struct power_supply_config psy_cfg = { .drv_data = battery, }; |
| + bool full_cap_broken = false; |
| + |
| + if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) && |
| + !ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity)) |
| + full_cap_broken = true; |
| |
| if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) { |
| - battery->bat_desc.properties = charge_battery_props; |
| - battery->bat_desc.num_properties = |
| - ARRAY_SIZE(charge_battery_props); |
| - } else if (!ACPI_BATTERY_CAPACITY_VALID( |
| - battery->full_charge_capacity)) { |
| - battery->bat_desc.properties = |
| - energy_battery_full_cap_broken_props; |
| - battery->bat_desc.num_properties = |
| - ARRAY_SIZE(energy_battery_full_cap_broken_props); |
| + 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); |
| + } else { |
| + battery->bat_desc.properties = charge_battery_props; |
| + battery->bat_desc.num_properties = |
| + ARRAY_SIZE(charge_battery_props); |
| + } |
| } else { |
| - battery->bat_desc.properties = energy_battery_props; |
| - battery->bat_desc.num_properties = |
| - ARRAY_SIZE(energy_battery_props); |
| + 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); |
| + } else { |
| + battery->bat_desc.properties = energy_battery_props; |
| + battery->bat_desc.num_properties = |
| + ARRAY_SIZE(energy_battery_props); |
| + } |
| } |
| |
| battery->bat_desc.name = acpi_device_bid(battery->device); |