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.
DarkSuspendImminent
D-Bus signal.HandleDarkSuspendReadiness
method call, the system re-suspends again.powerd transitions from Dark Resume to Full Resume in the following scenarios :
HandleUserActivity
D-Bus method.powerd does the following as part of transitioning from Dark Resume to Full Resume:
SuspendDone
D-Bus signal.For a device to be wake-capable, the driver attached to the device should call device_init_wakeup()
in its probe()
or 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-resume
to the board's model.yaml
(example).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.
Enable it
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
Look for Dark resume enabled
in /var/log/power_manager/powerd.LATEST
.
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.
powerd_dbus_suspend
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 probe()
or init()
method.
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.The following wake sources result in a dark resume if the feature is enabled.
shutdown-from-suspend extends battery life of ChromeOS device during prolonged non-use by proactively shutting down.
Why does /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 /sys/kernel/debug/wakeup_sources
.