diff options
Diffstat (limited to 'target/linux/goldfish/patches-2.6.30/0069-PM-Add-user-space-wake-lock-api.patch')
-rw-r--r-- | target/linux/goldfish/patches-2.6.30/0069-PM-Add-user-space-wake-lock-api.patch | 314 |
1 files changed, 0 insertions, 314 deletions
diff --git a/target/linux/goldfish/patches-2.6.30/0069-PM-Add-user-space-wake-lock-api.patch b/target/linux/goldfish/patches-2.6.30/0069-PM-Add-user-space-wake-lock-api.patch deleted file mode 100644 index c1d0125f11..0000000000 --- a/target/linux/goldfish/patches-2.6.30/0069-PM-Add-user-space-wake-lock-api.patch +++ /dev/null @@ -1,314 +0,0 @@ -From 48e1af2bdd11204f11b3770a6c8d3eee64aee2e8 Mon Sep 17 00:00:00 2001 -From: =?utf-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= <arve@android.com> -Date: Thu, 9 Oct 2008 21:01:46 -0700 -Subject: [PATCH 069/134] PM: Add user-space wake lock api. - -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. ---- - 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 - ---- a/kernel/power/Kconfig -+++ b/kernel/power/Kconfig -@@ -138,6 +138,16 @@ config WAKELOCK_STAT - ---help--- - Report wake lock stats in /proc/wakelocks - -+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 ---- a/kernel/power/Makefile -+++ b/kernel/power/Makefile -@@ -7,6 +7,7 @@ obj-$(CONFIG_PM) += 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 - ---- a/kernel/power/main.c -+++ b/kernel/power/main.c -@@ -595,6 +595,11 @@ pm_trace_store(struct kobject *kobj, str - 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[] = { - &state_attr.attr, - #ifdef CONFIG_PM_TRACE -@@ -603,6 +608,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, - }; - ---- a/kernel/power/power.h -+++ b/kernel/power/power.h -@@ -231,6 +231,17 @@ extern struct wake_lock main_wake_lock; - extern suspend_state_t requested_suspend_state; - #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); ---- /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; -+} -+ |