diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2010-10-23 13:35:15 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2010-10-23 14:05:03 -0400 |
commit | a1b4bd694a803eba49d637de32bb249638ceadb4 (patch) | |
tree | 30b3b4efbf394b8cd500b694c80485561a6827ab /drivers/acpi | |
parent | f6f94e2ab1b33f0082ac22d71f66385a60d8157f (diff) |
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 <sitsofe@yahoo.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/battery.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 98417201e9ce..ac74a7ddaaa4 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, | |||
186 | enum power_supply_property psp, | 186 | enum power_supply_property psp, |
187 | union power_supply_propval *val) | 187 | union power_supply_propval *val) |
188 | { | 188 | { |
189 | int ret = 0; | ||
189 | struct acpi_battery *battery = to_acpi_battery(psy); | 190 | struct acpi_battery *battery = to_acpi_battery(psy); |
190 | 191 | ||
191 | if (acpi_battery_present(battery)) { | 192 | if (acpi_battery_present(battery)) { |
@@ -214,26 +215,44 @@ static int acpi_battery_get_property(struct power_supply *psy, | |||
214 | val->intval = battery->cycle_count; | 215 | val->intval = battery->cycle_count; |
215 | break; | 216 | break; |
216 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: | 217 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: |
217 | val->intval = battery->design_voltage * 1000; | 218 | if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) |
219 | ret = -ENODEV; | ||
220 | else | ||
221 | val->intval = battery->design_voltage * 1000; | ||
218 | break; | 222 | break; |
219 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | 223 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: |
220 | val->intval = battery->voltage_now * 1000; | 224 | if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN) |
225 | ret = -ENODEV; | ||
226 | else | ||
227 | val->intval = battery->voltage_now * 1000; | ||
221 | break; | 228 | break; |
222 | case POWER_SUPPLY_PROP_CURRENT_NOW: | 229 | case POWER_SUPPLY_PROP_CURRENT_NOW: |
223 | case POWER_SUPPLY_PROP_POWER_NOW: | 230 | case POWER_SUPPLY_PROP_POWER_NOW: |
224 | val->intval = battery->rate_now * 1000; | 231 | if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN) |
232 | ret = -ENODEV; | ||
233 | else | ||
234 | val->intval = battery->rate_now * 1000; | ||
225 | break; | 235 | break; |
226 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | 236 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: |
227 | case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: | 237 | case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: |
228 | val->intval = battery->design_capacity * 1000; | 238 | if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) |
239 | ret = -ENODEV; | ||
240 | else | ||
241 | val->intval = battery->design_capacity * 1000; | ||
229 | break; | 242 | break; |
230 | case POWER_SUPPLY_PROP_CHARGE_FULL: | 243 | case POWER_SUPPLY_PROP_CHARGE_FULL: |
231 | case POWER_SUPPLY_PROP_ENERGY_FULL: | 244 | case POWER_SUPPLY_PROP_ENERGY_FULL: |
232 | val->intval = battery->full_charge_capacity * 1000; | 245 | if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN) |
246 | ret = -ENODEV; | ||
247 | else | ||
248 | val->intval = battery->full_charge_capacity * 1000; | ||
233 | break; | 249 | break; |
234 | case POWER_SUPPLY_PROP_CHARGE_NOW: | 250 | case POWER_SUPPLY_PROP_CHARGE_NOW: |
235 | case POWER_SUPPLY_PROP_ENERGY_NOW: | 251 | case POWER_SUPPLY_PROP_ENERGY_NOW: |
236 | val->intval = battery->capacity_now * 1000; | 252 | if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN) |
253 | ret = -ENODEV; | ||
254 | else | ||
255 | val->intval = battery->capacity_now * 1000; | ||
237 | break; | 256 | break; |
238 | case POWER_SUPPLY_PROP_MODEL_NAME: | 257 | case POWER_SUPPLY_PROP_MODEL_NAME: |
239 | val->strval = battery->model_number; | 258 | val->strval = battery->model_number; |
@@ -245,9 +264,9 @@ static int acpi_battery_get_property(struct power_supply *psy, | |||
245 | val->strval = battery->serial_number; | 264 | val->strval = battery->serial_number; |
246 | break; | 265 | break; |
247 | default: | 266 | default: |
248 | return -EINVAL; | 267 | ret = -EINVAL; |
249 | } | 268 | } |
250 | return 0; | 269 | return ret; |
251 | } | 270 | } |
252 | 271 | ||
253 | static enum power_supply_property charge_battery_props[] = { | 272 | static enum power_supply_property charge_battery_props[] = { |