Re: [RFC][PATCH 00/11] Android PM extensions

Arve Hjønnevåg
2009-01-30T06:04:32Z

Documentation/power/wakelocks.txt (version 3)
Wakelocks
=========

A locked wakelock, depending on its type, prevents the system from entering
suspend or other low-power states. When creating a wakelock, you can select
if it prevents suspend or low-power idle states. If the type is set to
WAKE_LOCK_SUSPEND, the wakelock prevents a full system suspend. If the type
is WAKE_LOCK_IDLE, low-power states that cause large interrupt latencies, or
that disable a set of interrupts, will not be entered from idle until the
wakelocks are released. Unless the type is specified, this document refers
to wakelocks with the type set to WAKE_LOCK_SUSPEND.

If the suspend operation has already started when locking a wakelock, it will
abort the suspend operation as long it has not already reached the suspend_late
stage. This means that locking a wakelock from an interrupt handler or a
freezeable thread always works, but if you lock a wakelock from a suspend_late
handler you must also return an error from that handler to abort suspend.

Wakelocks can be used to allow user-space to decide which keys should wake the
full system up and turn the screen on. Use set_irq_wake or a platform specific
api to make sure the keypad interrupt wakes up the cpu. Once the keypad driver
has resumed, the sequence of events can look like this:
- The Keypad driver gets an interrupt. It then locks the keypad-scan wakelock
and starts scanning the keypad matrix.
- The keypad-scan code detects a key change and reports it to the input-event
driver.
- The input-event driver sees the key change, enqueues an event, and locks
the input-event-queue wakelock.
- The keypad-scan code detects that no keys are held and unlocks the
keypad-scan wakelock.
- The user-space input-event thread returns from select/poll, locks the
process-input-events wakelock and then calls read in the input-event device.
- The input-event driver dequeues the key-event and, since the queue is now
empty, it unlocks the input-event-queue wakelock.
- The user-space input-event thread returns from read. It determines that the
key should not wake up the full system, releases the process-input-events
wakelock and calls select or poll.

Key pressed Key released
| |
keypad-scan ++++++++++++++++++
input-event-queue +++ +++
process-input-events +++ +++

Driver API
==========

A driver can use the wakelock api by adding a wakelock variable to its state
and calling wake_lock_init. For instance:
struct state {
struct wakelock wakelock;
}

init() {
wake_lock_init(&state->wakelock, WAKE_LOCK_SUSPEND, "wakelockname");
}

Before freeing the memory, wake_lock_destroy must be called:

uninit() {
wake_lock_destroy(&state->wakelock);
}

When the driver determines that it needs to run (usually in an interrupt
handler) it calls wake_lock:
wake_lock(&state->wakelock);

When it no longer needs to run it calls wake_unlock:
wake_unlock(&state->wakelock);

It can also call wake_lock_timeout to release the wakelock after a delay:
wake_lock_timeout(&state->wakelock, HZ);

This works whether the wakelock is already held or not. It is useful if the
driver woke up other parts of the system that do not use wakelocks but
still need to run. Avoid this when possible, since it will waste power
if the timeout is long or may fail to finish needed work if the timeout is
short.

User-space API
==============

Write "lockname" or "lockname timeout" to /sys/power/wake_lock lock and if
needed create a wakelock. The timeout here is specified nanoseconds.
Write "lockname" to /sys/power/wake_unlock to unlock a user wakelock.

Do not use randomly generated wakelock names as there is no api to free
a user-space wakelock.

--
Arve Hjønnevåg