Dark resume describes a state where the system resumes after being suspended but keeps its display off. Dark Resume helps the device to resume from sleep states to perform tasks that do not require user attention. powerd makes this decision of whether to enter Dark/Full Resume. This document describes how and when powerd decides to enter into Dark Resume. This document also covers the driver level support needed for powerd to make this decision properly.
powerd decides whether to enter Dark/Full Resume based on the wake source. All input devices that are wake capable (have power/wakeup attribute) are considered as potential sources for Full Resume. Other devices are treated as sources of Dark Resume.
Input devices need not be wake-capable by themselves. powerd traverses the sysfs path of the device node, to find the closest wake-capable parent. If found, powerd monitors the wakeup-count of the parent device. This helps in handling mfd devices where the mfd node aggregates and report wakeups from all its children. If powerd cannot find any wake-capable parent, it assumes this input device cannot wake the system up.
On path to suspend, powerd takes a snapshot of wakeup count for all the input devices that it is monitoring. On resume, powerd checks the wakeup count of these devices again to see if there is a difference. If so, powerd deems the wake as Full Resume. Otherwise, the wake is treated as a Dark Resume.
HandleDarkSuspendReadinessmethod call, the system re-suspends again.
powerd transitions from Dark Resume to Full Resume in the following scenarios :
powerd does the following as part of transitioning from Dark Resume to Full Resume:
For a device to be wake-capable, the driver attached to the device should call
device_init_wakeup() in its
init() methods. This call sets the
power.can_wakeup attribute of the device to true. This call also adds device-specific wakeup related attributes to sysfs.
Further, drivers should call
pm_wakeup_event() after processing a wake interrupt. This results in a increment in per-device wakeup count along with the aggregated wakeup count (
/sys/power/wakeup_count) of all devices.
Note that it is okay to call
pm_wakeup_event() on every interrupt. Per-device wakeup count increments only when
events_check_enabled is set. This bool is set whenever we write current wakeup count to
/sys/power/wakeup_count from the userspace. Userspace is expected to write to
/sys/power/wakeup_count just before suspend. Also
events_check_enabled is cleared on every resume.
On Chrome OS devices, powerd writes the current wakeup count into
/sys/power/wakeup_count before every suspend. This way, when
pm_wakeup_event() is called from IRQs, per-device
wakeup_count increments only if the system is in a system-wide suspend/resume cycle.
Please follow these steps to enable Dark Resume on a new device.
disable-dark-resumeto the board's
Perform the following steps to enable Dark Resume:
echo 0 > /var/lib/power_manager/disable_dark_resume
Perform the following steps to disable Dark Resume:
echo 1 > /var/lib/power_manager/disable_dark_resume
The commands below should facilitate a dark resume via the RTC wake source. Note, any issues with failures to suspend or spurious wakes should be resolved first in order to not block this testing.
echo 0 > /var/lib/power_manager/disable_dark_resume
Create an RTC wake that is always meant to be a dark resume.
powerd_dbus_suspend --disable_dark_resume=false --wakeup_timeout=10
Note after ~10 secs device should wake without screen on. It should be perceivable via things like:
Note device should return to suspend fairly quickly.
Wake manually via input device (keyboard, trackpad)
Examine powerd log for success
grep "In dark resume" /var/log/power_manager/powerd.LATEST
You should see something like:
[0908/104512.488613:INFO:dark_resume.cc(41)] In dark resume
Dark resume enabled in
You should see “Dark resume disabled” in the powerd logs if Dark Resume is disabled.
If a wake from a particular wake source results in Dark Resume when it is not supposed to, these steps might help in debugging what went wrong.
Check if the wake source is waking the device up when Dark Resume is disabled. Otherwise Dark Resume logic might not be at fault.
Check if the driver registers an input device to report events.
cat /proc/bus/input/devices lists all the input devices and their attributes. Otherwise fix the driver to register an input device.
Check if powerd is monitoring this specific input device for wakeups. You should see a log similar to
Monitoring input device event* with sysfs path /sys/devices/*/input/input*/event* to identify the wake source in
/var/log/power_manager/powerd.LATEST. If not, the driver might not have called
device_init_wakeup() in the
Check if the device driver is incrementing the wakeup counts correctly. Otherwise the driver might need to call
pm_wakeup_event() when handling interrupt.
If a wake from a particular wake source trigger a Full Resume when it is not supposed to, this might help in debugging what went wrong.
Powerd only tracks input devices that can trigger Full Resume. If a wake from other wake sources result in Full Resume, then one of the input devices is incrementing the wakeup count even when it is not the source of the wake. powerd prints the details of the device that incremented the wakeup count after resume. Look for a log similar to
Device /sys/devices/\*/\* had wakeup count \* before suspend and \* after resume in powerd logs. This is the device that need to be fixed.
mfd/cros_ec.c handles the interrupts from ChromeOS EC. On an interrupt
mfd/cros_ec.c driver calls
cros_ec_get_next_event to get further details. If the call succeeds, the driver then notifies all the interested drivers about the event. Individual drivers like cros_ec_keyb.c can increment the wakeup count if the event is for them. This way we can identify the actual sub device that woke us up.
Thus when adding a new device under EC that can wakeup the system
device_init_wakeup()in the probe method of the driver.
pm_wakeup_event()if the event is for this particular driver in the notification handler.
shutdown-from-suspend extends battery life of ChromeOS device during prolonged non-use by proactively shutting down.
/sys/power/wakeup_count increase even when the system is not in suspend/resume path?
/sys/power/wakeup_count is a misnomer. Instead of printing the
wakeup_count, the kernel currently prints combined_event_count. Thus you might see the wakeup count incrementing even when the system is not in the suspend resume path. Note that, per-device wakeup count has been fixed and reports properly.
Do we have support for USB devices?
Yes. The patch set [adds the support for USB].
Can we find the wake source from the logs?
Currently powerd only tracks input events. So, if the wake source is one of the input devices, you should see a log similar to
Device /sys/devices/*/* had wakeup count * before suspend and * after resume. If the wake source is not a input device, then you should see log saying
In Dark Resume.
Can we see the summary of wakeup stats all devices somewhere?
Summary of all wakeup sources can be found at