Commit e0d1f09e authored by Zhang Rui's avatar Zhang Rui Committed by Rafael J. Wysocki

ACPI / battery: wakeup the system only when necessary

ACPI Battery device receives notifications from firmware frequently,
and most of these notifications are some general events, like battery
remaining capacity change, etc, which should not wake the system up
if the system is in suspend/hibernate state.

This causes a problem that the system wakes up from suspend to freeze
shortly, because there is an ACPI battery notification every 10 seconds.

Fix the problem in this patch by registering ACPI battery device'
own wakeup source, and waking up the system only when the battery remaining
capacity is critical low, or lower than the alarm capacity set via _BTP.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=76221Signed-off-by: default avatarZhang Rui <rui.zhang@intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 9113e260
...@@ -622,7 +622,8 @@ static int sysfs_add_battery(struct acpi_battery *battery) ...@@ -622,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);
...@@ -741,7 +742,19 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume) ...@@ -741,7 +742,19 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume)
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;
} }
...@@ -1142,6 +1155,8 @@ static int acpi_battery_add(struct acpi_device *device) ...@@ -1142,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:
...@@ -1158,6 +1173,7 @@ static int acpi_battery_remove(struct acpi_device *device) ...@@ -1158,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
......
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