From a1b4bd694a803eba49d637de32bb249638ceadb4 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 23 Oct 2010 19:35:15 +0200 Subject: ACPI / Battery: Return -ENODEV for unknown values in get_property() The function acpi_battery_get_property() is called by the power supply framework's function power_supply_show_property() implementing the sysfs interface for power supply devices as the ACPI battery driver's ->get_property() callback. Thus it is supposed to return error code if the value of the given property is unknown. Unfortunately, however, it returns 0 in those cases and puts a wrong (negative) value into the intval field of the union power_supply_propval object provided by power_supply_show_property(). In consequence, wrong negative values are read by user space from the battery's sysfs files. Fix this by making acpi_battery_get_property() return -ENODEV for properties with unknown values (-ENODEV is returned, because power_supply_uevent() returns with error for any other error code returned by power_supply_show_property()). Reported-and-tested-by: Sitsofe Wheeler Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/acpi/battery.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 98417201e9c..ac74a7ddaaa 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -186,6 +186,7 @@ static int acpi_battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { + int ret = 0; struct acpi_battery *battery = to_acpi_battery(psy); if (acpi_battery_present(battery)) { @@ -214,26 +215,44 @@ static int acpi_battery_get_property(struct power_supply *psy, val->intval = battery->cycle_count; break; case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: - val->intval = battery->design_voltage * 1000; + if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) + ret = -ENODEV; + else + val->intval = battery->design_voltage * 1000; break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = battery->voltage_now * 1000; + if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN) + ret = -ENODEV; + else + val->intval = battery->voltage_now * 1000; break; case POWER_SUPPLY_PROP_CURRENT_NOW: case POWER_SUPPLY_PROP_POWER_NOW: - val->intval = battery->rate_now * 1000; + if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN) + ret = -ENODEV; + else + val->intval = battery->rate_now * 1000; break; case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: - val->intval = battery->design_capacity * 1000; + if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) + ret = -ENODEV; + else + val->intval = battery->design_capacity * 1000; break; case POWER_SUPPLY_PROP_CHARGE_FULL: case POWER_SUPPLY_PROP_ENERGY_FULL: - val->intval = battery->full_charge_capacity * 1000; + if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN) + ret = -ENODEV; + else + val->intval = battery->full_charge_capacity * 1000; break; case POWER_SUPPLY_PROP_CHARGE_NOW: case POWER_SUPPLY_PROP_ENERGY_NOW: - val->intval = battery->capacity_now * 1000; + if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN) + ret = -ENODEV; + else + val->intval = battery->capacity_now * 1000; break; case POWER_SUPPLY_PROP_MODEL_NAME: val->strval = battery->model_number; @@ -245,9 +264,9 @@ static int acpi_battery_get_property(struct power_supply *psy, val->strval = battery->serial_number; break; default: - return -EINVAL; + ret = -EINVAL; } - return 0; + return ret; } static enum power_supply_property charge_battery_props[] = { -- cgit v1.2.3-70-g09d2