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
This commit is contained in:
Коммит
f58c41cc04
|
@ -56,6 +56,10 @@
|
||||||
/* Battery power unit: 0 means mW, 1 means mA */
|
/* Battery power unit: 0 means mW, 1 means mA */
|
||||||
#define ACPI_BATTERY_POWER_UNIT_MA 1
|
#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
|
#define _COMPONENT ACPI_BATTERY_COMPONENT
|
||||||
|
|
||||||
ACPI_MODULE_NAME("battery");
|
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)
|
static int acpi_battery_is_charged(struct acpi_battery *battery)
|
||||||
{
|
{
|
||||||
/* either charging or discharging */
|
/* charging, discharging or critical low */
|
||||||
if (battery->state != 0)
|
if (battery->state != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -204,9 +208,9 @@ static int acpi_battery_get_property(struct power_supply *psy,
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
switch (psp) {
|
switch (psp) {
|
||||||
case POWER_SUPPLY_PROP_STATUS:
|
case POWER_SUPPLY_PROP_STATUS:
|
||||||
if (battery->state & 0x01)
|
if (battery->state & ACPI_BATTERY_STATE_DISCHARGING)
|
||||||
val->intval = POWER_SUPPLY_STATUS_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;
|
val->intval = POWER_SUPPLY_STATUS_CHARGING;
|
||||||
else if (acpi_battery_is_charged(battery))
|
else if (acpi_battery_is_charged(battery))
|
||||||
val->intval = POWER_SUPPLY_STATUS_FULL;
|
val->intval = POWER_SUPPLY_STATUS_FULL;
|
||||||
|
@ -269,6 +273,17 @@ static int acpi_battery_get_property(struct power_supply *psy,
|
||||||
else
|
else
|
||||||
val->intval = 0;
|
val->intval = 0;
|
||||||
break;
|
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:
|
case POWER_SUPPLY_PROP_MODEL_NAME:
|
||||||
val->strval = battery->model_number;
|
val->strval = battery->model_number;
|
||||||
break;
|
break;
|
||||||
|
@ -296,6 +311,7 @@ static enum power_supply_property charge_battery_props[] = {
|
||||||
POWER_SUPPLY_PROP_CHARGE_FULL,
|
POWER_SUPPLY_PROP_CHARGE_FULL,
|
||||||
POWER_SUPPLY_PROP_CHARGE_NOW,
|
POWER_SUPPLY_PROP_CHARGE_NOW,
|
||||||
POWER_SUPPLY_PROP_CAPACITY,
|
POWER_SUPPLY_PROP_CAPACITY,
|
||||||
|
POWER_SUPPLY_PROP_CAPACITY_LEVEL,
|
||||||
POWER_SUPPLY_PROP_MODEL_NAME,
|
POWER_SUPPLY_PROP_MODEL_NAME,
|
||||||
POWER_SUPPLY_PROP_MANUFACTURER,
|
POWER_SUPPLY_PROP_MANUFACTURER,
|
||||||
POWER_SUPPLY_PROP_SERIAL_NUMBER,
|
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_FULL,
|
||||||
POWER_SUPPLY_PROP_ENERGY_NOW,
|
POWER_SUPPLY_PROP_ENERGY_NOW,
|
||||||
POWER_SUPPLY_PROP_CAPACITY,
|
POWER_SUPPLY_PROP_CAPACITY,
|
||||||
|
POWER_SUPPLY_PROP_CAPACITY_LEVEL,
|
||||||
POWER_SUPPLY_PROP_MODEL_NAME,
|
POWER_SUPPLY_PROP_MODEL_NAME,
|
||||||
POWER_SUPPLY_PROP_MANUFACTURER,
|
POWER_SUPPLY_PROP_MANUFACTURER,
|
||||||
POWER_SUPPLY_PROP_SERIAL_NUMBER,
|
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.type = POWER_SUPPLY_TYPE_BATTERY;
|
||||||
battery->bat.get_property = acpi_battery_get_property;
|
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)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
return device_create_file(battery->bat.dev, &alarm_attr);
|
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);
|
int result, old_present = acpi_battery_present(battery);
|
||||||
result = acpi_battery_get_status(battery);
|
result = acpi_battery_get_status(battery);
|
||||||
|
@ -707,6 +725,10 @@ static int acpi_battery_update(struct acpi_battery *battery)
|
||||||
battery->update_time = 0;
|
battery->update_time = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (resume)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!battery->update_time ||
|
if (!battery->update_time ||
|
||||||
old_present != acpi_battery_present(battery)) {
|
old_present != acpi_battery_present(battery)) {
|
||||||
result = acpi_battery_get_info(battery);
|
result = acpi_battery_get_info(battery);
|
||||||
|
@ -720,7 +742,19 @@ static int acpi_battery_update(struct acpi_battery *battery)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = acpi_battery_get_state(battery);
|
result = acpi_battery_get_state(battery);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
acpi_battery_quirks(battery);
|
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;
|
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)
|
static int acpi_battery_read(int fid, struct seq_file *seq)
|
||||||
{
|
{
|
||||||
struct acpi_battery *battery = seq->private;
|
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);
|
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;
|
old = battery->bat.dev;
|
||||||
if (event == ACPI_BATTERY_NOTIFY_INFO)
|
if (event == ACPI_BATTERY_NOTIFY_INFO)
|
||||||
acpi_battery_refresh(battery);
|
acpi_battery_refresh(battery);
|
||||||
acpi_battery_update(battery);
|
acpi_battery_update(battery, false);
|
||||||
acpi_bus_generate_netlink_event(device->pnp.device_class,
|
acpi_bus_generate_netlink_event(device->pnp.device_class,
|
||||||
dev_name(&device->dev), event,
|
dev_name(&device->dev), event,
|
||||||
acpi_battery_present(battery));
|
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,
|
struct acpi_battery *battery = container_of(nb, struct acpi_battery,
|
||||||
pm_nb);
|
pm_nb);
|
||||||
|
int result;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case PM_POST_HIBERNATION:
|
case PM_POST_HIBERNATION:
|
||||||
case PM_POST_SUSPEND:
|
case PM_POST_SUSPEND:
|
||||||
if (battery->bat.dev) {
|
if (!acpi_battery_present(battery))
|
||||||
sysfs_remove_battery(battery);
|
return 0;
|
||||||
sysfs_add_battery(battery);
|
|
||||||
}
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1087,7 +1135,7 @@ static int acpi_battery_add(struct acpi_device *device)
|
||||||
mutex_init(&battery->sysfs_lock);
|
mutex_init(&battery->sysfs_lock);
|
||||||
if (acpi_has_method(battery->device->handle, "_BIX"))
|
if (acpi_has_method(battery->device->handle, "_BIX"))
|
||||||
set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
|
set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
|
||||||
result = acpi_battery_update(battery);
|
result = acpi_battery_update(battery, false);
|
||||||
if (result)
|
if (result)
|
||||||
goto fail;
|
goto fail;
|
||||||
#ifdef CONFIG_ACPI_PROCFS_POWER
|
#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;
|
battery->pm_nb.notifier_call = battery_notify;
|
||||||
register_pm_notifier(&battery->pm_nb);
|
register_pm_notifier(&battery->pm_nb);
|
||||||
|
|
||||||
|
device_init_wakeup(&device->dev, 1);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -1123,6 +1173,7 @@ static int acpi_battery_remove(struct acpi_device *device)
|
||||||
|
|
||||||
if (!device || !acpi_driver_data(device))
|
if (!device || !acpi_driver_data(device))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
device_init_wakeup(&device->dev, 0);
|
||||||
battery = acpi_driver_data(device);
|
battery = acpi_driver_data(device);
|
||||||
unregister_pm_notifier(&battery->pm_nb);
|
unregister_pm_notifier(&battery->pm_nb);
|
||||||
#ifdef CONFIG_ACPI_PROCFS_POWER
|
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||||
|
@ -1149,7 +1200,7 @@ static int acpi_battery_resume(struct device *dev)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
battery->update_time = 0;
|
battery->update_time = 0;
|
||||||
acpi_battery_update(battery);
|
acpi_battery_update(battery, true);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -537,7 +537,7 @@ static void psy_unregister_cooler(struct power_supply *psy)
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
struct device *dev;
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -568,7 +568,7 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_init(&psy->changed_lock);
|
spin_lock_init(&psy->changed_lock);
|
||||||
rc = device_init_wakeup(dev, true);
|
rc = device_init_wakeup(dev, ws);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto wakeup_init_failed;
|
goto wakeup_init_failed;
|
||||||
|
|
||||||
|
@ -606,8 +606,19 @@ dev_set_name_failed:
|
||||||
success:
|
success:
|
||||||
return rc;
|
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);
|
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)
|
void power_supply_unregister(struct power_supply *psy)
|
||||||
{
|
{
|
||||||
cancel_work_sync(&psy->changed_work);
|
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,
|
extern int power_supply_register(struct device *parent,
|
||||||
struct power_supply *psy);
|
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 void power_supply_unregister(struct power_supply *psy);
|
||||||
extern int power_supply_powers(struct power_supply *psy, struct device *dev);
|
extern int power_supply_powers(struct power_supply *psy, struct device *dev);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче