All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC][PATCH 00/11] Android PM extensions
@ 2009-02-05  2:50 Arve Hjønnevåg
  2009-02-05  2:50 ` [PATCH 01/13] PM: Add wake lock api Arve Hjønnevåg
  2009-02-06 23:51 ` [RFC][PATCH 00/11] Android PM extensions Rafael J. Wysocki
  0 siblings, 2 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  2:50 UTC (permalink / raw)
  To: linux-pm; +Cc: ncunningham, u.luckas, swetland

The following patch series adds two apis, wakelock and earlysuspend.
The Android platform uses the earlysuspend api to turn the screen
and some input devices on and off. The wakelock code determines when
to enter the full suspend state. 

These apis could also be useful to other platforms where the goal is
to enter full suspend whenever possible.

This is the second version posted to linux-pm. The main change from the first
version is that it no longer reuses /sys/power/state for the non-blocking
interface.

--
Arve Hjønnevåg

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* [PATCH 01/13] PM: Add wake lock api.
  2009-02-05  2:50 [RFC][PATCH 00/11] Android PM extensions Arve Hjønnevåg
@ 2009-02-05  2:50 ` Arve Hjønnevåg
  2009-02-05  2:50   ` [PATCH 02/13] PM: Add early suspend api Arve Hjønnevåg
                     ` (3 more replies)
  2009-02-06 23:51 ` [RFC][PATCH 00/11] Android PM extensions Rafael J. Wysocki
  1 sibling, 4 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  2:50 UTC (permalink / raw)
  To: linux-pm; +Cc: ncunningham, u.luckas, swetland

Signed-off-by: Arve Hjønnevåg <arve@android.com>
---
 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.txt
new file mode 100644
index 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.h
new file mode 100755
index 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 list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply related	[flat|nested] 251+ messages in thread

* [PATCH 02/13] PM: Add early suspend api.
  2009-02-05  2:50 ` [PATCH 01/13] PM: Add wake lock api Arve Hjønnevåg
@ 2009-02-05  2:50   ` Arve Hjønnevåg
  2009-02-05  2:50     ` [PATCH 03/13] PM: Implement wakelock api Arve Hjønnevåg
                       ` (3 more replies)
  2009-02-05  9:11   ` [PATCH 01/13] PM: Add wake lock api Pavel Machek
                     ` (2 subsequent siblings)
  3 siblings, 4 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  2:50 UTC (permalink / raw)
  To: linux-pm; +Cc: ncunningham, u.luckas, swetland

Signed-off-by: Arve Hjønnevåg <arve@android.com>
---
 Documentation/power/early-suspend.txt |   26 +++++++++++++++
 include/linux/earlysuspend.h          |   55 +++++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/power/early-suspend.txt
 create mode 100755 include/linux/earlysuspend.h

diff --git a/Documentation/power/early-suspend.txt b/Documentation/power/early-suspend.txt
new file mode 100644
index 0000000..8286d3a
--- /dev/null
+++ b/Documentation/power/early-suspend.txt
@@ -0,0 +1,26 @@
+Early-suspend
+=============
+
+The early-suspend api allows drivers to get notified when user-space writes to 
+/sys/power/request_state to indicate that the user visible sleep state should 
+change. A level controls what order the handlers are called in. Suspend 
+handlers are called in low to high level order, resume handlers are called in 
+the opposite order. 
+
+Four levels are defined:
+EARLY_SUSPEND_LEVEL_BLANK_SCREEN:
+  On suspend the screen should be turned off but the framebuffer must still be
+  accessible. On resume the screen can be turned back on.
+
+EARLY_SUSPEND_LEVEL_STOP_DRAWING:
+  On suspend this level notifies user-space that it should stop accessing the 
+  framebuffer and it waits for it to complete. On resume it notifies user-space 
+  that it should resume screen access.
+  Two methods are provided, console switch or a sysfs interface.
+
+EARLY_SUSPEND_LEVEL_DISABLE_FB:
+  Turn off the framebuffer on suspend and back on on resume.
+
+EARLY_SUSPEND_LEVEL_STOP_INPUT:
+  On suspend turn off input devices that are not capable of wakeup or where
+  wakeup is disabled. On resume turn the same devices back on.
diff --git a/include/linux/earlysuspend.h b/include/linux/earlysuspend.h
new file mode 100755
index 0000000..1587a3f
--- /dev/null
+++ b/include/linux/earlysuspend.h
@@ -0,0 +1,55 @@
+/* include/linux/earlysuspend.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_EARLYSUSPEND_H
+#define _LINUX_EARLYSUSPEND_H
+
+#include <linux/list.h>
+
+/* The early_suspend structure defines suspend and resume hooks to be called
+ * when the user visible sleep state of the system changes, and a level to
+ * control the order. They can be used to turn off the screen and input
+ * devices that are not used for wakeup.
+ * Suspend handlers are called in low to high level order, resume handlers are
+ * called in the opposite order. If, when calling register_early_suspend,
+ * the suspend handlers have already been called without a matching call to the
+ * resume handlers, the suspend handler will be called directly from
+ * register_early_suspend. This direct call can violate the normal level order.
+ */
+enum {
+	EARLY_SUSPEND_LEVEL_BLANK_SCREEN = 50,
+	EARLY_SUSPEND_LEVEL_STOP_INPUT = 75,
+	EARLY_SUSPEND_LEVEL_STOP_DRAWING = 100,
+	EARLY_SUSPEND_LEVEL_DISABLE_FB = 150,
+};
+struct early_suspend {
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	struct list_head link;
+	int level;
+	void (*suspend)(struct early_suspend *h);
+	void (*resume)(struct early_suspend *h);
+#endif
+};
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+void register_early_suspend(struct early_suspend *handler);
+void unregister_early_suspend(struct early_suspend *handler);
+#else
+#define register_early_suspend(handler) do { } while (0)
+#define unregister_early_suspend(handler) do { } while (0)
+#endif
+
+#endif
+
-- 
1.6.1

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply related	[flat|nested] 251+ messages in thread

* [PATCH 03/13] PM: Implement wakelock api.
  2009-02-05  2:50   ` [PATCH 02/13] PM: Add early suspend api Arve Hjønnevåg
@ 2009-02-05  2:50     ` Arve Hjønnevåg
  2009-02-05  2:50       ` [PATCH 04/13] PM: wakelock: Override wakelocks when using /sys/power/state Arve Hjønnevåg
                         ` (4 more replies)
  2009-02-05  9:14     ` [PATCH 02/13] PM: Add early suspend api Pavel Machek
                       ` (2 subsequent siblings)
  3 siblings, 5 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  2:50 UTC (permalink / raw)
  To: linux-pm; +Cc: ncunningham, u.luckas, swetland

Signed-off-by: Arve Hjønnevåg <arve@android.com>
---
 kernel/power/Kconfig    |   19 ++
 kernel/power/Makefile   |    1 +
 kernel/power/power.h    |    7 +
 kernel/power/wakelock.c |  598 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 625 insertions(+), 0 deletions(-)
 create mode 100644 kernel/power/wakelock.c

diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 23bd4da..6e3da6e 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -116,6 +116,25 @@ config SUSPEND_FREEZER
 
 	  Turning OFF this setting is NOT recommended! If in doubt, say Y.
 
+config HAS_WAKELOCK
+	bool
+
+config WAKELOCK
+	bool "Wake lock"
+	depends on PM && RTC_CLASS
+	default n
+	select HAS_WAKELOCK
+	---help---
+	  Enable wakelocks. When user space request a sleep state the
+	  sleep request will be delayed until no wake locks are held.
+
+config WAKELOCK_STAT
+	bool "Wake lock stats"
+	depends on WAKELOCK
+	default y
+	---help---
+	  Report wake lock stats in /proc/wakelocks
+
 config HIBERNATION
 	bool "Hibernation (aka 'suspend to disk')"
 	depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index d7a1016..8d8672b 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -6,6 +6,7 @@ endif
 obj-y				:= main.o
 obj-$(CONFIG_PM_SLEEP)		+= console.o
 obj-$(CONFIG_FREEZER)		+= process.o
+obj-$(CONFIG_WAKELOCK)		+= wakelock.o
 obj-$(CONFIG_HIBERNATION)	+= swsusp.o disk.o snapshot.o swap.o user.o
 
 obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 46b5ec7..1527174 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -223,3 +223,10 @@ static inline void suspend_thaw_processes(void)
 {
 }
 #endif
+
+#ifdef CONFIG_WAKELOCK
+/* kernel/power/wakelock.c */
+extern struct workqueue_struct *suspend_work_queue;
+extern struct wake_lock main_wake_lock;
+extern suspend_state_t requested_suspend_state;
+#endif
diff --git a/kernel/power/wakelock.c b/kernel/power/wakelock.c
new file mode 100644
index 0000000..c9e22f9
--- /dev/null
+++ b/kernel/power/wakelock.c
@@ -0,0 +1,598 @@
+/* kernel/power/wakelock.c
+ *
+ * Copyright (C) 2005-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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/suspend.h>
+#include <linux/syscalls.h> /* sys_sync */
+#include <linux/wakelock.h>
+#ifdef CONFIG_WAKELOCK_STAT
+#include <linux/proc_fs.h>
+#endif
+#include "power.h"
+
+enum {
+	DEBUG_EXIT_SUSPEND = 1U << 0,
+	DEBUG_WAKEUP = 1U << 1,
+	DEBUG_SUSPEND = 1U << 2,
+	DEBUG_EXPIRE = 1U << 3,
+	DEBUG_WAKE_LOCK = 1U << 4,
+};
+static int debug_mask = DEBUG_EXIT_SUSPEND | DEBUG_WAKEUP;
+module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+#define WAKE_LOCK_TYPE_MASK              (0x0f)
+#define WAKE_LOCK_INITIALIZED            (1U << 8)
+#define WAKE_LOCK_ACTIVE                 (1U << 9)
+#define WAKE_LOCK_AUTO_EXPIRE            (1U << 10)
+#define WAKE_LOCK_PREVENTING_SUSPEND     (1U << 11)
+
+static DEFINE_SPINLOCK(list_lock);
+static LIST_HEAD(inactive_locks);
+static struct list_head active_wake_locks[WAKE_LOCK_TYPE_COUNT];
+static int current_event_num;
+struct workqueue_struct *suspend_work_queue;
+struct wake_lock main_wake_lock;
+suspend_state_t requested_suspend_state = PM_SUSPEND_MEM;
+static struct wake_lock unknown_wakeup;
+
+#ifdef CONFIG_WAKELOCK_STAT
+static struct wake_lock deleted_wake_locks;
+static ktime_t last_sleep_time_update;
+static int wait_for_wakeup;
+
+int get_expired_time(struct wake_lock *lock, ktime_t *expire_time)
+{
+	struct timespec ts;
+	struct timespec kt;
+	struct timespec tomono;
+	struct timespec delta;
+	unsigned long seq;
+	long timeout;
+
+	if (!(lock->flags & WAKE_LOCK_AUTO_EXPIRE))
+		return 0;
+	do {
+		seq = read_seqbegin(&xtime_lock);
+		timeout = lock->expires - jiffies;
+		if (timeout > 0)
+			return 0;
+		kt = current_kernel_time();
+		tomono = wall_to_monotonic;
+	} while (read_seqretry(&xtime_lock, seq));
+	jiffies_to_timespec(-timeout, &delta);
+	set_normalized_timespec(&ts, kt.tv_sec + tomono.tv_sec - delta.tv_sec,
+				kt.tv_nsec + tomono.tv_nsec - delta.tv_nsec);
+	*expire_time = timespec_to_ktime(ts);
+	return 1;
+}
+
+
+static int print_lock_stat(char *buf, struct wake_lock *lock)
+{
+	int lock_count = lock->stat.count;
+	int expire_count = lock->stat.expire_count;
+	ktime_t active_time = ktime_set(0, 0);
+	ktime_t total_time = lock->stat.total_time;
+	ktime_t max_time = lock->stat.max_time;
+	ktime_t prevent_suspend_time = lock->stat.prevent_suspend_time;
+	if (lock->flags & WAKE_LOCK_ACTIVE) {
+		ktime_t now, add_time;
+		int expired = get_expired_time(lock, &now);
+		if (!expired)
+			now = ktime_get();
+		add_time = ktime_sub(now, lock->stat.last_time);
+		lock_count++;
+		if (!expired)
+			active_time = add_time;
+		else
+			expire_count++;
+		total_time = ktime_add(total_time, add_time);
+		if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND)
+			prevent_suspend_time = ktime_add(prevent_suspend_time,
+					ktime_sub(now, last_sleep_time_update));
+		if (add_time.tv64 > max_time.tv64)
+			max_time = add_time;
+	}
+
+	return sprintf(buf, "\"%s\"\t%d\t%d\t%d\t%lld\t%lld\t%lld\t%lld\t"
+		       "%lld\n", lock->name, lock_count, expire_count,
+		       lock->stat.wakeup_count, ktime_to_ns(active_time),
+		       ktime_to_ns(total_time),
+		       ktime_to_ns(prevent_suspend_time), ktime_to_ns(max_time),
+		       ktime_to_ns(lock->stat.last_time));
+}
+
+
+static int wakelocks_read_proc(char *page, char **start, off_t off,
+			       int count, int *eof, void *data)
+{
+	unsigned long irqflags;
+	struct wake_lock *lock;
+	int len = 0;
+	char *p = page;
+	int type;
+
+	spin_lock_irqsave(&list_lock, irqflags);
+
+	p += sprintf(p, "name\tcount\texpire_count\twake_count\tactive_since"
+		     "\ttotal_time\tsleep_time\tmax_time\tlast_change\n");
+	list_for_each_entry(lock, &inactive_locks, link) {
+		p += print_lock_stat(p, lock);
+	}
+	for (type = 0; type < WAKE_LOCK_TYPE_COUNT; type++) {
+		list_for_each_entry(lock, &active_wake_locks[type], link)
+			p += print_lock_stat(p, lock);
+	}
+	spin_unlock_irqrestore(&list_lock, irqflags);
+
+	*start = page + off;
+
+	len = p - page;
+	if (len > off)
+		len -= off;
+	else
+		len = 0;
+
+	return len < count ? len  : count;
+}
+
+static void wake_unlock_stat_locked(struct wake_lock *lock, int expired)
+{
+	ktime_t duration;
+	ktime_t now;
+	if (!(lock->flags & WAKE_LOCK_ACTIVE))
+		return;
+	if (get_expired_time(lock, &now))
+		expired = 1;
+	else
+		now = ktime_get();
+	lock->stat.count++;
+	if (expired)
+		lock->stat.expire_count++;
+	duration = ktime_sub(now, lock->stat.last_time);
+	lock->stat.total_time = ktime_add(lock->stat.total_time, duration);
+	if (ktime_to_ns(duration) > ktime_to_ns(lock->stat.max_time))
+		lock->stat.max_time = duration;
+	lock->stat.last_time = ktime_get();
+	if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND) {
+		duration = ktime_sub(now, last_sleep_time_update);
+		lock->stat.prevent_suspend_time = ktime_add(
+			lock->stat.prevent_suspend_time, duration);
+		lock->flags &= ~WAKE_LOCK_PREVENTING_SUSPEND;
+	}
+}
+
+static void update_sleep_wait_stats_locked(int done)
+{
+	struct wake_lock *lock;
+	ktime_t now, etime, elapsed, add;
+	int expired;
+
+	now = ktime_get();
+	elapsed = ktime_sub(now, last_sleep_time_update);
+	list_for_each_entry(lock, &active_wake_locks[WAKE_LOCK_SUSPEND], link) {
+		expired = get_expired_time(lock, &etime);
+		if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND) {
+			if (expired)
+				add = ktime_sub(etime, last_sleep_time_update);
+			else
+				add = elapsed;
+			lock->stat.prevent_suspend_time = ktime_add(
+				lock->stat.prevent_suspend_time, add);
+		}
+		if (done || expired)
+			lock->flags &= ~WAKE_LOCK_PREVENTING_SUSPEND;
+		else
+			lock->flags |= WAKE_LOCK_PREVENTING_SUSPEND;
+	}
+	last_sleep_time_update = now;
+}
+#endif
+
+
+static void expire_wake_lock(struct wake_lock *lock)
+{
+#ifdef CONFIG_WAKELOCK_STAT
+	wake_unlock_stat_locked(lock, 1);
+#endif
+	lock->flags &= ~(WAKE_LOCK_ACTIVE | WAKE_LOCK_AUTO_EXPIRE);
+	list_del(&lock->link);
+	list_add(&lock->link, &inactive_locks);
+	if (debug_mask & (DEBUG_WAKE_LOCK | DEBUG_EXPIRE))
+		pr_info("expired wake lock %s\n", lock->name);
+}
+
+static void print_active_locks(int type)
+{
+	unsigned long irqflags;
+	struct wake_lock *lock;
+
+	BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
+	spin_lock_irqsave(&list_lock, irqflags);
+	list_for_each_entry(lock, &active_wake_locks[type], link) {
+		if (lock->flags & WAKE_LOCK_AUTO_EXPIRE) {
+			long timeout = lock->expires - jiffies;
+			if (timeout <= 0)
+				pr_info("wake lock %s, expired\n", lock->name);
+			else
+				pr_info("active wake lock %s, time left %ld\n",
+					lock->name, timeout);
+		} else
+			pr_info("active wake lock %s\n", lock->name);
+	}
+	spin_unlock_irqrestore(&list_lock, irqflags);
+}
+
+static long has_wake_lock_locked(int type)
+{
+	struct wake_lock *lock, *n;
+	long max_timeout = 0;
+
+	BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
+	list_for_each_entry_safe(lock, n, &active_wake_locks[type], link) {
+		if (lock->flags & WAKE_LOCK_AUTO_EXPIRE) {
+			long timeout = lock->expires - jiffies;
+			if (timeout <= 0)
+				expire_wake_lock(lock);
+			else if (timeout > max_timeout)
+				max_timeout = timeout;
+		} else
+			return -1;
+	}
+	return max_timeout;
+}
+
+long has_wake_lock(int type)
+{
+	long ret;
+	unsigned long irqflags;
+	spin_lock_irqsave(&list_lock, irqflags);
+	ret = has_wake_lock_locked(type);
+	spin_unlock_irqrestore(&list_lock, irqflags);
+	return ret;
+}
+
+static void suspend(struct work_struct *work)
+{
+	int ret;
+	int entry_event_num;
+
+	if (has_wake_lock(WAKE_LOCK_SUSPEND)) {
+		if (debug_mask & DEBUG_SUSPEND)
+			pr_info("suspend: abort suspend\n");
+		return;
+	}
+
+	entry_event_num = current_event_num;
+	sys_sync();
+	if (debug_mask & DEBUG_SUSPEND)
+		pr_info("suspend: enter suspend\n");
+	ret = pm_suspend(requested_suspend_state);
+	if (debug_mask & DEBUG_EXIT_SUSPEND) {
+		struct timespec ts;
+		struct rtc_time tm;
+		getnstimeofday(&ts);
+		rtc_time_to_tm(ts.tv_sec, &tm);
+		pr_info("suspend: exit suspend, ret = %d "
+			"(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n", ret,
+			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+			tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
+	}
+	if (current_event_num == entry_event_num) {
+		if (debug_mask & DEBUG_SUSPEND)
+			pr_info("suspend: pm_suspend returned with no event\n");
+		wake_lock_timeout(&unknown_wakeup, HZ / 2);
+	}
+}
+static DECLARE_WORK(suspend_work, suspend);
+
+static void expire_wake_locks(unsigned long data)
+{
+	long has_lock;
+	unsigned long irqflags;
+	if (debug_mask & DEBUG_EXPIRE)
+		pr_info("expire_wake_locks: start\n");
+	if (debug_mask & DEBUG_SUSPEND)
+		print_active_locks(WAKE_LOCK_SUSPEND);
+	spin_lock_irqsave(&list_lock, irqflags);
+	has_lock = has_wake_lock_locked(WAKE_LOCK_SUSPEND);
+	if (debug_mask & DEBUG_EXPIRE)
+		pr_info("expire_wake_locks: done, has_lock %ld\n", has_lock);
+	if (has_lock == 0)
+		queue_work(suspend_work_queue, &suspend_work);
+	spin_unlock_irqrestore(&list_lock, irqflags);
+}
+static DEFINE_TIMER(expire_timer, expire_wake_locks, 0, 0);
+
+static int power_suspend_late(struct platform_device *pdev, pm_message_t state)
+{
+	int ret = has_wake_lock(WAKE_LOCK_SUSPEND) ? -EAGAIN : 0;
+#ifdef CONFIG_WAKELOCK_STAT
+	wait_for_wakeup = 1;
+#endif
+	if (debug_mask & DEBUG_SUSPEND)
+		pr_info("power_suspend_late return %d\n", ret);
+	return ret;
+}
+
+static struct platform_driver power_driver = {
+	.driver.name = "power",
+	.suspend_late = power_suspend_late,
+};
+static struct platform_device power_device = {
+	.name = "power",
+};
+
+void wake_lock_init(struct wake_lock *lock, int type, const char *name)
+{
+	unsigned long irqflags = 0;
+
+	if (name)
+		lock->name = name;
+	BUG_ON(!lock->name);
+
+	if (debug_mask & DEBUG_WAKE_LOCK)
+		pr_info("wake_lock_init name=%s\n", lock->name);
+#ifdef CONFIG_WAKELOCK_STAT
+	lock->stat.count = 0;
+	lock->stat.expire_count = 0;
+	lock->stat.wakeup_count = 0;
+	lock->stat.total_time = ktime_set(0, 0);
+	lock->stat.prevent_suspend_time = ktime_set(0, 0);
+	lock->stat.max_time = ktime_set(0, 0);
+	lock->stat.last_time = ktime_set(0, 0);
+#endif
+	lock->flags = (type & WAKE_LOCK_TYPE_MASK) | WAKE_LOCK_INITIALIZED;
+
+	INIT_LIST_HEAD(&lock->link);
+	spin_lock_irqsave(&list_lock, irqflags);
+	list_add(&lock->link, &inactive_locks);
+	spin_unlock_irqrestore(&list_lock, irqflags);
+}
+EXPORT_SYMBOL(wake_lock_init);
+
+void wake_lock_destroy(struct wake_lock *lock)
+{
+	unsigned long irqflags;
+	if (debug_mask & DEBUG_WAKE_LOCK)
+		pr_info("wake_lock_destroy name=%s\n", lock->name);
+	spin_lock_irqsave(&list_lock, irqflags);
+	lock->flags &= ~WAKE_LOCK_INITIALIZED;
+#ifdef CONFIG_WAKELOCK_STAT
+	if (lock->stat.count) {
+		deleted_wake_locks.stat.count += lock->stat.count;
+		deleted_wake_locks.stat.expire_count += lock->stat.expire_count;
+		deleted_wake_locks.stat.total_time =
+			ktime_add(deleted_wake_locks.stat.total_time,
+				  lock->stat.total_time);
+		deleted_wake_locks.stat.prevent_suspend_time =
+			ktime_add(deleted_wake_locks.stat.prevent_suspend_time,
+				  lock->stat.prevent_suspend_time);
+		deleted_wake_locks.stat.max_time =
+			ktime_add(deleted_wake_locks.stat.max_time,
+				  lock->stat.max_time);
+	}
+#endif
+	list_del(&lock->link);
+	spin_unlock_irqrestore(&list_lock, irqflags);
+}
+EXPORT_SYMBOL(wake_lock_destroy);
+
+static void wake_lock_internal(
+	struct wake_lock *lock, long timeout, int has_timeout)
+{
+	int type;
+	unsigned long irqflags;
+	long expire_in;
+
+	spin_lock_irqsave(&list_lock, irqflags);
+	type = lock->flags & WAKE_LOCK_TYPE_MASK;
+	BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
+	BUG_ON(!(lock->flags & WAKE_LOCK_INITIALIZED));
+#ifdef CONFIG_WAKELOCK_STAT
+	if (type == WAKE_LOCK_SUSPEND && wait_for_wakeup) {
+		if (debug_mask & DEBUG_WAKEUP)
+			pr_info("wakeup wake lock: %s\n", lock->name);
+		wait_for_wakeup = 0;
+		lock->stat.wakeup_count++;
+	}
+	if ((lock->flags & WAKE_LOCK_AUTO_EXPIRE) &&
+	    (long)(lock->expires - jiffies) <= 0) {
+		wake_unlock_stat_locked(lock, 0);
+		lock->stat.last_time = ktime_get();
+	}
+#endif
+	if (!(lock->flags & WAKE_LOCK_ACTIVE)) {
+		lock->flags |= WAKE_LOCK_ACTIVE;
+#ifdef CONFIG_WAKELOCK_STAT
+		lock->stat.last_time = ktime_get();
+#endif
+	}
+	list_del(&lock->link);
+	if (has_timeout) {
+		if (debug_mask & DEBUG_WAKE_LOCK)
+			pr_info("wake_lock: %s, type %d, timeout %ld.%03lu\n",
+				lock->name, type, timeout / HZ,
+				(timeout % HZ) * MSEC_PER_SEC / HZ);
+		lock->expires = jiffies + timeout;
+		lock->flags |= WAKE_LOCK_AUTO_EXPIRE;
+		list_add_tail(&lock->link, &active_wake_locks[type]);
+	} else {
+		if (debug_mask & DEBUG_WAKE_LOCK)
+			pr_info("wake_lock: %s, type %d\n", lock->name, type);
+		lock->expires = LONG_MAX;
+		lock->flags &= ~WAKE_LOCK_AUTO_EXPIRE;
+		list_add(&lock->link, &active_wake_locks[type]);
+	}
+	if (type == WAKE_LOCK_SUSPEND) {
+		current_event_num++;
+#ifdef CONFIG_WAKELOCK_STAT
+		if (lock == &main_wake_lock)
+			update_sleep_wait_stats_locked(1);
+		else if (!wake_lock_active(&main_wake_lock))
+			update_sleep_wait_stats_locked(0);
+#endif
+		if (has_timeout)
+			expire_in = has_wake_lock_locked(type);
+		else
+			expire_in = -1;
+		if (expire_in > 0) {
+			if (debug_mask & DEBUG_EXPIRE)
+				pr_info("wake_lock: %s, start expire timer, "
+					"%ld\n", lock->name, expire_in);
+			mod_timer(&expire_timer, jiffies + expire_in);
+		} else {
+			if (del_timer(&expire_timer))
+				if (debug_mask & DEBUG_EXPIRE)
+					pr_info("wake_lock: %s, stop expire "
+						"timer\n", lock->name);
+			if (expire_in == 0)
+				queue_work(suspend_work_queue, &suspend_work);
+		}
+	}
+	spin_unlock_irqrestore(&list_lock, irqflags);
+}
+
+void wake_lock(struct wake_lock *lock)
+{
+	wake_lock_internal(lock, 0, 0);
+}
+EXPORT_SYMBOL(wake_lock);
+
+void wake_lock_timeout(struct wake_lock *lock, long timeout)
+{
+	wake_lock_internal(lock, timeout, 1);
+}
+EXPORT_SYMBOL(wake_lock_timeout);
+
+void wake_unlock(struct wake_lock *lock)
+{
+	int type;
+	unsigned long irqflags;
+	spin_lock_irqsave(&list_lock, irqflags);
+	type = lock->flags & WAKE_LOCK_TYPE_MASK;
+#ifdef CONFIG_WAKELOCK_STAT
+	wake_unlock_stat_locked(lock, 0);
+#endif
+	if (debug_mask & DEBUG_WAKE_LOCK)
+		pr_info("wake_unlock: %s\n", lock->name);
+	lock->flags &= ~(WAKE_LOCK_ACTIVE | WAKE_LOCK_AUTO_EXPIRE);
+	list_del(&lock->link);
+	list_add(&lock->link, &inactive_locks);
+	if (type == WAKE_LOCK_SUSPEND) {
+		long has_lock = has_wake_lock_locked(type);
+		if (has_lock > 0) {
+			if (debug_mask & DEBUG_EXPIRE)
+				pr_info("wake_unlock: %s, start expire timer, "
+					"%ld\n", lock->name, has_lock);
+			mod_timer(&expire_timer, jiffies + has_lock);
+		} else {
+			if (del_timer(&expire_timer))
+				if (debug_mask & DEBUG_EXPIRE)
+					pr_info("wake_unlock: %s, stop expire "
+						"timer\n", lock->name);
+			if (has_lock == 0)
+				queue_work(suspend_work_queue, &suspend_work);
+		}
+		if (lock == &main_wake_lock) {
+			if (debug_mask & DEBUG_SUSPEND)
+				print_active_locks(WAKE_LOCK_SUSPEND);
+#ifdef CONFIG_WAKELOCK_STAT
+			update_sleep_wait_stats_locked(0);
+#endif
+		}
+	}
+	spin_unlock_irqrestore(&list_lock, irqflags);
+}
+EXPORT_SYMBOL(wake_unlock);
+
+int wake_lock_active(struct wake_lock *lock)
+{
+	return !!(lock->flags & WAKE_LOCK_ACTIVE);
+}
+EXPORT_SYMBOL(wake_lock_active);
+
+static int __init wakelocks_init(void)
+{
+	int ret;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(active_wake_locks); i++)
+		INIT_LIST_HEAD(&active_wake_locks[i]);
+
+#ifdef CONFIG_WAKELOCK_STAT
+	wake_lock_init(&deleted_wake_locks, WAKE_LOCK_SUSPEND,
+			"deleted_wake_locks");
+#endif
+	wake_lock_init(&main_wake_lock, WAKE_LOCK_SUSPEND, "main");
+	wake_lock(&main_wake_lock);
+	wake_lock_init(&unknown_wakeup, WAKE_LOCK_SUSPEND, "unknown_wakeups");
+
+	ret = platform_device_register(&power_device);
+	if (ret) {
+		pr_err("wakelocks_init: platform_device_register failed\n");
+		goto err_platform_device_register;
+	}
+	ret = platform_driver_register(&power_driver);
+	if (ret) {
+		pr_err("wakelocks_init: platform_driver_register failed\n");
+		goto err_platform_driver_register;
+	}
+
+	suspend_work_queue = create_singlethread_workqueue("suspend");
+	if (suspend_work_queue == NULL) {
+		ret = -ENOMEM;
+		goto err_suspend_work_queue;
+	}
+
+#ifdef CONFIG_WAKELOCK_STAT
+	create_proc_read_entry("wakelocks", S_IRUGO, NULL,
+				wakelocks_read_proc, NULL);
+#endif
+
+	return 0;
+
+err_suspend_work_queue:
+	platform_driver_unregister(&power_driver);
+err_platform_driver_register:
+	platform_device_unregister(&power_device);
+err_platform_device_register:
+	wake_lock_destroy(&unknown_wakeup);
+	wake_lock_destroy(&main_wake_lock);
+#ifdef CONFIG_WAKELOCK_STAT
+	wake_lock_destroy(&deleted_wake_locks);
+#endif
+	return ret;
+}
+
+static void  __exit wakelocks_exit(void)
+{
+#ifdef CONFIG_WAKELOCK_STAT
+	remove_proc_entry("wakelocks", NULL);
+#endif
+	destroy_workqueue(suspend_work_queue);
+	platform_driver_unregister(&power_driver);
+	platform_device_unregister(&power_device);
+	wake_lock_destroy(&unknown_wakeup);
+	wake_lock_destroy(&main_wake_lock);
+#ifdef CONFIG_WAKELOCK_STAT
+	wake_lock_destroy(&deleted_wake_locks);
+#endif
+}
+
+core_initcall(wakelocks_init);
+module_exit(wakelocks_exit);
-- 
1.6.1

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply related	[flat|nested] 251+ messages in thread

* [PATCH 04/13] PM: wakelock: Override wakelocks when using /sys/power/state
  2009-02-05  2:50     ` [PATCH 03/13] PM: Implement wakelock api Arve Hjønnevåg
@ 2009-02-05  2:50       ` Arve Hjønnevåg
  2009-02-05  2:50         ` [PATCH 05/13] PM: Add option to disable /sys/power/state interface Arve Hjønnevåg
  2009-02-07 22:31         ` [PATCH 04/13] PM: wakelock: Override wakelocks when using /sys/power/state Rafael J. Wysocki
  2009-02-05  9:16       ` [PATCH 03/13] PM: Implement wakelock api Pavel Machek
                         ` (3 subsequent siblings)
  4 siblings, 2 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  2:50 UTC (permalink / raw)
  To: linux-pm; +Cc: ncunningham, u.luckas, swetland

This preserves existing functionality when CONFIG_WAKELOCK is set.

Signed-off-by: Arve Hjønnevåg <arve@android.com>
---
 kernel/power/main.c     |    7 +++++++
 kernel/power/power.h    |    1 +
 kernel/power/wakelock.c |    4 ++++
 3 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/kernel/power/main.c b/kernel/power/main.c
index 2399888..ab9fc7f 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -515,6 +515,10 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
 	p = memchr(buf, '\n', n);
 	len = p ? p - buf : n;
 
+#ifdef CONFIG_WAKELOCK
+	ignore_suspend_wakelocks = 1;
+#endif
+
 	/* First, check if we are requested to hibernate */
 	if (len == 4 && !strncmp(buf, "disk", len)) {
 		error = hibernate();
@@ -531,6 +535,9 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
 #endif
 
  Exit:
+#ifdef CONFIG_WAKELOCK
+	ignore_suspend_wakelocks = 0;
+#endif
 	return error ? error : n;
 }
 
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 1527174..ed1b7f4 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -229,4 +229,5 @@ static inline void suspend_thaw_processes(void)
 extern struct workqueue_struct *suspend_work_queue;
 extern struct wake_lock main_wake_lock;
 extern suspend_state_t requested_suspend_state;
+extern bool ignore_suspend_wakelocks;
 #endif
diff --git a/kernel/power/wakelock.c b/kernel/power/wakelock.c
index c9e22f9..8a8608e 100644
--- a/kernel/power/wakelock.c
+++ b/kernel/power/wakelock.c
@@ -47,6 +47,7 @@ static int current_event_num;
 struct workqueue_struct *suspend_work_queue;
 struct wake_lock main_wake_lock;
 suspend_state_t requested_suspend_state = PM_SUSPEND_MEM;
+bool ignore_suspend_wakelocks;
 static struct wake_lock unknown_wakeup;
 
 #ifdef CONFIG_WAKELOCK_STAT
@@ -260,6 +261,9 @@ long has_wake_lock(int type)
 {
 	long ret;
 	unsigned long irqflags;
+	if (WARN_ONCE(type == WAKE_LOCK_SUSPEND && ignore_suspend_wakelocks,
+							"ignoring wakelocks\n"))
+		return 0;
 	spin_lock_irqsave(&list_lock, irqflags);
 	ret = has_wake_lock_locked(type);
 	spin_unlock_irqrestore(&list_lock, irqflags);
-- 
1.6.1

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply related	[flat|nested] 251+ messages in thread

* [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-05  2:50       ` [PATCH 04/13] PM: wakelock: Override wakelocks when using /sys/power/state Arve Hjønnevåg
@ 2009-02-05  2:50         ` Arve Hjønnevåg
  2009-02-05  2:50           ` [PATCH 06/13] PM: Implement early suspend api Arve Hjønnevåg
                             ` (2 more replies)
  2009-02-07 22:31         ` [PATCH 04/13] PM: wakelock: Override wakelocks when using /sys/power/state Rafael J. Wysocki
  1 sibling, 3 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  2:50 UTC (permalink / raw)
  To: linux-pm; +Cc: ncunningham, u.luckas, swetland

Signed-off-by: Arve Hjønnevåg <arve@android.com>
---
 kernel/power/Kconfig |    9 +++++++++
 kernel/power/main.c  |    4 ++++
 2 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 6e3da6e..dd76467 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -135,6 +135,15 @@ config WAKELOCK_STAT
 	---help---
 	  Report wake lock stats in /proc/wakelocks
 
+config DISABLE_SYS_POWER_STATE
+	bool "Disable /sys/power/state interface"
+	depends on WAKELOCK
+	default n
+	---help---
+	  The /sys/power/state interface does not respect wakelocks. If you
+	  want to run user-space code that does not support wakelocks, do not
+	  enable this option since it removes the interface.
+
 config HIBERNATION
 	bool "Hibernation (aka 'suspend to disk')"
 	depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
diff --git a/kernel/power/main.c b/kernel/power/main.c
index ab9fc7f..e2aae3e 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -479,6 +479,7 @@ struct kobject *power_kobj;
  *	proper enumerated value, and initiates a suspend transition.
  */
 
+#ifndef CONFIG_DISABLE_SYS_POWER_STATE
 static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
 			  char *buf)
 {
@@ -542,6 +543,7 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
 }
 
 power_attr(state);
+#endif
 
 #ifdef CONFIG_PM_TRACE
 int pm_trace_enabled;
@@ -569,7 +571,9 @@ power_attr(pm_trace);
 #endif /* CONFIG_PM_TRACE */
 
 static struct attribute * g[] = {
+#ifndef CONFIG_DISABLE_SYS_POWER_STATE
 	&state_attr.attr,
+#endif
 #ifdef CONFIG_PM_TRACE
 	&pm_trace_attr.attr,
 #endif
-- 
1.6.1

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply related	[flat|nested] 251+ messages in thread

* [PATCH 06/13] PM: Implement early suspend api
  2009-02-05  2:50         ` [PATCH 05/13] PM: Add option to disable /sys/power/state interface Arve Hjønnevåg
@ 2009-02-05  2:50           ` Arve Hjønnevåg
  2009-02-05  2:50             ` [PATCH 07/13] PM: wakelock: Add /sys/power/request_state Arve Hjønnevåg
                               ` (2 more replies)
  2009-02-05  9:17           ` [PATCH 05/13] PM: Add option to disable /sys/power/state interface Pavel Machek
  2009-02-07 22:37           ` Rafael J. Wysocki
  2 siblings, 3 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  2:50 UTC (permalink / raw)
  To: linux-pm; +Cc: ncunningham, u.luckas, swetland

Signed-off-by: Arve Hjønnevåg <arve@android.com>
---
 kernel/power/Kconfig        |   12 +++
 kernel/power/Makefile       |    1 +
 kernel/power/earlysuspend.c |  178 +++++++++++++++++++++++++++++++++++++++++++
 kernel/power/power.h        |    6 ++
 4 files changed, 197 insertions(+), 0 deletions(-)
 create mode 100644 kernel/power/earlysuspend.c

diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index dd76467..689abfe 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -119,6 +119,9 @@ config SUSPEND_FREEZER
 config HAS_WAKELOCK
 	bool
 
+config HAS_EARLYSUSPEND
+	bool
+
 config WAKELOCK
 	bool "Wake lock"
 	depends on PM && RTC_CLASS
@@ -144,6 +147,15 @@ config DISABLE_SYS_POWER_STATE
 	  want to run user-space code that does not support wakelocks, do not
 	  enable this option since it removes the interface.
 
+config EARLYSUSPEND
+	bool "Early suspend"
+	depends on WAKELOCK
+	default y
+	select HAS_EARLYSUSPEND
+	---help---
+	  Call early suspend handlers when the user requested sleep state
+	  changes.
+
 config HIBERNATION
 	bool "Hibernation (aka 'suspend to disk')"
 	depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index 8d8672b..2f17e1d 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -7,6 +7,7 @@ obj-y				:= main.o
 obj-$(CONFIG_PM_SLEEP)		+= console.o
 obj-$(CONFIG_FREEZER)		+= process.o
 obj-$(CONFIG_WAKELOCK)		+= wakelock.o
+obj-$(CONFIG_EARLYSUSPEND)	+= earlysuspend.o
 obj-$(CONFIG_HIBERNATION)	+= swsusp.o disk.o snapshot.o swap.o user.o
 
 obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
diff --git a/kernel/power/earlysuspend.c b/kernel/power/earlysuspend.c
new file mode 100644
index 0000000..4d70a7e
--- /dev/null
+++ b/kernel/power/earlysuspend.c
@@ -0,0 +1,178 @@
+/* kernel/power/earlysuspend.c
+ *
+ * Copyright (C) 2005-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.
+ *
+ */
+
+#include <linux/earlysuspend.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/rtc.h>
+#include <linux/syscalls.h> /* sys_sync */
+#include <linux/wakelock.h>
+#include <linux/workqueue.h>
+
+#include "power.h"
+
+enum {
+	DEBUG_USER_STATE = 1U << 0,
+	DEBUG_SUSPEND = 1U << 1,
+};
+static int debug_mask = DEBUG_USER_STATE;
+module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+static DEFINE_MUTEX(early_suspend_lock);
+static LIST_HEAD(early_suspend_handlers);
+static void early_suspend(struct work_struct *work);
+static void late_resume(struct work_struct *work);
+static DECLARE_WORK(early_suspend_work, early_suspend);
+static DECLARE_WORK(late_resume_work, late_resume);
+static DEFINE_SPINLOCK(state_lock);
+enum {
+	SUSPEND_REQUESTED = 0x1,
+	SUSPENDED = 0x2,
+	SUSPEND_REQUESTED_AND_SUSPENDED = SUSPEND_REQUESTED | SUSPENDED,
+};
+static int state;
+
+void register_early_suspend(struct early_suspend *handler)
+{
+	struct list_head *pos;
+
+	mutex_lock(&early_suspend_lock);
+	list_for_each(pos, &early_suspend_handlers) {
+		struct early_suspend *e;
+		e = list_entry(pos, struct early_suspend, link);
+		if (e->level > handler->level)
+			break;
+	}
+	list_add_tail(&handler->link, pos);
+	if ((state & SUSPENDED) && handler->suspend)
+		handler->suspend(handler);
+	mutex_unlock(&early_suspend_lock);
+}
+EXPORT_SYMBOL(register_early_suspend);
+
+void unregister_early_suspend(struct early_suspend *handler)
+{
+	mutex_lock(&early_suspend_lock);
+	list_del(&handler->link);
+	mutex_unlock(&early_suspend_lock);
+}
+EXPORT_SYMBOL(unregister_early_suspend);
+
+static void early_suspend(struct work_struct *work)
+{
+	struct early_suspend *pos;
+	unsigned long irqflags;
+	int abort = 0;
+
+	mutex_lock(&early_suspend_lock);
+	spin_lock_irqsave(&state_lock, irqflags);
+	if (state == SUSPEND_REQUESTED)
+		state |= SUSPENDED;
+	else
+		abort = 1;
+	spin_unlock_irqrestore(&state_lock, irqflags);
+
+	if (abort) {
+		if (debug_mask & DEBUG_SUSPEND)
+			pr_info("early_suspend: abort, state %d\n", state);
+		mutex_unlock(&early_suspend_lock);
+		goto abort;
+	}
+
+	if (debug_mask & DEBUG_SUSPEND)
+		pr_info("early_suspend: call handlers\n");
+	list_for_each_entry(pos, &early_suspend_handlers, link) {
+		if (pos->suspend)
+			pos->suspend(pos);
+	}
+	mutex_unlock(&early_suspend_lock);
+
+	if (debug_mask & DEBUG_SUSPEND)
+		pr_info("early_suspend: sync\n");
+
+	sys_sync();
+abort:
+	spin_lock_irqsave(&state_lock, irqflags);
+	if (state == SUSPEND_REQUESTED_AND_SUSPENDED)
+		wake_unlock(&main_wake_lock);
+	spin_unlock_irqrestore(&state_lock, irqflags);
+}
+
+static void late_resume(struct work_struct *work)
+{
+	struct early_suspend *pos;
+	unsigned long irqflags;
+	int abort = 0;
+
+	mutex_lock(&early_suspend_lock);
+	spin_lock_irqsave(&state_lock, irqflags);
+	if (state == SUSPENDED)
+		state = 0; /* clear SUSPENDED */
+	else
+		abort = 1;
+	spin_unlock_irqrestore(&state_lock, irqflags);
+
+	if (abort) {
+		if (debug_mask & DEBUG_SUSPEND)
+			pr_info("late_resume: abort, state %d\n", state);
+		goto abort;
+	}
+	if (debug_mask & DEBUG_SUSPEND)
+		pr_info("late_resume: call handlers\n");
+	list_for_each_entry_reverse(pos, &early_suspend_handlers, link)
+		if (pos->resume)
+			pos->resume(pos);
+	if (debug_mask & DEBUG_SUSPEND)
+		pr_info("late_resume: done\n");
+abort:
+	mutex_unlock(&early_suspend_lock);
+}
+
+void request_suspend_state(suspend_state_t new_state)
+{
+	unsigned long irqflags;
+	int old_sleep;
+
+	spin_lock_irqsave(&state_lock, irqflags);
+	old_sleep = state & SUSPEND_REQUESTED;
+	if (debug_mask & DEBUG_USER_STATE) {
+		struct timespec ts;
+		struct rtc_time tm;
+		getnstimeofday(&ts);
+		rtc_time_to_tm(ts.tv_sec, &tm);
+		pr_info("request_suspend_state: %s (%d->%d) at %lld "
+			"(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n",
+			new_state != PM_SUSPEND_ON ? "sleep" : "wakeup",
+			requested_suspend_state, new_state,
+			ktime_to_ns(ktime_get()),
+			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+			tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
+	}
+	if (!old_sleep && new_state != PM_SUSPEND_ON) {
+		state |= SUSPEND_REQUESTED;
+		queue_work(suspend_work_queue, &early_suspend_work);
+	} else if (old_sleep && new_state == PM_SUSPEND_ON) {
+		state &= ~SUSPEND_REQUESTED;
+		wake_lock(&main_wake_lock);
+		queue_work(suspend_work_queue, &late_resume_work);
+	}
+	requested_suspend_state = new_state;
+	spin_unlock_irqrestore(&state_lock, irqflags);
+}
+
+suspend_state_t get_suspend_state(void)
+{
+	return requested_suspend_state;
+}
diff --git a/kernel/power/power.h b/kernel/power/power.h
index ed1b7f4..acbb13a 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -231,3 +231,9 @@ extern struct wake_lock main_wake_lock;
 extern suspend_state_t requested_suspend_state;
 extern bool ignore_suspend_wakelocks;
 #endif
+
+#ifdef CONFIG_EARLYSUSPEND
+/* kernel/power/earlysuspend.c */
+void request_suspend_state(suspend_state_t state);
+suspend_state_t get_suspend_state(void);
+#endif
-- 
1.6.1

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply related	[flat|nested] 251+ messages in thread

* [PATCH 07/13] PM: wakelock: Add /sys/power/request_state
  2009-02-05  2:50           ` [PATCH 06/13] PM: Implement early suspend api Arve Hjønnevåg
@ 2009-02-05  2:50             ` Arve Hjønnevåg
  2009-02-05  2:50               ` [PATCH 08/13] PM: Add user-space wake lock api Arve Hjønnevåg
                                 ` (2 more replies)
  2009-02-06  0:18             ` [PATCH 06/13] PM: Implement early suspend api mark gross
  2009-02-07 22:47             ` Rafael J. Wysocki
  2 siblings, 3 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  2:50 UTC (permalink / raw)
  To: linux-pm; +Cc: ncunningham, u.luckas, swetland

This is a non-blocking interface that specifies which suspend state to
enter when no wakelocks are locked. A special state, "on", stops the
process by locking the "main" wakelock.

If early-suspend support is enabled, early suspend handlers will be called
when a state other than "on" is written. When writing "on", the corresonding
resume handlers are called.

Signed-off-by: Arve Hjønnevåg <arve@android.com>
---
 kernel/power/main.c |   74 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 74 insertions(+), 0 deletions(-)

diff --git a/kernel/power/main.c b/kernel/power/main.c
index e2aae3e..676a8b0 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -22,6 +22,7 @@
 #include <linux/freezer.h>
 #include <linux/vmstat.h>
 #include <linux/syscalls.h>
+#include <linux/wakelock.h>
 
 #include "power.h"
 
@@ -388,6 +389,9 @@ static void suspend_finish(void)
 
 
 static const char * const pm_states[PM_SUSPEND_MAX] = {
+#ifdef CONFIG_WAKELOCK
+	[PM_SUSPEND_ON]		= "on",
+#endif
 	[PM_SUSPEND_STANDBY]	= "standby",
 	[PM_SUSPEND_MEM]	= "mem",
 };
@@ -545,6 +549,73 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
 power_attr(state);
 #endif
 
+/**
+ *	request_state - control system power state.
+ *
+ *	This is similar to state, but it does not block until the system
+ *	resumes, and it will try to re-enter the state until another state is
+ *	requsted. Wakelocks are respected and the requested state will only
+ *	be entered when no wakelocks are held. Write "on" to cancel.
+ *
+ *	If CONFIG_EARLYSUSPEND is set, early_suspend hooks are called when
+ *	the requested state changes to or from "on"
+ */
+
+#ifdef CONFIG_WAKELOCK
+static ssize_t request_state_show(struct kobject *kobj, struct kobj_attribute *attr,
+			  char *buf)
+{
+	char *s = buf;
+	int i;
+
+	for (i = 0; i < PM_SUSPEND_MAX; i++) {
+		if (pm_states[i] && valid_state(i))
+			s += sprintf(s,"%s ", pm_states[i]);
+	}
+	if (s != buf)
+		/* convert the last space to a newline */
+		*(s-1) = '\n';
+	return (s - buf);
+}
+
+static ssize_t request_state_store(struct kobject *kobj, struct kobj_attribute *attr,
+			   const char *buf, size_t n)
+{
+	suspend_state_t state = PM_SUSPEND_ON;
+	const char * const *s;
+	char *p;
+	int len;
+	int error = -EINVAL;
+
+	p = memchr(buf, '\n', n);
+	len = p ? p - buf : n;
+
+	for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
+		if (*s && len == strlen(*s) && !strncmp(buf, *s, len))
+			break;
+	}
+	if (state < PM_SUSPEND_MAX && *s)
+		if (state == PM_SUSPEND_ON || valid_state(state)) {
+			error = 0;
+#ifdef CONFIG_EARLYSUSPEND
+			request_suspend_state(state);
+#else
+			if (!mutex_trylock(&pm_mutex))
+				return -EBUSY;
+			requested_suspend_state = state;
+			if (state == PM_SUSPEND_ON)
+				wake_lock(&main_wake_lock);
+			else
+				wake_unlock(&main_wake_lock);
+			mutex_unlock(&pm_mutex);
+#endif
+		}
+	return error ? error : n;
+}
+
+power_attr(request_state);
+#endif
+
 #ifdef CONFIG_PM_TRACE
 int pm_trace_enabled;
 
@@ -574,6 +645,9 @@ static struct attribute * g[] = {
 #ifndef CONFIG_DISABLE_SYS_POWER_STATE
 	&state_attr.attr,
 #endif
+#ifdef CONFIG_WAKELOCK
+	&request_state_attr.attr,
+#endif
 #ifdef CONFIG_PM_TRACE
 	&pm_trace_attr.attr,
 #endif
-- 
1.6.1

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply related	[flat|nested] 251+ messages in thread

* [PATCH 08/13] PM: Add user-space wake lock api.
  2009-02-05  2:50             ` [PATCH 07/13] PM: wakelock: Add /sys/power/request_state Arve Hjønnevåg
@ 2009-02-05  2:50               ` Arve Hjønnevåg
  2009-02-05  2:50                 ` [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held Arve Hjønnevåg
  2009-02-05  8:53                 ` [PATCH 08/13] PM: Add user-space wake lock api Pavel Machek
  2009-02-05  8:52               ` [PATCH 07/13] PM: wakelock: Add /sys/power/request_state Pavel Machek
  2009-02-07 22:54               ` Rafael J. Wysocki
  2 siblings, 2 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  2:50 UTC (permalink / raw)
  To: linux-pm; +Cc: ncunningham, u.luckas, swetland

This adds /sys/power/wake_lock and /sys/power/wake_unlock.
Writing a string to wake_lock creates a wake lock the
first time is sees a string and locks it. Optionally, the
string can be followed by a timeout.
To unlock the wake lock, write the same string to wake_unlock.

Signed-off-by: Arve Hjønnevåg <arve@android.com>
---
 kernel/power/Kconfig        |   10 ++
 kernel/power/Makefile       |    1 +
 kernel/power/main.c         |    9 ++
 kernel/power/power.h        |   11 ++
 kernel/power/userwakelock.c |  218 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 249 insertions(+), 0 deletions(-)
 create mode 100644 kernel/power/userwakelock.c

diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 689abfe..aedea7e 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -147,6 +147,16 @@ config DISABLE_SYS_POWER_STATE
 	  want to run user-space code that does not support wakelocks, do not
 	  enable this option since it removes the interface.
 
+config USER_WAKELOCK
+	bool "Userspace wake locks"
+	depends on WAKELOCK
+	default y
+	---help---
+	  User-space wake lock api. Write "lockname" or "lockname timeout"
+	  to /sys/power/wake_lock lock and if needed create a wake lock.
+	  Write "lockname" to /sys/power/wake_unlock to unlock a user wake
+	  lock.
+
 config EARLYSUSPEND
 	bool "Early suspend"
 	depends on WAKELOCK
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index 2f17e1d..d3467b3 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -7,6 +7,7 @@ obj-y				:= main.o
 obj-$(CONFIG_PM_SLEEP)		+= console.o
 obj-$(CONFIG_FREEZER)		+= process.o
 obj-$(CONFIG_WAKELOCK)		+= wakelock.o
+obj-$(CONFIG_USER_WAKELOCK)	+= userwakelock.o
 obj-$(CONFIG_EARLYSUSPEND)	+= earlysuspend.o
 obj-$(CONFIG_HIBERNATION)	+= swsusp.o disk.o snapshot.o swap.o user.o
 
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 676a8b0..a4065f3 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -641,6 +641,11 @@ pm_trace_store(struct kobject *kobj, struct kobj_attribute *attr,
 power_attr(pm_trace);
 #endif /* CONFIG_PM_TRACE */
 
+#ifdef CONFIG_USER_WAKELOCK
+power_attr(wake_lock);
+power_attr(wake_unlock);
+#endif
+
 static struct attribute * g[] = {
 #ifndef CONFIG_DISABLE_SYS_POWER_STATE
 	&state_attr.attr,
@@ -654,6 +659,10 @@ static struct attribute * g[] = {
 #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PM_DEBUG)
 	&pm_test_attr.attr,
 #endif
+#ifdef CONFIG_USER_WAKELOCK
+	&wake_lock_attr.attr,
+	&wake_unlock_attr.attr,
+#endif
 	NULL,
 };
 
diff --git a/kernel/power/power.h b/kernel/power/power.h
index acbb13a..1b01327 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -232,6 +232,17 @@ extern suspend_state_t requested_suspend_state;
 extern bool ignore_suspend_wakelocks;
 #endif
 
+#ifdef CONFIG_USER_WAKELOCK
+ssize_t wake_lock_show(struct kobject *kobj, struct kobj_attribute *attr,
+			char *buf);
+ssize_t wake_lock_store(struct kobject *kobj, struct kobj_attribute *attr,
+			const char *buf, size_t n);
+ssize_t wake_unlock_show(struct kobject *kobj, struct kobj_attribute *attr,
+			char *buf);
+ssize_t  wake_unlock_store(struct kobject *kobj, struct kobj_attribute *attr,
+			const char *buf, size_t n);
+#endif
+
 #ifdef CONFIG_EARLYSUSPEND
 /* kernel/power/earlysuspend.c */
 void request_suspend_state(suspend_state_t state);
diff --git a/kernel/power/userwakelock.c b/kernel/power/userwakelock.c
new file mode 100644
index 0000000..d7242d9
--- /dev/null
+++ b/kernel/power/userwakelock.c
@@ -0,0 +1,218 @@
+/* kernel/power/userwakelock.c
+ *
+ * Copyright (C) 2005-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.
+ *
+ */
+
+#include <linux/ctype.h>
+#include <linux/module.h>
+#include <linux/wakelock.h>
+
+#include "power.h"
+
+enum {
+	DEBUG_FAILURE	= BIT(0),
+	DEBUG_ERROR	= BIT(1),
+	DEBUG_NEW	= BIT(2),
+	DEBUG_ACCESS	= BIT(3),
+	DEBUG_LOOKUP	= BIT(4),
+};
+static int debug_mask = DEBUG_FAILURE;
+module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+static DEFINE_MUTEX(tree_lock);
+
+struct user_wake_lock {
+	struct rb_node		node;
+	struct wake_lock	wake_lock;
+	char			name[0];
+};
+struct rb_root user_wake_locks;
+
+static struct user_wake_lock *lookup_wake_lock_name(
+	const char *buf, int allocate, long *timeoutptr)
+{
+	struct rb_node **p = &user_wake_locks.rb_node;
+	struct rb_node *parent = NULL;
+	struct user_wake_lock *l;
+	int diff;
+	u64 timeout;
+	int name_len;
+	const char *arg;
+
+	/* Find length of lock name and start of optional timeout string */
+	arg = buf;
+	while (*arg && !isspace(*arg))
+		arg++;
+	name_len = arg - buf;
+	if (!name_len)
+		goto bad_arg;
+	while (isspace(*arg))
+		arg++;
+
+	/* Process timeout string */
+	if (timeoutptr && *arg) {
+		timeout = simple_strtoull(arg, (char **)&arg, 0);
+		while (isspace(*arg))
+			arg++;
+		if (*arg)
+			goto bad_arg;
+		/* convert timeout from nanoseconds to jiffies > 0 */
+		timeout += (NSEC_PER_SEC / HZ) - 1;
+		do_div(timeout, (NSEC_PER_SEC / HZ));
+		if (timeout <= 0)
+			timeout = 1;
+		*timeoutptr = timeout;
+	} else if (*arg)
+		goto bad_arg;
+	else if (timeoutptr)
+		*timeoutptr = 0;
+
+	/* Lookup wake lock in rbtree */
+	while (*p) {
+		parent = *p;
+		l = rb_entry(parent, struct user_wake_lock, node);
+		diff = strncmp(buf, l->name, name_len);
+		if (!diff && l->name[name_len])
+			diff = -1;
+		if (debug_mask & DEBUG_ERROR)
+			pr_info("lookup_wake_lock_name: compare %.*s %s %d\n",
+				name_len, buf, l->name, diff);
+
+		if (diff < 0)
+			p = &(*p)->rb_left;
+		else if (diff > 0)
+			p = &(*p)->rb_right;
+		else
+			return l;
+	}
+
+	/* Allocate and add new wakelock to rbtree */
+	if (!allocate) {
+		if (debug_mask & DEBUG_ERROR)
+			pr_info("lookup_wake_lock_name: %.*s not found\n",
+				name_len, buf);
+		return ERR_PTR(-EINVAL);
+	}
+	l = kzalloc(sizeof(*l) + name_len + 1, GFP_KERNEL);
+	if (l == NULL) {
+		if (debug_mask & DEBUG_FAILURE)
+			pr_err("lookup_wake_lock_name: failed to allocate "
+				"memory for %.*s\n", name_len, buf);
+		return ERR_PTR(-ENOMEM);
+	}
+	memcpy(l->name, buf, name_len);
+	if (debug_mask & DEBUG_NEW)
+		pr_info("lookup_wake_lock_name: new wake lock %s\n", l->name);
+	wake_lock_init(&l->wake_lock, WAKE_LOCK_SUSPEND, l->name);
+	rb_link_node(&l->node, parent, p);
+	rb_insert_color(&l->node, &user_wake_locks);
+	return l;
+
+bad_arg:
+	if (debug_mask & DEBUG_ERROR)
+		pr_info("lookup_wake_lock_name: wake lock, %.*s, bad arg, %s\n",
+			name_len, buf, arg);
+	return ERR_PTR(-EINVAL);
+}
+
+ssize_t wake_lock_show(
+	struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	char *s = buf;
+	char *end = buf + PAGE_SIZE;
+	struct rb_node *n;
+	struct user_wake_lock *l;
+
+	mutex_lock(&tree_lock);
+
+	for (n = rb_first(&user_wake_locks); n != NULL; n = rb_next(n)) {
+		l = rb_entry(n, struct user_wake_lock, node);
+		if (wake_lock_active(&l->wake_lock))
+			s += scnprintf(s, end - s, "%s ", l->name);
+	}
+	s += scnprintf(s, end - s, "\n");
+
+	mutex_unlock(&tree_lock);
+	return (s - buf);
+}
+
+ssize_t wake_lock_store(
+	struct kobject *kobj, struct kobj_attribute *attr,
+	const char *buf, size_t n)
+{
+	long timeout;
+	struct user_wake_lock *l;
+
+	mutex_lock(&tree_lock);
+	l = lookup_wake_lock_name(buf, 1, &timeout);
+	if (IS_ERR(l)) {
+		n = PTR_ERR(l);
+		goto bad_name;
+	}
+
+	if (debug_mask & DEBUG_ACCESS)
+		pr_info("wake_lock_store: %s, timeout %ld\n", l->name, timeout);
+
+	if (timeout)
+		wake_lock_timeout(&l->wake_lock, timeout);
+	else
+		wake_lock(&l->wake_lock);
+bad_name:
+	mutex_unlock(&tree_lock);
+	return n;
+}
+
+
+ssize_t wake_unlock_show(
+	struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	char *s = buf;
+	char *end = buf + PAGE_SIZE;
+	struct rb_node *n;
+	struct user_wake_lock *l;
+
+	mutex_lock(&tree_lock);
+
+	for (n = rb_first(&user_wake_locks); n != NULL; n = rb_next(n)) {
+		l = rb_entry(n, struct user_wake_lock, node);
+		if (!wake_lock_active(&l->wake_lock))
+			s += scnprintf(s, end - s, "%s ", l->name);
+	}
+	s += scnprintf(s, end - s, "\n");
+
+	mutex_unlock(&tree_lock);
+	return (s - buf);
+}
+
+ssize_t wake_unlock_store(
+	struct kobject *kobj, struct kobj_attribute *attr,
+	const char *buf, size_t n)
+{
+	struct user_wake_lock *l;
+
+	mutex_lock(&tree_lock);
+	l = lookup_wake_lock_name(buf, 0, NULL);
+	if (IS_ERR(l)) {
+		n = PTR_ERR(l);
+		goto not_found;
+	}
+
+	if (debug_mask & DEBUG_ACCESS)
+		pr_info("wake_unlock_store: %s\n", l->name);
+
+	wake_unlock(&l->wake_lock);
+not_found:
+	mutex_unlock(&tree_lock);
+	return n;
+}
+
-- 
1.6.1

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply related	[flat|nested] 251+ messages in thread

* [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held.
  2009-02-05  2:50               ` [PATCH 08/13] PM: Add user-space wake lock api Arve Hjønnevåg
@ 2009-02-05  2:50                 ` Arve Hjønnevåg
  2009-02-05  2:50                   ` [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes Arve Hjønnevåg
                                     ` (2 more replies)
  2009-02-05  8:53                 ` [PATCH 08/13] PM: Add user-space wake lock api Pavel Machek
  1 sibling, 3 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  2:50 UTC (permalink / raw)
  To: linux-pm; +Cc: ncunningham, u.luckas, swetland

Avoids a problem where the device sometimes hangs for 20 seconds
before the screen is turned on.

Signed-off-by: Arve Hjønnevåg <arve@android.com>
---
 kernel/power/process.c |   22 +++++++++++++++++-----
 1 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/kernel/power/process.c b/kernel/power/process.c
index ca63401..8388d01 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/syscalls.h>
 #include <linux/freezer.h>
+#include <linux/wakelock.h>
 
 /* 
  * Timeout for stopping processes
@@ -36,6 +37,7 @@ static int try_to_freeze_tasks(bool sig_only)
 	struct timeval start, end;
 	u64 elapsed_csecs64;
 	unsigned int elapsed_csecs;
+	unsigned int wakeup = 0;
 
 	do_gettimeofday(&start);
 
@@ -62,6 +64,10 @@ static int try_to_freeze_tasks(bool sig_only)
 		} while_each_thread(g, p);
 		read_unlock(&tasklist_lock);
 		yield();			/* Yield is okay here */
+		if (todo && has_wake_lock(WAKE_LOCK_SUSPEND)) {
+			wakeup = 1;
+			break;
+		}
 		if (time_after(jiffies, end_time))
 			break;
 	} while (todo);
@@ -77,11 +83,17 @@ static int try_to_freeze_tasks(bool sig_only)
 		 * and caller must call thaw_processes() if something fails),
 		 * but it cleans up leftover PF_FREEZE requests.
 		 */
-		printk("\n");
-		printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds "
-				"(%d tasks refusing to freeze):\n",
-				elapsed_csecs / 100, elapsed_csecs % 100, todo);
-		show_state();
+		if (wakeup) {
+			printk("\n");
+			printk(KERN_ERR "Freezing of %s aborted\n",
+					sig_only ? "user space " : "tasks ");
+		} else {
+			printk("\n");
+			printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds "
+					"(%d tasks refusing to freeze):\n",
+					elapsed_csecs / 100, elapsed_csecs % 100, todo);
+			show_state();
+		}
 		read_lock(&tasklist_lock);
 		do_each_thread(g, p) {
 			task_lock(p);
-- 
1.6.1

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply related	[flat|nested] 251+ messages in thread

* [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes.
  2009-02-05  2:50                 ` [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held Arve Hjønnevåg
@ 2009-02-05  2:50                   ` Arve Hjønnevåg
  2009-02-05  2:50                     ` [PATCH 11/13] PM: earlysuspend: Removing dependence on console Arve Hjønnevåg
  2009-02-05  9:03                     ` [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes Pavel Machek
  2009-02-05  8:55                   ` [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held Pavel Machek
  2009-02-06  0:35                   ` mark gross
  2 siblings, 2 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  2:50 UTC (permalink / raw)
  To: linux-pm; +Cc: ncunningham, u.luckas, swetland

Signed-off-by: Arve Hjønnevåg <arve@android.com>
---
 kernel/power/Kconfig               |   17 ++++++++
 kernel/power/Makefile              |    1 +
 kernel/power/consoleearlysuspend.c |   78 ++++++++++++++++++++++++++++++++++++
 3 files changed, 96 insertions(+), 0 deletions(-)
 create mode 100644 kernel/power/consoleearlysuspend.c

diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index aedea7e..f1a3d5c 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -166,6 +166,23 @@ config EARLYSUSPEND
 	  Call early suspend handlers when the user requested sleep state
 	  changes.
 
+choice
+	prompt "User-space screen access"
+	default CONSOLE_EARLYSUSPEND
+	depends on HAS_EARLYSUSPEND
+
+	config NO_USER_SPACE_SCREEN_ACCESS_CONTROL
+		bool "None"
+
+	config CONSOLE_EARLYSUSPEND
+		bool "Console switch on early-suspend"
+		depends on HAS_EARLYSUSPEND && VT
+		---help---
+		  Register early suspend handler to perform a console switch to
+		  when user-space should stop drawing to the screen and a switch
+		  back when it should resume.
+endchoice
+
 config HIBERNATION
 	bool "Hibernation (aka 'suspend to disk')"
 	depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index d3467b3..8bf293d 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_FREEZER)		+= process.o
 obj-$(CONFIG_WAKELOCK)		+= wakelock.o
 obj-$(CONFIG_USER_WAKELOCK)	+= userwakelock.o
 obj-$(CONFIG_EARLYSUSPEND)	+= earlysuspend.o
+obj-$(CONFIG_CONSOLE_EARLYSUSPEND)	+= consoleearlysuspend.o
 obj-$(CONFIG_HIBERNATION)	+= swsusp.o disk.o snapshot.o swap.o user.o
 
 obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
diff --git a/kernel/power/consoleearlysuspend.c b/kernel/power/consoleearlysuspend.c
new file mode 100644
index 0000000..a8befb4
--- /dev/null
+++ b/kernel/power/consoleearlysuspend.c
@@ -0,0 +1,78 @@
+/* kernel/power/consoleearlysuspend.c
+ *
+ * Copyright (C) 2005-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.
+ *
+ */
+
+#include <linux/console.h>
+#include <linux/earlysuspend.h>
+#include <linux/kbd_kern.h>
+#include <linux/module.h>
+#include <linux/vt_kern.h>
+#include <linux/wait.h>
+
+#define EARLY_SUSPEND_CONSOLE	(MAX_NR_CONSOLES-1)
+
+static int orig_fgconsole;
+static void console_early_suspend(struct early_suspend *h)
+{
+	acquire_console_sem();
+	orig_fgconsole = fg_console;
+	if (vc_allocate(EARLY_SUSPEND_CONSOLE))
+		goto err;
+	if (set_console(EARLY_SUSPEND_CONSOLE))
+		goto err;
+	release_console_sem();
+
+	if (vt_waitactive(EARLY_SUSPEND_CONSOLE))
+		pr_warning("console_early_suspend: Can't switch VCs.\n");
+	return;
+err:
+	pr_warning("console_early_suspend: Can't set console\n");
+	release_console_sem();
+}
+
+static void console_late_resume(struct early_suspend *h)
+{
+	int ret;
+	acquire_console_sem();
+	ret = set_console(orig_fgconsole);
+	release_console_sem();
+	if (ret) {
+		pr_warning("console_late_resume: Can't set console.\n");
+		return;
+	}
+
+	if (vt_waitactive(orig_fgconsole))
+		pr_warning("console_late_resume: Can't switch VCs.\n");
+}
+
+static struct early_suspend console_early_suspend_desc = {
+	.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING,
+	.suspend = console_early_suspend,
+	.resume = console_late_resume,
+};
+
+static int __init console_early_suspend_init(void)
+{
+	register_early_suspend(&console_early_suspend_desc);
+	return 0;
+}
+
+static void  __exit console_early_suspend_exit(void)
+{
+	unregister_early_suspend(&console_early_suspend_desc);
+}
+
+module_init(console_early_suspend_init);
+module_exit(console_early_suspend_exit);
+
-- 
1.6.1

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply related	[flat|nested] 251+ messages in thread

* [PATCH 11/13] PM: earlysuspend: Removing dependence on console.
  2009-02-05  2:50                   ` [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes Arve Hjønnevåg
@ 2009-02-05  2:50                     ` Arve Hjønnevåg
  2009-02-05  2:50                       ` [PATCH 12/13] Input: Hold wake lock while event queue is not empty Arve Hjønnevåg
  2009-02-05  9:06                       ` [PATCH 11/13] PM: earlysuspend: Removing dependence on console Pavel Machek
  2009-02-05  9:03                     ` [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes Pavel Machek
  1 sibling, 2 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  2:50 UTC (permalink / raw)
  To: linux-pm; +Cc: ncunningham, u.luckas, swetland, Rebecca Schultz

From: Rebecca Schultz <rschultz@google.com>

Rather than signaling a full update of the display from userspace via a
console switch, this patch introduces 2 files int /sys/power,
wait_for_fb_sleep and wait_for_fb_wake.  Reading these files will block
until the requested state has been entered.  When a read from
wait_for_fb_sleep returns userspace should stop drawing.  When
wait_for_fb_wake returns, it should do a full update.  If either are called
when the fb driver is already in the requested state, they will return
immediately.

Signed-off-by: Rebecca Schultz <rschultz@google.com>
Signed-off-by: Arve Hjønnevåg <arve@android.com>
---
 kernel/power/Kconfig          |    9 +++
 kernel/power/Makefile         |    1 +
 kernel/power/fbearlysuspend.c |  153 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 163 insertions(+), 0 deletions(-)
 create mode 100644 kernel/power/fbearlysuspend.c

diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index f1a3d5c..616341d 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -168,6 +168,7 @@ config EARLYSUSPEND
 
 choice
 	prompt "User-space screen access"
+	default FB_EARLYSUSPEND if !FRAMEBUFFER_CONSOLE
 	default CONSOLE_EARLYSUSPEND
 	depends on HAS_EARLYSUSPEND
 
@@ -181,6 +182,14 @@ choice
 		  Register early suspend handler to perform a console switch to
 		  when user-space should stop drawing to the screen and a switch
 		  back when it should resume.
+
+	config FB_EARLYSUSPEND
+		bool "Sysfs interface"
+		depends on HAS_EARLYSUSPEND
+		---help---
+		  Register early suspend handler that notifies and waits for
+		  user-space through sysfs when user-space should stop drawing
+		  to the screen and notifies user-space when it should resume.
 endchoice
 
 config HIBERNATION
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index 8bf293d..5beaa21 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_WAKELOCK)		+= wakelock.o
 obj-$(CONFIG_USER_WAKELOCK)	+= userwakelock.o
 obj-$(CONFIG_EARLYSUSPEND)	+= earlysuspend.o
 obj-$(CONFIG_CONSOLE_EARLYSUSPEND)	+= consoleearlysuspend.o
+obj-$(CONFIG_FB_EARLYSUSPEND)	+= fbearlysuspend.o
 obj-$(CONFIG_HIBERNATION)	+= swsusp.o disk.o snapshot.o swap.o user.o
 
 obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
diff --git a/kernel/power/fbearlysuspend.c b/kernel/power/fbearlysuspend.c
new file mode 100644
index 0000000..1513765
--- /dev/null
+++ b/kernel/power/fbearlysuspend.c
@@ -0,0 +1,153 @@
+/* kernel/power/fbearlysuspend.c
+ *
+ * Copyright (C) 2005-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.
+ *
+ */
+
+#include <linux/earlysuspend.h>
+#include <linux/module.h>
+#include <linux/wait.h>
+
+#include "power.h"
+
+static wait_queue_head_t fb_state_wq;
+static DEFINE_SPINLOCK(fb_state_lock);
+static enum {
+	FB_STATE_STOPPED_DRAWING,
+	FB_STATE_REQUEST_STOP_DRAWING,
+	FB_STATE_DRAWING_OK,
+} fb_state;
+
+/* tell userspace to stop drawing, wait for it to stop */
+static void stop_drawing_early_suspend(struct early_suspend *h)
+{
+	int ret;
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&fb_state_lock, irq_flags);
+	fb_state = FB_STATE_REQUEST_STOP_DRAWING;
+	spin_unlock_irqrestore(&fb_state_lock, irq_flags);
+
+	wake_up_all(&fb_state_wq);
+	ret = wait_event_timeout(fb_state_wq,
+				 fb_state == FB_STATE_STOPPED_DRAWING,
+				 HZ);
+	if (unlikely(fb_state != FB_STATE_STOPPED_DRAWING))
+		pr_warning("stop_drawing_early_suspend: timeout waiting for "
+			   "userspace to stop drawing\n");
+}
+
+/* tell userspace to start drawing */
+static void start_drawing_late_resume(struct early_suspend *h)
+{
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&fb_state_lock, irq_flags);
+	fb_state = FB_STATE_DRAWING_OK;
+	spin_unlock_irqrestore(&fb_state_lock, irq_flags);
+	wake_up(&fb_state_wq);
+}
+
+static struct early_suspend stop_drawing_early_suspend_desc = {
+	.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING,
+	.suspend = stop_drawing_early_suspend,
+	.resume = start_drawing_late_resume,
+};
+
+static ssize_t wait_for_fb_sleep_show(struct kobject *kobj,
+				      struct kobj_attribute *attr, char *buf)
+{
+	char *s = buf;
+	int ret;
+
+	ret = wait_event_interruptible(fb_state_wq,
+				       fb_state != FB_STATE_DRAWING_OK);
+	if (ret && fb_state == FB_STATE_DRAWING_OK)
+		return ret;
+	else
+		s += sprintf(buf, "sleeping");
+	return s - buf;
+}
+
+static ssize_t wait_for_fb_wake_show(struct kobject *kobj,
+				     struct kobj_attribute *attr, char *buf)
+{
+	char *s = buf;
+	int ret;
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&fb_state_lock, irq_flags);
+	if (fb_state == FB_STATE_REQUEST_STOP_DRAWING) {
+		fb_state = FB_STATE_STOPPED_DRAWING;
+		wake_up(&fb_state_wq);
+	}
+	spin_unlock_irqrestore(&fb_state_lock, irq_flags);
+
+	ret = wait_event_interruptible(fb_state_wq,
+				       fb_state == FB_STATE_DRAWING_OK);
+	if (ret && fb_state != FB_STATE_DRAWING_OK)
+		return ret;
+	else
+		s += sprintf(buf, "awake");
+
+	return s - buf;
+}
+
+#define power_ro_attr(_name) \
+static struct kobj_attribute _name##_attr = {	\
+	.attr	= {				\
+		.name = __stringify(_name),	\
+		.mode = 0444,			\
+	},					\
+	.show	= _name##_show,			\
+	.store	= NULL,		\
+}
+
+power_ro_attr(wait_for_fb_sleep);
+power_ro_attr(wait_for_fb_wake);
+
+static struct attribute *g[] = {
+	&wait_for_fb_sleep_attr.attr,
+	&wait_for_fb_wake_attr.attr,
+	NULL,
+};
+
+static struct attribute_group attr_group = {
+	.attrs = g,
+};
+
+static int __init android_power_init(void)
+{
+	int ret;
+
+	init_waitqueue_head(&fb_state_wq);
+	fb_state = FB_STATE_DRAWING_OK;
+
+	ret = sysfs_create_group(power_kobj, &attr_group);
+	if (ret) {
+		pr_err("android_power_init: sysfs_create_group failed\n");
+		return ret;
+	}
+
+	register_early_suspend(&stop_drawing_early_suspend_desc);
+	return 0;
+}
+
+static void  __exit android_power_exit(void)
+{
+	unregister_early_suspend(&stop_drawing_early_suspend_desc);
+	sysfs_remove_group(power_kobj, &attr_group);
+}
+
+module_init(android_power_init);
+module_exit(android_power_exit);
+
-- 
1.6.1

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply related	[flat|nested] 251+ messages in thread

* [PATCH 12/13] Input: Hold wake lock while event queue is not empty.
  2009-02-05  2:50                     ` [PATCH 11/13] PM: earlysuspend: Removing dependence on console Arve Hjønnevåg
@ 2009-02-05  2:50                       ` Arve Hjønnevåg
  2009-02-05  2:50                         ` [PATCH 13/13] ledtrig-sleep: Add led trigger for sleep debugging Arve Hjønnevåg
  2009-02-05  9:08                         ` [PATCH 12/13] Input: Hold wake lock while event queue is not empty Pavel Machek
  2009-02-05  9:06                       ` [PATCH 11/13] PM: earlysuspend: Removing dependence on console Pavel Machek
  1 sibling, 2 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  2:50 UTC (permalink / raw)
  To: linux-pm; +Cc: ncunningham, u.luckas, swetland

Allows userspace code to process input events while
the device appears to be asleep.

Signed-off-by: Arve Hjønnevåg <arve@android.com>
---
 drivers/input/evdev.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index ed8baa0..e24050b 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -19,6 +19,7 @@
 #include <linux/input.h>
 #include <linux/major.h>
 #include <linux/device.h>
+#include <linux/wakelock.h>
 #include "input-compat.h"
 
 struct evdev {
@@ -43,6 +44,7 @@ struct evdev_client {
 	struct fasync_struct *fasync;
 	struct evdev *evdev;
 	struct list_head node;
+	struct wake_lock wake_lock;
 };
 
 static struct evdev *evdev_table[EVDEV_MINORS];
@@ -55,6 +57,7 @@ static void evdev_pass_event(struct evdev_client *client,
 	 * Interrupts are disabled, just acquire the lock
 	 */
 	spin_lock(&client->buffer_lock);
+	wake_lock_timeout(&client->wake_lock, 5 * HZ);
 	client->buffer[client->head++] = *event;
 	client->head &= EVDEV_BUFFER_SIZE - 1;
 	spin_unlock(&client->buffer_lock);
@@ -236,6 +239,7 @@ static int evdev_release(struct inode *inode, struct file *file)
 	mutex_unlock(&evdev->mutex);
 
 	evdev_detach_client(evdev, client);
+	wake_lock_destroy(&client->wake_lock);
 	kfree(client);
 
 	evdev_close_device(evdev);
@@ -272,6 +276,7 @@ static int evdev_open(struct inode *inode, struct file *file)
 	}
 
 	spin_lock_init(&client->buffer_lock);
+	wake_lock_init(&client->wake_lock, WAKE_LOCK_SUSPEND, "evdev");
 	client->evdev = evdev;
 	evdev_attach_client(evdev, client);
 
@@ -335,6 +340,8 @@ static int evdev_fetch_next_event(struct evdev_client *client,
 	if (have_event) {
 		*event = client->buffer[client->tail++];
 		client->tail &= EVDEV_BUFFER_SIZE - 1;
+		if (client->head == client->tail)
+			wake_unlock(&client->wake_lock);
 	}
 
 	spin_unlock_irq(&client->buffer_lock);
-- 
1.6.1

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply related	[flat|nested] 251+ messages in thread

* [PATCH 13/13] ledtrig-sleep: Add led trigger for sleep debugging.
  2009-02-05  2:50                       ` [PATCH 12/13] Input: Hold wake lock while event queue is not empty Arve Hjønnevåg
@ 2009-02-05  2:50                         ` Arve Hjønnevåg
  2009-02-05  9:08                         ` [PATCH 12/13] Input: Hold wake lock while event queue is not empty Pavel Machek
  1 sibling, 0 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  2:50 UTC (permalink / raw)
  To: linux-pm; +Cc: ncunningham, u.luckas, swetland

Signed-off-by: Brian Swetland <swetland@google.com>
Signed-off-by: Arve Hjønnevåg <arve@android.com>
---
 drivers/leds/Kconfig         |    6 +++
 drivers/leds/Makefile        |    1 +
 drivers/leds/ledtrig-sleep.c |   80 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 87 insertions(+), 0 deletions(-)
 create mode 100644 drivers/leds/ledtrig-sleep.c

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 7427136..0af1786 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -223,4 +223,10 @@ config LEDS_TRIGGER_DEFAULT_ON
 	  This allows LEDs to be initialised in the ON state.
 	  If unsure, say Y.
 
+config LEDS_TRIGGER_SLEEP
+	tristate "LED Sleep Mode Trigger"
+	depends on LEDS_TRIGGERS && HAS_EARLYSUSPEND
+	help
+	  This turns LEDs on when the screen is off but the cpu still running.
+
 endif # NEW_LEDS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 9d76f0f..9cfc148 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -31,3 +31,4 @@ obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK)	+= ledtrig-ide-disk.o
 obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT)	+= ledtrig-heartbeat.o
 obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT)	+= ledtrig-backlight.o
 obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)	+= ledtrig-default-on.o
+obj-$(CONFIG_LEDS_TRIGGER_SLEEP)	+= ledtrig-sleep.o
diff --git a/drivers/leds/ledtrig-sleep.c b/drivers/leds/ledtrig-sleep.c
new file mode 100644
index 0000000..f164042
--- /dev/null
+++ b/drivers/leds/ledtrig-sleep.c
@@ -0,0 +1,80 @@
+/* drivers/leds/ledtrig-sleep.c
+ *
+ * Copyright (C) 2007 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.
+ *
+ */
+
+#include <linux/earlysuspend.h>
+#include <linux/leds.h>
+#include <linux/suspend.h>
+
+static int ledtrig_sleep_pm_callback(struct notifier_block *nfb,
+					unsigned long action,
+					void *ignored);
+
+DEFINE_LED_TRIGGER(ledtrig_sleep)
+static struct notifier_block ledtrig_sleep_pm_notifier = {
+	.notifier_call = ledtrig_sleep_pm_callback,
+	.priority = 0,
+};
+
+static void ledtrig_sleep_early_suspend(struct early_suspend *h)
+{
+	led_trigger_event(ledtrig_sleep, LED_FULL);
+}
+
+static void ledtrig_sleep_early_resume(struct early_suspend *h)
+{
+	led_trigger_event(ledtrig_sleep, LED_OFF);
+}
+
+static struct early_suspend ledtrig_sleep_early_suspend_handler = {
+	.suspend = ledtrig_sleep_early_suspend,
+	.resume = ledtrig_sleep_early_resume,
+};
+
+static int ledtrig_sleep_pm_callback(struct notifier_block *nfb,
+					unsigned long action,
+					void *ignored)
+{
+	switch (action) {
+	case PM_HIBERNATION_PREPARE:
+	case PM_SUSPEND_PREPARE:
+		led_trigger_event(ledtrig_sleep, LED_OFF);
+		return NOTIFY_OK;
+	case PM_POST_HIBERNATION:
+	case PM_POST_SUSPEND:
+		led_trigger_event(ledtrig_sleep, LED_FULL);
+		return NOTIFY_OK;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static int __init ledtrig_sleep_init(void)
+{
+	led_trigger_register_simple("sleep", &ledtrig_sleep);
+	register_pm_notifier(&ledtrig_sleep_pm_notifier);
+	register_early_suspend(&ledtrig_sleep_early_suspend_handler);
+	return 0;
+}
+
+static void __exit ledtrig_sleep_exit(void)
+{
+	unregister_early_suspend(&ledtrig_sleep_early_suspend_handler);
+	unregister_pm_notifier(&ledtrig_sleep_pm_notifier);
+	led_trigger_unregister_simple(ledtrig_sleep);
+}
+
+module_init(ledtrig_sleep_init);
+module_exit(ledtrig_sleep_exit);
+
-- 
1.6.1

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply related	[flat|nested] 251+ messages in thread

* Re: [PATCH 07/13] PM: wakelock: Add /sys/power/request_state
  2009-02-05  2:50             ` [PATCH 07/13] PM: wakelock: Add /sys/power/request_state Arve Hjønnevåg
  2009-02-05  2:50               ` [PATCH 08/13] PM: Add user-space wake lock api Arve Hjønnevåg
@ 2009-02-05  8:52               ` Pavel Machek
  2009-02-05  9:25                 ` Arve Hjønnevåg
  2009-02-07 22:54               ` Rafael J. Wysocki
  2 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-05  8:52 UTC (permalink / raw)
  To: Arve Hj??nnev??g; +Cc: ncunningham, u.luckas, swetland, linux-pm

Hi!

> This is a non-blocking interface that specifies which suspend state to
> enter when no wakelocks are locked. A special state, "on", stops the
> process by locking the "main" wakelock.
> 
> If early-suspend support is enabled, early suspend handlers will be called
> when a state other than "on" is written. When writing "on", the corresonding
> resume handlers are called.

> @@ -388,6 +389,9 @@ static void suspend_finish(void)
>  
>  
>  static const char * const pm_states[PM_SUSPEND_MAX] = {
> +#ifdef CONFIG_WAKELOCK
> +	[PM_SUSPEND_ON]		= "on",
> +#endif
>  	[PM_SUSPEND_STANDBY]	= "standby",
>  	[PM_SUSPEND_MEM]	= "mem",
>  };

By doing this you change /sys/power/state interface. I do not think
you want to do that.
							Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 08/13] PM: Add user-space wake lock api.
  2009-02-05  2:50               ` [PATCH 08/13] PM: Add user-space wake lock api Arve Hjønnevåg
  2009-02-05  2:50                 ` [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held Arve Hjønnevåg
@ 2009-02-05  8:53                 ` Pavel Machek
  1 sibling, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-05  8:53 UTC (permalink / raw)
  To: Arve Hj??nnev??g; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Wed 2009-02-04 18:50:21, Arve Hj??nnev??g wrote:
> This adds /sys/power/wake_lock and /sys/power/wake_unlock.
> Writing a string to wake_lock creates a wake lock the
> first time is sees a string and locks it. Optionally, the
> string can be followed by a timeout.
> To unlock the wake lock, write the same string to wake_unlock.

As discussed before, this interface is pretty ugly.
								Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held.
  2009-02-05  2:50                 ` [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held Arve Hjønnevåg
  2009-02-05  2:50                   ` [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes Arve Hjønnevåg
@ 2009-02-05  8:55                   ` Pavel Machek
  2009-02-05  9:30                     ` Arve Hjønnevåg
  2009-02-06  0:35                   ` mark gross
  2 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-05  8:55 UTC (permalink / raw)
  To: Arve Hj??nnev??g; +Cc: ncunningham, u.luckas, swetland, linux-pm

Hi!

> Avoids a problem where the device sometimes hangs for 20 seconds
> before the screen is turned on.

Fix the problem rather than working around it.

> @@ -62,6 +64,10 @@ static int try_to_freeze_tasks(bool sig_only)
>  		} while_each_thread(g, p);
>  		read_unlock(&tasklist_lock);
>  		yield();			/* Yield is okay here */
> +		if (todo && has_wake_lock(WAKE_LOCK_SUSPEND)) {
> +			wakeup = 1;
> +			break;
> +		}
>  		if (time_after(jiffies, end_time))
>  			break;
>  	} while (todo);

I do not see why wakelocks should change refrigerator behaviour.

> @@ -77,11 +83,17 @@ static int try_to_freeze_tasks(bool sig_only)
>  		 * and caller must call thaw_processes() if something fails),
>  		 * but it cleans up leftover PF_FREEZE requests.
>  		 */
> -		printk("\n");
> -		printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds "
> -				"(%d tasks refusing to freeze):\n",
> -				elapsed_csecs / 100, elapsed_csecs % 100, todo);
> -		show_state();
> +		if (wakeup) {
> +			printk("\n");
> +			printk(KERN_ERR "Freezing of %s aborted\n",
> +					sig_only ? "user space " : "tasks ");
> +		} else {
> +			printk("\n");
> +			printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds "
> +					"(%d tasks refusing to freeze):\n",
> +					elapsed_csecs / 100, elapsed_csecs % 100, todo);
> +			show_state();

Please find why the refrigerator fails for you. Yes, we want quiescent
state at least for hibernation resume.
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes.
  2009-02-05  2:50                   ` [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes Arve Hjønnevåg
  2009-02-05  2:50                     ` [PATCH 11/13] PM: earlysuspend: Removing dependence on console Arve Hjønnevåg
@ 2009-02-05  9:03                     ` Pavel Machek
  2009-02-05  9:37                       ` Arve Hjønnevåg
  2009-02-06  2:29                       ` Arve Hjønnevåg
  1 sibling, 2 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-05  9:03 UTC (permalink / raw)
  To: Arve Hj??nnev??g; +Cc: ncunningham, u.luckas, swetland, linux-pm

Hi!

changelog would be welcome.

> Signed-off-by: Arve Hj??nnev??g <arve@android.com>
> 
> diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
> index aedea7e..f1a3d5c 100644
> --- a/kernel/power/Kconfig
> +++ b/kernel/power/Kconfig
> @@ -166,6 +166,23 @@ config EARLYSUSPEND
>  	  Call early suspend handlers when the user requested sleep state
>  	  changes.
>  
> +choice
> +	prompt "User-space screen access"
> +	default CONSOLE_EARLYSUSPEND
> +	depends on HAS_EARLYSUSPEND
> +
> +	config NO_USER_SPACE_SCREEN_ACCESS_CONTROL
> +		bool "None"

Eh?

> +	config CONSOLE_EARLYSUSPEND
> +		bool "Console switch on early-suspend"
> +		depends on HAS_EARLYSUSPEND && VT
> +		---help---
> +		  Register early suspend handler to perform a console switch to
> +		  when user-space should stop drawing to the screen and a switch
> +		  back when it should resume.

I could not parse english here.

> index d3467b3..8bf293d 100644
> --- a/kernel/power/Makefile
> +++ b/kernel/power/Makefile
> @@ -9,6 +9,7 @@ obj-$(CONFIG_FREEZER)		+= process.o
>  obj-$(CONFIG_WAKELOCK)		+= wakelock.o
>  obj-$(CONFIG_USER_WAKELOCK)	+= userwakelock.o
>  obj-$(CONFIG_EARLYSUSPEND)	+= earlysuspend.o
> +obj-$(CONFIG_CONSOLE_EARLYSUSPEND)	+= consoleearlysuspend.o

Some _'s would be welcome in filename.

Actually, I'd hope that system where you control everything (such as
android) would not need to switch consoles. Console switch was
invented as a workaround for X owning the hardware....

...and how is it different from current console switching we do on PC?

								Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 11/13] PM: earlysuspend: Removing dependence on console.
  2009-02-05  2:50                     ` [PATCH 11/13] PM: earlysuspend: Removing dependence on console Arve Hjønnevåg
  2009-02-05  2:50                       ` [PATCH 12/13] Input: Hold wake lock while event queue is not empty Arve Hjønnevåg
@ 2009-02-05  9:06                       ` Pavel Machek
  2009-02-05  9:42                         ` Arve Hjønnevåg
  1 sibling, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-05  9:06 UTC (permalink / raw)
  To: Arve Hj??nnev??g
  Cc: ncunningham, u.luckas, swetland, Rebecca Schultz, linux-pm

On Wed 2009-02-04 18:50:24, Arve Hj??nnev??g wrote:
> From: Rebecca Schultz <rschultz@google.com>
> 
> Rather than signaling a full update of the display from userspace via a
> console switch, this patch introduces 2 files int /sys/power,
> wait_for_fb_sleep and wait_for_fb_wake.  Reading these files will block
> until the requested state has been entered.  When a read from
> wait_for_fb_sleep returns userspace should stop drawing.  When
> wait_for_fb_wake returns, it should do a full update.  If either are called
> when the fb driver is already in the requested state, they will return
> immediately.

You have just introduced another method of console switching in
previous patch. Please drop pieces of duplicate functionality you are
not using any more.

> @@ -181,6 +182,14 @@ choice
>  		  Register early suspend handler to perform a console switch to
>  		  when user-space should stop drawing to the screen and a switch
>  		  back when it should resume.
> +
> +	config FB_EARLYSUSPEND
> +		bool "Sysfs interface"
> +		depends on HAS_EARLYSUSPEND
> +		---help---
> +		  Register early suspend handler that notifies and waits for
> +		  user-space through sysfs when user-space should stop drawing
> +		  to the screen and notifies user-space when it should resume.
>  endchoice

Hmm, as far as I can tell, turning this option on will immediately
break suspend on all existing setups. Bad.

> +static int __init android_power_init(void)
> +{
> +	int ret;
> +
> +	init_waitqueue_head(&fb_state_wq);
> +	fb_state = FB_STATE_DRAWING_OK;
> +
> +	ret = sysfs_create_group(power_kobj, &attr_group);
> +	if (ret) {
> +		pr_err("android_power_init: sysfs_create_group failed\n");
> +		return ret;
> +	}
> +
> +	register_early_suspend(&stop_drawing_early_suspend_desc);
> +	return 0;
> +}
> +
> +static void  __exit android_power_exit(void)
> +{
> +	unregister_early_suspend(&stop_drawing_early_suspend_desc);
> +	sysfs_remove_group(power_kobj, &attr_group);
> +}
> +
> +module_init(android_power_init);
> +module_exit(android_power_exit);
> +

You probably want to avoid android_ prefix here, and invent some
better one.
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 12/13] Input: Hold wake lock while event queue is not empty.
  2009-02-05  2:50                       ` [PATCH 12/13] Input: Hold wake lock while event queue is not empty Arve Hjønnevåg
  2009-02-05  2:50                         ` [PATCH 13/13] ledtrig-sleep: Add led trigger for sleep debugging Arve Hjønnevåg
@ 2009-02-05  9:08                         ` Pavel Machek
  1 sibling, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-05  9:08 UTC (permalink / raw)
  To: Arve Hj??nnev??g; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Wed 2009-02-04 18:50:25, Arve Hj??nnev??g wrote:
> Allows userspace code to process input events while
> the device appears to be asleep.

...

> @@ -55,6 +57,7 @@ static void evdev_pass_event(struct evdev_client *client,
>  	 * Interrupts are disabled, just acquire the lock
>  	 */
>  	spin_lock(&client->buffer_lock);
> +	wake_lock_timeout(&client->wake_lock, 5 * HZ);
>  	client->buffer[client->head++] = *event;
>  	client->head &= EVDEV_BUFFER_SIZE - 1;
>  	spin_unlock(&client->buffer_lock);

...as long as userspace needs less than 5 seconds. Ugly hack.
								Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-05  2:50 ` [PATCH 01/13] PM: Add wake lock api Arve Hjønnevåg
  2009-02-05  2:50   ` [PATCH 02/13] PM: Add early suspend api Arve Hjønnevåg
@ 2009-02-05  9:11   ` Pavel Machek
  2009-02-06  0:28     ` Arve Hjønnevåg
  2009-02-06  1:32     ` [PATCH 01/13] PM: Add wake lock api mark gross
  2009-02-05 22:51   ` mark gross
  2009-02-07 18:56   ` Rafael J. Wysocki
  3 siblings, 2 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-05  9:11 UTC (permalink / raw)
  To: Arve Hj??nnev??g; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Wed 2009-02-04 18:50:14, Arve Hj??nnev??g wrote:
> Signed-off-by: Arve Hj??nnev??g <arve@android.com>
> ---
>  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.txt
> new file mode 100644
> index 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

idle states are very different from suspend. Mixing them does not look
like good idea... and IIRC we already have API somewhere to prevent
deep idle states. Intel did it for their wireless cards IIRC.


> +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       +++          +++
> +

I'm not sure if keyboard scanning example is good here. It is very
t-mobile G1 specific.
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 02/13] PM: Add early suspend api.
  2009-02-05  2:50   ` [PATCH 02/13] PM: Add early suspend api Arve Hjønnevåg
  2009-02-05  2:50     ` [PATCH 03/13] PM: Implement wakelock api Arve Hjønnevåg
@ 2009-02-05  9:14     ` Pavel Machek
  2009-02-05 23:26     ` mark gross
  2009-02-07 20:53     ` Rafael J. Wysocki
  3 siblings, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-05  9:14 UTC (permalink / raw)
  To: Arve Hj??nnev??g; +Cc: ncunningham, u.luckas, swetland, linux-pm



> +Early-suspend
> +=============
> +
> +The early-suspend api allows drivers to get notified when user-space writes to 
> +/sys/power/request_state to indicate that the user visible sleep state should 
> +change. 

"User visible sleep state"... hmm, PC developers are not going to
understand this.

> A level controls what order the handlers are called in. Suspend 
> +handlers are called in low to high level order, resume handlers are called in 
> +the opposite order. 
> +
> +Four levels are defined:
> +EARLY_SUSPEND_LEVEL_BLANK_SCREEN:
> +  On suspend the screen should be turned off but the framebuffer must still be
> +  accessible. On resume the screen can be turned back on.
> +

Blanking screen is traditionally done at user level? Why does this
need to be in kernel?

> +EARLY_SUSPEND_LEVEL_STOP_DRAWING:
> +  On suspend this level notifies user-space that it should stop accessing the 
> +  framebuffer and it waits for it to complete. On resume it notifies user-space 
> +  that it should resume screen access.


> +  Two methods are provided, console switch or a sysfs interface.

Yeah. Pick one.

> +EARLY_SUSPEND_LEVEL_DISABLE_FB:
> +  Turn off the framebuffer on suspend and back on on resume.
> +
> +EARLY_SUSPEND_LEVEL_STOP_INPUT:
> +  On suspend turn off input devices that are not capable of wakeup or where
> +  wakeup is disabled. On resume turn the same devices back on.

At this point I don't see why early suspend should be done in
kernel. Framebuffer control is better left to userspace... and turning
off input devices should not require this kind of API.
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 03/13] PM: Implement wakelock api.
  2009-02-05  2:50     ` [PATCH 03/13] PM: Implement wakelock api Arve Hjønnevåg
  2009-02-05  2:50       ` [PATCH 04/13] PM: wakelock: Override wakelocks when using /sys/power/state Arve Hjønnevåg
@ 2009-02-05  9:16       ` Pavel Machek
  2009-02-05 15:24       ` Alan Stern
                         ` (2 subsequent siblings)
  4 siblings, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-05  9:16 UTC (permalink / raw)
  To: Arve Hj??nnev??g; +Cc: ncunningham, u.luckas, swetland, linux-pm


> diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
> index 23bd4da..6e3da6e 100644
> --- a/kernel/power/Kconfig
> +++ b/kernel/power/Kconfig
> @@ -116,6 +116,25 @@ config SUSPEND_FREEZER
>  
>  	  Turning OFF this setting is NOT recommended! If in doubt, say Y.
>  
> +config HAS_WAKELOCK
> +	bool
> +
> +config WAKELOCK
> +	bool "Wake lock"
> +	depends on PM && RTC_CLASS

?

> +	default n
> +	select HAS_WAKELOCK
> +	---help---
> +	  Enable wakelocks. When user space request a sleep state the
> +	  sleep request will be delayed until no wake locks are held.

Not true... for /sys/power/state anyway.

> +int get_expired_time(struct wake_lock *lock, ktime_t *expire_time)
> +{
> +	struct timespec ts;
> +	struct timespec kt;
> +	struct timespec tomono;
> +	struct timespec delta;
> +	unsigned long seq;
> +	long timeout;
> +
> +	if (!(lock->flags & WAKE_LOCK_AUTO_EXPIRE))
> +		return 0;
> +	do {
> +		seq = read_seqbegin(&xtime_lock);
> +		timeout = lock->expires - jiffies;
> +		if (timeout > 0)
> +			return 0;
> +		kt = current_kernel_time();
> +		tomono = wall_to_monotonic;
> +	} while (read_seqretry(&xtime_lock, seq));
> +	jiffies_to_timespec(-timeout, &delta);
> +	set_normalized_timespec(&ts, kt.tv_sec + tomono.tv_sec - delta.tv_sec,
> +				kt.tv_nsec + tomono.tv_nsec - delta.tv_nsec);
> +	*expire_time = timespec_to_ktime(ts);
> +	return 1;
> +}
> +
> +
> +static int print_lock_stat(char *buf, struct wake_lock *lock)
> +{
> +	int lock_count = lock->stat.count;
> +	int expire_count = lock->stat.expire_count;
> +	ktime_t active_time = ktime_set(0, 0);
> +	ktime_t total_time = lock->stat.total_time;
> +	ktime_t max_time = lock->stat.max_time;
> +	ktime_t prevent_suspend_time = lock->stat.prevent_suspend_time;
> +	if (lock->flags & WAKE_LOCK_ACTIVE) {
> +		ktime_t now, add_time;
> +		int expired = get_expired_time(lock, &now);
> +		if (!expired)
> +			now = ktime_get();
> +		add_time = ktime_sub(now, lock->stat.last_time);
> +		lock_count++;
> +		if (!expired)
> +			active_time = add_time;
> +		else
> +			expire_count++;
> +		total_time = ktime_add(total_time, add_time);
> +		if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND)
> +			prevent_suspend_time = ktime_add(prevent_suspend_time,
> +					ktime_sub(now, last_sleep_time_update));
> +		if (add_time.tv64 > max_time.tv64)
> +			max_time = add_time;
> +	}
> +
> +	return sprintf(buf, "\"%s\"\t%d\t%d\t%d\t%lld\t%lld\t%lld\t%lld\t"
> +		       "%lld\n", lock->name, lock_count, expire_count,
> +		       lock->stat.wakeup_count, ktime_to_ns(active_time),
> +		       ktime_to_ns(total_time),
> +		       ktime_to_ns(prevent_suspend_time), ktime_to_ns(max_time),
> +		       ktime_to_ns(lock->stat.last_time));
> +}

I guess these should be documented somewhere.

> +static void  __exit wakelocks_exit(void)
> +{
> +#ifdef CONFIG_WAKELOCK_STAT
> +	remove_proc_entry("wakelocks", NULL);
> +#endif

You certainly do not want /proc/wakelocks. Seems like debugfs
material.

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-05  2:50         ` [PATCH 05/13] PM: Add option to disable /sys/power/state interface Arve Hjønnevåg
  2009-02-05  2:50           ` [PATCH 06/13] PM: Implement early suspend api Arve Hjønnevåg
@ 2009-02-05  9:17           ` Pavel Machek
  2009-02-07 22:37           ` Rafael J. Wysocki
  2 siblings, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-05  9:17 UTC (permalink / raw)
  To: Arve Hj??nnev??g; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Wed 2009-02-04 18:50:18, Arve Hj??nnev??g wrote:
> Signed-off-by: Arve Hj??nnev??g <arve@android.com>
> ---
>  kernel/power/Kconfig |    9 +++++++++
>  kernel/power/main.c  |    4 ++++
>  2 files changed, 13 insertions(+), 0 deletions(-)
> 
> diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
> index 6e3da6e..dd76467 100644
> --- a/kernel/power/Kconfig
> +++ b/kernel/power/Kconfig
> @@ -135,6 +135,15 @@ config WAKELOCK_STAT
>  	---help---
>  	  Report wake lock stats in /proc/wakelocks
>  
> +config DISABLE_SYS_POWER_STATE
> +	bool "Disable /sys/power/state interface"
> +	depends on WAKELOCK
> +	default n
> +	---help---
> +	  The /sys/power/state interface does not respect wakelocks. If you
> +	  want to run user-space code that does not support wakelocks, do not
> +	  enable this option since it removes the interface.

I do not think this is required for anything or useful. If you don't
want to force system to suspend, do not write to /sys/power/state. It
is root-only interface, so....

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 07/13] PM: wakelock: Add /sys/power/request_state
  2009-02-05  8:52               ` [PATCH 07/13] PM: wakelock: Add /sys/power/request_state Pavel Machek
@ 2009-02-05  9:25                 ` Arve Hjønnevåg
  2009-02-05  9:27                   ` Pavel Machek
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  9:25 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thu, Feb 5, 2009 at 12:52 AM, Pavel Machek <pavel@ucw.cz> wrote:
>>  static const char * const pm_states[PM_SUSPEND_MAX] = {
>> +#ifdef CONFIG_WAKELOCK
>> +     [PM_SUSPEND_ON]         = "on",
>> +#endif
>>       [PM_SUSPEND_STANDBY]    = "standby",
>>       [PM_SUSPEND_MEM]        = "mem",
>>  };
>
> By doing this you change /sys/power/state interface. I do not think
> you want to do that.

As long as valid_state(PM_SUSPEND_ON) returns 0, /sys/power/state
should be unaffected.
However, I can hardcode the "on" state in request_state if you prefer.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 07/13] PM: wakelock: Add /sys/power/request_state
  2009-02-05  9:25                 ` Arve Hjønnevåg
@ 2009-02-05  9:27                   ` Pavel Machek
  0 siblings, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-05  9:27 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thu 2009-02-05 01:25:03, Arve Hj?nnev?g wrote:
> On Thu, Feb 5, 2009 at 12:52 AM, Pavel Machek <pavel@ucw.cz> wrote:
> >>  static const char * const pm_states[PM_SUSPEND_MAX] = {
> >> +#ifdef CONFIG_WAKELOCK
> >> +     [PM_SUSPEND_ON]         = "on",
> >> +#endif
> >>       [PM_SUSPEND_STANDBY]    = "standby",
> >>       [PM_SUSPEND_MEM]        = "mem",
> >>  };
> >
> > By doing this you change /sys/power/state interface. I do not think
> > you want to do that.
> 
> As long as valid_state(PM_SUSPEND_ON) returns 0, /sys/power/state
> should be unaffected.
> However, I can hardcode the "on" state in request_state if you prefer.

As long as /sys/power/state is unaffected, I'm okay with this.

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held.
  2009-02-05  8:55                   ` [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held Pavel Machek
@ 2009-02-05  9:30                     ` Arve Hjønnevåg
  2009-02-05  9:49                       ` Pavel Machek
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  9:30 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thu, Feb 5, 2009 at 12:55 AM, Pavel Machek <pavel@ucw.cz> wrote:
> Hi!
>
>> Avoids a problem where the device sometimes hangs for 20 seconds
>> before the screen is turned on.
>
> Fix the problem rather than working around it.

We used to have problems where if a process was connected to a
debugger, and the debugger was frozen first, the this code would be
stuck until it times out. I have not seen this problem recently, but
aborting as soon as you know that you should wake up is still good.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes.
  2009-02-05  9:03                     ` [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes Pavel Machek
@ 2009-02-05  9:37                       ` Arve Hjønnevåg
  2009-02-05  9:51                         ` Pavel Machek
  2009-02-05 10:54                         ` Uli Luckas
  2009-02-06  2:29                       ` Arve Hjønnevåg
  1 sibling, 2 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  9:37 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thu, Feb 5, 2009 at 1:03 AM, Pavel Machek <pavel@ucw.cz> wrote:
>> +               Register early suspend handler to perform a console switch to
>> +               when user-space should stop drawing to the screen and a switch
>> +               back when it should resume.
>
> I could not parse english here.

The "to"on the first line should be removed.

> Actually, I'd hope that system where you control everything (such as
> android) would not need to switch consoles. Console switch was
> invented as a workaround for X owning the hardware....

We don't anymore, but if you enable console support (for debugging) we
support it.

> ...and how is it different from current console switching we do on PC?

It is not, but we turn off the framebuffer before the normal suspend
path so we need the switch here.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 11/13] PM: earlysuspend: Removing dependence on console.
  2009-02-05  9:06                       ` [PATCH 11/13] PM: earlysuspend: Removing dependence on console Pavel Machek
@ 2009-02-05  9:42                         ` Arve Hjønnevåg
  2009-02-05  9:53                           ` Pavel Machek
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  9:42 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, Rebecca Schultz, linux-pm

On Thu, Feb 5, 2009 at 1:06 AM, Pavel Machek <pavel@ucw.cz> wrote:
> You have just introduced another method of console switching in
> previous patch. Please drop pieces of duplicate functionality you are
> not using any more.

If console support is enabled use a console switch, if not use this.

>> +               Register early suspend handler that notifies and waits for
>> +               user-space through sysfs when user-space should stop drawing
>> +               to the screen and notifies user-space when it should resume.
>>  endchoice
>
> Hmm, as far as I can tell, turning this option on will immediately
> break suspend on all existing setups. Bad.

I'm not aware of any existing interface that works if console support
is not enabled.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held.
  2009-02-05  9:30                     ` Arve Hjønnevåg
@ 2009-02-05  9:49                       ` Pavel Machek
  2009-02-05  9:58                         ` Arve Hjønnevåg
  0 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-05  9:49 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thu 2009-02-05 01:30:35, Arve Hj?nnev?g wrote:
> On Thu, Feb 5, 2009 at 12:55 AM, Pavel Machek <pavel@ucw.cz> wrote:
> > Hi!
> >
> >> Avoids a problem where the device sometimes hangs for 20 seconds
> >> before the screen is turned on.
> >
> > Fix the problem rather than working around it.
> 
> We used to have problems where if a process was connected to a
> debugger, and the debugger was frozen first, the this code would be
> stuck until it times out. I have not seen this problem recently, but
> aborting as soon as you know that you should wake up is still good.

Can you explain why you need the change in the changelog then? It is
not at all clear to me.

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes.
  2009-02-05  9:37                       ` Arve Hjønnevåg
@ 2009-02-05  9:51                         ` Pavel Machek
  2009-02-05 10:54                         ` Uli Luckas
  1 sibling, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-05  9:51 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thu 2009-02-05 01:37:53, Arve Hj?nnev?g wrote:
> On Thu, Feb 5, 2009 at 1:03 AM, Pavel Machek <pavel@ucw.cz> wrote:
> >> +               Register early suspend handler to perform a console switch to
> >> +               when user-space should stop drawing to the screen and a switch
> >> +               back when it should resume.
> >
> > I could not parse english here.
> 
> The "to"on the first line should be removed.
> 
> > Actually, I'd hope that system where you control everything (such as
> > android) would not need to switch consoles. Console switch was
> > invented as a workaround for X owning the hardware....
> 
> We don't anymore, but if you enable console support (for debugging) we
> support it.

I'd guess the audience of debugging people running android is pretty
limited. I'd suggest this is not really suitable for mainline.

								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 11/13] PM: earlysuspend: Removing dependence on console.
  2009-02-05  9:42                         ` Arve Hjønnevåg
@ 2009-02-05  9:53                           ` Pavel Machek
  0 siblings, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-05  9:53 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, swetland, Rebecca Schultz, linux-pm


> >> +               Register early suspend handler that notifies and waits for
> >> +               user-space through sysfs when user-space should stop drawing
> >> +               to the screen and notifies user-space when it should resume.
> >>  endchoice
> >
> > Hmm, as far as I can tell, turning this option on will immediately
> > break suspend on all existing setups. Bad.
> 
> I'm not aware of any existing interface that works if console support
> is not enabled.

That's why console switching support is mandatory today.

If you want to change that, fine, but CONFIG_ option should not
immediately break existing setups. Rather, you should detect that
userspace is capable of using new interface, and only then wait for
it...
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held.
  2009-02-05  9:49                       ` Pavel Machek
@ 2009-02-05  9:58                         ` Arve Hjønnevåg
  2009-02-05 10:02                           ` Pavel Machek
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05  9:58 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thu, Feb 5, 2009 at 1:49 AM, Pavel Machek <pavel@ucw.cz> wrote:
> On Thu 2009-02-05 01:30:35, Arve Hj?nnev?g wrote:
>> On Thu, Feb 5, 2009 at 12:55 AM, Pavel Machek <pavel@ucw.cz> wrote:
>> > Hi!
>> >
>> >> Avoids a problem where the device sometimes hangs for 20 seconds
>> >> before the screen is turned on.
>> >
>> > Fix the problem rather than working around it.
>>
>> We used to have problems where if a process was connected to a
>> debugger, and the debugger was frozen first, the this code would be
>> stuck until it times out. I have not seen this problem recently, but
>> aborting as soon as you know that you should wake up is still good.
>
> Can you explain why you need the change in the changelog then? It is
> not at all clear to me.

We should also check if we should abort after suspending any driver.
This was just the only place where the delay was noticeable since it
tries for 20 seconds.

I'll extend the change description.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held.
  2009-02-05  9:58                         ` Arve Hjønnevåg
@ 2009-02-05 10:02                           ` Pavel Machek
  2009-02-05 10:08                             ` Arve Hjønnevåg
  2009-02-06  3:42                             ` Arve Hjønnevåg
  0 siblings, 2 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-05 10:02 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thu 2009-02-05 01:58:40, Arve Hj?nnev?g wrote:
> On Thu, Feb 5, 2009 at 1:49 AM, Pavel Machek <pavel@ucw.cz> wrote:
> > On Thu 2009-02-05 01:30:35, Arve Hj?nnev?g wrote:
> >> On Thu, Feb 5, 2009 at 12:55 AM, Pavel Machek <pavel@ucw.cz> wrote:
> >> > Hi!
> >> >
> >> >> Avoids a problem where the device sometimes hangs for 20 seconds
> >> >> before the screen is turned on.
> >> >
> >> > Fix the problem rather than working around it.
> >>
> >> We used to have problems where if a process was connected to a
> >> debugger, and the debugger was frozen first, the this code would be
> >> stuck until it times out. I have not seen this problem recently, but
> >> aborting as soon as you know that you should wake up is still good.
> >
> > Can you explain why you need the change in the changelog then? It is
> > not at all clear to me.
> 
> We should also check if we should abort after suspending any driver.
> This was just the only place where the delay was noticeable since it
> tries for 20 seconds.

I still don't get it. Refrigerator freezes userspace processes, not
devices.

Are you trying to improve hadling of suspend abort during freeze?

> I'll extend the change description.

...so I guess I'll wait for extended description.
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held.
  2009-02-05 10:02                           ` Pavel Machek
@ 2009-02-05 10:08                             ` Arve Hjønnevåg
  2009-02-06  3:42                             ` Arve Hjønnevåg
  1 sibling, 0 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-05 10:08 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thu, Feb 5, 2009 at 2:02 AM, Pavel Machek <pavel@ucw.cz> wrote:
>> We should also check if we should abort after suspending any driver.
>> This was just the only place where the delay was noticeable since it
>> tries for 20 seconds.
>
> I still don't get it. Refrigerator freezes userspace processes, not
> devices.

Individual devices could also be slow to suspend, so aborting as soon
as you know that suspend will fail would be better. Right now I only
have two abort points, during freeze and a single late suspend
handler.

> Are you trying to improve hadling of suspend abort during freeze?

Yes.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes.
  2009-02-05  9:37                       ` Arve Hjønnevåg
  2009-02-05  9:51                         ` Pavel Machek
@ 2009-02-05 10:54                         ` Uli Luckas
  1 sibling, 0 replies; 251+ messages in thread
From: Uli Luckas @ 2009-02-05 10:54 UTC (permalink / raw)
  To: linux-pm; +Cc: swetland, ncunningham

On Thursday, 5. February 2009, Arve Hjønnevåg wrote:
> On Thu, Feb 5, 2009 at 1:03 AM, Pavel Machek <pavel@ucw.cz> wrote:
> > ...and how is it different from current console switching we do on PC?
>
> It is not, but we turn off the framebuffer before the normal suspend
> path so we need the switch here.
Couldn't you just keep drawing to the disabled frame buffer?

Uli
-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 03/13] PM: Implement wakelock api.
  2009-02-05  2:50     ` [PATCH 03/13] PM: Implement wakelock api Arve Hjønnevåg
  2009-02-05  2:50       ` [PATCH 04/13] PM: wakelock: Override wakelocks when using /sys/power/state Arve Hjønnevåg
  2009-02-05  9:16       ` [PATCH 03/13] PM: Implement wakelock api Pavel Machek
@ 2009-02-05 15:24       ` Alan Stern
  2009-02-06  0:10       ` mark gross
  2009-02-07 22:27       ` Rafael J. Wysocki
  4 siblings, 0 replies; 251+ messages in thread
From: Alan Stern @ 2009-02-05 15:24 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Wed, 4 Feb 2009, [utf-8] Arve Hjønnevåg wrote:

> --- a/kernel/power/Kconfig
> +++ b/kernel/power/Kconfig
> @@ -116,6 +116,25 @@ config SUSPEND_FREEZER
>  
>  	  Turning OFF this setting is NOT recommended! If in doubt, say Y.
>  
> +config HAS_WAKELOCK
> +	bool
> +
> +config WAKELOCK
> +	bool "Wake lock"
> +	depends on PM && RTC_CLASS
> +	default n
> +	select HAS_WAKELOCK
> +	---help---
> +	  Enable wakelocks. When user space request a sleep state the
> +	  sleep request will be delayed until no wake locks are held.

You know, when submitting multiple patches it is customary to break the 
code up in such a way that intermediate forms (where some of the 
patches have been applied but not all of them) will compile and run 
correctly.  This is so that people will be able to carry out bisection 
searches while looking for other bugs.

Right here we see that you introduce CONFIG_WAKELOCK in patch 03/13, 
but it gets used already in patch 01/13.  That's not good.

One other thing -- this may be a standard Kconfig idiom, but what 
reason is there for CONFIG_HAS_WAKELOCK?  Does it get used anywhere?  
It if does, couldn't CONFIG_WAKELOCK be used instead?

Alan Stern

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-05  2:50 ` [PATCH 01/13] PM: Add wake lock api Arve Hjønnevåg
  2009-02-05  2:50   ` [PATCH 02/13] PM: Add early suspend api Arve Hjønnevåg
  2009-02-05  9:11   ` [PATCH 01/13] PM: Add wake lock api Pavel Machek
@ 2009-02-05 22:51   ` mark gross
  2009-02-06  0:13     ` Arve Hjønnevåg
  2009-02-07 18:56   ` Rafael J. Wysocki
  3 siblings, 1 reply; 251+ messages in thread
From: mark gross @ 2009-02-05 22:51 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: swetland, linux-pm, u.luckas, ncunningham

On Wed, Feb 04, 2009 at 06:50:14PM -0800, Arve Hjønnevåg wrote:
> Signed-off-by: Arve Hjønnevåg <arve@android.com>
> ---
>  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.txt
> new file mode 100644
> index 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.

How much of this can be implemented using a pm-qos approach?

> +
> +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       +++          +++
> +

This feels a lot like operating points implemented as a collection of
product specific binary locks.  How could this be generalized to be less
application specific?

> +
> +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);

um, if a driver grabs the wakelock for another device that is sleeping
how will it know when that sleeping device is ready to be used?  Is
wake_lock going to block until the dives its locking is in a good power
state?  (I'm guessing yes) Is doing this in the context of and IRQ a
good idea?

> +
> +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);

Timer?

> +
> +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.h
> new file mode 100755
> index 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

Shouldn't this #ifdef be in the files using wake_lock.h?  If
!CONFIG_HAS_WAKELOCK then should all the definitions here not be parsed
at compile time?

> +	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);

Type? or class?  What is this type concept?  Should we have some strong
typing to the enum list above or at least a comment on what are the
types that are valid to call this API with?

> +
> +#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

I don't like these type of use of ifdef to no-op out API's do we really
need to do it this way?  

> +
> +#endif
> +
> -- 
> 1.6.1
> 
> _______________________________________________
> linux-pm mailing list
> linux-pm@lists.linux-foundation.org
> https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 02/13] PM: Add early suspend api.
  2009-02-05  2:50   ` [PATCH 02/13] PM: Add early suspend api Arve Hjønnevåg
  2009-02-05  2:50     ` [PATCH 03/13] PM: Implement wakelock api Arve Hjønnevåg
  2009-02-05  9:14     ` [PATCH 02/13] PM: Add early suspend api Pavel Machek
@ 2009-02-05 23:26     ` mark gross
  2009-02-06  9:33       ` Uli Luckas
  2009-02-07 20:53     ` Rafael J. Wysocki
  3 siblings, 1 reply; 251+ messages in thread
From: mark gross @ 2009-02-05 23:26 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: swetland, linux-pm, u.luckas, ncunningham

On Wed, Feb 04, 2009 at 06:50:15PM -0800, Arve Hjønnevåg wrote:
> Signed-off-by: Arve Hjønnevåg <arve@android.com>
> ---
>  Documentation/power/early-suspend.txt |   26 +++++++++++++++
>  include/linux/earlysuspend.h          |   55 +++++++++++++++++++++++++++++++++
>  2 files changed, 81 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/power/early-suspend.txt
>  create mode 100755 include/linux/earlysuspend.h
> 
> diff --git a/Documentation/power/early-suspend.txt b/Documentation/power/early-suspend.txt
> new file mode 100644
> index 0000000..8286d3a
> --- /dev/null
> +++ b/Documentation/power/early-suspend.txt
> @@ -0,0 +1,26 @@
> +Early-suspend
> +=============
> +
> +The early-suspend api allows drivers to get notified when user-space writes to 
> +/sys/power/request_state to indicate that the user visible sleep state should 
> +change. A level controls what order the handlers are called in. Suspend 
> +handlers are called in low to high level order, resume handlers are called in 
> +the opposite order. 
> +
> +Four levels are defined:
> +EARLY_SUSPEND_LEVEL_BLANK_SCREEN:
> +  On suspend the screen should be turned off but the framebuffer must still be
> +  accessible. On resume the screen can be turned back on.
> +
> +EARLY_SUSPEND_LEVEL_STOP_DRAWING:
> +  On suspend this level notifies user-space that it should stop accessing the 
> +  framebuffer and it waits for it to complete. On resume it notifies user-space 
> +  that it should resume screen access.
> +  Two methods are provided, console switch or a sysfs interface.
> +
> +EARLY_SUSPEND_LEVEL_DISABLE_FB:
> +  Turn off the framebuffer on suspend and back on on resume.
> +
> +EARLY_SUSPEND_LEVEL_STOP_INPUT:
> +  On suspend turn off input devices that are not capable of wakeup or where
> +  wakeup is disabled. On resume turn the same devices back on.

these levels names are domain and device profile centric.  How can we
make these be applicable to more than the HTC dream? 

Why 4 levels?  4 seems like too many, but why stop at 4 why not 8?


> diff --git a/include/linux/earlysuspend.h b/include/linux/earlysuspend.h
> new file mode 100755
> index 0000000..1587a3f
> --- /dev/null
> +++ b/include/linux/earlysuspend.h
> @@ -0,0 +1,55 @@
> +/* include/linux/earlysuspend.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_EARLYSUSPEND_H
> +#define _LINUX_EARLYSUSPEND_H
> +
> +#include <linux/list.h>
> +
> +/* The early_suspend structure defines suspend and resume hooks to be called
> + * when the user visible sleep state of the system changes, and a level to
> + * control the order. They can be used to turn off the screen and input
> + * devices that are not used for wakeup.
> + * Suspend handlers are called in low to high level order, resume handlers are
> + * called in the opposite order. If, when calling register_early_suspend,
> + * the suspend handlers have already been called without a matching call to the
> + * resume handlers, the suspend handler will be called directly from
> + * register_early_suspend. This direct call can violate the normal level order.
> + */
> +enum {
> +	EARLY_SUSPEND_LEVEL_BLANK_SCREEN = 50,
> +	EARLY_SUSPEND_LEVEL_STOP_INPUT = 75,
> +	EARLY_SUSPEND_LEVEL_STOP_DRAWING = 100,
> +	EARLY_SUSPEND_LEVEL_DISABLE_FB = 150,
> +};

Application domain independent levels may be more useful to the larger
community.


> +struct early_suspend {
> +#ifdef CONFIG_HAS_EARLYSUSPEND
> +	struct list_head link;
> +	int level;
> +	void (*suspend)(struct early_suspend *h);
> +	void (*resume)(struct early_suspend *h);
> +#endif
> +};
> +
> +#ifdef CONFIG_HAS_EARLYSUSPEND
> +void register_early_suspend(struct early_suspend *handler);
> +void unregister_early_suspend(struct early_suspend *handler);
> +#else
> +#define register_early_suspend(handler) do { } while (0)
> +#define unregister_early_suspend(handler) do { } while (0)
> +#endif
> +

do we really need to no-op this code this way?


--mgross

> +#endif
> +
> -- 
> 1.6.1
> 
> _______________________________________________
> linux-pm mailing list
> linux-pm@lists.linux-foundation.org
> https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 03/13] PM: Implement wakelock api.
  2009-02-05  2:50     ` [PATCH 03/13] PM: Implement wakelock api Arve Hjønnevåg
                         ` (2 preceding siblings ...)
  2009-02-05 15:24       ` Alan Stern
@ 2009-02-06  0:10       ` mark gross
  2009-02-06  0:38         ` Arve Hjønnevåg
  2009-02-07 22:27       ` Rafael J. Wysocki
  4 siblings, 1 reply; 251+ messages in thread
From: mark gross @ 2009-02-06  0:10 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: swetland, linux-pm, u.luckas, ncunningham

On Wed, Feb 04, 2009 at 06:50:16PM -0800, Arve Hjønnevåg wrote:
> Signed-off-by: Arve Hjønnevåg <arve@android.com>
> ---
>  kernel/power/Kconfig    |   19 ++
>  kernel/power/Makefile   |    1 +
>  kernel/power/power.h    |    7 +
>  kernel/power/wakelock.c |  598 +++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 625 insertions(+), 0 deletions(-)
>  create mode 100644 kernel/power/wakelock.c
> 
> diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
> index 23bd4da..6e3da6e 100644
> --- a/kernel/power/Kconfig
> +++ b/kernel/power/Kconfig
> @@ -116,6 +116,25 @@ config SUSPEND_FREEZER
>  
>  	  Turning OFF this setting is NOT recommended! If in doubt, say Y.
>  
> +config HAS_WAKELOCK
> +	bool
> +
> +config WAKELOCK
> +	bool "Wake lock"
> +	depends on PM && RTC_CLASS
> +	default n
> +	select HAS_WAKELOCK
> +	---help---
> +	  Enable wakelocks. When user space request a sleep state the
> +	  sleep request will be delayed until no wake locks are held.
> +
> +config WAKELOCK_STAT
> +	bool "Wake lock stats"
> +	depends on WAKELOCK
> +	default y
> +	---help---
> +	  Report wake lock stats in /proc/wakelocks
> +
>  config HIBERNATION
>  	bool "Hibernation (aka 'suspend to disk')"
>  	depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
> diff --git a/kernel/power/Makefile b/kernel/power/Makefile
> index d7a1016..8d8672b 100644
> --- a/kernel/power/Makefile
> +++ b/kernel/power/Makefile
> @@ -6,6 +6,7 @@ endif
>  obj-y				:= main.o
>  obj-$(CONFIG_PM_SLEEP)		+= console.o
>  obj-$(CONFIG_FREEZER)		+= process.o
> +obj-$(CONFIG_WAKELOCK)		+= wakelock.o
>  obj-$(CONFIG_HIBERNATION)	+= swsusp.o disk.o snapshot.o swap.o user.o
>  
>  obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
> diff --git a/kernel/power/power.h b/kernel/power/power.h
> index 46b5ec7..1527174 100644
> --- a/kernel/power/power.h
> +++ b/kernel/power/power.h
> @@ -223,3 +223,10 @@ static inline void suspend_thaw_processes(void)
>  {
>  }
>  #endif
> +
> +#ifdef CONFIG_WAKELOCK
> +/* kernel/power/wakelock.c */
> +extern struct workqueue_struct *suspend_work_queue;
> +extern struct wake_lock main_wake_lock;
> +extern suspend_state_t requested_suspend_state;
> +#endif
> diff --git a/kernel/power/wakelock.c b/kernel/power/wakelock.c
> new file mode 100644
> index 0000000..c9e22f9
> --- /dev/null
> +++ b/kernel/power/wakelock.c
> @@ -0,0 +1,598 @@
> +/* kernel/power/wakelock.c
> + *
> + * Copyright (C) 2005-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.
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/rtc.h>
> +#include <linux/suspend.h>
> +#include <linux/syscalls.h> /* sys_sync */
> +#include <linux/wakelock.h>
> +#ifdef CONFIG_WAKELOCK_STAT
> +#include <linux/proc_fs.h>
> +#endif
> +#include "power.h"
> +
> +enum {
> +	DEBUG_EXIT_SUSPEND = 1U << 0,
> +	DEBUG_WAKEUP = 1U << 1,
> +	DEBUG_SUSPEND = 1U << 2,
> +	DEBUG_EXPIRE = 1U << 3,
> +	DEBUG_WAKE_LOCK = 1U << 4,
> +};
> +static int debug_mask = DEBUG_EXIT_SUSPEND | DEBUG_WAKEUP;
> +module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
> +
> +#define WAKE_LOCK_TYPE_MASK              (0x0f)
> +#define WAKE_LOCK_INITIALIZED            (1U << 8)
> +#define WAKE_LOCK_ACTIVE                 (1U << 9)
> +#define WAKE_LOCK_AUTO_EXPIRE            (1U << 10)
> +#define WAKE_LOCK_PREVENTING_SUSPEND     (1U << 11)
> +
> +static DEFINE_SPINLOCK(list_lock);
> +static LIST_HEAD(inactive_locks);
> +static struct list_head active_wake_locks[WAKE_LOCK_TYPE_COUNT];
> +static int current_event_num;
> +struct workqueue_struct *suspend_work_queue;
> +struct wake_lock main_wake_lock;
> +suspend_state_t requested_suspend_state = PM_SUSPEND_MEM;
> +static struct wake_lock unknown_wakeup;
> +
> +#ifdef CONFIG_WAKELOCK_STAT
> +static struct wake_lock deleted_wake_locks;
> +static ktime_t last_sleep_time_update;
> +static int wait_for_wakeup;
> +
> +int get_expired_time(struct wake_lock *lock, ktime_t *expire_time)
> +{
> +	struct timespec ts;
> +	struct timespec kt;
> +	struct timespec tomono;
> +	struct timespec delta;
> +	unsigned long seq;
> +	long timeout;
> +
> +	if (!(lock->flags & WAKE_LOCK_AUTO_EXPIRE))
> +		return 0;
> +	do {
> +		seq = read_seqbegin(&xtime_lock);
> +		timeout = lock->expires - jiffies;
> +		if (timeout > 0)
> +			return 0;
> +		kt = current_kernel_time();
> +		tomono = wall_to_monotonic;
> +	} while (read_seqretry(&xtime_lock, seq));
> +	jiffies_to_timespec(-timeout, &delta);
> +	set_normalized_timespec(&ts, kt.tv_sec + tomono.tv_sec - delta.tv_sec,
> +				kt.tv_nsec + tomono.tv_nsec - delta.tv_nsec);
> +	*expire_time = timespec_to_ktime(ts);
> +	return 1;
> +}
> +
> +
> +static int print_lock_stat(char *buf, struct wake_lock *lock)
> +{
> +	int lock_count = lock->stat.count;
> +	int expire_count = lock->stat.expire_count;
> +	ktime_t active_time = ktime_set(0, 0);
> +	ktime_t total_time = lock->stat.total_time;
> +	ktime_t max_time = lock->stat.max_time;
> +	ktime_t prevent_suspend_time = lock->stat.prevent_suspend_time;
> +	if (lock->flags & WAKE_LOCK_ACTIVE) {
> +		ktime_t now, add_time;
> +		int expired = get_expired_time(lock, &now);
> +		if (!expired)
> +			now = ktime_get();
> +		add_time = ktime_sub(now, lock->stat.last_time);
> +		lock_count++;
> +		if (!expired)
> +			active_time = add_time;
> +		else
> +			expire_count++;
> +		total_time = ktime_add(total_time, add_time);
> +		if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND)
> +			prevent_suspend_time = ktime_add(prevent_suspend_time,
> +					ktime_sub(now, last_sleep_time_update));
> +		if (add_time.tv64 > max_time.tv64)
> +			max_time = add_time;
> +	}
> +
> +	return sprintf(buf, "\"%s\"\t%d\t%d\t%d\t%lld\t%lld\t%lld\t%lld\t"
> +		       "%lld\n", lock->name, lock_count, expire_count,
> +		       lock->stat.wakeup_count, ktime_to_ns(active_time),
> +		       ktime_to_ns(total_time),
> +		       ktime_to_ns(prevent_suspend_time), ktime_to_ns(max_time),
> +		       ktime_to_ns(lock->stat.last_time));
> +}
> +
> +
> +static int wakelocks_read_proc(char *page, char **start, off_t off,
> +			       int count, int *eof, void *data)
> +{
> +	unsigned long irqflags;
> +	struct wake_lock *lock;
> +	int len = 0;
> +	char *p = page;
> +	int type;
> +
> +	spin_lock_irqsave(&list_lock, irqflags);
> +
> +	p += sprintf(p, "name\tcount\texpire_count\twake_count\tactive_since"
> +		     "\ttotal_time\tsleep_time\tmax_time\tlast_change\n");
> +	list_for_each_entry(lock, &inactive_locks, link) {
> +		p += print_lock_stat(p, lock);
> +	}
> +	for (type = 0; type < WAKE_LOCK_TYPE_COUNT; type++) {
> +		list_for_each_entry(lock, &active_wake_locks[type], link)
> +			p += print_lock_stat(p, lock);
> +	}
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +
> +	*start = page + off;
> +
> +	len = p - page;
> +	if (len > off)
> +		len -= off;
> +	else
> +		len = 0;
> +
> +	return len < count ? len  : count;
> +}
> +
> +static void wake_unlock_stat_locked(struct wake_lock *lock, int expired)
> +{
> +	ktime_t duration;
> +	ktime_t now;
> +	if (!(lock->flags & WAKE_LOCK_ACTIVE))
> +		return;
> +	if (get_expired_time(lock, &now))
> +		expired = 1;
> +	else
> +		now = ktime_get();
> +	lock->stat.count++;
> +	if (expired)
> +		lock->stat.expire_count++;
> +	duration = ktime_sub(now, lock->stat.last_time);
> +	lock->stat.total_time = ktime_add(lock->stat.total_time, duration);
> +	if (ktime_to_ns(duration) > ktime_to_ns(lock->stat.max_time))
> +		lock->stat.max_time = duration;
> +	lock->stat.last_time = ktime_get();
> +	if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND) {
> +		duration = ktime_sub(now, last_sleep_time_update);
> +		lock->stat.prevent_suspend_time = ktime_add(
> +			lock->stat.prevent_suspend_time, duration);
> +		lock->flags &= ~WAKE_LOCK_PREVENTING_SUSPEND;
> +	}
> +}
> +
> +static void update_sleep_wait_stats_locked(int done)
> +{
> +	struct wake_lock *lock;
> +	ktime_t now, etime, elapsed, add;
> +	int expired;
> +
> +	now = ktime_get();
> +	elapsed = ktime_sub(now, last_sleep_time_update);
> +	list_for_each_entry(lock, &active_wake_locks[WAKE_LOCK_SUSPEND], link) {

Is this list opperation SMP safe?  what if some on on the other CPU
removes a lock form user mode while walking this guy?  this goes for all
your list walking.

> +		expired = get_expired_time(lock, &etime);
> +		if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND) {
> +			if (expired)
> +				add = ktime_sub(etime, last_sleep_time_update);
> +			else
> +				add = elapsed;
> +			lock->stat.prevent_suspend_time = ktime_add(
> +				lock->stat.prevent_suspend_time, add);
> +		}
> +		if (done || expired)
> +			lock->flags &= ~WAKE_LOCK_PREVENTING_SUSPEND;
> +		else
> +			lock->flags |= WAKE_LOCK_PREVENTING_SUSPEND;
> +	}
> +	last_sleep_time_update = now;
> +}
> +#endif
> +
> +
> +static void expire_wake_lock(struct wake_lock *lock)
> +{
> +#ifdef CONFIG_WAKELOCK_STAT
> +	wake_unlock_stat_locked(lock, 1);
> +#endif
> +	lock->flags &= ~(WAKE_LOCK_ACTIVE | WAKE_LOCK_AUTO_EXPIRE);
> +	list_del(&lock->link);
> +	list_add(&lock->link, &inactive_locks);
> +	if (debug_mask & (DEBUG_WAKE_LOCK | DEBUG_EXPIRE))
> +		pr_info("expired wake lock %s\n", lock->name);
> +}

Are we missing locking for this list opperation?

> +
> +static void print_active_locks(int type)
> +{
> +	unsigned long irqflags;
> +	struct wake_lock *lock;
> +
> +	BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
> +	spin_lock_irqsave(&list_lock, irqflags);
> +	list_for_each_entry(lock, &active_wake_locks[type], link) {
> +		if (lock->flags & WAKE_LOCK_AUTO_EXPIRE) {
> +			long timeout = lock->expires - jiffies;
> +			if (timeout <= 0)
> +				pr_info("wake lock %s, expired\n", lock->name);
> +			else
> +				pr_info("active wake lock %s, time left %ld\n",
> +					lock->name, timeout);
> +		} else
> +			pr_info("active wake lock %s\n", lock->name);
> +	}
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +}
> +
> +static long has_wake_lock_locked(int type)
> +{
> +	struct wake_lock *lock, *n;
> +	long max_timeout = 0;
> +
> +	BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
> +	list_for_each_entry_safe(lock, n, &active_wake_locks[type], link) {
> +		if (lock->flags & WAKE_LOCK_AUTO_EXPIRE) {
> +			long timeout = lock->expires - jiffies;
> +			if (timeout <= 0)
> +				expire_wake_lock(lock);
> +			else if (timeout > max_timeout)
> +				max_timeout = timeout;
> +		} else
> +			return -1;
> +	}
> +	return max_timeout;
> +}
> +
> +long has_wake_lock(int type)
> +{
> +	long ret;
> +	unsigned long irqflags;
> +	spin_lock_irqsave(&list_lock, irqflags);
> +	ret = has_wake_lock_locked(type);
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +	return ret;
> +}
> +
> +static void suspend(struct work_struct *work)

there are a lot of "suspend" functions in the kernel already that have
different calling semantics, can we change this name so my TAG file is
more sane?

> +{
> +	int ret;
> +	int entry_event_num;
> +
> +	if (has_wake_lock(WAKE_LOCK_SUSPEND)) {
> +		if (debug_mask & DEBUG_SUSPEND)
> +			pr_info("suspend: abort suspend\n");
> +		return;
> +	}
> +
> +	entry_event_num = current_event_num;
> +	sys_sync();

um, this feel wrong to me.

> +	if (debug_mask & DEBUG_SUSPEND)
> +		pr_info("suspend: enter suspend\n");
> +	ret = pm_suspend(requested_suspend_state);

oh, you are adding yet another path to getting the system into a
suspended state.  is this necessary?

> +	if (debug_mask & DEBUG_EXIT_SUSPEND) {
> +		struct timespec ts;
> +		struct rtc_time tm;
> +		getnstimeofday(&ts);
> +		rtc_time_to_tm(ts.tv_sec, &tm);
> +		pr_info("suspend: exit suspend, ret = %d "
> +			"(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n", ret,
> +			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
> +			tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
> +	}
> +	if (current_event_num == entry_event_num) {
> +		if (debug_mask & DEBUG_SUSPEND)
> +			pr_info("suspend: pm_suspend returned with no event\n");
> +		wake_lock_timeout(&unknown_wakeup, HZ / 2);
> +	}
> +}
> +static DECLARE_WORK(suspend_work, suspend);
> +
> +static void expire_wake_locks(unsigned long data)
> +{
> +	long has_lock;
> +	unsigned long irqflags;
> +	if (debug_mask & DEBUG_EXPIRE)
> +		pr_info("expire_wake_locks: start\n");
> +	if (debug_mask & DEBUG_SUSPEND)
> +		print_active_locks(WAKE_LOCK_SUSPEND);
> +	spin_lock_irqsave(&list_lock, irqflags);
> +	has_lock = has_wake_lock_locked(WAKE_LOCK_SUSPEND);
> +	if (debug_mask & DEBUG_EXPIRE)
> +		pr_info("expire_wake_locks: done, has_lock %ld\n", has_lock);
> +	if (has_lock == 0)
> +		queue_work(suspend_work_queue, &suspend_work);
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +}
> +static DEFINE_TIMER(expire_timer, expire_wake_locks, 0, 0);
> +
> +static int power_suspend_late(struct platform_device *pdev, pm_message_t state)
> +{
> +	int ret = has_wake_lock(WAKE_LOCK_SUSPEND) ? -EAGAIN : 0;
> +#ifdef CONFIG_WAKELOCK_STAT
> +	wait_for_wakeup = 1;
> +#endif
> +	if (debug_mask & DEBUG_SUSPEND)
> +		pr_info("power_suspend_late return %d\n", ret);
> +	return ret;
> +}
> +
> +static struct platform_driver power_driver = {
> +	.driver.name = "power",
> +	.suspend_late = power_suspend_late,
> +};
> +static struct platform_device power_device = {
> +	.name = "power",
> +};
> +
> +void wake_lock_init(struct wake_lock *lock, int type, const char *name)
> +{
> +	unsigned long irqflags = 0;
> +
> +	if (name)
> +		lock->name = name;
> +	BUG_ON(!lock->name);
> +
> +	if (debug_mask & DEBUG_WAKE_LOCK)
> +		pr_info("wake_lock_init name=%s\n", lock->name);
> +#ifdef CONFIG_WAKELOCK_STAT
> +	lock->stat.count = 0;
> +	lock->stat.expire_count = 0;
> +	lock->stat.wakeup_count = 0;
> +	lock->stat.total_time = ktime_set(0, 0);
> +	lock->stat.prevent_suspend_time = ktime_set(0, 0);
> +	lock->stat.max_time = ktime_set(0, 0);
> +	lock->stat.last_time = ktime_set(0, 0);
> +#endif
> +	lock->flags = (type & WAKE_LOCK_TYPE_MASK) | WAKE_LOCK_INITIALIZED;
> +
> +	INIT_LIST_HEAD(&lock->link);
> +	spin_lock_irqsave(&list_lock, irqflags);
> +	list_add(&lock->link, &inactive_locks);
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +}
> +EXPORT_SYMBOL(wake_lock_init);
> +
> +void wake_lock_destroy(struct wake_lock *lock)
> +{
> +	unsigned long irqflags;
> +	if (debug_mask & DEBUG_WAKE_LOCK)
> +		pr_info("wake_lock_destroy name=%s\n", lock->name);
> +	spin_lock_irqsave(&list_lock, irqflags);
> +	lock->flags &= ~WAKE_LOCK_INITIALIZED;
> +#ifdef CONFIG_WAKELOCK_STAT
> +	if (lock->stat.count) {
> +		deleted_wake_locks.stat.count += lock->stat.count;
> +		deleted_wake_locks.stat.expire_count += lock->stat.expire_count;
> +		deleted_wake_locks.stat.total_time =
> +			ktime_add(deleted_wake_locks.stat.total_time,
> +				  lock->stat.total_time);
> +		deleted_wake_locks.stat.prevent_suspend_time =
> +			ktime_add(deleted_wake_locks.stat.prevent_suspend_time,
> +				  lock->stat.prevent_suspend_time);
> +		deleted_wake_locks.stat.max_time =
> +			ktime_add(deleted_wake_locks.stat.max_time,
> +				  lock->stat.max_time);
> +	}
> +#endif
> +	list_del(&lock->link);
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +}
> +EXPORT_SYMBOL(wake_lock_destroy);
> +
> +static void wake_lock_internal(
> +	struct wake_lock *lock, long timeout, int has_timeout)
> +{
> +	int type;
> +	unsigned long irqflags;
> +	long expire_in;
> +
> +	spin_lock_irqsave(&list_lock, irqflags);
> +	type = lock->flags & WAKE_LOCK_TYPE_MASK;
> +	BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
> +	BUG_ON(!(lock->flags & WAKE_LOCK_INITIALIZED));
> +#ifdef CONFIG_WAKELOCK_STAT
> +	if (type == WAKE_LOCK_SUSPEND && wait_for_wakeup) {
> +		if (debug_mask & DEBUG_WAKEUP)
> +			pr_info("wakeup wake lock: %s\n", lock->name);
> +		wait_for_wakeup = 0;
> +		lock->stat.wakeup_count++;
> +	}
> +	if ((lock->flags & WAKE_LOCK_AUTO_EXPIRE) &&
> +	    (long)(lock->expires - jiffies) <= 0) {
> +		wake_unlock_stat_locked(lock, 0);
> +		lock->stat.last_time = ktime_get();
> +	}
> +#endif
> +	if (!(lock->flags & WAKE_LOCK_ACTIVE)) {
> +		lock->flags |= WAKE_LOCK_ACTIVE;
> +#ifdef CONFIG_WAKELOCK_STAT
> +		lock->stat.last_time = ktime_get();
> +#endif
> +	}
> +	list_del(&lock->link);
> +	if (has_timeout) {
> +		if (debug_mask & DEBUG_WAKE_LOCK)
> +			pr_info("wake_lock: %s, type %d, timeout %ld.%03lu\n",
> +				lock->name, type, timeout / HZ,
> +				(timeout % HZ) * MSEC_PER_SEC / HZ);
> +		lock->expires = jiffies + timeout;
> +		lock->flags |= WAKE_LOCK_AUTO_EXPIRE;
> +		list_add_tail(&lock->link, &active_wake_locks[type]);
> +	} else {
> +		if (debug_mask & DEBUG_WAKE_LOCK)
> +			pr_info("wake_lock: %s, type %d\n", lock->name, type);
> +		lock->expires = LONG_MAX;
> +		lock->flags &= ~WAKE_LOCK_AUTO_EXPIRE;
> +		list_add(&lock->link, &active_wake_locks[type]);
> +	}
> +	if (type == WAKE_LOCK_SUSPEND) {
> +		current_event_num++;
> +#ifdef CONFIG_WAKELOCK_STAT
> +		if (lock == &main_wake_lock)
> +			update_sleep_wait_stats_locked(1);
> +		else if (!wake_lock_active(&main_wake_lock))
> +			update_sleep_wait_stats_locked(0);
> +#endif
> +		if (has_timeout)
> +			expire_in = has_wake_lock_locked(type);
> +		else
> +			expire_in = -1;
> +		if (expire_in > 0) {
> +			if (debug_mask & DEBUG_EXPIRE)
> +				pr_info("wake_lock: %s, start expire timer, "
> +					"%ld\n", lock->name, expire_in);
> +			mod_timer(&expire_timer, jiffies + expire_in);
> +		} else {
> +			if (del_timer(&expire_timer))
> +				if (debug_mask & DEBUG_EXPIRE)
> +					pr_info("wake_lock: %s, stop expire "
> +						"timer\n", lock->name);
> +			if (expire_in == 0)
> +				queue_work(suspend_work_queue, &suspend_work);
> +		}
> +	}
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +}
> +
> +void wake_lock(struct wake_lock *lock)
> +{
> +	wake_lock_internal(lock, 0, 0);
> +}
> +EXPORT_SYMBOL(wake_lock);
> +
> +void wake_lock_timeout(struct wake_lock *lock, long timeout)
> +{
> +	wake_lock_internal(lock, timeout, 1);
> +}
> +EXPORT_SYMBOL(wake_lock_timeout);
> +
> +void wake_unlock(struct wake_lock *lock)
> +{
> +	int type;
> +	unsigned long irqflags;
> +	spin_lock_irqsave(&list_lock, irqflags);
> +	type = lock->flags & WAKE_LOCK_TYPE_MASK;
> +#ifdef CONFIG_WAKELOCK_STAT
> +	wake_unlock_stat_locked(lock, 0);
> +#endif
> +	if (debug_mask & DEBUG_WAKE_LOCK)
> +		pr_info("wake_unlock: %s\n", lock->name);
> +	lock->flags &= ~(WAKE_LOCK_ACTIVE | WAKE_LOCK_AUTO_EXPIRE);
> +	list_del(&lock->link);
> +	list_add(&lock->link, &inactive_locks);
> +	if (type == WAKE_LOCK_SUSPEND) {
> +		long has_lock = has_wake_lock_locked(type);
> +		if (has_lock > 0) {
> +			if (debug_mask & DEBUG_EXPIRE)
> +				pr_info("wake_unlock: %s, start expire timer, "
> +					"%ld\n", lock->name, has_lock);
> +			mod_timer(&expire_timer, jiffies + has_lock);
> +		} else {
> +			if (del_timer(&expire_timer))
> +				if (debug_mask & DEBUG_EXPIRE)
> +					pr_info("wake_unlock: %s, stop expire "
> +						"timer\n", lock->name);
> +			if (has_lock == 0)
> +				queue_work(suspend_work_queue, &suspend_work);
> +		}
> +		if (lock == &main_wake_lock) {
> +			if (debug_mask & DEBUG_SUSPEND)
> +				print_active_locks(WAKE_LOCK_SUSPEND);
> +#ifdef CONFIG_WAKELOCK_STAT
> +			update_sleep_wait_stats_locked(0);
> +#endif
> +		}
> +	}
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +}
> +EXPORT_SYMBOL(wake_unlock);
> +
> +int wake_lock_active(struct wake_lock *lock)
> +{
> +	return !!(lock->flags & WAKE_LOCK_ACTIVE);
> +}
> +EXPORT_SYMBOL(wake_lock_active);
> +
> +static int __init wakelocks_init(void)
> +{
> +	int ret;
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(active_wake_locks); i++)
> +		INIT_LIST_HEAD(&active_wake_locks[i]);
> +
> +#ifdef CONFIG_WAKELOCK_STAT
> +	wake_lock_init(&deleted_wake_locks, WAKE_LOCK_SUSPEND,
> +			"deleted_wake_locks");
> +#endif
> +	wake_lock_init(&main_wake_lock, WAKE_LOCK_SUSPEND, "main");
> +	wake_lock(&main_wake_lock);
> +	wake_lock_init(&unknown_wakeup, WAKE_LOCK_SUSPEND, "unknown_wakeups");
> +
> +	ret = platform_device_register(&power_device);
> +	if (ret) {
> +		pr_err("wakelocks_init: platform_device_register failed\n");
> +		goto err_platform_device_register;
> +	}
> +	ret = platform_driver_register(&power_driver);
> +	if (ret) {
> +		pr_err("wakelocks_init: platform_driver_register failed\n");
> +		goto err_platform_driver_register;
> +	}
> +
> +	suspend_work_queue = create_singlethread_workqueue("suspend");
> +	if (suspend_work_queue == NULL) {
> +		ret = -ENOMEM;
> +		goto err_suspend_work_queue;
> +	}
> +
> +#ifdef CONFIG_WAKELOCK_STAT
> +	create_proc_read_entry("wakelocks", S_IRUGO, NULL,
> +				wakelocks_read_proc, NULL);

Shouldn't we *not* be using /proc?  I think this should be under sysfs.

> +#endif
> +
> +	return 0;
> +
> +err_suspend_work_queue:
> +	platform_driver_unregister(&power_driver);
> +err_platform_driver_register:
> +	platform_device_unregister(&power_device);
> +err_platform_device_register:
> +	wake_lock_destroy(&unknown_wakeup);
> +	wake_lock_destroy(&main_wake_lock);
> +#ifdef CONFIG_WAKELOCK_STAT
> +	wake_lock_destroy(&deleted_wake_locks);
> +#endif
> +	return ret;
> +}
> +
> +static void  __exit wakelocks_exit(void)
> +{
> +#ifdef CONFIG_WAKELOCK_STAT
> +	remove_proc_entry("wakelocks", NULL);
> +#endif
> +	destroy_workqueue(suspend_work_queue);
> +	platform_driver_unregister(&power_driver);
> +	platform_device_unregister(&power_device);
> +	wake_lock_destroy(&unknown_wakeup);
> +	wake_lock_destroy(&main_wake_lock);
> +#ifdef CONFIG_WAKELOCK_STAT
> +	wake_lock_destroy(&deleted_wake_locks);
> +#endif
> +}
> +
> +core_initcall(wakelocks_init);
> +module_exit(wakelocks_exit);
> -- 
> 1.6.1
> 
> _______________________________________________
> linux-pm mailing list
> linux-pm@lists.linux-foundation.org
> https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-05 22:51   ` mark gross
@ 2009-02-06  0:13     ` Arve Hjønnevåg
  2009-02-10 20:25       ` Pavel Machek
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-06  0:13 UTC (permalink / raw)
  To: mgross; +Cc: swetland, linux-pm, u.luckas, ncunningham

On Thu, Feb 5, 2009 at 2:51 PM, mark gross <mgross@linux.intel.com> wrote:
>> +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.
>
> How much of this can be implemented using a pm-qos approach?

WAKE_LOCK_IDLE overlaps with pm-qos, if you use it to prevent latency.

>
>> +
>> +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       +++          +++
>> +
>
> This feels a lot like operating points implemented as a collection of
> product specific binary locks.  How could this be generalized to be less
> application specific?

Are you complaining about the example being product specific, or the
api? I don't think the api is product specific.

>> +When the driver determines that it needs to run (usually in an interrupt
>> +handler) it calls wake_lock:
>> +     wake_lock(&state->wakelock);
>
> um, if a driver grabs the wakelock for another device that is sleeping
> how will it know when that sleeping device is ready to be used?  Is

A driver does not grab another driver's wakelock. If your driver
depends on another device it should wait for resume to be called
before accessing it.

> wake_lock going to block until the dives its locking is in a good power
> state?  (I'm guessing yes) Is doing this in the context of and IRQ a
> good idea?

wake_lock never blocks.

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

What is your question?


>> +struct wake_lock {
>> +#ifdef CONFIG_HAS_WAKELOCK
>
> Shouldn't this #ifdef be in the files using wake_lock.h?  If
> !CONFIG_HAS_WAKELOCK then should all the definitions here not be parsed
> at compile time?

I think the general policy is to avoid #ifdefs in the .c files.

>
>> +     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);
>
> Type? or class?  What is this type concept?  Should we have some strong
> typing to the enum list above or at least a comment on what are the
> types that are valid to call this API with?

+       WAKE_LOCK_SUSPEND, /* Prevent suspend */
+       WAKE_LOCK_IDLE,    /* Prevent low power idle */

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 06/13] PM: Implement early suspend api
  2009-02-05  2:50           ` [PATCH 06/13] PM: Implement early suspend api Arve Hjønnevåg
  2009-02-05  2:50             ` [PATCH 07/13] PM: wakelock: Add /sys/power/request_state Arve Hjønnevåg
@ 2009-02-06  0:18             ` mark gross
  2009-02-07 22:47             ` Rafael J. Wysocki
  2 siblings, 0 replies; 251+ messages in thread
From: mark gross @ 2009-02-06  0:18 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: swetland, linux-pm, u.luckas, ncunningham

On Wed, Feb 04, 2009 at 06:50:19PM -0800, Arve Hjønnevåg wrote:
> Signed-off-by: Arve Hjønnevåg <arve@android.com>
> ---
>  kernel/power/Kconfig        |   12 +++
>  kernel/power/Makefile       |    1 +
>  kernel/power/earlysuspend.c |  178 +++++++++++++++++++++++++++++++++++++++++++
>  kernel/power/power.h        |    6 ++
>  4 files changed, 197 insertions(+), 0 deletions(-)
>  create mode 100644 kernel/power/earlysuspend.c
> 
> diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
> index dd76467..689abfe 100644
> --- a/kernel/power/Kconfig
> +++ b/kernel/power/Kconfig
> @@ -119,6 +119,9 @@ config SUSPEND_FREEZER
>  config HAS_WAKELOCK
>  	bool
>  
> +config HAS_EARLYSUSPEND
> +	bool
> +
>  config WAKELOCK
>  	bool "Wake lock"
>  	depends on PM && RTC_CLASS
> @@ -144,6 +147,15 @@ config DISABLE_SYS_POWER_STATE
>  	  want to run user-space code that does not support wakelocks, do not
>  	  enable this option since it removes the interface.
>  
> +config EARLYSUSPEND
> +	bool "Early suspend"
> +	depends on WAKELOCK
> +	default y
> +	select HAS_EARLYSUSPEND
> +	---help---
> +	  Call early suspend handlers when the user requested sleep state
> +	  changes.
> +
>  config HIBERNATION
>  	bool "Hibernation (aka 'suspend to disk')"
>  	depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
> diff --git a/kernel/power/Makefile b/kernel/power/Makefile
> index 8d8672b..2f17e1d 100644
> --- a/kernel/power/Makefile
> +++ b/kernel/power/Makefile
> @@ -7,6 +7,7 @@ obj-y				:= main.o
>  obj-$(CONFIG_PM_SLEEP)		+= console.o
>  obj-$(CONFIG_FREEZER)		+= process.o
>  obj-$(CONFIG_WAKELOCK)		+= wakelock.o
> +obj-$(CONFIG_EARLYSUSPEND)	+= earlysuspend.o
>  obj-$(CONFIG_HIBERNATION)	+= swsusp.o disk.o snapshot.o swap.o user.o
>  
>  obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
> diff --git a/kernel/power/earlysuspend.c b/kernel/power/earlysuspend.c
> new file mode 100644
> index 0000000..4d70a7e
> --- /dev/null
> +++ b/kernel/power/earlysuspend.c
> @@ -0,0 +1,178 @@
> +/* kernel/power/earlysuspend.c
> + *
> + * Copyright (C) 2005-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.
> + *
> + */
> +
> +#include <linux/earlysuspend.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/rtc.h>
> +#include <linux/syscalls.h> /* sys_sync */
> +#include <linux/wakelock.h>
> +#include <linux/workqueue.h>
> +
> +#include "power.h"
> +
> +enum {
> +	DEBUG_USER_STATE = 1U << 0,
> +	DEBUG_SUSPEND = 1U << 1,
> +};
> +static int debug_mask = DEBUG_USER_STATE;
> +module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
> +
> +static DEFINE_MUTEX(early_suspend_lock);
> +static LIST_HEAD(early_suspend_handlers);
> +static void early_suspend(struct work_struct *work);
> +static void late_resume(struct work_struct *work);
> +static DECLARE_WORK(early_suspend_work, early_suspend);
> +static DECLARE_WORK(late_resume_work, late_resume);
> +static DEFINE_SPINLOCK(state_lock);
> +enum {
> +	SUSPEND_REQUESTED = 0x1,
> +	SUSPENDED = 0x2,
> +	SUSPEND_REQUESTED_AND_SUSPENDED = SUSPEND_REQUESTED | SUSPENDED,
> +};
> +static int state;
> +
> +void register_early_suspend(struct early_suspend *handler)
> +{
> +	struct list_head *pos;
> +
> +	mutex_lock(&early_suspend_lock);
> +	list_for_each(pos, &early_suspend_handlers) {
> +		struct early_suspend *e;
> +		e = list_entry(pos, struct early_suspend, link);
> +		if (e->level > handler->level)
> +			break;
> +	}
> +	list_add_tail(&handler->link, pos);
> +	if ((state & SUSPENDED) && handler->suspend)
> +		handler->suspend(handler);
> +	mutex_unlock(&early_suspend_lock);
> +}
> +EXPORT_SYMBOL(register_early_suspend);
> +
> +void unregister_early_suspend(struct early_suspend *handler)
> +{
> +	mutex_lock(&early_suspend_lock);
> +	list_del(&handler->link);
> +	mutex_unlock(&early_suspend_lock);
> +}
> +EXPORT_SYMBOL(unregister_early_suspend);
> +
> +static void early_suspend(struct work_struct *work)
> +{
> +	struct early_suspend *pos;
> +	unsigned long irqflags;
> +	int abort = 0;
> +
> +	mutex_lock(&early_suspend_lock);
> +	spin_lock_irqsave(&state_lock, irqflags);
> +	if (state == SUSPEND_REQUESTED)
> +		state |= SUSPENDED;
> +	else
> +		abort = 1;
> +	spin_unlock_irqrestore(&state_lock, irqflags);
> +
> +	if (abort) {
> +		if (debug_mask & DEBUG_SUSPEND)
> +			pr_info("early_suspend: abort, state %d\n", state);
> +		mutex_unlock(&early_suspend_lock);
> +		goto abort;
> +	}
> +
> +	if (debug_mask & DEBUG_SUSPEND)
> +		pr_info("early_suspend: call handlers\n");
> +	list_for_each_entry(pos, &early_suspend_handlers, link) {
> +		if (pos->suspend)
> +			pos->suspend(pos);
> +	}
> +	mutex_unlock(&early_suspend_lock);
> +
> +	if (debug_mask & DEBUG_SUSPEND)
> +		pr_info("early_suspend: sync\n");
> +
> +	sys_sync();

couldn't this trigger GC if you are running something like JFFS2 and
have an indeterminant execution time?  

tough call.  predictable suspend times or gard against FS corruption.

> +abort:
> +	spin_lock_irqsave(&state_lock, irqflags);
> +	if (state == SUSPEND_REQUESTED_AND_SUSPENDED)
> +		wake_unlock(&main_wake_lock);
> +	spin_unlock_irqrestore(&state_lock, irqflags);
> +}
> +
> +static void late_resume(struct work_struct *work)
> +{
> +	struct early_suspend *pos;
> +	unsigned long irqflags;
> +	int abort = 0;
> +
> +	mutex_lock(&early_suspend_lock);
> +	spin_lock_irqsave(&state_lock, irqflags);
> +	if (state == SUSPENDED)
> +		state = 0; /* clear SUSPENDED */
> +	else
> +		abort = 1;
> +	spin_unlock_irqrestore(&state_lock, irqflags);
> +
> +	if (abort) {
> +		if (debug_mask & DEBUG_SUSPEND)
> +			pr_info("late_resume: abort, state %d\n", state);
> +		goto abort;
> +	}
> +	if (debug_mask & DEBUG_SUSPEND)
> +		pr_info("late_resume: call handlers\n");
> +	list_for_each_entry_reverse(pos, &early_suspend_handlers, link)
> +		if (pos->resume)
> +			pos->resume(pos);
> +	if (debug_mask & DEBUG_SUSPEND)
> +		pr_info("late_resume: done\n");
> +abort:
> +	mutex_unlock(&early_suspend_lock);
> +}
> +
> +void request_suspend_state(suspend_state_t new_state)
> +{
> +	unsigned long irqflags;
> +	int old_sleep;
> +
> +	spin_lock_irqsave(&state_lock, irqflags);
> +	old_sleep = state & SUSPEND_REQUESTED;
> +	if (debug_mask & DEBUG_USER_STATE) {
> +		struct timespec ts;
> +		struct rtc_time tm;
> +		getnstimeofday(&ts);
> +		rtc_time_to_tm(ts.tv_sec, &tm);
> +		pr_info("request_suspend_state: %s (%d->%d) at %lld "
> +			"(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n",
> +			new_state != PM_SUSPEND_ON ? "sleep" : "wakeup",
> +			requested_suspend_state, new_state,
> +			ktime_to_ns(ktime_get()),
> +			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
> +			tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
> +	}
> +	if (!old_sleep && new_state != PM_SUSPEND_ON) {
> +		state |= SUSPEND_REQUESTED;
> +		queue_work(suspend_work_queue, &early_suspend_work);
> +	} else if (old_sleep && new_state == PM_SUSPEND_ON) {
> +		state &= ~SUSPEND_REQUESTED;
> +		wake_lock(&main_wake_lock);
> +		queue_work(suspend_work_queue, &late_resume_work);
> +	}
> +	requested_suspend_state = new_state;
> +	spin_unlock_irqrestore(&state_lock, irqflags);
> +}
> +
> +suspend_state_t get_suspend_state(void)
> +{
> +	return requested_suspend_state;
> +}
> diff --git a/kernel/power/power.h b/kernel/power/power.h
> index ed1b7f4..acbb13a 100644
> --- a/kernel/power/power.h
> +++ b/kernel/power/power.h
> @@ -231,3 +231,9 @@ extern struct wake_lock main_wake_lock;
>  extern suspend_state_t requested_suspend_state;
>  extern bool ignore_suspend_wakelocks;
>  #endif
> +
> +#ifdef CONFIG_EARLYSUSPEND
> +/* kernel/power/earlysuspend.c */
> +void request_suspend_state(suspend_state_t state);
> +suspend_state_t get_suspend_state(void);
> +#endif
> -- 
> 1.6.1
> 
> _______________________________________________
> linux-pm mailing list
> linux-pm@lists.linux-foundation.org
> https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-05  9:11   ` [PATCH 01/13] PM: Add wake lock api Pavel Machek
@ 2009-02-06  0:28     ` Arve Hjønnevåg
  2009-02-06  9:45       ` Uli Luckas
                         ` (2 more replies)
  2009-02-06  1:32     ` [PATCH 01/13] PM: Add wake lock api mark gross
  1 sibling, 3 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-06  0:28 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thu, Feb 5, 2009 at 1:11 AM, Pavel Machek <pavel@ucw.cz> wrote:
> On Wed 2009-02-04 18:50:14, Arve Hj??nnev??g wrote:
>> +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
>
> idle states are very different from suspend. Mixing them does not look
> like good idea... and IIRC we already have API somewhere to prevent
> deep idle states. Intel did it for their wireless cards IIRC.

If you are talking about the pm_qos interface, then yes there is some
overlap. We did not use the pm_qos interface since it does a linear
scan for a string every time you change a requirement, and it only let
you specify the latency you need not the power level. We have
interrupts that stop working at the lowest power level and this does
not easily translate into a latency value.

>> +                 Key pressed   Key released
>> +                     |             |
>> +keypad-scan          ++++++++++++++++++
>> +input-event-queue        +++          +++
>> +process-input-events       +++          +++
>> +
>
> I'm not sure if keyboard scanning example is good here. It is very
> t-mobile G1 specific.

There is no G1 specific code in the keypad driver. I also don't
remember seeing any development boards without a similar keypad. I
like this example since it show how an event can be passed from the
kernel to user-space.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held.
  2009-02-05  2:50                 ` [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held Arve Hjønnevåg
  2009-02-05  2:50                   ` [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes Arve Hjønnevåg
  2009-02-05  8:55                   ` [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held Pavel Machek
@ 2009-02-06  0:35                   ` mark gross
  2 siblings, 0 replies; 251+ messages in thread
From: mark gross @ 2009-02-06  0:35 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: swetland, linux-pm, u.luckas, ncunningham

On Wed, Feb 04, 2009 at 06:50:22PM -0800, Arve Hjønnevåg wrote:
> Avoids a problem where the device sometimes hangs for 20 seconds
> before the screen is turned on.
>

wouldn't it be better to find out what freeze_task call is blocking and
fix that?

 
> Signed-off-by: Arve Hjønnevåg <arve@android.com>
> ---
>  kernel/power/process.c |   22 +++++++++++++++++-----
>  1 files changed, 17 insertions(+), 5 deletions(-)
> 
> diff --git a/kernel/power/process.c b/kernel/power/process.c
> index ca63401..8388d01 100644
> --- a/kernel/power/process.c
> +++ b/kernel/power/process.c
> @@ -13,6 +13,7 @@
>  #include <linux/module.h>
>  #include <linux/syscalls.h>
>  #include <linux/freezer.h>
> +#include <linux/wakelock.h>
>  
>  /* 
>   * Timeout for stopping processes
> @@ -36,6 +37,7 @@ static int try_to_freeze_tasks(bool sig_only)
>  	struct timeval start, end;
>  	u64 elapsed_csecs64;
>  	unsigned int elapsed_csecs;
> +	unsigned int wakeup = 0;
>  
>  	do_gettimeofday(&start);
>  
> @@ -62,6 +64,10 @@ static int try_to_freeze_tasks(bool sig_only)
>  		} while_each_thread(g, p);
>  		read_unlock(&tasklist_lock);
>  		yield();			/* Yield is okay here */
> +		if (todo && has_wake_lock(WAKE_LOCK_SUSPEND)) {
> +			wakeup = 1;
> +			break;
> +		}

this effectivey give the freezing algorithm one shot at putting threads
into a suspend safe state.  arn't you risking bugs on resume by doing
this?

>  		if (time_after(jiffies, end_time))
>  			break;
>  	} while (todo);
> @@ -77,11 +83,17 @@ static int try_to_freeze_tasks(bool sig_only)
>  		 * and caller must call thaw_processes() if something fails),
>  		 * but it cleans up leftover PF_FREEZE requests.
>  		 */
> -		printk("\n");
> -		printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds "
> -				"(%d tasks refusing to freeze):\n",
> -				elapsed_csecs / 100, elapsed_csecs % 100, todo);
> -		show_state();
> +		if (wakeup) {
> +			printk("\n");
> +			printk(KERN_ERR "Freezing of %s aborted\n",
> +					sig_only ? "user space " : "tasks ");
> +		} else {
> +			printk("\n");
> +			printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds "
> +					"(%d tasks refusing to freeze):\n",
> +					elapsed_csecs / 100, elapsed_csecs % 100, todo);
> +			show_state();
> +		}
>  		read_lock(&tasklist_lock);
>  		do_each_thread(g, p) {
>  			task_lock(p);
> -- 
> 1.6.1
> 
> _______________________________________________
> linux-pm mailing list
> linux-pm@lists.linux-foundation.org
> https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 03/13] PM: Implement wakelock api.
  2009-02-06  0:10       ` mark gross
@ 2009-02-06  0:38         ` Arve Hjønnevåg
  2009-02-07  0:33           ` mark gross
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-06  0:38 UTC (permalink / raw)
  To: mgross; +Cc: swetland, linux-pm, u.luckas, ncunningham

On Thu, Feb 5, 2009 at 4:10 PM, mark gross <mgross@linux.intel.com> wrote:
> On Wed, Feb 04, 2009 at 06:50:16PM -0800, Arve Hjønnevåg wrote:
>> +static void update_sleep_wait_stats_locked(int done)
>> +{
>> +     struct wake_lock *lock;
>> +     ktime_t now, etime, elapsed, add;
>> +     int expired;
>> +
>> +     now = ktime_get();
>> +     elapsed = ktime_sub(now, last_sleep_time_update);
>> +     list_for_each_entry(lock, &active_wake_locks[WAKE_LOCK_SUSPEND], link) {
>
> Is this list opperation SMP safe?  what if some on on the other CPU
> removes a lock form user mode while walking this guy?  this goes for all
> your list walking.

I have not tested the code on an SMP system, but the list is protected
by a spinlock.

>> +static void expire_wake_lock(struct wake_lock *lock)
>> +{
>> +#ifdef CONFIG_WAKELOCK_STAT
>> +     wake_unlock_stat_locked(lock, 1);
>> +#endif
>> +     lock->flags &= ~(WAKE_LOCK_ACTIVE | WAKE_LOCK_AUTO_EXPIRE);
>> +     list_del(&lock->link);
>> +     list_add(&lock->link, &inactive_locks);
>> +     if (debug_mask & (DEBUG_WAKE_LOCK | DEBUG_EXPIRE))
>> +             pr_info("expired wake lock %s\n", lock->name);
>> +}
>
> Are we missing locking for this list opperation?

No.

>> +static void suspend(struct work_struct *work)
>
> there are a lot of "suspend" functions in the kernel already that have
> different calling semantics, can we change this name so my TAG file is
> more sane?

OK.

>
>> +{
>> +     int ret;
>> +     int entry_event_num;
>> +
>> +     if (has_wake_lock(WAKE_LOCK_SUSPEND)) {
>> +             if (debug_mask & DEBUG_SUSPEND)
>> +                     pr_info("suspend: abort suspend\n");
>> +             return;
>> +     }
>> +
>> +     entry_event_num = current_event_num;
>> +     sys_sync();
>
> um, this feel wrong to me.

Wrong or redundant? I can remove sys_sync here since pm_suspend calls it anyway.

>
>> +     if (debug_mask & DEBUG_SUSPEND)
>> +             pr_info("suspend: enter suspend\n");
>> +     ret = pm_suspend(requested_suspend_state);
>
> oh, you are adding yet another path to getting the system into a
> suspended state.  is this necessary?

Yes.

>> +#ifdef CONFIG_WAKELOCK_STAT
>> +     create_proc_read_entry("wakelocks", S_IRUGO, NULL,
>> +                             wakelocks_read_proc, NULL);
>
> Shouldn't we *not* be using /proc?  I think this should be under sysfs.

It is not allowed under sysfs. Debugfs has been suggested, but we
don't have debugfs mounted, and we include the wakelock stats in debug
reports.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-05  9:11   ` [PATCH 01/13] PM: Add wake lock api Pavel Machek
  2009-02-06  0:28     ` Arve Hjønnevåg
@ 2009-02-06  1:32     ` mark gross
  1 sibling, 0 replies; 251+ messages in thread
From: mark gross @ 2009-02-06  1:32 UTC (permalink / raw)
  To: Pavel Machek; +Cc: swetland, u.luckas, ncunningham, linux-pm

On Thu, Feb 05, 2009 at 10:11:32AM +0100, Pavel Machek wrote:
> On Wed 2009-02-04 18:50:14, Arve Hj??nnev??g wrote:
> > Signed-off-by: Arve Hj??nnev??g <arve@android.com>
> > ---
> >  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.txt
> > new file mode 100644
> > index 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
> 
> idle states are very different from suspend. Mixing them does not look
> like good idea... and IIRC we already have API somewhere to prevent
> deep idle states. Intel did it for their wireless cards IIRC.

PM QOS does this.

> 
> 
> > +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       +++          +++
> > +
> 
> I'm not sure if keyboard scanning example is good here. It is very
> t-mobile G1 specific.
> 								Pavel
> -- 
> (english) http://www.livejournal.com/~pavelmachek
> (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
> _______________________________________________
> linux-pm mailing list
> linux-pm@lists.linux-foundation.org
> https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes.
  2009-02-05  9:03                     ` [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes Pavel Machek
  2009-02-05  9:37                       ` Arve Hjønnevåg
@ 2009-02-06  2:29                       ` Arve Hjønnevåg
  2009-02-08 22:02                         ` Pavel Machek
  1 sibling, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-06  2:29 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thu, Feb 5, 2009 at 1:03 AM, Pavel Machek <pavel@ucw.cz> wrote:
> changelog would be welcome.
    PM: earlysuspend: Add console switch when user requested sleep
state changes.

    When early-suspend is enabled, the framebuffer is turned off at
    early-suspend. If CONSOLE_EARLYSUSPEND is enabled, a console switch
    is used to notify user space that it should stop drawing before
    the framebuffer is disabled, and that it should repaint and resume
    drawing after the framebuffer is turned back on.


-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held.
  2009-02-05 10:02                           ` Pavel Machek
  2009-02-05 10:08                             ` Arve Hjønnevåg
@ 2009-02-06  3:42                             ` Arve Hjønnevåg
  2009-02-08 23:00                               ` Pavel Machek
  1 sibling, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-06  3:42 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thu, Feb 5, 2009 at 2:02 AM, Pavel Machek <pavel@ucw.cz> wrote:
> ...so I guess I'll wait for extended description.
    PM: wakelock: Abort task freezing if a wakelock is locked.

    If a wakelock is locked, suspend will fail anyway. Since try_to_freeze_tasks
    can take up to 20 seconds to complete or fail, aborting as soon as someone
    locks a wakelock (e.g. from an interrupt handler) improves the worst case
    wakeup latency.

    On an older kernel where task freezing could fail for processes attached
    to a debugger, this fixed a problem where the device sometimes hung for
    20 seconds before the screen turned on.


-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 02/13] PM: Add early suspend api.
  2009-02-05 23:26     ` mark gross
@ 2009-02-06  9:33       ` Uli Luckas
  2009-02-06 23:26         ` Arve Hjønnevåg
  0 siblings, 1 reply; 251+ messages in thread
From: Uli Luckas @ 2009-02-06  9:33 UTC (permalink / raw)
  To: mgross; +Cc: swetland, ncunningham, linux-pm

On Friday, 6. February 2009, mark gross wrote:
> On Wed, Feb 04, 2009 at 06:50:15PM -0800, Arve Hjønnevåg wrote:
> > Signed-off-by: Arve Hjønnevåg <arve@android.com>
> > ---
> >  Documentation/power/early-suspend.txt |   26 +++++++++++++++
> >  include/linux/earlysuspend.h          |   55
> > +++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 0
> > deletions(-)
> >  create mode 100644 Documentation/power/early-suspend.txt
> >  create mode 100755 include/linux/earlysuspend.h
> >
> > diff --git a/Documentation/power/early-suspend.txt
> > b/Documentation/power/early-suspend.txt new file mode 100644
> > index 0000000..8286d3a
> > --- /dev/null
> > +++ b/Documentation/power/early-suspend.txt
> > @@ -0,0 +1,26 @@
> > +Early-suspend
> > +=============
> > +
> > +The early-suspend api allows drivers to get notified when user-space
> > writes to +/sys/power/request_state to indicate that the user visible
> > sleep state should +change. A level controls what order the handlers are
> > called in. Suspend +handlers are called in low to high level order,
> > resume handlers are called in +the opposite order.
> > +
> > +Four levels are defined:
> > +EARLY_SUSPEND_LEVEL_BLANK_SCREEN:
> > +  On suspend the screen should be turned off but the framebuffer must
> > still be +  accessible. On resume the screen can be turned back on.
> > +
> > +EARLY_SUSPEND_LEVEL_STOP_DRAWING:
> > +  On suspend this level notifies user-space that it should stop
> > accessing the +  framebuffer and it waits for it to complete. On resume
> > it notifies user-space +  that it should resume screen access.
> > +  Two methods are provided, console switch or a sysfs interface.
> > +
> > +EARLY_SUSPEND_LEVEL_DISABLE_FB:
> > +  Turn off the framebuffer on suspend and back on on resume.
> > +
> > +EARLY_SUSPEND_LEVEL_STOP_INPUT:
> > +  On suspend turn off input devices that are not capable of wakeup or
> > where +  wakeup is disabled. On resume turn the same devices back on.
>
> these levels names are domain and device profile centric.  How can we
> make these be applicable to more than the HTC dream?
>
> Why 4 levels?  4 seems like too many, but why stop at 4 why not 8?
>
The random number 4 comes from randomly pushing things from userspace to 
kernelspace.
The only thing that I can see the kernel really needs to do is inform user 
space when it comes back from suspend.
I never got a reply to why userspace should ever have to stop drawing to the 
frame buffer. If there is a valid reason for that, we might also need a 
blocking pre-suspend notifier, telling userspace that the device will suspend 
imediately.

Uli

-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-06  0:28     ` Arve Hjønnevåg
@ 2009-02-06  9:45       ` Uli Luckas
  2009-02-08 21:30       ` Pavel Machek
  2009-02-08 22:17       ` non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock api.) Pavel Machek
  2 siblings, 0 replies; 251+ messages in thread
From: Uli Luckas @ 2009-02-06  9:45 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: ncunningham, swetland, linux-pm

On Friday, 6. February 2009, Arve Hjønnevåg wrote:
> On Thu, Feb 5, 2009 at 1:11 AM, Pavel Machek <pavel@ucw.cz> wrote:
> > On Wed 2009-02-04 18:50:14, Arve Hj??nnev??g wrote:
> >> +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
> >
> > idle states are very different from suspend. Mixing them does not look
> > like good idea... and IIRC we already have API somewhere to prevent
> > deep idle states. Intel did it for their wireless cards IIRC.
>
> If you are talking about the pm_qos interface, then yes there is some
> overlap. We did not use the pm_qos interface since it does a linear
> scan for a string every time you change a requirement, and it only let
> you specify the latency you need not the power level. We have
> interrupts that stop working at the lowest power level and this does
> not easily translate into a latency value.
>
> >> +                 Key pressed   Key released
> >> +                     |             |
> >> +keypad-scan          ++++++++++++++++++
> >> +input-event-queue        +++          +++
> >> +process-input-events       +++          +++
> >> +
> >
> > I'm not sure if keyboard scanning example is good here. It is very
> > t-mobile G1 specific.
>
> There is no G1 specific code in the keypad driver. I also don't
> remember seeing any development boards without a similar keypad. I
> like this example since it show how an event can be passed from the
> kernel to user-space.
>
I absolutely agree. The example shows how you can keep wake locks right from 
the time the interrupt comes in through all levels until a user space action 
gets triggered.

Uli

-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 02/13] PM: Add early suspend api.
  2009-02-06  9:33       ` Uli Luckas
@ 2009-02-06 23:26         ` Arve Hjønnevåg
  0 siblings, 0 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-06 23:26 UTC (permalink / raw)
  To: Uli Luckas; +Cc: swetland, linux-pm, ncunningham

On Fri, Feb 6, 2009 at 1:33 AM, Uli Luckas <u.luckas@road.de> wrote:
>> > +Four levels are defined:
>> > +EARLY_SUSPEND_LEVEL_BLANK_SCREEN:
>> > +  On suspend the screen should be turned off but the framebuffer must
>> > still be +  accessible. On resume the screen can be turned back on.
>> > +
>> > +EARLY_SUSPEND_LEVEL_STOP_DRAWING:
>> > +  On suspend this level notifies user-space that it should stop
>> > accessing the +  framebuffer and it waits for it to complete. On resume
>> > it notifies user-space +  that it should resume screen access.
>> > +  Two methods are provided, console switch or a sysfs interface.
>> > +
>> > +EARLY_SUSPEND_LEVEL_DISABLE_FB:
>> > +  Turn off the framebuffer on suspend and back on on resume.
>> > +
>> > +EARLY_SUSPEND_LEVEL_STOP_INPUT:
>> > +  On suspend turn off input devices that are not capable of wakeup or
>> > where +  wakeup is disabled. On resume turn the same devices back on.
>>
>> these levels names are domain and device profile centric.  How can we
>> make these be applicable to more than the HTC dream?
>>
>> Why 4 levels?  4 seems like too many, but why stop at 4 why not 8?
>>
> The random number 4 comes from randomly pushing things from userspace to
> kernelspace.

You can use as many levels as you want. We defined these four levels
because they should be called in a specific order.

> The only thing that I can see the kernel really needs to do is inform user
> space when it comes back from suspend.
> I never got a reply to why userspace should ever have to stop drawing to the
> frame buffer. If there is a valid reason for that, we might also need a
> blocking pre-suspend notifier, telling userspace that the device will suspend
> imediately.

User-space should stop drawing into the framebuffer before it is
powered down. If the framebuffer that is accessible to user-space is
in main memory not stopping may be harmless since the screen is
blanked anyway.

The sequence for turning the screen off and on here was mostly
dictated by initially using the existing method of changing
framebuffer ownership, the console switch.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-05  2:50 [RFC][PATCH 00/11] Android PM extensions Arve Hjønnevåg
  2009-02-05  2:50 ` [PATCH 01/13] PM: Add wake lock api Arve Hjønnevåg
@ 2009-02-06 23:51 ` Rafael J. Wysocki
  1 sibling, 0 replies; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-06 23:51 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thursday 05 February 2009, Arve Hjønnevåg wrote:
> The following patch series adds two apis, wakelock and earlysuspend.
> The Android platform uses the earlysuspend api to turn the screen
> and some input devices on and off. The wakelock code determines when
> to enter the full suspend state. 
> 
> These apis could also be useful to other platforms where the goal is
> to enter full suspend whenever possible.
> 
> This is the second version posted to linux-pm. The main change from the first
> version is that it no longer reuses /sys/power/state for the non-blocking
> interface.

Unfortunately, I haven't had the time to review the patches in detail yet.

I'll do that as soon as I can.

Thanks,
Rafael
_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 03/13] PM: Implement wakelock api.
  2009-02-06  0:38         ` Arve Hjønnevåg
@ 2009-02-07  0:33           ` mark gross
  2009-02-07  0:47             ` Arve Hjønnevåg
  0 siblings, 1 reply; 251+ messages in thread
From: mark gross @ 2009-02-07  0:33 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: swetland, linux-pm, u.luckas, ncunningham

On Thu, Feb 05, 2009 at 04:38:04PM -0800, Arve Hjønnevåg wrote:
> On Thu, Feb 5, 2009 at 4:10 PM, mark gross <mgross@linux.intel.com> wrote:
> > On Wed, Feb 04, 2009 at 06:50:16PM -0800, Arve Hjønnevåg wrote:
> >> +static void update_sleep_wait_stats_locked(int done)
> >> +{
> >> +     struct wake_lock *lock;
> >> +     ktime_t now, etime, elapsed, add;
> >> +     int expired;
> >> +
> >> +     now = ktime_get();
> >> +     elapsed = ktime_sub(now, last_sleep_time_update);
> >> +     list_for_each_entry(lock, &active_wake_locks[WAKE_LOCK_SUSPEND], link) {
> >
> > Is this list opperation SMP safe?  what if some on on the other CPU
> > removes a lock form user mode while walking this guy?  this goes for all
> > your list walking.
> 
> I have not tested the code on an SMP system, but the list is protected
> by a spinlock.

ok, I was just looking for it and didn't notice it in the calling code.

> 
> >> +static void expire_wake_lock(struct wake_lock *lock)
> >> +{
> >> +#ifdef CONFIG_WAKELOCK_STAT
> >> +     wake_unlock_stat_locked(lock, 1);
> >> +#endif
> >> +     lock->flags &= ~(WAKE_LOCK_ACTIVE | WAKE_LOCK_AUTO_EXPIRE);
> >> +     list_del(&lock->link);
> >> +     list_add(&lock->link, &inactive_locks);
> >> +     if (debug_mask & (DEBUG_WAKE_LOCK | DEBUG_EXPIRE))
> >> +             pr_info("expired wake lock %s\n", lock->name);
> >> +}
> >
> > Are we missing locking for this list opperation?
> 
> No.

ok.

> 
> >> +static void suspend(struct work_struct *work)
> >
> > there are a lot of "suspend" functions in the kernel already that have
> > different calling semantics, can we change this name so my TAG file is
> > more sane?
> 
> OK.
> 
> >
> >> +{
> >> +     int ret;
> >> +     int entry_event_num;
> >> +
> >> +     if (has_wake_lock(WAKE_LOCK_SUSPEND)) {
> >> +             if (debug_mask & DEBUG_SUSPEND)
> >> +                     pr_info("suspend: abort suspend\n");
> >> +             return;
> >> +     }
> >> +
> >> +     entry_event_num = current_event_num;
> >> +     sys_sync();
> >
> > um, this feel wrong to me.
> 
> Wrong or redundant? I can remove sys_sync here since pm_suspend calls it anyway.

its just a latency enhanced api call I wouldn't expect to see called.

> 
> >
> >> +     if (debug_mask & DEBUG_SUSPEND)
> >> +             pr_info("suspend: enter suspend\n");
> >> +     ret = pm_suspend(requested_suspend_state);
> >
> > oh, you are adding yet another path to getting the system into a
> > suspended state.  is this necessary?
> 
> Yes.
> 
> >> +#ifdef CONFIG_WAKELOCK_STAT
> >> +     create_proc_read_entry("wakelocks", S_IRUGO, NULL,
> >> +                             wakelocks_read_proc, NULL);
> >
> > Shouldn't we *not* be using /proc?  I think this should be under sysfs.
> 
> It is not allowed under sysfs. Debugfs has been suggested, but we
> don't have debugfs mounted, and we include the wakelock stats in debug
> reports.
> 

why not under sysfs?  

--mgross

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 03/13] PM: Implement wakelock api.
  2009-02-07  0:33           ` mark gross
@ 2009-02-07  0:47             ` Arve Hjønnevåg
  2009-02-09 18:00               ` mark gross
  2009-02-10 20:24               ` Pavel Machek
  0 siblings, 2 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-07  0:47 UTC (permalink / raw)
  To: mgross; +Cc: swetland, linux-pm, u.luckas, ncunningham

On Fri, Feb 6, 2009 at 4:33 PM, mark gross <mgross@linux.intel.com> wrote:
>> >> +#ifdef CONFIG_WAKELOCK_STAT
>> >> +     create_proc_read_entry("wakelocks", S_IRUGO, NULL,
>> >> +                             wakelocks_read_proc, NULL);
>> >
>> > Shouldn't we *not* be using /proc?  I think this should be under sysfs.
>>
>> It is not allowed under sysfs. Debugfs has been suggested, but we
>> don't have debugfs mounted, and we include the wakelock stats in debug
>> reports.
>>
>
> why not under sysfs?

The rules for sysfs state that there should be one value or an array
of values per file.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-05  2:50 ` [PATCH 01/13] PM: Add wake lock api Arve Hjønnevåg
                     ` (2 preceding siblings ...)
  2009-02-05 22:51   ` mark gross
@ 2009-02-07 18:56   ` Rafael J. Wysocki
  2009-02-07 22:51     ` Arve Hjønnevåg
  3 siblings, 1 reply; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-07 18:56 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thursday 05 February 2009, Arve Hjønnevåg wrote:
> Signed-off-by: Arve Hjønnevåg <arve@android.com>
> ---
>  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.txt
> new file mode 100644
> index 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.

Hm, can you please explain to me what this example is supposed to illustrate?

If my understanding is correct, a wakelock is a mechanism that, if held, will
prevent the system from (automatically) entering a sleep state, but why do we
need a number of such wakelocks instead of just one reference counter with the
rule that (automatic) suspend can only happen if the counter is zero?

Then, code paths wanting to prevent the suspend from happening would only need
to increase the counter and it shouldn't be difficult to provide a user space
interface for that.

> +
> +                 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.

And what's this call needed for?

> +
> +
> +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.

Is there a mechanism allowing us to see what wakelocks have been created by
the user land?  Something like this would be useful for debugging.

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

This appears to be very fragile.  Please rethink it.

> +
> diff --git a/include/linux/wakelock.h b/include/linux/wakelock.h
> new file mode 100755
> index 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);

What's the purpose of this function?

> +
> +/* 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);

And this?

> +
> +#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
> +

Thanks,
Rafael
_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 02/13] PM: Add early suspend api.
  2009-02-05  2:50   ` [PATCH 02/13] PM: Add early suspend api Arve Hjønnevåg
                       ` (2 preceding siblings ...)
  2009-02-05 23:26     ` mark gross
@ 2009-02-07 20:53     ` Rafael J. Wysocki
  2009-02-07 23:34       ` Arve Hjønnevåg
  3 siblings, 1 reply; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-07 20:53 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thursday 05 February 2009, Arve Hjønnevåg wrote:
> Signed-off-by: Arve Hjønnevåg <arve@android.com>
> ---
>  Documentation/power/early-suspend.txt |   26 +++++++++++++++
>  include/linux/earlysuspend.h          |   55 +++++++++++++++++++++++++++++++++
>  2 files changed, 81 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/power/early-suspend.txt
>  create mode 100755 include/linux/earlysuspend.h
> 
> diff --git a/Documentation/power/early-suspend.txt b/Documentation/power/early-suspend.txt
> new file mode 100644
> index 0000000..8286d3a
> --- /dev/null
> +++ b/Documentation/power/early-suspend.txt
> @@ -0,0 +1,26 @@
> +Early-suspend
> +=============
> +
> +The early-suspend api allows drivers to get notified when user-space writes to 
> +/sys/power/request_state to indicate that the user visible sleep state should 
> +change. A level controls what order the handlers are called in. Suspend 
> +handlers are called in low to high level order, resume handlers are called in 
> +the opposite order. 

I don't really understand this description, sorry.

In particular, what values can be written to /sys/power/request_state, what
their meaning is and what's supposed to happen if someone writes one of these
values to this file?

> +
> +Four levels are defined:
> +EARLY_SUSPEND_LEVEL_BLANK_SCREEN:
> +  On suspend the screen should be turned off but the framebuffer must still be
> +  accessible. On resume the screen can be turned back on.

What exactly is the meaning of "suspend" here?

> +EARLY_SUSPEND_LEVEL_STOP_DRAWING:
> +  On suspend this level notifies user-space that it should stop accessing the 
> +  framebuffer and it waits for it to complete. On resume it notifies user-space 
> +  that it should resume screen access.
> +  Two methods are provided, console switch or a sysfs interface.

How exactly is the notification supposed to happen?

> +EARLY_SUSPEND_LEVEL_DISABLE_FB:
> +  Turn off the framebuffer on suspend and back on on resume.
> +
> +EARLY_SUSPEND_LEVEL_STOP_INPUT:
> +  On suspend turn off input devices that are not capable of wakeup or where
> +  wakeup is disabled. On resume turn the same devices back on.

This always happens during suspend-resume.  How is this different from the
usual suspend-resume behaviour?

> diff --git a/include/linux/earlysuspend.h b/include/linux/earlysuspend.h
> new file mode 100755
> index 0000000..1587a3f
> --- /dev/null
> +++ b/include/linux/earlysuspend.h
> @@ -0,0 +1,55 @@
> +/* include/linux/earlysuspend.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_EARLYSUSPEND_H
> +#define _LINUX_EARLYSUSPEND_H
> +
> +#include <linux/list.h>
> +
> +/* The early_suspend structure defines suspend and resume hooks to be called
> + * when the user visible sleep state of the system changes, and a level to
> + * control the order. They can be used to turn off the screen and input
> + * devices that are not used for wakeup.
> + * Suspend handlers are called in low to high level order, resume handlers are
> + * called in the opposite order. If, when calling register_early_suspend,
> + * the suspend handlers have already been called without a matching call to the
> + * resume handlers, the suspend handler will be called directly from
> + * register_early_suspend. This direct call can violate the normal level order.
> + */
> +enum {
> +	EARLY_SUSPEND_LEVEL_BLANK_SCREEN = 50,
> +	EARLY_SUSPEND_LEVEL_STOP_INPUT = 75,
> +	EARLY_SUSPEND_LEVEL_STOP_DRAWING = 100,
> +	EARLY_SUSPEND_LEVEL_DISABLE_FB = 150,
> +};
> +struct early_suspend {
> +#ifdef CONFIG_HAS_EARLYSUSPEND
> +	struct list_head link;
> +	int level;
> +	void (*suspend)(struct early_suspend *h);
> +	void (*resume)(struct early_suspend *h);
> +#endif
> +};

Does this mean addional suspend-resume callbacks for device drivers?

If so, how are they different from the "standard" suspend-resume callbacks?

Also, what about bus types that carry out some suspend-resume operations
for their devices, like PCI?  Your early callbacks don't seem to take the
bus type part into account.

> +#ifdef CONFIG_HAS_EARLYSUSPEND
> +void register_early_suspend(struct early_suspend *handler);
> +void unregister_early_suspend(struct early_suspend *handler);
> +#else
> +#define register_early_suspend(handler) do { } while (0)
> +#define unregister_early_suspend(handler) do { } while (0)
> +#endif
> +
> +#endif
> +

My understanding of the 'early suspend' idea is that it is a mechanism allowing
us to place some devices selectively into low power states before the actual
suspend happens.  However, this is exactly the same as runtime power
management on demand, with an interface allowing user space to put devices into
low power states.

Now, in my opinion, runtime power management should be implemented on the
bus type level, since bus types differ from each other by power management
requirements, mechanisms that can be used and hardware interfaces.

I have some prototype patches for PCI runtime PM in the works.  I didn't
intend to post them just yet, since I'm considering them as work in progress.
Still, I can do that if you think it would be useful.

Thanks,
Rafael
_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 03/13] PM: Implement wakelock api.
  2009-02-05  2:50     ` [PATCH 03/13] PM: Implement wakelock api Arve Hjønnevåg
                         ` (3 preceding siblings ...)
  2009-02-06  0:10       ` mark gross
@ 2009-02-07 22:27       ` Rafael J. Wysocki
  2009-02-11  2:52         ` Arve Hjønnevåg
  4 siblings, 1 reply; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-07 22:27 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thursday 05 February 2009, Arve Hjønnevåg wrote:
> Signed-off-by: Arve Hjønnevåg <arve@android.com>
> ---
>  kernel/power/Kconfig    |   19 ++
>  kernel/power/Makefile   |    1 +
>  kernel/power/power.h    |    7 +
>  kernel/power/wakelock.c |  598 +++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 625 insertions(+), 0 deletions(-)
>  create mode 100644 kernel/power/wakelock.c
> 
> diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
> index 23bd4da..6e3da6e 100644
> --- a/kernel/power/Kconfig
> +++ b/kernel/power/Kconfig
> @@ -116,6 +116,25 @@ config SUSPEND_FREEZER
>  
>  	  Turning OFF this setting is NOT recommended! If in doubt, say Y.
>  
> +config HAS_WAKELOCK
> +	bool
> +
> +config WAKELOCK
> +	bool "Wake lock"
> +	depends on PM && RTC_CLASS
> +	default n
> +	select HAS_WAKELOCK
> +	---help---
> +	  Enable wakelocks. When user space request a sleep state the
> +	  sleep request will be delayed until no wake locks are held.
> +
> +config WAKELOCK_STAT
> +	bool "Wake lock stats"
> +	depends on WAKELOCK
> +	default y
> +	---help---
> +	  Report wake lock stats in /proc/wakelocks
> +
>  config HIBERNATION
>  	bool "Hibernation (aka 'suspend to disk')"
>  	depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
> diff --git a/kernel/power/Makefile b/kernel/power/Makefile
> index d7a1016..8d8672b 100644
> --- a/kernel/power/Makefile
> +++ b/kernel/power/Makefile
> @@ -6,6 +6,7 @@ endif
>  obj-y				:= main.o
>  obj-$(CONFIG_PM_SLEEP)		+= console.o
>  obj-$(CONFIG_FREEZER)		+= process.o
> +obj-$(CONFIG_WAKELOCK)		+= wakelock.o
>  obj-$(CONFIG_HIBERNATION)	+= swsusp.o disk.o snapshot.o swap.o user.o
>  
>  obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
> diff --git a/kernel/power/power.h b/kernel/power/power.h
> index 46b5ec7..1527174 100644
> --- a/kernel/power/power.h
> +++ b/kernel/power/power.h
> @@ -223,3 +223,10 @@ static inline void suspend_thaw_processes(void)
>  {
>  }
>  #endif
> +
> +#ifdef CONFIG_WAKELOCK
> +/* kernel/power/wakelock.c */
> +extern struct workqueue_struct *suspend_work_queue;
> +extern struct wake_lock main_wake_lock;
> +extern suspend_state_t requested_suspend_state;
> +#endif
> diff --git a/kernel/power/wakelock.c b/kernel/power/wakelock.c
> new file mode 100644
> index 0000000..c9e22f9
> --- /dev/null
> +++ b/kernel/power/wakelock.c
> @@ -0,0 +1,598 @@
> +/* kernel/power/wakelock.c
> + *
> + * Copyright (C) 2005-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.
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/rtc.h>
> +#include <linux/suspend.h>
> +#include <linux/syscalls.h> /* sys_sync */
> +#include <linux/wakelock.h>
> +#ifdef CONFIG_WAKELOCK_STAT
> +#include <linux/proc_fs.h>
> +#endif
> +#include "power.h"
> +
> +enum {
> +	DEBUG_EXIT_SUSPEND = 1U << 0,
> +	DEBUG_WAKEUP = 1U << 1,
> +	DEBUG_SUSPEND = 1U << 2,
> +	DEBUG_EXPIRE = 1U << 3,
> +	DEBUG_WAKE_LOCK = 1U << 4,
> +};
> +static int debug_mask = DEBUG_EXIT_SUSPEND | DEBUG_WAKEUP;
> +module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
> +
> +#define WAKE_LOCK_TYPE_MASK              (0x0f)
> +#define WAKE_LOCK_INITIALIZED            (1U << 8)
> +#define WAKE_LOCK_ACTIVE                 (1U << 9)
> +#define WAKE_LOCK_AUTO_EXPIRE            (1U << 10)
> +#define WAKE_LOCK_PREVENTING_SUSPEND     (1U << 11)
> +
> +static DEFINE_SPINLOCK(list_lock);
> +static LIST_HEAD(inactive_locks);
> +static struct list_head active_wake_locks[WAKE_LOCK_TYPE_COUNT];
> +static int current_event_num;
> +struct workqueue_struct *suspend_work_queue;
> +struct wake_lock main_wake_lock;
> +suspend_state_t requested_suspend_state = PM_SUSPEND_MEM;
> +static struct wake_lock unknown_wakeup;
> +
> +#ifdef CONFIG_WAKELOCK_STAT
> +static struct wake_lock deleted_wake_locks;
> +static ktime_t last_sleep_time_update;
> +static int wait_for_wakeup;

Care to add kerneldoc comments to the functions?

> +int get_expired_time(struct wake_lock *lock, ktime_t *expire_time)

I would use 'bool'.

> +{
> +	struct timespec ts;
> +	struct timespec kt;
> +	struct timespec tomono;
> +	struct timespec delta;
> +	unsigned long seq;
> +	long timeout;
> +
> +	if (!(lock->flags & WAKE_LOCK_AUTO_EXPIRE))
> +		return 0;
> +	do {
> +		seq = read_seqbegin(&xtime_lock);
> +		timeout = lock->expires - jiffies;

Can it overflow?

Anyway, you are using struct timespec in computations, so why don't you
store it in the lock structure?

> +		if (timeout > 0)
> +			return 0;
> +		kt = current_kernel_time();
> +		tomono = wall_to_monotonic;
> +	} while (read_seqretry(&xtime_lock, seq));
> +	jiffies_to_timespec(-timeout, &delta);
> +	set_normalized_timespec(&ts, kt.tv_sec + tomono.tv_sec - delta.tv_sec,
> +				kt.tv_nsec + tomono.tv_nsec - delta.tv_nsec);
> +	*expire_time = timespec_to_ktime(ts);
> +	return 1;
> +}
> +
> +
> +static int print_lock_stat(char *buf, struct wake_lock *lock)
> +{
> +	int lock_count = lock->stat.count;
> +	int expire_count = lock->stat.expire_count;
> +	ktime_t active_time = ktime_set(0, 0);
> +	ktime_t total_time = lock->stat.total_time;
> +	ktime_t max_time = lock->stat.max_time;
> +	ktime_t prevent_suspend_time = lock->stat.prevent_suspend_time;
> +	if (lock->flags & WAKE_LOCK_ACTIVE) {
> +		ktime_t now, add_time;
> +		int expired = get_expired_time(lock, &now);
> +		if (!expired)
> +			now = ktime_get();
> +		add_time = ktime_sub(now, lock->stat.last_time);
> +		lock_count++;
> +		if (!expired)
> +			active_time = add_time;
> +		else
> +			expire_count++;
> +		total_time = ktime_add(total_time, add_time);
> +		if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND)
> +			prevent_suspend_time = ktime_add(prevent_suspend_time,
> +					ktime_sub(now, last_sleep_time_update));
> +		if (add_time.tv64 > max_time.tv64)
> +			max_time = add_time;
> +	}
> +
> +	return sprintf(buf, "\"%s\"\t%d\t%d\t%d\t%lld\t%lld\t%lld\t%lld\t"
> +		       "%lld\n", lock->name, lock_count, expire_count,
> +		       lock->stat.wakeup_count, ktime_to_ns(active_time),
> +		       ktime_to_ns(total_time),
> +		       ktime_to_ns(prevent_suspend_time), ktime_to_ns(max_time),
> +		       ktime_to_ns(lock->stat.last_time));
> +}
> +

Why did you decide to put that in /proc ?

> +static int wakelocks_read_proc(char *page, char **start, off_t off,
> +			       int count, int *eof, void *data)
> +{
> +	unsigned long irqflags;
> +	struct wake_lock *lock;
> +	int len = 0;
> +	char *p = page;
> +	int type;
> +
> +	spin_lock_irqsave(&list_lock, irqflags);
> +
> +	p += sprintf(p, "name\tcount\texpire_count\twake_count\tactive_since"
> +		     "\ttotal_time\tsleep_time\tmax_time\tlast_change\n");
> +	list_for_each_entry(lock, &inactive_locks, link) {
> +		p += print_lock_stat(p, lock);
> +	}
> +	for (type = 0; type < WAKE_LOCK_TYPE_COUNT; type++) {
> +		list_for_each_entry(lock, &active_wake_locks[type], link)
> +			p += print_lock_stat(p, lock);
> +	}
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +
> +	*start = page + off;
> +
> +	len = p - page;
> +	if (len > off)
> +		len -= off;
> +	else
> +		len = 0;
> +
> +	return len < count ? len  : count;
> +}
> +
> +static void wake_unlock_stat_locked(struct wake_lock *lock, int expired)
> +{
> +	ktime_t duration;
> +	ktime_t now;
> +	if (!(lock->flags & WAKE_LOCK_ACTIVE))
> +		return;
> +	if (get_expired_time(lock, &now))
> +		expired = 1;

I'd use 'true'.

> +	else
> +		now = ktime_get();
> +	lock->stat.count++;
> +	if (expired)
> +		lock->stat.expire_count++;
> +	duration = ktime_sub(now, lock->stat.last_time);
> +	lock->stat.total_time = ktime_add(lock->stat.total_time, duration);
> +	if (ktime_to_ns(duration) > ktime_to_ns(lock->stat.max_time))
> +		lock->stat.max_time = duration;
> +	lock->stat.last_time = ktime_get();
> +	if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND) {
> +		duration = ktime_sub(now, last_sleep_time_update);
> +		lock->stat.prevent_suspend_time = ktime_add(
> +			lock->stat.prevent_suspend_time, duration);
> +		lock->flags &= ~WAKE_LOCK_PREVENTING_SUSPEND;
> +	}
> +}
> +
> +static void update_sleep_wait_stats_locked(int done)
> +{
> +	struct wake_lock *lock;
> +	ktime_t now, etime, elapsed, add;
> +	int expired;
> +
> +	now = ktime_get();
> +	elapsed = ktime_sub(now, last_sleep_time_update);
> +	list_for_each_entry(lock, &active_wake_locks[WAKE_LOCK_SUSPEND], link) {
> +		expired = get_expired_time(lock, &etime);
> +		if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND) {
> +			if (expired)
> +				add = ktime_sub(etime, last_sleep_time_update);
> +			else
> +				add = elapsed;
> +			lock->stat.prevent_suspend_time = ktime_add(
> +				lock->stat.prevent_suspend_time, add);
> +		}
> +		if (done || expired)
> +			lock->flags &= ~WAKE_LOCK_PREVENTING_SUSPEND;
> +		else
> +			lock->flags |= WAKE_LOCK_PREVENTING_SUSPEND;
> +	}
> +	last_sleep_time_update = now;
> +}
> +#endif
> +
> +
> +static void expire_wake_lock(struct wake_lock *lock)
> +{
> +#ifdef CONFIG_WAKELOCK_STAT
> +	wake_unlock_stat_locked(lock, 1);
> +#endif
> +	lock->flags &= ~(WAKE_LOCK_ACTIVE | WAKE_LOCK_AUTO_EXPIRE);
> +	list_del(&lock->link);
> +	list_add(&lock->link, &inactive_locks);
> +	if (debug_mask & (DEBUG_WAKE_LOCK | DEBUG_EXPIRE))
> +		pr_info("expired wake lock %s\n", lock->name);
> +}
> +
> +static void print_active_locks(int type)
> +{
> +	unsigned long irqflags;
> +	struct wake_lock *lock;
> +
> +	BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
> +	spin_lock_irqsave(&list_lock, irqflags);
> +	list_for_each_entry(lock, &active_wake_locks[type], link) {
> +		if (lock->flags & WAKE_LOCK_AUTO_EXPIRE) {
> +			long timeout = lock->expires - jiffies;
> +			if (timeout <= 0)
> +				pr_info("wake lock %s, expired\n", lock->name);
> +			else
> +				pr_info("active wake lock %s, time left %ld\n",
> +					lock->name, timeout);
> +		} else
> +			pr_info("active wake lock %s\n", lock->name);
> +	}
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +}
> +
> +static long has_wake_lock_locked(int type)

I'd change the name, it suggests something different from what the function
does.

> +{
> +	struct wake_lock *lock, *n;
> +	long max_timeout = 0;
> +
> +	BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
> +	list_for_each_entry_safe(lock, n, &active_wake_locks[type], link) {
> +		if (lock->flags & WAKE_LOCK_AUTO_EXPIRE) {
> +			long timeout = lock->expires - jiffies;

I think time_after() is for things like this.

> +			if (timeout <= 0)
> +				expire_wake_lock(lock);
> +			else if (timeout > max_timeout)
> +				max_timeout = timeout;
> +		} else
> +			return -1;
> +	}
> +	return max_timeout;
> +}
> +
> +long has_wake_lock(int type)
> +{
> +	long ret;
> +	unsigned long irqflags;
> +	spin_lock_irqsave(&list_lock, irqflags);
> +	ret = has_wake_lock_locked(type);
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +	return ret;
> +}
> +
> +static void suspend(struct work_struct *work)
> +{
> +	int ret;
> +	int entry_event_num;
> +
> +	if (has_wake_lock(WAKE_LOCK_SUSPEND)) {
> +		if (debug_mask & DEBUG_SUSPEND)
> +			pr_info("suspend: abort suspend\n");
> +		return;
> +	}
> +
> +	entry_event_num = current_event_num;
> +	sys_sync();

pm_suspend() will do it, you don't need to.

> +	if (debug_mask & DEBUG_SUSPEND)
> +		pr_info("suspend: enter suspend\n");

Shouldn't that check if someone has taken a wakelock in the meantime?

> +	ret = pm_suspend(requested_suspend_state);
> +	if (debug_mask & DEBUG_EXIT_SUSPEND) {
> +		struct timespec ts;
> +		struct rtc_time tm;
> +		getnstimeofday(&ts);
> +		rtc_time_to_tm(ts.tv_sec, &tm);
> +		pr_info("suspend: exit suspend, ret = %d "
> +			"(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n", ret,
> +			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
> +			tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
> +	}
> +	if (current_event_num == entry_event_num) {
> +		if (debug_mask & DEBUG_SUSPEND)
> +			pr_info("suspend: pm_suspend returned with no event\n");
> +		wake_lock_timeout(&unknown_wakeup, HZ / 2);
> +	}
> +}
> +static DECLARE_WORK(suspend_work, suspend);
> +
> +static void expire_wake_locks(unsigned long data)
> +{
> +	long has_lock;
> +	unsigned long irqflags;
> +	if (debug_mask & DEBUG_EXPIRE)
> +		pr_info("expire_wake_locks: start\n");
> +	if (debug_mask & DEBUG_SUSPEND)
> +		print_active_locks(WAKE_LOCK_SUSPEND);
> +	spin_lock_irqsave(&list_lock, irqflags);
> +	has_lock = has_wake_lock_locked(WAKE_LOCK_SUSPEND);
> +	if (debug_mask & DEBUG_EXPIRE)
> +		pr_info("expire_wake_locks: done, has_lock %ld\n", has_lock);
> +	if (has_lock == 0)
> +		queue_work(suspend_work_queue, &suspend_work);
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +}
> +static DEFINE_TIMER(expire_timer, expire_wake_locks, 0, 0);
> +
> +static int power_suspend_late(struct platform_device *pdev, pm_message_t state)
> +{
> +	int ret = has_wake_lock(WAKE_LOCK_SUSPEND) ? -EAGAIN : 0;
> +#ifdef CONFIG_WAKELOCK_STAT
> +	wait_for_wakeup = 1;
> +#endif
> +	if (debug_mask & DEBUG_SUSPEND)
> +		pr_info("power_suspend_late return %d\n", ret);
> +	return ret;
> +}
> +
> +static struct platform_driver power_driver = {
> +	.driver.name = "power",
> +	.suspend_late = power_suspend_late,
> +};
> +static struct platform_device power_device = {
> +	.name = "power",
> +};

What's this and what's it for?

> +
> +void wake_lock_init(struct wake_lock *lock, int type, const char *name)
> +{
> +	unsigned long irqflags = 0;
> +
> +	if (name)
> +		lock->name = name;

Hm.  I'd rather reserve memory for the name and copy it from the address
provided by the caller.

> +	BUG_ON(!lock->name);

Isn't it a bit too drastic?  Perhaps make it return a value so that the caller
can check if it has the lock?

> +
> +	if (debug_mask & DEBUG_WAKE_LOCK)
> +		pr_info("wake_lock_init name=%s\n", lock->name);
> +#ifdef CONFIG_WAKELOCK_STAT
> +	lock->stat.count = 0;
> +	lock->stat.expire_count = 0;
> +	lock->stat.wakeup_count = 0;
> +	lock->stat.total_time = ktime_set(0, 0);
> +	lock->stat.prevent_suspend_time = ktime_set(0, 0);
> +	lock->stat.max_time = ktime_set(0, 0);
> +	lock->stat.last_time = ktime_set(0, 0);
> +#endif
> +	lock->flags = (type & WAKE_LOCK_TYPE_MASK) | WAKE_LOCK_INITIALIZED;
> +
> +	INIT_LIST_HEAD(&lock->link);
> +	spin_lock_irqsave(&list_lock, irqflags);
> +	list_add(&lock->link, &inactive_locks);
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +}
> +EXPORT_SYMBOL(wake_lock_init);
> +
> +void wake_lock_destroy(struct wake_lock *lock)
> +{
> +	unsigned long irqflags;
> +	if (debug_mask & DEBUG_WAKE_LOCK)
> +		pr_info("wake_lock_destroy name=%s\n", lock->name);
> +	spin_lock_irqsave(&list_lock, irqflags);
> +	lock->flags &= ~WAKE_LOCK_INITIALIZED;
> +#ifdef CONFIG_WAKELOCK_STAT
> +	if (lock->stat.count) {
> +		deleted_wake_locks.stat.count += lock->stat.count;
> +		deleted_wake_locks.stat.expire_count += lock->stat.expire_count;
> +		deleted_wake_locks.stat.total_time =
> +			ktime_add(deleted_wake_locks.stat.total_time,
> +				  lock->stat.total_time);
> +		deleted_wake_locks.stat.prevent_suspend_time =
> +			ktime_add(deleted_wake_locks.stat.prevent_suspend_time,
> +				  lock->stat.prevent_suspend_time);
> +		deleted_wake_locks.stat.max_time =
> +			ktime_add(deleted_wake_locks.stat.max_time,
> +				  lock->stat.max_time);
> +	}
> +#endif
> +	list_del(&lock->link);
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +}
> +EXPORT_SYMBOL(wake_lock_destroy);
> +
> +static void wake_lock_internal(

What  about __wake_lock() ?

> +	struct wake_lock *lock, long timeout, int has_timeout)

What's the point of the last argument?  Wouldn't timeout == 0 be sufficient?

Also, does it make sense to pass negative timeout to it?

> +{
> +	int type;
> +	unsigned long irqflags;
> +	long expire_in;
> +
> +	spin_lock_irqsave(&list_lock, irqflags);
> +	type = lock->flags & WAKE_LOCK_TYPE_MASK;
> +	BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
> +	BUG_ON(!(lock->flags & WAKE_LOCK_INITIALIZED));

I don't like these BUG_ON()s.  Please do something less drastic instead.

> +#ifdef CONFIG_WAKELOCK_STAT
> +	if (type == WAKE_LOCK_SUSPEND && wait_for_wakeup) {
> +		if (debug_mask & DEBUG_WAKEUP)
> +			pr_info("wakeup wake lock: %s\n", lock->name);
> +		wait_for_wakeup = 0;
> +		lock->stat.wakeup_count++;
> +	}
> +	if ((lock->flags & WAKE_LOCK_AUTO_EXPIRE) &&
> +	    (long)(lock->expires - jiffies) <= 0) {
> +		wake_unlock_stat_locked(lock, 0);
> +		lock->stat.last_time = ktime_get();
> +	}
> +#endif
> +	if (!(lock->flags & WAKE_LOCK_ACTIVE)) {
> +		lock->flags |= WAKE_LOCK_ACTIVE;
> +#ifdef CONFIG_WAKELOCK_STAT
> +		lock->stat.last_time = ktime_get();
> +#endif
> +	}
> +	list_del(&lock->link);
> +	if (has_timeout) {
> +		if (debug_mask & DEBUG_WAKE_LOCK)
> +			pr_info("wake_lock: %s, type %d, timeout %ld.%03lu\n",
> +				lock->name, type, timeout / HZ,
> +				(timeout % HZ) * MSEC_PER_SEC / HZ);
> +		lock->expires = jiffies + timeout;
> +		lock->flags |= WAKE_LOCK_AUTO_EXPIRE;
> +		list_add_tail(&lock->link, &active_wake_locks[type]);
> +	} else {
> +		if (debug_mask & DEBUG_WAKE_LOCK)
> +			pr_info("wake_lock: %s, type %d\n", lock->name, type);
> +		lock->expires = LONG_MAX;
> +		lock->flags &= ~WAKE_LOCK_AUTO_EXPIRE;
> +		list_add(&lock->link, &active_wake_locks[type]);
> +	}

Why not to use list_add_tail() in both cases?

> +	if (type == WAKE_LOCK_SUSPEND) {
> +		current_event_num++;
> +#ifdef CONFIG_WAKELOCK_STAT
> +		if (lock == &main_wake_lock)
> +			update_sleep_wait_stats_locked(1);
> +		else if (!wake_lock_active(&main_wake_lock))
> +			update_sleep_wait_stats_locked(0);
> +#endif
> +		if (has_timeout)
> +			expire_in = has_wake_lock_locked(type);
> +		else
> +			expire_in = -1;

	expire_i = has_timeout ? has_wake_lock_locked(type) : -1;

(there is something like this above too).

> +		if (expire_in > 0) {
> +			if (debug_mask & DEBUG_EXPIRE)
> +				pr_info("wake_lock: %s, start expire timer, "
> +					"%ld\n", lock->name, expire_in);
> +			mod_timer(&expire_timer, jiffies + expire_in);

What exactly are you trying to achieve here?

> +		} else {
> +			if (del_timer(&expire_timer))
> +				if (debug_mask & DEBUG_EXPIRE)
> +					pr_info("wake_lock: %s, stop expire "
> +						"timer\n", lock->name);
> +			if (expire_in == 0)
> +				queue_work(suspend_work_queue, &suspend_work);

This appears to only happen if timeout = 0 is passed to this function while
has_timeout == true.  Is it correct?

> +		}
> +	}
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +}
> +
> +void wake_lock(struct wake_lock *lock)
> +{
> +	wake_lock_internal(lock, 0, 0);
> +}
> +EXPORT_SYMBOL(wake_lock);
> +
> +void wake_lock_timeout(struct wake_lock *lock, long timeout)
> +{
> +	wake_lock_internal(lock, timeout, 1);
> +}
> +EXPORT_SYMBOL(wake_lock_timeout);
> +
> +void wake_unlock(struct wake_lock *lock)
> +{
> +	int type;
> +	unsigned long irqflags;
> +	spin_lock_irqsave(&list_lock, irqflags);
> +	type = lock->flags & WAKE_LOCK_TYPE_MASK;
> +#ifdef CONFIG_WAKELOCK_STAT
> +	wake_unlock_stat_locked(lock, 0);
> +#endif
> +	if (debug_mask & DEBUG_WAKE_LOCK)
> +		pr_info("wake_unlock: %s\n", lock->name);
> +	lock->flags &= ~(WAKE_LOCK_ACTIVE | WAKE_LOCK_AUTO_EXPIRE);
> +	list_del(&lock->link);
> +	list_add(&lock->link, &inactive_locks);
> +	if (type == WAKE_LOCK_SUSPEND) {
> +		long has_lock = has_wake_lock_locked(type);
> +		if (has_lock > 0) {
> +			if (debug_mask & DEBUG_EXPIRE)
> +				pr_info("wake_unlock: %s, start expire timer, "
> +					"%ld\n", lock->name, has_lock);
> +			mod_timer(&expire_timer, jiffies + has_lock);
> +		} else {
> +			if (del_timer(&expire_timer))
> +				if (debug_mask & DEBUG_EXPIRE)
> +					pr_info("wake_unlock: %s, stop expire "
> +						"timer\n", lock->name);
> +			if (has_lock == 0)
> +				queue_work(suspend_work_queue, &suspend_work);
> +		}
> +		if (lock == &main_wake_lock) {
> +			if (debug_mask & DEBUG_SUSPEND)
> +				print_active_locks(WAKE_LOCK_SUSPEND);
> +#ifdef CONFIG_WAKELOCK_STAT
> +			update_sleep_wait_stats_locked(0);
> +#endif
> +		}
> +	}
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +}
> +EXPORT_SYMBOL(wake_unlock);
> +
> +int wake_lock_active(struct wake_lock *lock)
> +{
> +	return !!(lock->flags & WAKE_LOCK_ACTIVE);
> +}
> +EXPORT_SYMBOL(wake_lock_active);
> +
> +static int __init wakelocks_init(void)
> +{
> +	int ret;
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(active_wake_locks); i++)
> +		INIT_LIST_HEAD(&active_wake_locks[i]);
> +
> +#ifdef CONFIG_WAKELOCK_STAT
> +	wake_lock_init(&deleted_wake_locks, WAKE_LOCK_SUSPEND,
> +			"deleted_wake_locks");
> +#endif
> +	wake_lock_init(&main_wake_lock, WAKE_LOCK_SUSPEND, "main");
> +	wake_lock(&main_wake_lock);
> +	wake_lock_init(&unknown_wakeup, WAKE_LOCK_SUSPEND, "unknown_wakeups");
> +
> +	ret = platform_device_register(&power_device);
> +	if (ret) {
> +		pr_err("wakelocks_init: platform_device_register failed\n");
> +		goto err_platform_device_register;
> +	}
> +	ret = platform_driver_register(&power_driver);
> +	if (ret) {
> +		pr_err("wakelocks_init: platform_driver_register failed\n");
> +		goto err_platform_driver_register;
> +	}

Is this really a platform thing?

What exactly is the benefit of having the 'power_device' and 'power_driver'
registered?.

> +
> +	suspend_work_queue = create_singlethread_workqueue("suspend");
> +	if (suspend_work_queue == NULL) {
> +		ret = -ENOMEM;
> +		goto err_suspend_work_queue;
> +	}
> +
> +#ifdef CONFIG_WAKELOCK_STAT
> +	create_proc_read_entry("wakelocks", S_IRUGO, NULL,
> +				wakelocks_read_proc, NULL);
> +#endif
> +
> +	return 0;
> +
> +err_suspend_work_queue:
> +	platform_driver_unregister(&power_driver);
> +err_platform_driver_register:
> +	platform_device_unregister(&power_device);
> +err_platform_device_register:
> +	wake_lock_destroy(&unknown_wakeup);
> +	wake_lock_destroy(&main_wake_lock);
> +#ifdef CONFIG_WAKELOCK_STAT
> +	wake_lock_destroy(&deleted_wake_locks);
> +#endif
> +	return ret;
> +}
> +
> +static void  __exit wakelocks_exit(void)
> +{
> +#ifdef CONFIG_WAKELOCK_STAT
> +	remove_proc_entry("wakelocks", NULL);
> +#endif
> +	destroy_workqueue(suspend_work_queue);
> +	platform_driver_unregister(&power_driver);
> +	platform_device_unregister(&power_device);
> +	wake_lock_destroy(&unknown_wakeup);
> +	wake_lock_destroy(&main_wake_lock);
> +#ifdef CONFIG_WAKELOCK_STAT
> +	wake_lock_destroy(&deleted_wake_locks);
> +#endif
> +}
> +
> +core_initcall(wakelocks_init);
> +module_exit(wakelocks_exit);

In general, I found this mechanism overly complicated.

As I said previously, I don't really see a benefit of using multiple wakelocks
over using a single reference counter with certain timer mechanism triggering
suspend in the counter is 0.

Also, I'd really prefer to see the patch without the CONFIG_WAKELOCK_STAT
thing included, first.  It would have been much easier to read.

Thanks,
Rafael
_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 04/13] PM: wakelock: Override wakelocks when using /sys/power/state
  2009-02-05  2:50       ` [PATCH 04/13] PM: wakelock: Override wakelocks when using /sys/power/state Arve Hjønnevåg
  2009-02-05  2:50         ` [PATCH 05/13] PM: Add option to disable /sys/power/state interface Arve Hjønnevåg
@ 2009-02-07 22:31         ` Rafael J. Wysocki
  1 sibling, 0 replies; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-07 22:31 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thursday 05 February 2009, Arve Hjønnevåg wrote:
> This preserves existing functionality when CONFIG_WAKELOCK is set.
> 
> Signed-off-by: Arve Hjønnevåg <arve@android.com>
> ---
>  kernel/power/main.c     |    7 +++++++
>  kernel/power/power.h    |    1 +
>  kernel/power/wakelock.c |    4 ++++
>  3 files changed, 12 insertions(+), 0 deletions(-)
> 
> diff --git a/kernel/power/main.c b/kernel/power/main.c
> index 2399888..ab9fc7f 100644
> --- a/kernel/power/main.c
> +++ b/kernel/power/main.c
> @@ -515,6 +515,10 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
>  	p = memchr(buf, '\n', n);
>  	len = p ? p - buf : n;
>  
> +#ifdef CONFIG_WAKELOCK
> +	ignore_suspend_wakelocks = 1;
> +#endif

Please replace that with a function call like

disable_wakelocks();

that will be defined as an empty static inline for !CONFIG_WAKELOCK .

> +
>  	/* First, check if we are requested to hibernate */
>  	if (len == 4 && !strncmp(buf, "disk", len)) {
>  		error = hibernate();
> @@ -531,6 +535,9 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
>  #endif
>  
>   Exit:
> +#ifdef CONFIG_WAKELOCK
> +	ignore_suspend_wakelocks = 0;
> +#endif

Again, please replace that with something like

enable_wakelocks();

>  	return error ? error : n;
>  }
>  
> diff --git a/kernel/power/power.h b/kernel/power/power.h
> index 1527174..ed1b7f4 100644
> --- a/kernel/power/power.h
> +++ b/kernel/power/power.h
> @@ -229,4 +229,5 @@ static inline void suspend_thaw_processes(void)
>  extern struct workqueue_struct *suspend_work_queue;
>  extern struct wake_lock main_wake_lock;
>  extern suspend_state_t requested_suspend_state;
> +extern bool ignore_suspend_wakelocks;
>  #endif
> diff --git a/kernel/power/wakelock.c b/kernel/power/wakelock.c
> index c9e22f9..8a8608e 100644
> --- a/kernel/power/wakelock.c
> +++ b/kernel/power/wakelock.c
> @@ -47,6 +47,7 @@ static int current_event_num;
>  struct workqueue_struct *suspend_work_queue;
>  struct wake_lock main_wake_lock;
>  suspend_state_t requested_suspend_state = PM_SUSPEND_MEM;
> +bool ignore_suspend_wakelocks;
>  static struct wake_lock unknown_wakeup;
>  
>  #ifdef CONFIG_WAKELOCK_STAT
> @@ -260,6 +261,9 @@ long has_wake_lock(int type)
>  {
>  	long ret;
>  	unsigned long irqflags;
> +	if (WARN_ONCE(type == WAKE_LOCK_SUSPEND && ignore_suspend_wakelocks,
> +							"ignoring wakelocks\n"))
> +		return 0;
>  	spin_lock_irqsave(&list_lock, irqflags);
>  	ret = has_wake_lock_locked(type);
>  	spin_unlock_irqrestore(&list_lock, irqflags);

Thanks,
Rafael
_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-05  2:50         ` [PATCH 05/13] PM: Add option to disable /sys/power/state interface Arve Hjønnevåg
  2009-02-05  2:50           ` [PATCH 06/13] PM: Implement early suspend api Arve Hjønnevåg
  2009-02-05  9:17           ` [PATCH 05/13] PM: Add option to disable /sys/power/state interface Pavel Machek
@ 2009-02-07 22:37           ` Rafael J. Wysocki
  2009-02-08 10:33             ` Pavel Machek
  2 siblings, 1 reply; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-07 22:37 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thursday 05 February 2009, Arve Hjønnevåg wrote:
> Signed-off-by: Arve Hjønnevåg <arve@android.com>

This is completely wrong, IMO.

Removing an interface that has existed forever just because it happens to
be incompatible with your new shiny feature is not acceptable to me.

Please try to make the new feature work with the existing interface instead.

> ---
>  kernel/power/Kconfig |    9 +++++++++
>  kernel/power/main.c  |    4 ++++
>  2 files changed, 13 insertions(+), 0 deletions(-)
> 
> diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
> index 6e3da6e..dd76467 100644
> --- a/kernel/power/Kconfig
> +++ b/kernel/power/Kconfig
> @@ -135,6 +135,15 @@ config WAKELOCK_STAT
>  	---help---
>  	  Report wake lock stats in /proc/wakelocks
>  
> +config DISABLE_SYS_POWER_STATE
> +	bool "Disable /sys/power/state interface"
> +	depends on WAKELOCK
> +	default n
> +	---help---
> +	  The /sys/power/state interface does not respect wakelocks. If you
> +	  want to run user-space code that does not support wakelocks, do not
> +	  enable this option since it removes the interface.
> +
>  config HIBERNATION
>  	bool "Hibernation (aka 'suspend to disk')"
>  	depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
> diff --git a/kernel/power/main.c b/kernel/power/main.c
> index ab9fc7f..e2aae3e 100644
> --- a/kernel/power/main.c
> +++ b/kernel/power/main.c
> @@ -479,6 +479,7 @@ struct kobject *power_kobj;
>   *	proper enumerated value, and initiates a suspend transition.
>   */
>  
> +#ifndef CONFIG_DISABLE_SYS_POWER_STATE
>  static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
>  			  char *buf)
>  {
> @@ -542,6 +543,7 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
>  }
>  
>  power_attr(state);
> +#endif
>  
>  #ifdef CONFIG_PM_TRACE
>  int pm_trace_enabled;
> @@ -569,7 +571,9 @@ power_attr(pm_trace);
>  #endif /* CONFIG_PM_TRACE */
>  
>  static struct attribute * g[] = {
> +#ifndef CONFIG_DISABLE_SYS_POWER_STATE
>  	&state_attr.attr,
> +#endif
>  #ifdef CONFIG_PM_TRACE
>  	&pm_trace_attr.attr,
>  #endif

Thanks,
Rafael
_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 06/13] PM: Implement early suspend api
  2009-02-05  2:50           ` [PATCH 06/13] PM: Implement early suspend api Arve Hjønnevåg
  2009-02-05  2:50             ` [PATCH 07/13] PM: wakelock: Add /sys/power/request_state Arve Hjønnevåg
  2009-02-06  0:18             ` [PATCH 06/13] PM: Implement early suspend api mark gross
@ 2009-02-07 22:47             ` Rafael J. Wysocki
  2009-02-08  2:32               ` Benjamin Herrenschmidt
  2 siblings, 1 reply; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-07 22:47 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thursday 05 February 2009, Arve Hjønnevåg wrote:
> Signed-off-by: Arve Hjønnevåg <arve@android.com>

I don't really agree with this design, because I don't think it's suitable for
all bus types.  Namely, if any bus type partially handles suspend-resume of
its devices to offload device drivers, I don't see how that is going to work
along with your design.

You seem to require the drivers that will register the early resume handlers
to take care of everything, along with the operations that should really belong
to bus types.  I don't think it's a good approach. 

Thanks,
Rafael

> ---
>  kernel/power/Kconfig        |   12 +++
>  kernel/power/Makefile       |    1 +
>  kernel/power/earlysuspend.c |  178 +++++++++++++++++++++++++++++++++++++++++++
>  kernel/power/power.h        |    6 ++
>  4 files changed, 197 insertions(+), 0 deletions(-)
>  create mode 100644 kernel/power/earlysuspend.c
> 
> diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
> index dd76467..689abfe 100644
> --- a/kernel/power/Kconfig
> +++ b/kernel/power/Kconfig
> @@ -119,6 +119,9 @@ config SUSPEND_FREEZER
>  config HAS_WAKELOCK
>  	bool
>  
> +config HAS_EARLYSUSPEND
> +	bool
> +
>  config WAKELOCK
>  	bool "Wake lock"
>  	depends on PM && RTC_CLASS
> @@ -144,6 +147,15 @@ config DISABLE_SYS_POWER_STATE
>  	  want to run user-space code that does not support wakelocks, do not
>  	  enable this option since it removes the interface.
>  
> +config EARLYSUSPEND
> +	bool "Early suspend"
> +	depends on WAKELOCK
> +	default y
> +	select HAS_EARLYSUSPEND
> +	---help---
> +	  Call early suspend handlers when the user requested sleep state
> +	  changes.
> +
>  config HIBERNATION
>  	bool "Hibernation (aka 'suspend to disk')"
>  	depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
> diff --git a/kernel/power/Makefile b/kernel/power/Makefile
> index 8d8672b..2f17e1d 100644
> --- a/kernel/power/Makefile
> +++ b/kernel/power/Makefile
> @@ -7,6 +7,7 @@ obj-y				:= main.o
>  obj-$(CONFIG_PM_SLEEP)		+= console.o
>  obj-$(CONFIG_FREEZER)		+= process.o
>  obj-$(CONFIG_WAKELOCK)		+= wakelock.o
> +obj-$(CONFIG_EARLYSUSPEND)	+= earlysuspend.o
>  obj-$(CONFIG_HIBERNATION)	+= swsusp.o disk.o snapshot.o swap.o user.o
>  
>  obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
> diff --git a/kernel/power/earlysuspend.c b/kernel/power/earlysuspend.c
> new file mode 100644
> index 0000000..4d70a7e
> --- /dev/null
> +++ b/kernel/power/earlysuspend.c
> @@ -0,0 +1,178 @@
> +/* kernel/power/earlysuspend.c
> + *
> + * Copyright (C) 2005-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.
> + *
> + */
> +
> +#include <linux/earlysuspend.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/rtc.h>
> +#include <linux/syscalls.h> /* sys_sync */
> +#include <linux/wakelock.h>
> +#include <linux/workqueue.h>
> +
> +#include "power.h"
> +
> +enum {
> +	DEBUG_USER_STATE = 1U << 0,
> +	DEBUG_SUSPEND = 1U << 1,
> +};
> +static int debug_mask = DEBUG_USER_STATE;
> +module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
> +
> +static DEFINE_MUTEX(early_suspend_lock);
> +static LIST_HEAD(early_suspend_handlers);
> +static void early_suspend(struct work_struct *work);
> +static void late_resume(struct work_struct *work);
> +static DECLARE_WORK(early_suspend_work, early_suspend);
> +static DECLARE_WORK(late_resume_work, late_resume);
> +static DEFINE_SPINLOCK(state_lock);
> +enum {
> +	SUSPEND_REQUESTED = 0x1,
> +	SUSPENDED = 0x2,
> +	SUSPEND_REQUESTED_AND_SUSPENDED = SUSPEND_REQUESTED | SUSPENDED,
> +};
> +static int state;
> +
> +void register_early_suspend(struct early_suspend *handler)
> +{
> +	struct list_head *pos;
> +
> +	mutex_lock(&early_suspend_lock);
> +	list_for_each(pos, &early_suspend_handlers) {
> +		struct early_suspend *e;
> +		e = list_entry(pos, struct early_suspend, link);
> +		if (e->level > handler->level)
> +			break;
> +	}
> +	list_add_tail(&handler->link, pos);
> +	if ((state & SUSPENDED) && handler->suspend)
> +		handler->suspend(handler);
> +	mutex_unlock(&early_suspend_lock);
> +}
> +EXPORT_SYMBOL(register_early_suspend);
> +
> +void unregister_early_suspend(struct early_suspend *handler)
> +{
> +	mutex_lock(&early_suspend_lock);
> +	list_del(&handler->link);
> +	mutex_unlock(&early_suspend_lock);
> +}
> +EXPORT_SYMBOL(unregister_early_suspend);
> +
> +static void early_suspend(struct work_struct *work)
> +{
> +	struct early_suspend *pos;
> +	unsigned long irqflags;
> +	int abort = 0;
> +
> +	mutex_lock(&early_suspend_lock);
> +	spin_lock_irqsave(&state_lock, irqflags);
> +	if (state == SUSPEND_REQUESTED)
> +		state |= SUSPENDED;
> +	else
> +		abort = 1;
> +	spin_unlock_irqrestore(&state_lock, irqflags);
> +
> +	if (abort) {
> +		if (debug_mask & DEBUG_SUSPEND)
> +			pr_info("early_suspend: abort, state %d\n", state);
> +		mutex_unlock(&early_suspend_lock);
> +		goto abort;
> +	}
> +
> +	if (debug_mask & DEBUG_SUSPEND)
> +		pr_info("early_suspend: call handlers\n");
> +	list_for_each_entry(pos, &early_suspend_handlers, link) {
> +		if (pos->suspend)
> +			pos->suspend(pos);
> +	}
> +	mutex_unlock(&early_suspend_lock);
> +
> +	if (debug_mask & DEBUG_SUSPEND)
> +		pr_info("early_suspend: sync\n");
> +
> +	sys_sync();
> +abort:
> +	spin_lock_irqsave(&state_lock, irqflags);
> +	if (state == SUSPEND_REQUESTED_AND_SUSPENDED)
> +		wake_unlock(&main_wake_lock);
> +	spin_unlock_irqrestore(&state_lock, irqflags);
> +}
> +
> +static void late_resume(struct work_struct *work)
> +{
> +	struct early_suspend *pos;
> +	unsigned long irqflags;
> +	int abort = 0;
> +
> +	mutex_lock(&early_suspend_lock);
> +	spin_lock_irqsave(&state_lock, irqflags);
> +	if (state == SUSPENDED)
> +		state = 0; /* clear SUSPENDED */
> +	else
> +		abort = 1;
> +	spin_unlock_irqrestore(&state_lock, irqflags);
> +
> +	if (abort) {
> +		if (debug_mask & DEBUG_SUSPEND)
> +			pr_info("late_resume: abort, state %d\n", state);
> +		goto abort;
> +	}
> +	if (debug_mask & DEBUG_SUSPEND)
> +		pr_info("late_resume: call handlers\n");
> +	list_for_each_entry_reverse(pos, &early_suspend_handlers, link)
> +		if (pos->resume)
> +			pos->resume(pos);
> +	if (debug_mask & DEBUG_SUSPEND)
> +		pr_info("late_resume: done\n");
> +abort:
> +	mutex_unlock(&early_suspend_lock);
> +}
> +
> +void request_suspend_state(suspend_state_t new_state)
> +{
> +	unsigned long irqflags;
> +	int old_sleep;
> +
> +	spin_lock_irqsave(&state_lock, irqflags);
> +	old_sleep = state & SUSPEND_REQUESTED;
> +	if (debug_mask & DEBUG_USER_STATE) {
> +		struct timespec ts;
> +		struct rtc_time tm;
> +		getnstimeofday(&ts);
> +		rtc_time_to_tm(ts.tv_sec, &tm);
> +		pr_info("request_suspend_state: %s (%d->%d) at %lld "
> +			"(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n",
> +			new_state != PM_SUSPEND_ON ? "sleep" : "wakeup",
> +			requested_suspend_state, new_state,
> +			ktime_to_ns(ktime_get()),
> +			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
> +			tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
> +	}
> +	if (!old_sleep && new_state != PM_SUSPEND_ON) {
> +		state |= SUSPEND_REQUESTED;
> +		queue_work(suspend_work_queue, &early_suspend_work);
> +	} else if (old_sleep && new_state == PM_SUSPEND_ON) {
> +		state &= ~SUSPEND_REQUESTED;
> +		wake_lock(&main_wake_lock);
> +		queue_work(suspend_work_queue, &late_resume_work);
> +	}
> +	requested_suspend_state = new_state;
> +	spin_unlock_irqrestore(&state_lock, irqflags);
> +}
> +
> +suspend_state_t get_suspend_state(void)
> +{
> +	return requested_suspend_state;
> +}
> diff --git a/kernel/power/power.h b/kernel/power/power.h
> index ed1b7f4..acbb13a 100644
> --- a/kernel/power/power.h
> +++ b/kernel/power/power.h
> @@ -231,3 +231,9 @@ extern struct wake_lock main_wake_lock;
>  extern suspend_state_t requested_suspend_state;
>  extern bool ignore_suspend_wakelocks;
>  #endif
> +
> +#ifdef CONFIG_EARLYSUSPEND
> +/* kernel/power/earlysuspend.c */
> +void request_suspend_state(suspend_state_t state);
> +suspend_state_t get_suspend_state(void);
> +#endif
_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-07 18:56   ` Rafael J. Wysocki
@ 2009-02-07 22:51     ` Arve Hjønnevåg
  2009-02-07 23:25       ` Rafael J. Wysocki
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-07 22:51 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sat, Feb 7, 2009 at 10:56 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> If my understanding is correct, a wakelock is a mechanism that, if held, will
> prevent the system from (automatically) entering a sleep state, but why do we
> need a number of such wakelocks instead of just one reference counter with the
> rule that (automatic) suspend can only happen if the counter is zero?

Using wakelocks instead of a global reference count ensures that your
request cannot be cleared by someone else. It means that you can,
without knowing the current state of the lock, safely call wake_lock
when you know that you need the wakelock, and wake_unlock when you are
done. It allows wakelocks with timeouts and detailed stats.

> Then, code paths wanting to prevent the suspend from happening would only need
> to increase the counter and it shouldn't be difficult to provide a user space
> interface for that.

No, but you would also need to provide way to decrement it, which
would allow user-space to override a request to stay awake in the
kernel or from another client.

>> +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.
>
> And what's this call needed for?

It is needed to give code that do not use wakelocks a chance to run.
For instance we have not added wakelocks to the network stack. We also
use it in some places when passing data to untrusted userspace code.

> Is there a mechanism allowing us to see what wakelocks have been created by
> the user land?  Something like this would be useful for debugging.

/proc/wakelocks shows all wakelocks. It does not currently indicate if
a wakelock is from userspace, but if you are looking for a specific
lock it is easy to find. I can add a prefix to the name of all user
space wakelocks of you want.

>> +Do not use randomly generated wakelock names as there is no api to free
>> +a user-space wakelock.
>
> This appears to be very fragile.  Please rethink it.

I'm adding a /dev interface which removes this limitation.

>> +/* 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);
>
> What's the purpose of this function?

It is used by our alarm driver to abort suspend.

>> +/* 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);
>
> And this?

It is used to abort suspend. Currently when freezing processes, but it
could also be called between each driver suspend call to improve
wakeup latency when a wakelock is locked while suspending.

We also use it (with WAKE_LOCK_IDLE) to select the idle sleep mode.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 07/13] PM: wakelock: Add /sys/power/request_state
  2009-02-05  2:50             ` [PATCH 07/13] PM: wakelock: Add /sys/power/request_state Arve Hjønnevåg
  2009-02-05  2:50               ` [PATCH 08/13] PM: Add user-space wake lock api Arve Hjønnevåg
  2009-02-05  8:52               ` [PATCH 07/13] PM: wakelock: Add /sys/power/request_state Pavel Machek
@ 2009-02-07 22:54               ` Rafael J. Wysocki
  2 siblings, 0 replies; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-07 22:54 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thursday 05 February 2009, Arve Hjønnevåg wrote:
> This is a non-blocking interface that specifies which suspend state to
> enter when no wakelocks are locked. A special state, "on", stops the
> process by locking the "main" wakelock.
> 
> If early-suspend support is enabled, early suspend handlers will be called
> when a state other than "on" is written. When writing "on", the corresonding
> resume handlers are called.
> 
> Signed-off-by: Arve Hjønnevåg <arve@android.com>
> ---
>  kernel/power/main.c |   74 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 74 insertions(+), 0 deletions(-)
> 
> diff --git a/kernel/power/main.c b/kernel/power/main.c
> index e2aae3e..676a8b0 100644
> --- a/kernel/power/main.c
> +++ b/kernel/power/main.c
> @@ -22,6 +22,7 @@
>  #include <linux/freezer.h>
>  #include <linux/vmstat.h>
>  #include <linux/syscalls.h>
> +#include <linux/wakelock.h>
>  
>  #include "power.h"
>  
> @@ -388,6 +389,9 @@ static void suspend_finish(void)
>  
>  
>  static const char * const pm_states[PM_SUSPEND_MAX] = {
> +#ifdef CONFIG_WAKELOCK
> +	[PM_SUSPEND_ON]		= "on",
> +#endif
>  	[PM_SUSPEND_STANDBY]	= "standby",
>  	[PM_SUSPEND_MEM]	= "mem",
>  };
> @@ -545,6 +549,73 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
>  power_attr(state);
>  #endif
>  
> +/**
> + *	request_state - control system power state.
> + *
> + *	This is similar to state, but it does not block until the system
> + *	resumes, and it will try to re-enter the state until another state is
> + *	requsted. Wakelocks are respected and the requested state will only
> + *	be entered when no wakelocks are held. Write "on" to cancel.
> + *
> + *	If CONFIG_EARLYSUSPEND is set, early_suspend hooks are called when
> + *	the requested state changes to or from "on"
> + */
> +
> +#ifdef CONFIG_WAKELOCK
> +static ssize_t request_state_show(struct kobject *kobj, struct kobj_attribute *attr,
> +			  char *buf)
> +{
> +	char *s = buf;
> +	int i;
> +
> +	for (i = 0; i < PM_SUSPEND_MAX; i++) {
> +		if (pm_states[i] && valid_state(i))
> +			s += sprintf(s,"%s ", pm_states[i]);
> +	}
> +	if (s != buf)
> +		/* convert the last space to a newline */
> +		*(s-1) = '\n';
> +	return (s - buf);
> +}

Isn't the above duplicated code?

> +
> +static ssize_t request_state_store(struct kobject *kobj, struct kobj_attribute *attr,
> +			   const char *buf, size_t n)
> +{
> +	suspend_state_t state = PM_SUSPEND_ON;
> +	const char * const *s;
> +	char *p;
> +	int len;
> +	int error = -EINVAL;
> +
> +	p = memchr(buf, '\n', n);
> +	len = p ? p - buf : n;
> +
> +	for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
> +		if (*s && len == strlen(*s) && !strncmp(buf, *s, len))
> +			break;
> +	}
> +	if (state < PM_SUSPEND_MAX && *s)
> +		if (state == PM_SUSPEND_ON || valid_state(state)) {
> +			error = 0;
> +#ifdef CONFIG_EARLYSUSPEND
> +			request_suspend_state(state);
> +#else

Remove this #ifdef please.

> +			if (!mutex_trylock(&pm_mutex))
> +				return -EBUSY;
> +			requested_suspend_state = state;
> +			if (state == PM_SUSPEND_ON)
> +				wake_lock(&main_wake_lock);
> +			else
> +				wake_unlock(&main_wake_lock);

What's the main_wake_lock and what exactly is its role?

> +			mutex_unlock(&pm_mutex);
> +#endif
> +		}
> +	return error ? error : n;
> +}
> +
> +power_attr(request_state);
> +#endif
> +
>  #ifdef CONFIG_PM_TRACE
>  int pm_trace_enabled;
>  
> @@ -574,6 +645,9 @@ static struct attribute * g[] = {
>  #ifndef CONFIG_DISABLE_SYS_POWER_STATE
>  	&state_attr.attr,
>  #endif
> +#ifdef CONFIG_WAKELOCK
> +	&request_state_attr.attr,
> +#endif
>  #ifdef CONFIG_PM_TRACE
>  	&pm_trace_attr.attr,
>  #endif

I don't think all of this is really necessary.  IMO we should create bus
type-specific interfaces for putting devices into low power states at run time,
that will work along with the existing suspend-resume infrastructure,
instead of this.

Thanks,
Rafael
_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-07 22:51     ` Arve Hjønnevåg
@ 2009-02-07 23:25       ` Rafael J. Wysocki
  2009-02-08  0:20         ` Arve Hjønnevåg
  0 siblings, 1 reply; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-07 23:25 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Saturday 07 February 2009, Arve Hjønnevåg wrote:
> On Sat, Feb 7, 2009 at 10:56 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > If my understanding is correct, a wakelock is a mechanism that, if held, will
> > prevent the system from (automatically) entering a sleep state, but why do we
> > need a number of such wakelocks instead of just one reference counter with the
> > rule that (automatic) suspend can only happen if the counter is zero?
> 
> Using wakelocks instead of a global reference count ensures that your
> request cannot be cleared by someone else.

Decreasing the refcount without increasing it would have been a bug, IMO.

> It means that you can, without knowing the current state of the lock, safely
> call wake_lock when you know that you need the wakelock, and
> wake_unlock when you are done.

You can do the same with a reference counter IMO.

> It allows wakelocks with timeouts

OK

What for?

> and detailed stats.

Well, I'm not sure how this is useful in the long run.

> > Then, code paths wanting to prevent the suspend from happening would only need
> > to increase the counter and it shouldn't be difficult to provide a user space
> > interface for that.
> 
> No, but you would also need to provide way to decrement it, which
> would allow user-space to override a request to stay awake in the
> kernel or from another client.

OK, that's a good reason.

However, it might be better to use a refcount along with some mechanism
allowing user space processes to increase it only once before decreasing.
That would require a per-task flag, but I think you can reuse one of the
freezer flags for that (the freezer is not going to run as long as a wakelock
is held, right?).

> >> +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.
> >
> > And what's this call needed for?

Please don't remove the context.  This makes reading your reply difficult.

> It is needed to give code that do not use wakelocks a chance to run.
> For instance we have not added wakelocks to the network stack. We also
> use it in some places when passing data to untrusted userspace code.

Do you mean to take a wakelock with a timeout in one code path so that some
other code path can run knowing that suspend will not happen?

If this is correct, I don't like it, because it's inherently unreliable (you
really never know how long it will take the other code path to run, so you
can't choose the timeout 100% accurately).

I really would use a refcount and make sure it's increased (and obviously
decreased) by _every_ code path that needs to prevent suspend from happening,
including networking and so on.

> > Is there a mechanism allowing us to see what wakelocks have been created by
> > the user land?  Something like this would be useful for debugging.
> 
> /proc/wakelocks shows all wakelocks. It does not currently indicate if
> a wakelock is from userspace, but if you are looking for a specific
> lock it is easy to find. I can add a prefix to the name of all user
> space wakelocks of you want.

Well, actually, do the wakelocks have to have the names?

> >> +Do not use randomly generated wakelock names as there is no api to free
> >> +a user-space wakelock.
> >
> > This appears to be very fragile.  Please rethink it.
> 
> I'm adding a /dev interface which removes this limitation.
> 
> >> +/* 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);
> >
> > What's the purpose of this function?
> 
> It is used by our alarm driver to abort suspend.

In what way, exactly?

> >> +/* 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);

Well, it should be called max_wake_lock_timeout() or something like this.

> > And this?
> 
> It is used to abort suspend. Currently when freezing processes, but it
> could also be called between each driver suspend call to improve
> wakeup latency when a wakelock is locked while suspending.
> 
> We also use it (with WAKE_LOCK_IDLE) to select the idle sleep mode.

OK, but it is not supposed to be used by device drivers, right?

Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 02/13] PM: Add early suspend api.
  2009-02-07 20:53     ` Rafael J. Wysocki
@ 2009-02-07 23:34       ` Arve Hjønnevåg
  2009-02-08 20:59         ` Pavel Machek
  2009-02-08 23:59         ` Rafael J. Wysocki
  0 siblings, 2 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-07 23:34 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sat, Feb 7, 2009 at 12:53 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
>> +The early-suspend api allows drivers to get notified when user-space writes to
>> +/sys/power/request_state to indicate that the user visible sleep state should
>> +change. A level controls what order the handlers are called in. Suspend
>> +handlers are called in low to high level order, resume handlers are called in
>> +the opposite order.
>
> I don't really understand this description, sorry.
>
> In particular, what values can be written to /sys/power/request_state, what
> their meaning is and what's supposed to happen if someone writes one of these
> values to this file?

Is it clearer if I change it to:

The early-suspend api allows drivers to get notified when user-space writes a
sleep state, e.g. "mem", or "on" to /sys/power/request_state to indicate that
the user visible sleep state should change. ...

>
>> +
>> +Four levels are defined:
>> +EARLY_SUSPEND_LEVEL_BLANK_SCREEN:
>> +  On suspend the screen should be turned off but the framebuffer must still be
>> +  accessible. On resume the screen can be turned back on.
>
> What exactly is the meaning of "suspend" here?

early-suspend.

>> +EARLY_SUSPEND_LEVEL_STOP_DRAWING:
>> +  On suspend this level notifies user-space that it should stop accessing the
>> +  framebuffer and it waits for it to complete. On resume it notifies user-space
>> +  that it should resume screen access.
>> +  Two methods are provided, console switch or a sysfs interface.
>
> How exactly is the notification supposed to happen?

Console switch or a blocking sysfs read.

>> +EARLY_SUSPEND_LEVEL_DISABLE_FB:
>> +  Turn off the framebuffer on suspend and back on on resume.
>> +
>> +EARLY_SUSPEND_LEVEL_STOP_INPUT:
>> +  On suspend turn off input devices that are not capable of wakeup or where
>> +  wakeup is disabled. On resume turn the same devices back on.
>
> This always happens during suspend-resume.  How is this different from the
> usual suspend-resume behaviour?

It happens when user-space changes the state, before wakelocks are released.

>> +struct early_suspend {
>> +#ifdef CONFIG_HAS_EARLYSUSPEND
>> +     struct list_head link;
>> +     int level;
>> +     void (*suspend)(struct early_suspend *h);
>> +     void (*resume)(struct early_suspend *h);
>> +#endif
>> +};
>
> Does this mean addional suspend-resume callbacks for device drivers?

Yes.

> If so, how are they different from the "standard" suspend-resume callbacks?

They are called at a different time.

> Also, what about bus types that carry out some suspend-resume operations
> for their devices, like PCI?  Your early callbacks don't seem to take the
> bus type part into account.

No, the driver will have to take care of this. It has to do the same
work as it would do if it got and ioctl command to enter a low power
state.

> My understanding of the 'early suspend' idea is that it is a mechanism allowing
> us to place some devices selectively into low power states before the actual
> suspend happens.  However, this is exactly the same as runtime power
> management on demand, with an interface allowing user space to put devices into
> low power states.

The main point is to have a single entrypoint from user-space. We do
not have a list of devices to suspend in user-space.

> Now, in my opinion, runtime power management should be implemented on the
> bus type level, since bus types differ from each other by power management
> requirements, mechanisms that can be used and hardware interfaces.
>
> I have some prototype patches for PCI runtime PM in the works.  I didn't
> intend to post them just yet, since I'm considering them as work in progress.
> Still, I can do that if you think it would be useful.

We don't have a PCI bus, but a generic mechanism to put individual
devices to sleep, from within the kernel or from user-space, would be
useful.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-07 23:25       ` Rafael J. Wysocki
@ 2009-02-08  0:20         ` Arve Hjønnevåg
  2009-02-08 21:21           ` Pavel Machek
  2009-02-09  0:15           ` Rafael J. Wysocki
  0 siblings, 2 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-08  0:20 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sat, Feb 7, 2009 at 3:25 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> On Saturday 07 February 2009, Arve Hjønnevåg wrote:
>> On Sat, Feb 7, 2009 at 10:56 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
>> > If my understanding is correct, a wakelock is a mechanism that, if held, will
>> > prevent the system from (automatically) entering a sleep state, but why do we
>> > need a number of such wakelocks instead of just one reference counter with the
>> > rule that (automatic) suspend can only happen if the counter is zero?
>>
>> Using wakelocks instead of a global reference count ensures that your
>> request cannot be cleared by someone else.
>
> Decreasing the refcount without increasing it would have been a bug, IMO.

Yes, but if all you have is a global reference count, you can't tell
where the bug is.

>> It means that you can, without knowing the current state of the lock, safely
>> call wake_lock when you know that you need the wakelock, and
>> wake_unlock when you are done.
>
> You can do the same with a reference counter IMO.

Not without some per lock state.

>> It allows wakelocks with timeouts
>
> OK
>
> What for?

So we do not have to change everything at once, and so we can allow
code that we do not really trust a chance to run.

>> and detailed stats.
>
> Well, I'm not sure how this is useful in the long run.

You may want to know which app drained your battery.

>> > Then, code paths wanting to prevent the suspend from happening would only need
>> > to increase the counter and it shouldn't be difficult to provide a user space
>> > interface for that.
>>
>> No, but you would also need to provide way to decrement it, which
>> would allow user-space to override a request to stay awake in the
>> kernel or from another client.
>
> OK, that's a good reason.
>
> However, it might be better to use a refcount along with some mechanism
> allowing user space processes to increase it only once before decreasing.
> That would require a per-task flag, but I think you can reuse one of the
> freezer flags for that (the freezer is not going to run as long as a wakelock
> is held, right?).

How would this be better?

>
>> >> +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.
>> >
>> > And what's this call needed for?
>
> Please don't remove the context.  This makes reading your reply difficult.

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

>
>> It is needed to give code that do not use wakelocks a chance to run.
>> For instance we have not added wakelocks to the network stack. We also
>> use it in some places when passing data to untrusted userspace code.
>
> Do you mean to take a wakelock with a timeout in one code path so that some
> other code path can run knowing that suspend will not happen?
>
> If this is correct, I don't like it, because it's inherently unreliable (you
> really never know how long it will take the other code path to run, so you
> can't choose the timeout 100% accurately).

I agree, but without wakelock support you have two options. Do not
user suspend at all, or use a global timeout that you reset everywhere
we lock a wakelock. By using wakelocks with timeouts we can at least
make some events 100% reliable.

>
> I really would use a refcount and make sure it's increased (and obviously
> decreased) by _every_ code path that needs to prevent suspend from happening,
> including networking and so on.
>
>> > Is there a mechanism allowing us to see what wakelocks have been created by
>> > the user land?  Something like this would be useful for debugging.
>>
>> /proc/wakelocks shows all wakelocks. It does not currently indicate if
>> a wakelock is from userspace, but if you are looking for a specific
>> lock it is easy to find. I can add a prefix to the name of all user
>> space wakelocks of you want.
>
> Well, actually, do the wakelocks have to have the names?

If you want to debug the system or provide stats, yes.

>> >> +/* 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);
>> >
>> > What's the purpose of this function?
>>
>> It is used by our alarm driver to abort suspend.
>
> In what way, exactly?

The alarm driver sets an rtc alarm on suspend. After grabbing its
state lock it, checks if the wakelock is active. Since the wakelock
implementation now prevents suspend in a suspend_late hook when
wakelocks are held, this may not be strictly necessary anymore, but
prevents the alarm driver from having to deal with the state of being
suspended while an alarm is pending.

>> >> +/* 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);
>
> Well, it should be called max_wake_lock_timeout() or something like this.

I called it has_wake_lock since most of the clients do not care about
the timeout. I think "if(has_wake_lock(" is easier to read than
"if(max_wake_lock_timeout(".

>
>> > And this?
>>
>> It is used to abort suspend. Currently when freezing processes, but it
>> could also be called between each driver suspend call to improve
>> wakeup latency when a wakelock is locked while suspending.
>>
>> We also use it (with WAKE_LOCK_IDLE) to select the idle sleep mode.
>
> OK, but it is not supposed to be used by device drivers, right?

No, it is only used by generic or machine specific power management code.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 06/13] PM: Implement early suspend api
  2009-02-07 22:47             ` Rafael J. Wysocki
@ 2009-02-08  2:32               ` Benjamin Herrenschmidt
  2009-02-08 13:33                 ` Rafael J. Wysocki
  0 siblings, 1 reply; 251+ messages in thread
From: Benjamin Herrenschmidt @ 2009-02-08  2:32 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: swetland, u.luckas, ncunningham, linux-pm

On Sat, 2009-02-07 at 23:47 +0100, Rafael J. Wysocki wrote:
> On Thursday 05 February 2009, Arve Hjønnevåg wrote:
> > Signed-off-by: Arve Hjønnevåg <arve@android.com>
> 
> I don't really agree with this design, because I don't think it's suitable for
> all bus types.  Namely, if any bus type partially handles suspend-resume of
> its devices to offload device drivers, I don't see how that is going to work
> along with your design.
> 
> You seem to require the drivers that will register the early resume handlers
> to take care of everything, along with the operations that should really belong
> to bus types.  I don't think it's a good approach. 

More specifically, with the work you (Rafael) are doing at the moment,
things like PCI or other low level busses would be fully restored in
the early resume phase before drivers gets their resume_early.
Henceforth, it would be possible for things like fbdev's etc... to
resume from resume_early() which is probably soon enough.

Ie. I currently have this hack in radeonfb to resume it even before that
while IRQs are still off etc... but it's a can of worms due to various
might_sleep() hits in subsystems left and right (PCI, AGP, etc...).

I'm actually thinking that when I migrate all of that to radeon DRM/KMS,
I'll probably stick it all just in late_suspend/early_resume provided
our plans to change the interrupt disabling go in and might_sleep()
becomes safe in that phase.

I don't see this Android early_suspend stuff fitting anywhere in that
scheme... looks to me like some people hacked up some ad-hoc trick for
their own local need without instead trying to figure out how to fit
things with the existing infrastructure (or possibly propose changes to
the existing infrastructure to fit their needs).

Ben.

> Thanks,
> Rafael
> 
> > ---
> >  kernel/power/Kconfig        |   12 +++
> >  kernel/power/Makefile       |    1 +
> >  kernel/power/earlysuspend.c |  178 +++++++++++++++++++++++++++++++++++++++++++
> >  kernel/power/power.h        |    6 ++
> >  4 files changed, 197 insertions(+), 0 deletions(-)
> >  create mode 100644 kernel/power/earlysuspend.c
> > 
> > diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
> > index dd76467..689abfe 100644
> > --- a/kernel/power/Kconfig
> > +++ b/kernel/power/Kconfig
> > @@ -119,6 +119,9 @@ config SUSPEND_FREEZER
> >  config HAS_WAKELOCK
> >  	bool
> >  
> > +config HAS_EARLYSUSPEND
> > +	bool
> > +
> >  config WAKELOCK
> >  	bool "Wake lock"
> >  	depends on PM && RTC_CLASS
> > @@ -144,6 +147,15 @@ config DISABLE_SYS_POWER_STATE
> >  	  want to run user-space code that does not support wakelocks, do not
> >  	  enable this option since it removes the interface.
> >  
> > +config EARLYSUSPEND
> > +	bool "Early suspend"
> > +	depends on WAKELOCK
> > +	default y
> > +	select HAS_EARLYSUSPEND
> > +	---help---
> > +	  Call early suspend handlers when the user requested sleep state
> > +	  changes.
> > +
> >  config HIBERNATION
> >  	bool "Hibernation (aka 'suspend to disk')"
> >  	depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
> > diff --git a/kernel/power/Makefile b/kernel/power/Makefile
> > index 8d8672b..2f17e1d 100644
> > --- a/kernel/power/Makefile
> > +++ b/kernel/power/Makefile
> > @@ -7,6 +7,7 @@ obj-y				:= main.o
> >  obj-$(CONFIG_PM_SLEEP)		+= console.o
> >  obj-$(CONFIG_FREEZER)		+= process.o
> >  obj-$(CONFIG_WAKELOCK)		+= wakelock.o
> > +obj-$(CONFIG_EARLYSUSPEND)	+= earlysuspend.o
> >  obj-$(CONFIG_HIBERNATION)	+= swsusp.o disk.o snapshot.o swap.o user.o
> >  
> >  obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
> > diff --git a/kernel/power/earlysuspend.c b/kernel/power/earlysuspend.c
> > new file mode 100644
> > index 0000000..4d70a7e
> > --- /dev/null
> > +++ b/kernel/power/earlysuspend.c
> > @@ -0,0 +1,178 @@
> > +/* kernel/power/earlysuspend.c
> > + *
> > + * Copyright (C) 2005-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.
> > + *
> > + */
> > +
> > +#include <linux/earlysuspend.h>
> > +#include <linux/module.h>
> > +#include <linux/mutex.h>
> > +#include <linux/rtc.h>
> > +#include <linux/syscalls.h> /* sys_sync */
> > +#include <linux/wakelock.h>
> > +#include <linux/workqueue.h>
> > +
> > +#include "power.h"
> > +
> > +enum {
> > +	DEBUG_USER_STATE = 1U << 0,
> > +	DEBUG_SUSPEND = 1U << 1,
> > +};
> > +static int debug_mask = DEBUG_USER_STATE;
> > +module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
> > +
> > +static DEFINE_MUTEX(early_suspend_lock);
> > +static LIST_HEAD(early_suspend_handlers);
> > +static void early_suspend(struct work_struct *work);
> > +static void late_resume(struct work_struct *work);
> > +static DECLARE_WORK(early_suspend_work, early_suspend);
> > +static DECLARE_WORK(late_resume_work, late_resume);
> > +static DEFINE_SPINLOCK(state_lock);
> > +enum {
> > +	SUSPEND_REQUESTED = 0x1,
> > +	SUSPENDED = 0x2,
> > +	SUSPEND_REQUESTED_AND_SUSPENDED = SUSPEND_REQUESTED | SUSPENDED,
> > +};
> > +static int state;
> > +
> > +void register_early_suspend(struct early_suspend *handler)
> > +{
> > +	struct list_head *pos;
> > +
> > +	mutex_lock(&early_suspend_lock);
> > +	list_for_each(pos, &early_suspend_handlers) {
> > +		struct early_suspend *e;
> > +		e = list_entry(pos, struct early_suspend, link);
> > +		if (e->level > handler->level)
> > +			break;
> > +	}
> > +	list_add_tail(&handler->link, pos);
> > +	if ((state & SUSPENDED) && handler->suspend)
> > +		handler->suspend(handler);
> > +	mutex_unlock(&early_suspend_lock);
> > +}
> > +EXPORT_SYMBOL(register_early_suspend);
> > +
> > +void unregister_early_suspend(struct early_suspend *handler)
> > +{
> > +	mutex_lock(&early_suspend_lock);
> > +	list_del(&handler->link);
> > +	mutex_unlock(&early_suspend_lock);
> > +}
> > +EXPORT_SYMBOL(unregister_early_suspend);
> > +
> > +static void early_suspend(struct work_struct *work)
> > +{
> > +	struct early_suspend *pos;
> > +	unsigned long irqflags;
> > +	int abort = 0;
> > +
> > +	mutex_lock(&early_suspend_lock);
> > +	spin_lock_irqsave(&state_lock, irqflags);
> > +	if (state == SUSPEND_REQUESTED)
> > +		state |= SUSPENDED;
> > +	else
> > +		abort = 1;
> > +	spin_unlock_irqrestore(&state_lock, irqflags);
> > +
> > +	if (abort) {
> > +		if (debug_mask & DEBUG_SUSPEND)
> > +			pr_info("early_suspend: abort, state %d\n", state);
> > +		mutex_unlock(&early_suspend_lock);
> > +		goto abort;
> > +	}
> > +
> > +	if (debug_mask & DEBUG_SUSPEND)
> > +		pr_info("early_suspend: call handlers\n");
> > +	list_for_each_entry(pos, &early_suspend_handlers, link) {
> > +		if (pos->suspend)
> > +			pos->suspend(pos);
> > +	}
> > +	mutex_unlock(&early_suspend_lock);
> > +
> > +	if (debug_mask & DEBUG_SUSPEND)
> > +		pr_info("early_suspend: sync\n");
> > +
> > +	sys_sync();
> > +abort:
> > +	spin_lock_irqsave(&state_lock, irqflags);
> > +	if (state == SUSPEND_REQUESTED_AND_SUSPENDED)
> > +		wake_unlock(&main_wake_lock);
> > +	spin_unlock_irqrestore(&state_lock, irqflags);
> > +}
> > +
> > +static void late_resume(struct work_struct *work)
> > +{
> > +	struct early_suspend *pos;
> > +	unsigned long irqflags;
> > +	int abort = 0;
> > +
> > +	mutex_lock(&early_suspend_lock);
> > +	spin_lock_irqsave(&state_lock, irqflags);
> > +	if (state == SUSPENDED)
> > +		state = 0; /* clear SUSPENDED */
> > +	else
> > +		abort = 1;
> > +	spin_unlock_irqrestore(&state_lock, irqflags);
> > +
> > +	if (abort) {
> > +		if (debug_mask & DEBUG_SUSPEND)
> > +			pr_info("late_resume: abort, state %d\n", state);
> > +		goto abort;
> > +	}
> > +	if (debug_mask & DEBUG_SUSPEND)
> > +		pr_info("late_resume: call handlers\n");
> > +	list_for_each_entry_reverse(pos, &early_suspend_handlers, link)
> > +		if (pos->resume)
> > +			pos->resume(pos);
> > +	if (debug_mask & DEBUG_SUSPEND)
> > +		pr_info("late_resume: done\n");
> > +abort:
> > +	mutex_unlock(&early_suspend_lock);
> > +}
> > +
> > +void request_suspend_state(suspend_state_t new_state)
> > +{
> > +	unsigned long irqflags;
> > +	int old_sleep;
> > +
> > +	spin_lock_irqsave(&state_lock, irqflags);
> > +	old_sleep = state & SUSPEND_REQUESTED;
> > +	if (debug_mask & DEBUG_USER_STATE) {
> > +		struct timespec ts;
> > +		struct rtc_time tm;
> > +		getnstimeofday(&ts);
> > +		rtc_time_to_tm(ts.tv_sec, &tm);
> > +		pr_info("request_suspend_state: %s (%d->%d) at %lld "
> > +			"(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n",
> > +			new_state != PM_SUSPEND_ON ? "sleep" : "wakeup",
> > +			requested_suspend_state, new_state,
> > +			ktime_to_ns(ktime_get()),
> > +			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
> > +			tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
> > +	}
> > +	if (!old_sleep && new_state != PM_SUSPEND_ON) {
> > +		state |= SUSPEND_REQUESTED;
> > +		queue_work(suspend_work_queue, &early_suspend_work);
> > +	} else if (old_sleep && new_state == PM_SUSPEND_ON) {
> > +		state &= ~SUSPEND_REQUESTED;
> > +		wake_lock(&main_wake_lock);
> > +		queue_work(suspend_work_queue, &late_resume_work);
> > +	}
> > +	requested_suspend_state = new_state;
> > +	spin_unlock_irqrestore(&state_lock, irqflags);
> > +}
> > +
> > +suspend_state_t get_suspend_state(void)
> > +{
> > +	return requested_suspend_state;
> > +}
> > diff --git a/kernel/power/power.h b/kernel/power/power.h
> > index ed1b7f4..acbb13a 100644
> > --- a/kernel/power/power.h
> > +++ b/kernel/power/power.h
> > @@ -231,3 +231,9 @@ extern struct wake_lock main_wake_lock;
> >  extern suspend_state_t requested_suspend_state;
> >  extern bool ignore_suspend_wakelocks;
> >  #endif
> > +
> > +#ifdef CONFIG_EARLYSUSPEND
> > +/* kernel/power/earlysuspend.c */
> > +void request_suspend_state(suspend_state_t state);
> > +suspend_state_t get_suspend_state(void);
> > +#endif
> _______________________________________________
> linux-pm mailing list
> linux-pm@lists.linux-foundation.org
> https://lists.linux-foundation.org/mailman/listinfo/linux-pm

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-07 22:37           ` Rafael J. Wysocki
@ 2009-02-08 10:33             ` Pavel Machek
  2009-02-08 13:50               ` Rafael J. Wysocki
  0 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-08 10:33 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sat 2009-02-07 23:37:39, Rafael J. Wysocki wrote:
> On Thursday 05 February 2009, Arve Hj??nnev??g wrote:
> > Signed-off-by: Arve Hj??nnev??g <arve@android.com>
> 
> This is completely wrong, IMO.
> 
> Removing an interface that has existed forever just because it happens to
> be incompatible with your new shiny feature is not acceptable to me.

Agreed. AFAICS this patch can be just dropped, or maybe kept specially
for android if those few bytes matter to them.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 06/13] PM: Implement early suspend api
  2009-02-08  2:32               ` Benjamin Herrenschmidt
@ 2009-02-08 13:33                 ` Rafael J. Wysocki
  0 siblings, 0 replies; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-08 13:33 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: swetland, u.luckas, ncunningham, linux-pm

On Sunday 08 February 2009, Benjamin Herrenschmidt wrote:
> On Sat, 2009-02-07 at 23:47 +0100, Rafael J. Wysocki wrote:
> > On Thursday 05 February 2009, Arve Hjønnevåg wrote:
> > > Signed-off-by: Arve Hjønnevåg <arve@android.com>
> > 
> > I don't really agree with this design, because I don't think it's suitable for
> > all bus types.  Namely, if any bus type partially handles suspend-resume of
> > its devices to offload device drivers, I don't see how that is going to work
> > along with your design.
> > 
> > You seem to require the drivers that will register the early resume handlers
> > to take care of everything, along with the operations that should really belong
> > to bus types.  I don't think it's a good approach. 
> 
> More specifically, with the work you (Rafael) are doing at the moment,
> things like PCI or other low level busses would be fully restored in
> the early resume phase before drivers gets their resume_early.
> Henceforth, it would be possible for things like fbdev's etc... to
> resume from resume_early() which is probably soon enough.

That's correct IMO.

> Ie. I currently have this hack in radeonfb to resume it even before that
> while IRQs are still off etc... but it's a can of worms due to various
> might_sleep() hits in subsystems left and right (PCI, AGP, etc...).
> 
> I'm actually thinking that when I migrate all of that to radeon DRM/KMS,
> I'll probably stick it all just in late_suspend/early_resume provided
> our plans to change the interrupt disabling go in and might_sleep()
> becomes safe in that phase.

I'm going to start working on the disabling of interrupts shortly.

> I don't see this Android early_suspend stuff fitting anywhere in that
> scheme... looks to me like some people hacked up some ad-hoc trick for
> their own local need without instead trying to figure out how to fit
> things with the existing infrastructure (or possibly propose changes to
> the existing infrastructure to fit their needs).

This also is my impression.

Thanks,
Rafael
_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-08 10:33             ` Pavel Machek
@ 2009-02-08 13:50               ` Rafael J. Wysocki
  2009-02-08 14:04                 ` Brian Swetland
  2009-02-08 21:04                 ` Pavel Machek
  0 siblings, 2 replies; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-08 13:50 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sunday 08 February 2009, Pavel Machek wrote:
> On Sat 2009-02-07 23:37:39, Rafael J. Wysocki wrote:
> > On Thursday 05 February 2009, Arve Hj??nnev??g wrote:
> > > Signed-off-by: Arve Hj??nnev??g <arve@android.com>
> > 
> > This is completely wrong, IMO.
> > 
> > Removing an interface that has existed forever just because it happens to
> > be incompatible with your new shiny feature is not acceptable to me.
> 
> Agreed. AFAICS this patch can be just dropped, or maybe kept specially
> for android if those few bytes matter to them.

Just to make things crystal clear, in fact I don't like any patches in this
series.

The wakelocks seem to be overdesigned to me and the "early suspend" thing
doesn't really fit our suspend-resume framework, especially after the changes
made recently to the PCI PM code (and the changes that are going to be made
to it shortly).

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-08 13:50               ` Rafael J. Wysocki
@ 2009-02-08 14:04                 ` Brian Swetland
  2009-02-08 21:06                   ` Pavel Machek
                                     ` (2 more replies)
  2009-02-08 21:04                 ` Pavel Machek
  1 sibling, 3 replies; 251+ messages in thread
From: Brian Swetland @ 2009-02-08 14:04 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: ncunningham, u.luckas, linux-pm

["Rafael J. Wysocki" <rjw@sisk.pl>]
> 
> Just to make things crystal clear, in fact I don't like any patches in this
> series.
> 
> The wakelocks seem to be overdesigned to me and the "early suspend" thing
> doesn't really fit our suspend-resume framework, especially after the changes
> made recently to the PCI PM code (and the changes that are going to be made
> to it shortly).

Out of curiosity, do these changes provide a model where the system can
be in suspend 99+% of the time, waking up for specific events
(voice/data telephony, user interaction, etc), and rapidly returning to
suspend when the processing required is complete?  That's the larger
goal that the wakelock design seeks to accomplish, which is working
pretty well for us in shipping mobile devices.

Being in suspend, where periodic user and kernel timers aren't running,
and random userspace threads aren't possibly spinning, rather than just 
being in idle in the lowest power possible state, represent a pretty 
significant power savings.

None of the hardware we're working with has a PCI bus, or ACPI, or much
of any traditional desktop/server pc features, which may account for
some of the difference in outlook and approach here.

Brian

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 02/13] PM: Add early suspend api.
  2009-02-07 23:34       ` Arve Hjønnevåg
@ 2009-02-08 20:59         ` Pavel Machek
  2009-02-08 23:59         ` Rafael J. Wysocki
  1 sibling, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-08 20:59 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, swetland, linux-pm

Hi!

> > My understanding of the 'early suspend' idea is that it is a mechanism allowing
> > us to place some devices selectively into low power states before the actual
> > suspend happens.  However, this is exactly the same as runtime power
> > management on demand, with an interface allowing user space to put devices into
> > low power states.
> 
> The main point is to have a single entrypoint from user-space. We do
> not have a list of devices to suspend in user-space.

I guess "single entrypoint" is not worth all the effort. ... plus,
different machines will likely need different "single entrypoints".

Can we get working "runtime suspend", instead?
									Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-08 13:50               ` Rafael J. Wysocki
  2009-02-08 14:04                 ` Brian Swetland
@ 2009-02-08 21:04                 ` Pavel Machek
  2009-02-08 21:40                   ` Alan Stern
  2009-02-08 23:44                   ` Rafael J. Wysocki
  1 sibling, 2 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-08 21:04 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: ncunningham, u.luckas, swetland, linux-pm

Hi!

> > > This is completely wrong, IMO.
> > > 
> > > Removing an interface that has existed forever just because it happens to
> > > be incompatible with your new shiny feature is not acceptable to me.
> > 
> > Agreed. AFAICS this patch can be just dropped, or maybe kept specially
> > for android if those few bytes matter to them.
> 
> Just to make things crystal clear, in fact I don't like any patches in this
> series.
> 
> The wakelocks seem to be overdesigned to me and the "early suspend" thing

Well, it is true that wakelocks could be single atomic_t ... but they
would make them undebuggable. Ok, wakelock interface sucks. But I
believe something like that is neccessary.

(In fact, I invented something similar for sleepy linux patches).

Early suspend would be better done by runtime suspend, agreed.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-08 14:04                 ` Brian Swetland
@ 2009-02-08 21:06                   ` Pavel Machek
  2009-02-08 23:41                     ` Rafael J. Wysocki
  2009-02-08 23:40                   ` Rafael J. Wysocki
  2009-02-12 11:16                   ` Matthew Garrett
  2 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-08 21:06 UTC (permalink / raw)
  To: Brian Swetland; +Cc: ncunningham, u.luckas, linux-pm

Hi!


> Being in suspend, where periodic user and kernel timers aren't running,
> and random userspace threads aren't possibly spinning, rather than just 
> being in idle in the lowest power possible state, represent a pretty 
> significant power savings.

If kernel timers fire too often, fix them. If user land spins, fix it,
or SIGSTOP.

And yes, autosleep is useful. That's why I done those "sleepy linux"
patches.
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-08  0:20         ` Arve Hjønnevåg
@ 2009-02-08 21:21           ` Pavel Machek
  2009-02-09  0:03             ` Rafael J. Wysocki
  2009-02-09  0:15           ` Rafael J. Wysocki
  1 sibling, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-08 21:21 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, swetland, linux-pm

Hi!

> >> > If my understanding is correct, a wakelock is a mechanism that, if held, will
> >> > prevent the system from (automatically) entering a sleep state, but why do we
> >> > need a number of such wakelocks instead of just one reference counter with the
> >> > rule that (automatic) suspend can only happen if the counter is zero?
> >>
> >> Using wakelocks instead of a global reference count ensures that your
> >> request cannot be cleared by someone else.
> >
> > Decreasing the refcount without increasing it would have been a bug, IMO.
> 
> Yes, but if all you have is a global reference count, you can't tell
> where the bug is.
...
> >> and detailed stats.
> >
> > Well, I'm not sure how this is useful in the long run.
> 
> You may want to know which app drained your battery.

_If_ we want to allow userspace to hold wakelocks (better name could
be awakelock or nosleeplock?) then some way of displaying them is
required.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-06  0:28     ` Arve Hjønnevåg
  2009-02-06  9:45       ` Uli Luckas
@ 2009-02-08 21:30       ` Pavel Machek
  2009-02-08 23:11         ` Arve Hjønnevåg
  2009-02-08 22:17       ` non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock api.) Pavel Machek
  2 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-08 21:30 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thu 2009-02-05 16:28:28, Arve Hj?nnev?g wrote:
> On Thu, Feb 5, 2009 at 1:11 AM, Pavel Machek <pavel@ucw.cz> wrote:
> > On Wed 2009-02-04 18:50:14, Arve Hj??nnev??g wrote:
> >> +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
> >
> > idle states are very different from suspend. Mixing them does not look
> > like good idea... and IIRC we already have API somewhere to prevent
> > deep idle states. Intel did it for their wireless cards IIRC.
> 
> If you are talking about the pm_qos interface, then yes there is some
> overlap. We did not use the pm_qos interface since it does a linear
> scan for a string every time you change a requirement, and it only
> let

If pm_qos code is too slow for you, just fix it! 

> you specify the latency you need not the power level. We have
> interrupts that stop working at the lowest power level and this does
> not easily translate into a latency value.

Could clock framwork be used for this? 

Or maybe you just want to prevent low idle states as long as those
interrupts are claimed, no new api needed?

									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-08 21:04                 ` Pavel Machek
@ 2009-02-08 21:40                   ` Alan Stern
  2009-02-08 23:00                     ` Arve Hjønnevåg
  2009-02-08 23:44                     ` Rafael J. Wysocki
  2009-02-08 23:44                   ` Rafael J. Wysocki
  1 sibling, 2 replies; 251+ messages in thread
From: Alan Stern @ 2009-02-08 21:40 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sun, 8 Feb 2009, Pavel Machek wrote:

> Well, it is true that wakelocks could be single atomic_t ... but they
> would make them undebuggable. Ok, wakelock interface sucks. But I
> believe something like that is neccessary.

krefs don't have name strings for keeping track of who has been 
incrementing or decrementing their counters.  And it's true that krefs 
are nearly undebuggable.  But somehow we've managed to struggle along 
without adding names to krefs.  Why should wakelocks be any different?

Alan Stern

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes.
  2009-02-06  2:29                       ` Arve Hjønnevåg
@ 2009-02-08 22:02                         ` Pavel Machek
  2009-02-08 22:53                           ` Arve Hjønnevåg
  0 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-08 22:02 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thu 2009-02-05 18:29:30, Arve Hj?nnev?g wrote:
> On Thu, Feb 5, 2009 at 1:03 AM, Pavel Machek <pavel@ucw.cz> wrote:
> > changelog would be welcome.
>     PM: earlysuspend: Add console switch when user requested sleep
> state changes.
> 
>     When early-suspend is enabled, the framebuffer is turned off at
>     early-suspend. If CONSOLE_EARLYSUSPEND is enabled, a console switch
>     is used to notify user space that it should stop drawing before
>     the framebuffer is disabled, and that it should repaint and resume
>     drawing after the framebuffer is turned back on.

I'd say that userspace can just do the switch itself? I mean, blanking
is slow&uncommon operation... and behaviour of kernel should not
depend on CONFIG_ options.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock api.)
  2009-02-06  0:28     ` Arve Hjønnevåg
  2009-02-06  9:45       ` Uli Luckas
  2009-02-08 21:30       ` Pavel Machek
@ 2009-02-08 22:17       ` Pavel Machek
  2009-02-08 22:40         ` Arve Hjønnevåg
  2009-02-09  1:49         ` non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock api. ) Uli Luckas
  2 siblings, 2 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-08 22:17 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, swetland, linux-pm

Hi!

Ok, I think that this wakelock stuff is in "can't be used properly"
area on Rusty's scale of nasty interfaces.

So... do I understand this correctly that if I want to run "make zImage"
on Android, I'll need to modify make, gcc, .... to keep system awake?

	(How to do that? Give all the userland processes access to
	/sys/wakelocks ?)

BTW what does android do when battery goes critically low? I believe
you want to suspend, ignoring wakelocks, at that point.

And now, you have some X-like system.

	/* We were idle for too long */
	blank_screen();

	unlock_all_wakelocks();		/* We want machine to sleep */

	wait_for_key();
	/* (here) */
	lock_wakelocks("processing_key_wakelock");

...is that approximately correct? There's race there, right? If (here)
processing takes too long, or whatever, kernel will sleep the machine
before it even displays "do you want to unlock the screen" dialog,
right?

Can you solve that in a way that works, always?
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake  lock api.)
  2009-02-08 22:17       ` non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock api.) Pavel Machek
@ 2009-02-08 22:40         ` Arve Hjønnevåg
  2009-02-08 23:14           ` Pavel Machek
  2009-02-09  1:49         ` non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock api. ) Uli Luckas
  1 sibling, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-08 22:40 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sun, Feb 8, 2009 at 2:17 PM, Pavel Machek <pavel@ucw.cz> wrote:
> Hi!
>
> Ok, I think that this wakelock stuff is in "can't be used properly"
> area on Rusty's scale of nasty interfaces.
>
> So... do I understand this correctly that if I want to run "make zImage"
> on Android, I'll need to modify make, gcc, .... to keep system awake?

Or you could grab a wake lock before starting the job. e.g.
"runwithwakelock make".

What prevents the system from suspending while you run make in your
existing system?

>        (How to do that? Give all the userland processes access to
>        /sys/wakelocks ?)

That depends, do you want users to be able to keep the system on?

> BTW what does android do when battery goes critically low? I believe
> you want to suspend, ignoring wakelocks, at that point.

I don't know for sure, but I believe it does a full shutdown.

> And now, you have some X-like system.
>
>        /* We were idle for too long */
>        blank_screen();
>
>        unlock_all_wakelocks();         /* We want machine to sleep */
>
>        wait_for_key();
>        /* (here) */
>        lock_wakelocks("processing_key_wakelock");
>
> ...is that approximately correct? There's race there, right? If (here)
> processing takes too long, or whatever, kernel will sleep the machine
> before it even displays "do you want to unlock the screen" dialog,
> right?
>
> Can you solve that in a way that works, always?

There is no unlock_all_wakelocks call, you unlock the "main" wakelock
by writing to /sys/power/request_state. There is no race in your
example as long as your wait_for_key function just does a select or
poll call and does not read the key events. The wakelock on the event
queue prevents sleep. This is what my example in the wakelock doc
describes.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes.
  2009-02-08 22:02                         ` Pavel Machek
@ 2009-02-08 22:53                           ` Arve Hjønnevåg
  2009-02-08 22:58                             ` Pavel Machek
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-08 22:53 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sun, Feb 8, 2009 at 2:02 PM, Pavel Machek <pavel@ucw.cz> wrote:
> On Thu 2009-02-05 18:29:30, Arve Hj?nnev?g wrote:
>> On Thu, Feb 5, 2009 at 1:03 AM, Pavel Machek <pavel@ucw.cz> wrote:
>> > changelog would be welcome.
>>     PM: earlysuspend: Add console switch when user requested sleep
>> state changes.
>>
>>     When early-suspend is enabled, the framebuffer is turned off at
>>     early-suspend. If CONSOLE_EARLYSUSPEND is enabled, a console switch
>>     is used to notify user space that it should stop drawing before
>>     the framebuffer is disabled, and that it should repaint and resume
>>     drawing after the framebuffer is turned back on.
>
> I'd say that userspace can just do the switch itself?

The purpose of the console switch is to take the framebuffer away from
user-space. Are you suggesting that we instead should initiate sleep
when user-space switches to the sleep console?

> I mean, blanking
> is slow&uncommon operation... and behaviour of kernel should not
> depend on CONFIG_ options.

The kernel does a console switch now. This just changes when it happens.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-11 15:45             ` Rafael J. Wysocki
@ 2009-02-08 22:57               ` Pavel Machek
  0 siblings, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-08 22:57 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Brian Swetland, linux-pm, u.luckas, ncunningham

On Wed 2009-02-11 16:45:46, Rafael J. Wysocki wrote:
> On Wednesday 11 February 2009, Alan Stern wrote:
> > On Tue, 10 Feb 2009, Brian Swetland wrote:
> > 
> > > [Pavel Machek <pavel@ucw.cz>]
> > > > > 
> > > > > wake_lock never blocks.
> > > > 
> > > > Wakelock is really bad name: it is not a lock and it does not protect
> > > > wake. I'd say we need better name here.
> > > 
> > > I agree with you here -- I've had this discussion with Arve previously,
> > > but have been unable to offer a compelling alternative name.  Anybody
> > > have a good idea?
> 
> Well, even "sleep lock" would have been better.
> 
> > delay_sleep or delaysleep?  block_sleep or blocksleep?  Any of the 
> > above with "sleep" replaced by "suspend"?
> 
> I also thought about "sleep stopper".  It reflects what the feature does. :-)

'caffeine' ? :-).
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes.
  2009-02-08 22:53                           ` Arve Hjønnevåg
@ 2009-02-08 22:58                             ` Pavel Machek
  0 siblings, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-08 22:58 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sun 2009-02-08 14:53:33, Arve Hj?nnev?g wrote:
> On Sun, Feb 8, 2009 at 2:02 PM, Pavel Machek <pavel@ucw.cz> wrote:
> > On Thu 2009-02-05 18:29:30, Arve Hj?nnev?g wrote:
> >> On Thu, Feb 5, 2009 at 1:03 AM, Pavel Machek <pavel@ucw.cz> wrote:
> >> > changelog would be welcome.
> >>     PM: earlysuspend: Add console switch when user requested sleep
> >> state changes.
> >>
> >>     When early-suspend is enabled, the framebuffer is turned off at
> >>     early-suspend. If CONSOLE_EARLYSUSPEND is enabled, a console switch
> >>     is used to notify user space that it should stop drawing before
> >>     the framebuffer is disabled, and that it should repaint and resume
> >>     drawing after the framebuffer is turned back on.
> >
> > I'd say that userspace can just do the switch itself?
> 
> The purpose of the console switch is to take the framebuffer away from
> user-space. Are you suggesting that we instead should initiate sleep
> when user-space switches to the sleep console?

That looks like a solution, yes.
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held.
  2009-02-06  3:42                             ` Arve Hjønnevåg
@ 2009-02-08 23:00                               ` Pavel Machek
  0 siblings, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-08 23:00 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thu 2009-02-05 19:42:13, Arve Hj?nnev?g wrote:
> On Thu, Feb 5, 2009 at 2:02 AM, Pavel Machek <pavel@ucw.cz> wrote:
> > ...so I guess I'll wait for extended description.
>     PM: wakelock: Abort task freezing if a wakelock is locked.
> 
>     If a wakelock is locked, suspend will fail anyway. Since try_to_freeze_tasks
>     can take up to 20 seconds to complete or fail, aborting as soon as someone
>     locks a wakelock (e.g. from an interrupt handler) improves the worst case
>     wakeup latency.

Well, I'd rather fix the cases when freeze() takes too long. If that
is infeasible, yes, I guess we can do this.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-08 21:40                   ` Alan Stern
@ 2009-02-08 23:00                     ` Arve Hjønnevåg
  2009-02-08 23:03                       ` Pavel Machek
  2009-02-08 23:44                     ` Rafael J. Wysocki
  1 sibling, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-08 23:00 UTC (permalink / raw)
  To: Alan Stern; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sun, Feb 8, 2009 at 1:40 PM, Alan Stern <stern@rowland.harvard.edu> wrote:
> On Sun, 8 Feb 2009, Pavel Machek wrote:
>
>> Well, it is true that wakelocks could be single atomic_t ... but they
>> would make them undebuggable. Ok, wakelock interface sucks. But I
>> believe something like that is neccessary.
>
> krefs don't have name strings for keeping track of who has been
> incrementing or decrementing their counters.  And it's true that krefs
> are nearly undebuggable.  But somehow we've managed to struggle along
> without adding names to krefs.  Why should wakelocks be any different?

It sounds like you suggesting that we add another nearly undebuggable interface.

Using only a single atomic_t would not allow us to use a wakelock a
switch, or to specify a timeout. You could replace the list in the
implementation with a single atomic_t by adding more state to each
wakelock, but I like my current solution better.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-08 23:00                     ` Arve Hjønnevåg
@ 2009-02-08 23:03                       ` Pavel Machek
  2009-02-09  0:31                         ` Rafael J. Wysocki
  0 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-08 23:03 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sun 2009-02-08 15:00:38, Arve Hj?nnev?g wrote:
> On Sun, Feb 8, 2009 at 1:40 PM, Alan Stern <stern@rowland.harvard.edu> wrote:
> > On Sun, 8 Feb 2009, Pavel Machek wrote:
> >
> >> Well, it is true that wakelocks could be single atomic_t ... but they
> >> would make them undebuggable. Ok, wakelock interface sucks. But I
> >> believe something like that is neccessary.
> >
> > krefs don't have name strings for keeping track of who has been
> > incrementing or decrementing their counters.  And it's true that krefs
> > are nearly undebuggable.  But somehow we've managed to struggle along
> > without adding names to krefs.  Why should wakelocks be any different?
> 
> It sounds like you suggesting that we add another nearly undebuggable interface.
> 
> Using only a single atomic_t would not allow us to use a wakelock a
> switch, or to specify a timeout. You could replace the list in the
> implementation with a single atomic_t by adding more state to each
> wakelock, but I like my current solution better.

For the record, I agree here. And... if struct wakelock contains char
* or not is a very small detail.

If wakelocks can be locked from userspace is _not_ a detail; and if
they can we do need the names.
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-08 21:30       ` Pavel Machek
@ 2009-02-08 23:11         ` Arve Hjønnevåg
  2009-02-09  9:06           ` Pavel Machek
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-08 23:11 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sun, Feb 8, 2009 at 1:30 PM, Pavel Machek <pavel@ucw.cz> wrote:
> On Thu 2009-02-05 16:28:28, Arve Hj?nnev?g wrote:
>> On Thu, Feb 5, 2009 at 1:11 AM, Pavel Machek <pavel@ucw.cz> wrote:
>> > On Wed 2009-02-04 18:50:14, Arve Hj??nnev??g wrote:
>> >> +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
>> >
>> > idle states are very different from suspend. Mixing them does not look
>> > like good idea... and IIRC we already have API somewhere to prevent
>> > deep idle states. Intel did it for their wireless cards IIRC.
>>
>> If you are talking about the pm_qos interface, then yes there is some
>> overlap. We did not use the pm_qos interface since it does a linear
>> scan for a string every time you change a requirement, and it only
>> let
>
> If pm_qos code is too slow for you, just fix it!

The problem is with the api. It uses strings as handles. It was easier
for us to just add another wakelock type since the wakelock code
already supported two types (I have since removed one).

>> you specify the latency you need not the power level. We have
>> interrupts that stop working at the lowest power level and this does
>> not easily translate into a latency value.
>
> Could clock framwork be used for this?

Possibly.

> Or maybe you just want to prevent low idle states as long as those
> interrupts are claimed, no new api needed?

I thnik this is a better solution, and we do this for the main
interrupt controller. We did not do this for gpio interrupts since we
did not have a list.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock api.)
  2009-02-08 22:40         ` Arve Hjønnevåg
@ 2009-02-08 23:14           ` Pavel Machek
  2009-02-08 23:35             ` Arve Hjønnevåg
  0 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-08 23:14 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sun 2009-02-08 14:40:29, Arve Hj?nnev?g wrote:
> On Sun, Feb 8, 2009 at 2:17 PM, Pavel Machek <pavel@ucw.cz> wrote:
> > Hi!
> >
> > Ok, I think that this wakelock stuff is in "can't be used properly"
> > area on Rusty's scale of nasty interfaces.
> >
> > So... do I understand this correctly that if I want to run "make zImage"
> > on Android, I'll need to modify make, gcc, .... to keep system awake?
> 
> Or you could grab a wake lock before starting the job. e.g.
> "runwithwakelock make".

Uhuh.

> What prevents the system from suspending while you run make in your
> existing system?

My existing system does not autosleep.

My experimental sleepy linux will autosleep if it knows there are no
runnable userspace jobs, and if nearest timer to fire is far enough in
future.

> >        (How to do that? Give all the userland processes access to
> >        /sys/wakelocks ?)
> 
> That depends, do you want users to be able to keep the system on?

Yes. But I also want to kill -9 to work, and want my system to sleep
after I kill -9ed all the offending processes.

...which would suggest that wakelock should be a filedescriptor. hmm.

> > BTW what does android do when battery goes critically low? I believe
> > you want to suspend, ignoring wakelocks, at that point.
> 
> I don't know for sure, but I believe it does a full shutdown.

Ok, but suspend would be more elgant (faster, does not loose user
context). Take it as an example where mixing auto-sleep and forced
sleep makes sense.

> > And now, you have some X-like system.
> >
> >        /* We were idle for too long */
> >        blank_screen();
> >
> >        unlock_all_wakelocks();         /* We want machine to sleep */
> >
> >        wait_for_key();
> >        /* (here) */
> >        lock_wakelocks("processing_key_wakelock");
> >
> > ...is that approximately correct? There's race there, right? If (here)
> > processing takes too long, or whatever, kernel will sleep the machine
> > before it even displays "do you want to unlock the screen" dialog,
> > right?
> >
> > Can you solve that in a way that works, always?
...
> There is no race in your
> example as long as your wait_for_key function just does a select or
> poll call and does not read the key events. The wakelock on the event
> queue prevents sleep.

Ugh; okay, interesting. So if rogue userspace program wants to keep
system awake forever, all it needs to do is take filedescriptor from
some input device, select() on it and not read events?
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake  lock api.)
  2009-02-08 23:14           ` Pavel Machek
@ 2009-02-08 23:35             ` Arve Hjønnevåg
  2009-02-10 11:15               ` Pavel Machek
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-08 23:35 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sun, Feb 8, 2009 at 3:14 PM, Pavel Machek <pavel@ucw.cz> wrote:
>> What prevents the system from suspending while you run make in your
>> existing system?
>
> My existing system does not autosleep.

Does it not support any kind of autosleep, or did you not enable it.
If you enable autosleep after some number of minutes of inactivity,
does the the running make job keep the system on? The systems I have
seen (not Linux) will go to sleep while make is still running.

> My experimental sleepy linux will autosleep if it knows there are no
> runnable userspace jobs, and if nearest timer to fire is far enough in
> future.

We do this from idle. The nearest timer is never more than one second
in the future.

>
>> >        (How to do that? Give all the userland processes access to
>> >        /sys/wakelocks ?)
>>
>> That depends, do you want users to be able to keep the system on?
>
> Yes. But I also want to kill -9 to work, and want my system to sleep
> after I kill -9ed all the offending processes.
>
> ...which would suggest that wakelock should be a filedescriptor. hmm.

I'm working on this.

>> > BTW what does android do when battery goes critically low? I believe
>> > you want to suspend, ignoring wakelocks, at that point.
>>
>> I don't know for sure, but I believe it does a full shutdown.
>
> Ok, but suspend would be more elgant (faster, does not loose user
> context). Take it as an example where mixing auto-sleep and forced
> sleep makes sense.

I think a high priority sleep (like someone suggested) make more sense
than a forced sleep for this situation. The wakelock code could deal
with this as another wakelock type, and ignore normal wakelocks when a
high priority sleep is requested. We cannot necessarily ignore all
wakelocks since some may be used to manage the battery and charger.

> Ugh; okay, interesting. So if rogue userspace program wants to keep
> system awake forever, all it needs to do is take filedescriptor from
> some input device, select() on it and not read events?

Yes, but input devices should not be accessible to any process.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-08 14:04                 ` Brian Swetland
  2009-02-08 21:06                   ` Pavel Machek
@ 2009-02-08 23:40                   ` Rafael J. Wysocki
  2009-02-08 23:58                     ` Arve Hjønnevåg
  2009-02-12 11:16                   ` Matthew Garrett
  2 siblings, 1 reply; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-08 23:40 UTC (permalink / raw)
  To: Brian Swetland; +Cc: ncunningham, u.luckas, linux-pm

On Sunday 08 February 2009, Brian Swetland wrote:
> ["Rafael J. Wysocki" <rjw@sisk.pl>]
> > 
> > Just to make things crystal clear, in fact I don't like any patches in this
> > series.
> > 
> > The wakelocks seem to be overdesigned to me and the "early suspend" thing
> > doesn't really fit our suspend-resume framework, especially after the changes
> > made recently to the PCI PM code (and the changes that are going to be made
> > to it shortly).
> 
> Out of curiosity, do these changes provide a model where the system can
> be in suspend 99+% of the time, waking up for specific events
> (voice/data telephony, user interaction, etc), and rapidly returning to
> suspend when the processing required is complete?

The changes I was referring to above were rather related to the "normal"
suspend (ie. the one happening as a result of writing "mem" into
/sys/power/state).  Namely, we believe that for some devices it is not
necessary or even desirable to allow the driver to perform all of the power
management operations by itself.  For example, we are going to make the PCI
PM core (which in fact is the PCI bus type driver) handle the saving and
restoration of PCI devices' configuration registers as well as putting the
devices into low power states and back into the full power state.  We can do
that, because in the "normal" suspend code path the suspend routines of a
driver are executed by the appropriate bus type's suspend routines and not
directly by the PM core.  The "early suspend" mechanism seems to go round this
by calling directly into device drivers.

Also, please observe that if there is a mechanism allowing us to put individual
devices, or entire subsystems (such as a bus with devices attached to it), into
low power states at run time, without placing the entire system in a sleep
state, and put them back into the full power state as needed, we won't need
anything like the "early suspend" introduced by this series of patches.

In fact, there is an ongoing effort to design such a mechanism and the USB
autosuspend may be considered as a part of it.  I'm currently working on doing
something similar for PCI devices.  I have some prototype patches and I can
post them if you'd like to look at them, although they really are work in
progress right now.

> That's the larger goal that the wakelock design seeks to accomplish, which
> is working pretty well for us in shipping mobile devices.
>
> Being in suspend, where periodic user and kernel timers aren't running,
> and random userspace threads aren't possibly spinning, rather than just 
> being in idle in the lowest power possible state, represent a pretty 
> significant power savings.

I generally agree, but I don't think that the approach presented by this series
of patches is one I'd like to implement.

> None of the hardware we're working with has a PCI bus, or ACPI, or much
> of any traditional desktop/server pc features, which may account for
> some of the difference in outlook and approach here.

Yes, certainly.  That's why the "early suspend" approach as proposed here does
not look practical to us.

As far as the wakelocks are concerned, the goal they are designed to achieve is
quite simple: you want to prevent suspend from happening in certain situations.
In principle, one flag is sufficient for that.  Still, there are many code
paths that might set and unset this flag and it would have been bad if the flag
had been set by one code path and then immediately unset by another one.
To prevent this from happening one can use a reference count with the rule that
suspend can only happen if it is equal to zero.

However, you want the user land to be able to prevent suspend from happening.
Now, there are couple of questions that need to be answered.  Namely, do you
want any user space processes to be able to block suspend and if so, then
why?  If not, then which processes should be able to do that?  How many of
such processes are going to be?  The solution of choice may well depend on the
answers here, but I don't see why the wakelocks as proposed are necessary for
that in any case.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-08 21:06                   ` Pavel Machek
@ 2009-02-08 23:41                     ` Rafael J. Wysocki
  2009-02-09  1:58                       ` Uli Luckas
  0 siblings, 1 reply; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-08 23:41 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, Brian Swetland, linux-pm

On Sunday 08 February 2009, Pavel Machek wrote:
> Hi!
> 
> 
> > Being in suspend, where periodic user and kernel timers aren't running,
> > and random userspace threads aren't possibly spinning, rather than just 
> > being in idle in the lowest power possible state, represent a pretty 
> > significant power savings.
> 
> If kernel timers fire too often, fix them. If user land spins, fix it,
> or SIGSTOP.
> 
> And yes, autosleep is useful. That's why I done those "sleepy linux"
> patches.

I agree, it is.  Still, I don't think the wakelocks in the proposed form are
the right way to implement it.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-10 14:18                                 ` Rafael J. Wysocki
@ 2009-02-08 23:41                                   ` Pavel Machek
  0 siblings, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-08 23:41 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: ncunningham, u.luckas, swetland, linux-pm


> > > No, we are talking of allocating kernel memory on behalf of user space
> > > processes with no apparent limitations.
> > 
> > Ok, I see now. Yes, letting each process allocated unlimited number of
> > wakelocks is indeed bad.
> > 
> > (But the names for in-kernel users should be ok, right?)
> 
> Yes, in principle, but what exactly the benefit would be?
> 
> In the kernel we can use rwlock for blocking suspend, for example,
> that will be taken for reading by the code paths wanting to prevent suspend
> from happening and for writing by the suspend code.
> 
> > "Wakelock is a filedescriptor" would solve that...
> 
> Sort of.
> 
> Still, I don't think there's much point in having more than one "wakelock"
> per process.
> 
> Moreover, I _guess_ it would be sufficient to have only one such thing for
> the entire user space and single daemon and a (user land) library to manage it.

...which is what android userland actually does...

OTOH they also veto suspend if any events are unprocessed on input
device queues... so tying it to filedescriptor would make some sense.

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-08 21:04                 ` Pavel Machek
  2009-02-08 21:40                   ` Alan Stern
@ 2009-02-08 23:44                   ` Rafael J. Wysocki
  1 sibling, 0 replies; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-08 23:44 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sunday 08 February 2009, Pavel Machek wrote:
> Hi!
> 
> > > > This is completely wrong, IMO.
> > > > 
> > > > Removing an interface that has existed forever just because it happens to
> > > > be incompatible with your new shiny feature is not acceptable to me.
> > > 
> > > Agreed. AFAICS this patch can be just dropped, or maybe kept specially
> > > for android if those few bytes matter to them.
> > 
> > Just to make things crystal clear, in fact I don't like any patches in this
> > series.
> > 
> > The wakelocks seem to be overdesigned to me and the "early suspend" thing
> 
> Well, it is true that wakelocks could be single atomic_t ... but they
> would make them undebuggable. Ok, wakelock interface sucks. But I
> believe something like that is neccessary.
> 
> (In fact, I invented something similar for sleepy linux patches).

Something like this, yes.

Perhaps it's a good occasion to discuss that and reach an agreement on how to
implement it.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-08 21:40                   ` Alan Stern
  2009-02-08 23:00                     ` Arve Hjønnevåg
@ 2009-02-08 23:44                     ` Rafael J. Wysocki
  1 sibling, 0 replies; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-08 23:44 UTC (permalink / raw)
  To: Alan Stern; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sunday 08 February 2009, Alan Stern wrote:
> On Sun, 8 Feb 2009, Pavel Machek wrote:
> 
> > Well, it is true that wakelocks could be single atomic_t ... but they
> > would make them undebuggable. Ok, wakelock interface sucks. But I
> > believe something like that is neccessary.
> 
> krefs don't have name strings for keeping track of who has been 
> incrementing or decrementing their counters.  And it's true that krefs 
> are nearly undebuggable.  But somehow we've managed to struggle along 
> without adding names to krefs.  Why should wakelocks be any different?

Yeah, I don't really see why.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-08 23:40                   ` Rafael J. Wysocki
@ 2009-02-08 23:58                     ` Arve Hjønnevåg
  2009-02-09  0:26                       ` Rafael J. Wysocki
                                         ` (2 more replies)
  0 siblings, 3 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-08 23:58 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: ncunningham, u.luckas, Brian Swetland, linux-pm

On Sun, Feb 8, 2009 at 3:40 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> On Sunday 08 February 2009, Brian Swetland wrote:
>> Out of curiosity, do these changes provide a model where the system can
>> be in suspend 99+% of the time, waking up for specific events
>> (voice/data telephony, user interaction, etc), and rapidly returning to
>> suspend when the processing required is complete?
>
> The changes I was referring to above were rather related to the "normal"
> suspend (ie. the one happening as a result of writing "mem" into
> /sys/power/state).  Namely, we believe that for some devices it is not
> necessary or even desirable to allow the driver to perform all of the power
> management operations by itself.  For example, we are going to make the PCI
> PM core (which in fact is the PCI bus type driver) handle the saving and
> restoration of PCI devices' configuration registers as well as putting the
> devices into low power states and back into the full power state.  We can do
> that, because in the "normal" suspend code path the suspend routines of a
> driver are executed by the appropriate bus type's suspend routines and not
> directly by the PM core.  The "early suspend" mechanism seems to go round this
> by calling directly into device drivers.

How do you handle devices that should be in a low power mode when
closed, and a high(er) power mode when open. While adding
early-suspend hooks to a driver may be ugly, it does not need any more
support than open and close does.

> Also, please observe that if there is a mechanism allowing us to put individual
> devices, or entire subsystems (such as a bus with devices attached to it), into
> low power states at run time, without placing the entire system in a sleep
> state, and put them back into the full power state as needed, we won't need
> anything like the "early suspend" introduced by this series of patches.

While early-suspend is not needed, it is still convenient on an
embedded device where some drivers are clearly only used when the
screen is on.

> As far as the wakelocks are concerned, the goal they are designed to achieve is
> quite simple: you want to prevent suspend from happening in certain situations.
> In principle, one flag is sufficient for that.  Still, there are many code
> paths that might set and unset this flag and it would have been bad if the flag
> had been set by one code path and then immediately unset by another one.
> To prevent this from happening one can use a reference count with the rule that
> suspend can only happen if it is equal to zero.

We also want accountability.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 02/13] PM: Add early suspend api.
  2009-02-07 23:34       ` Arve Hjønnevåg
  2009-02-08 20:59         ` Pavel Machek
@ 2009-02-08 23:59         ` Rafael J. Wysocki
  1 sibling, 0 replies; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-08 23:59 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sunday 08 February 2009, Arve Hjønnevåg wrote:
> On Sat, Feb 7, 2009 at 12:53 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> >> +The early-suspend api allows drivers to get notified when user-space writes to
> >> +/sys/power/request_state to indicate that the user visible sleep state should
> >> +change. A level controls what order the handlers are called in. Suspend
> >> +handlers are called in low to high level order, resume handlers are called in
> >> +the opposite order.
> >
> > I don't really understand this description, sorry.
> >
> > In particular, what values can be written to /sys/power/request_state, what
> > their meaning is and what's supposed to happen if someone writes one of these
> > values to this file?
> 
> Is it clearer if I change it to:
> 
> The early-suspend api allows drivers to get notified when user-space writes a
> sleep state, e.g. "mem", or "on" to /sys/power/request_state to indicate that
> the user visible sleep state should change. ...

So, how is it different from the "normal" suspend?  Do you want that to happen
before tasks are frozen?

> >
> >> +
> >> +Four levels are defined:
> >> +EARLY_SUSPEND_LEVEL_BLANK_SCREEN:
> >> +  On suspend the screen should be turned off but the framebuffer must still be
> >> +  accessible. On resume the screen can be turned back on.
> >
> > What exactly is the meaning of "suspend" here?
> 
> early-suspend.

OK

How exactly are these levels going to be used?

> >> +EARLY_SUSPEND_LEVEL_STOP_DRAWING:
> >> +  On suspend this level notifies user-space that it should stop accessing the
> >> +  framebuffer and it waits for it to complete. On resume it notifies user-space
> >> +  that it should resume screen access.
> >> +  Two methods are provided, console switch or a sysfs interface.
> >
> > How exactly is the notification supposed to happen?
> 
> Console switch or a blocking sysfs read.

Let's choose the console switch for example.  What would you like to happen
during early suspend on the EARLY_SUSPEND_LEVEL_STOP_DRAWING level?

> >> +EARLY_SUSPEND_LEVEL_DISABLE_FB:
> >> +  Turn off the framebuffer on suspend and back on on resume.
> >> +
> >> +EARLY_SUSPEND_LEVEL_STOP_INPUT:
> >> +  On suspend turn off input devices that are not capable of wakeup or where
> >> +  wakeup is disabled. On resume turn the same devices back on.
> >
> > This always happens during suspend-resume.  How is this different from the
> > usual suspend-resume behaviour?
> 
> It happens when user-space changes the state, before wakelocks are released.

Can you give an example, please?

> >> +struct early_suspend {
> >> +#ifdef CONFIG_HAS_EARLYSUSPEND
> >> +     struct list_head link;
> >> +     int level;
> >> +     void (*suspend)(struct early_suspend *h);
> >> +     void (*resume)(struct early_suspend *h);
> >> +#endif
> >> +};
> >
> > Does this mean addional suspend-resume callbacks for device drivers?
> 
> Yes.
> 
> > If so, how are they different from the "standard" suspend-resume callbacks?
> 
> They are called at a different time.

My question was about the functionality.  Are they supposed to be
_functionally_ different from the "standard" callbacks?

> > Also, what about bus types that carry out some suspend-resume operations
> > for their devices, like PCI?  Your early callbacks don't seem to take the
> > bus type part into account.
> 
> No, the driver will have to take care of this. It has to do the same
> work as it would do if it got and ioctl command to enter a low power
> state.

Many drivers have no such ioctls.  Moreover, during "normal" suspend the
drivers' ->suspend() callbacks are not called directly by the PM core, but they
are called via the appropriate bus type driver's ->suspend() callback, so the
bus type driver may perform additional operations before or after calling the
driver's callback.  The PCI bus type driver actually does it.

> > My understanding of the 'early suspend' idea is that it is a mechanism allowing
> > us to place some devices selectively into low power states before the actual
> > suspend happens.  However, this is exactly the same as runtime power
> > management on demand, with an interface allowing user space to put devices into
> > low power states.
> 
> The main point is to have a single entrypoint from user-space. We do
> not have a list of devices to suspend in user-space.

We don't need such a list.  The devices may be suspended automatically by the
kernel after a period of (device) inactivity, for example.

> > Now, in my opinion, runtime power management should be implemented on the
> > bus type level, since bus types differ from each other by power management
> > requirements, mechanisms that can be used and hardware interfaces.
> >
> > I have some prototype patches for PCI runtime PM in the works.  I didn't
> > intend to post them just yet, since I'm considering them as work in progress.
> > Still, I can do that if you think it would be useful.
> 
> We don't have a PCI bus, but a generic mechanism to put individual
> devices to sleep, from within the kernel or from user-space, would be
> useful.

The mechanism may not be 100% generic, because for different buses and
platforms there are different _hardware_ mechanisms for putting devices into
low power/full power states.  For example, PCI devices can generally be in
one of 4 different power states, while there are only 2 power states available
to USB devices.  Also, on PCI you can put an entire BUS segment into a low
power state, etc.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-08 21:21           ` Pavel Machek
@ 2009-02-09  0:03             ` Rafael J. Wysocki
  0 siblings, 0 replies; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-09  0:03 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sunday 08 February 2009, Pavel Machek wrote:
> Hi!
> 
> > >> > If my understanding is correct, a wakelock is a mechanism that, if held, will
> > >> > prevent the system from (automatically) entering a sleep state, but why do we
> > >> > need a number of such wakelocks instead of just one reference counter with the
> > >> > rule that (automatic) suspend can only happen if the counter is zero?
> > >>
> > >> Using wakelocks instead of a global reference count ensures that your
> > >> request cannot be cleared by someone else.
> > >
> > > Decreasing the refcount without increasing it would have been a bug, IMO.
> > 
> > Yes, but if all you have is a global reference count, you can't tell
> > where the bug is.
> ...
> > >> and detailed stats.
> > >
> > > Well, I'm not sure how this is useful in the long run.
> > 
> > You may want to know which app drained your battery.
> 
> _If_ we want to allow userspace to hold wakelocks (better name could
> be awakelock or nosleeplock?) then some way of displaying them is
> required.

BTW, I don't like the name "wakelocks" at all.  They are not locks in the
traditional sense, they are just flags preventing something (suspend) from
happening.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-08  0:20         ` Arve Hjønnevåg
  2009-02-08 21:21           ` Pavel Machek
@ 2009-02-09  0:15           ` Rafael J. Wysocki
  2009-02-09  2:03             ` Arve Hjønnevåg
  1 sibling, 1 reply; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-09  0:15 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sunday 08 February 2009, Arve Hjønnevåg wrote:
> On Sat, Feb 7, 2009 at 3:25 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > On Saturday 07 February 2009, Arve Hjønnevåg wrote:
> >> On Sat, Feb 7, 2009 at 10:56 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> >> > If my understanding is correct, a wakelock is a mechanism that, if held, will
> >> > prevent the system from (automatically) entering a sleep state, but why do we
> >> > need a number of such wakelocks instead of just one reference counter with the
> >> > rule that (automatic) suspend can only happen if the counter is zero?
> >>
> >> Using wakelocks instead of a global reference count ensures that your
> >> request cannot be cleared by someone else.
> >
> > Decreasing the refcount without increasing it would have been a bug, IMO.
> 
> Yes, but if all you have is a global reference count, you can't tell
> where the bug is.

Still, in the kernel we use reference counts all over the place.

> >> It means that you can, without knowing the current state of the lock, safely
> >> call wake_lock when you know that you need the wakelock, and
> >> wake_unlock when you are done.
> >
> > You can do the same with a reference counter IMO.
> 
> Not without some per lock state.

What prevents me from increasing the reference counter when necessary and
decreasing it when I'm done, actually?

> >> It allows wakelocks with timeouts
> >
> > OK
> >
> > What for?
> 
> So we do not have to change everything at once, and so we can allow
> code that we do not really trust a chance to run.

Well, are you sure this is the best way of achieving this goal?

> >> and detailed stats.
> >
> > Well, I'm not sure how this is useful in the long run.
> 
> You may want to know which app drained your battery.
> 
> >> > Then, code paths wanting to prevent the suspend from happening would only need
> >> > to increase the counter and it shouldn't be difficult to provide a user space
> >> > interface for that.
> >>
> >> No, but you would also need to provide way to decrement it, which
> >> would allow user-space to override a request to stay awake in the
> >> kernel or from another client.
> >
> > OK, that's a good reason.
> >
> > However, it might be better to use a refcount along with some mechanism
> > allowing user space processes to increase it only once before decreasing.
> > That would require a per-task flag, but I think you can reuse one of the
> > freezer flags for that (the freezer is not going to run as long as a wakelock
> > is held, right?).
> 
> How would this be better?

Simpler code, less overhead.  But I'm not insisting, just showing you another
possible approach.

> >> >> +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.
> >> >
> >> > And what's this call needed for?
> >
> > Please don't remove the context.  This makes reading your reply difficult.
> 
>  +It can also call wake_lock_timeout to release the wakelock after a delay:
>  +     wake_lock_timeout(&state->wakelock, HZ);
>  +
> 
> >
> >> It is needed to give code that do not use wakelocks a chance to run.
> >> For instance we have not added wakelocks to the network stack. We also
> >> use it in some places when passing data to untrusted userspace code.
> >
> > Do you mean to take a wakelock with a timeout in one code path so that some
> > other code path can run knowing that suspend will not happen?
> >
> > If this is correct, I don't like it, because it's inherently unreliable (you
> > really never know how long it will take the other code path to run, so you
> > can't choose the timeout 100% accurately).
> 
> I agree, but without wakelock support you have two options. Do not
> user suspend at all, or use a global timeout that you reset everywhere
> we lock a wakelock. By using wakelocks with timeouts we can at least
> make some events 100% reliable.

I'm not convinced.

Sorry to say that, but IMO the "wakelock with timeout" mechanism looks more
like a (poor) workaround than a solution of the problem.  Surely, I woulnd't
have tried to introduce anything similar into the kernel.

> >
> > I really would use a refcount and make sure it's increased (and obviously
> > decreased) by _every_ code path that needs to prevent suspend from happening,
> > including networking and so on.
> >
> >> > Is there a mechanism allowing us to see what wakelocks have been created by
> >> > the user land?  Something like this would be useful for debugging.
> >>
> >> /proc/wakelocks shows all wakelocks. It does not currently indicate if
> >> a wakelock is from userspace, but if you are looking for a specific
> >> lock it is easy to find. I can add a prefix to the name of all user
> >> space wakelocks of you want.
> >
> > Well, actually, do the wakelocks have to have the names?
> 
> If you want to debug the system or provide stats, yes.

Care to elaborate?

> >> >> +/* 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);
> >> >
> >> > What's the purpose of this function?
> >>
> >> It is used by our alarm driver to abort suspend.
> >
> > In what way, exactly?
> 
> The alarm driver sets an rtc alarm on suspend. After grabbing its
> state lock it, checks if the wakelock is active. Since the wakelock
> implementation now prevents suspend in a suspend_late hook when
> wakelocks are held, this may not be strictly necessary anymore, but
> prevents the alarm driver from having to deal with the state of being
> suspended while an alarm is pending.

OK, thanks.

> >> >> +/* 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);
> >
> > Well, it should be called max_wake_lock_timeout() or something like this.
> 
> I called it has_wake_lock since most of the clients do not care about
> the timeout. I think "if(has_wake_lock(" is easier to read than
> "if(max_wake_lock_timeout(".
> 
> >
> >> > And this?
> >>
> >> It is used to abort suspend. Currently when freezing processes, but it
> >> could also be called between each driver suspend call to improve
> >> wakeup latency when a wakelock is locked while suspending.
> >>
> >> We also use it (with WAKE_LOCK_IDLE) to select the idle sleep mode.
> >
> > OK, but it is not supposed to be used by device drivers, right?
> 
> No, it is only used by generic or machine specific power management code.

Your original description seemed to imply that it was a part of the API
available to device drivers.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-08 23:58                     ` Arve Hjønnevåg
@ 2009-02-09  0:26                       ` Rafael J. Wysocki
  2009-02-09  1:35                         ` Arve Hjønnevåg
  2009-02-09  3:07                       ` Alan Stern
  2009-02-09  9:09                       ` Pavel Machek
  2 siblings, 1 reply; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-09  0:26 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: ncunningham, u.luckas, Brian Swetland, linux-pm

On Monday 09 February 2009, Arve Hjønnevåg wrote:
> On Sun, Feb 8, 2009 at 3:40 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > On Sunday 08 February 2009, Brian Swetland wrote:
> >> Out of curiosity, do these changes provide a model where the system can
> >> be in suspend 99+% of the time, waking up for specific events
> >> (voice/data telephony, user interaction, etc), and rapidly returning to
> >> suspend when the processing required is complete?
> >
> > The changes I was referring to above were rather related to the "normal"
> > suspend (ie. the one happening as a result of writing "mem" into
> > /sys/power/state).  Namely, we believe that for some devices it is not
> > necessary or even desirable to allow the driver to perform all of the power
> > management operations by itself.  For example, we are going to make the PCI
> > PM core (which in fact is the PCI bus type driver) handle the saving and
> > restoration of PCI devices' configuration registers as well as putting the
> > devices into low power states and back into the full power state.  We can do
> > that, because in the "normal" suspend code path the suspend routines of a
> > driver are executed by the appropriate bus type's suspend routines and not
> > directly by the PM core.  The "early suspend" mechanism seems to go round this
> > by calling directly into device drivers.
> 
> How do you handle devices that should be in a low power mode when
> closed, and a high(er) power mode when open. While adding
> early-suspend hooks to a driver may be ugly, it does not need any more
> support than open and close does.

I don't really see how the early-suspend helps here.  Can you please explain?

> > Also, please observe that if there is a mechanism allowing us to put individual
> > devices, or entire subsystems (such as a bus with devices attached to it), into
> > low power states at run time, without placing the entire system in a sleep
> > state, and put them back into the full power state as needed, we won't need
> > anything like the "early suspend" introduced by this series of patches.
> 
> While early-suspend is not needed, it is still convenient on an
> embedded device where some drivers are clearly only used when the
> screen is on.

Ah, that's interesting.  So in fact you want some devices to go into low power
states as soon as the screen is off and that's why you fint the early-suspend
useful.  Is this correct?

> > As far as the wakelocks are concerned, the goal they are designed to achieve is
> > quite simple: you want to prevent suspend from happening in certain situations.
> > In principle, one flag is sufficient for that.  Still, there are many code
> > paths that might set and unset this flag and it would have been bad if the flag
> > had been set by one code path and then immediately unset by another one.
> > To prevent this from happening one can use a reference count with the rule that
> > suspend can only happen if it is equal to zero.
> 
> We also want accountability.

You can still have it, to some extent, by implementing the routines for getting
and releasing the reference appropriately.

Still, I'm very much interested in your reply to the last paragraph of my
message, the one that you removed.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-08 23:03                       ` Pavel Machek
@ 2009-02-09  0:31                         ` Rafael J. Wysocki
  2009-02-09  2:11                           ` Uli Luckas
  2009-02-09  9:01                           ` Pavel Machek
  0 siblings, 2 replies; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-09  0:31 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Monday 09 February 2009, Pavel Machek wrote:
> On Sun 2009-02-08 15:00:38, Arve Hj?nnev?g wrote:
> > On Sun, Feb 8, 2009 at 1:40 PM, Alan Stern <stern@rowland.harvard.edu> wrote:
> > > On Sun, 8 Feb 2009, Pavel Machek wrote:
> > >
> > >> Well, it is true that wakelocks could be single atomic_t ... but they
> > >> would make them undebuggable. Ok, wakelock interface sucks. But I
> > >> believe something like that is neccessary.
> > >
> > > krefs don't have name strings for keeping track of who has been
> > > incrementing or decrementing their counters.  And it's true that krefs
> > > are nearly undebuggable.  But somehow we've managed to struggle along
> > > without adding names to krefs.  Why should wakelocks be any different?
> > 
> > It sounds like you suggesting that we add another nearly undebuggable interface.
> > 
> > Using only a single atomic_t would not allow us to use a wakelock a
> > switch, or to specify a timeout. You could replace the list in the
> > implementation with a single atomic_t by adding more state to each
> > wakelock, but I like my current solution better.
> 
> For the record, I agree here. And... if struct wakelock contains char
> * or not is a very small detail.

It really isn't, because it means allocating (kernel) memory for each wakelock,
to store the name.

> If wakelocks can be locked from userspace is _not_ a detail; and if
> they can we do need the names.

Do we?  What about one lock per process and using process names?
Or better process IDs or even thread IDs?

And why exactly do we want _every_ user space process to be able to prevent
suspend from happening?

Moreover, why do we want user space processes to be able to take multiple
wakelocks?  What's the purpose of having more than one wakelock per process?

Is there a limit on the number of wakelocks a user space process can create
and if not, then why?

Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-09  0:26                       ` Rafael J. Wysocki
@ 2009-02-09  1:35                         ` Arve Hjønnevåg
  2009-02-09  1:53                           ` Brian Swetland
  2009-02-09  9:15                           ` Pavel Machek
  0 siblings, 2 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-09  1:35 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: ncunningham, u.luckas, Brian Swetland, linux-pm

On Sun, Feb 8, 2009 at 4:26 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> On Monday 09 February 2009, Arve Hjønnevåg wrote:
>> On Sun, Feb 8, 2009 at 3:40 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
>> > On Sunday 08 February 2009, Brian Swetland wrote:
>> >> Out of curiosity, do these changes provide a model where the system can
>> >> be in suspend 99+% of the time, waking up for specific events
>> >> (voice/data telephony, user interaction, etc), and rapidly returning to
>> >> suspend when the processing required is complete?
>> >
>> > The changes I was referring to above were rather related to the "normal"
>> > suspend (ie. the one happening as a result of writing "mem" into
>> > /sys/power/state).  Namely, we believe that for some devices it is not
>> > necessary or even desirable to allow the driver to perform all of the power
>> > management operations by itself.  For example, we are going to make the PCI
>> > PM core (which in fact is the PCI bus type driver) handle the saving and
>> > restoration of PCI devices' configuration registers as well as putting the
>> > devices into low power states and back into the full power state.  We can do
>> > that, because in the "normal" suspend code path the suspend routines of a
>> > driver are executed by the appropriate bus type's suspend routines and not
>> > directly by the PM core.  The "early suspend" mechanism seems to go round this
>> > by calling directly into device drivers.
>>
>> How do you handle devices that should be in a low power mode when
>> closed, and a high(er) power mode when open. While adding
>> early-suspend hooks to a driver may be ugly, it does not need any more
>> support than open and close does.
>
> I don't really see how the early-suspend helps here.  Can you please explain?

It does not. I was asking if your bus framework allows a driver to
power down a device when it is closed. If it does, an early suspend
hook could use the same api.

>
>> > Also, please observe that if there is a mechanism allowing us to put individual
>> > devices, or entire subsystems (such as a bus with devices attached to it), into
>> > low power states at run time, without placing the entire system in a sleep
>> > state, and put them back into the full power state as needed, we won't need
>> > anything like the "early suspend" introduced by this series of patches.
>>
>> While early-suspend is not needed, it is still convenient on an
>> embedded device where some drivers are clearly only used when the
>> screen is on.
>
> Ah, that's interesting.  So in fact you want some devices to go into low power
> states as soon as the screen is off and that's why you fint the early-suspend
> useful.  Is this correct?

Yes. We turn off the touchscreen and trackball when the screen turns
off since both these devices use additional power when enabled.
Neither of these devices can be turned off (after a timeout) while the
screen is on.

> Still, I'm very much interested in your reply to the last paragraph of my
> message, the one that you removed.

Yes we need access to wakelocks from user space. We also allow third
party apps to use wakelocks if they request the right permission. This
could include a music player keeping the device on while playing a
song, or an pop email client using an alarm to download email every
hour.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock api. )
  2009-02-08 22:17       ` non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock api.) Pavel Machek
  2009-02-08 22:40         ` Arve Hjønnevåg
@ 2009-02-09  1:49         ` Uli Luckas
  2009-02-10 11:17           ` non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock?api.) Pavel Machek
  1 sibling, 1 reply; 251+ messages in thread
From: Uli Luckas @ 2009-02-09  1:49 UTC (permalink / raw)
  To: linux-pm; +Cc: swetland, ncunningham

On Sunday 08 February 2009, Pavel Machek wrote:
> Hi!
>
> Ok, I think that this wakelock stuff is in "can't be used properly"
> area on Rusty's scale of nasty interfaces.
>
> So... do I understand this correctly that if I want to run "make zImage"
> on Android, I'll need to modify make, gcc, .... to keep system awake?
>
> 	(How to do that? Give all the userland processes access to
> 	/sys/wakelocks ?)
>
> BTW what does android do when battery goes critically low? I believe
> you want to suspend, ignoring wakelocks, at that point.
>
> And now, you have some X-like system.
>
> 	/* We were idle for too long */
> 	blank_screen();
>
> 	unlock_all_wakelocks();		/* We want machine to sleep */
>
> 	wait_for_key();
> 	/* (here) */
> 	lock_wakelocks("processing_key_wakelock");
>
> ...is that approximately correct? There's race there, right? If (here)
> processing takes too long, or whatever, kernel will sleep the machine
> before it even displays "do you want to unlock the screen" dialog,
> right?
>
> Can you solve that in a way that works, always?
> 									Pavel

Pavel, actually Arve's whole wakelock concept is about avoiding races. Please 
go back to where he explains the keyboard example.
The idea is that the keyboard driver grabs a wake lock in it's interrupt and 
releases the lock only, after the resulting key events are read from the 
device's queue. 
This way, userspace can safely select on the key events, then grab it's own 
lock. At that time, the two locks overlap! After that, userspace reads the 
key events. This causes the keyboard driver to relaease it's wake lock. 
Userspace still holds it's wake lock thogh.
You see? The locks together with the key events have been passed to userspace 
safey. Absolutely race free. 

So your example becomes:
	/* We were idle for too long */
 	blank_screen();
	unlock_my_wakelocks();   /* We want machine to sleep if no one
                                                       else holds a wakelock*/
	wait_for_key();                 /* Select on key events */
	/* (here) */
	lock_wakelocks("processing_key_wakelock");
 	read_key_events();

We should take a look at those cases, though, where a timed wacke locks are 
needed. That is definitely unsafe.

Uli

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-09  1:35                         ` Arve Hjønnevåg
@ 2009-02-09  1:53                           ` Brian Swetland
  2009-02-09  8:58                             ` Pavel Machek
  2009-02-09  9:15                           ` Pavel Machek
  1 sibling, 1 reply; 251+ messages in thread
From: Brian Swetland @ 2009-02-09  1:53 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: ncunningham, u.luckas, linux-pm

[Arve Hjønnevåg <arve@android.com>]
> 
> > Still, I'm very much interested in your reply to the last paragraph of my
> > message, the one that you removed.
> 
> Yes we need access to wakelocks from user space. We also allow third
> party apps to use wakelocks if they request the right permission. This
> could include a music player keeping the device on while playing a
> song, or an pop email client using an alarm to download email every
> hour.

To expand on this a bit: We don't allow arbitrary apps to directly grab
wakelocks with the sys interface -- instead a system service in
userspace manages wakelock requests on behalf of apps needing them.

This allows permission enforcement (users get to know/choose which 
apps actually *can* keep the device awake in the background) and other
policy decisions to be made at the app framework level. 

Brian

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-08 23:41                     ` Rafael J. Wysocki
@ 2009-02-09  1:58                       ` Uli Luckas
  2009-02-10  0:09                         ` Rafael J. Wysocki
  0 siblings, 1 reply; 251+ messages in thread
From: Uli Luckas @ 2009-02-09  1:58 UTC (permalink / raw)
  To: linux-pm; +Cc: Brian Swetland, ncunningham

On Monday 09 February 2009, Rafael J. Wysocki wrote:
> On Sunday 08 February 2009, Pavel Machek wrote:
> > Hi!
> >
> > > Being in suspend, where periodic user and kernel timers aren't running,
> > > and random userspace threads aren't possibly spinning, rather than just
> > > being in idle in the lowest power possible state, represent a pretty
> > > significant power savings.
> >
> > If kernel timers fire too often, fix them. If user land spins, fix it,
> > or SIGSTOP.
> >
> > And yes, autosleep is useful. That's why I done those "sleepy linux"
> > patches.
>
> I agree, it is.  Still, I don't think the wakelocks in the proposed form
> are the right way to implement it.
>
What do you think is the right approach then?

Uli

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-09  0:15           ` Rafael J. Wysocki
@ 2009-02-09  2:03             ` Arve Hjønnevåg
  2009-02-11 22:23               ` Rafael J. Wysocki
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-09  2:03 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sun, Feb 8, 2009 at 4:15 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
>> >> It means that you can, without knowing the current state of the lock, safely
>> >> call wake_lock when you know that you need the wakelock, and
>> >> wake_unlock when you are done.
>> >
>> > You can do the same with a reference counter IMO.
>>
>> Not without some per lock state.
>
> What prevents me from increasing the reference counter when necessary and
> decreasing it when I'm done, actually?

Nothing prevents a driver from incrementing and decrementing a
reference count correctly, but it has to know if it already has a
reference. If you want to implement my current wake_lock api with a
global reference count, you need some per lock state to indicate if
the lock is locked or not.

>> >> It allows wakelocks with timeouts
>> >
>> > OK
>> >
>> > What for?
>>
>> So we do not have to change everything at once, and so we can allow
>> code that we do not really trust a chance to run.
>
> Well, are you sure this is the best way of achieving this goal?

No, but I have not seen any better suggestions, that solve the problem.

>> > However, it might be better to use a refcount along with some mechanism
>> > allowing user space processes to increase it only once before decreasing.
>> > That would require a per-task flag, but I think you can reuse one of the
>> > freezer flags for that (the freezer is not going to run as long as a wakelock
>> > is held, right?).
>>
>> How would this be better?
>
> Simpler code, less overhead.  But I'm not insisting, just showing you another
> possible approach.

I agree that a global reference count is less overhead, but we need
timeout support the make the system work for now. I don't see what a
per-task flag would be helpful with. Not all wakelocks are associated
with tasks.

>
>> >> >> +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.
>> >> >
>> >> > And what's this call needed for?
>> >
>> > Please don't remove the context.  This makes reading your reply difficult.
>>
>>  +It can also call wake_lock_timeout to release the wakelock after a delay:
>>  +     wake_lock_timeout(&state->wakelock, HZ);
>>  +
>>
>> >
>> >> It is needed to give code that do not use wakelocks a chance to run.
>> >> For instance we have not added wakelocks to the network stack. We also
>> >> use it in some places when passing data to untrusted userspace code.
>> >
>> > Do you mean to take a wakelock with a timeout in one code path so that some
>> > other code path can run knowing that suspend will not happen?
>> >
>> > If this is correct, I don't like it, because it's inherently unreliable (you
>> > really never know how long it will take the other code path to run, so you
>> > can't choose the timeout 100% accurately).
>>
>> I agree, but without wakelock support you have two options. Do not
>> user suspend at all, or use a global timeout that you reset everywhere
>> we lock a wakelock. By using wakelocks with timeouts we can at least
>> make some events 100% reliable.
>
> I'm not convinced.
>
> Sorry to say that, but IMO the "wakelock with timeout" mechanism looks more
> like a (poor) workaround than a solution of the problem.  Surely, I woulnd't
> have tried to introduce anything similar into the kernel.

I do not want to add wakelocks to every kernel subsystem while there
is no wakelock support in the mainline kernel. Using wakelocks with
timeouts allow us to make progress.

>> >
>> > I really would use a refcount and make sure it's increased (and obviously
>> > decreased) by _every_ code path that needs to prevent suspend from happening,
>> > including networking and so on.
>> >
>> >> > Is there a mechanism allowing us to see what wakelocks have been created by
>> >> > the user land?  Something like this would be useful for debugging.
>> >>
>> >> /proc/wakelocks shows all wakelocks. It does not currently indicate if
>> >> a wakelock is from userspace, but if you are looking for a specific
>> >> lock it is easy to find. I can add a prefix to the name of all user
>> >> space wakelocks of you want.
>> >
>> > Well, actually, do the wakelocks have to have the names?
>>
>> If you want to debug the system or provide stats, yes.
>
> Care to elaborate?

We report the name and how long each wakelock is active in
/proc/wakelocks. Without a name, those stats are not very useful. You
can also enable debug options to print a message the kernel log every
time a wakelock is locked, unlocked or used to trigger a wakeup.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-09  0:31                         ` Rafael J. Wysocki
@ 2009-02-09  2:11                           ` Uli Luckas
  2009-02-09  2:24                             ` Arve Hjønnevåg
  2009-02-09  9:01                           ` Pavel Machek
  1 sibling, 1 reply; 251+ messages in thread
From: Uli Luckas @ 2009-02-09  2:11 UTC (permalink / raw)
  To: linux-pm; +Cc: swetland, ncunningham

On Monday 09 February 2009, Rafael J. Wysocki wrote:
> On Monday 09 February 2009, Pavel Machek wrote:
> > On Sun 2009-02-08 15:00:38, Arve Hj?nnev?g wrote:
> > > On Sun, Feb 8, 2009 at 1:40 PM, Alan Stern <stern@rowland.harvard.edu> 
wrote:
> > > > On Sun, 8 Feb 2009, Pavel Machek wrote:
> > > >> Well, it is true that wakelocks could be single atomic_t ... but
> > > >> they would make them undebuggable. Ok, wakelock interface sucks. But
> > > >> I believe something like that is neccessary.
> > > >
> > > > krefs don't have name strings for keeping track of who has been
> > > > incrementing or decrementing their counters.  And it's true that
> > > > krefs are nearly undebuggable.  But somehow we've managed to struggle
> > > > along without adding names to krefs.  Why should wakelocks be any
> > > > different?
> > >
> > > It sounds like you suggesting that we add another nearly undebuggable
> > > interface.
> > >
> > > Using only a single atomic_t would not allow us to use a wakelock a
> > > switch, or to specify a timeout. You could replace the list in the
> > > implementation with a single atomic_t by adding more state to each
> > > wakelock, but I like my current solution better.
> >
> > For the record, I agree here. And... if struct wakelock contains char
> > * or not is a very small detail.
>
> It really isn't, because it means allocating (kernel) memory for each
> wakelock, to store the name.
>
> > If wakelocks can be locked from userspace is _not_ a detail; and if
> > they can we do need the names.
>
> Do we?  What about one lock per process and using process names?
> Or better process IDs or even thread IDs?
>
I like that idea. A process should be able to hold _one_ wake lock (which 
would be released if the process dies). If it turns out, that more then on 
lock is convenient for a process, a library can easily agregate these locks. 
If the last userspace wake lock is released, the library code can relase the 
processes kernel wake lock.

> And why exactly do we want _every_ user space process to be able to prevent
> suspend from happening?
>
I don't understand your question. Which porcesses do you propose can veto 
suspend? Which processes can't?

> Moreover, why do we want user space processes to be able to take multiple
> wakelocks?  What's the purpose of having more than one wakelock per
> process?
>
> Is there a limit on the number of wakelocks a user space process can create
> and if not, then why?
>
Agreed as stated above. We should agree right now to switch to one lock per 
process. Arve?

Uli

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-09  2:11                           ` Uli Luckas
@ 2009-02-09  2:24                             ` Arve Hjønnevåg
  2009-02-09  2:56                               ` Uli Luckas
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-09  2:24 UTC (permalink / raw)
  To: Uli Luckas; +Cc: swetland, linux-pm, ncunningham

On Sun, Feb 8, 2009 at 6:11 PM, Uli Luckas <u.luckas@road.de> wrote:
> On Monday 09 February 2009, Rafael J. Wysocki wrote:
>> On Monday 09 February 2009, Pavel Machek wrote:
>> > If wakelocks can be locked from userspace is _not_ a detail; and if
>> > they can we do need the names.
>>
>> Do we?  What about one lock per process and using process names?
>> Or better process IDs or even thread IDs?
>>
> I like that idea. A process should be able to hold _one_ wake lock (which
> would be released if the process dies). If it turns out, that more then on
> lock is convenient for a process, a library can easily agregate these locks.
> If the last userspace wake lock is released, the library code can relase the
> processes kernel wake lock.

>> Is there a limit on the number of wakelocks a user space process can create
>> and if not, then why?
>>
> Agreed as stated above. We should agree right now to switch to one lock per
> process. Arve?

This would work, but how would you implement it? I'm implementing an
ioctl interface that will allow automatic cleanup without modifying
the task struct.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-09  2:24                             ` Arve Hjønnevåg
@ 2009-02-09  2:56                               ` Uli Luckas
  0 siblings, 0 replies; 251+ messages in thread
From: Uli Luckas @ 2009-02-09  2:56 UTC (permalink / raw)
  To: linux-pm; +Cc: swetland, ncunningham

On Monday 09 February 2009, Arve Hjønnevåg wrote:
> On Sun, Feb 8, 2009 at 6:11 PM, Uli Luckas <u.luckas@road.de> wrote:
> > On Monday 09 February 2009, Rafael J. Wysocki wrote:
> >> On Monday 09 February 2009, Pavel Machek wrote:
> >> > If wakelocks can be locked from userspace is _not_ a detail; and if
> >> > they can we do need the names.
> >>
> >> Do we?  What about one lock per process and using process names?
> >> Or better process IDs or even thread IDs?
> >
> > I like that idea. A process should be able to hold _one_ wake lock (which
> > would be released if the process dies). If it turns out, that more then
> > on lock is convenient for a process, a library can easily agregate these
> > locks. If the last userspace wake lock is released, the library code can
> > relase the processes kernel wake lock.
> >
> >> Is there a limit on the number of wakelocks a user space process can
> >> create and if not, then why?
> >
> > Agreed as stated above. We should agree right now to switch to one lock
> > per process. Arve?
>
> This would work, but how would you implement it? I'm implementing an
> ioctl interface that will allow automatic cleanup without modifying
> the task struct.
I thought about a global ref count + a per thread flag. Now if your lock ioctl 
is first called for a specific thread it increases the global ref count and 
sets the thread's 'locked' flag. If the lock ioctl is called again for this 
thread it's a noop (with warning?). Now the first unlock ioctl decreases the 
ref count and clears the locked flag. Further unlock ioctls are noops until 
the lock is taken again. 
In another thread Rafael mentioned something about reusing freezer flags. If 
needed, he can probably give a detailed hint.
Does that sound feasible?

Uli

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-08 23:58                     ` Arve Hjønnevåg
  2009-02-09  0:26                       ` Rafael J. Wysocki
@ 2009-02-09  3:07                       ` Alan Stern
  2009-02-11 22:26                         ` Rafael J. Wysocki
  2009-02-09  9:09                       ` Pavel Machek
  2 siblings, 1 reply; 251+ messages in thread
From: Alan Stern @ 2009-02-09  3:07 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: ncunningham, u.luckas, Brian Swetland, linux-pm

On Sun, 8 Feb 2009, Arve Hjønnevåg wrote:

> How do you handle devices that should be in a low power mode when
> closed, and a high(er) power mode when open. While adding
> early-suspend hooks to a driver may be ugly, it does not need any more
> support than open and close does.

This illustrates some of the problems of differing outlooks.  In an 
embedded system, the set of devices is limited and the set of available 
power states is known beforehand.  In other settings neither of these 
is true.

Early-suspend is an example of a partially-functional system state.  
In your Android-centric approach, early-suspend is centered around the 
screen.  But other sorts of systems way well have other requirements 
and may want their partially-functional system state to be centered 
around something else.  Or they may want to have more than one 
partially-functional system state.

What we need is a mechanism capable of accomodating all these different
requirements.  Presumably the core kernel would provide the hooks but
the implementation details would be left up to platform-specific code.  
There should be a generic scheme for representing partially-functional
system states, together with a list of devices to be put in low-power
mode for each state and an indication of which low-power mode to use
(since a device can have more than one low-power mode).  Device drivers
should have an interface for going into a particular low-power state.

The extent to which all of this needs to be split between the kernel
and userspace isn't immediately clear.  Latency issues might force a
large part of it to live in the kernel.  On the other hand, if the list
of devices & modes can be pushed out to userspace, then the in-kernel
portion could end up being nothing more than a runtime-PM mechanism of
the sort we have been discussing for years.

Alan Stern

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-09  1:53                           ` Brian Swetland
@ 2009-02-09  8:58                             ` Pavel Machek
  2009-02-09 13:31                               ` Brian Swetland
  0 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-09  8:58 UTC (permalink / raw)
  To: Brian Swetland; +Cc: ncunningham, u.luckas, linux-pm

> [Arve Hj?nnev?g <arve@android.com>]
> > 
> > > Still, I'm very much interested in your reply to the last paragraph of my
> > > message, the one that you removed.
> > 
> > Yes we need access to wakelocks from user space. We also allow third
> > party apps to use wakelocks if they request the right permission. This
> > could include a music player keeping the device on while playing a
> > song, or an pop email client using an alarm to download email every
> > hour.
> 
> To expand on this a bit: We don't allow arbitrary apps to directly grab
> wakelocks with the sys interface -- instead a system service in
> userspace manages wakelock requests on behalf of apps needing them.

So in fact single wakelock for userspace would be enough for you?

Cool, that certainly makes user<->kernel interface easier.

OTOH "gcc now has to talk to system service" requirement is quite ugly.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-09  0:31                         ` Rafael J. Wysocki
  2009-02-09  2:11                           ` Uli Luckas
@ 2009-02-09  9:01                           ` Pavel Machek
  2009-02-10  0:17                             ` Rafael J. Wysocki
  1 sibling, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-09  9:01 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: ncunningham, u.luckas, swetland, linux-pm

> On Monday 09 February 2009, Pavel Machek wrote:
> > On Sun 2009-02-08 15:00:38, Arve Hj?nnev?g wrote:
> > > On Sun, Feb 8, 2009 at 1:40 PM, Alan Stern <stern@rowland.harvard.edu> wrote:
> > > > On Sun, 8 Feb 2009, Pavel Machek wrote:
> > > >
> > > >> Well, it is true that wakelocks could be single atomic_t ... but they
> > > >> would make them undebuggable. Ok, wakelock interface sucks. But I
> > > >> believe something like that is neccessary.
> > > >
> > > > krefs don't have name strings for keeping track of who has been
> > > > incrementing or decrementing their counters.  And it's true that krefs
> > > > are nearly undebuggable.  But somehow we've managed to struggle along
> > > > without adding names to krefs.  Why should wakelocks be any different?
> > > 
> > > It sounds like you suggesting that we add another nearly undebuggable interface.
> > > 
> > > Using only a single atomic_t would not allow us to use a wakelock a
> > > switch, or to specify a timeout. You could replace the list in the
> > > implementation with a single atomic_t by adding more state to each
> > > wakelock, but I like my current solution better.
> > 
> > For the record, I agree here. And... if struct wakelock contains char
> > * or not is a very small detail.
> 
> It really isn't, because it means allocating (kernel) memory for each wakelock,
> to store the name.

If it can be #ifdef DEBUG or something, I don't see a problem. And it
does not need to allocate anything, most wakelocks will be just
static. So we are talking about 10bytes per wakelock of overhead --
not too bad.

									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-08 23:11         ` Arve Hjønnevåg
@ 2009-02-09  9:06           ` Pavel Machek
  0 siblings, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-09  9:06 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, swetland, linux-pm

> On Sun, Feb 8, 2009 at 1:30 PM, Pavel Machek <pavel@ucw.cz> wrote:
> > On Thu 2009-02-05 16:28:28, Arve Hj?nnev?g wrote:
> >> On Thu, Feb 5, 2009 at 1:11 AM, Pavel Machek <pavel@ucw.cz> wrote:
> >> > On Wed 2009-02-04 18:50:14, Arve Hj??nnev??g wrote:
> >> >> +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
> >> >
> >> > idle states are very different from suspend. Mixing them does not look
> >> > like good idea... and IIRC we already have API somewhere to prevent
> >> > deep idle states. Intel did it for their wireless cards IIRC.
> >>
> >> If you are talking about the pm_qos interface, then yes there is some
> >> overlap. We did not use the pm_qos interface since it does a linear
> >> scan for a string every time you change a requirement, and it only
> >> let
> >
> > If pm_qos code is too slow for you, just fix it!
> 
> The problem is with the api. It uses strings as handles. It was easier
> for us to just add another wakelock type since the wakelock code
> already supported two types (I have since removed one).

Please use pm_qos code.

> > Or maybe you just want to prevent low idle states as long as those
> > interrupts are claimed, no new api needed?
> 
> I thnik this is a better solution, and we do this for the main
> interrupt controller. We did not do this for gpio interrupts since we
> did not have a list.

Ok, if you can do this for gpios, too, that would be ideal.


									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-08 23:58                     ` Arve Hjønnevåg
  2009-02-09  0:26                       ` Rafael J. Wysocki
  2009-02-09  3:07                       ` Alan Stern
@ 2009-02-09  9:09                       ` Pavel Machek
  2 siblings, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-09  9:09 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, Brian Swetland, linux-pm

> On Sun, Feb 8, 2009 at 3:40 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > On Sunday 08 February 2009, Brian Swetland wrote:
> >> Out of curiosity, do these changes provide a model where the system can
> >> be in suspend 99+% of the time, waking up for specific events
> >> (voice/data telephony, user interaction, etc), and rapidly returning to
> >> suspend when the processing required is complete?
> >
> > The changes I was referring to above were rather related to the "normal"
> > suspend (ie. the one happening as a result of writing "mem" into
> > /sys/power/state).  Namely, we believe that for some devices it is not
> > necessary or even desirable to allow the driver to perform all of the power
> > management operations by itself.  For example, we are going to make the PCI
> > PM core (which in fact is the PCI bus type driver) handle the saving and
> > restoration of PCI devices' configuration registers as well as putting the
> > devices into low power states and back into the full power state.  We can do
> > that, because in the "normal" suspend code path the suspend routines of a
> > driver are executed by the appropriate bus type's suspend routines and not
> > directly by the PM core.  The "early suspend" mechanism seems to go round this
> > by calling directly into device drivers.
> 
> How do you handle devices that should be in a low power mode when
> closed, and a high(er) power mode when open. While adding
> early-suspend hooks to a driver may be ugly, it does not need any more
> support than open and close does.

I put the device to low power mode when its close() is called, and I
pull it back up when open() is called....? Every well-behaved driver
should do that, even on PC.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-09  1:35                         ` Arve Hjønnevåg
  2009-02-09  1:53                           ` Brian Swetland
@ 2009-02-09  9:15                           ` Pavel Machek
  1 sibling, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-09  9:15 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, Brian Swetland, linux-pm

Hi!

> >> > Also, please observe that if there is a mechanism allowing us to put individual
> >> > devices, or entire subsystems (such as a bus with devices attached to it), into
> >> > low power states at run time, without placing the entire system in a sleep
> >> > state, and put them back into the full power state as needed, we won't need
> >> > anything like the "early suspend" introduced by this series of patches.
> >>
> >> While early-suspend is not needed, it is still convenient on an
> >> embedded device where some drivers are clearly only used when the
> >> screen is on.
> >
> > Ah, that's interesting.  So in fact you want some devices to go into low power
> > states as soon as the screen is off and that's why you fint the early-suspend
> > useful.  Is this correct?
> 
> Yes. We turn off the touchscreen and trackball when the screen turns
> off since both these devices use additional power when enabled.
> Neither of these devices can be turned off (after a timeout) while the
> screen is on.

Ok, first: It is not at all clear to me that trackball / touchscreen
is unusable with screen off. For weird cases (using android to
remotely control PC?) screen-off trackball-on makes
sense. Actually... if you are charging than maybe waking up the device
by touching the screen is a good idea? So maybe you are putting a bit
too much policy into kernel.

OTOH, as long as you do it in android-specific code, that's probably
okay.

So lets assume that trackball is unusable with screen off. Stuff is
easy, then either

1) make your useland close trackball/touchscreen devices when they
turn the screen off.

(This is actually preffered, as it keeps policy out of the kernel)

or

2) Just use notifier chain to notify trackball/touchscreen when the
screen is going off.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-09  8:58                             ` Pavel Machek
@ 2009-02-09 13:31                               ` Brian Swetland
  2009-02-10 11:19                                 ` Pavel Machek
  0 siblings, 1 reply; 251+ messages in thread
From: Brian Swetland @ 2009-02-09 13:31 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, linux-pm

[Pavel Machek <pavel@ucw.cz>]
> > [Arve Hj?nnev?g <arve@android.com>]
> > > 
> > > Yes we need access to wakelocks from user space. We also allow third
> > > party apps to use wakelocks if they request the right permission. This
> > > could include a music player keeping the device on while playing a
> > > song, or an pop email client using an alarm to download email every
> > > hour.
> > 
> > To expand on this a bit: We don't allow arbitrary apps to directly grab
> > wakelocks with the sys interface -- instead a system service in
> > userspace manages wakelock requests on behalf of apps needing them.
> 
> So in fact single wakelock for userspace would be enough for you?
> 
> Cool, that certainly makes user<->kernel interface easier.
> 
> OTOH "gcc now has to talk to system service" requirement is quite ugly.

I think we'd still want multiple entities to hold wakelocks from
userspace -- in the Android case, the daemon that handles low level
telephony state also has its own wakelock.  I was speaking more from a
permission standpoint that there may not need to be a 1:1 between
userspace entities needing to keep the system from sleeping and a
wakelock in the kernel.

Arve has a prototype of a driver interface instead of the sysfs
interface where one opens /dev/wakelock to obtain a wakelock (via fd)
which can be cleaned up automatically on app exit, etc.

I don't think you'd actually want to have plain 'ol commandline tools
like gcc and so on to be modified to be aware of wakelocks.  Instead,
I'd imagine you'd setup a general "run x while keeping the system awake"
tool, or maybe modify just the shell you're using.

Brian

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 03/13] PM: Implement wakelock api.
  2009-02-07  0:47             ` Arve Hjønnevåg
@ 2009-02-09 18:00               ` mark gross
  2009-02-10 20:24               ` Pavel Machek
  1 sibling, 0 replies; 251+ messages in thread
From: mark gross @ 2009-02-09 18:00 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: swetland, linux-pm, u.luckas, ncunningham

On Fri, Feb 06, 2009 at 04:47:59PM -0800, Arve Hjønnevåg wrote:
> On Fri, Feb 6, 2009 at 4:33 PM, mark gross <mgross@linux.intel.com> wrote:
> >> >> +#ifdef CONFIG_WAKELOCK_STAT
> >> >> +     create_proc_read_entry("wakelocks", S_IRUGO, NULL,
> >> >> +                             wakelocks_read_proc, NULL);
> >> >
> >> > Shouldn't we *not* be using /proc?  I think this should be under sysfs.
> >>
> >> It is not allowed under sysfs. Debugfs has been suggested, but we
> >> don't have debugfs mounted, and we include the wakelock stats in debug
> >> reports.
> >>
> >
> > why not under sysfs?
> 
> The rules for sysfs state that there should be one value or an array
> of values per file.
>

Have you considered creating a misc device in /dev instead?

--mgross 

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-09  1:58                       ` Uli Luckas
@ 2009-02-10  0:09                         ` Rafael J. Wysocki
  0 siblings, 0 replies; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-10  0:09 UTC (permalink / raw)
  To: Uli Luckas; +Cc: Brian Swetland, linux-pm, ncunningham

On Monday 09 February 2009, Uli Luckas wrote:
> On Monday 09 February 2009, Rafael J. Wysocki wrote:
> > On Sunday 08 February 2009, Pavel Machek wrote:
> > > Hi!
> > >
> > > > Being in suspend, where periodic user and kernel timers aren't running,
> > > > and random userspace threads aren't possibly spinning, rather than just
> > > > being in idle in the lowest power possible state, represent a pretty
> > > > significant power savings.
> > >
> > > If kernel timers fire too often, fix them. If user land spins, fix it,
> > > or SIGSTOP.
> > >
> > > And yes, autosleep is useful. That's why I done those "sleepy linux"
> > > patches.
> >
> > I agree, it is.  Still, I don't think the wakelocks in the proposed form
> > are the right way to implement it.
> >
> What do you think is the right approach then?

That depend on whether or not you want user space processes to be able to
prevent suspend from happening.

If I didn't, I'd use a reference counter.  If I did, I'd probably use a
special per-task flag or something similar.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-09  9:01                           ` Pavel Machek
@ 2009-02-10  0:17                             ` Rafael J. Wysocki
  2009-02-10  9:13                               ` Pavel Machek
  0 siblings, 1 reply; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-10  0:17 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Monday 09 February 2009, Pavel Machek wrote:
> > On Monday 09 February 2009, Pavel Machek wrote:
> > > On Sun 2009-02-08 15:00:38, Arve Hj?nnev?g wrote:
> > > > On Sun, Feb 8, 2009 at 1:40 PM, Alan Stern <stern@rowland.harvard.edu> wrote:
> > > > > On Sun, 8 Feb 2009, Pavel Machek wrote:
> > > > >
> > > > >> Well, it is true that wakelocks could be single atomic_t ... but they
> > > > >> would make them undebuggable. Ok, wakelock interface sucks. But I
> > > > >> believe something like that is neccessary.
> > > > >
> > > > > krefs don't have name strings for keeping track of who has been
> > > > > incrementing or decrementing their counters.  And it's true that krefs
> > > > > are nearly undebuggable.  But somehow we've managed to struggle along
> > > > > without adding names to krefs.  Why should wakelocks be any different?
> > > > 
> > > > It sounds like you suggesting that we add another nearly undebuggable interface.
> > > > 
> > > > Using only a single atomic_t would not allow us to use a wakelock a
> > > > switch, or to specify a timeout. You could replace the list in the
> > > > implementation with a single atomic_t by adding more state to each
> > > > wakelock, but I like my current solution better.
> > > 
> > > For the record, I agree here. And... if struct wakelock contains char
> > > * or not is a very small detail.
> > 
> > It really isn't, because it means allocating (kernel) memory for each wakelock,
> > to store the name.
> 
> If it can be #ifdef DEBUG or something, I don't see a problem. And it
> does not need to allocate anything, most wakelocks will be just
> static. So we are talking about 10bytes per wakelock of overhead --
> not too bad.

No, we are talking of allocating kernel memory on behalf of user space
processes with no apparent limitations.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-10  0:17                             ` Rafael J. Wysocki
@ 2009-02-10  9:13                               ` Pavel Machek
  2009-02-10 14:18                                 ` Rafael J. Wysocki
  0 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-10  9:13 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: ncunningham, u.luckas, swetland, linux-pm

> On Monday 09 February 2009, Pavel Machek wrote:
> > > On Monday 09 February 2009, Pavel Machek wrote:
> > > > On Sun 2009-02-08 15:00:38, Arve Hj?nnev?g wrote:
> > > > > On Sun, Feb 8, 2009 at 1:40 PM, Alan Stern <stern@rowland.harvard.edu> wrote:
> > > > > > On Sun, 8 Feb 2009, Pavel Machek wrote:
> > > > > >
> > > > > >> Well, it is true that wakelocks could be single atomic_t ... but they
> > > > > >> would make them undebuggable. Ok, wakelock interface sucks. But I
> > > > > >> believe something like that is neccessary.
> > > > > >
> > > > > > krefs don't have name strings for keeping track of who has been
> > > > > > incrementing or decrementing their counters.  And it's true that krefs
> > > > > > are nearly undebuggable.  But somehow we've managed to struggle along
> > > > > > without adding names to krefs.  Why should wakelocks be any different?
> > > > > 
> > > > > It sounds like you suggesting that we add another nearly undebuggable interface.
> > > > > 
> > > > > Using only a single atomic_t would not allow us to use a wakelock a
> > > > > switch, or to specify a timeout. You could replace the list in the
> > > > > implementation with a single atomic_t by adding more state to each
> > > > > wakelock, but I like my current solution better.
> > > > 
> > > > For the record, I agree here. And... if struct wakelock contains char
> > > > * or not is a very small detail.
> > > 
> > > It really isn't, because it means allocating (kernel) memory for each wakelock,
> > > to store the name.
> > 
> > If it can be #ifdef DEBUG or something, I don't see a problem. And it
> > does not need to allocate anything, most wakelocks will be just
> > static. So we are talking about 10bytes per wakelock of overhead --
> > not too bad.
> 
> No, we are talking of allocating kernel memory on behalf of user space
> processes with no apparent limitations.

Ok, I see now. Yes, letting each process allocated unlimited number of
wakelocks is indeed bad.

(But the names for in-kernel users should be ok, right?)

"Wakelock is a filedescriptor" would solve that...
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock api.)
  2009-02-08 23:35             ` Arve Hjønnevåg
@ 2009-02-10 11:15               ` Pavel Machek
  2009-02-11  3:12                 ` Arve Hjønnevåg
  0 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-10 11:15 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, swetland, linux-pm

> On Sun, Feb 8, 2009 at 3:14 PM, Pavel Machek <pavel@ucw.cz> wrote:
> >> What prevents the system from suspending while you run make in your
> >> existing system?
> >
> > My existing system does not autosleep.
> 
> Does it not support any kind of autosleep, or did you not enable it.
> If you enable autosleep after some number of minutes of inactivity,
> does the the running make job keep the system on? The systems I have
> seen (not Linux) will go to sleep while make is still running.

My system does not support autosleep. The systems that do it from
timer, unconditionally do it like after 30 minutes by default; while
android wants to suspend after some seconds.

> > My experimental sleepy linux will autosleep if it knows there are no
> > runnable userspace jobs, and if nearest timer to fire is far enough in
> > future.
> 
> We do this from idle. The nearest timer is never more than one second
> in the future.

Well, so you fix the timers... that is good for everyone. I got to 5
second with some effort, and could extend it some more.

> >> > BTW what does android do when battery goes critically low? I believe
> >> > you want to suspend, ignoring wakelocks, at that point.
> >>
> >> I don't know for sure, but I believe it does a full shutdown.
> >
> > Ok, but suspend would be more elgant (faster, does not loose user
> > context). Take it as an example where mixing auto-sleep and forced
> > sleep makes sense.
> 
> I think a high priority sleep (like someone suggested) make more sense
> than a forced sleep for this situation. The wakelock code could deal
> with this as another wakelock type, and ignore normal wakelocks when a
> high priority sleep is requested. We cannot necessarily ignore all
> wakelocks since some may be used to manage the battery and charger.

Now.. that's a differnce from PC. But...if you shutdown -h now, what
happens to battery and charger?

> > Ugh; okay, interesting. So if rogue userspace program wants to keep
> > system awake forever, all it needs to do is take filedescriptor from
> > some input device, select() on it and not read events?
> 
> Yes, but input devices should not be accessible to any process.

Normally, untrusted processes are welcome to use ttyX directly... I
know about X today...
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock?api.)
  2009-02-09  1:49         ` non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock api. ) Uli Luckas
@ 2009-02-10 11:17           ` Pavel Machek
  2009-02-10 12:10             ` Woodruff, Richard
  2009-02-10 12:35             ` Uli Luckas
  0 siblings, 2 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-10 11:17 UTC (permalink / raw)
  To: Uli Luckas; +Cc: swetland, linux-pm, ncunningham

> On Sunday 08 February 2009, Pavel Machek wrote:
> > Hi!
> >
> > Ok, I think that this wakelock stuff is in "can't be used properly"
> > area on Rusty's scale of nasty interfaces.
> >
> > So... do I understand this correctly that if I want to run "make zImage"
> > on Android, I'll need to modify make, gcc, .... to keep system awake?
> >
> > 	(How to do that? Give all the userland processes access to
> > 	/sys/wakelocks ?)
> >
> > BTW what does android do when battery goes critically low? I believe
> > you want to suspend, ignoring wakelocks, at that point.
> >
> > And now, you have some X-like system.
> >
> > 	/* We were idle for too long */
> > 	blank_screen();
> >
> > 	unlock_all_wakelocks();		/* We want machine to sleep */
> >
> > 	wait_for_key();
> > 	/* (here) */
> > 	lock_wakelocks("processing_key_wakelock");
> >
> > ...is that approximately correct? There's race there, right? If (here)
> > processing takes too long, or whatever, kernel will sleep the machine
> > before it even displays "do you want to unlock the screen" dialog,
> > right?
> >
> > Can you solve that in a way that works, always?
> > 									Pavel
> 
> Pavel, actually Arve's whole wakelock concept is about avoiding races. Please 
> go back to where he explains the keyboard example.
> The idea is that the keyboard driver grabs a wake lock in it's interrupt and 
> releases the lock only, after the resulting key events are read from the 
> device's queue. 
> This way, userspace can safely select on the key events, then grab it's own 
> lock. At that time, the two locks overlap! After that, userspace reads the 
> key events. This causes the keyboard driver to relaease it's wake lock. 
> Userspace still holds it's wake lock thogh.
> You see? The locks together with the key events have been passed to userspace 
> safey. Absolutely race free. 
> 
> So your example becomes:
> 	/* We were idle for too long */
>  	blank_screen();
> 	unlock_my_wakelocks();   /* We want machine to sleep if no one
>                                                        else holds a wakelock*/
> 	wait_for_key();                 /* Select on key events */
> 	/* (here) */
> 	lock_wakelocks("processing_key_wakelock");
>  	read_key_events();
> 
> We should take a look at those cases, though, where a timed wacke locks are 
> needed. That is definitely unsafe.

Well, I failed to see the "as long as there's event waiting on
select(), it can not sleep". I still wonder how it works down the
chain...

you expect all applications to use select?

[like... vi?]

Plus I don't like that any application select-ing on input device can
prevent system from sleeping. That's quite a unexpected sideeffect.

									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-09 13:31                               ` Brian Swetland
@ 2009-02-10 11:19                                 ` Pavel Machek
  0 siblings, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-10 11:19 UTC (permalink / raw)
  To: Brian Swetland; +Cc: ncunningham, u.luckas, linux-pm

> [Pavel Machek <pavel@ucw.cz>]
> > > [Arve Hj?nnev?g <arve@android.com>]
> > > > 
> > > > Yes we need access to wakelocks from user space. We also allow third
> > > > party apps to use wakelocks if they request the right permission. This
> > > > could include a music player keeping the device on while playing a
> > > > song, or an pop email client using an alarm to download email every
> > > > hour.
> > > 
> > > To expand on this a bit: We don't allow arbitrary apps to directly grab
> > > wakelocks with the sys interface -- instead a system service in
> > > userspace manages wakelock requests on behalf of apps needing them.
> > 
> > So in fact single wakelock for userspace would be enough for you?
> > 
> > Cool, that certainly makes user<->kernel interface easier.
> > 
> > OTOH "gcc now has to talk to system service" requirement is quite ugly.
> 
> I think we'd still want multiple entities to hold wakelocks from
> userspace -- in the Android case, the daemon that handles low level
> telephony state also has its own wakelock.  I was speaking more from a
> permission standpoint that there may not need to be a 1:1 between
> userspace entities needing to keep the system from sleeping and a
> wakelock in the kernel.
> 
> Arve has a prototype of a driver interface instead of the sysfs
> interface where one opens /dev/wakelock to obtain a wakelock (via fd)
> which can be cleaned up automatically on app exit, etc.
> 
> I don't think you'd actually want to have plain 'ol commandline tools
> like gcc and so on to be modified to be aware of wakelocks.  Instead,
> I'd imagine you'd setup a general "run x while keeping the system awake"
> tool, or maybe modify just the shell you're using.

Well, changing all the applications is ugly. Teaching user to use
"awake make" is even more so. Shell modification.. first there are
many shells, second what if command user ran just sits there? Like
another shell? ...so I don't see how that would work.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock?api.)
  2009-02-10 11:17           ` non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock?api.) Pavel Machek
@ 2009-02-10 12:10             ` Woodruff, Richard
  2009-02-10 13:14               ` Pavel Machek
  2009-02-10 12:35             ` Uli Luckas
  1 sibling, 1 reply; 251+ messages in thread
From: Woodruff, Richard @ 2009-02-10 12:10 UTC (permalink / raw)
  To: Pavel Machek; +Cc: swetland, linux-pm, Uli Luckas, ncunningham


> From: linux-pm-bounces@lists.linux-foundation.org [mailto:linux-pm-
> bounces@lists.linux-foundation.org] On Behalf Of Pavel Machek
> Sent: Tuesday, February 10, 2009 5:18 AM

> Plus I don't like that any application select-ing on input device can
> prevent system from sleeping. That's quite a unexpected sideeffect.

Not sure this is your point.  But when doing PowerTop based debug in our Linux userspace we found several applications using select() (or some variant) with a much short timeout than needed.  In effect they were polling and keeping the system alive.

In the cases it was an application in our control we converted it to something sane.

Regards,
Richard W.

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock?api.)
  2009-02-10 11:17           ` non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock?api.) Pavel Machek
  2009-02-10 12:10             ` Woodruff, Richard
@ 2009-02-10 12:35             ` Uli Luckas
  1 sibling, 0 replies; 251+ messages in thread
From: Uli Luckas @ 2009-02-10 12:35 UTC (permalink / raw)
  To: Pavel Machek; +Cc: swetland, linux-pm, ncunningham

On Tuesday, 10. February 2009, Pavel Machek wrote:
> > On Sunday 08 February 2009, Pavel Machek wrote:
> > > Hi!
> > >
> > > Ok, I think that this wakelock stuff is in "can't be used properly"
> > > area on Rusty's scale of nasty interfaces.
> > >
> > > So... do I understand this correctly that if I want to run "make
> > > zImage" on Android, I'll need to modify make, gcc, .... to keep system
> > > awake?
> > >
> > > 	(How to do that? Give all the userland processes access to
> > > 	/sys/wakelocks ?)
> > >
> > > BTW what does android do when battery goes critically low? I believe
> > > you want to suspend, ignoring wakelocks, at that point.
> > >
> > > And now, you have some X-like system.
> > >
> > > 	/* We were idle for too long */
> > > 	blank_screen();
> > >
> > > 	unlock_all_wakelocks();		/* We want machine to sleep */
> > >
> > > 	wait_for_key();
> > > 	/* (here) */
> > > 	lock_wakelocks("processing_key_wakelock");
> > >
> > > ...is that approximately correct? There's race there, right? If (here)
> > > processing takes too long, or whatever, kernel will sleep the machine
> > > before it even displays "do you want to unlock the screen" dialog,
> > > right?
> > >
> > > Can you solve that in a way that works, always?
> > > 									Pavel
> >
> > Pavel, actually Arve's whole wakelock concept is about avoiding races.
> > Please go back to where he explains the keyboard example.
> > The idea is that the keyboard driver grabs a wake lock in it's interrupt
> > and releases the lock only, after the resulting key events are read from
> > the device's queue.
> > This way, userspace can safely select on the key events, then grab it's
> > own lock. At that time, the two locks overlap! After that, userspace
> > reads the key events. This causes the keyboard driver to relaease it's
> > wake lock. Userspace still holds it's wake lock thogh.
> > You see? The locks together with the key events have been passed to
> > userspace safey. Absolutely race free.
> >
> > So your example becomes:
> > 	/* We were idle for too long */
> >  	blank_screen();
> > 	unlock_my_wakelocks();   /* We want machine to sleep if no one
> >                                                        else holds a
> > wakelock*/ wait_for_key();                 /* Select on key events */
> > 	/* (here) */
> > 	lock_wakelocks("processing_key_wakelock");
> >  	read_key_events();
> >
> > We should take a look at those cases, though, where a timed wacke locks
> > are needed. That is definitely unsafe.
>
> Well, I failed to see the "as long as there's event waiting on
> select(), it can not sleep". I still wonder how it works down the
> chain...
>
> you expect all applications to use select?
>
> [like... vi?]
>
> Plus I don't like that any application select-ing on input device can
> prevent system from sleeping. That's quite a unexpected sideeffect.
>
It's not about selecting on the input device. The select semantics are not 
changed. It's about not processing input events.
Right, if you open /dev/input/event0 and then don't read it, you can prevent 
the system from suspend. Your application said it wants to process input 
events and so the input driver keeps the system awake until all events are 
passed on.
On my system all event devices belong to root. So this behavior should be 
safe.

regards,
Uli

-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock?api.)
  2009-02-10 12:10             ` Woodruff, Richard
@ 2009-02-10 13:14               ` Pavel Machek
  2009-02-10 13:20                 ` Woodruff, Richard
  0 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-10 13:14 UTC (permalink / raw)
  To: Woodruff, Richard; +Cc: swetland, linux-pm, Uli Luckas, ncunningham

On Tue 2009-02-10 06:10:24, Woodruff, Richard wrote:
> 
> > From: linux-pm-bounces@lists.linux-foundation.org [mailto:linux-pm-
> > bounces@lists.linux-foundation.org] On Behalf Of Pavel Machek
> > Sent: Tuesday, February 10, 2009 5:18 AM
> 
> > Plus I don't like that any application select-ing on input device can
> > prevent system from sleeping. That's quite a unexpected sideeffect.
> 
> Not sure this is your point.  But when doing PowerTop based debug in our Linux userspace we found several applications using select() (or some variant) with a much short timeout than needed.  In effect they were polling and keeping the system alive.
> 
> In the cases it was an application in our control we converted it to something sane.
> 

No, that's something different.

Apparently, on android, if there's event ready on one of the input
devices, system will not go to sleep. That's quite an "interesting"
behaviour.

Heh, they could rely on it and get rid of the wakelock. Just create
strange device that disallows system sleep when you select() on it,
and allows it when you read() from it :-).
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock?api.)
  2009-02-10 13:14               ` Pavel Machek
@ 2009-02-10 13:20                 ` Woodruff, Richard
  2009-02-10 13:42                   ` Brian Swetland
  0 siblings, 1 reply; 251+ messages in thread
From: Woodruff, Richard @ 2009-02-10 13:20 UTC (permalink / raw)
  To: Pavel Machek; +Cc: swetland, linux-pm, Uli Luckas, ncunningham


> From: Pavel Machek [mailto:pavel@ucw.cz]
> Sent: Tuesday, February 10, 2009 7:15 AM

> > Not sure this is your point.  But when doing PowerTop based debug in our
> Linux userspace we found several applications using select() (or some variant)
> with a much short timeout than needed.  In effect they were polling and
> keeping the system alive.
> >
> > In the cases it was an application in our control we converted it to
> something sane.
> >
>
> No, that's something different.
>
> Apparently, on android, if there's event ready on one of the input
> devices, system will not go to sleep. That's quite an "interesting"
> behaviour.
>
> Heh, they could rely on it and get rid of the wakelock. Just create
> strange device that disallows system sleep when you select() on it,
> and allows it when you read() from it :-).

Ok, thanks. When I looked quickly a couple months back I thought they raised a user space side wake locks on input consumers.  These translated back to the kernel lock and keep the system up.

Gist was something like you don't want to sleep until user activity data was processed.  Any high latency sleep/suspend would be perceived by user.

Regards,
Richard W.

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock?api.)
  2009-02-10 13:20                 ` Woodruff, Richard
@ 2009-02-10 13:42                   ` Brian Swetland
  0 siblings, 0 replies; 251+ messages in thread
From: Brian Swetland @ 2009-02-10 13:42 UTC (permalink / raw)
  To: Woodruff, Richard; +Cc: linux-pm, Uli Luckas, ncunningham

["Woodruff, Richard" <r-woodruff2@ti.com>]
> > From: Pavel Machek [mailto:pavel@ucw.cz]
> >
> > Apparently, on android, if there's event ready on one of the input
> > devices, system will not go to sleep. That's quite an "interesting"
> > behaviour.
> >
> > Heh, they could rely on it and get rid of the wakelock. Just create
> > strange device that disallows system sleep when you select() on it,
> > and allows it when you read() from it :-).
> 
> Ok, thanks. When I looked quickly a couple months back I thought they 
> raised a user space side wake locks on input consumers.  These 
> translated back to the kernel lock and keep the system up.
> 
> Gist was something like you don't want to sleep until user activity 
> data was processed.  Any high latency sleep/suspend would be perceived 
> by user.

The intention is to make sure we hand-off "awakeness" from kernel to
userspace when the system is waking up to process an event.  Which is
why the event dispatcher in the framework select()s, grabs a wakelock if
readable (overlapping with the wakelock held when data is in the input
queue in the kernel), read()s the events (causing the kernel side to
drop its lock when the queue is empty) and dispatches them while holding 
the wakelock until things are sorted out.

Generally, arbitrary processes cannot open input devices in Android, so
this being a mechanism for abuse of keeping the system awake has not
been an issue thus far. 

Brian

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-10  9:13                               ` Pavel Machek
@ 2009-02-10 14:18                                 ` Rafael J. Wysocki
  2009-02-08 23:41                                   ` Pavel Machek
  0 siblings, 1 reply; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-10 14:18 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Tuesday 10 February 2009, Pavel Machek wrote:
> > On Monday 09 February 2009, Pavel Machek wrote:
> > > > On Monday 09 February 2009, Pavel Machek wrote:
> > > > > On Sun 2009-02-08 15:00:38, Arve Hj?nnev?g wrote:
> > > > > > On Sun, Feb 8, 2009 at 1:40 PM, Alan Stern <stern@rowland.harvard.edu> wrote:
> > > > > > > On Sun, 8 Feb 2009, Pavel Machek wrote:
> > > > > > >
> > > > > > >> Well, it is true that wakelocks could be single atomic_t ... but they
> > > > > > >> would make them undebuggable. Ok, wakelock interface sucks. But I
> > > > > > >> believe something like that is neccessary.
> > > > > > >
> > > > > > > krefs don't have name strings for keeping track of who has been
> > > > > > > incrementing or decrementing their counters.  And it's true that krefs
> > > > > > > are nearly undebuggable.  But somehow we've managed to struggle along
> > > > > > > without adding names to krefs.  Why should wakelocks be any different?
> > > > > > 
> > > > > > It sounds like you suggesting that we add another nearly undebuggable interface.
> > > > > > 
> > > > > > Using only a single atomic_t would not allow us to use a wakelock a
> > > > > > switch, or to specify a timeout. You could replace the list in the
> > > > > > implementation with a single atomic_t by adding more state to each
> > > > > > wakelock, but I like my current solution better.
> > > > > 
> > > > > For the record, I agree here. And... if struct wakelock contains char
> > > > > * or not is a very small detail.
> > > > 
> > > > It really isn't, because it means allocating (kernel) memory for each wakelock,
> > > > to store the name.
> > > 
> > > If it can be #ifdef DEBUG or something, I don't see a problem. And it
> > > does not need to allocate anything, most wakelocks will be just
> > > static. So we are talking about 10bytes per wakelock of overhead --
> > > not too bad.
> > 
> > No, we are talking of allocating kernel memory on behalf of user space
> > processes with no apparent limitations.
> 
> Ok, I see now. Yes, letting each process allocated unlimited number of
> wakelocks is indeed bad.
> 
> (But the names for in-kernel users should be ok, right?)

Yes, in principle, but what exactly the benefit would be?

In the kernel we can use rwlock for blocking suspend, for example,
that will be taken for reading by the code paths wanting to prevent suspend
from happening and for writing by the suspend code.

> "Wakelock is a filedescriptor" would solve that...

Sort of.

Still, I don't think there's much point in having more than one "wakelock"
per process.

Moreover, I _guess_ it would be sufficient to have only one such thing for
the entire user space and single daemon and a (user land) library to manage it.

Assume there is a deamon that owns the "wakelock" (I'd prefer to call it
"suspend stop valve" or something like this) and each process wanting the
"lock" to be active has to ask the deamon to hold the lock on its behalf (it
also will have to authenticate itself before the deamon etc.).

That would move the whole thing out of the kernel, I think.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 03/13] PM: Implement wakelock api.
  2009-02-07  0:47             ` Arve Hjønnevåg
  2009-02-09 18:00               ` mark gross
@ 2009-02-10 20:24               ` Pavel Machek
  1 sibling, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-10 20:24 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: swetland, linux-pm, u.luckas, ncunningham

On Fri 2009-02-06 16:47:59, Arve Hj?nnev?g wrote:
> On Fri, Feb 6, 2009 at 4:33 PM, mark gross <mgross@linux.intel.com> wrote:
> >> >> +#ifdef CONFIG_WAKELOCK_STAT
> >> >> +     create_proc_read_entry("wakelocks", S_IRUGO, NULL,
> >> >> +                             wakelocks_read_proc, NULL);
> >> >
> >> > Shouldn't we *not* be using /proc?  I think this should be under sysfs.
> >>
> >> It is not allowed under sysfs. Debugfs has been suggested, but we
> >> don't have debugfs mounted, and we include the wakelock stats in debug
> >> reports.
> >>
> >
> > why not under sysfs?
> 
> The rules for sysfs state that there should be one value or an array
> of values per file.

Yeah, so fix the wakelocks to be like that. echo "lock wakelock_name
3" > control_file is a wrong interface, anyway.

What about creating wakelocks with echo "3" > wakelock_name in special
directory?

And then you can use readdir in that directory to get your debugging
info...


-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-06  0:13     ` Arve Hjønnevåg
@ 2009-02-10 20:25       ` Pavel Machek
  2009-02-11  2:11         ` Arve Hjønnevåg
  2009-02-11  4:47         ` Brian Swetland
  0 siblings, 2 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-10 20:25 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: swetland, linux-pm, u.luckas, ncunningham

On Thu 2009-02-05 16:13:27, Arve Hj?nnev?g wrote:
> On Thu, Feb 5, 2009 at 2:51 PM, mark gross <mgross@linux.intel.com> wrote:
> >> +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.
> >
> > How much of this can be implemented using a pm-qos approach?
> 
> WAKE_LOCK_IDLE overlaps with pm-qos, if you use it to prevent latency.

Yes. So pleaase remove wake_lock_idle and use pm-qos. Feel free to
improve pm-qos if you need to.

> > wake_lock going to block until the dives its locking is in a good power
> > state?  (I'm guessing yes) Is doing this in the context of and IRQ a
> > good idea?
> 
> wake_lock never blocks.

Wakelock is really bad name: it is not a lock and it does not protect
wake. I'd say we need better name here.
-- 

(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-10 20:25       ` Pavel Machek
@ 2009-02-11  2:11         ` Arve Hjønnevåg
  2009-02-11  4:47         ` Brian Swetland
  1 sibling, 0 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-11  2:11 UTC (permalink / raw)
  To: Pavel Machek; +Cc: swetland, linux-pm, u.luckas, ncunningham

On Tue, Feb 10, 2009 at 12:25 PM, Pavel Machek <pavel@ucw.cz> wrote:
> Wakelock is really bad name: it is not a lock and it does not protect
> wake. I'd say we need better name here.

It is similar to a reader/writer lock, and it does protect the wake
state. The writer, the suspend code, blocks until all the readers
release their lock. If there are no readers after suspending all the
drivers, the wake state changes. Since the readers can only run when
in the awake state, they never block.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 03/13] PM: Implement wakelock api.
  2009-02-07 22:27       ` Rafael J. Wysocki
@ 2009-02-11  2:52         ` Arve Hjønnevåg
  0 siblings, 0 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-11  2:52 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Sat, Feb 7, 2009 at 2:27 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
>> +{
>> +     struct timespec ts;
>> +     struct timespec kt;
>> +     struct timespec tomono;
>> +     struct timespec delta;
>> +     unsigned long seq;
>> +     long timeout;
>> +
>> +     if (!(lock->flags & WAKE_LOCK_AUTO_EXPIRE))
>> +             return 0;
>> +     do {
>> +             seq = read_seqbegin(&xtime_lock);
>> +             timeout = lock->expires - jiffies;
>
> Can it overflow?

Yes, but I have not fixed this since you have to hold a wakelock for
several months to hit it. I could fix it may expiring wakelocks at
least every MAX_JIFFY_OFFSET or by moving to jiffies_64.

> Anyway, you are using struct timespec in computations, so why don't you
> store it in the lock structure?

I only use struct timespec for the stats.

>> +
>> +static int print_lock_stat(char *buf, struct wake_lock *lock)
>> +{
>> +     int lock_count = lock->stat.count;
>> +     int expire_count = lock->stat.expire_count;
>> +     ktime_t active_time = ktime_set(0, 0);
>> +     ktime_t total_time = lock->stat.total_time;
>> +     ktime_t max_time = lock->stat.max_time;
>> +     ktime_t prevent_suspend_time = lock->stat.prevent_suspend_time;
>> +     if (lock->flags & WAKE_LOCK_ACTIVE) {
>> +             ktime_t now, add_time;
>> +             int expired = get_expired_time(lock, &now);
>> +             if (!expired)
>> +                     now = ktime_get();
>> +             add_time = ktime_sub(now, lock->stat.last_time);
>> +             lock_count++;
>> +             if (!expired)
>> +                     active_time = add_time;
>> +             else
>> +                     expire_count++;
>> +             total_time = ktime_add(total_time, add_time);
>> +             if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND)
>> +                     prevent_suspend_time = ktime_add(prevent_suspend_time,
>> +                                     ktime_sub(now, last_sleep_time_update));
>> +             if (add_time.tv64 > max_time.tv64)
>> +                     max_time = add_time;
>> +     }
>> +
>> +     return sprintf(buf, "\"%s\"\t%d\t%d\t%d\t%lld\t%lld\t%lld\t%lld\t"
>> +                    "%lld\n", lock->name, lock_count, expire_count,
>> +                    lock->stat.wakeup_count, ktime_to_ns(active_time),
>> +                    ktime_to_ns(total_time),
>> +                    ktime_to_ns(prevent_suspend_time), ktime_to_ns(max_time),
>> +                    ktime_to_ns(lock->stat.last_time));
>> +}
>> +
>
> Why did you decide to put that in /proc ?

That's where most other stats are reported.

>> +static long has_wake_lock_locked(int type)
>
> I'd change the name, it suggests something different from what the function
> does.

It does what the name suggest, and more. The code that just cares if
there are lock held or not is easier to read this way.

>> +{
>> +     struct wake_lock *lock, *n;
>> +     long max_timeout = 0;
>> +
>> +     BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
>> +     list_for_each_entry_safe(lock, n, &active_wake_locks[type], link) {
>> +             if (lock->flags & WAKE_LOCK_AUTO_EXPIRE) {
>> +                     long timeout = lock->expires - jiffies;
>
> I think time_after() is for things like this.

time_after does not return the timeout, which I need here. I changed
another instance though.

>> +static void suspend(struct work_struct *work)
>> +{
>> +     int ret;
>> +     int entry_event_num;
>> +
>> +     if (has_wake_lock(WAKE_LOCK_SUSPEND)) {
>> +             if (debug_mask & DEBUG_SUSPEND)
>> +                     pr_info("suspend: abort suspend\n");
>> +             return;
>> +     }
>> +
>> +     entry_event_num = current_event_num;
>> +     sys_sync();
>
> pm_suspend() will do it, you don't need to.

Removed.

>
>> +     if (debug_mask & DEBUG_SUSPEND)
>> +             pr_info("suspend: enter suspend\n");
>
> Shouldn't that check if someone has taken a wakelock in the meantime?

It checks at the top of the function. With sys_sync gone, another
check would not be useful.

>> +     ret = pm_suspend(requested_suspend_state);


>> +static int power_suspend_late(struct platform_device *pdev, pm_message_t state)
>> +{
>> +     int ret = has_wake_lock(WAKE_LOCK_SUSPEND) ? -EAGAIN : 0;
>> +#ifdef CONFIG_WAKELOCK_STAT
>> +     wait_for_wakeup = 1;
>> +#endif
>> +     if (debug_mask & DEBUG_SUSPEND)
>> +             pr_info("power_suspend_late return %d\n", ret);
>> +     return ret;
>> +}
>> +
>> +static struct platform_driver power_driver = {
>> +     .driver.name = "power",
>> +     .suspend_late = power_suspend_late,
>> +};
>> +static struct platform_device power_device = {
>> +     .name = "power",
>> +};
>
> What's this and what's it for?

It makes sure suspend fails if a wakelock is locked while suspending.
Is there a simpler way to register a suspend_late handler?

>> +void wake_lock_init(struct wake_lock *lock, int type, const char *name)
>> +{
>> +     unsigned long irqflags = 0;
>> +
>> +     if (name)
>> +             lock->name = name;
>
> Hm.  I'd rather reserve memory for the name and copy it from the address
> provided by the caller.

I'd rather not. With the current interface, wake_lock_init can never fail.

>> +     BUG_ON(!lock->name);
>
> Isn't it a bit too drastic?  Perhaps make it return a value so that the caller
> can check if it has the lock?

I think a BUG_ON is appropriate. Calling wake_lock_init with an
invalid argument is a driver bug.

>> +static void wake_lock_internal(
>
> What  about __wake_lock() ?

OK.

>
>> +     struct wake_lock *lock, long timeout, int has_timeout)
>
> What's the point of the last argument?  Wouldn't timeout == 0 be sufficient?

No, timeout == 0 means expire immediately.

> Also, does it make sense to pass negative timeout to it?

A negative timeout is fine, as long as it does not underflow.

>
>> +{
>> +     int type;
>> +     unsigned long irqflags;
>> +     long expire_in;
>> +
>> +     spin_lock_irqsave(&list_lock, irqflags);
>> +     type = lock->flags & WAKE_LOCK_TYPE_MASK;
>> +     BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
>> +     BUG_ON(!(lock->flags & WAKE_LOCK_INITIALIZED));
>
> I don't like these BUG_ON()s.  Please do something less drastic instead.
>
>> +#ifdef CONFIG_WAKELOCK_STAT
>> +     if (type == WAKE_LOCK_SUSPEND && wait_for_wakeup) {
>> +             if (debug_mask & DEBUG_WAKEUP)
>> +                     pr_info("wakeup wake lock: %s\n", lock->name);
>> +             wait_for_wakeup = 0;
>> +             lock->stat.wakeup_count++;
>> +     }
>> +     if ((lock->flags & WAKE_LOCK_AUTO_EXPIRE) &&
>> +         (long)(lock->expires - jiffies) <= 0) {
>> +             wake_unlock_stat_locked(lock, 0);
>> +             lock->stat.last_time = ktime_get();
>> +     }
>> +#endif
>> +     if (!(lock->flags & WAKE_LOCK_ACTIVE)) {
>> +             lock->flags |= WAKE_LOCK_ACTIVE;
>> +#ifdef CONFIG_WAKELOCK_STAT
>> +             lock->stat.last_time = ktime_get();
>> +#endif
>> +     }
>> +     list_del(&lock->link);
>> +     if (has_timeout) {
>> +             if (debug_mask & DEBUG_WAKE_LOCK)
>> +                     pr_info("wake_lock: %s, type %d, timeout %ld.%03lu\n",
>> +                             lock->name, type, timeout / HZ,
>> +                             (timeout % HZ) * MSEC_PER_SEC / HZ);
>> +             lock->expires = jiffies + timeout;
>> +             lock->flags |= WAKE_LOCK_AUTO_EXPIRE;
>> +             list_add_tail(&lock->link, &active_wake_locks[type]);
>> +     } else {
>> +             if (debug_mask & DEBUG_WAKE_LOCK)
>> +                     pr_info("wake_lock: %s, type %d\n", lock->name, type);
>> +             lock->expires = LONG_MAX;
>> +             lock->flags &= ~WAKE_LOCK_AUTO_EXPIRE;
>> +             list_add(&lock->link, &active_wake_locks[type]);
>> +     }
>
> Why not to use list_add_tail() in both cases?

If you add a wakelock with no timeout, there is no reason for
has_wake_lock_locked to look at more than one wakelock.

>
>> +     if (type == WAKE_LOCK_SUSPEND) {
>> +             current_event_num++;
>> +#ifdef CONFIG_WAKELOCK_STAT
>> +             if (lock == &main_wake_lock)
>> +                     update_sleep_wait_stats_locked(1);
>> +             else if (!wake_lock_active(&main_wake_lock))
>> +                     update_sleep_wait_stats_locked(0);
>> +#endif
>> +             if (has_timeout)
>> +                     expire_in = has_wake_lock_locked(type);
>> +             else
>> +                     expire_in = -1;
>
>        expire_i = has_timeout ? has_wake_lock_locked(type) : -1;
>
> (there is something like this above too).
>
>> +             if (expire_in > 0) {
>> +                     if (debug_mask & DEBUG_EXPIRE)
>> +                             pr_info("wake_lock: %s, start expire timer, "
>> +                                     "%ld\n", lock->name, expire_in);
>> +                     mod_timer(&expire_timer, jiffies + expire_in);
>
> What exactly are you trying to achieve here?

Unlock wakelocks with timeouts when doing so can allow the system to
go to sleep.

>
>> +             } else {
>> +                     if (del_timer(&expire_timer))
>> +                             if (debug_mask & DEBUG_EXPIRE)
>> +                                     pr_info("wake_lock: %s, stop expire "
>> +                                             "timer\n", lock->name);
>> +                     if (expire_in == 0)
>> +                             queue_work(suspend_work_queue, &suspend_work);
>
> This appears to only happen if timeout = 0 is passed to this function while
> has_timeout == true.  Is it correct?

Unless you are on a system where jiffies can change while this
function is running, then yes.

>> +     ret = platform_device_register(&power_device);
>> +     if (ret) {
>> +             pr_err("wakelocks_init: platform_device_register failed\n");
>> +             goto err_platform_device_register;
>> +     }
>> +     ret = platform_driver_register(&power_driver);
>> +     if (ret) {
>> +             pr_err("wakelocks_init: platform_driver_register failed\n");
>> +             goto err_platform_driver_register;
>> +     }
>
> Is this really a platform thing?
>
> What exactly is the benefit of having the 'power_device' and 'power_driver'
> registered?.

I need both for suspend_late to be called.


> Also, I'd really prefer to see the patch without the CONFIG_WAKELOCK_STAT
> thing included, first.  It would have been much easier to read.

I moved more of the stats code to the CONFIG_WAKELOCK_STAT section
which should help.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake  lock api.)
  2009-02-10 11:15               ` Pavel Machek
@ 2009-02-11  3:12                 ` Arve Hjønnevåg
  0 siblings, 0 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-11  3:12 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Tue, Feb 10, 2009 at 3:15 AM, Pavel Machek <pavel@ucw.cz> wrote:

>> I think a high priority sleep (like someone suggested) make more sense
>> than a forced sleep for this situation. The wakelock code could deal
>> with this as another wakelock type, and ignore normal wakelocks when a
>> high priority sleep is requested. We cannot necessarily ignore all
>> wakelocks since some may be used to manage the battery and charger.
>
> Now.. that's a differnce from PC. But...if you shutdown -h now, what
> happens to battery and charger?

If shutdown -h performs a poweroff and not just halt, the system will
power off if no charger is connected, or it will reboot and stay
bootloader (with the screen off) if the charger is connected. If you
halt and stop processing events, the other core will panic and reboot
the system.


-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-10 20:25       ` Pavel Machek
  2009-02-11  2:11         ` Arve Hjønnevåg
@ 2009-02-11  4:47         ` Brian Swetland
  2009-02-11  8:40           ` Uli Luckas
                             ` (2 more replies)
  1 sibling, 3 replies; 251+ messages in thread
From: Brian Swetland @ 2009-02-11  4:47 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, linux-pm

[Pavel Machek <pavel@ucw.cz>]
> > 
> > wake_lock never blocks.
> 
> Wakelock is really bad name: it is not a lock and it does not protect
> wake. I'd say we need better name here.

I agree with you here -- I've had this discussion with Arve previously,
but have been unable to offer a compelling alternative name.  Anybody
have a good idea?

Some people use "sleep vote" for a similar mechanism (though usually
you're voting against sleep, which makes it feel backwards to me).

Brian

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-11  4:47         ` Brian Swetland
@ 2009-02-11  8:40           ` Uli Luckas
  2009-02-11 14:58           ` Alan Stern
  2009-02-12 18:47           ` mark gross
  2 siblings, 0 replies; 251+ messages in thread
From: Uli Luckas @ 2009-02-11  8:40 UTC (permalink / raw)
  To: Brian Swetland; +Cc: ncunningham, linux-pm

On Wednesday, 11. February 2009, Brian Swetland wrote:
> [Pavel Machek <pavel@ucw.cz>]
>
> > > wake_lock never blocks.
> >
> > Wakelock is really bad name: it is not a lock and it does not protect
> > wake. I'd say we need better name here.
>
> I agree with you here -- I've had this discussion with Arve previously,
> but have been unable to offer a compelling alternative name.  Anybody
> have a good idea?
>
> Some people use "sleep vote" for a similar mechanism (though usually
> you're voting against sleep, which makes it feel backwards to me).
>
Which makes it a veto.


-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-11  4:47         ` Brian Swetland
  2009-02-11  8:40           ` Uli Luckas
@ 2009-02-11 14:58           ` Alan Stern
  2009-02-11 15:45             ` Rafael J. Wysocki
  2009-02-11 21:37             ` Pavel Machek
  2009-02-12 18:47           ` mark gross
  2 siblings, 2 replies; 251+ messages in thread
From: Alan Stern @ 2009-02-11 14:58 UTC (permalink / raw)
  To: Brian Swetland; +Cc: ncunningham, u.luckas, linux-pm

On Tue, 10 Feb 2009, Brian Swetland wrote:

> [Pavel Machek <pavel@ucw.cz>]
> > > 
> > > wake_lock never blocks.
> > 
> > Wakelock is really bad name: it is not a lock and it does not protect
> > wake. I'd say we need better name here.
> 
> I agree with you here -- I've had this discussion with Arve previously,
> but have been unable to offer a compelling alternative name.  Anybody
> have a good idea?

delay_sleep or delaysleep?  block_sleep or blocksleep?  Any of the 
above with "sleep" replaced by "suspend"?

Alan Stern

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-11 14:58           ` Alan Stern
@ 2009-02-11 15:45             ` Rafael J. Wysocki
  2009-02-08 22:57               ` Pavel Machek
  2009-02-11 21:37             ` Pavel Machek
  1 sibling, 1 reply; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-11 15:45 UTC (permalink / raw)
  To: Brian Swetland; +Cc: linux-pm, u.luckas, ncunningham

On Wednesday 11 February 2009, Alan Stern wrote:
> On Tue, 10 Feb 2009, Brian Swetland wrote:
> 
> > [Pavel Machek <pavel@ucw.cz>]
> > > > 
> > > > wake_lock never blocks.
> > > 
> > > Wakelock is really bad name: it is not a lock and it does not protect
> > > wake. I'd say we need better name here.
> > 
> > I agree with you here -- I've had this discussion with Arve previously,
> > but have been unable to offer a compelling alternative name.  Anybody
> > have a good idea?

Well, even "sleep lock" would have been better.

> delay_sleep or delaysleep?  block_sleep or blocksleep?  Any of the 
> above with "sleep" replaced by "suspend"?

I also thought about "sleep stopper".  It reflects what the feature does. :-)

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-11 14:58           ` Alan Stern
  2009-02-11 15:45             ` Rafael J. Wysocki
@ 2009-02-11 21:37             ` Pavel Machek
  2009-02-11 22:05               ` Alan Stern
  2009-02-11 23:55               ` Arve Hjønnevåg
  1 sibling, 2 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-11 21:37 UTC (permalink / raw)
  To: Alan Stern; +Cc: Brian Swetland, ncunningham, u.luckas, linux-pm

On Wed 2009-02-11 09:58:23, Alan Stern wrote:
> On Tue, 10 Feb 2009, Brian Swetland wrote:
> 
> > [Pavel Machek <pavel@ucw.cz>]
> > > > 
> > > > wake_lock never blocks.
> > > 
> > > Wakelock is really bad name: it is not a lock and it does not protect
> > > wake. I'd say we need better name here.
> > 
> > I agree with you here -- I've had this discussion with Arve previously,
> > but have been unable to offer a compelling alternative name.  Anybody
> > have a good idea?
> 
> delay_sleep or delaysleep?  block_sleep or blocksleep?  Any of the 
> above with "sleep" replaced by "suspend"?

Actually "sleep_veto" sounded best.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-11 21:37             ` Pavel Machek
@ 2009-02-11 22:05               ` Alan Stern
  2009-02-11 23:55               ` Arve Hjønnevåg
  1 sibling, 0 replies; 251+ messages in thread
From: Alan Stern @ 2009-02-11 22:05 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Brian Swetland, ncunningham, u.luckas, linux-pm

On Wed, 11 Feb 2009, Pavel Machek wrote:

> On Wed 2009-02-11 09:58:23, Alan Stern wrote:
> > On Tue, 10 Feb 2009, Brian Swetland wrote:
> > 
> > > [Pavel Machek <pavel@ucw.cz>]
> > > > > 
> > > > > wake_lock never blocks.
> > > > 
> > > > Wakelock is really bad name: it is not a lock and it does not protect
> > > > wake. I'd say we need better name here.
> > > 
> > > I agree with you here -- I've had this discussion with Arve previously,
> > > but have been unable to offer a compelling alternative name.  Anybody
> > > have a good idea?
> > 
> > delay_sleep or delaysleep?  block_sleep or blocksleep?  Any of the 
> > above with "sleep" replaced by "suspend"?
> 
> Actually "sleep_veto" sounded best.

I don't like it quite as much because these things don't _veto_ a 
sleep, they only delay it.  But that's a minor point.

Alan Stern

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-09  2:03             ` Arve Hjønnevåg
@ 2009-02-11 22:23               ` Rafael J. Wysocki
  2009-02-11 23:42                 ` Arve Hjønnevåg
  0 siblings, 1 reply; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-11 22:23 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Monday 09 February 2009, Arve Hjønnevåg wrote:
> On Sun, Feb 8, 2009 at 4:15 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> >> >> It means that you can, without knowing the current state of the lock, safely
> >> >> call wake_lock when you know that you need the wakelock, and
> >> >> wake_unlock when you are done.
> >> >
> >> > You can do the same with a reference counter IMO.
> >>
> >> Not without some per lock state.
> >
> > What prevents me from increasing the reference counter when necessary and
> > decreasing it when I'm done, actually?
> 
> Nothing prevents a driver from incrementing and decrementing a
> reference count correctly, but it has to know if it already has a
> reference. If you want to implement my current wake_lock api with a
> global reference count, you need some per lock state to indicate if
> the lock is locked or not.

Well, I don't.  In fact I think it's too complicated.

> >> >> It allows wakelocks with timeouts
> >> >
> >> > OK
> >> >
> >> > What for?
> >>
> >> So we do not have to change everything at once, and so we can allow
> >> code that we do not really trust a chance to run.
> >
> > Well, are you sure this is the best way of achieving this goal?
> 
> No, but I have not seen any better suggestions, that solve the problem.

Wakelocks with timeout are not a solution IMO.

> >> > However, it might be better to use a refcount along with some mechanism
> >> > allowing user space processes to increase it only once before decreasing.
> >> > That would require a per-task flag, but I think you can reuse one of the
> >> > freezer flags for that (the freezer is not going to run as long as a wakelock
> >> > is held, right?).
> >>
> >> How would this be better?
> >
> > Simpler code, less overhead.  But I'm not insisting, just showing you another
> > possible approach.
> 
> I agree that a global reference count is less overhead, but we need
> timeout support the make the system work for now.

I don't really think we need it in the mainline kernel.

> I don't see what a per-task flag would be helpful with. Not all wakelocks are
> associated with tasks.

What are they associated with, then?

> >
> >> >> >> +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.
> >> >> >
> >> >> > And what's this call needed for?
> >> >
> >> > Please don't remove the context.  This makes reading your reply difficult.
> >>
> >>  +It can also call wake_lock_timeout to release the wakelock after a delay:
> >>  +     wake_lock_timeout(&state->wakelock, HZ);
> >>  +
> >>
> >> >
> >> >> It is needed to give code that do not use wakelocks a chance to run.
> >> >> For instance we have not added wakelocks to the network stack. We also
> >> >> use it in some places when passing data to untrusted userspace code.
> >> >
> >> > Do you mean to take a wakelock with a timeout in one code path so that some
> >> > other code path can run knowing that suspend will not happen?
> >> >
> >> > If this is correct, I don't like it, because it's inherently unreliable (you
> >> > really never know how long it will take the other code path to run, so you
> >> > can't choose the timeout 100% accurately).
> >>
> >> I agree, but without wakelock support you have two options. Do not
> >> user suspend at all, or use a global timeout that you reset everywhere
> >> we lock a wakelock. By using wakelocks with timeouts we can at least
> >> make some events 100% reliable.
> >
> > I'm not convinced.
> >
> > Sorry to say that, but IMO the "wakelock with timeout" mechanism looks more
> > like a (poor) workaround than a solution of the problem.  Surely, I woulnd't
> > have tried to introduce anything similar into the kernel.
> 
> I do not want to add wakelocks to every kernel subsystem while there
> is no wakelock support in the mainline kernel. Using wakelocks with
> timeouts allow us to make progress.

It would hide the real invasiveness of the changes you'd like to make, which
need not be a good thing.

> >> > I really would use a refcount and make sure it's increased (and obviously
> >> > decreased) by _every_ code path that needs to prevent suspend from happening,
> >> > including networking and so on.
> >> >
> >> >> > Is there a mechanism allowing us to see what wakelocks have been created by
> >> >> > the user land?  Something like this would be useful for debugging.
> >> >>
> >> >> /proc/wakelocks shows all wakelocks. It does not currently indicate if
> >> >> a wakelock is from userspace, but if you are looking for a specific
> >> >> lock it is easy to find. I can add a prefix to the name of all user
> >> >> space wakelocks of you want.
> >> >
> >> > Well, actually, do the wakelocks have to have the names?
> >>
> >> If you want to debug the system or provide stats, yes.
> >
> > Care to elaborate?
> 
> We report the name and how long each wakelock is active in
> /proc/wakelocks. Without a name, those stats are not very useful. You
> can also enable debug options to print a message the kernel log every
> time a wakelock is locked, unlocked or used to trigger a wakeup.

Well, you put quite a lot of effort into making this nicely debuggable and so
on, but I think you should have submitted the minimal core functionality first
to see if people were comfortable with it.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-09  3:07                       ` Alan Stern
@ 2009-02-11 22:26                         ` Rafael J. Wysocki
  0 siblings, 0 replies; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-11 22:26 UTC (permalink / raw)
  To: Alan Stern; +Cc: ncunningham, u.luckas, Brian Swetland, linux-pm

On Monday 09 February 2009, Alan Stern wrote:
> On Sun, 8 Feb 2009, Arve Hjønnevåg wrote:
> 
> > How do you handle devices that should be in a low power mode when
> > closed, and a high(er) power mode when open. While adding
> > early-suspend hooks to a driver may be ugly, it does not need any more
> > support than open and close does.
> 
> This illustrates some of the problems of differing outlooks.  In an 
> embedded system, the set of devices is limited and the set of available 
> power states is known beforehand.  In other settings neither of these 
> is true.
> 
> Early-suspend is an example of a partially-functional system state.  
> In your Android-centric approach, early-suspend is centered around the 
> screen.  But other sorts of systems way well have other requirements 
> and may want their partially-functional system state to be centered 
> around something else.  Or they may want to have more than one 
> partially-functional system state.
> 
> What we need is a mechanism capable of accomodating all these different
> requirements.  Presumably the core kernel would provide the hooks but
> the implementation details would be left up to platform-specific code.  
> There should be a generic scheme for representing partially-functional
> system states, together with a list of devices to be put in low-power
> mode for each state and an indication of which low-power mode to use
> (since a device can have more than one low-power mode).  Device drivers
> should have an interface for going into a particular low-power state.
> 
> The extent to which all of this needs to be split between the kernel
> and userspace isn't immediately clear.  Latency issues might force a
> large part of it to live in the kernel.  On the other hand, if the list
> of devices & modes can be pushed out to userspace, then the in-kernel
> portion could end up being nothing more than a runtime-PM mechanism of
> the sort we have been discussing for years.

Agreed.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-11 22:23               ` Rafael J. Wysocki
@ 2009-02-11 23:42                 ` Arve Hjønnevåg
  2009-02-12 22:22                   ` Rafael J. Wysocki
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-11 23:42 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Wed, Feb 11, 2009 at 2:23 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
>> >> >> It allows wakelocks with timeouts
>> >> >
>> >> > OK
>> >> >
>> >> > What for?
>> >>
>> >> So we do not have to change everything at once, and so we can allow
>> >> code that we do not really trust a chance to run.
>> >
>> > Well, are you sure this is the best way of achieving this goal?
>>
>> No, but I have not seen any better suggestions, that solve the problem.
>
> Wakelocks with timeout are not a solution IMO.

It is an improvement over the current situation where you have to use
timeouts for everything.

>> >> > However, it might be better to use a refcount along with some mechanism
>> >> > allowing user space processes to increase it only once before decreasing.
>> >> > That would require a per-task flag, but I think you can reuse one of the
>> >> > freezer flags for that (the freezer is not going to run as long as a wakelock
>> >> > is held, right?).
>> >>
>> >> How would this be better?
>> >
>> > Simpler code, less overhead.  But I'm not insisting, just showing you another
>> > possible approach.
>>
>> I agree that a global reference count is less overhead, but we need
>> timeout support the make the system work for now.
>
> I don't really think we need it in the mainline kernel.

We do if we want anyone to be able to ship an android device capable
of suspending with the mainline kernel.

>
>> I don't see what a per-task flag would be helpful with. Not all wakelocks are
>> associated with tasks.
>
> What are they associated with, then?

Data (usually queues). If by per task you mean per process and not per
thread, you could use use your flag to clean up when a process dies
though.

>> We report the name and how long each wakelock is active in
>> /proc/wakelocks. Without a name, those stats are not very useful. You
>> can also enable debug options to print a message the kernel log every
>> time a wakelock is locked, unlocked or used to trigger a wakeup.
>
> Well, you put quite a lot of effort into making this nicely debuggable and so
> on, but I think you should have submitted the minimal core functionality first
> to see if people were comfortable with it.

The code I submitted is usable and tested. Without wakelocks we cannot
use suspend, and without wakelock timeouts we cannot pass events to
components that do not use wakelocks.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-11 21:37             ` Pavel Machek
  2009-02-11 22:05               ` Alan Stern
@ 2009-02-11 23:55               ` Arve Hjønnevåg
  1 sibling, 0 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-11 23:55 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Brian Swetland, ncunningham, u.luckas, linux-pm

On Wed, Feb 11, 2009 at 1:37 PM, Pavel Machek <pavel@ucw.cz> wrote:
> On Wed 2009-02-11 09:58:23, Alan Stern wrote:
>> On Tue, 10 Feb 2009, Brian Swetland wrote:
>>
>> > [Pavel Machek <pavel@ucw.cz>]
>> > > >
>> > > > wake_lock never blocks.
>> > >
>> > > Wakelock is really bad name: it is not a lock and it does not protect
>> > > wake. I'd say we need better name here.
>> >
>> > I agree with you here -- I've had this discussion with Arve previously,
>> > but have been unable to offer a compelling alternative name.  Anybody
>> > have a good idea?
>>
>> delay_sleep or delaysleep?  block_sleep or blocksleep?  Any of the
>> above with "sleep" replaced by "suspend"?
>
> Actually "sleep_veto" sounded best.

What is the api for a sleep_veto? Lock and unlock makes sense for a
wakelock, but not for a veto.

The original driver used suspendlock for the kernel api, but we used
wakelock for the userspace apis. I changed the name to wakelock so
that it would match the user space api (which we cannot change), and
also because people here usually referred to them as wakelocks despite
the name of the kernel apis.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 05/13] PM: Add option to disable /sys/power/state interface
  2009-02-08 14:04                 ` Brian Swetland
  2009-02-08 21:06                   ` Pavel Machek
  2009-02-08 23:40                   ` Rafael J. Wysocki
@ 2009-02-12 11:16                   ` Matthew Garrett
  2 siblings, 0 replies; 251+ messages in thread
From: Matthew Garrett @ 2009-02-12 11:16 UTC (permalink / raw)
  To: Brian Swetland; +Cc: ncunningham, u.luckas, linux-pm

On Sun, Feb 08, 2009 at 06:04:04AM -0800, Brian Swetland wrote:

> Being in suspend, where periodic user and kernel timers aren't running,
> and random userspace threads aren't possibly spinning, rather than just 
> being in idle in the lowest power possible state, represent a pretty 
> significant power savings.

Nokia have produced a Linux-based device that runs off a phone battery 
and has roughly a week of standby time without entering an explicit 
suspend state at any time, so dealing with this is clearly possible. 
What we need is to ensure that driver interfaces allow the kernel to 
know when a given piece of hardware is required and place it in an 
appropriate power state - the USB autosuspend code is probably the best 
kernelwide example of this right now.

Part of the reason you're getting pushback is that your solution to the 
problem of shutting down unused hardware is tied to embedded-style 
systems with very low resume latencies. You can afford to handle the 
problem by entering an explicit suspend state. In the x86 mobile world, 
we don't have that option. It's simply too slow and disruptive to the 
user experience. As a consequence we're far more interested in hardware 
power management that doesn't require an explicit system-wide suspend.

A solution that's focused on powering down as much unused hardware as 
possible regardless of the system state benefits the x86 world as well 
as the embedded world, so I think there's a fairly strong argument that 
it's a better solution than one requiring an explicit system state 
change. Arve mentioned that your hardware enters the same power state in 
idle as in suspend, so the only real difference here is that in the 
"better" solution you're inferring that the hardware is idle based on 
the demands of userspace rather than explicitly shutting it down.

At least, from the kernel side. The userspace side is more awkward - as 
Pavel suggested you could obtain a pretty similar outcome by just 
sending SIGSTOP to pretty much everything, which is kind of ugly but 
would probably work.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-11  4:47         ` Brian Swetland
  2009-02-11  8:40           ` Uli Luckas
  2009-02-11 14:58           ` Alan Stern
@ 2009-02-12 18:47           ` mark gross
  2 siblings, 0 replies; 251+ messages in thread
From: mark gross @ 2009-02-12 18:47 UTC (permalink / raw)
  To: Brian Swetland; +Cc: ncunningham, u.luckas, linux-pm

On Tue, Feb 10, 2009 at 08:47:36PM -0800, Brian Swetland wrote:
> [Pavel Machek <pavel@ucw.cz>]
> > > 
> > > wake_lock never blocks.
> > 
> > Wakelock is really bad name: it is not a lock and it does not protect
> > wake. I'd say we need better name here.
> 
> I agree with you here -- I've had this discussion with Arve previously,
> but have been unable to offer a compelling alternative name.  Anybody
> have a good idea?

nodoz  (just kidding)

names are always hard for me.  What you are talking about is
constraining entry to low power states.  (mostly)


> 
> Some people use "sleep vote" for a similar mechanism (though usually
> you're voting against sleep, which makes it feel backwards to me).

with what OS?

--mgross

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-11 23:42                 ` Arve Hjønnevåg
@ 2009-02-12 22:22                   ` Rafael J. Wysocki
  2009-02-12 23:42                     ` Woodruff, Richard
  0 siblings, 1 reply; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-12 22:22 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thursday 12 February 2009, Arve Hjønnevåg wrote:
> On Wed, Feb 11, 2009 at 2:23 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> >> >> >> It allows wakelocks with timeouts
[--snip--]
> > Well, you put quite a lot of effort into making this nicely debuggable and so
> > on, but I think you should have submitted the minimal core functionality first
> > to see if people were comfortable with it.
> 
> The code I submitted is usable and tested.

Unfortunately, that doesn't help it a lot.  There's a lot of usable and tested
code out of the kernel.

In general, kernel code is mergeable if people agree with it, which is not the
case with your patches.

> Without wakelocks we cannot use suspend, and without wakelock timeouts
> we cannot pass events to components that do not use wakelocks.

This is a very strong statement, as though there had not been any alternative
to the wakelocks.  I don't really think it's the case.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-12 22:22                   ` Rafael J. Wysocki
@ 2009-02-12 23:42                     ` Woodruff, Richard
  2009-02-13  1:10                       ` Matthew Garrett
  0 siblings, 1 reply; 251+ messages in thread
From: Woodruff, Richard @ 2009-02-12 23:42 UTC (permalink / raw)
  To: Rafael J. Wysocki, Arve Hjønnevåg
  Cc: swetland, ncunningham, u.luckas, linux-pm


> From: linux-pm-bounces@lists.linux-foundation.org [mailto:linux-pm-
> bounces@lists.linux-foundation.org] On Behalf Of Rafael J. Wysocki
> Sent: Thursday, February 12, 2009 4:23 PM

> Unfortunately, that doesn't help it a lot.  There's a lot of usable and tested
> code out of the kernel.
>
> In general, kernel code is mergeable if people agree with it, which is not the
> case with your patches.

Do you see the code breaking the current system?  Is what's being offered configurable off. Can be entered with experimental Kconfig?  Maybe the code needs to be refactored such that it doesn't hurt existing functions but people can get the benefit of it.

It is discouraging to hear comments like "we have been talking about for years something else" yet nothing exists or is in open development. Things can evolve in place.

If something better actually exists and there are people willing to spend the time to do it, then it would be good to see the details. Android is big enough and has enough momentum that it will live for a while.

You've offered some examples on future PCI bus plans. Many embedded devices don't have this and won't see benefit. How possible is it to move to a generic bus like platform and do work there? It would be more globally useable against that.

Thanks,
Richard W.

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-12 23:42                     ` Woodruff, Richard
@ 2009-02-13  1:10                       ` Matthew Garrett
  2009-02-13  2:21                         ` Arve Hjønnevåg
                                           ` (3 more replies)
  0 siblings, 4 replies; 251+ messages in thread
From: Matthew Garrett @ 2009-02-13  1:10 UTC (permalink / raw)
  To: Woodruff, Richard; +Cc: ncunningham, u.luckas, swetland, linux-pm

On Thu, Feb 12, 2009 at 05:42:01PM -0600, Woodruff, Richard wrote:

> It is discouraging to hear comments like "we have been talking about for years something else" yet nothing exists or is in open development. Things can evolve in place.

This is userlad-visible ABI. We can't evolve it in place - we need to 
get it right before merging it, otherwise we need to carry on 
maintaining code for an extended period of time in order to ensure that 
there's no userland code that depends on it.

I dislike the kernel-side use of wakelocks. They're basically equivalent 
to a device returning -EBUSY during the suspend phase, which is 
something that can be done without any kernel modifications. I'm more 
interested in the userspace side, but I'd like to know more about what 
sort of constraints userspace is likely to impose. In general kernel 
people respond better to a "Here is a problem statement, here is our 
proposed solution" type statement than "Here is our code".

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13  1:10                       ` Matthew Garrett
@ 2009-02-13  2:21                         ` Arve Hjønnevåg
  2009-02-13  2:40                           ` Nigel Cunningham
  2009-02-13  3:17                         ` Woodruff, Richard
                                           ` (2 subsequent siblings)
  3 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-13  2:21 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: ncunningham, swetland, u.luckas, linux-pm

On Thu, Feb 12, 2009 at 5:10 PM, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> I dislike the kernel-side use of wakelocks. They're basically equivalent
> to a device returning -EBUSY during the suspend phase, which is
> something that can be done without any kernel modifications.

I don't get why people object to wakelocks supporting timeouts, but
think drivers returning -EBUSY to abort suspend is ok. If suspend
fails, the higher level code has to periodically retry until it can
succeed. This means that the device is awake for longer than it need
to, and you are repeatedly wasting time freezing all tasks and
suspending a set of drivers before you get to the driver that is
preventing suspend.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13  2:21                         ` Arve Hjønnevåg
@ 2009-02-13  2:40                           ` Nigel Cunningham
  0 siblings, 0 replies; 251+ messages in thread
From: Nigel Cunningham @ 2009-02-13  2:40 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: swetland, u.luckas, linux-pm

On Thu, 2009-02-12 at 18:21 -0800, Arve Hjønnevåg wrote:
> On Thu, Feb 12, 2009 at 5:10 PM, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> > I dislike the kernel-side use of wakelocks. They're basically equivalent
> > to a device returning -EBUSY during the suspend phase, which is
> > something that can be done without any kernel modifications.
> 
> I don't get why people object to wakelocks supporting timeouts, but
> think drivers returning -EBUSY to abort suspend is ok. If suspend
> fails, the higher level code has to periodically retry until it can
> succeed. This means that the device is awake for longer than it need
> to, and you are repeatedly wasting time freezing all tasks and
> suspending a set of drivers before you get to the driver that is
> preventing suspend.

I for one don't think drivers returning -EBUSY is okay. Once a user asks
for suspend to ram or hibernation, nothing but improper configuration
(in the hibernation case) should stop them getting it. Even if they ask
to suspend to ram in the middle of writing a cd, they should get the
suspend to ram. But, of course, I'm just one voice.

Regards,

Nigel

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13  1:10                       ` Matthew Garrett
  2009-02-13  2:21                         ` Arve Hjønnevåg
@ 2009-02-13  3:17                         ` Woodruff, Richard
  2009-02-13 10:55                         ` Uli Luckas
  2009-02-26 15:04                         ` Pavel Machek
  3 siblings, 0 replies; 251+ messages in thread
From: Woodruff, Richard @ 2009-02-13  3:17 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: ncunningham, u.luckas, swetland, linux-pm


> From: Matthew Garrett [mailto:mjg59@srcf.ucam.org]
> Sent: Thursday, February 12, 2009 7:11 PM

> On Thu, Feb 12, 2009 at 05:42:01PM -0600, Woodruff, Richard wrote:
>
> > It is discouraging to hear comments like "we have been talking about for
> years something else" yet nothing exists or is in open development. Things can
> evolve in place.
>
> This is userlad-visible ABI. We can't evolve it in place - we need to
> get it right before merging it, otherwise we need to carry on
> maintaining code for an extended period of time in order to ensure that
> there's no userland code that depends on it.

It would be nice to do something evil and require a handshake which generates a random but unique string in sysfs at leaf level for interface. Making the namespace generation to be a bit more of a protocol instead of string matching might force a bit more flexible user space.

There are examples like syscalls of things which seem to grow with out huge contention.

> I dislike the kernel-side use of wakelocks. They're basically equivalent
> to a device returning -EBUSY during the suspend phase, which is
> something that can be done without any kernel modifications. I'm more
> interested in the userspace side, but I'd like to know more about what
> sort of constraints userspace is likely to impose. In general kernel
> people respond better to a "Here is a problem statement, here is our
> proposed solution" type statement than "Here is our code".

It is far better to get -EBUSY at the start of the suspend call out then at the end. Latency is less and not all drivers behave so well when resuming from a partial suspend.

I also agree kernel space could have been different and user space is interesting. However, I'm one to appreciate function over form. When you get them both its zen, but if is pretty and doesn't work its useless.

Thanks,
Richard W.

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13  1:10                       ` Matthew Garrett
  2009-02-13  2:21                         ` Arve Hjønnevåg
  2009-02-13  3:17                         ` Woodruff, Richard
@ 2009-02-13 10:55                         ` Uli Luckas
  2009-02-13 14:06                           ` Matthew Garrett
  2009-02-26 15:04                         ` Pavel Machek
  3 siblings, 1 reply; 251+ messages in thread
From: Uli Luckas @ 2009-02-13 10:55 UTC (permalink / raw)
  To: linux-pm; +Cc: ncunningham, swetland

On Friday, 13. February 2009, Matthew Garrett wrote:
> I dislike the kernel-side use of wakelocks. They're basically equivalent
> to a device returning -EBUSY during the suspend phase, which is
> something that can be done without any kernel modifications. 
That's absouletely wrong. With wake locks, you are in a pre suspend state and 
stay there until all wakelocks are released. Then you go to sleep.

With -EBUSY the kernel gives up on suspend until some source triggers it 
again. When exactly should suspend then be retried?

Uli

-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13 10:55                         ` Uli Luckas
@ 2009-02-13 14:06                           ` Matthew Garrett
  2009-02-13 14:24                             ` Brian Swetland
                                               ` (2 more replies)
  0 siblings, 3 replies; 251+ messages in thread
From: Matthew Garrett @ 2009-02-13 14:06 UTC (permalink / raw)
  To: Uli Luckas; +Cc: swetland, linux-pm, ncunningham

On Fri, Feb 13, 2009 at 11:55:06AM +0100, Uli Luckas wrote:
> On Friday, 13. February 2009, Matthew Garrett wrote:
> > I dislike the kernel-side use of wakelocks. They're basically equivalent
> > to a device returning -EBUSY during the suspend phase, which is
> > something that can be done without any kernel modifications. 
> That's absouletely wrong. With wake locks, you are in a pre suspend state and 
> stay there until all wakelocks are released. Then you go to sleep.
> 
> With -EBUSY the kernel gives up on suspend until some source triggers it 
> again. When exactly should suspend then be retried?

Ok, so let's think about this differently. What we want is simply for 
drivers to be able to block an automatic suspend. For performance 
reasons we want to keep track of this state without calling into the 
entire driver tree. Now that the userspace API can automatically clean 
up after itself, why is this not just a simple counter? Kernel API would 
be something like:

(input arrives)
inhibit_suspend();
(input queue is emptied)
uninhibit_suspend();

perhaps using the device struct or something as a token for debug 
purposes. Userland ABI would then be a single /dev/inhibit_suspend, 
with the counter being bumped each time an application opens it. It'll 
automatically be dropped if the application exits without cleaning up.

This seems simpler and also avoids any arguments about the naming 
scheme. What am I missing?
-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13 14:06                           ` Matthew Garrett
@ 2009-02-13 14:24                             ` Brian Swetland
  2009-02-13 14:37                               ` Matthew Garrett
  2009-02-13 16:49                             ` Uli Luckas
  2009-02-13 23:36                             ` Arve Hjønnevåg
  2 siblings, 1 reply; 251+ messages in thread
From: Brian Swetland @ 2009-02-13 14:24 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: linux-pm, Uli Luckas, ncunningham

[Matthew Garrett <mjg59@srcf.ucam.org>]
> 
> Ok, so let's think about this differently. What we want is simply for 
> drivers to be able to block an automatic suspend. For performance 
> reasons we want to keep track of this state without calling into the 
> entire driver tree. Now that the userspace API can automatically clean 
> up after itself, why is this not just a simple counter? Kernel API would 
> be something like:
> 
> (input arrives)
> inhibit_suspend();
> (input queue is emptied)
> uninhibit_suspend();
> 
> perhaps using the device struct or something as a token for debug 
> purposes. Userland ABI would then be a single /dev/inhibit_suspend, 
> with the counter being bumped each time an application opens it. It'll 
> automatically be dropped if the application exits without cleaning up.
> 
> This seems simpler and also avoids any arguments about the naming 
> scheme. What am I missing?

If we can enable keeping stats (probably as a config option that
defaults off) to help answer the "battery life is down 20% in this
build, are we preventing suspend more than before?" question, this
seems like a reasonable direction to me.

For the case where somebody wants to release the hold on suspend after a
timer expiration, that can be built on top of this, so that's covered.

I think the "what happens when a process crashes and its suspend
inhibits are released" issue still needs some thought -- if say a
background/service process crashes while holding a lock we want to
have the process be able to be restarted by init or whatnot without
having to wait for some other activity.  This is a real example we
ran into in the past -- telephony process crashes and the device 
doesn't get back on the network until the user presses a key, an 
alarm fires, etc.

I suspect this is more sparse than Arve is hoping for, and maybe
I've missed some obvious concern he has. 

Brian

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13 14:24                             ` Brian Swetland
@ 2009-02-13 14:37                               ` Matthew Garrett
  2009-02-13 14:46                                 ` Brian Swetland
  2009-02-13 16:46                                 ` Uli Luckas
  0 siblings, 2 replies; 251+ messages in thread
From: Matthew Garrett @ 2009-02-13 14:37 UTC (permalink / raw)
  To: Brian Swetland; +Cc: linux-pm, Uli Luckas, ncunningham

On Fri, Feb 13, 2009 at 06:24:09AM -0800, Brian Swetland wrote:

> I think the "what happens when a process crashes and its suspend
> inhibits are released" issue still needs some thought -- if say a
> background/service process crashes while holding a lock we want to
> have the process be able to be restarted by init or whatnot without
> having to wait for some other activity.  This is a real example we
> ran into in the past -- telephony process crashes and the device 
> doesn't get back on the network until the user presses a key, an 
> alarm fires, etc.

The easiest way to handle this would seem to be a multiplexing daemon 
that implements whatever policy a specific use case has. In your case 
this would do its own reference counting and then implement timeouts for 
specific applications, perhaps with some kind of acl so arbitrary apps 
can't take a lock and then fall down a well. If you've got a 
sufficiently advanced init then you'd be able to flag an application as 
being in restart state and then have the daemon hold the lock until the 
application chooses to reacquire it or not, which seems more flexible 
than any purely kernel-based implementation.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13 14:37                               ` Matthew Garrett
@ 2009-02-13 14:46                                 ` Brian Swetland
  2009-02-13 15:07                                   ` Matthew Garrett
  2009-02-13 16:46                                 ` Uli Luckas
  1 sibling, 1 reply; 251+ messages in thread
From: Brian Swetland @ 2009-02-13 14:46 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: linux-pm, Uli Luckas, ncunningham

[Matthew Garrett <mjg59@srcf.ucam.org>]
> On Fri, Feb 13, 2009 at 06:24:09AM -0800, Brian Swetland wrote:
> 
> > I think the "what happens when a process crashes and its suspend
> > inhibits are released" issue still needs some thought -- if say a
> > background/service process crashes while holding a lock we want to
> > have the process be able to be restarted by init or whatnot without
> > having to wait for some other activity.  This is a real example we
> > ran into in the past -- telephony process crashes and the device 
> > doesn't get back on the network until the user presses a key, an 
> > alarm fires, etc.
> 
> The easiest way to handle this would seem to be a multiplexing daemon 
> that implements whatever policy a specific use case has. In your case 
> this would do its own reference counting and then implement timeouts for 
> specific applications, perhaps with some kind of acl so arbitrary apps 
> can't take a lock and then fall down a well. If you've got a 
> sufficiently advanced init then you'd be able to flag an application as 
> being in restart state and then have the daemon hold the lock until the 
> application chooses to reacquire it or not, which seems more flexible 
> than any purely kernel-based implementation.

It'd be nice to not have to indirect all userspace suspend inhibits.
If we had the device interface to userspace actually have INHIBIT
and STOP_INHIBIT ops, we could notice if the fd is closed without
actually returning the state to STOP_INHIBIT cleanly.  Add a mechanism
for waiting until somebody exits unexpectedly that init or your monitor
process could use, you avoid the indirection and have a mechanism for
handing over to whatever is responsible for restarting something that's
in an unhappy state.  Too convoluted?

Brian

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13 14:46                                 ` Brian Swetland
@ 2009-02-13 15:07                                   ` Matthew Garrett
  2009-02-13 22:52                                     ` Rafael J. Wysocki
  0 siblings, 1 reply; 251+ messages in thread
From: Matthew Garrett @ 2009-02-13 15:07 UTC (permalink / raw)
  To: Brian Swetland; +Cc: linux-pm, Uli Luckas, ncunningham

On Fri, Feb 13, 2009 at 06:46:58AM -0800, Brian Swetland wrote:
> [Matthew Garrett <mjg59@srcf.ucam.org>]
> > The easiest way to handle this would seem to be a multiplexing daemon 
> > that implements whatever policy a specific use case has. In your case 
> > this would do its own reference counting and then implement timeouts for 
> > specific applications, perhaps with some kind of acl so arbitrary apps 
> > can't take a lock and then fall down a well. If you've got a 
> > sufficiently advanced init then you'd be able to flag an application as 
> > being in restart state and then have the daemon hold the lock until the 
> > application chooses to reacquire it or not, which seems more flexible 
> > than any purely kernel-based implementation.
> 
> It'd be nice to not have to indirect all userspace suspend inhibits.
> If we had the device interface to userspace actually have INHIBIT
> and STOP_INHIBIT ops, we could notice if the fd is closed without
> actually returning the state to STOP_INHIBIT cleanly.  Add a mechanism
> for waiting until somebody exits unexpectedly that init or your monitor
> process could use, you avoid the indirection and have a mechanism for
> handing over to whatever is responsible for restarting something that's
> in an unhappy state.  Too convoluted?

Mm. How do you guarantee a timely handover? Doing it in userland means 
that you can adapt it to work with whatever process restart setup you 
have, whereas doing it in kernel means adapting whatever process restart 
setup you have to the kernel. I'd still lean towards thinking that the 
userland approach means you can have tighter integration with the rest 
of your stack.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13 14:37                               ` Matthew Garrett
  2009-02-13 14:46                                 ` Brian Swetland
@ 2009-02-13 16:46                                 ` Uli Luckas
  2009-02-13 17:05                                   ` Matthew Garrett
  1 sibling, 1 reply; 251+ messages in thread
From: Uli Luckas @ 2009-02-13 16:46 UTC (permalink / raw)
  To: linux-pm; +Cc: ncunningham, Brian Swetland

On Friday, 13. February 2009, Matthew Garrett wrote:
> On Fri, Feb 13, 2009 at 06:24:09AM -0800, Brian Swetland wrote:
> > I think the "what happens when a process crashes and its suspend
> > inhibits are released" issue still needs some thought -- if say a
> > background/service process crashes while holding a lock we want to
> > have the process be able to be restarted by init or whatnot without
> > having to wait for some other activity.  This is a real example we
> > ran into in the past -- telephony process crashes and the device
> > doesn't get back on the network until the user presses a key, an
> > alarm fires, etc.
>
> The easiest way to handle this would seem to be a multiplexing daemon
> that implements whatever policy a specific use case has. In your case
> this would do its own reference counting and then implement timeouts for
> specific applications, perhaps with some kind of acl so arbitrary apps
> can't take a lock and then fall down a well. If you've got a
> sufficiently advanced init then you'd be able to flag an application as
> being in restart state and then have the daemon hold the lock until the 
> application chooses to reacquire it or not, which seems more flexible
> than any purely kernel-based implementation.
That's racy. By the time the daemon notices that a process crashed, the kernel 
might already have triggered suspend. userspace might then be frozen before 
it can accuire the 'process restarting' lock.
I also wonder, if it is immanently racy to use userspcae communication 
(client/daemon) for suspend locks. What if the daemon is already frozen when 
a client sends a lock request request? 

Uli

-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13 14:06                           ` Matthew Garrett
  2009-02-13 14:24                             ` Brian Swetland
@ 2009-02-13 16:49                             ` Uli Luckas
  2009-02-13 17:09                               ` Matthew Garrett
  2009-02-27 13:18                               ` Pavel Machek
  2009-02-13 23:36                             ` Arve Hjønnevåg
  2 siblings, 2 replies; 251+ messages in thread
From: Uli Luckas @ 2009-02-13 16:49 UTC (permalink / raw)
  To: linux-pm; +Cc: ncunningham, swetland

On Friday, 13. February 2009, Matthew Garrett wrote:
> Userland ABI would then be a single /dev/inhibit_suspend,
> with the counter being bumped each time an application opens it. It'll
> automatically be dropped if the application exits without cleaning up.
>
> This seems simpler and also avoids any arguments about the naming
> scheme. What am I missing?
Opening and closing an fd sounds like a lot of overhead. Taking and releasing 
locks if going to be a called with very highg frequency. I'd go for an ioctl.

Uli


-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13 16:46                                 ` Uli Luckas
@ 2009-02-13 17:05                                   ` Matthew Garrett
  2009-02-13 18:13                                     ` Uli Luckas
  0 siblings, 1 reply; 251+ messages in thread
From: Matthew Garrett @ 2009-02-13 17:05 UTC (permalink / raw)
  To: Uli Luckas; +Cc: Brian Swetland, linux-pm, ncunningham

On Fri, Feb 13, 2009 at 05:46:42PM +0100, Uli Luckas wrote:

> That's racy. By the time the daemon notices that a process crashed, the kernel 
> might already have triggered suspend. userspace might then be frozen before 
> it can accuire the 'process restarting' lock.
> I also wonder, if it is immanently racy to use userspcae communication 
> (client/daemon) for suspend locks. What if the daemon is already frozen when 
> a client sends a lock request request? 

The daemon holds the lock in the first place. There's no race. As for 
issues with the freezer, I think my position on that is fairly well 
known...

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13 16:49                             ` Uli Luckas
@ 2009-02-13 17:09                               ` Matthew Garrett
  2009-02-13 18:18                                 ` Uli Luckas
  2009-02-27 13:18                               ` Pavel Machek
  1 sibling, 1 reply; 251+ messages in thread
From: Matthew Garrett @ 2009-02-13 17:09 UTC (permalink / raw)
  To: Uli Luckas; +Cc: swetland, linux-pm, ncunningham

On Fri, Feb 13, 2009 at 05:49:57PM +0100, Uli Luckas wrote:
> On Friday, 13. February 2009, Matthew Garrett wrote:
> > Userland ABI would then be a single /dev/inhibit_suspend,
> > with the counter being bumped each time an application opens it. It'll
> > automatically be dropped if the application exits without cleaning up.
> >
> > This seems simpler and also avoids any arguments about the naming
> > scheme. What am I missing?
> Opening and closing an fd sounds like a lot of overhead. Taking and releasing 
> locks if going to be a called with very highg frequency. I'd go for an ioctl.

Is the performance of open() really that bad compared to ioctl()? And 
what are your tasks doing that this would actually be a noticable 
performance issue? Userspace should not be taking and releasing these 
locks with high frequency. It should be doing so in response to events, 
and events occur infrequently. Given that the implementation in the 
field is writing strings into a file in sysfs and nobody's complained, I 
don't think this is a huge concern.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13 17:05                                   ` Matthew Garrett
@ 2009-02-13 18:13                                     ` Uli Luckas
  2009-02-13 19:14                                       ` Matthew Garrett
  0 siblings, 1 reply; 251+ messages in thread
From: Uli Luckas @ 2009-02-13 18:13 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: Brian Swetland, linux-pm, ncunningham

On Friday, 13. February 2009, Matthew Garrett wrote:
> On Fri, Feb 13, 2009 at 05:46:42PM +0100, Uli Luckas wrote:
> > That's racy. By the time the daemon notices that a process crashed, the
> > kernel might already have triggered suspend. userspace might then be
> > frozen before it can accuire the 'process restarting' lock.
> > I also wonder, if it is immanently racy to use userspcae communication
> > (client/daemon) for suspend locks. What if the daemon is already frozen
> > when a client sends a lock request request?
>
> The daemon holds the lock in the first place.
When did the daemon take the lock? When it anticipated the process would 
crash?

> There's no race. As for issues with the freezer, I think my position on that
> is fairly well known...
Not to me.

Uli

-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13 17:09                               ` Matthew Garrett
@ 2009-02-13 18:18                                 ` Uli Luckas
  0 siblings, 0 replies; 251+ messages in thread
From: Uli Luckas @ 2009-02-13 18:18 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: swetland, linux-pm, ncunningham

On Friday, 13. February 2009, Matthew Garrett wrote:
> On Fri, Feb 13, 2009 at 05:49:57PM +0100, Uli Luckas wrote:
> > On Friday, 13. February 2009, Matthew Garrett wrote:
> > > Userland ABI would then be a single /dev/inhibit_suspend,
> > > with the counter being bumped each time an application opens it. It'll
> > > automatically be dropped if the application exits without cleaning up.
> > >
> > > This seems simpler and also avoids any arguments about the naming
> > > scheme. What am I missing?
> >
> > Opening and closing an fd sounds like a lot of overhead. Taking and
> > releasing locks if going to be a called with very highg frequency. I'd go
> > for an ioctl.
>
> Is the performance of open() really that bad compared to ioctl()? And
> what are your tasks doing that this would actually be a noticable
> performance issue? Userspace should not be taking and releasing these
> locks with high frequency. It should be doing so in response to events,
> and events occur infrequently. 
Touch screen events for example are performance critical if you want to be 
able to draw smooth curves. To get rid of timed locks, the concept might have 
to be extended to network packets, serial data, ...

> Given that the implementation in the field is writing strings into a file in
> sysfs and nobody's complained, I don't think this is a huge concern.
That's because a lot of areas are not yet under wake lock protection.

Uli


-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13 18:13                                     ` Uli Luckas
@ 2009-02-13 19:14                                       ` Matthew Garrett
  2009-02-13 19:35                                         ` Uli Luckas
  0 siblings, 1 reply; 251+ messages in thread
From: Matthew Garrett @ 2009-02-13 19:14 UTC (permalink / raw)
  To: Uli Luckas; +Cc: Brian Swetland, linux-pm, ncunningham

On Fri, Feb 13, 2009 at 07:13:52PM +0100, Uli Luckas wrote:
> On Friday, 13. February 2009, Matthew Garrett wrote:
> >
> > The daemon holds the lock in the first place.
> When did the daemon take the lock? When it anticipated the process would 
> crash?

When it was first asked to. In this model invidual applications wouldn't 
take locks themselves - it would be up to the daemon to handle the 
kernel interaction.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13 19:14                                       ` Matthew Garrett
@ 2009-02-13 19:35                                         ` Uli Luckas
  0 siblings, 0 replies; 251+ messages in thread
From: Uli Luckas @ 2009-02-13 19:35 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: Brian Swetland, linux-pm, ncunningham

On Friday, 13. February 2009, Matthew Garrett wrote:
> On Fri, Feb 13, 2009 at 07:13:52PM +0100, Uli Luckas wrote:
> > On Friday, 13. February 2009, Matthew Garrett wrote:
> > > The daemon holds the lock in the first place.
> >
> > When did the daemon take the lock? When it anticipated the process would
> > crash?
>
> When it was first asked to. In this model invidual applications wouldn't
> take locks themselves - it would be up to the daemon to handle the
> kernel interaction.

Thanks for explaining

Uli

-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13 15:07                                   ` Matthew Garrett
@ 2009-02-13 22:52                                     ` Rafael J. Wysocki
  0 siblings, 0 replies; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-13 22:52 UTC (permalink / raw)
  To: linux-pm; +Cc: ncunningham, Uli Luckas, Brian Swetland

On Friday 13 February 2009, Matthew Garrett wrote:
> On Fri, Feb 13, 2009 at 06:46:58AM -0800, Brian Swetland wrote:
> > [Matthew Garrett <mjg59@srcf.ucam.org>]
> > > The easiest way to handle this would seem to be a multiplexing daemon 
> > > that implements whatever policy a specific use case has. In your case 
> > > this would do its own reference counting and then implement timeouts for 
> > > specific applications, perhaps with some kind of acl so arbitrary apps 
> > > can't take a lock and then fall down a well. If you've got a 
> > > sufficiently advanced init then you'd be able to flag an application as 
> > > being in restart state and then have the daemon hold the lock until the 
> > > application chooses to reacquire it or not, which seems more flexible 
> > > than any purely kernel-based implementation.
> > 
> > It'd be nice to not have to indirect all userspace suspend inhibits.
> > If we had the device interface to userspace actually have INHIBIT
> > and STOP_INHIBIT ops, we could notice if the fd is closed without
> > actually returning the state to STOP_INHIBIT cleanly.  Add a mechanism
> > for waiting until somebody exits unexpectedly that init or your monitor
> > process could use, you avoid the indirection and have a mechanism for
> > handing over to whatever is responsible for restarting something that's
> > in an unhappy state.  Too convoluted?
> 
> Mm. How do you guarantee a timely handover? Doing it in userland means 
> that you can adapt it to work with whatever process restart setup you 
> have, whereas doing it in kernel means adapting whatever process restart 
> setup you have to the kernel. I'd still lean towards thinking that the 
> userland approach means you can have tighter integration with the rest 
> of your stack.

FWIW, I agree.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13 14:06                           ` Matthew Garrett
  2009-02-13 14:24                             ` Brian Swetland
  2009-02-13 16:49                             ` Uli Luckas
@ 2009-02-13 23:36                             ` Arve Hjønnevåg
  2009-02-14  0:05                               ` Matthew Garrett
  2 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-13 23:36 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: swetland, linux-pm, Uli Luckas, ncunningham

On Fri, Feb 13, 2009 at 6:06 AM, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> On Fri, Feb 13, 2009 at 11:55:06AM +0100, Uli Luckas wrote:
>> On Friday, 13. February 2009, Matthew Garrett wrote:
>> > I dislike the kernel-side use of wakelocks. They're basically equivalent
>> > to a device returning -EBUSY during the suspend phase, which is
>> > something that can be done without any kernel modifications.
>> That's absouletely wrong. With wake locks, you are in a pre suspend state and
>> stay there until all wakelocks are released. Then you go to sleep.
>>
>> With -EBUSY the kernel gives up on suspend until some source triggers it
>> again. When exactly should suspend then be retried?
>
> Ok, so let's think about this differently. What we want is simply for
> drivers to be able to block an automatic suspend. For performance
> reasons we want to keep track of this state without calling into the
> entire driver tree. Now that the userspace API can automatically clean
> up after itself, why is this not just a simple counter? Kernel API would
> be something like:
>
> (input arrives)
> inhibit_suspend();
> (input queue is emptied)
> uninhibit_suspend();

My objections to a global reference count are the same as before.
There is no accountability and no timeout support. I also prefer the
api to each driver to be a switch and not a reference count. I
understand the objections to using timeouts, but in practice we need
them today. If we move the timeout support to each driver that needs
it, it does not only make the drivers more complex, but we also loose
the ability to skip the timers that will not trigger suspend.

I even use a wakelock with a timeout internally to deal with the case
where a legacy driver return -EBUSY from its suspend hook. If I don't
use a timeout here, we either have to retry suspend immediately which
may never succeed if the thread that needs to run to clear the
condition is frozen again before it gets a chance to run, or we stop
trying to suspend indefinitely.

> perhaps using the device struct or something as a token for debug

I don't think adding the debug state to the device struct is much of
an improvement over using a wake_lock struct. You either have to
iterate over every device when extracting the debug information, or
you have to maintain similar lists to what the wakelock code uses now.
For the drivers point of view, it saves an init and destroy call but
it prevent using more than one lock per device or using it without a
device.

> purposes. Userland ABI would then be a single /dev/inhibit_suspend,
> with the counter being bumped each time an application opens it. It'll
> automatically be dropped if the application exits without cleaning up.

Whether the kernel api uses a single ref count or a list of wakelocks
does not dictate the user space api. The last patch sent I sent out
uses ioctls to lock and unlock a single wakelock per file descriptor.
Do anyone have a problem with that api?

> This seems simpler and also avoids any arguments about the naming
> scheme. What am I missing?

How does changing the name to inhibit_suspend() and
uninhibit_suspend() prevent arguments about the naming scheme? Calling
uninhibit_suspend once does not ensure that suspend is uninhibited.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13 23:36                             ` Arve Hjønnevåg
@ 2009-02-14  0:05                               ` Matthew Garrett
  2009-02-14  0:50                                 ` Arve Hjønnevåg
  0 siblings, 1 reply; 251+ messages in thread
From: Matthew Garrett @ 2009-02-14  0:05 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: swetland, linux-pm, Uli Luckas, ncunningham

On Fri, Feb 13, 2009 at 03:36:06PM -0800, Arve Hjønnevåg wrote:

> My objections to a global reference count are the same as before.
> There is no accountability and no timeout support. I also prefer the
> api to each driver to be a switch and not a reference count. I
> understand the objections to using timeouts, but in practice we need
> them today. If we move the timeout support to each driver that needs
> it, it does not only make the drivers more complex, but we also loose
> the ability to skip the timers that will not trigger suspend.

The only reason you've given for needing a timeout is that there are 
sections of the kernel that don't support wakelocks. The only reason 
there are sections of the kernel that don't support wakelocks is that 
people don't like the API. This argument is pretty circular. I think 
people would be much happier to have a deterministic kernel than a 
probabalistic one.

> I even use a wakelock with a timeout internally to deal with the case
> where a legacy driver return -EBUSY from its suspend hook. If I don't
> use a timeout here, we either have to retry suspend immediately which
> may never succeed if the thread that needs to run to clear the
> condition is frozen again before it gets a chance to run, or we stop
> trying to suspend indefinitely.

Well, yeah, that's another pretty solid argument in favor of killing the 
freezer...

> I don't think adding the debug state to the device struct is much of
> an improvement over using a wake_lock struct. You either have to
> iterate over every device when extracting the debug information, or
> you have to maintain similar lists to what the wakelock code uses now.
> For the drivers point of view, it saves an init and destroy call but
> it prevent using more than one lock per device or using it without a
> device.

Mm? I was thinking that in the debug case you'd replace the counter with 
a list containing the device structs, then simply dump the device name 
to your debug output.

> > purposes. Userland ABI would then be a single /dev/inhibit_suspend,
> > with the counter being bumped each time an application opens it. It'll
> > automatically be dropped if the application exits without cleaning up.
> 
> Whether the kernel api uses a single ref count or a list of wakelocks
> does not dictate the user space api. The last patch sent I sent out
> uses ioctls to lock and unlock a single wakelock per file descriptor.
> Do anyone have a problem with that api?

Requiring an ioctl makes it trickier to use from scripting languages, 
but beyond that I'm not too concerned.

> > This seems simpler and also avoids any arguments about the naming
> > scheme. What am I missing?
> 
> How does changing the name to inhibit_suspend() and
> uninhibit_suspend() prevent arguments about the naming scheme? Calling
> uninhibit_suspend once does not ensure that suspend is uninhibited.

If you're passing a device struct then I think it implies that that 
device is no linger inhibiting suspend.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-14  0:05                               ` Matthew Garrett
@ 2009-02-14  0:50                                 ` Arve Hjønnevåg
  2009-02-14  1:06                                   ` Matthew Garrett
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-14  0:50 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: swetland, linux-pm, Uli Luckas, ncunningham

On Fri, Feb 13, 2009 at 4:05 PM, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> On Fri, Feb 13, 2009 at 03:36:06PM -0800, Arve Hjønnevåg wrote:
>
>> My objections to a global reference count are the same as before.
>> There is no accountability and no timeout support. I also prefer the
>> api to each driver to be a switch and not a reference count. I
>> understand the objections to using timeouts, but in practice we need
>> them today. If we move the timeout support to each driver that needs
>> it, it does not only make the drivers more complex, but we also loose
>> the ability to skip the timers that will not trigger suspend.
>
> The only reason you've given for needing a timeout is that there are
> sections of the kernel that don't support wakelocks.

Or when not trusting userspace. In the last user space api, I also use
a timeout when a process dies with a wakelock locked.

> The only reason
> there are sections of the kernel that don't support wakelocks is that
> people don't like the API.

That is a pretty big leap. There is no wakelock api in the current
kernel. I think the absence of an api is a more plausible explanation
for it not being used than that people do not like the api.

> This argument is pretty circular.
> I think
> people would be much happier to have a deterministic kernel than a
> probabalistic one.

The current kernel only supports probabilistic mode. Wakelocks are a
step towards your deterministic kernel, not away form it. It is
possible to add a wakelock api that supports timeouts today, and
remove timeout support later if it is no longer needed.

>
>> I even use a wakelock with a timeout internally to deal with the case
>> where a legacy driver return -EBUSY from its suspend hook. If I don't
>> use a timeout here, we either have to retry suspend immediately which
>> may never succeed if the thread that needs to run to clear the
>> condition is frozen again before it gets a chance to run, or we stop
>> trying to suspend indefinitely.
>
> Well, yeah, that's another pretty solid argument in favor of killing the
> freezer...

Not freezing threads does not solve the problem. The thread could be
waiting for a driver that is suspended before the driver that is
preventing suspend.

>
>> I don't think adding the debug state to the device struct is much of
>> an improvement over using a wake_lock struct. You either have to
>> iterate over every device when extracting the debug information, or
>> you have to maintain similar lists to what the wakelock code uses now.
>> For the drivers point of view, it saves an init and destroy call but
>> it prevent using more than one lock per device or using it without a
>> device.
>
> Mm? I was thinking that in the debug case you'd replace the counter with
> a list containing the device structs, then simply dump the device name
> to your debug output.

We always use the debug case. I don't think a list of device struct is
better than a list of wakelocks.

>
>> > purposes. Userland ABI would then be a single /dev/inhibit_suspend,
>> > with the counter being bumped each time an application opens it. It'll
>> > automatically be dropped if the application exits without cleaning up.
>>
>> Whether the kernel api uses a single ref count or a list of wakelocks
>> does not dictate the user space api. The last patch sent I sent out
>> uses ioctls to lock and unlock a single wakelock per file descriptor.
>> Do anyone have a problem with that api?
>
> Requiring an ioctl makes it trickier to use from scripting languages,
> but beyond that I'm not too concerned.
>
>> > This seems simpler and also avoids any arguments about the naming
>> > scheme. What am I missing?
>>
>> How does changing the name to inhibit_suspend() and
>> uninhibit_suspend() prevent arguments about the naming scheme? Calling
>> uninhibit_suspend once does not ensure that suspend is uninhibited.
>
> If you're passing a device struct then I think it implies that that
> device is no linger inhibiting suspend.

How is passing the device struct to the api better than passing a
wake_lock struct?

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-14  0:50                                 ` Arve Hjønnevåg
@ 2009-02-14  1:06                                   ` Matthew Garrett
  2009-02-14  1:33                                     ` Arve Hjønnevåg
  0 siblings, 1 reply; 251+ messages in thread
From: Matthew Garrett @ 2009-02-14  1:06 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: swetland, linux-pm, Uli Luckas, ncunningham

On Fri, Feb 13, 2009 at 04:50:11PM -0800, Arve Hjønnevåg wrote:
> On Fri, Feb 13, 2009 at 4:05 PM, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> > The only reason you've given for needing a timeout is that there are
> > sections of the kernel that don't support wakelocks.
> 
> Or when not trusting userspace. In the last user space api, I also use
> a timeout when a process dies with a wakelock locked.

That's policy that's easily to implement in userspace.

> > The only reason
> > there are sections of the kernel that don't support wakelocks is that
> > people don't like the API.
> 
> That is a pretty big leap. There is no wakelock api in the current
> kernel. I think the absence of an api is a more plausible explanation
> for it not being used than that people do not like the api.

If an acceptable API gets merged then there's no reason not to quickly 
spread it to the sections of the kernel which would benefit.

> > Well, yeah, that's another pretty solid argument in favor of killing the
> > freezer...
> 
> Not freezing threads does not solve the problem. The thread could be
> waiting for a driver that is suspended before the driver that is
> preventing suspend.

I think it would be pretty acceptable to schedule a retry for the 
suspend if the count is still zero at that point.

> > Mm? I was thinking that in the debug case you'd replace the counter with
> > a list containing the device structs, then simply dump the device name
> > to your debug output.
> 
> We always use the debug case. I don't think a list of device struct is
> better than a list of wakelocks.

You may. Others will not. There's benefit in simplifying the non-debug 
case.

> > If you're passing a device struct then I think it implies that that
> > device is no linger inhibiting suspend.
> 
> How is passing the device struct to the api better than passing a
> wake_lock struct?

It's not hugely, but it seems like a neater description of what's going 
on. I don't really object to the use of a struct wait_lock - I think 
it's more complicated than necessary for the vast majority of cases, but 
that's not a significant issue. I think the name doesn't do a good job 
of indicating what's going on, and I think the timeout aspect is a 
misfeature.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-14  1:06                                   ` Matthew Garrett
@ 2009-02-14  1:33                                     ` Arve Hjønnevåg
  2009-02-14  1:49                                       ` Matthew Garrett
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-14  1:33 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: swetland, linux-pm, Uli Luckas, ncunningham

On Fri, Feb 13, 2009 at 5:06 PM, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> On Fri, Feb 13, 2009 at 04:50:11PM -0800, Arve Hjønnevåg wrote:
>> On Fri, Feb 13, 2009 at 4:05 PM, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
>> > The only reason you've given for needing a timeout is that there are
>> > sections of the kernel that don't support wakelocks.
>>
>> Or when not trusting userspace. In the last user space api, I also use
>> a timeout when a process dies with a wakelock locked.
>
> That's policy that's easily to implement in userspace.

How? When the process dies its wakelock is destroyed. With the old
sysfs interface, this was not a problem since the wakelocks were not
cleaned up. If we allow userspace wakelocks to be persistent, then
there is no limit on how many wakelocks userspace can create (which
was one of the objections against the sysfs interface).

>
>> > The only reason
>> > there are sections of the kernel that don't support wakelocks is that
>> > people don't like the API.
>>
>> That is a pretty big leap. There is no wakelock api in the current
>> kernel. I think the absence of an api is a more plausible explanation
>> for it not being used than that people do not like the api.
>
> If an acceptable API gets merged then there's no reason not to quickly
> spread it to the sections of the kernel which would benefit.

It is not trivial to add wakelocks to every section of the kernel that
may need to run.

>> > Well, yeah, that's another pretty solid argument in favor of killing the
>> > freezer...
>>
>> Not freezing threads does not solve the problem. The thread could be
>> waiting for a driver that is suspended before the driver that is
>> preventing suspend.
>
> I think it would be pretty acceptable to schedule a retry for the
> suspend if the count is still zero at that point.

I don't. If a driver returns -EBUSY the system will use 100% cpu until
either the driver stops returning -EBUSY, or someone else locks a
wakelock.

>
>> > Mm? I was thinking that in the debug case you'd replace the counter with
>> > a list containing the device structs, then simply dump the device name
>> > to your debug output.
>>
>> We always use the debug case. I don't think a list of device struct is
>> better than a list of wakelocks.
>
> You may. Others will not. There's benefit in simplifying the non-debug
> case.

A counter is not significantly simpler than a list if you remove all
the debug and timeout support:
lock:
  list_add
unlock:
  list_del
  if list_empty
    schedule suspend

>> > If you're passing a device struct then I think it implies that that
>> > device is no linger inhibiting suspend.
>>
>> How is passing the device struct to the api better than passing a
>> wake_lock struct?
>
> It's not hugely, but it seems like a neater description of what's going
> on. I don't really object to the use of a struct wait_lock - I think
> it's more complicated than necessary for the vast majority of cases, but
> that's not a significant issue.

You think the api is more complicated than necessary, or the
implementation? A lot of the complexity in the wakelock implementation
removes complexity from the drivers.

> I think the name doesn't do a good job
> of indicating what's going on, and I think the timeout aspect is a
> misfeature.

I understand your objection to using timeouts, but removing the use of
timeouts is not currently an option. If you accept that timeouts will
be used, supporting them in the wakelock code simplifies the drivers
and reduces overhead.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-14  1:33                                     ` Arve Hjønnevåg
@ 2009-02-14  1:49                                       ` Matthew Garrett
  2009-02-14  5:51                                         ` Arve Hjønnevåg
  0 siblings, 1 reply; 251+ messages in thread
From: Matthew Garrett @ 2009-02-14  1:49 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: swetland, linux-pm, Uli Luckas, ncunningham

On Fri, Feb 13, 2009 at 05:33:35PM -0800, Arve Hjønnevåg wrote:
> On Fri, Feb 13, 2009 at 5:06 PM, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> > On Fri, Feb 13, 2009 at 04:50:11PM -0800, Arve Hjønnevåg wrote:
> >> Or when not trusting userspace. In the last user space api, I also use
> >> a timeout when a process dies with a wakelock locked.
> >
> > That's policy that's easily to implement in userspace.
> 
> How? When the process dies its wakelock is destroyed. With the old
> sysfs interface, this was not a problem since the wakelocks were not
> cleaned up. If we allow userspace wakelocks to be persistent, then
> there is no limit on how many wakelocks userspace can create (which
> was one of the objections against the sysfs interface).

Like I suggested before, just multiplex them through a single daemon in 
userspace. That lets you tie your policy into your platform specifics. 
You get to do things like keep the lock until whatever process restarts 
dead system components indicates that your input process is running 
again, for instance.

> >> That is a pretty big leap. There is no wakelock api in the current
> >> kernel. I think the absence of an api is a more plausible explanation
> >> for it not being used than that people do not like the api.
> >
> > If an acceptable API gets merged then there's no reason not to quickly
> > spread it to the sections of the kernel which would benefit.
> 
> It is not trivial to add wakelocks to every section of the kernel that
> may need to run.

Doing things right is often harder, yes :)

> > I think it would be pretty acceptable to schedule a retry for the
> > suspend if the count is still zero at that point.
> 
> I don't. If a driver returns -EBUSY the system will use 100% cpu until
> either the driver stops returning -EBUSY, or someone else locks a
> wakelock.

The retry doesn't have to be immediate. Yes, this is something of a 
hypocritical argument given everything else I've had to say about 
timeouts, but working out why a driver's preventing a suspend is 
probably a Hard Problem. I don't think this single case is enough to add 
it to the entire API.

> >> We always use the debug case. I don't think a list of device struct is
> >> better than a list of wakelocks.
> >
> > You may. Others will not. There's benefit in simplifying the non-debug
> > case.
> 
> A counter is not significantly simpler than a list if you remove all
> the debug and timeout support:
> lock:
>   list_add
> unlock:
>   list_del
>   if list_empty
>     schedule suspend

Remember that for things like IDE we probably need to have locks in the 
fast path. An atomic_inc is a lot cheaper than a spinlock protected 
list_add.

> > I think the name doesn't do a good job
> > of indicating what's going on, and I think the timeout aspect is a
> > misfeature.
> 
> I understand your objection to using timeouts, but removing the use of
> timeouts is not currently an option. If you accept that timeouts will
> be used, supporting them in the wakelock code simplifies the drivers
> and reduces overhead.

Why is it not an option?

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-14  1:49                                       ` Matthew Garrett
@ 2009-02-14  5:51                                         ` Arve Hjønnevåg
  2009-02-14 20:44                                           ` Matthew Garrett
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-14  5:51 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: swetland, linux-pm, Uli Luckas, ncunningham

On Fri, Feb 13, 2009 at 5:49 PM, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> On Fri, Feb 13, 2009 at 05:33:35PM -0800, Arve Hjønnevåg wrote:
>> On Fri, Feb 13, 2009 at 5:06 PM, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
>> > On Fri, Feb 13, 2009 at 04:50:11PM -0800, Arve Hjønnevåg wrote:
>> >> Or when not trusting userspace. In the last user space api, I also use
>> >> a timeout when a process dies with a wakelock locked.
>> >
>> > That's policy that's easily to implement in userspace.
>>
>> How? When the process dies its wakelock is destroyed. With the old
>> sysfs interface, this was not a problem since the wakelocks were not
>> cleaned up. If we allow userspace wakelocks to be persistent, then
>> there is no limit on how many wakelocks userspace can create (which
>> was one of the objections against the sysfs interface).
>
> Like I suggested before, just multiplex them through a single daemon in
> userspace. That lets you tie your policy into your platform specifics.
> You get to do things like keep the lock until whatever process restarts
> dead system components indicates that your input process is running
> again, for instance.

OK, so you want a single daemon in userspace (init?) to handle process
restarting and wakelocks.

>> >> That is a pretty big leap. There is no wakelock api in the current
>> >> kernel. I think the absence of an api is a more plausible explanation
>> >> for it not being used than that people do not like the api.
>> >
>> > If an acceptable API gets merged then there's no reason not to quickly
>> > spread it to the sections of the kernel which would benefit.
>>
>> It is not trivial to add wakelocks to every section of the kernel that
>> may need to run.
>
> Doing things right is often harder, yes :)
>
>> > I think it would be pretty acceptable to schedule a retry for the
>> > suspend if the count is still zero at that point.
>>
>> I don't. If a driver returns -EBUSY the system will use 100% cpu until
>> either the driver stops returning -EBUSY, or someone else locks a
>> wakelock.
>
> The retry doesn't have to be immediate. Yes, this is something of a
> hypocritical argument given everything else I've had to say about
> timeouts, but working out why a driver's preventing a suspend is
> probably a Hard Problem. I don't think this single case is enough to add
> it to the entire API.

It is not a single case. Having wakelocks with timeout support makes
it trivial to work around the problem.

>
>> >> We always use the debug case. I don't think a list of device struct is
>> >> better than a list of wakelocks.
>> >
>> > You may. Others will not. There's benefit in simplifying the non-debug
>> > case.
>>
>> A counter is not significantly simpler than a list if you remove all
>> the debug and timeout support:
>> lock:
>>   list_add
>> unlock:
>>   list_del
>>   if list_empty
>>     schedule suspend
>
> Remember that for things like IDE we probably need to have locks in the
> fast path. An atomic_inc is a lot cheaper than a spinlock protected
> list_add.

The slow path for spinlocks and atomic operations are about the same.
On an smp arm v6 we have:

static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
	unsigned long tmp;

	__asm__ __volatile__(
"1:	ldrex	%0, [%1]\n"
"	teq	%0, #0\n"
#ifdef CONFIG_CPU_32v6K
"	wfene\n"
#endif
"	strexeq	%0, %2, [%1]\n"
"	teqeq	%0, #0\n"
"	bne	1b"
	: "=&r" (tmp)
	: "r" (&lock->lock), "r" (1)
	: "cc");

	smp_mb();
}


and:

static inline int atomic_add_return(int i, atomic_t *v)
{
	unsigned long tmp;
	int result;

	__asm__ __volatile__("@ atomic_add_return\n"
"1:	ldrex	%0, [%2]\n"
"	add	%0, %0, %3\n"
"	strex	%1, %0, [%2]\n"
"	teq	%1, #0\n"
"	bne	1b"
	: "=&r" (result), "=&r" (tmp)
	: "r" (&v->counter), "Ir" (i)
	: "cc");

	return result;
}



>
>> > I think the name doesn't do a good job
>> > of indicating what's going on, and I think the timeout aspect is a
>> > misfeature.
>>
>> I understand your objection to using timeouts, but removing the use of
>> timeouts is not currently an option. If you accept that timeouts will
>> be used, supporting them in the wakelock code simplifies the drivers
>> and reduces overhead.
>
> Why is it not an option?

I think we have covered this.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-14  5:51                                         ` Arve Hjønnevåg
@ 2009-02-14 20:44                                           ` Matthew Garrett
  0 siblings, 0 replies; 251+ messages in thread
From: Matthew Garrett @ 2009-02-14 20:44 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: swetland, linux-pm, Uli Luckas, ncunningham

On Fri, Feb 13, 2009 at 09:51:22PM -0800, Arve Hjønnevåg wrote:
> On Fri, Feb 13, 2009 at 5:49 PM, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> > Like I suggested before, just multiplex them through a single daemon in
> > userspace. That lets you tie your policy into your platform specifics.
> > You get to do things like keep the lock until whatever process restarts
> > dead system components indicates that your input process is running
> > again, for instance.
> 
> OK, so you want a single daemon in userspace (init?) to handle process
> restarting and wakelocks.

That would be one way of doing it, but it would also be fine to have 
some sort of IPC between multiple daemons.

> > The retry doesn't have to be immediate. Yes, this is something of a
> > hypocritical argument given everything else I've had to say about
> > timeouts, but working out why a driver's preventing a suspend is
> > probably a Hard Problem. I don't think this single case is enough to add
> > it to the entire API.
> 
> It is not a single case. Having wakelocks with timeout support makes
> it trivial to work around the problem.

You're not describing these cases. So far we've got "We need timeouts 
because we haven't added locking everywhere that it's needed in the 
kernel" and "We need timeouts because we want to poll in the case of a 
failed suspend". I don't think these are convincing reasons - the first 
should be fixed before merging the code and the second is a hack to 
begin with. Getting -EBUSY and then setting a wakelock with a timeout to 
trigger a resuspend would be more cleanly implemented by scheduling a 
timeout to re-trigger the attempt.

> > Remember that for things like IDE we probably need to have locks in the
> > fast path. An atomic_inc is a lot cheaper than a spinlock protected
> > list_add.
> 
> The slow path for spinlocks and atomic operations are about the same.
> On an smp arm v6 we have:

On x86 an uncontended spin_lock()/spin_unlock() cycle appears to be an 
order of magnitude slower than an atomic_inc. How much this matters 
probably depends on how frequently you think these locks will be taken 
and what the probability of them being contended is.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13  1:10                       ` Matthew Garrett
                                           ` (2 preceding siblings ...)
  2009-02-13 10:55                         ` Uli Luckas
@ 2009-02-26 15:04                         ` Pavel Machek
  2009-02-26 21:11                           ` Arve Hjønnevåg
  3 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-26 15:04 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: swetland, ncunningham, u.luckas, linux-pm

Hi!

> > It is discouraging to hear comments like "we have been talking about for years something else" yet nothing exists or is in open development. Things can evolve in place.
> 
> This is userlad-visible ABI. We can't evolve it in place - we need to 
> get it right before merging it, otherwise we need to carry on 
> maintaining code for an extended period of time in order to ensure that 
> there's no userland code that depends on it.

Plus... sleepy patches showed that autosuspend can be done *without*
new userland ABIs.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-26 15:04                         ` Pavel Machek
@ 2009-02-26 21:11                           ` Arve Hjønnevåg
  2009-02-26 21:36                             ` Pavel Machek
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-26 21:11 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, linux-pm, swetland

On Thu, Feb 26, 2009 at 7:04 AM, Pavel Machek <pavel@ucw.cz> wrote:
> Hi!
>
>> > It is discouraging to hear comments like "we have been talking about for years something else" yet nothing exists or is in open development. Things can evolve in place.
>>
>> This is userlad-visible ABI. We can't evolve it in place - we need to
>> get it right before merging it, otherwise we need to carry on
>> maintaining code for an extended period of time in order to ensure that
>> there's no userland code that depends on it.
>
> Plus... sleepy patches showed that autosuspend can be done *without*
> new userland ABIs.

As far as I can tell the sleepy patches tries to enter suspend if the
system is idle. If you plan to wake back up for the first timer, then
the end result of this is the same as what we get by entering the low
power state from arch_idle in the msm platform. Due to the frequent
wakeups, the power use is higher than our suspend state. If you don't
wake up on the first timer, you need something like the wakelock api
so apps specify that they need to run even if they were inactive for 3
seconds.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-26 21:11                           ` Arve Hjønnevåg
@ 2009-02-26 21:36                             ` Pavel Machek
  2009-02-27  0:16                               ` Arve Hjønnevåg
  0 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-26 21:36 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, linux-pm, swetland

On Thu 2009-02-26 13:11:05, Arve Hj?nnev?g wrote:
> On Thu, Feb 26, 2009 at 7:04 AM, Pavel Machek <pavel@ucw.cz> wrote:
> > Hi!
> >
> >> > It is discouraging to hear comments like "we have been talking about for years something else" yet nothing exists or is in open development. Things can evolve in place.
> >>
> >> This is userlad-visible ABI. We can't evolve it in place - we need to
> >> get it right before merging it, otherwise we need to carry on
> >> maintaining code for an extended period of time in order to ensure that
> >> there's no userland code that depends on it.
> >
> > Plus... sleepy patches showed that autosuspend can be done *without*
> > new userland ABIs.
> 
> As far as I can tell the sleepy patches tries to enter suspend if the
> system is idle. If you plan to wake back up for the first timer, then
> the end result of this is the same as what we get by entering the low
> power state from arch_idle in the msm platform. Due to the frequent
> wakeups, the power use is higher than our suspend state. If you don't
> wake up on the first timer, you need something like the wakelock api
> so apps specify that they need to run even if they were inactive for 3
> seconds.

You understand it right... it wakes up on first event. So you
eliminate all the timers that fire too often... and fix userspace if
neccessary.

Given that your 3rd party apps are written in java, you should have
enough control over them.

What in-kernel timers are causing problems for you? For how long can
Android sleep?
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-26 21:36                             ` Pavel Machek
@ 2009-02-27  0:16                               ` Arve Hjønnevåg
  2009-02-27  9:56                                 ` Pavel Machek
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-27  0:16 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, linux-pm, swetland

On Thu, Feb 26, 2009 at 1:36 PM, Pavel Machek <pavel@ucw.cz> wrote:
> On Thu 2009-02-26 13:11:05, Arve Hj?nnev?g wrote:
>> On Thu, Feb 26, 2009 at 7:04 AM, Pavel Machek <pavel@ucw.cz> wrote:
>> > Hi!
>> >
>> >> > It is discouraging to hear comments like "we have been talking about for years something else" yet nothing exists or is in open development. Things can evolve in place.
>> >>
>> >> This is userlad-visible ABI. We can't evolve it in place - we need to
>> >> get it right before merging it, otherwise we need to carry on
>> >> maintaining code for an extended period of time in order to ensure that
>> >> there's no userland code that depends on it.
>> >
>> > Plus... sleepy patches showed that autosuspend can be done *without*
>> > new userland ABIs.
>>
>> As far as I can tell the sleepy patches tries to enter suspend if the
>> system is idle. If you plan to wake back up for the first timer, then
>> the end result of this is the same as what we get by entering the low
>> power state from arch_idle in the msm platform. Due to the frequent
>> wakeups, the power use is higher than our suspend state. If you don't
>> wake up on the first timer, you need something like the wakelock api
>> so apps specify that they need to run even if they were inactive for 3
>> seconds.
>
> You understand it right... it wakes up on first event. So you
> eliminate all the timers that fire too often... and fix userspace if
> neccessary.
>
> Given that your 3rd party apps are written in java, you should have
> enough control over them.

How does the language the apps are written in affect this problem? Are
you saying that java apps should not be allowed to run every second?

> What in-kernel timers are causing problems for you?

I don't know for sure, but last time I checked, the the network stack
woke up every second. /proc/timer_list shows tick_sched_timer always
running in the next second.

> For how long can Android sleep?

>From idle, about a second. From suspend, minutes with the radio on, an
hour (msm limitation) with the radio off.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-27  0:16                               ` Arve Hjønnevåg
@ 2009-02-27  9:56                                 ` Pavel Machek
  2009-02-28  3:20                                   ` Arve Hjønnevåg
  0 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-27  9:56 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: ncunningham, u.luckas, linux-pm, swetland

Hi!

> >> As far as I can tell the sleepy patches tries to enter suspend if the
> >> system is idle. If you plan to wake back up for the first timer, then
> >> the end result of this is the same as what we get by entering the low
> >> power state from arch_idle in the msm platform. Due to the frequent
> >> wakeups, the power use is higher than our suspend state. If you don't
> >> wake up on the first timer, you need something like the wakelock api
> >> so apps specify that they need to run even if they were inactive for 3
> >> seconds.
> >
> > You understand it right... it wakes up on first event. So you
> > eliminate all the timers that fire too often... and fix userspace if
> > neccessary.
> >
> > Given that your 3rd party apps are written in java, you should have
> > enough control over them.
> 
> How does the language the apps are written in affect this problem? Are
> you saying that java apps should not be allowed to run every second?

I'm trying to say that you have pretty good control over java apps. So
you could for example make them call modified select with sloppiness,
or make them set their own sloppiness etc...

> > What in-kernel timers are causing problems for you?
> 
> I don't know for sure, but last time I checked, the the network stack
> woke up every second. /proc/timer_list shows tick_sched_timer always
> running in the next second.

I went through those in minimal system, and was able to mostly solve
that. Can we simply get network stack (etc) fixed?
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-13 16:49                             ` Uli Luckas
  2009-02-13 17:09                               ` Matthew Garrett
@ 2009-02-27 13:18                               ` Pavel Machek
  2009-02-27 14:07                                 ` Uli Luckas
  1 sibling, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-27 13:18 UTC (permalink / raw)
  To: Uli Luckas; +Cc: swetland, linux-pm, ncunningham

On Fri 2009-02-13 17:49:57, Uli Luckas wrote:
> On Friday, 13. February 2009, Matthew Garrett wrote:
> > Userland ABI would then be a single /dev/inhibit_suspend,
> > with the counter being bumped each time an application opens it. It'll
> > automatically be dropped if the application exits without cleaning up.
> >
> > This seems simpler and also avoids any arguments about the naming
> > scheme. What am I missing?
> Opening and closing an fd sounds like a lot of overhead. Taking and releasing 
> locks if going to be a called with very highg frequency. I'd go for an ioctl.

Ehm?

And introduce nasty interface, and probably slower too since open() is
time-critical and ioctl() is not? Or do you have benchmarks?
								Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-27 13:18                               ` Pavel Machek
@ 2009-02-27 14:07                                 ` Uli Luckas
  2009-02-27 20:32                                   ` Pavel Machek
  0 siblings, 1 reply; 251+ messages in thread
From: Uli Luckas @ 2009-02-27 14:07 UTC (permalink / raw)
  To: Pavel Machek; +Cc: swetland, linux-pm, ncunningham


[-- Attachment #1.1: Type: text/plain, Size: 1387 bytes --]

On Friday, 27. February 2009, Pavel Machek wrote:
> On Fri 2009-02-13 17:49:57, Uli Luckas wrote:
> > On Friday, 13. February 2009, Matthew Garrett wrote:
> > > Userland ABI would then be a single /dev/inhibit_suspend,
> > > with the counter being bumped each time an application opens it. It'll
> > > automatically be dropped if the application exits without cleaning up.
> > >
> > > This seems simpler and also avoids any arguments about the naming
> > > scheme. What am I missing?
> >
> > Opening and closing an fd sounds like a lot of overhead. Taking and
> > releasing locks if going to be a called with very highg frequency. I'd go
> > for an ioctl.
>
> Ehm?
>
> And introduce nasty interface, and probably slower too since open() is
> time-critical and ioctl() is not? Or do you have benchmarks?
> 								Pavel

No, just specualting as open() needs to do a directory lookup. It also needs 
to do book keeping. I'd be surprised if open was faster then ioctl.

On the otherhand if you consider ioctl nasty, maybe write() is an option?

Uli

-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

[-- Attachment #1.2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-27 14:07                                 ` Uli Luckas
@ 2009-02-27 20:32                                   ` Pavel Machek
  2009-03-02 13:53                                     ` Uli Luckas
  0 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-27 20:32 UTC (permalink / raw)
  To: Uli Luckas; +Cc: swetland, linux-pm, ncunningham

On Fri 2009-02-27 15:07:14, Uli Luckas wrote:
> On Friday, 27. February 2009, Pavel Machek wrote:
> > On Fri 2009-02-13 17:49:57, Uli Luckas wrote:
> > > On Friday, 13. February 2009, Matthew Garrett wrote:
> > > > Userland ABI would then be a single /dev/inhibit_suspend,
> > > > with the counter being bumped each time an application opens it. It'll
> > > > automatically be dropped if the application exits without cleaning up.
> > > >
> > > > This seems simpler and also avoids any arguments about the naming
> > > > scheme. What am I missing?
> > >
> > > Opening and closing an fd sounds like a lot of overhead. Taking and
> > > releasing locks if going to be a called with very highg frequency. I'd go
> > > for an ioctl.
> >
> > Ehm?
> >
> > And introduce nasty interface, and probably slower too since open() is
> > time-critical and ioctl() is not? Or do you have benchmarks?
> 
> No, just specualting as open() needs to do a directory lookup. It also needs 
> to do book keeping. I'd be surprised if open was faster then ioctl.

Unless you measure how much slower it is...

> On the otherhand if you consider ioctl nasty, maybe write() is an option?

You want sleepvetos to be automatically unlocked/freed on close and
process exit/kill, so neither write nor ioctl is the right interface.


-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-27  9:56                                 ` Pavel Machek
@ 2009-02-28  3:20                                   ` Arve Hjønnevåg
  0 siblings, 0 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-28  3:20 UTC (permalink / raw)
  To: Pavel Machek; +Cc: ncunningham, u.luckas, linux-pm, swetland

On Fri, Feb 27, 2009 at 1:56 AM, Pavel Machek <pavel@ucw.cz> wrote:
> Hi!
>
>> >> As far as I can tell the sleepy patches tries to enter suspend if the
>> >> system is idle. If you plan to wake back up for the first timer, then
>> >> the end result of this is the same as what we get by entering the low
>> >> power state from arch_idle in the msm platform. Due to the frequent
>> >> wakeups, the power use is higher than our suspend state. If you don't
>> >> wake up on the first timer, you need something like the wakelock api
>> >> so apps specify that they need to run even if they were inactive for 3
>> >> seconds.
>> >
>> > You understand it right... it wakes up on first event. So you
>> > eliminate all the timers that fire too often... and fix userspace if
>> > neccessary.
>> >
>> > Given that your 3rd party apps are written in java, you should have
>> > enough control over them.
>>
>> How does the language the apps are written in affect this problem? Are
>> you saying that java apps should not be allowed to run every second?
>
> I'm trying to say that you have pretty good control over java apps. So

I'm trying to say that we do not.

> you could for example make them call modified select with sloppiness,
> or make them set their own sloppiness etc...
>
>> > What in-kernel timers are causing problems for you?
>>
>> I don't know for sure, but last time I checked, the the network stack
>> woke up every second. /proc/timer_list shows tick_sched_timer always
>> running in the next second.
>
> I went through those in minimal system, and was able to mostly solve
> that. Can we simply get network stack (etc) fixed?

If you have fixes to eliminate polling in the network stack, please
submit them (unless you already have) as this would benefit every
system. Even if you eliminate all polling in the kernel, and the
platform supports the same low power state from idle, I still think
suspend is a useful way to pause the entire system when it does not
need to run.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-02-27 20:32                                   ` Pavel Machek
@ 2009-03-02 13:53                                     ` Uli Luckas
  2009-03-03 14:02                                       ` Pavel Machek
  0 siblings, 1 reply; 251+ messages in thread
From: Uli Luckas @ 2009-03-02 13:53 UTC (permalink / raw)
  To: Pavel Machek; +Cc: swetland, linux-pm, ncunningham

On Friday, 27. February 2009, Pavel Machek wrote:
> On Fri 2009-02-27 15:07:14, Uli Luckas wrote:
> > On Friday, 27. February 2009, Pavel Machek wrote:
> > > On Fri 2009-02-13 17:49:57, Uli Luckas wrote:
> > > > On Friday, 13. February 2009, Matthew Garrett wrote:
> > > > > Userland ABI would then be a single /dev/inhibit_suspend,
> > > > > with the counter being bumped each time an application opens it.
> > > > > It'll automatically be dropped if the application exits without
> > > > > cleaning up.
> > > > >
> > > > > This seems simpler and also avoids any arguments about the naming
> > > > > scheme. What am I missing?
> > > >
> > > > Opening and closing an fd sounds like a lot of overhead. Taking and
> > > > releasing locks if going to be a called with very highg frequency.
> > > > I'd go for an ioctl.
> > >
> > > Ehm?
> > >
> > > And introduce nasty interface, and probably slower too since open() is
> > > time-critical and ioctl() is not? Or do you have benchmarks?
> >
> > No, just specualting as open() needs to do a directory lookup. It also
> > needs to do book keeping. I'd be surprised if open was faster then ioctl.
>
> Unless you measure how much slower it is...
>
OK. Opening /dev/null 100000 times readonly takes 365 ms on my machine. 
Opening it once and then, 100000 times writing 1 byte takes 32 ms.
Why exactly did you think I had to provide numbers???

> > On the otherhand if you consider ioctl nasty, maybe write() is an option?
>
> You want sleepvetos to be automatically unlocked/freed on close and
> process exit/kill, so neither write nor ioctl is the right interface.
An application opens a device node and then writes 1s to take the lock and 0s 
to release it.
Why does that make it impossible to auto-release the lock on close?

Uli


-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-03-02 13:53                                     ` Uli Luckas
@ 2009-03-03 14:02                                       ` Pavel Machek
  2009-03-04 13:41                                         ` Uli Luckas
  2009-03-04 14:00                                         ` Uli Luckas
  0 siblings, 2 replies; 251+ messages in thread
From: Pavel Machek @ 2009-03-03 14:02 UTC (permalink / raw)
  To: Uli Luckas; +Cc: swetland, linux-pm, ncunningham

Hi!

> > > > And introduce nasty interface, and probably slower too since open() is
> > > > time-critical and ioctl() is not? Or do you have benchmarks?
> > >
> > > No, just specualting as open() needs to do a directory lookup. It also
> > > needs to do book keeping. I'd be surprised if open was faster then ioctl.
> >
> > Unless you measure how much slower it is...
> >
> OK. Opening /dev/null 100000 times readonly takes 365 ms on my machine. 
> Opening it once and then, 100000 times writing 1 byte takes 32 ms.
> Why exactly did you think I had to provide numbers???

Arve said:

> >> I just checked my phone, and over a 24 hour awake time (370 hours
> >> uptime) period, it acquired about 5 million wakelocks (mostly for
> >> input events). If these were cache hits, and took as long as my
> >> benchmark did, that accounts for 20 seconds of overhead (0.023%
> >> of
> >> awake, 0.1% of not-idle (5.5h).

Ok. 20seconds vs. 200 seconds seems interesting.

OTOH... Android seems to do IPC for wakelock manipulation, and that's
way higher overhead than open() syscall, so perhaps it is not that
critical?

Hmm ...given that original interface was "open /sys file, write,
close", I can't believe wakelocks are so critical that they are worth
ugly interface.

> > > On the otherhand if you consider ioctl nasty, maybe write() is an option?
> >
> > You want sleepvetos to be automatically unlocked/freed on close and
> > process exit/kill, so neither write nor ioctl is the right interface.
> An application opens a device node and then writes 1s to take the lock and 0s 
> to release it.

For example doing binary 0/1 writes from shell is hard... 
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-03-03 14:02                                       ` Pavel Machek
@ 2009-03-04 13:41                                         ` Uli Luckas
  2009-03-04 14:00                                         ` Uli Luckas
  1 sibling, 0 replies; 251+ messages in thread
From: Uli Luckas @ 2009-03-04 13:41 UTC (permalink / raw)
  To: Pavel Machek; +Cc: swetland, linux-pm, ncunningham

> > > > On the otherhand if you consider ioctl nasty, maybe write() is an
> > > > option?
> > >
> > > You want sleepvetos to be automatically unlocked/freed on close and
> > > process exit/kill, so neither write nor ioctl is the right interface.
> >
> > An application opens a device node and then writes 1s to take the lock
> > and 0s to release it.
>
> For example doing binary 0/1 writes from shell is hard...
> 									Pavel
If you have a strategy to hold an fd open from a shell, we can always agree on 
writing '0's and '1's to that fd.

Uli


-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-03-03 14:02                                       ` Pavel Machek
  2009-03-04 13:41                                         ` Uli Luckas
@ 2009-03-04 14:00                                         ` Uli Luckas
  2009-03-04 14:13                                           ` Pavel Machek
  1 sibling, 1 reply; 251+ messages in thread
From: Uli Luckas @ 2009-03-04 14:00 UTC (permalink / raw)
  To: Pavel Machek; +Cc: swetland, linux-pm, ncunningham


[-- Attachment #1.1: Type: text/plain, Size: 2047 bytes --]

On Tuesday, 3. March 2009, Pavel Machek wrote:
> Hi!
>
> > > > > And introduce nasty interface, and probably slower too since open()
> > > > > is time-critical and ioctl() is not? Or do you have benchmarks?
> > > >
> > > > No, just specualting as open() needs to do a directory lookup. It
> > > > also needs to do book keeping. I'd be surprised if open was faster
> > > > then ioctl.
> > >
> > > Unless you measure how much slower it is...
> >
> > OK. Opening /dev/null 100000 times readonly takes 365 ms on my machine.
> > Opening it once and then, 100000 times writing 1 byte takes 32 ms.
> > Why exactly did you think I had to provide numbers???
>
> Arve said:
> > >> I just checked my phone, and over a 24 hour awake time (370 hours
> > >> uptime) period, it acquired about 5 million wakelocks (mostly for
> > >> input events). If these were cache hits, and took as long as my
> > >> benchmark did, that accounts for 20 seconds of overhead (0.023%
> > >> of
> > >> awake, 0.1% of not-idle (5.5h).
>
> Ok. 20seconds vs. 200 seconds seems interesting.
>
> OTOH... Android seems to do IPC for wakelock manipulation, and that's
> way higher overhead than open() syscall, so perhaps it is not that
> critical?
>
Is IPC (writing a byte through a pipe/socket) really more expensive than 
open/close?
Even if it is, this brings us back to another thread of this topic. The reason 
for getting away with IPC might be that on the android platform the major 
part of wake locking is still done by timeouts. One thing that comes to mind 
here is network packets. You just don't want to open/close a fd for every 
network packet that you process. Neither for serial data, bluetooth 
packets, ...

Uli

-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

[-- Attachment #1.2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-03-04 14:00                                         ` Uli Luckas
@ 2009-03-04 14:13                                           ` Pavel Machek
  2009-03-04 14:34                                             ` Uli Luckas
  0 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-03-04 14:13 UTC (permalink / raw)
  To: Uli Luckas; +Cc: swetland, linux-pm, ncunningham

On Wed 2009-03-04 15:00:01, Uli Luckas wrote:
> On Tuesday, 3. March 2009, Pavel Machek wrote:
> > Hi!
> >
> > > > > > And introduce nasty interface, and probably slower too since open()
> > > > > > is time-critical and ioctl() is not? Or do you have benchmarks?
> > > > >
> > > > > No, just specualting as open() needs to do a directory lookup. It
> > > > > also needs to do book keeping. I'd be surprised if open was faster
> > > > > then ioctl.
> > > >
> > > > Unless you measure how much slower it is...
> > >
> > > OK. Opening /dev/null 100000 times readonly takes 365 ms on my machine.
> > > Opening it once and then, 100000 times writing 1 byte takes 32 ms.
> > > Why exactly did you think I had to provide numbers???
> >
> > Arve said:
> > > >> I just checked my phone, and over a 24 hour awake time (370 hours
> > > >> uptime) period, it acquired about 5 million wakelocks (mostly for
> > > >> input events). If these were cache hits, and took as long as my
> > > >> benchmark did, that accounts for 20 seconds of overhead (0.023%
> > > >> of
> > > >> awake, 0.1% of not-idle (5.5h).
> >
> > Ok. 20seconds vs. 200 seconds seems interesting.
> >
> > OTOH... Android seems to do IPC for wakelock manipulation, and that's
> > way higher overhead than open() syscall, so perhaps it is not that
> > critical?
> >
> Is IPC (writing a byte through a pipe/socket) really more expensive than 
> open/close?

Given that on current android it is "send a byte to another process
that does open/write/close"... yes that looks more expensive than
single open.

> here is network packets. You just don't want to open/close a fd for every 
> network packet that you process. Neither for serial data, bluetooth 
> packets, ...

You mix userland and kernel users.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-03-04 14:13                                           ` Pavel Machek
@ 2009-03-04 14:34                                             ` Uli Luckas
  2009-03-04 17:10                                               ` Pavel Machek
  0 siblings, 1 reply; 251+ messages in thread
From: Uli Luckas @ 2009-03-04 14:34 UTC (permalink / raw)
  To: Pavel Machek; +Cc: swetland, linux-pm, ncunningham

On Wednesday, 4. March 2009, Pavel Machek wrote:
> On Wed 2009-03-04 15:00:01, Uli Luckas wrote:
> > On Tuesday, 3. March 2009, Pavel Machek wrote:
> > > Hi!
> > >
> > > > > > > And introduce nasty interface, and probably slower too since
> > > > > > > open() is time-critical and ioctl() is not? Or do you have
> > > > > > > benchmarks?
> > > > > >
> > > > > > No, just specualting as open() needs to do a directory lookup. It
> > > > > > also needs to do book keeping. I'd be surprised if open was
> > > > > > faster then ioctl.
> > > > >
> > > > > Unless you measure how much slower it is...
> > > >
> > > > OK. Opening /dev/null 100000 times readonly takes 365 ms on my
> > > > machine. Opening it once and then, 100000 times writing 1 byte takes
> > > > 32 ms. Why exactly did you think I had to provide numbers???
> > >
> > > Arve said:
> > > > >> I just checked my phone, and over a 24 hour awake time (370 hours
> > > > >> uptime) period, it acquired about 5 million wakelocks (mostly for
> > > > >> input events). If these were cache hits, and took as long as my
> > > > >> benchmark did, that accounts for 20 seconds of overhead (0.023%
> > > > >> of
> > > > >> awake, 0.1% of not-idle (5.5h).
> > >
> > > Ok. 20seconds vs. 200 seconds seems interesting.
> > >
> > > OTOH... Android seems to do IPC for wakelock manipulation, and that's
> > > way higher overhead than open() syscall, so perhaps it is not that
> > > critical?
> >
> > Is IPC (writing a byte through a pipe/socket) really more expensive than
> > open/close?
>
> Given that on current android it is "send a byte to another process
> that does open/write/close"... yes that looks more expensive than
> single open.
>
OK. But that's fixable. And it probably has to be fixed when timed wake locks 
go away (see my other reply).

> > here is network packets. You just don't want to open/close a fd for every
> > network packet that you process. Neither for serial data, bluetooth
> > packets, ...
>
> You mix userland and kernel users.
> 									Pavel
No. I don't.
The idea of wake locks was to hand locks over from a driver's interrupt all 
the way to userspace. 
This is done in an interlocked way to ensure that the device does not suspend 
from the time of interrupt until userspace has handled the event that caused 
the interrupt (e.g. A modem sending "RING" on the serial line).
Basically, in a timerless wake lock implementation userspace has to take a 
wake lock every time select returns.

Uli


-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-03-04 14:34                                             ` Uli Luckas
@ 2009-03-04 17:10                                               ` Pavel Machek
  2009-03-05 17:42                                                 ` Uli Luckas
  0 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-03-04 17:10 UTC (permalink / raw)
  To: Uli Luckas; +Cc: swetland, linux-pm, ncunningham

Hi!

> > > here is network packets. You just don't want to open/close a fd for every
> > > network packet that you process. Neither for serial data, bluetooth
> > > packets, ...
> >
> > You mix userland and kernel users.

> No. I don't.
> The idea of wake locks was to hand locks over from a driver's interrupt all 
> the way to userspace. 
> This is done in an interlocked way to ensure that the device does not suspend 
> from the time of interrupt until userspace has handled the event that caused 
> the interrupt (e.g. A modem sending "RING" on the serial line).
> Basically, in a timerless wake lock implementation userspace has to take a 
> wake lock every time select returns.

Well... in case it is really performance critical, we may want new
syscalls.

Actually, given how deep change of semantics this is, new syscalls may
be good idea.

Or better yet eliminate polling from userspace apps and just avoid
suspending whenever userspace is running (like sleepy patches do).
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-03-04 17:10                                               ` Pavel Machek
@ 2009-03-05 17:42                                                 ` Uli Luckas
  2009-03-08  8:32                                                   ` Pavel Machek
  0 siblings, 1 reply; 251+ messages in thread
From: Uli Luckas @ 2009-03-05 17:42 UTC (permalink / raw)
  To: Pavel Machek; +Cc: swetland, linux-pm, ncunningham

On Wednesday, 4. March 2009, Pavel Machek wrote:
> Hi!
>
> > > > here is network packets. You just don't want to open/close a fd for
> > > > every network packet that you process. Neither for serial data,
> > > > bluetooth packets, ...
> > >
> > > You mix userland and kernel users.
> >
> > No. I don't.
> > The idea of wake locks was to hand locks over from a driver's interrupt
> > all the way to userspace.
> > This is done in an interlocked way to ensure that the device does not
> > suspend from the time of interrupt until userspace has handled the event
> > that caused the interrupt (e.g. A modem sending "RING" on the serial
> > line).
> > Basically, in a timerless wake lock implementation userspace has to take
> > a wake lock every time select returns.
>
> Well... in case it is really performance critical, we may want new
> syscalls.
>
> Actually, given how deep change of semantics this is, new syscalls may
> be good idea.
>
> Or better yet eliminate polling from userspace apps and just avoid
> suspending whenever userspace is running (like sleepy patches do).
> 									Pavel
I don't know the details of sleepy linux so I'd appreciate if someone can 
eluminate if the following scenarios could be handled efficiently with sleepy 
linux:
1) You wake up through RTC, read the battery, update the color of your 
   fancy 'battery good' LED and go back to sleep imediately. The real work
   takes milliseconds.
2) You send a request to the internet and go idle by selecting for an answer.
   You probably don't want to go to sleep as you know, the answer will be
   there shortly.

Uli

-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-03-05 17:42                                                 ` Uli Luckas
@ 2009-03-08  8:32                                                   ` Pavel Machek
  2009-03-08 12:34                                                     ` Alan Stern
  0 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-03-08  8:32 UTC (permalink / raw)
  To: Uli Luckas; +Cc: swetland, linux-pm, ncunningham

On Thu 2009-03-05 18:42:05, Uli Luckas wrote:
> On Wednesday, 4. March 2009, Pavel Machek wrote:
> > Hi!
> >
> > > > > here is network packets. You just don't want to open/close a fd for
> > > > > every network packet that you process. Neither for serial data,
> > > > > bluetooth packets, ...
> > > >
> > > > You mix userland and kernel users.
> > >
> > > No. I don't.
> > > The idea of wake locks was to hand locks over from a driver's interrupt
> > > all the way to userspace.
> > > This is done in an interlocked way to ensure that the device does not
> > > suspend from the time of interrupt until userspace has handled the event
> > > that caused the interrupt (e.g. A modem sending "RING" on the serial
> > > line).
> > > Basically, in a timerless wake lock implementation userspace has to take
> > > a wake lock every time select returns.
> >
> > Well... in case it is really performance critical, we may want new
> > syscalls.
> >
> > Actually, given how deep change of semantics this is, new syscalls may
> > be good idea.
> >
> > Or better yet eliminate polling from userspace apps and just avoid
> > suspending whenever userspace is running (like sleepy patches do).
> > 									Pavel
> I don't know the details of sleepy linux so I'd appreciate if someone can 
> eluminate if the following scenarios could be handled efficiently with sleepy 
> linux:
> 1) You wake up through RTC, read the battery, update the color of your 
>    fancy 'battery good' LED and go back to sleep imediately. The real work
>    takes milliseconds.

This should work.

> 2) You send a request to the internet and go idle by selecting for an answer.
>    You probably don't want to go to sleep as you know, the answer will be
>    there shortly.

Way to get this to work would be to keep the system woke up 300msec or
so after each network packet -- assuming that if one came another is
probably coming soon.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [PATCH 01/13] PM: Add wake lock api.
  2009-03-08  8:32                                                   ` Pavel Machek
@ 2009-03-08 12:34                                                     ` Alan Stern
  0 siblings, 0 replies; 251+ messages in thread
From: Alan Stern @ 2009-03-08 12:34 UTC (permalink / raw)
  To: Pavel Machek; +Cc: swetland, linux-pm, Uli Luckas, ncunningham

On Sun, 8 Mar 2009, Pavel Machek wrote:

> > I don't know the details of sleepy linux so I'd appreciate if someone can 
> > eluminate if the following scenarios could be handled efficiently with sleepy 
> > linux:
> > 1) You wake up through RTC, read the battery, update the color of your 
> >    fancy 'battery good' LED and go back to sleep imediately. The real work
> >    takes milliseconds.
> 
> This should work.
> 
> > 2) You send a request to the internet and go idle by selecting for an answer.
> >    You probably don't want to go to sleep as you know, the answer will be
> >    there shortly.
> 
> Way to get this to work would be to keep the system woke up 300msec or
> so after each network packet -- assuming that if one came another is
> probably coming soon.

That sounds like a perfect use for a suspend_blocker with a timeout!

Alan Stern

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-03  4:18                                               ` Arve Hjønnevåg
  2009-02-03 20:30                                                 ` Alan Stern
@ 2009-02-04 13:29                                                 ` Pavel Machek
  1 sibling, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-04 13:29 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: Brian Swetland, linux-pm, Uli Luckas, Nigel Cunningham


> > For example, if one process tries to start an auto-suspend, and at the
> > same time another process writes "mem" to /sys/power/state?  Then the
> > second process should take precedence and the system should go into
> > suspend.  When it wakes up again, the first process would still be
> > waiting for an auto-suspend to occur.  I suppose the details don't
> > matter much because it's not likely to crop up often.
> 
> I'll make a change to make any write to /sys/power/state disable
> wakelocks. I'll probably also add a config option to remove
> /sys/power/state.
> 
> Before I post another patch series I have a few questions:
> - Should I merge the wakelock and early-suspend api patches with their
> implementations? (I initially implemented the api on top of the old
> android_power driver, but we not longer use this)

I think so.

> - Once wakelocks are disabled by writing to /sys/power/state, is there
> any demand for re-enabling wakelock support?

I do not think wakelocks should be disabled. They should probably be
ignored for echo mem > state, but disabling them sounds wrong.

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-02 23:21                                             ` Arve Hjønnevåg
  2009-02-02 23:51                                               ` Nigel Cunningham
@ 2009-02-04 13:25                                               ` Pavel Machek
  1 sibling, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-04 13:25 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: Brian Swetland, Nigel Cunningham, Uli Luckas, linux-pm

Hi!

> <ncunningham@crca.org.au> wrote:
> > It sounds to me like all of this stuff is just power management of
> > individual devices, which should be done through the sysfs interface and
> > completely unrelated to /sys/power/state.
> 
> It is easier for us to add a hook to the individual drivers than to
> maintain a list of devices in user-space. Also, last time I checked,
> the only way to disable individual devices was through a deprecated
> interface. Is there a new way to do this?

No, but we need one, sooner or later. I'd say that implementing nice
device power management would be better than early-suspend hack.

> > That said, if suspend to ram is what they really want for 'auto-mem',
> > what you're suggesting sounds good to me.
> 
> Suspend gives us two advantages over idle. All threads are frozen
> which means that an app that is using too much cpu time no longer
> drains the battery. And, the monotonic clock stops.

SIGSTOP should be the right tool if some application uses too much
cycles...


-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-03  4:18                                               ` Arve Hjønnevåg
@ 2009-02-03 20:30                                                 ` Alan Stern
  2009-02-04 13:29                                                 ` Pavel Machek
  1 sibling, 0 replies; 251+ messages in thread
From: Alan Stern @ 2009-02-03 20:30 UTC (permalink / raw)
  To: Arve Hjønnevåg
  Cc: Brian Swetland, linux-pm, Uli Luckas, Nigel Cunningham

On Mon, 2 Feb 2009, Arve Hjønnevåg wrote:

> >> Also, what do you mean by a runtime PM interface?
> >
> > I'm making a distinction between system PM and runtime (also known as
> > dynamic) PM.  With system PM the entire system goes into a low-power
> > state -- that's what we mean when we talk about suspend or hibernation.
> > With runtime PM the system as a whole remains running while selected
> > devices are individually put into a low-power state.
> >
> > For example, right now Linux will put a USB host controller into a
> > low-power state if no USB devices are plugged into it.  This runtime PM
> > interface is described in Documentation/usb/power-management.txt.  You
> > might want to use some of those mechanisms for controlling your
> > devices.
> 
> OK, but I don't think this affects our use of wakelocks.

No, but it might very well affect your implementation of early-suspend.

> I'll make a change to make any write to /sys/power/state disable
> wakelocks. I'll probably also add a config option to remove
> /sys/power/state.
> 
> Before I post another patch series I have a few questions:
> - Should I merge the wakelock and early-suspend api patches with their
> implementations? (I initially implemented the api on top of the old
> android_power driver, but we not longer use this)

It depends how big the patches are.  If they're not too large, go ahead 
and merge the API patch with the implementation.  But if they're 
difficult to read because they are rather big, keep them separate.

> - Once wakelocks are disabled by writing to /sys/power/state, is there
> any demand for re-enabling wakelock support?

I don't know.  You might as well re-enable it as soon as the system 
resumes.

> - Are there any objections to using /sys/power/request_state to
> specify the state to enter when all wakelocks unlocked.

Okay with me.

Alan Stern

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-02 16:15                         ` Uli Luckas
  2009-02-02 16:35                           ` Alan Stern
@ 2009-02-03 20:15                           ` Pavel Machek
  1 sibling, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-03 20:15 UTC (permalink / raw)
  To: Uli Luckas; +Cc: swetland, linux-pm, Nigel Cunningham


> > The problem is that he's talking about making changes to a kernel that
> > will be installed in all sorts of machines, from phones all the way up
> > to supercomputers.  When you do this, you have to broaden your point of
> > view -- your code has to run correctly in all of these settings.
> >
> Well, it should not interfere with any of these settings. And I think it is 
> understood by now that we has to take back the semantic change of "echo mem 
> > /sys/power/state"
> 
> On the other hand, I think it is quite reasonable to have aditional suspend 
> mechanisms on a phone then you have on a super computer. Obviously you don't 
> want the supercomputer to suspend everytime nobody is watching :-)

Actually you'd like your supercomputer to turn on wake-on-lan then
sleep when noone is watching (and there are no pending jobs). 'green
datacenter' is popular buzzword ;-).

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-03  3:27                                             ` Alan Stern
@ 2009-02-03  4:18                                               ` Arve Hjønnevåg
  2009-02-03 20:30                                                 ` Alan Stern
  2009-02-04 13:29                                                 ` Pavel Machek
  0 siblings, 2 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-03  4:18 UTC (permalink / raw)
  To: Alan Stern; +Cc: Brian Swetland, linux-pm, Uli Luckas, Nigel Cunningham

On Mon, Feb 2, 2009 at 7:27 PM, Alan Stern <stern@rowland.harvard.edu> wrote:
> If you'd like a way for the kernel to communicate to userspace that the
> last wakelock has been unlocked, you could use a signal or a select.
> But the simplest way would be to make a process block on reading a
> sysfs file until the last wakelock is released.

I do not want the kernel to communicate to userspace that the last
wakelock has been unlocked, I want it to suspend right away. I was
answering your question about why the kernel needs to be involved. Yes
I could add a notification that tells user-space to suspend again, but
it would not offer any additional functionality over my current
solution.

>> Also, what do you mean by a runtime PM interface?
>
> I'm making a distinction between system PM and runtime (also known as
> dynamic) PM.  With system PM the entire system goes into a low-power
> state -- that's what we mean when we talk about suspend or hibernation.
> With runtime PM the system as a whole remains running while selected
> devices are individually put into a low-power state.
>
> For example, right now Linux will put a USB host controller into a
> low-power state if no USB devices are plugged into it.  This runtime PM
> interface is described in Documentation/usb/power-management.txt.  You
> might want to use some of those mechanisms for controlling your
> devices.

OK, but I don't think this affects our use of wakelocks.

> For example, if one process tries to start an auto-suspend, and at the
> same time another process writes "mem" to /sys/power/state?  Then the
> second process should take precedence and the system should go into
> suspend.  When it wakes up again, the first process would still be
> waiting for an auto-suspend to occur.  I suppose the details don't
> matter much because it's not likely to crop up often.

I'll make a change to make any write to /sys/power/state disable
wakelocks. I'll probably also add a config option to remove
/sys/power/state.

Before I post another patch series I have a few questions:
- Should I merge the wakelock and early-suspend api patches with their
implementations? (I initially implemented the api on top of the old
android_power driver, but we not longer use this)
- Once wakelocks are disabled by writing to /sys/power/state, is there
any demand for re-enabling wakelock support?
- Are there any objections to using /sys/power/request_state to
specify the state to enter when all wakelocks unlocked.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-02 23:10                                           ` Arve Hjønnevåg
@ 2009-02-03  3:27                                             ` Alan Stern
  2009-02-03  4:18                                               ` Arve Hjønnevåg
  0 siblings, 1 reply; 251+ messages in thread
From: Alan Stern @ 2009-02-03  3:27 UTC (permalink / raw)
  To: Arve Hjønnevåg
  Cc: Brian Swetland, linux-pm, Uli Luckas, Nigel Cunningham

On Mon, 2 Feb 2009, Arve Hjønnevåg wrote:

> On Mon, Feb 2, 2009 at 7:09 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
> > On Mon, 2 Feb 2009, Uli Luckas wrote:
> >> Except you always want early-suspend and auto-suspend at the same time. The
> >> idea is, if all display of system states is off (early-suspend), we can
> >> enable or disable the cpu at will (auto-suspend) because nobody will notice.
> >
> > Why should the kernel have to get involved?  Why can't userspace manage
> > both early-suspend and auto-suspend?
> 
> The kernel does not need to be involved in early-suspend. We use
> early-suspend as a simple way to shut down the framebuffer and some
> input devices.
> If by auto-suspend you mean suspend after user inactivity (usually
> after a number of seconds or minutes), then the kernel does not need
> to be involved, but if you mean suspending when all wakelocks are
> unlocked, the kernel needs to be involved to avoid delays. If the last
> wakelock to be unlocked is a kernel wakelock, then user-space would
> not know that it needs to re-attempt suspend.

I meant both: suspending after user inactivity when all wakelocks are 
unlocked.

If you'd like a way for the kernel to communicate to userspace that the
last wakelock has been unlocked, you could use a signal or a select.
But the simplest way would be to make a process block on reading a
sysfs file until the last wakelock is released.

> > That is, consider the following: Userspace initiates an early-suspend
> > by using a runtime PM interface to turn off the screen and some other
> > devices.  After a short time, if they are still off, then userspace can
> > initiate an auto-suspend by writing "auto-mem" to /sys/power/state.
> 
> Why do you want a delay?

I thought you wanted one.  If you don't then okay, don't use a delay.

> Also, what do you mean by a runtime PM interface?

I'm making a distinction between system PM and runtime (also known as 
dynamic) PM.  With system PM the entire system goes into a low-power 
state -- that's what we mean when we talk about suspend or hibernation.  
With runtime PM the system as a whole remains running while selected 
devices are individually put into a low-power state.

For example, right now Linux will put a USB host controller into a
low-power state if no USB devices are plugged into it.  This runtime PM
interface is described in Documentation/usb/power-management.txt.  You
might want to use some of those mechanisms for controlling your
devices.

> > All the kernel would need to know is the difference between
> > auto-suspend and normal suspend: one respects wakelocks and the other
> > doesn't.
> 
> If by normal suspend you mean what is supported in the kernel now,
> then OK. We can support existing userspace code by ignoring wakelocks.
> My intention was that you only enable the WAKELOCK config option when
> using it, but I agree that it is better to allow the kernel to be
> built with support for both modes.
> 
> What do you think should happen if user-space tries to use both interfaces?

For example, if one process tries to start an auto-suspend, and at the 
same time another process writes "mem" to /sys/power/state?  Then the 
second process should take precedence and the system should go into 
suspend.  When it wakes up again, the first process would still be 
waiting for an auto-suspend to occur.  I suppose the details don't 
matter much because it's not likely to crop up often.

Alan Stern

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-02 23:51                                               ` Nigel Cunningham
@ 2009-02-03  0:08                                                 ` Arve Hjønnevåg
  0 siblings, 0 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-03  0:08 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Brian Swetland, linux-pm, Uli Luckas

On Mon, Feb 2, 2009 at 3:51 PM, Nigel Cunningham
<ncunningham@crca.org.au> wrote:
>> It is easier for us to add a hook to the individual drivers than to
>> maintain a list of devices in user-space. Also, last time I checked,
>> the only way to disable individual devices was through a deprecated
>> interface. Is there a new way to do this?
>
> Not as far as I know, but I understood that we weren't focusing on what
> currently exists, but on what ought to exist to properly support what
> you're after, in a generic enough way to be useful to others as well.

Early-suspend was easier to add to the kernel, and easier for us to
use from user-space.

> Well, I'm imagining a state that is more than just idle - where, as you
> say, processes don't run until some sort of wakeup event occurs.

You are describing suspend.

>> Suspend gives us two advantages over idle. All threads are frozen
>> which means that an app that is using too much cpu time no longer
>> drains the battery. And, the monotonic clock stops.
>
> Do you want to leave any devices on while in this state? If not, okay -
> suspend to ram sounds right. If yes, I think you want to take
> leave /sys/power/disk alone and go along the lines of run-time power
> management instead.

I don't think leaving a device on should prevent us from using
suspend. Wakeup from suspend is already supported. If wakeup is
enabled for a device, it needs to be in a power state that can support
wakeup (whether this is its lowest power state or not).

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-02 23:21                                             ` Arve Hjønnevåg
@ 2009-02-02 23:51                                               ` Nigel Cunningham
  2009-02-03  0:08                                                 ` Arve Hjønnevåg
  2009-02-04 13:25                                               ` Pavel Machek
  1 sibling, 1 reply; 251+ messages in thread
From: Nigel Cunningham @ 2009-02-02 23:51 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: Brian Swetland, linux-pm, Uli Luckas

Hi.

On Mon, 2009-02-02 at 15:21 -0800, Arve Hjønnevåg wrote:
> On Mon, Feb 2, 2009 at 1:47 PM, Nigel Cunningham
> <ncunningham@crca.org.au> wrote:
> > It sounds to me like all of this stuff is just power management of
> > individual devices, which should be done through the sysfs interface and
> > completely unrelated to /sys/power/state.
> 
> It is easier for us to add a hook to the individual drivers than to
> maintain a list of devices in user-space. Also, last time I checked,
> the only way to disable individual devices was through a deprecated
> interface. Is there a new way to do this?

Not as far as I know, but I understood that we weren't focusing on what
currently exists, but on what ought to exist to properly support what
you're after, in a generic enough way to be useful to others as well.

> > I'm putting the talk about
> > suspending the CPU in this box too because it sounds like the desire is
> > to stop the CPU without necessarily suspending other devices such as
> > transmitters - sort of a CPU freq state where the frequency is 0.
> 
> Is this different from idle?

Well, I'm imagining a state that is more than just idle - where, as you
say, processes don't run until some sort of wakeup event occurs.

> > That said, if suspend to ram is what they really want for 'auto-mem',
> > what you're suggesting sounds good to me.
> 
> Suspend gives us two advantages over idle. All threads are frozen
> which means that an app that is using too much cpu time no longer
> drains the battery. And, the monotonic clock stops.

Do you want to leave any devices on while in this state? If not, okay -
suspend to ram sounds right. If yes, I think you want to take
leave /sys/power/disk alone and go along the lines of run-time power
management instead.

Regards,

Nigel

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-02 21:47                                           ` Nigel Cunningham
@ 2009-02-02 23:21                                             ` Arve Hjønnevåg
  2009-02-02 23:51                                               ` Nigel Cunningham
  2009-02-04 13:25                                               ` Pavel Machek
  0 siblings, 2 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-02 23:21 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: Brian Swetland, linux-pm, Uli Luckas

On Mon, Feb 2, 2009 at 1:47 PM, Nigel Cunningham
<ncunningham@crca.org.au> wrote:
> It sounds to me like all of this stuff is just power management of
> individual devices, which should be done through the sysfs interface and
> completely unrelated to /sys/power/state.

It is easier for us to add a hook to the individual drivers than to
maintain a list of devices in user-space. Also, last time I checked,
the only way to disable individual devices was through a deprecated
interface. Is there a new way to do this?

> I'm putting the talk about
> suspending the CPU in this box too because it sounds like the desire is
> to stop the CPU without necessarily suspending other devices such as
> transmitters - sort of a CPU freq state where the frequency is 0.

Is this different from idle?

> That said, if suspend to ram is what they really want for 'auto-mem',
> what you're suggesting sounds good to me.

Suspend gives us two advantages over idle. All threads are frozen
which means that an app that is using too much cpu time no longer
drains the battery. And, the monotonic clock stops.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-02 15:09                                         ` Alan Stern
  2009-02-02 16:24                                           ` Uli Luckas
  2009-02-02 21:47                                           ` Nigel Cunningham
@ 2009-02-02 23:10                                           ` Arve Hjønnevåg
  2009-02-03  3:27                                             ` Alan Stern
  2 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-02 23:10 UTC (permalink / raw)
  To: Alan Stern; +Cc: Brian Swetland, linux-pm, Uli Luckas, Nigel Cunningham

On Mon, Feb 2, 2009 at 7:09 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
> On Mon, 2 Feb 2009, Uli Luckas wrote:
>> Except you always want early-suspend and auto-suspend at the same time. The
>> idea is, if all display of system states is off (early-suspend), we can
>> enable or disable the cpu at will (auto-suspend) because nobody will notice.
>
> Why should the kernel have to get involved?  Why can't userspace manage
> both early-suspend and auto-suspend?

The kernel does not need to be involved in early-suspend. We use
early-suspend as a simple way to shut down the framebuffer and some
input devices.
If by auto-suspend you mean suspend after user inactivity (usually
after a number of seconds or minutes), then the kernel does not need
to be involved, but if you mean suspending when all wakelocks are
unlocked, the kernel needs to be involved to avoid delays. If the last
wakelock to be unlocked is a kernel wakelock, then user-space would
not know that it needs to re-attempt suspend.

> That is, consider the following: Userspace initiates an early-suspend
> by using a runtime PM interface to turn off the screen and some other
> devices.  After a short time, if they are still off, then userspace can
> initiate an auto-suspend by writing "auto-mem" to /sys/power/state.

Why do you want a delay?
Also, what do you mean by a runtime PM interface?

> All the kernel would need to know is the difference between
> auto-suspend and normal suspend: one respects wakelocks and the other
> doesn't.

If by normal suspend you mean what is supported in the kernel now,
then OK. We can support existing userspace code by ignoring wakelocks.
My intention was that you only enable the WAKELOCK config option when
using it, but I agree that it is better to allow the kernel to be
built with support for both modes.

What do you think should happen if user-space tries to use both interfaces?

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-02 15:09                                         ` Alan Stern
  2009-02-02 16:24                                           ` Uli Luckas
@ 2009-02-02 21:47                                           ` Nigel Cunningham
  2009-02-02 23:21                                             ` Arve Hjønnevåg
  2009-02-02 23:10                                           ` Arve Hjønnevåg
  2 siblings, 1 reply; 251+ messages in thread
From: Nigel Cunningham @ 2009-02-02 21:47 UTC (permalink / raw)
  To: Alan Stern; +Cc: Brian Swetland, linux-pm, Uli Luckas

Hi.

On Mon, 2009-02-02 at 10:09 -0500, Alan Stern wrote:
> On Mon, 2 Feb 2009, Uli Luckas wrote:
> 
> > On Sunday, 1. February 2009, Alan Stern wrote:
> > > Early-suspend seems to be a completely different matter.  In fact it
> > > isn't a suspend state at all, as far as I understand it.  It's more
> > > like what you get simply by doing a runtime suspend on some collection
> > > of devices.  I don't see that the kernel needs to treat it as a special
> > > state, and in might be possible to have a user program manage the whole
> > > thing -- provided the drivers in question implement runtime power
> > > management (as USB has done).
> > >
> > > Alan Stern
> > 
> > Except you always want early-suspend and auto-suspend at the same time. The 
> > idea is, if all display of system states is off (early-suspend), we can 
> > enable or disable the cpu at will (auto-suspend) because nobody will notice. 
> 
> Why should the kernel have to get involved?  Why can't userspace manage 
> both early-suspend and auto-suspend?
> 
> That is, consider the following: Userspace initiates an early-suspend
> by using a runtime PM interface to turn off the screen and some other
> devices.  After a short time, if they are still off, then userspace can
> initiate an auto-suspend by writing "auto-mem" to /sys/power/state.
> 
> All the kernel would need to know is the difference between
> auto-suspend and normal suspend: one respects wakelocks and the other
> doesn't.

It sounds to me like all of this stuff is just power management of
individual devices, which should be done through the sysfs interface and
completely unrelated to /sys/power/state. I'm putting the talk about
suspending the CPU in this box too because it sounds like the desire is
to stop the CPU without necessarily suspending other devices such as
transmitters - sort of a CPU freq state where the frequency is 0.

That said, if suspend to ram is what they really want for 'auto-mem',
what you're suggesting sounds good to me.

Regards,

Nigel

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-02 16:15                         ` Uli Luckas
@ 2009-02-02 16:35                           ` Alan Stern
  2009-02-03 20:15                           ` Pavel Machek
  1 sibling, 0 replies; 251+ messages in thread
From: Alan Stern @ 2009-02-02 16:35 UTC (permalink / raw)
  To: Uli Luckas; +Cc: swetland, linux-pm, Nigel Cunningham

On Mon, 2 Feb 2009, Uli Luckas wrote:

> Well, it should not interfere with any of these settings. And I think it is 
> understood by now that we has to take back the semantic change of "echo mem 
> > /sys/power/state"
> 
> On the other hand, I think it is quite reasonable to have aditional suspend 
> mechanisms on a phone then you have on a super computer. Obviously you don't 
> want the supercomputer to suspend everytime nobody is watching :-)

Agreed.

Alan Stern

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-02 15:09                                         ` Alan Stern
@ 2009-02-02 16:24                                           ` Uli Luckas
  2009-02-02 21:47                                           ` Nigel Cunningham
  2009-02-02 23:10                                           ` Arve Hjønnevåg
  2 siblings, 0 replies; 251+ messages in thread
From: Uli Luckas @ 2009-02-02 16:24 UTC (permalink / raw)
  To: linux-pm; +Cc: Brian Swetland, Nigel Cunningham

On Monday, 2. February 2009, Alan Stern wrote:
> On Mon, 2 Feb 2009, Uli Luckas wrote:
> > On Sunday, 1. February 2009, Alan Stern wrote:
> > > Early-suspend seems to be a completely different matter.  In fact it
> > > isn't a suspend state at all, as far as I understand it.  It's more
> > > like what you get simply by doing a runtime suspend on some collection
> > > of devices.  I don't see that the kernel needs to treat it as a special
> > > state, and in might be possible to have a user program manage the whole
> > > thing -- provided the drivers in question implement runtime power
> > > management (as USB has done).
> > >
> > > Alan Stern
> >
> > Except you always want early-suspend and auto-suspend at the same time.
> > The idea is, if all display of system states is off (early-suspend), we
> > can enable or disable the cpu at will (auto-suspend) because nobody will
> > notice.
>
> Why should the kernel have to get involved?  Why can't userspace manage
> both early-suspend and auto-suspend?
>
> That is, consider the following: Userspace initiates an early-suspend
> by using a runtime PM interface to turn off the screen and some other
> devices.  After a short time, if they are still off, then userspace can
> initiate an auto-suspend by writing "auto-mem" to /sys/power/state.
>
> All the kernel would need to know is the difference between
> auto-suspend and normal suspend: one respects wakelocks and the other
> doesn't.
>
Actually i don't know. Arve?
Things would get a lot less complex if we could leave the early suspend stuff 
out of the kernel.

Uli

-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-02 15:05                       ` Alan Stern
@ 2009-02-02 16:15                         ` Uli Luckas
  2009-02-02 16:35                           ` Alan Stern
  2009-02-03 20:15                           ` Pavel Machek
  0 siblings, 2 replies; 251+ messages in thread
From: Uli Luckas @ 2009-02-02 16:15 UTC (permalink / raw)
  To: Alan Stern; +Cc: swetland, linux-pm, Nigel Cunningham

On Monday, 2. February 2009, Alan Stern wrote:
> On Mon, 2 Feb 2009, Uli Luckas wrote:
> > Hi Alan,
> > we have had a (userspace) wake-lock implementation on our handyPC devices
> > for a couple of years now. So maybe I can shed some light.
> >
> > The above quote underlines pretty well, where Arve's and your ideas of
> > eraly-suspend and wake-locks diverge. And why you are missunderstanding
> > each other.
> > Arve is always talking about "blanking the screen" because that's what
> > the users sees. From the user's perspective the device is "suspended" as
> > soon as his user interfaces vanishes. That's probably also why his
> > notions of "suspend" and "wake" are not alway following a strict
> > definition.
>
> And that's partly why I have been complaining about the things he
> writes.  To a kernel programmer, "suspend" has a very specific meaning,
> quite different from what it might mean to a user.  When Arve posts on
> a kernel-oriented mailing list, he should use such words in a way his
> readers will understand.
>
Full Ack

> > If the device stays blanked while the user has his 10 min phone
> > conversation, then he won't even notice wether the device suspends or not
> > after the call. This is the idea. The user does not care for anything
> > they can't see.
> >
> > Arve is not talking about a laptop that needs to sleep befor it's
> > ventilation slot are covered. He is talking about a phone that could well
> > do with only blanking it's screen. Except it want's to save battery when
> > ever possible.
>
> The problem is that he's talking about making changes to a kernel that
> will be installed in all sorts of machines, from phones all the way up
> to supercomputers.  When you do this, you have to broaden your point of
> view -- your code has to run correctly in all of these settings.
>
Well, it should not interfere with any of these settings. And I think it is 
understood by now that we has to take back the semantic change of "echo mem 
> /sys/power/state"

On the other hand, I think it is quite reasonable to have aditional suspend 
mechanisms on a phone then you have on a super computer. Obviously you don't 
want the supercomputer to suspend everytime nobody is watching :-)

Uli


-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-02 11:00                                       ` Uli Luckas
@ 2009-02-02 15:09                                         ` Alan Stern
  2009-02-02 16:24                                           ` Uli Luckas
                                                             ` (2 more replies)
  0 siblings, 3 replies; 251+ messages in thread
From: Alan Stern @ 2009-02-02 15:09 UTC (permalink / raw)
  To: Uli Luckas; +Cc: Brian Swetland, linux-pm, Nigel Cunningham

On Mon, 2 Feb 2009, Uli Luckas wrote:

> On Sunday, 1. February 2009, Alan Stern wrote:
> > Early-suspend seems to be a completely different matter.  In fact it
> > isn't a suspend state at all, as far as I understand it.  It's more
> > like what you get simply by doing a runtime suspend on some collection
> > of devices.  I don't see that the kernel needs to treat it as a special
> > state, and in might be possible to have a user program manage the whole
> > thing -- provided the drivers in question implement runtime power
> > management (as USB has done).
> >
> > Alan Stern
> 
> Except you always want early-suspend and auto-suspend at the same time. The 
> idea is, if all display of system states is off (early-suspend), we can 
> enable or disable the cpu at will (auto-suspend) because nobody will notice. 

Why should the kernel have to get involved?  Why can't userspace manage 
both early-suspend and auto-suspend?

That is, consider the following: Userspace initiates an early-suspend
by using a runtime PM interface to turn off the screen and some other
devices.  After a short time, if they are still off, then userspace can
initiate an auto-suspend by writing "auto-mem" to /sys/power/state.

All the kernel would need to know is the difference between
auto-suspend and normal suspend: one respects wakelocks and the other
doesn't.

Alan Stern

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-02 10:42                     ` Uli Luckas
@ 2009-02-02 15:05                       ` Alan Stern
  2009-02-02 16:15                         ` Uli Luckas
  0 siblings, 1 reply; 251+ messages in thread
From: Alan Stern @ 2009-02-02 15:05 UTC (permalink / raw)
  To: Uli Luckas; +Cc: swetland, linux-pm, Nigel Cunningham

On Mon, 2 Feb 2009, Uli Luckas wrote:

> Hi Alan,
> we have had a (userspace) wake-lock implementation on our handyPC devices for 
> a couple of years now. So maybe I can shed some light.
> 
> The above quote underlines pretty well, where Arve's and your ideas of 
> eraly-suspend and wake-locks diverge. And why you are missunderstanding each 
> other.
> Arve is always talking about "blanking the screen" because that's what the 
> users sees. From the user's perspective the device is "suspended" as soon as 
> his user interfaces vanishes. That's probably also why his notions 
> of "suspend" and "wake" are not alway following a strict definition. 

And that's partly why I have been complaining about the things he 
writes.  To a kernel programmer, "suspend" has a very specific meaning, 
quite different from what it might mean to a user.  When Arve posts on 
a kernel-oriented mailing list, he should use such words in a way his 
readers will understand.

> If the device stays blanked while the user has his 10 min phone conversation, 
> then he won't even notice wether the device suspends or not after the call. 
> This is the idea. The user does not care for anything they can't see.
> 
> Arve is not talking about a laptop that needs to sleep befor it's ventilation 
> slot are covered. He is talking about a phone that could well do with only 
> blanking it's screen. Except it want's to save battery when ever possible.

The problem is that he's talking about making changes to a kernel that 
will be installed in all sorts of machines, from phones all the way up 
to supercomputers.  When you do this, you have to broaden your point of 
view -- your code has to run correctly in all of these settings.

Alan Stern

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-02 11:56                         ` Pavel Machek
@ 2009-02-02 12:38                           ` Uli Luckas
  0 siblings, 0 replies; 251+ messages in thread
From: Uli Luckas @ 2009-02-02 12:38 UTC (permalink / raw)
  To: linux-pm; +Cc: Brian Swetland, Nigel Cunningham

On Monday, 2. February 2009, Pavel Machek wrote:
> On Sun 2009-02-01 00:20:04, Rafael J. Wysocki wrote:
> > On Saturday 31 January 2009, Arve Hj?nnev?g wrote:
> > > On Sat, Jan 31, 2009 at 7:41 AM, Alan Stern <stern@rowland.harvard.edu> 
wrote:
> > > > On Fri, 30 Jan 2009, Brian Swetland wrote:
> > > >> Imagine the computer in question is a cellphone which is going to
> > > >> need to wake up when a call comes in to do traditional cellphone
> > > >> things, like ring, bring up the incall UI (so the user can
> > > >> answer/cancel), etc.
> > > >
> > > > Yes.  So what?  Nothing I said prevents the computer from waking up
> > > > when a call comes in.  What I said was that when the user tells the
> > > > computer to suspend (e.g., by writing "mem" to /sys/power/state), the
> > > > computer should suspend even if some wakelocks are still locked.
> > >
> > > But this could prevent the phone from ringing. What if the user-space
> > > code that is responsible for playing the ringtone has been notified
> > > that a call is coming in and starts reading the audio file with the
> > > ringtone. At the same, the user, unaware that someone is calling,
> > > presses the power button. If we ignore the wakelock in this situation,
> > > the phone will not ring.
>
> Yes, you don't want to write "mem" to /sys/power/state on android. You
> want to write something like "auto-mem" there.
>
ACK.
Don't change the way "mem" works. Just don't use it if it does the wrong thing 
on android.

Uli


-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-31 23:20                       ` Rafael J. Wysocki
  2009-01-31 23:32                         ` Arve Hjønnevåg
@ 2009-02-02 11:56                         ` Pavel Machek
  2009-02-02 12:38                           ` Uli Luckas
  1 sibling, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-02-02 11:56 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Brian Swetland, linux-pm, Nigel Cunningham

On Sun 2009-02-01 00:20:04, Rafael J. Wysocki wrote:
> On Saturday 31 January 2009, Arve Hj?nnev?g wrote:
> > On Sat, Jan 31, 2009 at 7:41 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
> > > On Fri, 30 Jan 2009, Brian Swetland wrote:
> > >> Imagine the computer in question is a cellphone which is going to need
> > >> to wake up when a call comes in to do traditional cellphone things, like
> > >> ring, bring up the incall UI (so the user can answer/cancel), etc.
> > >
> > > Yes.  So what?  Nothing I said prevents the computer from waking up
> > > when a call comes in.  What I said was that when the user tells the
> > > computer to suspend (e.g., by writing "mem" to /sys/power/state), the
> > > computer should suspend even if some wakelocks are still locked.
> > 
> > But this could prevent the phone from ringing. What if the user-space
> > code that is responsible for playing the ringtone has been notified
> > that a call is coming in and starts reading the audio file with the
> > ringtone. At the same, the user, unaware that someone is calling,
> > presses the power button. If we ignore the wakelock in this situation,
> > the phone will not ring.

Yes, you don't want to write "mem" to /sys/power/state on android. You
want to write something like "auto-mem" there.

> What if the user decides to power off the phone and a call comes in at the
> same time?

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-31 18:39                     ` Rafael J. Wysocki
  2009-01-31 18:54                       ` Igor Stoppa
  2009-02-01  1:04                       ` Arve Hjønnevåg
@ 2009-02-02 11:55                       ` Pavel Machek
  2 siblings, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-02 11:55 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Brian Swetland, linux-pm, Nigel Cunningham

Hi!

> However, I think that what we are used to call a sleep (or suspend) state is
> really a power off state for cell phone people.  So lets define what we're
> talking about.
> 
> Sleep states (suspend to RAM, hibernation) are the states of the whole system
> in which no instructions are executed by the processor(s).  The
> difference

s/processor(s)/CPU/.

Even in PC, you have keyboard controller running while sleeping. On
cellphone, you have some kind of pmu chip + GSM chip running. So
cellphone actually _is_ useful even when CPU is sleeping.

> between a sleep state and the power off state is that in a sleep state we have
> some application context saved (in memory or in a storage device) and
> (in principle) after the system goes back to the working state, the
> applications can continue doing do whatever they had been doing before the
> system was put into the sleep state.
> 
> If instructions are executed by the processor(s), the system is in the working
> state.

ACK.

> Well, I think that sleep states are not really useful in cell phones.  Useful
> is the ability to put all devices into low power states separately and as
> needed (eg. after a period of inactivity).  IOW, the system as a
> whole is

No, it does not work like that. Cellphone with sleeping CPU
(suspended-to-RAM) is still very useful.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-30  6:04               ` Arve Hjønnevåg
@ 2009-02-02 11:49                 ` Pavel Machek
  0 siblings, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-02 11:49 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: swetland, Nigel Cunningham, linux-pm

Hi!

> 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.

Do you have some examples of user wakelocks?

The API is quite ugly; creating objects by writing to file.

If userspace does not want system to suspend, could it simply write
"on" to /sys/power/state ?
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-30 12:34                 ` Uli Luckas
@ 2009-02-02 11:46                   ` Pavel Machek
  0 siblings, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-02-02 11:46 UTC (permalink / raw)
  To: Uli Luckas; +Cc: swetland, linux-pm, Nigel Cunningham

On Fri 2009-01-30 13:34:02, Uli Luckas wrote:
> On Friday, 30. January 2009, Pavel Machek wrote:
> > > >> - The user-space input-event thread returns from read. It determines
> > > >> that the key should not wake up the system, releases the
> > > >> process-input-events wakelock and calls select or poll.
> > > >
> > > > This makes no sense.  If the system wasn't asleep to begin with, how
> > > > could the key wake it up?  And if the system _was_ asleep to begin
> > > > with, how could all of this happen without waking the system up?
> > >
> > > What I mean here is that the screen turns on and the system does not
> > > immediately go back to sleep. The user-space framework has its own
> > > idea of whether the system is awake or not. I can change this to
> > > "fully wake up" or "turn on the screen".
> >
> > "turn on the screen", please. (But I still don't quite get it; screen
> > should be at full control of userspace, so why is kernel interaction
> > needed?) Pavel
> >
> Turning on the screen is only on thing userspace can do. What exactly happens 
> is beyon the scope of the kernel interface.
> The right term is probably something like "break out of auto-suspend" or "wake 
> from auto suspend".

I guess I'm missing big parts of the picture here. It would be nice to
document how it all works together... somewhere.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-01 17:43                                     ` Alan Stern
  2009-02-01 19:27                                       ` Woodruff, Richard
@ 2009-02-02 11:00                                       ` Uli Luckas
  2009-02-02 15:09                                         ` Alan Stern
  1 sibling, 1 reply; 251+ messages in thread
From: Uli Luckas @ 2009-02-02 11:00 UTC (permalink / raw)
  To: linux-pm; +Cc: Brian Swetland, Nigel Cunningham

On Sunday, 1. February 2009, Alan Stern wrote:
> Early-suspend seems to be a completely different matter.  In fact it
> isn't a suspend state at all, as far as I understand it.  It's more
> like what you get simply by doing a runtime suspend on some collection
> of devices.  I don't see that the kernel needs to treat it as a special
> state, and in might be possible to have a user program manage the whole
> thing -- provided the drivers in question implement runtime power
> management (as USB has done).
>
> Alan Stern

Except you always want early-suspend and auto-suspend at the same time. The 
idea is, if all display of system states is off (early-suspend), we can 
enable or disable the cpu at will (auto-suspend) because nobody will notice. 

Uli


-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-31 16:19                   ` Alan Stern
  2009-01-31 23:28                     ` Arve Hjønnevåg
@ 2009-02-02 10:42                     ` Uli Luckas
  2009-02-02 15:05                       ` Alan Stern
  1 sibling, 1 reply; 251+ messages in thread
From: Uli Luckas @ 2009-02-02 10:42 UTC (permalink / raw)
  To: linux-pm; +Cc: swetland, Nigel Cunningham


[-- Attachment #1.1: Type: text/plain, Size: 2369 bytes --]

On Saturday, 31. January 2009, Alan Stern wrote:
> > Also, consider the case where the user presses the power button to go
> > to sleep. Before this sleep request has finished a phone call comes
> > in. The driver gets an interrupt, enqueues the message and locks a
> > wakelock to make sure user-space gets a chance to process the message.
> > If we ignore this wakelock, the phone will either not ring at all, or
> > it will ring later when the device wakes up for some other reason.
>
> For situations like this, the driver can simply refuse to suspend.  You
> don't need to use a wakelock.
>
> In fact, if you did use a wakelock the behavior would be very strange.  
> The user presses the power button, an instant later a call comes in,
> the device doesn't go to sleep, the user answers the call, and as soon
> as he hangs up (perhaps 10 minutes later) the wakelock is released and
> the device immediately goes to sleep!  Not what the user would expect.
Hi Alan,
we have had a (userspace) wake-lock implementation on our handyPC devices for 
a couple of years now. So maybe I can shed some light.

The above quote underlines pretty well, where Arve's and your ideas of 
eraly-suspend and wake-locks diverge. And why you are missunderstanding each 
other.
Arve is always talking about "blanking the screen" because that's what the 
users sees. From the user's perspective the device is "suspended" as soon as 
his user interfaces vanishes. That's probably also why his notions 
of "suspend" and "wake" are not alway following a strict definition. 
If the device stays blanked while the user has his 10 min phone conversation, 
then he won't even notice wether the device suspends or not after the call. 
This is the idea. The user does not care for anything they can't see.

Arve is not talking about a laptop that needs to sleep befor it's ventilation 
slot are covered. He is talking about a phone that could well do with only 
blanking it's screen. Except it want's to save battery when ever possible.


Uli

-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

[-- Attachment #1.2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-01 17:43                                     ` Alan Stern
@ 2009-02-01 19:27                                       ` Woodruff, Richard
  2009-02-02 11:00                                       ` Uli Luckas
  1 sibling, 0 replies; 251+ messages in thread
From: Woodruff, Richard @ 2009-02-01 19:27 UTC (permalink / raw)
  To: Alan Stern, Rafael J. Wysocki; +Cc: Brian Swetland, Nigel Cunningham, linux-pm

> Early-suspend seems to be a completely different matter.  In fact it
> isn't a suspend state at all, as far as I understand it.  It's more
> like what you get simply by doing a runtime suspend on some collection
> of devices.  I don't see that the kernel needs to treat it as a special
> state, and in might be possible to have a user program manage the whole
> thing -- provided the drivers in question implement runtime power
> management (as USB has done).

The bit of use I saw was a few devices were broken out from the global suspend chain (display and some input).  They were effetely controlled from user space activity timers. The 'early_suspend' was sequenced before the global suspend call. Effectively this created a partial idle state where some drivers were down and others up. Also, the drivers on early_suspend might resume with out a global suspend. They also were not registered on global chain.

The upside of this from my point of view was the drivers on early suspend chain were high latency drivers. If they were linked into the global suspend chain they would drive up cost of frequent suspend substantially (a 60Hz or slower LCD DMA re-sync on both directions is costly, more so for some slow SPI-GPS kind of device). One example might be some periodic task wakes up to check the battery level then re-sleeps. On the resume side you don't want to restart the display system to do this. Since it is on a separate early-suspend-chain it doesn't wake until a later re-activated user space issues the wake if it needs to be.

Personally I still like an on-demand architecture for kernel space where drivers are coming up and down independently per control and data flow.  But this is harder. Splitting suspend seems to be an ok tradeoff for this problem.  Anyway, they don't conflict, you just use fewer or no kernel wake locks.  The user space ones are still around to help control the wild west up there.

This kind of system suspend seems good for power optimization at the user input speed time scale (hundreds of mS). It probably is too heavy to get really good power for constant active mode power like an mp3. At the current time scale the best you could hope for is DVFS with this. Doing DPS (dynamic-power-switching) to shut down individual blocks during playback, this seems like it would be to slow unless you had groups of independent 'early_suspend' device chains.

A mix of cpuidle + wakelock-aggressive-system-suspend should provide decent coverage for power states.

Again, I'll defer to android experts.

Regards,
Richard W.

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-01 12:30                                   ` Rafael J. Wysocki
  2009-02-01 14:03                                     ` Woodruff, Richard
@ 2009-02-01 17:43                                     ` Alan Stern
  2009-02-01 19:27                                       ` Woodruff, Richard
  2009-02-02 11:00                                       ` Uli Luckas
  1 sibling, 2 replies; 251+ messages in thread
From: Alan Stern @ 2009-02-01 17:43 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Brian Swetland, Nigel Cunningham, linux-pm

On Sun, 1 Feb 2009, Rafael J. Wysocki wrote:

> > In that case, why are you against using wakelocks to abort the suspend
> > sequence? It covers the case where the driver knows that a call is
> > coming in, without any confusion about when the abort condition
> > clears. And, it avoids the overhead of freezing every process for an
> > operation that is doomed to fail.
> 
> I'm not really against (yet), I'm only trying to clearly understand the
> benefit.
> 
> The problem pointed out by Alan is real, the user expects the system to suspend
> as soon as the button is pressed and wakelocks may get in the way.
> 
> Your example is also good, but I think the problem in your example (phone
> call coming in while suspending) may be resolved without wakelocks.  Moreover,
> it is a general problem of a wake-up event coming in while suspending and
> it requires a general solution independent of wakelocks.

I'm beginning to get the impression that we're really talking about two 
different kinds of suspend here.  They can be described as 
"high-priority suspend" and "low-priority suspend".

A high-priority suspend occurs when userspace writes "mem" to 
/sys/power/state.  It should override wakelock settings and put the 
system to sleep as soon as possible (subject to abort by drivers, of 
course, but they better have a pretty good reason for aborting).

A low-priority suspend is what Arve has been talking about; it occurs
when the user pushes the phone's "power" button or the auto-suspend
mechanism activates.  It is subject to blocking by wakelocks, and there
should also be a way (although I don't recall seeing it described) to
cancel a low-priority suspend request while it is waiting for a
wakelock to be released.

The idea behind these low-priority suspends is that there are certain 
activities which should be atomic with respect to suspends, that is, 
the system should not normally be allowed to suspend while the activity 
is taking place.  These are things that last longer than a single 
interrupt handler.  Examples we have seen include waiting for all key 
presses to be released (because the keypad can't be enabled for wakeup 
if any keys are pressed) or waiting for a userspace process to finish 
playing a ring tone.

If a high-priority suspend occurs while some keys are pressed, the
keypad driver has a few possible courses of action: abort the suspend,
re-enable the interrupt circuitry, or disable keypad wakeups.  I'm not
sure which would be best; the issue probably won't arise much.  
Similarly, a high-priority suspend while a ring tone is being played
should cause the system to go to sleep right in the middle of playing.

Normally we would expect that on a desktop or laptop, the only source
of low-priority suspend requests would be the auto-suspend code.  On a
phone or other embedded device, we would not expect to see any
high-priority suspend requests under normal circumstances.  But of 
course there could always be exceptions, if someone wanted them.


Early-suspend seems to be a completely different matter.  In fact it 
isn't a suspend state at all, as far as I understand it.  It's more 
like what you get simply by doing a runtime suspend on some collection 
of devices.  I don't see that the kernel needs to treat it as a special 
state, and in might be possible to have a user program manage the whole 
thing -- provided the drivers in question implement runtime power 
management (as USB has done).

Alan Stern

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-01 12:30                                   ` Rafael J. Wysocki
@ 2009-02-01 14:03                                     ` Woodruff, Richard
  2009-02-01 17:43                                     ` Alan Stern
  1 sibling, 0 replies; 251+ messages in thread
From: Woodruff, Richard @ 2009-02-01 14:03 UTC (permalink / raw)
  To: Rafael J. Wysocki, Arve Hjønnevåg
  Cc: Brian Swetland, linux-pm, Nigel Cunningham

> > In that case, why are you against using wakelocks to abort the suspend
> > sequence? It covers the case where the driver knows that a call is
> > coming in, without any confusion about when the abort condition
> > clears. And, it avoids the overhead of freezing every process for an
> > operation that is doomed to fail.
>
> I'm not really against (yet), I'm only trying to clearly understand the
> benefit.
>
> The problem pointed out by Alan is real, the user expects the system to
> suspend
> as soon as the button is pressed and wakelocks may get in the way.
>
> Your example is also good, but I think the problem in your example (phone
> call coming in while suspending) may be resolved without wakelocks.  Moreover,
> it is a general problem of a wake-up event coming in while suspending and
> it requires a general solution independent of wakelocks.

What is being done is automatic very aggressive use of suspend. This is not a button press by the user.  As the same end mechanism is used (plumbing and end suspend call in driver) people are worried about semantics.

At the driver level it might be viewed as a constraint frame work which allows veto of the system-auto-suspend.  It provides a short circuits of the suspend before it gets very far.

There is a summed user space input point which allows user space to have a vote.  The upper level user space coordination prior to summed kernel interface is interesting.

At the kernel level if you work really really hard and use actively timers I think cpuidle and pm_qos can get you a similar aggressive sleep. However, there are many 'bad' drivers and it's a lot easier to re-use the suspend path. Being told to sleep is something drivers know, but doing it automatically and interfaces around that is not.  For OMAP3 we fixed up all drivers make cpuidle work and also keep traditional suspend.  This has been hard but possible.

While it is possible to fix kernel space doing the same to user space can be very hard. User space is much bigger and badness there can sink all your work in the kernel. What is good about android-system-auto-suspend here is that the freezer will stop a lot of bad processes in their tracks. To stop breakages in user space you can do the preferred thing and fix the code to be smart which could be hard/impossible or raise and lower a wakelock.  The wake lock is easier by comparison.

Any corrections by android experts are welcome.

Regards,
Richard W.

BTW, yes, the screen state is very import event in system power management on a cell phone.  When it blanks you move into a time where you can be very aggressive.  At this point a lot of timers (like user activity) and the like are expired.  You can do things which were not valid before as they would disrupt user experience.  Embedded people will use this as a critical point of reference as it's a pivot point.

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-01  2:14                                 ` Arve Hjønnevåg
@ 2009-02-01 12:30                                   ` Rafael J. Wysocki
  2009-02-01 14:03                                     ` Woodruff, Richard
  2009-02-01 17:43                                     ` Alan Stern
  0 siblings, 2 replies; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-01 12:30 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: Brian Swetland, linux-pm, Nigel Cunningham

On Sunday 01 February 2009, Arve Hjønnevåg wrote:
> On Sat, Jan 31, 2009 at 5:32 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> >> > If incoming calls are supposed to wake up the system, then there are two
> >> > possibilities:
> >> > - the already started suspend sequence may be aborted and the system may be put
> >> >  into the low power state,
> >>
> >> I assume you mean high power state not low power state, or does low
> >> power state mean early-suspend state. If so, locking a wakelock will
> >> accomplish this.
> >
> > Actually, I meant the working state.  Aborting suspend sequence always means
> > go back to the working state.
> >
> > Also, I think the device that detected the incoming call should abort the
> > suspend sequence by refusing to suspend.
> >
> >> > - the system may be suspended and then immediately woken up.
> >>
> >> If you mean this as a general strategy, and not a specific outcome,
> >> then it does not always work (for the reasons I have already stated).
> >
> > I meant a specific outcome.
> >
> > It may be impossible to abort suspend if the call comes in sufficiently
> > late.
> 
> In that case, why are you against using wakelocks to abort the suspend
> sequence? It covers the case where the driver knows that a call is
> coming in, without any confusion about when the abort condition
> clears. And, it avoids the overhead of freezing every process for an
> operation that is doomed to fail.

I'm not really against (yet), I'm only trying to clearly understand the
benefit.

The problem pointed out by Alan is real, the user expects the system to suspend
as soon as the button is pressed and wakelocks may get in the way.

Your example is also good, but I think the problem in your example (phone
call coming in while suspending) may be resolved without wakelocks.  Moreover,
it is a general problem of a wake-up event coming in while suspending and
it requires a general solution independent of wakelocks.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-01  1:32                               ` Rafael J. Wysocki
@ 2009-02-01  2:14                                 ` Arve Hjønnevåg
  2009-02-01 12:30                                   ` Rafael J. Wysocki
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-01  2:14 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Brian Swetland, linux-pm, Nigel Cunningham

On Sat, Jan 31, 2009 at 5:32 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
>> > If incoming calls are supposed to wake up the system, then there are two
>> > possibilities:
>> > - the already started suspend sequence may be aborted and the system may be put
>> >  into the low power state,
>>
>> I assume you mean high power state not low power state, or does low
>> power state mean early-suspend state. If so, locking a wakelock will
>> accomplish this.
>
> Actually, I meant the working state.  Aborting suspend sequence always means
> go back to the working state.
>
> Also, I think the device that detected the incoming call should abort the
> suspend sequence by refusing to suspend.
>
>> > - the system may be suspended and then immediately woken up.
>>
>> If you mean this as a general strategy, and not a specific outcome,
>> then it does not always work (for the reasons I have already stated).
>
> I meant a specific outcome.
>
> It may be impossible to abort suspend if the call comes in sufficiently
> late.

In that case, why are you against using wakelocks to abort the suspend
sequence? It covers the case where the driver knows that a call is
coming in, without any confusion about when the abort condition
clears. And, it avoids the overhead of freezing every process for an
operation that is doomed to fail.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-01  1:17                             ` Arve Hjønnevåg
@ 2009-02-01  1:32                               ` Rafael J. Wysocki
  2009-02-01  2:14                                 ` Arve Hjønnevåg
  0 siblings, 1 reply; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-01  1:32 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: Brian Swetland, linux-pm, Nigel Cunningham

On Sunday 01 February 2009, Arve Hjønnevåg wrote:
> On Sat, Jan 31, 2009 at 4:18 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > If the user forcibly puts the device into suspend, it's very much like powering
> > off.  The kernel shouldn't prevent that from happening unless in error
> > conditions.
> 
> No, when the phone is powered off, it is not expected to ring. When it
> is suspended it is expected to ring.
> 
> > If incoming calls are supposed to wake up the system, then there are two
> > possibilities:
> > - the already started suspend sequence may be aborted and the system may be put
> >  into the low power state,
> 
> I assume you mean high power state not low power state, or does low
> power state mean early-suspend state. If so, locking a wakelock will
> accomplish this.

Actually, I meant the working state.  Aborting suspend sequence always means
go back to the working state.

Also, I think the device that detected the incoming call should abort the
suspend sequence by refusing to suspend.

> > - the system may be suspended and then immediately woken up.
> 
> If you mean this as a general strategy, and not a specific outcome,
> then it does not always work (for the reasons I have already stated).

I meant a specific outcome.

It may be impossible to abort suspend if the call comes in sufficiently
late.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-02-01  0:18                           ` Rafael J. Wysocki
@ 2009-02-01  1:17                             ` Arve Hjønnevåg
  2009-02-01  1:32                               ` Rafael J. Wysocki
  0 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-01  1:17 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Brian Swetland, linux-pm, Nigel Cunningham

On Sat, Jan 31, 2009 at 4:18 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> If the user forcibly puts the device into suspend, it's very much like powering
> off.  The kernel shouldn't prevent that from happening unless in error
> conditions.

No, when the phone is powered off, it is not expected to ring. When it
is suspended it is expected to ring.

> If incoming calls are supposed to wake up the system, then there are two
> possibilities:
> - the already started suspend sequence may be aborted and the system may be put
>  into the low power state,

I assume you mean high power state not low power state, or does low
power state mean early-suspend state. If so, locking a wakelock will
accomplish this.

> - the system may be suspended and then immediately woken up.

If you mean this as a general strategy, and not a specific outcome,
then it does not always work (for the reasons I have already stated).

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-31 18:39                     ` Rafael J. Wysocki
  2009-01-31 18:54                       ` Igor Stoppa
@ 2009-02-01  1:04                       ` Arve Hjønnevåg
  2009-02-02 11:55                       ` Pavel Machek
  2 siblings, 0 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-02-01  1:04 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Brian Swetland, linux-pm, Nigel Cunningham

On Sat, Jan 31, 2009 at 10:39 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> However, I think that what we are used to call a sleep (or suspend) state is
> really a power off state for cell phone people.

No, our power off state is the same as on the desktop. We do use the
power key to enter and exit sleep, but you can configure a desktop
system to do this as well.

> Sleep states (suspend to RAM, hibernation) are the states of the whole system
> in which no instructions are executed by the processor(s).  The difference
> between a sleep state and the power off state is that in a sleep state we have
> some application context saved (in memory or in a storage device) and
> (in principle) after the system goes back to the working state, the
> applications can continue doing do whatever they had been doing before the
> system was put into the sleep state.

On many arm processors there is also a big difference in what events
can take you out of the power-off state versus the sleep-state. On
some systems only the power button or the charger can turn the system
back on after power-off while a number of external and internal
interrupts can take the cpu out of the deep-sleep-state.


> Well, I think that sleep states are not really useful in cell phones.  Useful
> is the ability to put all devices into low power states separately and as
> needed (eg. after a period of inactivity).  IOW, the system as a whole is
> in the working state, but some parts of the hardware may be in low power states
> (even all of the I/O devices may be in low power states).  That may very well
> look "asleep" from the user point of view, but it is not a sleep state.

That may be true for single-core phones, but for dual core phones we
get significant power savings by doing a full suspend on the core that
runs Linux. On the system we currently have, we can enter the same
hardware state from idle as we can from suspend. But, on an idle
system with the radio is off, there are enough periodic timers to
double the average power draw. On a previous system the power draw
from idle was not even close to the power draw from suspend.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-31 23:32                         ` Arve Hjønnevåg
@ 2009-02-01  0:18                           ` Rafael J. Wysocki
  2009-02-01  1:17                             ` Arve Hjønnevåg
  0 siblings, 1 reply; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-02-01  0:18 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: Brian Swetland, linux-pm, Nigel Cunningham

On Sunday 01 February 2009, Arve Hjønnevåg wrote:
> On Sat, Jan 31, 2009 at 3:20 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > On Saturday 31 January 2009, Arve Hjønnevåg wrote:
> >> But this could prevent the phone from ringing. What if the user-space
> >> code that is responsible for playing the ringtone has been notified
> >> that a call is coming in and starts reading the audio file with the
> >> ringtone. At the same, the user, unaware that someone is calling,
> >> presses the power button. If we ignore the wakelock in this situation,
> >> the phone will not ring.
> >
> > What if the user decides to power off the phone and a call comes in at the
> > same time?
> 
> If you are talking about a shutdown, not sleep, then the phone just
> turns off. The phone is not expected to ring when it is turned off so
> there is no point in delaying shutdown.

If the user forcibly puts the device into suspend, it's very much like powering
off.  The kernel shouldn't prevent that from happening unless in error
conditions.

If incoming calls are supposed to wake up the system, then there are two
possibilities:
- the already started suspend sequence may be aborted and the system may be put
  into the low power state,
- the system may be suspended and then immediately woken up.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-31 23:20                       ` Rafael J. Wysocki
@ 2009-01-31 23:32                         ` Arve Hjønnevåg
  2009-02-01  0:18                           ` Rafael J. Wysocki
  2009-02-02 11:56                         ` Pavel Machek
  1 sibling, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-01-31 23:32 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Brian Swetland, linux-pm, Nigel Cunningham

On Sat, Jan 31, 2009 at 3:20 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> On Saturday 31 January 2009, Arve Hjønnevåg wrote:
>> But this could prevent the phone from ringing. What if the user-space
>> code that is responsible for playing the ringtone has been notified
>> that a call is coming in and starts reading the audio file with the
>> ringtone. At the same, the user, unaware that someone is calling,
>> presses the power button. If we ignore the wakelock in this situation,
>> the phone will not ring.
>
> What if the user decides to power off the phone and a call comes in at the
> same time?

If you are talking about a shutdown, not sleep, then the phone just
turns off. The phone is not expected to ring when it is turned off so
there is no point in delaying shutdown.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-31 16:19                   ` Alan Stern
@ 2009-01-31 23:28                     ` Arve Hjønnevåg
  2009-02-02 10:42                     ` Uli Luckas
  1 sibling, 0 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-01-31 23:28 UTC (permalink / raw)
  To: Alan Stern; +Cc: swetland, Nigel Cunningham, linux-pm

On Sat, Jan 31, 2009 at 8:19 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
> On Fri, 30 Jan 2009, Arve Hjønnevåg wrote:
>> On Fri, Jan 30, 2009 at 7:13 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
>> > Personally, I think we need to be able to suspend computers even when
>> > there are some unconsumed type-ahead characters in the input buffer.
>> > But that's merely an implementation detail.
>>
>> For us, the key that will turn the screen back on could be in this buffer.
>
> Why do you have this fixation on the screen?  Forget about the screen
> and consider the system as a whole.
>
> If the keyboard is enabled for wakeup, then typing a key _will_ wake
> the system up from suspend -- provided the key was typed after the
> system went to sleep.  It's silly to think that a key which was typed
> before the computer was suspended should cause it to wake up.

Only if you ignore the screen state. If the screen is off and the user
presses the power button, I expect it to turn on, not off.

>> If we go to sleep while the keypad wakelock is locked, then the keypad
>> can no longer wake the system up. Note that this is specific to a
>> keypad driver that scans the keypad matrix in software. A keyboard
>> that generates an interrupt on every key change does not need its own
>> wakelock.
>
> Are you sure about this?  IIRC, you said earlier that your keyboard
> generates an interrupt on a key press only when no other keys are
> already pressed.  Okay -- so imagine the system suspends while a key is
> pressed.  Pressing another key won't generate an interrupt and hence
> won't wake up the system.  But releasing all the keys and then pressing
> one _will_ generate an interrupt and so will wake up the system.  I
> don't see any problem with this.

A keypad matrix as outputs and inputs. To get an interrupt when any
key is pressed, all the output are driven and the interrupt is enabled
on the input. When you get this interrupt you turn off the interrupt
and stop driving all the outputs. Instead you drive one output, wait
for some settle time, and then read the inputs. If you go to sleep in
this state, no key will every wake the system up.

That said, if the interrupt is edge triggered, it is possible to
implement the behaviour you describe. You can pretend no keys are held
when the driver's suspend hook is called and start driving all the
output.

>> Also, consider the case where the user presses the power button to go
>> to sleep. Before this sleep request has finished a phone call comes
>> in. The driver gets an interrupt, enqueues the message and locks a
>> wakelock to make sure user-space gets a chance to process the message.
>> If we ignore this wakelock, the phone will either not ring at all, or
>> it will ring later when the device wakes up for some other reason.
>
> For situations like this, the driver can simply refuse to suspend.  You
> don't need to use a wakelock.

How is this better than using a wakelock? Is I understand you
correctly, that would mean that the user pressed the power button, and
instead of entering suspend as soon as all wakelocks are unlocked, you
don't enter suspend at all.

Also, when should the driver stop refusing suspend? As soon as it has
delivered a message to user-space? After some delay? When do you try
to enter suspend again after a driver refused a request?

> In fact, if you did use a wakelock the behavior would be very strange.
> The user presses the power button, an instant later a call comes in,
> the device doesn't go to sleep, the user answers the call, and as soon
> as he hangs up (perhaps 10 minutes later) the wakelock is released and
> the device immediately goes to sleep!  Not what the user would expect.

Normally when the user presses a key, the auto off timer in userspace
gets reset. This prevents the system from going back to sleep
immediately.

>
>> There is a class of applications where we do want the behaviour you
>> describe, but so far all of them also require the screen to stay on.
>
> Again this fixation with the screen.  Forget about the screen!
>
>> This is handled entirely by our user-space framework which also has
>> other options (like keeping the keypad backlight on).
>>
>> > For example: Suppose some program happens to hold a wakelock, perhaps
>> > because of a simple bug, when the user closes the laptop lid and throws
>> > the laptop into a backpack.  We don't want the computer to remain awake
>> > under those circumstances!
>>
>> If the program hold the wakelock because of a bug we don't want the
>> computer on, but if it operating correctly we do.
>
> _I_ don't.  I want my device to suspend itself when I tell it to.
> Nothing is more annoying than a machine that doesn't turn itself off
> when told to do so.
>
>> Since we don't have
>> a good way to detect if the program locked the wakelock because of a
>> bug, we assume it is correct and honor the request. We have debugging
>> interfaces to report how often and for how long wakelocks are locked.
>> We also do not allow applications to use wakelocks unless they have
>> the required permission.
>
> I admit that in a properly-operating system there won't be any
> wakelocks held because of bugs.  But there might be wakelocks held for
> other reasons, and I don't want _them_ to interfere when I suspend the
> machine either.

But the purpose of wakelocks is to interfere with suspend. I keep
bringing up the screen state, because it is the state that is visible
to the user on our device. If the screen is off we enter suspend
whenever possible, if the screen is on we do not.

>> And, every pm_suspend
>> call is the result of unlocking the last wakelock.
>
> Not true.  What if all the wakelocks are already unlocked when the user
> writes "mem" to /sys/power/state?

In the current implementation, early-suspend handlers are called, then
the "main" wakelock is unlocked.

>> > So what this example really shows is how wakelocks can be used to
>> > prevent auto suspend from kicking back in the moment a keystroke is
>> > received, before userspace has even had a chance to decide whether or
>> > not to turn auto suspend off.  That's how you should describe it -- not
>> > as a way of preventing keystrokes from waking the system up.
>>
>> I was trying to show that user-space decides which keys allow the
>> system to wake up. From the kernels point of view, every key causes a
>> wakeup, but if user-space decides that the key should not wake the
>> system, the system will go back to sleep as soon as possible (when all
>> wakelocks are unlocked).
>
> This paragraph is an excellent example of the muddiness of your
> thinking.  Userspace does _not_ decide which keys allow the system to
> wake up.  _All_ keys cause the system to wake up; userspace then
> decides which ones should cause the system to go right back into
> suspend.
>
> But you don't need wakelocks to do this.  You can get the same effect
> without them, just by running a program that writes "mem" (not
> "auto-mem"!) to /sys/power/state whenever it sees a keystroke it
> doesn't like.  So this example does not illustrate the power of
> wakelocks.

That would not work very well. All threads would be frozen, some
drivers suspended, the driver that knows that there are more keys in
the queue rejects suspend, and the process is reversed.

>> The user-space notion of suspend matches the early-suspend state.
>
> Then call it "early-suspend"!  Don't call it "suspend" or "the
> user-space notion of suspend".

I was trying to keep the wakelock discussion separate from the
early-suspend. Perhaps this was a mistake.

>>  I
>> consider early-suspend another stage, not a different concept. The
>> difference between early-suspend and suspend is similar to the
>> difference between device suspend and sysdev suspend. What would you
>> call the the first stage of suspend that we have added?
>
> "Early-suspend" is an okay name.  However I have the impression that
> you want to prolong the early-suspend stage, and sometimes even go back
> to full power directly from early-suspend.  There's nothing wrong with
> that; just make it clear that this is what you're doing.
>
> In fact, I get the impression that much of what you're talking about
> has to do with providing ways to short-circuit a complete suspend and
> go directly from early-suspend back to full power.

Yes we go from fully awake to early suspend and back to fully awake,
and we also go from fully suspended to early-suspend and back to fully
suspended.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-31 22:41                     ` Arve Hjønnevåg
@ 2009-01-31 23:20                       ` Rafael J. Wysocki
  2009-01-31 23:32                         ` Arve Hjønnevåg
  2009-02-02 11:56                         ` Pavel Machek
  0 siblings, 2 replies; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-01-31 23:20 UTC (permalink / raw)
  To: linux-pm; +Cc: Brian Swetland, Nigel Cunningham

On Saturday 31 January 2009, Arve Hjønnevåg wrote:
> On Sat, Jan 31, 2009 at 7:41 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
> > On Fri, 30 Jan 2009, Brian Swetland wrote:
> >> Imagine the computer in question is a cellphone which is going to need
> >> to wake up when a call comes in to do traditional cellphone things, like
> >> ring, bring up the incall UI (so the user can answer/cancel), etc.
> >
> > Yes.  So what?  Nothing I said prevents the computer from waking up
> > when a call comes in.  What I said was that when the user tells the
> > computer to suspend (e.g., by writing "mem" to /sys/power/state), the
> > computer should suspend even if some wakelocks are still locked.
> 
> But this could prevent the phone from ringing. What if the user-space
> code that is responsible for playing the ringtone has been notified
> that a call is coming in and starts reading the audio file with the
> ringtone. At the same, the user, unaware that someone is calling,
> presses the power button. If we ignore the wakelock in this situation,
> the phone will not ring.

What if the user decides to power off the phone and a call comes in at the
same time?

Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-31 15:41                   ` Alan Stern
  2009-01-31 18:39                     ` Rafael J. Wysocki
@ 2009-01-31 22:41                     ` Arve Hjønnevåg
  2009-01-31 23:20                       ` Rafael J. Wysocki
  1 sibling, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-01-31 22:41 UTC (permalink / raw)
  To: Alan Stern; +Cc: Brian Swetland, Nigel Cunningham, linux-pm

On Sat, Jan 31, 2009 at 7:41 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
> On Fri, 30 Jan 2009, Brian Swetland wrote:
>> Imagine the computer in question is a cellphone which is going to need
>> to wake up when a call comes in to do traditional cellphone things, like
>> ring, bring up the incall UI (so the user can answer/cancel), etc.
>
> Yes.  So what?  Nothing I said prevents the computer from waking up
> when a call comes in.  What I said was that when the user tells the
> computer to suspend (e.g., by writing "mem" to /sys/power/state), the
> computer should suspend even if some wakelocks are still locked.

But this could prevent the phone from ringing. What if the user-space
code that is responsible for playing the ringtone has been notified
that a call is coming in and starts reading the audio file with the
ringtone. At the same, the user, unaware that someone is calling,
presses the power button. If we ignore the wakelock in this situation,
the phone will not ring.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-31 18:39                     ` Rafael J. Wysocki
@ 2009-01-31 18:54                       ` Igor Stoppa
  2009-02-01  1:04                       ` Arve Hjønnevåg
  2009-02-02 11:55                       ` Pavel Machek
  2 siblings, 0 replies; 251+ messages in thread
From: Igor Stoppa @ 2009-01-31 18:54 UTC (permalink / raw)
  To: ext Rafael J. Wysocki; +Cc: Brian Swetland, linux-pm, Nigel Cunningham

Hi,
On Sat, 2009-01-31 at 19:39 +0100, ext Rafael J. Wysocki wrote:

> Well, I think that sleep states are not really useful in cell phones.
> Useful
> is the ability to put all devices into low power states separately and
> as
> needed (eg. after a period of inactivity).  IOW, the system as a whole
> is
> in the working state, but some parts of the hardware may be in low
> power states
> (even all of the I/O devices may be in low power states).  That may
> very well
> look "asleep" from the user point of view, but it is not a sleep
> state.

yup

it's very depressing that several years after we released the Nokia 770,
in the far 2005, people are still talking about these basic concepts.

And while it can be somehow excused for what concerns the x86 world of
laptops, it's even more depressing that such discussion surfaces in
relation to Android.

-- 

Cheers, Igor

---

Igor Stoppa
Maemo Software - Nokia Devices R&D - Helsinki

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-31 15:41                   ` Alan Stern
@ 2009-01-31 18:39                     ` Rafael J. Wysocki
  2009-01-31 18:54                       ` Igor Stoppa
                                         ` (2 more replies)
  2009-01-31 22:41                     ` Arve Hjønnevåg
  1 sibling, 3 replies; 251+ messages in thread
From: Rafael J. Wysocki @ 2009-01-31 18:39 UTC (permalink / raw)
  To: linux-pm; +Cc: Brian Swetland, Nigel Cunningham

Sorry for being late to the party, I had more urgent things to take care of.

On Saturday 31 January 2009, Alan Stern wrote:
> On Fri, 30 Jan 2009, Brian Swetland wrote:
> 
> > [Alan Stern <stern@rowland.harvard.edu>]
> > > > > Does the wakelock mechanism distinguish between suspend or power-state
> > > > > transitions that happen automatically and transitions requested
> > > > > directly by userspace?
> > > > 
> > > > No.
> > > 
> > > And I think this is a big mistake.  It makes sense to have locks for
> > > blocking auto suspend, but it does not make sense to prevent the user
> > > from putting his own computer to sleep.
> > > 
> > > For example: Suppose some program happens to hold a wakelock, perhaps 
> > > because of a simple bug, when the user closes the laptop lid and throws 
> > > the laptop into a backpack.  We don't want the computer to remain awake 
> > > under those circumstances!
> > 
> > It depends on the particular "computer" and the problem you're solving.
> 
> I disagree.

Yeah.

However, I think that what we are used to call a sleep (or suspend) state is
really a power off state for cell phone people.  So lets define what we're
talking about.

Sleep states (suspend to RAM, hibernation) are the states of the whole system
in which no instructions are executed by the processor(s).  The difference
between a sleep state and the power off state is that in a sleep state we have
some application context saved (in memory or in a storage device) and
(in principle) after the system goes back to the working state, the
applications can continue doing do whatever they had been doing before the
system was put into the sleep state.

If instructions are executed by the processor(s), the system is in the working
state.

> > Imagine the computer in question is a cellphone which is going to need
> > to wake up when a call comes in to do traditional cellphone things, like
> > ring, bring up the incall UI (so the user can answer/cancel), etc.
> 
> Yes.  So what?  Nothing I said prevents the computer from waking up 
> when a call comes in.  What I said was that when the user tells the 
> computer to suspend (e.g., by writing "mem" to /sys/power/state), the 
> computer should suspend even if some wakelocks are still locked.

Agreed.

There should be well defined set of signals that can wake up the system
from the sleep state and the user should be able to control them.
 
> > Or perhaps it's an always-connected data device that might get remote
> > messages (IM notifications, contacts/email sync, etc) over the network
> > while it's "asleep" that need some processing.
> 
> By "asleep", do you mean something other than suspended?  If you do 
> then you have misunderstood me.  I'm talking about a true suspend -- 
> that is, the suspend routines in drivers/base/power/main.c have run, 
> everything is in a low-power state or turned off, and the CPU isn't 
> running.
> 
> Obviously the computer can't do any processing when it is suspended.  
> The only thing it can do is resume.  And a resume can be initiated by a
> wide variety of signals, including such things as receipt of a network 
> packet or a phone call.
> 
> > Bad usage of wakelocks can certainly lead to poor battery life, but
> > there are definitely situations where you might want to operate in a
> > mode where the user considers the device "asleep" but it may still wake
> > up to handle certain tasks.
> 
> I don't care what the user thinks; I care about what the kernel 
> actually does.  If the user wants to delude himself into thinking the 
> computer is "asleep" while the kernel is still running, that's his 
> problem.

Well, I think that sleep states are not really useful in cell phones.  Useful
is the ability to put all devices into low power states separately and as
needed (eg. after a period of inactivity).  IOW, the system as a whole is
in the working state, but some parts of the hardware may be in low power states
(even all of the I/O devices may be in low power states).  That may very well
look "asleep" from the user point of view, but it is not a sleep state.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-31  0:02                 ` Arve Hjønnevåg
@ 2009-01-31 16:19                   ` Alan Stern
  2009-01-31 23:28                     ` Arve Hjønnevåg
  2009-02-02 10:42                     ` Uli Luckas
  0 siblings, 2 replies; 251+ messages in thread
From: Alan Stern @ 2009-01-31 16:19 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: swetland, Nigel Cunningham, linux-pm

On Fri, 30 Jan 2009, Arve Hjønnevåg wrote:

> On Fri, Jan 30, 2009 at 7:13 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
> > Personally, I think we need to be able to suspend computers even when
> > there are some unconsumed type-ahead characters in the input buffer.
> > But that's merely an implementation detail.
> 
> For us, the key that will turn the screen back on could be in this buffer.

Why do you have this fixation on the screen?  Forget about the screen 
and consider the system as a whole.

If the keyboard is enabled for wakeup, then typing a key _will_ wake 
the system up from suspend -- provided the key was typed after the 
system went to sleep.  It's silly to think that a key which was typed 
before the computer was suspended should cause it to wake up.


> > And I think this is a big mistake.  It makes sense to have locks for
> > blocking auto suspend, but it does not make sense to prevent the user
> > from putting his own computer to sleep.
> 
> If we go to sleep while the keypad wakelock is locked, then the keypad
> can no longer wake the system up. Note that this is specific to a
> keypad driver that scans the keypad matrix in software. A keyboard
> that generates an interrupt on every key change does not need its own
> wakelock.

Are you sure about this?  IIRC, you said earlier that your keyboard
generates an interrupt on a key press only when no other keys are
already pressed.  Okay -- so imagine the system suspends while a key is
pressed.  Pressing another key won't generate an interrupt and hence
won't wake up the system.  But releasing all the keys and then pressing
one _will_ generate an interrupt and so will wake up the system.  I
don't see any problem with this.

> Also, consider the case where the user presses the power button to go
> to sleep. Before this sleep request has finished a phone call comes
> in. The driver gets an interrupt, enqueues the message and locks a
> wakelock to make sure user-space gets a chance to process the message.
> If we ignore this wakelock, the phone will either not ring at all, or
> it will ring later when the device wakes up for some other reason.

For situations like this, the driver can simply refuse to suspend.  You 
don't need to use a wakelock.

In fact, if you did use a wakelock the behavior would be very strange.  
The user presses the power button, an instant later a call comes in, 
the device doesn't go to sleep, the user answers the call, and as soon 
as he hangs up (perhaps 10 minutes later) the wakelock is released and 
the device immediately goes to sleep!  Not what the user would expect.

> There is a class of applications where we do want the behaviour you
> describe, but so far all of them also require the screen to stay on.

Again this fixation with the screen.  Forget about the screen!

> This is handled entirely by our user-space framework which also has
> other options (like keeping the keypad backlight on).
> 
> > For example: Suppose some program happens to hold a wakelock, perhaps
> > because of a simple bug, when the user closes the laptop lid and throws
> > the laptop into a backpack.  We don't want the computer to remain awake
> > under those circumstances!
> 
> If the program hold the wakelock because of a bug we don't want the
> computer on, but if it operating correctly we do.

_I_ don't.  I want my device to suspend itself when I tell it to.  
Nothing is more annoying than a machine that doesn't turn itself off 
when told to do so.

> Since we don't have
> a good way to detect if the program locked the wakelock because of a
> bug, we assume it is correct and honor the request. We have debugging
> interfaces to report how often and for how long wakelocks are locked.
> We also do not allow applications to use wakelocks unless they have
> the required permission.

I admit that in a properly-operating system there won't be any 
wakelocks held because of bugs.  But there might be wakelocks held for 
other reasons, and I don't want _them_ to interfere when I suspend the 
machine either.

> > In fact, it would be a good idea to inform drivers (by passing a
> > particular pm_message_t argument to the suspend method) whether a
> > particular suspend was initiated by the user or as an auto suspend.  In
> > some cases a driver might very well want to allow one while preventing
> > the other.
> 
> I'm not sure this would be useful. We don't have any drivers that only
> need their wakelock to prevent auto suspend.

Maybe you do but you don't realize it.  :-)  And even if you don't, 
maybe other people do.

> And, every pm_suspend
> call is the result of unlocking the last wakelock.

Not true.  What if all the wakelocks are already unlocked when the user 
writes "mem" to /sys/power/state?


> > So what this example really shows is how wakelocks can be used to
> > prevent auto suspend from kicking back in the moment a keystroke is
> > received, before userspace has even had a chance to decide whether or
> > not to turn auto suspend off.  That's how you should describe it -- not
> > as a way of preventing keystrokes from waking the system up.
> 
> I was trying to show that user-space decides which keys allow the
> system to wake up. From the kernels point of view, every key causes a
> wakeup, but if user-space decides that the key should not wake the
> system, the system will go back to sleep as soon as possible (when all
> wakelocks are unlocked).

This paragraph is an excellent example of the muddiness of your 
thinking.  Userspace does _not_ decide which keys allow the system to 
wake up.  _All_ keys cause the system to wake up; userspace then 
decides which ones should cause the system to go right back into 
suspend.

But you don't need wakelocks to do this.  You can get the same effect
without them, just by running a program that writes "mem" (not
"auto-mem"!) to /sys/power/state whenever it sees a keystroke it
doesn't like.  So this example does not illustrate the power of
wakelocks.

> The user-space notion of suspend matches the early-suspend state.

Then call it "early-suspend"!  Don't call it "suspend" or "the 
user-space notion of suspend".

>  I
> consider early-suspend another stage, not a different concept. The
> difference between early-suspend and suspend is similar to the
> difference between device suspend and sysdev suspend. What would you
> call the the first stage of suspend that we have added?

"Early-suspend" is an okay name.  However I have the impression that
you want to prolong the early-suspend stage, and sometimes even go back
to full power directly from early-suspend.  There's nothing wrong with 
that; just make it clear that this is what you're doing.

In fact, I get the impression that much of what you're talking about 
has to do with providing ways to short-circuit a complete suspend and 
go directly from early-suspend back to full power.

Alan Stern

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-31  7:47                 ` Brian Swetland
@ 2009-01-31 15:41                   ` Alan Stern
  2009-01-31 18:39                     ` Rafael J. Wysocki
  2009-01-31 22:41                     ` Arve Hjønnevåg
  0 siblings, 2 replies; 251+ messages in thread
From: Alan Stern @ 2009-01-31 15:41 UTC (permalink / raw)
  To: Brian Swetland; +Cc: Nigel Cunningham, linux-pm

On Fri, 30 Jan 2009, Brian Swetland wrote:

> [Alan Stern <stern@rowland.harvard.edu>]
> > > > Does the wakelock mechanism distinguish between suspend or power-state
> > > > transitions that happen automatically and transitions requested
> > > > directly by userspace?
> > > 
> > > No.
> > 
> > And I think this is a big mistake.  It makes sense to have locks for
> > blocking auto suspend, but it does not make sense to prevent the user
> > from putting his own computer to sleep.
> > 
> > For example: Suppose some program happens to hold a wakelock, perhaps 
> > because of a simple bug, when the user closes the laptop lid and throws 
> > the laptop into a backpack.  We don't want the computer to remain awake 
> > under those circumstances!
> 
> It depends on the particular "computer" and the problem you're solving.

I disagree.

> Imagine the computer in question is a cellphone which is going to need
> to wake up when a call comes in to do traditional cellphone things, like
> ring, bring up the incall UI (so the user can answer/cancel), etc.

Yes.  So what?  Nothing I said prevents the computer from waking up 
when a call comes in.  What I said was that when the user tells the 
computer to suspend (e.g., by writing "mem" to /sys/power/state), the 
computer should suspend even if some wakelocks are still locked.

> Or perhaps it's an always-connected data device that might get remote
> messages (IM notifications, contacts/email sync, etc) over the network
> while it's "asleep" that need some processing.

By "asleep", do you mean something other than suspended?  If you do 
then you have misunderstood me.  I'm talking about a true suspend -- 
that is, the suspend routines in drivers/base/power/main.c have run, 
everything is in a low-power state or turned off, and the CPU isn't 
running.

Obviously the computer can't do any processing when it is suspended.  
The only thing it can do is resume.  And a resume can be initiated by a
wide variety of signals, including such things as receipt of a network 
packet or a phone call.

> Bad usage of wakelocks can certainly lead to poor battery life, but
> there are definitely situations where you might want to operate in a
> mode where the user considers the device "asleep" but it may still wake
> up to handle certain tasks.

I don't care what the user thinks; I care about what the kernel 
actually does.  If the user wants to delude himself into thinking the 
computer is "asleep" while the kernel is still running, that's his 
problem.

Alan Stern

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-30 15:13               ` Alan Stern
  2009-01-31  0:02                 ` Arve Hjønnevåg
@ 2009-01-31  7:47                 ` Brian Swetland
  2009-01-31 15:41                   ` Alan Stern
  1 sibling, 1 reply; 251+ messages in thread
From: Brian Swetland @ 2009-01-31  7:47 UTC (permalink / raw)
  To: Alan Stern; +Cc: Nigel Cunningham, linux-pm

[Alan Stern <stern@rowland.harvard.edu>]
> > > Does the wakelock mechanism distinguish between suspend or power-state
> > > transitions that happen automatically and transitions requested
> > > directly by userspace?
> > 
> > No.
> 
> And I think this is a big mistake.  It makes sense to have locks for
> blocking auto suspend, but it does not make sense to prevent the user
> from putting his own computer to sleep.
> 
> For example: Suppose some program happens to hold a wakelock, perhaps 
> because of a simple bug, when the user closes the laptop lid and throws 
> the laptop into a backpack.  We don't want the computer to remain awake 
> under those circumstances!

It depends on the particular "computer" and the problem you're solving.

Imagine the computer in question is a cellphone which is going to need
to wake up when a call comes in to do traditional cellphone things, like
ring, bring up the incall UI (so the user can answer/cancel), etc.

Or perhaps it's an always-connected data device that might get remote
messages (IM notifications, contacts/email sync, etc) over the network
while it's "asleep" that need some processing.

Bad usage of wakelocks can certainly lead to poor battery life, but
there are definitely situations where you might want to operate in a
mode where the user considers the device "asleep" but it may still wake
up to handle certain tasks.

Brian

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-30 15:13               ` Alan Stern
@ 2009-01-31  0:02                 ` Arve Hjønnevåg
  2009-01-31 16:19                   ` Alan Stern
  2009-01-31  7:47                 ` Brian Swetland
  1 sibling, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-01-31  0:02 UTC (permalink / raw)
  To: Alan Stern; +Cc: swetland, Nigel Cunningham, linux-pm

On Fri, Jan 30, 2009 at 7:13 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
> Personally, I think we need to be able to suspend computers even when
> there are some unconsumed type-ahead characters in the input buffer.
> But that's merely an implementation detail.

For us, the key that will turn the screen back on could be in this buffer.

>> > Does the wakelock mechanism distinguish between suspend or power-state
>> > transitions that happen automatically and transitions requested
>> > directly by userspace?
>>
>> No.
>
> And I think this is a big mistake.  It makes sense to have locks for
> blocking auto suspend, but it does not make sense to prevent the user
> from putting his own computer to sleep.

If we go to sleep while the keypad wakelock is locked, then the keypad
can no longer wake the system up. Note that this is specific to a
keypad driver that scans the keypad matrix in software. A keyboard
that generates an interrupt on every key change does not need its own
wakelock.

Also, consider the case where the user presses the power button to go
to sleep. Before this sleep request has finished a phone call comes
in. The driver gets an interrupt, enqueues the message and locks a
wakelock to make sure user-space gets a chance to process the message.
If we ignore this wakelock, the phone will either not ring at all, or
it will ring later when the device wakes up for some other reason.

There is a class of applications where we do want the behaviour you
describe, but so far all of them also require the screen to stay on.
This is handled entirely by our user-space framework which also has
other options (like keeping the keypad backlight on).

> For example: Suppose some program happens to hold a wakelock, perhaps
> because of a simple bug, when the user closes the laptop lid and throws
> the laptop into a backpack.  We don't want the computer to remain awake
> under those circumstances!

If the program hold the wakelock because of a bug we don't want the
computer on, but if it operating correctly we do. Since we don't have
a good way to detect if the program locked the wakelock because of a
bug, we assume it is correct and honor the request. We have debugging
interfaces to report how often and for how long wakelocks are locked.
We also do not allow applications to use wakelocks unless they have
the required permission.

> In fact, it would be a good idea to inform drivers (by passing a
> particular pm_message_t argument to the suspend method) whether a
> particular suspend was initiated by the user or as an auto suspend.  In
> some cases a driver might very well want to allow one while preventing
> the other.

I'm not sure this would be useful. We don't have any drivers that only
need their wakelock to prevent auto suspend. And, every pm_suspend
call is the result of unlocking the last wakelock.

>> >> - The user-space input-event thread returns from read. It determines that the
>> >>   key should not wake up the system, releases the process-input-events
>> >>   wakelock and calls select or poll.
>> >
>> > This makes no sense.  If the system wasn't asleep to begin with, how
>> > could the key wake it up?  And if the system _was_ asleep to begin
>> > with, how could all of this happen without waking the system up?
>>
>> What I mean here is that the screen turns on and the system does not
>> immediately go back to sleep. The user-space framework has its own
>> idea of whether the system is awake or not. I can change this to
>> "fully wake up" or "turn on the screen".
>
> So what this example really shows is how wakelocks can be used to
> prevent auto suspend from kicking back in the moment a keystroke is
> received, before userspace has even had a chance to decide whether or
> not to turn auto suspend off.  That's how you should describe it -- not
> as a way of preventing keystrokes from waking the system up.

I was trying to show that user-space decides which keys allow the
system to wake up. From the kernels point of view, every key causes a
wakeup, but if user-space decides that the key should not wake the
system, the system will go back to sleep as soon as possible (when all
wakelocks are unlocked).

> In fact, you have made the discussion very confusing by using the same
> terms ("suspend", "wake up", and so) for at least three different
> concepts: full system suspend, early-suspend, and this new userspace
> framework's idea of suspend.  Not to mention this other notion of
> turning off the screen (and perhaps a few other devices) while leaving
> the system as a whole running.  In the future, please use different
> words when talking about different concepts.

The user-space notion of suspend matches the early-suspend state. I
consider early-suspend another stage, not a different concept. The
difference between early-suspend and suspend is similar to the
difference between device suspend and sysdev suspend. What would you
call the the first stage of suspend that we have added?

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-30  4:40             ` Arve Hjønnevåg
  2009-01-30  6:04               ` Arve Hjønnevåg
  2009-01-30  9:11               ` Pavel Machek
@ 2009-01-30 15:13               ` Alan Stern
  2009-01-31  0:02                 ` Arve Hjønnevåg
  2009-01-31  7:47                 ` Brian Swetland
  2 siblings, 2 replies; 251+ messages in thread
From: Alan Stern @ 2009-01-30 15:13 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: swetland, Nigel Cunningham, linux-pm

On Thu, 29 Jan 2009, Arve Hjønnevåg wrote:

> > Does the input-event-queue wakelock always prevent the system from
> > suspending whenever the input queue is nonempty?
> 
> Yes.
> 
> > Does that mean if I
> > type ahead while a program is running, I can't suspend the computer
> > until the program processes the keystrokes?
> 
> The actual suspend will not happen until all the keys are processed,
> but user-space can turn the screen off at any time.

Okay, this is slowly getting clearer.

Personally, I think we need to be able to suspend computers even when 
there are some unconsumed type-ahead characters in the input buffer.  
But that's merely an implementation detail.

> > Does the wakelock mechanism distinguish between suspend or power-state
> > transitions that happen automatically and transitions requested
> > directly by userspace?
> 
> No.

And I think this is a big mistake.  It makes sense to have locks for
blocking auto suspend, but it does not make sense to prevent the user
from putting his own computer to sleep.

For example: Suppose some program happens to hold a wakelock, perhaps 
because of a simple bug, when the user closes the laptop lid and throws 
the laptop into a backpack.  We don't want the computer to remain awake 
under those circumstances!

In fact, it would be a good idea to inform drivers (by passing a 
particular pm_message_t argument to the suspend method) whether a 
particular suspend was initiated by the user or as an auto suspend.  In 
some cases a driver might very well want to allow one while preventing 
the other.

> When the user decides to suspend, we use the early-suspend api to tell
> the kernel to turn of the screen and possibly some other devices.
> Wakelocks are useful without early-suspend, but it must always enter
> suspend when the last wakelock is unlocked.

Wakelocks and early-suspend are separate issues.  Let's consider only
wakelocks.

> >> - The user-space input-event thread returns from read. It determines that the
> >>   key should not wake up the system, releases the process-input-events
> >>   wakelock and calls select or poll.
> >
> > This makes no sense.  If the system wasn't asleep to begin with, how
> > could the key wake it up?  And if the system _was_ asleep to begin
> > with, how could all of this happen without waking the system up?
> 
> What I mean here is that the screen turns on and the system does not
> immediately go back to sleep. The user-space framework has its own
> idea of whether the system is awake or not. I can change this to
> "fully wake up" or "turn on the screen".

So what this example really shows is how wakelocks can be used to
prevent auto suspend from kicking back in the moment a keystroke is
received, before userspace has even had a chance to decide whether or
not to turn auto suspend off.  That's how you should describe it -- not
as a way of preventing keystrokes from waking the system up.

In fact, you have made the discussion very confusing by using the same
terms ("suspend", "wake up", and so) for at least three different
concepts: full system suspend, early-suspend, and this new userspace
framework's idea of suspend.  Not to mention this other notion of
turning off the screen (and perhaps a few other devices) while leaving
the system as a whole running.  In the future, please use different
words when talking about different concepts.

Alan Stern

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-30  9:11               ` Pavel Machek
@ 2009-01-30 12:34                 ` Uli Luckas
  2009-02-02 11:46                   ` Pavel Machek
  0 siblings, 1 reply; 251+ messages in thread
From: Uli Luckas @ 2009-01-30 12:34 UTC (permalink / raw)
  To: linux-pm; +Cc: swetland, Nigel Cunningham

On Friday, 30. January 2009, Pavel Machek wrote:
> > >> - The user-space input-event thread returns from read. It determines
> > >> that the key should not wake up the system, releases the
> > >> process-input-events wakelock and calls select or poll.
> > >
> > > This makes no sense.  If the system wasn't asleep to begin with, how
> > > could the key wake it up?  And if the system _was_ asleep to begin
> > > with, how could all of this happen without waking the system up?
> >
> > What I mean here is that the screen turns on and the system does not
> > immediately go back to sleep. The user-space framework has its own
> > idea of whether the system is awake or not. I can change this to
> > "fully wake up" or "turn on the screen".
>
> "turn on the screen", please. (But I still don't quite get it; screen
> should be at full control of userspace, so why is kernel interaction
> needed?) Pavel
>
Turning on the screen is only on thing userspace can do. What exactly happens 
is beyon the scope of the kernel interface.
The right term is probably something like "break out of auto-suspend" or "wake 
from auto suspend".
 

-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-30  9:08           ` Pavel Machek
@ 2009-01-30  9:25             ` Brian Swetland
  0 siblings, 0 replies; 251+ messages in thread
From: Brian Swetland @ 2009-01-30  9:25 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Nigel Cunningham, linux-pm

[Pavel Machek <pavel@ucw.cz>]
> > On Thu, Jan 29, 2009 at 5:04 AM, Pavel Machek <pavel@ucw.cz> wrote:
> > > AFAICT, this is something very different. It is attempt to do
> > > autosuspend right. Imagine burning cd... right now you can suspend,
> > > and it will just stop the burn.
> > >
> > > Wakelocks code allows you to tell the machine 'feel free to suspend
> > > when you have nothing to do'... so the machine will burn the cd and
> > > then suspend.
...
> 
> I don't get it. So you are running userspace while system is
> suspended? 

The general idea is that we aggressively try to be suspended as much as
possible.  Typically this means that when the display is turned off
(after the user inactivity timeout, managed from a userspace process),
suspend is requested.

If work is being done that requires the system to keep running, a
wakelock is held, preventing suspend from happening.

If suspend happens, but we resume due to a wakeup interrupt (for
example, user pressing a key), a wakelock is typically acquired during
the interrupt handler (which is called while we're resuming) and
arranged to be held until the event is delivered to userspace.  The
userspace code which receives events acquires a wakelock before draining
the queue (after select returns, before reading, etc) so that it keeps
the system awake until the event is processed.

In many cases the system pretty rapidly drops wakelocks and returns to
suspend state.

Brian

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-30  4:40             ` Arve Hjønnevåg
  2009-01-30  6:04               ` Arve Hjønnevåg
@ 2009-01-30  9:11               ` Pavel Machek
  2009-01-30 12:34                 ` Uli Luckas
  2009-01-30 15:13               ` Alan Stern
  2 siblings, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-01-30  9:11 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: swetland, Nigel Cunningham, linux-pm


> >> - The user-space input-event thread returns from read. It determines that the
> >>   key should not wake up the system, releases the process-input-events
> >>   wakelock and calls select or poll.
> >
> > This makes no sense.  If the system wasn't asleep to begin with, how
> > could the key wake it up?  And if the system _was_ asleep to begin
> > with, how could all of this happen without waking the system up?
> 
> What I mean here is that the screen turns on and the system does not
> immediately go back to sleep. The user-space framework has its own
> idea of whether the system is awake or not. I can change this to
> "fully wake up" or "turn on the screen".

"turn on the screen", please. (But I still don't quite get it; screen
should be at full control of userspace, so why is kernel interaction needed?)
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-30  1:16         ` Arve Hjønnevåg
  2009-01-30  3:27           ` Alan Stern
@ 2009-01-30  9:08           ` Pavel Machek
  2009-01-30  9:25             ` Brian Swetland
  1 sibling, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-01-30  9:08 UTC (permalink / raw)
  To: Arve Hj?nnev?g; +Cc: swetland, Nigel Cunningham, linux-pm

> On Thu, Jan 29, 2009 at 5:04 AM, Pavel Machek <pavel@ucw.cz> wrote:
> > AFAICT, this is something very different. It is attempt to do
> > autosuspend right. Imagine burning cd... right now you can suspend,
> > and it will just stop the burn.
> >
> > Wakelocks code allows you to tell the machine 'feel free to suspend
> > when you have nothing to do'... so the machine will burn the cd and
> > then suspend.
> >
> 
> Yes, wakelocks solves this problem, but our auto-suspend code is all
> in user-space so the kernel would not have to be involved in that
> particular example.
> 
> I added an example to the document that may help illustrate why we
> added wakelock support in the kernel:
> 
> ---
> Documentation/power/wakelocks.txt
> Wakelocks
> =========
> 
> A wakelock prevents the system from entering suspend or other low-power
> states when active. 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.
> 
> Wakelocks can be used to allow user-space to decide which keys should wake
> the system. 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.
> - 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 system, releases the process-input-events
>   wakelock and calls select or poll.

I don't get it. So you are running userspace while system is
suspended? 
								Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-30  4:40             ` Arve Hjønnevåg
@ 2009-01-30  6:04               ` Arve Hjønnevåg
  2009-02-02 11:49                 ` Pavel Machek
  2009-01-30  9:11               ` Pavel Machek
  2009-01-30 15:13               ` Alan Stern
  2 siblings, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-01-30  6:04 UTC (permalink / raw)
  To: Alan Stern; +Cc: swetland, Nigel Cunningham, linux-pm

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

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-30  3:27           ` Alan Stern
@ 2009-01-30  4:40             ` Arve Hjønnevåg
  2009-01-30  6:04               ` Arve Hjønnevåg
                                 ` (2 more replies)
  0 siblings, 3 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-01-30  4:40 UTC (permalink / raw)
  To: Alan Stern; +Cc: swetland, Nigel Cunningham, linux-pm

On Thu, Jan 29, 2009 at 7:27 PM, Alan Stern <stern@rowland.harvard.edu> wrote:
> On Thu, 29 Jan 2009, Arve Hjønnevåg wrote:
>> A wakelock prevents the system from entering suspend or other low-power
>> states when active.
>
> I wish your writing was clearer.  "when active" could mean "when the
> system is active" or "when the wakelock is active".  Try to be less
> ambiguous.  For example: "When a wakelock is locked, it blocks the
> system from entering suspend or other low-power states."

OK.

>> 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.
>
> Here you talk about "will not be entered from idle", whereas above you
> mention "when active".  So which is it?  Does a wakelock affect an
> active system or an idle system?

Most of the document refers to wakelocks of type WAKE_LOCK_SUSPEND. If
create a wakelock of type WAKE_LOCK_IDLE affects the idle power state
instead.

>> - The Keypad driver gets an interrupt. It then locks the keypad-scan wakelock
>>   and starts scanning the keypad.
>
> Is the system asleep to begin with?  If it is, how does the keypad
> driver get this interrupt unless the system first wakes up?

It may have been. If it was, wake up should be for the interrupt using
the existing set_irq_wake call.

> Conversely, what happens if the PM core has just started a system
> suspend?  Does locking the wakelock force the suspend to be aborted?

Yes, assuming is has not already suspended all the drivers and
disabled interrupts.

>
>> - 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.
>
> What use is the keypad-scan wakelock?  Isn't the fact that the keypad
> driver's interrupt handler is running already sufficient to prevent or
> delay a system suspend?

Once you hold one key down, you cannot get another interrupt if you
press another key on the same input line. The driver uses a timer to
scan the keypad matrix until all keys are released. A key on a
dedicated input with both rising and falling edge detect interrupt
would not need this 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.
>
> Does the input-event-queue wakelock always prevent the system from
> suspending whenever the input queue is nonempty?

Yes.

> Does that mean if I
> type ahead while a program is running, I can't suspend the computer
> until the program processes the keystrokes?

The actual suspend will not happen until all the keys are processed,
but user-space can turn the screen off at any time.

> Does the wakelock mechanism distinguish between suspend or power-state
> transitions that happen automatically and transitions requested
> directly by userspace?

No.

> This would be a little more understandable if
> the wakelocks only prevent the system from suspending itself and don't
> prevent me from suspending the system.

When the user decides to suspend, we use the early-suspend api to tell
the kernel to turn of the screen and possibly some other devices.
Wakelocks are useful without early-suspend, but it must always enter
suspend when the last wakelock is unlocked.

>
>> - The user-space input-event thread returns from read. It determines that the
>>   key should not wake up the system, releases the process-input-events
>>   wakelock and calls select or poll.
>
> This makes no sense.  If the system wasn't asleep to begin with, how
> could the key wake it up?  And if the system _was_ asleep to begin
> with, how could all of this happen without waking the system up?

What I mean here is that the screen turns on and the system does not
immediately go back to sleep. The user-space framework has its own
idea of whether the system is awake or not. I can change this to
"fully wake up" or "turn on the screen".

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-30  1:16         ` Arve Hjønnevåg
@ 2009-01-30  3:27           ` Alan Stern
  2009-01-30  4:40             ` Arve Hjønnevåg
  2009-01-30  9:08           ` Pavel Machek
  1 sibling, 1 reply; 251+ messages in thread
From: Alan Stern @ 2009-01-30  3:27 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: swetland, Nigel Cunningham, linux-pm

On Thu, 29 Jan 2009, Arve Hjønnevåg wrote:

> Documentation/power/wakelocks.txt
> Wakelocks
> =========
> 
> A wakelock prevents the system from entering suspend or other low-power
> states when active.

I wish your writing was clearer.  "when active" could mean "when the 
system is active" or "when the wakelock is active".  Try to be less 
ambiguous.  For example: "When a wakelock is locked, it blocks the 
system from entering suspend or other low-power 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.

Here you talk about "will not be entered from idle", whereas above you 
mention "when active".  So which is it?  Does a wakelock affect an 
active system or an idle system?

> Wakelocks can be used to allow user-space to decide which keys should wake
> the system. 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.

Is the system asleep to begin with?  If it is, how does the keypad 
driver get this interrupt unless the system first wakes up?

Conversely, what happens if the PM core has just started a system
suspend?  Does locking the wakelock force the suspend to be aborted?

> - 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.

What use is the keypad-scan wakelock?  Isn't the fact that the keypad
driver's interrupt handler is running already sufficient to prevent or
delay a system suspend?

> - 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.

Does the input-event-queue wakelock always prevent the system from 
suspending whenever the input queue is nonempty?  Does that mean if I 
type ahead while a program is running, I can't suspend the computer 
until the program processes the keystrokes?

Does the wakelock mechanism distinguish between suspend or power-state
transitions that happen automatically and transitions requested
directly by userspace?  This would be a little more understandable if
the wakelocks only prevent the system from suspending itself and don't
prevent me from suspending the system.

> - The user-space input-event thread returns from read. It determines that the
>   key should not wake up the system, releases the process-input-events
>   wakelock and calls select or poll.

This makes no sense.  If the system wasn't asleep to begin with, how 
could the key wake it up?  And if the system _was_ asleep to begin 
with, how could all of this happen without waking the system up?

Alan Stern

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-29 13:04       ` Pavel Machek
@ 2009-01-30  1:16         ` Arve Hjønnevåg
  2009-01-30  3:27           ` Alan Stern
  2009-01-30  9:08           ` Pavel Machek
  0 siblings, 2 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-01-30  1:16 UTC (permalink / raw)
  To: Pavel Machek; +Cc: swetland, Nigel Cunningham, linux-pm

On Thu, Jan 29, 2009 at 5:04 AM, Pavel Machek <pavel@ucw.cz> wrote:
> AFAICT, this is something very different. It is attempt to do
> autosuspend right. Imagine burning cd... right now you can suspend,
> and it will just stop the burn.
>
> Wakelocks code allows you to tell the machine 'feel free to suspend
> when you have nothing to do'... so the machine will burn the cd and
> then suspend.
>

Yes, wakelocks solves this problem, but our auto-suspend code is all
in user-space so the kernel would not have to be involved in that
particular example.

I added an example to the document that may help illustrate why we
added wakelock support in the kernel:

---
Documentation/power/wakelocks.txt
Wakelocks
=========

A wakelock prevents the system from entering suspend or other low-power
states when active. 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.

Wakelocks can be used to allow user-space to decide which keys should wake
the system. 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.
- 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 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

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-15 15:08     ` Alan Stern
  2009-01-15 20:34       ` Arve Hjønnevåg
@ 2009-01-29 13:04       ` Pavel Machek
  2009-01-30  1:16         ` Arve Hjønnevåg
  1 sibling, 1 reply; 251+ messages in thread
From: Pavel Machek @ 2009-01-29 13:04 UTC (permalink / raw)
  To: Alan Stern; +Cc: swetland, Nigel Cunningham, linux-pm

On Thu 2009-01-15 10:08:51, Alan Stern wrote:
> 6~On Wed, 14 Jan 2009, Arve Hj?nnev?g wrote:
> 
> > On Wed, Jan 14, 2009 at 1:01 AM, Nigel Cunningham
> > <ncunningham@crca.org.au> wrote:
> > > Would you be able to provide some more documentation?
> > 
> > Would something like this help:
> > Documentation/power/wakelocks.txt
> > 
> > Wakelocks
> > =========
> > 
> > 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.
> 
> Apart from the grammatical errors in this document and the
> over-engineering it describes, the writeup is terribly ambiguous.  
> What do you mean by "prevents a full system suspend"?  Does it mean
> that attempts to suspend the system will fail?  Or will they just
> block until all these locks are released?
 
AFAICT, this is something very different. It is attempt to do
autosuspend right. Imagine burning cd... right now you can suspend,
and it will just stop the burn.

Wakelocks code allows you to tell the machine 'feel free to suspend
when you have nothing to do'... so the machine will burn the cd and
then suspend.

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-14  1:27 Arve Hjønnevåg
  2009-01-14  9:01 ` Nigel Cunningham
@ 2009-01-28 19:31 ` Pavel Machek
  1 sibling, 0 replies; 251+ messages in thread
From: Pavel Machek @ 2009-01-28 19:31 UTC (permalink / raw)
  To: Arve Hj??nnev??g; +Cc: swetland, linux-pm

On Tue 2009-01-13 17:27:45, Arve Hj??nnev??g wrote:
> The following patch series adds two apis, wakelock and earlysuspend.
> The Android platform uses the earlysuspend api to turn the screen
> and some input devices on and off. The wakelock code determines when
> to enter the full suspend state.
> 
> These apis could also be useful to other platforms where the goal is
> to enter full suspend whenever possible.

'sleepy linux'. Thanks for doing this.
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-15 15:08     ` Alan Stern
@ 2009-01-15 20:34       ` Arve Hjønnevåg
  2009-01-29 13:04       ` Pavel Machek
  1 sibling, 0 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-01-15 20:34 UTC (permalink / raw)
  To: Alan Stern; +Cc: swetland, Nigel Cunningham, linux-pm

On Thu, Jan 15, 2009 at 7:08 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
> What do you mean by "prevents a full system suspend"?  Does it mean
> that attempts to suspend the system will fail?  Or will they just
> block until all these locks are released?

When you release the last wakelock, the wakelock code will attempt to
suspend. Holding a wakelock prevents this, and it also will abort
suspend for you if the system is in the middle of suspending drivers.

> Is there in fact any reason to add a new way for drivers to prevent a
> full system suspend?  They can already cause a suspend to fail by
> returning an error from their suspend method, or cause a suspend to
> block by sleeping in their suspend method.

Returning an error would from suspend works to some degree, but it
provides no indication of when to retry the suspend operation. Also
each suspend attempt will freeze and thaw every process in the system
so it is not a good way to ensure that userspace code gets to run.
Sleeping in the suspend method will also prevent a wakeup so it is
only usable for short delays. Wakelocks can be held for hours if
needed.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-15  4:42   ` Arve Hjønnevåg
@ 2009-01-15 15:08     ` Alan Stern
  2009-01-15 20:34       ` Arve Hjønnevåg
  2009-01-29 13:04       ` Pavel Machek
  0 siblings, 2 replies; 251+ messages in thread
From: Alan Stern @ 2009-01-15 15:08 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: swetland, Nigel Cunningham, linux-pm

6~On Wed, 14 Jan 2009, Arve Hjønnevåg wrote:

> On Wed, Jan 14, 2009 at 1:01 AM, Nigel Cunningham
> <ncunningham@crca.org.au> wrote:
> > Would you be able to provide some more documentation?
> 
> Would something like this help:
> Documentation/power/wakelocks.txt
> 
> Wakelocks
> =========
> 
> 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.

Apart from the grammatical errors in this document and the
over-engineering it describes, the writeup is terribly ambiguous.  
What do you mean by "prevents a full system suspend"?  Does it mean
that attempts to suspend the system will fail?  Or will they just
block until all these locks are released?

Is there in fact any reason to add a new way for drivers to prevent a 
full system suspend?  They can already cause a suspend to fail by 
returning an error from their suspend method, or cause a suspend to 
block by sleeping in their suspend method.

Alan Stern

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-14  9:01 ` Nigel Cunningham
  2009-01-15  0:10   ` Arve Hjønnevåg
@ 2009-01-15  4:42   ` Arve Hjønnevåg
  2009-01-15 15:08     ` Alan Stern
  1 sibling, 1 reply; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-01-15  4:42 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: swetland, linux-pm

On Wed, Jan 14, 2009 at 1:01 AM, Nigel Cunningham
<ncunningham@crca.org.au> wrote:
> Would you be able to provide some more documentation?

Would something like this help:
Documentation/power/wakelocks.txt

Wakelocks
=========

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.


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 wake_lock is already held or not. It is useful if the
driver woke up other parts of the system that does 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 wake lock. The timeout here is specified nanoseconds.
Write "lockname" to /sys/power/wake_unlock to unlock a user wake lock.

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



-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-14  9:01 ` Nigel Cunningham
@ 2009-01-15  0:10   ` Arve Hjønnevåg
  2009-01-15  4:42   ` Arve Hjønnevåg
  1 sibling, 0 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-01-15  0:10 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: swetland, linux-pm

On Wed, Jan 14, 2009 at 1:01 AM, Nigel Cunningham
<ncunningham@crca.org.au> wrote:
> Would you be able to provide some more documentation? In particular, I'm
> wondering what's 'early' about earlysuspend. It might also be good to
> something to Documentation/power explaining what the apis are, when/how
> they're supposed to be used and such like.

I called it earlysuspend since it a prerequisite for entering the
normal suspend state. It is really the user visible suspend state.

> In the Kconfig files, I'm also missing the point to HAS_EARLYSUSPEND and
> HAS_WAKELOCK - they're bools that depends only on  and WAKELOCK
> respectively, so shouldn't you be able to just use the later symbols in
> ifdefs?

I initially had provided the wakelock and earlysuspend apis on top of
the android_power driver then added the current implementation. If
there is no interest in allowing multiple implementations of the api,
can can remove these.

> There are a few inlined #ifdefs (#ifdef CONFIG_WAKELOCK_STAT, eg) - the
> convention as I understand it is to keep #ifdefs out of .c files as much
> as possible, #ifdef'ing functions in header files instead.

I would not want to move these to the (existing) header file as they
are private to the wakelock implementation, but I could add some some
helper functions in a single #ifdef block.

-- 
Arve Hjønnevåg

^ permalink raw reply	[flat|nested] 251+ messages in thread

* Re: [RFC][PATCH 00/11] Android PM extensions
  2009-01-14  1:27 Arve Hjønnevåg
@ 2009-01-14  9:01 ` Nigel Cunningham
  2009-01-15  0:10   ` Arve Hjønnevåg
  2009-01-15  4:42   ` Arve Hjønnevåg
  2009-01-28 19:31 ` Pavel Machek
  1 sibling, 2 replies; 251+ messages in thread
From: Nigel Cunningham @ 2009-01-14  9:01 UTC (permalink / raw)
  To: Arve Hjønnevåg; +Cc: swetland, linux-pm

Hi Arve.

On Tue, 2009-01-13 at 17:27 -0800, Arve Hjønnevåg wrote:
> The following patch series adds two apis, wakelock and earlysuspend.
> The Android platform uses the earlysuspend api to turn the screen
> and some input devices on and off. The wakelock code determines when
> to enter the full suspend state.
> 
> These apis could also be useful to other platforms where the goal is
> to enter full suspend whenever possible.

A few general comments:

Would you be able to provide some more documentation? In particular, I'm
wondering what's 'early' about earlysuspend. It might also be good to
something to Documentation/power explaining what the apis are, when/how
they're supposed to be used and such like.

In the Kconfig files, I'm also missing the point to HAS_EARLYSUSPEND and
HAS_WAKELOCK - they're bools that depends only on  and WAKELOCK
respectively, so shouldn't you be able to just use the later symbols in
ifdefs?

There are a few inlined #ifdefs (#ifdef CONFIG_WAKELOCK_STAT, eg) - the
convention as I understand it is to keep #ifdefs out of .c files as much
as possible, #ifdef'ing functions in header files instead.

Regards,

Nigel

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

* [RFC][PATCH 00/11] Android PM extensions
@ 2009-01-14  1:27 Arve Hjønnevåg
  2009-01-14  9:01 ` Nigel Cunningham
  2009-01-28 19:31 ` Pavel Machek
  0 siblings, 2 replies; 251+ messages in thread
From: Arve Hjønnevåg @ 2009-01-14  1:27 UTC (permalink / raw)
  To: linux-pm; +Cc: swetland

The following patch series adds two apis, wakelock and earlysuspend.
The Android platform uses the earlysuspend api to turn the screen
and some input devices on and off. The wakelock code determines when
to enter the full suspend state.

These apis could also be useful to other platforms where the goal is
to enter full suspend whenever possible.

--
Arve Hjønnevåg

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

^ permalink raw reply	[flat|nested] 251+ messages in thread

end of thread, other threads:[~2009-03-08 12:34 UTC | newest]

Thread overview: 251+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-02-05  2:50 [RFC][PATCH 00/11] Android PM extensions Arve Hjønnevåg
2009-02-05  2:50 ` [PATCH 01/13] PM: Add wake lock api Arve Hjønnevåg
2009-02-05  2:50   ` [PATCH 02/13] PM: Add early suspend api Arve Hjønnevåg
2009-02-05  2:50     ` [PATCH 03/13] PM: Implement wakelock api Arve Hjønnevåg
2009-02-05  2:50       ` [PATCH 04/13] PM: wakelock: Override wakelocks when using /sys/power/state Arve Hjønnevåg
2009-02-05  2:50         ` [PATCH 05/13] PM: Add option to disable /sys/power/state interface Arve Hjønnevåg
2009-02-05  2:50           ` [PATCH 06/13] PM: Implement early suspend api Arve Hjønnevåg
2009-02-05  2:50             ` [PATCH 07/13] PM: wakelock: Add /sys/power/request_state Arve Hjønnevåg
2009-02-05  2:50               ` [PATCH 08/13] PM: Add user-space wake lock api Arve Hjønnevåg
2009-02-05  2:50                 ` [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held Arve Hjønnevåg
2009-02-05  2:50                   ` [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes Arve Hjønnevåg
2009-02-05  2:50                     ` [PATCH 11/13] PM: earlysuspend: Removing dependence on console Arve Hjønnevåg
2009-02-05  2:50                       ` [PATCH 12/13] Input: Hold wake lock while event queue is not empty Arve Hjønnevåg
2009-02-05  2:50                         ` [PATCH 13/13] ledtrig-sleep: Add led trigger for sleep debugging Arve Hjønnevåg
2009-02-05  9:08                         ` [PATCH 12/13] Input: Hold wake lock while event queue is not empty Pavel Machek
2009-02-05  9:06                       ` [PATCH 11/13] PM: earlysuspend: Removing dependence on console Pavel Machek
2009-02-05  9:42                         ` Arve Hjønnevåg
2009-02-05  9:53                           ` Pavel Machek
2009-02-05  9:03                     ` [PATCH 10/13] PM: earlysuspend: Add console switch when user requested sleep state changes Pavel Machek
2009-02-05  9:37                       ` Arve Hjønnevåg
2009-02-05  9:51                         ` Pavel Machek
2009-02-05 10:54                         ` Uli Luckas
2009-02-06  2:29                       ` Arve Hjønnevåg
2009-02-08 22:02                         ` Pavel Machek
2009-02-08 22:53                           ` Arve Hjønnevåg
2009-02-08 22:58                             ` Pavel Machek
2009-02-05  8:55                   ` [PATCH 09/13] PM: wakelock: Abort task freezing if a wake lock is held Pavel Machek
2009-02-05  9:30                     ` Arve Hjønnevåg
2009-02-05  9:49                       ` Pavel Machek
2009-02-05  9:58                         ` Arve Hjønnevåg
2009-02-05 10:02                           ` Pavel Machek
2009-02-05 10:08                             ` Arve Hjønnevåg
2009-02-06  3:42                             ` Arve Hjønnevåg
2009-02-08 23:00                               ` Pavel Machek
2009-02-06  0:35                   ` mark gross
2009-02-05  8:53                 ` [PATCH 08/13] PM: Add user-space wake lock api Pavel Machek
2009-02-05  8:52               ` [PATCH 07/13] PM: wakelock: Add /sys/power/request_state Pavel Machek
2009-02-05  9:25                 ` Arve Hjønnevåg
2009-02-05  9:27                   ` Pavel Machek
2009-02-07 22:54               ` Rafael J. Wysocki
2009-02-06  0:18             ` [PATCH 06/13] PM: Implement early suspend api mark gross
2009-02-07 22:47             ` Rafael J. Wysocki
2009-02-08  2:32               ` Benjamin Herrenschmidt
2009-02-08 13:33                 ` Rafael J. Wysocki
2009-02-05  9:17           ` [PATCH 05/13] PM: Add option to disable /sys/power/state interface Pavel Machek
2009-02-07 22:37           ` Rafael J. Wysocki
2009-02-08 10:33             ` Pavel Machek
2009-02-08 13:50               ` Rafael J. Wysocki
2009-02-08 14:04                 ` Brian Swetland
2009-02-08 21:06                   ` Pavel Machek
2009-02-08 23:41                     ` Rafael J. Wysocki
2009-02-09  1:58                       ` Uli Luckas
2009-02-10  0:09                         ` Rafael J. Wysocki
2009-02-08 23:40                   ` Rafael J. Wysocki
2009-02-08 23:58                     ` Arve Hjønnevåg
2009-02-09  0:26                       ` Rafael J. Wysocki
2009-02-09  1:35                         ` Arve Hjønnevåg
2009-02-09  1:53                           ` Brian Swetland
2009-02-09  8:58                             ` Pavel Machek
2009-02-09 13:31                               ` Brian Swetland
2009-02-10 11:19                                 ` Pavel Machek
2009-02-09  9:15                           ` Pavel Machek
2009-02-09  3:07                       ` Alan Stern
2009-02-11 22:26                         ` Rafael J. Wysocki
2009-02-09  9:09                       ` Pavel Machek
2009-02-12 11:16                   ` Matthew Garrett
2009-02-08 21:04                 ` Pavel Machek
2009-02-08 21:40                   ` Alan Stern
2009-02-08 23:00                     ` Arve Hjønnevåg
2009-02-08 23:03                       ` Pavel Machek
2009-02-09  0:31                         ` Rafael J. Wysocki
2009-02-09  2:11                           ` Uli Luckas
2009-02-09  2:24                             ` Arve Hjønnevåg
2009-02-09  2:56                               ` Uli Luckas
2009-02-09  9:01                           ` Pavel Machek
2009-02-10  0:17                             ` Rafael J. Wysocki
2009-02-10  9:13                               ` Pavel Machek
2009-02-10 14:18                                 ` Rafael J. Wysocki
2009-02-08 23:41                                   ` Pavel Machek
2009-02-08 23:44                     ` Rafael J. Wysocki
2009-02-08 23:44                   ` Rafael J. Wysocki
2009-02-07 22:31         ` [PATCH 04/13] PM: wakelock: Override wakelocks when using /sys/power/state Rafael J. Wysocki
2009-02-05  9:16       ` [PATCH 03/13] PM: Implement wakelock api Pavel Machek
2009-02-05 15:24       ` Alan Stern
2009-02-06  0:10       ` mark gross
2009-02-06  0:38         ` Arve Hjønnevåg
2009-02-07  0:33           ` mark gross
2009-02-07  0:47             ` Arve Hjønnevåg
2009-02-09 18:00               ` mark gross
2009-02-10 20:24               ` Pavel Machek
2009-02-07 22:27       ` Rafael J. Wysocki
2009-02-11  2:52         ` Arve Hjønnevåg
2009-02-05  9:14     ` [PATCH 02/13] PM: Add early suspend api Pavel Machek
2009-02-05 23:26     ` mark gross
2009-02-06  9:33       ` Uli Luckas
2009-02-06 23:26         ` Arve Hjønnevåg
2009-02-07 20:53     ` Rafael J. Wysocki
2009-02-07 23:34       ` Arve Hjønnevåg
2009-02-08 20:59         ` Pavel Machek
2009-02-08 23:59         ` Rafael J. Wysocki
2009-02-05  9:11   ` [PATCH 01/13] PM: Add wake lock api Pavel Machek
2009-02-06  0:28     ` Arve Hjønnevåg
2009-02-06  9:45       ` Uli Luckas
2009-02-08 21:30       ` Pavel Machek
2009-02-08 23:11         ` Arve Hjønnevåg
2009-02-09  9:06           ` Pavel Machek
2009-02-08 22:17       ` non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock api.) Pavel Machek
2009-02-08 22:40         ` Arve Hjønnevåg
2009-02-08 23:14           ` Pavel Machek
2009-02-08 23:35             ` Arve Hjønnevåg
2009-02-10 11:15               ` Pavel Machek
2009-02-11  3:12                 ` Arve Hjønnevåg
2009-02-09  1:49         ` non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock api. ) Uli Luckas
2009-02-10 11:17           ` non-racy examples, please (was Re: [PATCH 01/13] PM: Add wake lock?api.) Pavel Machek
2009-02-10 12:10             ` Woodruff, Richard
2009-02-10 13:14               ` Pavel Machek
2009-02-10 13:20                 ` Woodruff, Richard
2009-02-10 13:42                   ` Brian Swetland
2009-02-10 12:35             ` Uli Luckas
2009-02-06  1:32     ` [PATCH 01/13] PM: Add wake lock api mark gross
2009-02-05 22:51   ` mark gross
2009-02-06  0:13     ` Arve Hjønnevåg
2009-02-10 20:25       ` Pavel Machek
2009-02-11  2:11         ` Arve Hjønnevåg
2009-02-11  4:47         ` Brian Swetland
2009-02-11  8:40           ` Uli Luckas
2009-02-11 14:58           ` Alan Stern
2009-02-11 15:45             ` Rafael J. Wysocki
2009-02-08 22:57               ` Pavel Machek
2009-02-11 21:37             ` Pavel Machek
2009-02-11 22:05               ` Alan Stern
2009-02-11 23:55               ` Arve Hjønnevåg
2009-02-12 18:47           ` mark gross
2009-02-07 18:56   ` Rafael J. Wysocki
2009-02-07 22:51     ` Arve Hjønnevåg
2009-02-07 23:25       ` Rafael J. Wysocki
2009-02-08  0:20         ` Arve Hjønnevåg
2009-02-08 21:21           ` Pavel Machek
2009-02-09  0:03             ` Rafael J. Wysocki
2009-02-09  0:15           ` Rafael J. Wysocki
2009-02-09  2:03             ` Arve Hjønnevåg
2009-02-11 22:23               ` Rafael J. Wysocki
2009-02-11 23:42                 ` Arve Hjønnevåg
2009-02-12 22:22                   ` Rafael J. Wysocki
2009-02-12 23:42                     ` Woodruff, Richard
2009-02-13  1:10                       ` Matthew Garrett
2009-02-13  2:21                         ` Arve Hjønnevåg
2009-02-13  2:40                           ` Nigel Cunningham
2009-02-13  3:17                         ` Woodruff, Richard
2009-02-13 10:55                         ` Uli Luckas
2009-02-13 14:06                           ` Matthew Garrett
2009-02-13 14:24                             ` Brian Swetland
2009-02-13 14:37                               ` Matthew Garrett
2009-02-13 14:46                                 ` Brian Swetland
2009-02-13 15:07                                   ` Matthew Garrett
2009-02-13 22:52                                     ` Rafael J. Wysocki
2009-02-13 16:46                                 ` Uli Luckas
2009-02-13 17:05                                   ` Matthew Garrett
2009-02-13 18:13                                     ` Uli Luckas
2009-02-13 19:14                                       ` Matthew Garrett
2009-02-13 19:35                                         ` Uli Luckas
2009-02-13 16:49                             ` Uli Luckas
2009-02-13 17:09                               ` Matthew Garrett
2009-02-13 18:18                                 ` Uli Luckas
2009-02-27 13:18                               ` Pavel Machek
2009-02-27 14:07                                 ` Uli Luckas
2009-02-27 20:32                                   ` Pavel Machek
2009-03-02 13:53                                     ` Uli Luckas
2009-03-03 14:02                                       ` Pavel Machek
2009-03-04 13:41                                         ` Uli Luckas
2009-03-04 14:00                                         ` Uli Luckas
2009-03-04 14:13                                           ` Pavel Machek
2009-03-04 14:34                                             ` Uli Luckas
2009-03-04 17:10                                               ` Pavel Machek
2009-03-05 17:42                                                 ` Uli Luckas
2009-03-08  8:32                                                   ` Pavel Machek
2009-03-08 12:34                                                     ` Alan Stern
2009-02-13 23:36                             ` Arve Hjønnevåg
2009-02-14  0:05                               ` Matthew Garrett
2009-02-14  0:50                                 ` Arve Hjønnevåg
2009-02-14  1:06                                   ` Matthew Garrett
2009-02-14  1:33                                     ` Arve Hjønnevåg
2009-02-14  1:49                                       ` Matthew Garrett
2009-02-14  5:51                                         ` Arve Hjønnevåg
2009-02-14 20:44                                           ` Matthew Garrett
2009-02-26 15:04                         ` Pavel Machek
2009-02-26 21:11                           ` Arve Hjønnevåg
2009-02-26 21:36                             ` Pavel Machek
2009-02-27  0:16                               ` Arve Hjønnevåg
2009-02-27  9:56                                 ` Pavel Machek
2009-02-28  3:20                                   ` Arve Hjønnevåg
2009-02-06 23:51 ` [RFC][PATCH 00/11] Android PM extensions Rafael J. Wysocki
  -- strict thread matches above, loose matches on Subject: below --
2009-01-14  1:27 Arve Hjønnevåg
2009-01-14  9:01 ` Nigel Cunningham
2009-01-15  0:10   ` Arve Hjønnevåg
2009-01-15  4:42   ` Arve Hjønnevåg
2009-01-15 15:08     ` Alan Stern
2009-01-15 20:34       ` Arve Hjønnevåg
2009-01-29 13:04       ` Pavel Machek
2009-01-30  1:16         ` Arve Hjønnevåg
2009-01-30  3:27           ` Alan Stern
2009-01-30  4:40             ` Arve Hjønnevåg
2009-01-30  6:04               ` Arve Hjønnevåg
2009-02-02 11:49                 ` Pavel Machek
2009-01-30  9:11               ` Pavel Machek
2009-01-30 12:34                 ` Uli Luckas
2009-02-02 11:46                   ` Pavel Machek
2009-01-30 15:13               ` Alan Stern
2009-01-31  0:02                 ` Arve Hjønnevåg
2009-01-31 16:19                   ` Alan Stern
2009-01-31 23:28                     ` Arve Hjønnevåg
2009-02-02 10:42                     ` Uli Luckas
2009-02-02 15:05                       ` Alan Stern
2009-02-02 16:15                         ` Uli Luckas
2009-02-02 16:35                           ` Alan Stern
2009-02-03 20:15                           ` Pavel Machek
2009-01-31  7:47                 ` Brian Swetland
2009-01-31 15:41                   ` Alan Stern
2009-01-31 18:39                     ` Rafael J. Wysocki
2009-01-31 18:54                       ` Igor Stoppa
2009-02-01  1:04                       ` Arve Hjønnevåg
2009-02-02 11:55                       ` Pavel Machek
2009-01-31 22:41                     ` Arve Hjønnevåg
2009-01-31 23:20                       ` Rafael J. Wysocki
2009-01-31 23:32                         ` Arve Hjønnevåg
2009-02-01  0:18                           ` Rafael J. Wysocki
2009-02-01  1:17                             ` Arve Hjønnevåg
2009-02-01  1:32                               ` Rafael J. Wysocki
2009-02-01  2:14                                 ` Arve Hjønnevåg
2009-02-01 12:30                                   ` Rafael J. Wysocki
2009-02-01 14:03                                     ` Woodruff, Richard
2009-02-01 17:43                                     ` Alan Stern
2009-02-01 19:27                                       ` Woodruff, Richard
2009-02-02 11:00                                       ` Uli Luckas
2009-02-02 15:09                                         ` Alan Stern
2009-02-02 16:24                                           ` Uli Luckas
2009-02-02 21:47                                           ` Nigel Cunningham
2009-02-02 23:21                                             ` Arve Hjønnevåg
2009-02-02 23:51                                               ` Nigel Cunningham
2009-02-03  0:08                                                 ` Arve Hjønnevåg
2009-02-04 13:25                                               ` Pavel Machek
2009-02-02 23:10                                           ` Arve Hjønnevåg
2009-02-03  3:27                                             ` Alan Stern
2009-02-03  4:18                                               ` Arve Hjønnevåg
2009-02-03 20:30                                                 ` Alan Stern
2009-02-04 13:29                                                 ` Pavel Machek
2009-02-02 11:56                         ` Pavel Machek
2009-02-02 12:38                           ` Uli Luckas
2009-01-30  9:08           ` Pavel Machek
2009-01-30  9:25             ` Brian Swetland
2009-01-28 19:31 ` Pavel Machek

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.