[PATCH 03/10] PM: wakelock: Add driver to access wakelocks from user-space

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

 



Adds ioctls to create a wakelock, and to lock and unlock the wakelock.To delete the wakelock, close the device.
Signed-off-by: Arve Hjønnevåg <arve@xxxxxxxxxxx>--- Documentation/power/wakelocks.txt |   24 ++++++ include/linux/wakelock-dev.h      |   26 +++++++ kernel/power/Kconfig              |    9 +++ kernel/power/Makefile             |    1 + kernel/power/userwakelock.c       |  145 +++++++++++++++++++++++++++++++++++++ 5 files changed, 205 insertions(+), 0 deletions(-) create mode 100644 include/linux/wakelock-dev.h create mode 100644 kernel/power/userwakelock.c
diff --git a/Documentation/power/wakelocks.txt b/Documentation/power/wakelocks.txtindex 893a438..939908f 100644--- a/Documentation/power/wakelocks.txt+++ b/Documentation/power/wakelocks.txt@@ -78,3 +78,27 @@ 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+==============++To create a wakelock from user-space, open the wakelock device:+    fd = open("/dev/wakelock", O_RDWR | O_CLOEXEC);+then call:+    ioctl(fd, WAKELOCK_IOCTL_INIT(strlen(name)), name);++To lock a wakelock call:+    ioctl(fd, WAKELOCK_IOCTL_LOCK);+or+    ioctl(fd, WAKELOCK_IOCTL_LOCK_TIMEOUT, &timespec_timeout);++To unlock call:+    ioctl(fd, WAKELOCK_IOCTL_UNLOCK);++To destroy the wakelock, close the device:+    close(fd);++A module parameter, unclean_exit_grace_period, can be set to allow servers+some time to restart if they crash with a wakelock held. If the process dies or+the device is closed while the wakelock is locked, a wakelock will be held for+the number of seconds specified.+diff --git a/include/linux/wakelock-dev.h b/include/linux/wakelock-dev.hnew file mode 100644index 0000000..5dfb1c6--- /dev/null+++ b/include/linux/wakelock-dev.h@@ -0,0 +1,26 @@+/* include/linux/wakelock-dev.h+ *+ * Copyright (C) 2009 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_DEV_H+#define _LINUX_WAKELOCK_DEV_H++#include <linux/ioctl.h>++#define WAKELOCK_IOCTL_INIT(len)	_IOC(_IOC_WRITE,'w',0,len)+#define WAKELOCK_IOCTL_LOCK		_IO('w', 1)+#define WAKELOCK_IOCTL_LOCK_TIMEOUT	_IOW('w', 2, struct timespec)+#define WAKELOCK_IOCTL_UNLOCK		_IO('w', 3)++#endifdiff --git a/kernel/power/Kconfig b/kernel/power/Kconfigindex 9abd97e..6abd5f2 100644--- a/kernel/power/Kconfig+++ b/kernel/power/Kconfig@@ -133,6 +133,15 @@ 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. Creates a misc device with ioctls+	  to create, lock and unlock a wakelock. The wakelock will be+	  deleted when the device is closed.+ config HIBERNATION 	bool "Hibernation (aka 'suspend to disk')" 	depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLEdiff --git a/kernel/power/Makefile b/kernel/power/Makefileindex 8d8672b..63d30db 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_HIBERNATION)	+= swsusp.o disk.o snapshot.o swap.o user.o  obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.odiff --git a/kernel/power/userwakelock.c b/kernel/power/userwakelock.cnew file mode 100644index 0000000..c27c2f7--- /dev/null+++ b/kernel/power/userwakelock.c@@ -0,0 +1,145 @@+/* kernel/power/userwakelock.c+ *+ * Copyright (C) 2009 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/fs.h>+#include <linux/miscdevice.h>+#include <linux/module.h>+#include <linux/uaccess.h>+#include <linux/wakelock.h>+#include <linux/wakelock-dev.h>++enum {+	DEBUG_FAILURE	= BIT(0),+};+static int debug_mask = DEBUG_FAILURE;+module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);++static int unclean_exit_grace_period = 0;+module_param_named(unclean_exit_grace_period, unclean_exit_grace_period, int, S_IRUGO | S_IWUSR | S_IWGRP);++static DEFINE_MUTEX(ioctl_lock);+static struct wake_lock unclean_exit_wake_lock;++struct user_wake_lock {+	struct wake_lock	wake_lock;+	char			name[0];+};++static int create_user_wake_lock(struct file *file, void __user *name,+				 size_t name_len)+{+	struct user_wake_lock *l;+	if (file->private_data)+		return -EBUSY;+	l = kzalloc(sizeof(*l) + name_len + 1, GFP_KERNEL);+	if (!l)+		return -ENOMEM;+	if (copy_from_user(l->name, name, name_len))+		goto err_fault;+	wake_lock_init(&l->wake_lock, WAKE_LOCK_SUSPEND, l->name);+	file->private_data = l;+	return 0;++err_fault:+	kfree(l);+	return -EFAULT;+}++static long user_wakelock_ioctl(struct file *file, unsigned int cmd,+				unsigned long _arg)+{+	void __user *arg = (void __user *)_arg;+	struct user_wake_lock *l;+	struct timespec ts;+	unsigned long timeout;+	long ret;++	mutex_lock(&ioctl_lock);+	if ((cmd & ~IOCSIZE_MASK) == WAKELOCK_IOCTL_INIT(0)) {+		ret = create_user_wake_lock(file, arg, _IOC_SIZE(cmd));+		goto done;+	}+	l = file->private_data;+	if (!l) {+		ret = -ENOENT;+		goto done;+	}+	switch (cmd) {+	case WAKELOCK_IOCTL_LOCK:+		wake_lock(&l->wake_lock);+		ret = 0;+		break;+	case WAKELOCK_IOCTL_LOCK_TIMEOUT:+		if (copy_from_user(&ts, arg, sizeof(ts))) {+			ret = -EFAULT;+			goto done;+		}+		timeout  = timespec_to_jiffies(&ts);+		wake_lock_timeout(&l->wake_lock, timeout);+		ret = 0;+		break;+	case WAKELOCK_IOCTL_UNLOCK:+		wake_unlock(&l->wake_lock);+		ret = 0;+		break;+	default:+		ret = -ENOTSUPP;+	}+done:+	if (ret && debug_mask & DEBUG_FAILURE)+		pr_err("user_wakelock_ioctl: cmd %x failed, %ld\n", cmd, ret);+	mutex_unlock(&ioctl_lock);+	return ret;+}++static int user_wakelock_release(struct inode *inode, struct file *file)+{+	struct user_wake_lock *l = file->private_data;+	if (!l)+		return 0;+	if (wake_lock_active(&l->wake_lock) && unclean_exit_grace_period)+		wake_lock_timeout(&unclean_exit_wake_lock,+				  unclean_exit_grace_period * HZ);+	wake_lock_destroy(&l->wake_lock);+	kfree(l);+	return 0;+}++const struct file_operations user_wakelock_fops = {+	.release = user_wakelock_release,+	.unlocked_ioctl = user_wakelock_ioctl,+};++struct miscdevice user_wakelock_device = {+	.minor = MISC_DYNAMIC_MINOR,+	.name = "wakelock",+	.fops = &user_wakelock_fops,+};++static int __init user_wakelock_init(void)+{+	wake_lock_init(&unclean_exit_wake_lock, WAKE_LOCK_SUSPEND,+		       "user-unclean-exit");+	return misc_register(&user_wakelock_device);+}++static void __exit user_wakelock_exit(void)+{+	misc_deregister(&user_wakelock_device);+	wake_lock_destroy(&unclean_exit_wake_lock);+}++module_init(user_wakelock_init);+module_exit(user_wakelock_exit);-- 1.6.1
_______________________________________________linux-pm mailing listlinux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx://lists.linux-foundation.org/mailman/listinfo/linux-pm


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

  Powered by Linux