On Saturday 01 May 2010, Arve Hjønnevåg wrote: > Add a misc device, "suspend_blocker", that allows user-space processes > to block auto suspend. The device has ioctls to create a suspend_blocker, > and to block and unblock suspend. To delete the suspend_blocker, close > the device. > > Signed-off-by: Arve Hjønnevåg <arve@xxxxxxxxxxx> > --- > Documentation/ioctl/ioctl-number.txt | 3 +- > Documentation/power/opportunistic-suspend.txt | 17 ++++ > include/linux/suspend_block_dev.h | 25 +++++ > kernel/power/Kconfig | 9 ++ > kernel/power/Makefile | 1 + > kernel/power/user_suspend_blocker.c | 128 +++++++++++++++++++++++++ > 6 files changed, 182 insertions(+), 1 deletions(-) > create mode 100644 include/linux/suspend_block_dev.h > create mode 100644 kernel/power/user_suspend_blocker.c > > diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt > index dd5806f..e2458f7 100644 > --- a/Documentation/ioctl/ioctl-number.txt > +++ b/Documentation/ioctl/ioctl-number.txt > @@ -254,7 +254,8 @@ Code Seq#(hex) Include File Comments > 'q' 80-FF linux/telephony.h Internet PhoneJACK, Internet LineJACK > linux/ixjuser.h <http://www.quicknet.net> > 'r' 00-1F linux/msdos_fs.h and fs/fat/dir.c > -'s' all linux/cdk.h > +'s' all linux/cdk.h conflict! > +'s' all linux/suspend_block_dev.h conflict! > 't' 00-7F linux/if_ppp.h > 't' 80-8F linux/isdn_ppp.h > 't' 90 linux/toshiba.h > diff --git a/Documentation/power/opportunistic-suspend.txt b/Documentation/power/opportunistic-suspend.txt > index 3d060e8..f2b145e 100644 > --- a/Documentation/power/opportunistic-suspend.txt > +++ b/Documentation/power/opportunistic-suspend.txt > @@ -117,3 +117,20 @@ if (list_empty(&state->pending_work)) > else > suspend_block(&state->suspend_blocker); > > +User-space API > +============== > + > +To create a suspend_blocker from user-space, open the suspend_blocker device: > + fd = open("/dev/suspend_blocker", O_RDWR | O_CLOEXEC); > +then call: > + ioctl(fd, SUSPEND_BLOCKER_IOCTL_INIT(strlen(name)), name); > + > +To activate a suspend_blocker call: > + ioctl(fd, SUSPEND_BLOCKER_IOCTL_BLOCK); > + > +To unblock call: > + ioctl(fd, SUSPEND_BLOCKER_IOCTL_UNBLOCK); > + > +To destroy the suspend_blocker, close the device: > + close(fd); > + > diff --git a/include/linux/suspend_block_dev.h b/include/linux/suspend_block_dev.h > new file mode 100644 > index 0000000..24bc5c7 > --- /dev/null > +++ b/include/linux/suspend_block_dev.h > @@ -0,0 +1,25 @@ > +/* include/linux/suspend_block_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_SUSPEND_BLOCK_DEV_H > +#define _LINUX_SUSPEND_BLOCK_DEV_H > + > +#include <linux/ioctl.h> > + > +#define SUSPEND_BLOCKER_IOCTL_INIT(len) _IOC(_IOC_WRITE, 's', 0, len) > +#define SUSPEND_BLOCKER_IOCTL_BLOCK _IO('s', 1) > +#define SUSPEND_BLOCKER_IOCTL_UNBLOCK _IO('s', 2) > + > +#endif > diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig > index 55a06a1..fe5a2f2 100644 > --- a/kernel/power/Kconfig > +++ b/kernel/power/Kconfig > @@ -146,6 +146,15 @@ config OPPORTUNISTIC_SUSPEND > determines the sleep state the system will be put into when there are > no active suspend blockers. > > +config USER_SUSPEND_BLOCKERS > + bool "Userspace suspend blockers" > + depends on OPPORTUNISTIC_SUSPEND > + default y > + ---help--- > + User-space suspend block api. Creates a misc device with ioctls > + to create, block and unblock a suspend_blocker. The suspend_blocker > + will be deleted when the device is closed. > + > config HIBERNATION_NVS > bool > > diff --git a/kernel/power/Makefile b/kernel/power/Makefile > index ee5276d..78f703b 100644 > --- a/kernel/power/Makefile > +++ b/kernel/power/Makefile > @@ -8,6 +8,7 @@ obj-$(CONFIG_PM_SLEEP) += console.o > obj-$(CONFIG_FREEZER) += process.o > obj-$(CONFIG_SUSPEND) += suspend.o > obj-$(CONFIG_OPPORTUNISTIC_SUSPEND) += suspend_blocker.o > +obj-$(CONFIG_USER_SUSPEND_BLOCKERS) += user_suspend_blocker.o > obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o > obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o > obj-$(CONFIG_HIBERNATION_NVS) += hibernate_nvs.o > diff --git a/kernel/power/user_suspend_blocker.c b/kernel/power/user_suspend_blocker.c > new file mode 100644 > index 0000000..dc1d06f > --- /dev/null > +++ b/kernel/power/user_suspend_blocker.c > @@ -0,0 +1,128 @@ > +/* kernel/power/user_suspend_block.c > + * > + * Copyright (C) 2009-2010 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/slab.h> > +#include <linux/suspend_blocker.h> > +#include <linux/suspend_block_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 DEFINE_MUTEX(ioctl_lock); > + > +struct user_suspend_blocker { > + struct suspend_blocker blocker; > + char name[0]; > +}; > + > +static int create_user_suspend_blocker(struct file *file, void __user *name, > + size_t name_len) > +{ > + struct user_suspend_blocker *bl; > + if (file->private_data) > + return -EBUSY; > + if (name_len > NAME_MAX) > + return -ENAMETOOLONG; > + bl = kzalloc(sizeof(*bl) + name_len + 1, GFP_KERNEL); > + if (!bl) > + return -ENOMEM; > + if (copy_from_user(bl->name, name, name_len)) > + goto err_fault; > + suspend_blocker_init(&bl->blocker, bl->name); > + file->private_data = bl; Hmm. It doesn't seem to be possible to create two different suspend blockers using the same file handle. So, what exactly is a process supposed to do to use two suspend blockers at the same time? Rafael _______________________________________________ linux-pm mailing list linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/linux-pm