[PATCH 01/13] PM: Add wake lock api.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Signed-off-by: Arve Hjønnevåg <arve@xxxxxxxxxxx>--- Documentation/power/wakelocks.txt |   91 ++++++++++++++++++++++++++++++++++++ include/linux/wakelock.h          |   92 +++++++++++++++++++++++++++++++++++++ 2 files changed, 183 insertions(+), 0 deletions(-) create mode 100644 Documentation/power/wakelocks.txt create mode 100755 include/linux/wakelock.h
diff --git a/Documentation/power/wakelocks.txt b/Documentation/power/wakelocks.txtnew file mode 100644index 0000000..219bb11--- /dev/null+++ b/Documentation/power/wakelocks.txt@@ -0,0 +1,91 @@+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.+diff --git a/include/linux/wakelock.h b/include/linux/wakelock.hnew file mode 100755index 0000000..b17e993--- /dev/null+++ b/include/linux/wakelock.h@@ -0,0 +1,92 @@+/* include/linux/wakelock.h+ *+ * Copyright (C) 2007-2008 Google, Inc.+ *+ * This software is licensed under the terms of the GNU General Public+ * License version 2, as published by the Free Software Foundation, and+ * may be copied, distributed, and modified under those terms.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ */++#ifndef _LINUX_WAKELOCK_H+#define _LINUX_WAKELOCK_H++#include <linux/list.h>+#include <linux/ktime.h>++/* A wake_lock prevents the system from entering suspend or other low power+ * states when active. If the type is set to WAKE_LOCK_SUSPEND, the wake_lock+ * 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 entered from idle until the wake_locks are released.+ */++enum {+	WAKE_LOCK_SUSPEND, /* Prevent suspend */+	WAKE_LOCK_IDLE,    /* Prevent low power idle */+	WAKE_LOCK_TYPE_COUNT+};++struct wake_lock {+#ifdef CONFIG_HAS_WAKELOCK+	struct list_head    link;+	int                 flags;+	const char         *name;+	unsigned long       expires;+#ifdef CONFIG_WAKELOCK_STAT+	struct {+		int             count;+		int             expire_count;+		int             wakeup_count;+		ktime_t         total_time;+		ktime_t         prevent_suspend_time;+		ktime_t         max_time;+		ktime_t         last_time;+	} stat;+#endif+#endif+};++#ifdef CONFIG_HAS_WAKELOCK++void wake_lock_init(struct wake_lock *lock, int type, const char *name);+void wake_lock_destroy(struct wake_lock *lock);+void wake_lock(struct wake_lock *lock);+void wake_lock_timeout(struct wake_lock *lock, long timeout);+void wake_unlock(struct wake_lock *lock);++/* wake_lock_active returns a non-zero value if the wake_lock is currently+ * locked. If the wake_lock has a timeout, it does not check the timeout,+ * but if the timeout had already expired when it was checked elsewhere+ * this function will return 0.+ */+int wake_lock_active(struct wake_lock *lock);++/* has_wake_lock returns 0 if no wake locks of the specified type are active,+ * and non-zero if one or more wake locks are held. Specifically it returns+ * -1 if one or more wake locks with no timeout are active or the+ * number of jiffies until all active wake locks time out.+ */+long has_wake_lock(int type);++#else++static inline void wake_lock_init(struct wake_lock *lock, int type,+					const char *name) {}+static inline void wake_lock_destroy(struct wake_lock *lock) {}+static inline void wake_lock(struct wake_lock *lock) {}+static inline void wake_lock_timeout(struct wake_lock *lock, long timeout) {}+static inline void wake_unlock(struct wake_lock *lock) {}++static inline int wake_lock_active(struct wake_lock *lock) { return 0; }+static inline long has_wake_lock(int type) { return 0; }++#endif++#endif+-- 1.6.1
_______________________________________________linux-pm mailing listlinux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx://lists.linux-foundation.org/mailman/listinfo/linux-pm


[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux