Commit f58c41cc authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branch 'acpi-battery'

* acpi-battery:
  ACPI / battery: wakeup the system only when necessary
  power_supply: allow power supply devices registered w/o wakeup source
  ACPI / battery: introduce support for POWER_SUPPLY_PROP_CAPACITY_LEVEL
  ACPI / battery: Accelerate battery resume callback
parents ee7f9d7c e0d1f09e
......@@ -56,6 +56,10 @@
/* Battery power unit: 0 means mW, 1 means mA */
#define ACPI_BATTERY_POWER_UNIT_MA 1
#define ACPI_BATTERY_STATE_DISCHARGING 0x1
#define ACPI_BATTERY_STATE_CHARGING 0x2
#define ACPI_BATTERY_STATE_CRITICAL 0x4
#define _COMPONENT ACPI_BATTERY_COMPONENT
ACPI_MODULE_NAME("battery");
......@@ -169,7 +173,7 @@ static int acpi_battery_get_state(struct acpi_battery *battery);
static int acpi_battery_is_charged(struct acpi_battery *battery)
{
/* either charging or discharging */
/* charging, discharging or critical low */
if (battery->state != 0)
return 0;
......@@ -204,9 +208,9 @@ static int acpi_battery_get_property(struct power_supply *psy,
return -ENODEV;
switch (psp) {
case POWER_SUPPLY_PROP_STATUS:
if (battery->state & 0x01)
if (battery->state & ACPI_BATTERY_STATE_DISCHARGING)
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
else if (battery->state & 0x02)
else if (battery->state & ACPI_BATTERY_STATE_CHARGING)
val->intval = POWER_SUPPLY_STATUS_CHARGING;
else if (acpi_battery_is_charged(battery))
val->intval = POWER_SUPPLY_STATUS_FULL;
......@@ -269,6 +273,17 @@ static int acpi_battery_get_property(struct power_supply *psy,
else
val->intval = 0;
break;
case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
if (battery->state & ACPI_BATTERY_STATE_CRITICAL)
val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
else if (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
(battery->capacity_now <= battery->alarm))
val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
else if (acpi_battery_is_charged(battery))
val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
else
val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
break;
case POWER_SUPPLY_PROP_MODEL_NAME:
val->strval = battery->model_number;
break;
......@@ -296,6 +311,7 @@ static enum power_supply_property charge_battery_props[] = {
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,
......@@ -313,6 +329,7 @@ static enum power_supply_property energy_battery_props[] = {
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,
......@@ -605,7 +622,8 @@ static int sysfs_add_battery(struct acpi_battery *battery)
battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
battery->bat.get_property = acpi_battery_get_property;
result = power_supply_register(&battery->device->dev, &battery->bat);
result = power_supply_register_no_ws(&battery->device->dev, &battery->bat);
if (result)
return result;
return device_create_file(battery->bat.dev, &alarm_attr);
......@@ -696,7 +714,7 @@ static void acpi_battery_quirks(struct acpi_battery *battery)
}
}
static int acpi_battery_update(struct acpi_battery *battery)
static int acpi_battery_update(struct acpi_battery *battery, bool resume)
{
int result, old_present = acpi_battery_present(battery);
result = acpi_battery_get_status(battery);
......@@ -707,6 +725,10 @@ static int acpi_battery_update(struct acpi_battery *battery)
battery->update_time = 0;
return 0;
}
if (resume)
return 0;
if (!battery->update_time ||
old_present != acpi_battery_present(battery)) {
result = acpi_battery_get_info(battery);
......@@ -720,7 +742,19 @@ static int acpi_battery_update(struct acpi_battery *battery)
return result;
}
result = acpi_battery_get_state(battery);
if (result)
return result;
acpi_battery_quirks(battery);
/*
* Wakeup the system if battery is critical low
* or lower than the alarm level
*/
if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
(test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
(battery->capacity_now <= battery->alarm)))
pm_wakeup_event(&battery->device->dev, 0);
return result;
}
......@@ -915,7 +949,7 @@ static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = {
static int acpi_battery_read(int fid, struct seq_file *seq)
{
struct acpi_battery *battery = seq->private;
int result = acpi_battery_update(battery);
int result = acpi_battery_update(battery, false);
return acpi_print_funcs[fid](seq, result);
}
......@@ -1030,7 +1064,7 @@ static void acpi_battery_notify(struct acpi_device *device, u32 event)
old = battery->bat.dev;
if (event == ACPI_BATTERY_NOTIFY_INFO)
acpi_battery_refresh(battery);
acpi_battery_update(battery);
acpi_battery_update(battery, false);
acpi_bus_generate_netlink_event(device->pnp.device_class,
dev_name(&device->dev), event,
acpi_battery_present(battery));
......@@ -1045,13 +1079,27 @@ static int battery_notify(struct notifier_block *nb,
{
struct acpi_battery *battery = container_of(nb, struct acpi_battery,
pm_nb);
int result;
switch (mode) {
case PM_POST_HIBERNATION:
case PM_POST_SUSPEND:
if (battery->bat.dev) {
sysfs_remove_battery(battery);
sysfs_add_battery(battery);
}
if (!acpi_battery_present(battery))
return 0;
if (!battery->bat.dev) {
result = acpi_battery_get_info(battery);
if (result)
return result;
result = sysfs_add_battery(battery);
if (result)
return result;
} else
acpi_battery_refresh(battery);
acpi_battery_init_alarm(battery);
acpi_battery_get_state(battery);
break;
}
......@@ -1087,7 +1135,7 @@ static int acpi_battery_add(struct acpi_device *device)
mutex_init(&battery->sysfs_lock);
if (acpi_has_method(battery->device->handle, "_BIX"))
set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
result = acpi_battery_update(battery);
result = acpi_battery_update(battery, false);
if (result)
goto fail;
#ifdef CONFIG_ACPI_PROCFS_POWER
......@@ -1107,6 +1155,8 @@ static int acpi_battery_add(struct acpi_device *device)
battery->pm_nb.notifier_call = battery_notify;
register_pm_notifier(&battery->pm_nb);
device_init_wakeup(&device->dev, 1);
return result;
fail:
......@@ -1123,6 +1173,7 @@ static int acpi_battery_remove(struct acpi_device *device)
if (!device || !acpi_driver_data(device))
return -EINVAL;
device_init_wakeup(&device->dev, 0);
battery = acpi_driver_data(device);
unregister_pm_notifier(&battery->pm_nb);
#ifdef CONFIG_ACPI_PROCFS_POWER
......@@ -1149,7 +1200,7 @@ static int acpi_battery_resume(struct device *dev)
return -EINVAL;
battery->update_time = 0;
acpi_battery_update(battery);
acpi_battery_update(battery, true);
return 0;
}
#else
......
......@@ -537,7 +537,7 @@ static void psy_unregister_cooler(struct power_supply *psy)
}
#endif
int power_supply_register(struct device *parent, struct power_supply *psy)
int __power_supply_register(struct device *parent, struct power_supply *psy, bool ws)
{
struct device *dev;
int rc;
......@@ -568,7 +568,7 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
}
spin_lock_init(&psy->changed_lock);
rc = device_init_wakeup(dev, true);
rc = device_init_wakeup(dev, ws);
if (rc)
goto wakeup_init_failed;
......@@ -606,8 +606,19 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
success:
return rc;
}
int power_supply_register(struct device *parent, struct power_supply *psy)
{
return __power_supply_register(parent, psy, true);
}
EXPORT_SYMBOL_GPL(power_supply_register);
int power_supply_register_no_ws(struct device *parent, struct power_supply *psy)
{
return __power_supply_register(parent, psy, false);
}
EXPORT_SYMBOL_GPL(power_supply_register_no_ws);
void power_supply_unregister(struct power_supply *psy)
{
cancel_work_sync(&psy->changed_work);
......
......@@ -264,6 +264,8 @@ static inline int power_supply_is_system_supplied(void) { return -ENOSYS; }
extern int power_supply_register(struct device *parent,
struct power_supply *psy);
extern int power_supply_register_no_ws(struct device *parent,
struct power_supply *psy);
extern void power_supply_unregister(struct power_supply *psy);
extern int power_supply_powers(struct power_supply *psy, struct device *dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment