mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Pavel Machek <pavel@ucw.cz>
To: Arve Hj??nnev??g <arve@android.com>
Cc: linux-pm@lists.linux-foundation.org,
	linux-kernel@vger.kernel.org, "Rafael J. Wysocki" <rjw@sisk.pl>,
	Alan Stern <stern@rowland.harvard.edu>, Tejun Heo <tj@kernel.org>,
	Oleg Nesterov <oleg@redhat.com>, Len Brown <len.brown@intel.com>,
	Randy Dunlap <rdunlap@xenotime.net>,
	Jesse Barnes <jbarnes@virtuousgeek.org>,
	Magnus Damm <damm@igel.co.jp>,
	Nigel Cunningham <nigel@tuxonice.net>,
	Cornelia Huck <cornelia.huck@de.ibm.com>,
	Ming Lei <tom.leiming@gmail.com>,
	Wu Fengguang <fengguang.wu@intel.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Maxim Levitsky <maximlevitsky@gmail.com>,
	linux-doc@vger.kernel.org
Subject: Re: [PATCH 1/8] PM: Add suspend block api.
Date: Sun, 2 May 2010 09:01:45 +0200	[thread overview]
Message-ID: <20100502070145.GC1790@ucw.cz> (raw)
In-Reply-To: <1272667021-21312-2-git-send-email-arve@android.com>

On Fri 2010-04-30 15:36:54, Arve Hj??nnev??g wrote:
> Adds /sys/power/policy that selects the behaviour of /sys/power/state.
> After setting the policy to opportunistic, writes to /sys/power/state
> become non-blocking requests that specify which suspend state to enter
> when no suspend blockers are active. A special state, "on", stops the
> process by activating the "main" suspend blocker.
> 
> Signed-off-by: Arve Hj??nnev??g <arve@android.com>

Also note that this patch mixes up adding new in-kernel interface with
adding new userland API.

The in-kernel interface seems to be sane and it would be nice to merge
it soon, unfortunately the strange userland API is in the same patch :-(.

> ---
>  Documentation/power/opportunistic-suspend.txt |  119 +++++++++++
>  include/linux/suspend_blocker.h               |   64 ++++++
>  kernel/power/Kconfig                          |   16 ++
>  kernel/power/Makefile                         |    1 +
>  kernel/power/main.c                           |   92 ++++++++-
>  kernel/power/power.h                          |    9 +
>  kernel/power/suspend.c                        |    4 +-
>  kernel/power/suspend_blocker.c                |  261 +++++++++++++++++++++++++
>  8 files changed, 559 insertions(+), 7 deletions(-)
>  create mode 100644 Documentation/power/opportunistic-suspend.txt
>  create mode 100755 include/linux/suspend_blocker.h
>  create mode 100644 kernel/power/suspend_blocker.c
> 
> diff --git a/Documentation/power/opportunistic-suspend.txt b/Documentation/power/opportunistic-suspend.txt
> new file mode 100644
> index 0000000..3d060e8
> --- /dev/null
> +++ b/Documentation/power/opportunistic-suspend.txt
> @@ -0,0 +1,119 @@
> +Opportunistic Suspend
> +=====================
> +
> +Opportunistic suspend is a feature allowing the system to be suspended (ie. put
> +into one of the available sleep states) automatically whenever it is regarded
> +as idle.  The suspend blockers framework described below is used to determine
> +when that happens.
> +
> +The /sys/power/policy sysfs attribute is used to switch the system between the
> +opportunistic and "forced" suspend behavior, where in the latter case the
> +system is only suspended if a specific value, corresponding to one of the
> +available system sleep states, is written into /sys/power/state.  However, in
> +the former, opportunistic, case the system is put into the sleep state
> +corresponding to the value written to /sys/power/state whenever there are no
> +active suspend blockers. The default policy is "forced". Also, suspend blockers
> +do not affect sleep states entered from idle.
> +
> +When the policy is "opportunisic", there is a special value, "on", that can be
> +written to /sys/power/state. This will block the automatic sleep request, as if
> +a suspend blocker was used by a device driver. This way the opportunistic
> +suspend may be blocked by user space whithout switching back to the "forced"
> +mode.
> +
> +A suspend blocker is an object used to inform the PM subsystem when the system
> +can or cannot be suspended in the "opportunistic" mode (the "forced" mode
> +ignores suspend blockers).  To use it, a device driver creates a struct
> +suspend_blocker that must be initialized with suspend_blocker_init(). Before
> +freeing the suspend_blocker structure or its name, suspend_blocker_destroy()
> +must be called on it.
> +
> +A suspend blocker is activated using suspend_block(), which prevents the PM
> +subsystem from putting the system into the requested sleep state in the
> +"opportunistic" mode until the suspend blocker is deactivated with
> +suspend_unblock(). Multiple suspend blockers may be active simultaneously, and
> +the system will not suspend as long as at least one of them is active.
> +
> +If opportunistic suspend is already in progress when suspend_block() is called,
> +it will abort the suspend, unless suspend_ops->enter has already been
> +executed. If suspend is aborted this way, the system is usually not fully
> +operational at that point. The suspend callbacks of some drivers may still be
> +running and it usually takes time to restore the system to the fully operational
> +state.
> +
> +Here's an example showing how a cell phone or other embedded system can handle
> +keystrokes (or other input events) in the presence of suspend blockers. 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 calls suspend_block on the
> +  keypad-scan suspend_blocker 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 calls
> +  suspend_block on the input-event-queue suspend_blocker.
> +- The keypad-scan code detects that no keys are held and calls suspend_unblock
> +  on the keypad-scan suspend_blocker.
> +- The user-space input-event thread returns from select/poll, calls
> +  suspend_block on the process-input-events suspend_blocker and then calls read
> +  on the input-event device.
> +- The input-event driver dequeues the key-event and, since the queue is now
> +  empty, it calls suspend_unblock on the input-event-queue suspend_blocker.
> +- The user-space input-event thread returns from read. If it determines that
> +  the key should be ignored, it calls suspend_unblock on the
> +  process_input_events suspend_blocker and then calls select or poll. The
> +  system will automatically suspend again, since now no suspend blockers are
> +  active.
> +
> +If the key that was pressed instead should preform a simple action (for example,
> +adjusting the volume), this action can be performed right before calling
> +suspend_unblock on the process_input_events suspend_blocker. However, if the key
> +triggers a longer-running action, that action needs its own suspend_blocker and
> +suspend_block must be called on that suspend blocker before calling
> +suspend_unblock on the process_input_events suspend_blocker.
> +
> +                 Key pressed   Key released
> +                     |             |
> +keypad-scan          ++++++++++++++++++
> +input-event-queue        +++          +++
> +process-input-events       +++          +++
> +
> +
> +Driver API
> +==========
> +
> +A driver can use the suspend block api by adding a suspend_blocker variable to
> +its state and calling suspend_blocker_init. For instance:
> +struct state {
> +	struct suspend_blocker suspend_blocker;
> +}
> +
> +init() {
> +	suspend_blocker_init(&state->suspend_blocker, "suspend-blocker-name");
> +}
> +
> +Before freeing the memory, suspend_blocker_destroy must be called:
> +
> +uninit() {
> +	suspend_blocker_destroy(&state->suspend_blocker);
> +}
> +
> +When the driver determines that it needs to run (usually in an interrupt
> +handler) it calls suspend_block:
> +	suspend_block(&state->suspend_blocker);
> +
> +When it no longer needs to run it calls suspend_unblock:
> +	suspend_unblock(&state->suspend_blocker);
> +
> +Calling suspend_block when the suspend blocker is active or suspend_unblock when
> +it is not active has no effect (i.e., these functions don't nest). This allows
> +drivers to update their state and call suspend suspend_block or suspend_unblock
> +based on the result.
> +For instance:
> +
> +if (list_empty(&state->pending_work))
> +	suspend_unblock(&state->suspend_blocker);
> +else
> +	suspend_block(&state->suspend_blocker);
> +
> diff --git a/include/linux/suspend_blocker.h b/include/linux/suspend_blocker.h
> new file mode 100755
> index 0000000..f9928cc
> --- /dev/null
> +++ b/include/linux/suspend_blocker.h
> @@ -0,0 +1,64 @@
> +/* include/linux/suspend_blocker.h
> + *
> + * Copyright (C) 2007-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_BLOCKER_H
> +#define _LINUX_SUSPEND_BLOCKER_H
> +
> +#include <linux/list.h>
> +
> +/**
> + * struct suspend_blocker - the basic suspend_blocker structure
> + * @link:	List entry for active or inactive list.
> + * @flags:	Tracks initialized and active state.
> + * @name:	Name used for debugging.
> + *
> + * When a suspend_blocker is active it prevents the system from entering
> + * opportunistic suspend.
> + *
> + * The suspend_blocker structure must be initialized by suspend_blocker_init()
> + */
> +
> +struct suspend_blocker {
> +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND
> +	struct list_head    link;
> +	int                 flags;
> +	const char         *name;
> +#endif
> +};
> +
> +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND
> +
> +void suspend_blocker_init(struct suspend_blocker *blocker, const char *name);
> +void suspend_blocker_destroy(struct suspend_blocker *blocker);
> +void suspend_block(struct suspend_blocker *blocker);
> +void suspend_unblock(struct suspend_blocker *blocker);
> +bool suspend_blocker_is_active(struct suspend_blocker *blocker);
> +bool suspend_is_blocked(void);
> +
> +#else
> +
> +static inline void suspend_blocker_init(struct suspend_blocker *blocker,
> +					const char *name) {}
> +static inline void suspend_blocker_destroy(struct suspend_blocker *blocker) {}
> +static inline void suspend_block(struct suspend_blocker *blocker) {}
> +static inline void suspend_unblock(struct suspend_blocker *blocker) {}
> +static inline bool suspend_blocker_is_active(struct suspend_blocker *bl)
> +								{ return 0; }
> +static inline bool suspend_is_blocked(void) { return 0; }
> +
> +#endif
> +
> +#endif
> +
> diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
> index 5c36ea9..55a06a1 100644
> --- a/kernel/power/Kconfig
> +++ b/kernel/power/Kconfig
> @@ -130,6 +130,22 @@ config SUSPEND_FREEZER
>  
>  	  Turning OFF this setting is NOT recommended! If in doubt, say Y.
>  
> +config OPPORTUNISTIC_SUSPEND
> +	bool "Suspend blockers"
> +	depends on PM_SLEEP
> +	select RTC_LIB
> +	default n
> +	---help---
> +	  Opportunistic sleep support.  Allows the system to be put into a sleep
> +	  state opportunistically, if it doesn't do any useful work at the
> +	  moment. The PM subsystem is switched into this mode of operation by
> +	  writing "opportunistic" into /sys/power/policy, while writing
> +	  "forced" to this file turns the opportunistic suspend feature off.
> +	  In the "opportunistic" mode suspend blockers are used to determine
> +	  when to suspend the system and the value written to /sys/power/state
> +	  determines the sleep state the system will be put into when there are
> +	  no active suspend blockers.
> +
>  config HIBERNATION_NVS
>  	bool
>  
> diff --git a/kernel/power/Makefile b/kernel/power/Makefile
> index 4319181..ee5276d 100644
> --- 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_SUSPEND)		+= suspend.o
> +obj-$(CONFIG_OPPORTUNISTIC_SUSPEND)	+= 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/main.c b/kernel/power/main.c
> index b58800b..030ecdc 100644
> --- a/kernel/power/main.c
> +++ b/kernel/power/main.c
> @@ -12,6 +12,7 @@
>  #include <linux/string.h>
>  #include <linux/resume-trace.h>
>  #include <linux/workqueue.h>
> +#include <linux/suspend_blocker.h>
>  
>  #include "power.h"
>  
> @@ -20,6 +21,27 @@ DEFINE_MUTEX(pm_mutex);
>  unsigned int pm_flags;
>  EXPORT_SYMBOL(pm_flags);
>  
> +struct policy {
> +	const char *name;
> +	bool (*valid_state)(suspend_state_t state);
> +	int (*set_state)(suspend_state_t state);
> +};
> +static struct policy policies[] = {
> +	{
> +		.name		= "forced",
> +		.valid_state	= valid_state,
> +		.set_state	= enter_state,
> +	},
> +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND
> +	{
> +		.name		= "opportunistic",
> +		.valid_state	= request_suspend_valid_state,
> +		.set_state	= request_suspend_state,
> +	},
> +#endif
> +};
> +static int policy;
> +
>  #ifdef CONFIG_PM_SLEEP
>  
>  /* Routines for PM-transition notifications */
> @@ -146,6 +168,12 @@ struct kobject *power_kobj;
>   *
>   *	store() accepts one of those strings, translates it into the 
>   *	proper enumerated value, and initiates a suspend transition.
> + *
> + *	If policy is set to opportunistic, store() does not block until the
> + *	system resumes, and it will try to re-enter the state until another
> + *	state is requested. Suspend blockers are respected and the requested
> + *	state will only be entered when no suspend blockers are active.
> + *	Write "on" to cancel.
>   */
>  static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
>  			  char *buf)
> @@ -155,12 +183,13 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
>  	int i;
>  
>  	for (i = 0; i < PM_SUSPEND_MAX; i++) {
> -		if (pm_states[i] && valid_state(i))
> +		if (pm_states[i] && policies[policy].valid_state(i))
>  			s += sprintf(s,"%s ", pm_states[i]);
>  	}
>  #endif
>  #ifdef CONFIG_HIBERNATION
> -	s += sprintf(s, "%s\n", "disk");
> +	if (!policy)
> +		s += sprintf(s, "%s\n", "disk");
>  #else
>  	if (s != buf)
>  		/* convert the last space to a newline */
> @@ -173,7 +202,7 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
>  			   const char *buf, size_t n)
>  {
>  #ifdef CONFIG_SUSPEND
> -	suspend_state_t state = PM_SUSPEND_STANDBY;
> +	suspend_state_t state = PM_SUSPEND_ON;
>  	const char * const *s;
>  #endif
>  	char *p;
> @@ -184,7 +213,7 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
>  	len = p ? p - buf : n;
>  
>  	/* First, check if we are requested to hibernate */
> -	if (len == 4 && !strncmp(buf, "disk", len)) {
> +	if (len == 4 && !strncmp(buf, "disk", len) && !policy) {
>  		error = hibernate();
>    goto Exit;
>  	}
> @@ -195,7 +224,7 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
>  			break;
>  	}
>  	if (state < PM_SUSPEND_MAX && *s)
> -		error = enter_state(state);
> +		error = policies[policy].set_state(state);
>  #endif
>  
>   Exit:
> @@ -204,6 +233,55 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
>  
>  power_attr(state);
>  
> +/**
> + *	policy - set policy for state
> + */
> +
> +static ssize_t policy_show(struct kobject *kobj,
> +			   struct kobj_attribute *attr, char *buf)
> +{
> +	char *s = buf;
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(policies); i++) {
> +		if (i == policy)
> +			s += sprintf(s, "[%s] ", policies[i].name);
> +		else
> +			s += sprintf(s, "%s ", policies[i].name);
> +	}
> +	if (s != buf)
> +		/* convert the last space to a newline */
> +		*(s-1) = '\n';
> +	return (s - buf);
> +}
> +
> +static ssize_t policy_store(struct kobject *kobj,
> +			    struct kobj_attribute *attr,
> +			    const char *buf, size_t n)
> +{
> +	const char *s;
> +	char *p;
> +	int len;
> +	int i;
> +
> +	p = memchr(buf, '\n', n);
> +	len = p ? p - buf : n;
> +
> +	for (i = 0; i < ARRAY_SIZE(policies); i++) {
> +		s = policies[i].name;
> +		if (s && len == strlen(s) && !strncmp(buf, s, len)) {
> +			mutex_lock(&pm_mutex);
> +			policies[policy].set_state(PM_SUSPEND_ON);
> +			policy = i;
> +			mutex_unlock(&pm_mutex);
> +			return n;
> +		}
> +	}
> +	return -EINVAL;
> +}
> +
> +power_attr(policy);
> +
>  #ifdef CONFIG_PM_TRACE
>  int pm_trace_enabled;
>  
> @@ -231,6 +309,7 @@ power_attr(pm_trace);
>  
>  static struct attribute * g[] = {
>  	&state_attr.attr,
> +	&policy_attr.attr,
>  #ifdef CONFIG_PM_TRACE
>  	&pm_trace_attr.attr,
>  #endif
> @@ -247,7 +326,7 @@ static struct attribute_group attr_group = {
>  	.attrs = g,
>  };
>  
> -#ifdef CONFIG_PM_RUNTIME
> +#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_OPPORTUNISTIC_SUSPEND)
>  struct workqueue_struct *pm_wq;
>  EXPORT_SYMBOL_GPL(pm_wq);
>  
> @@ -266,6 +345,7 @@ static int __init pm_init(void)
>  	int error = pm_start_workqueue();
>  	if (error)
>  		return error;
> +	suspend_block_init();
>  	power_kobj = kobject_create_and_add("power", NULL);
>  	if (!power_kobj)
>  		return -ENOMEM;
> diff --git a/kernel/power/power.h b/kernel/power/power.h
> index 46c5a26..67d10fd 100644
> --- a/kernel/power/power.h
> +++ b/kernel/power/power.h
> @@ -236,3 +236,12 @@ static inline void suspend_thaw_processes(void)
>  {
>  }
>  #endif
> +
> +/* kernel/power/suspend_block.c */
> +extern int request_suspend_state(suspend_state_t state);
> +extern bool request_suspend_valid_state(suspend_state_t state);
> +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND
> +extern void __init suspend_block_init(void);
> +#else
> +static inline void suspend_block_init(void) {}
> +#endif
> diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
> index 56e7dbb..dc42006 100644
> --- a/kernel/power/suspend.c
> +++ b/kernel/power/suspend.c
> @@ -16,10 +16,12 @@
>  #include <linux/cpu.h>
>  #include <linux/syscalls.h>
>  #include <linux/gfp.h>
> +#include <linux/suspend_blocker.h>
>  
>  #include "power.h"
>  
>  const char *const pm_states[PM_SUSPEND_MAX] = {
> +	[PM_SUSPEND_ON]		= "on",
>  	[PM_SUSPEND_STANDBY]	= "standby",
>  	[PM_SUSPEND_MEM]	= "mem",
>  };
> @@ -157,7 +159,7 @@ static int suspend_enter(suspend_state_t state)
>  
>  	error = sysdev_suspend(PMSG_SUSPEND);
>  	if (!error) {
> -		if (!suspend_test(TEST_CORE))
> +		if (!suspend_is_blocked() && !suspend_test(TEST_CORE))
>  			error = suspend_ops->enter(state);
>  		sysdev_resume();
>  	}
> diff --git a/kernel/power/suspend_blocker.c b/kernel/power/suspend_blocker.c
> new file mode 100644
> index 0000000..2c58b21
> --- /dev/null
> +++ b/kernel/power/suspend_blocker.c
> @@ -0,0 +1,261 @@
> +/* kernel/power/suspend_blocker.c
> + *
> + * Copyright (C) 2005-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/module.h>
> +#include <linux/rtc.h>
> +#include <linux/suspend.h>
> +#include <linux/suspend_blocker.h>
> +#include "power.h"
> +
> +extern struct workqueue_struct *pm_wq;
> +
> +enum {
> +	DEBUG_EXIT_SUSPEND = 1U << 0,
> +	DEBUG_WAKEUP = 1U << 1,
> +	DEBUG_USER_STATE = 1U << 2,
> +	DEBUG_SUSPEND = 1U << 3,
> +	DEBUG_SUSPEND_BLOCKER = 1U << 4,
> +};
> +static int debug_mask = DEBUG_EXIT_SUSPEND | DEBUG_WAKEUP | DEBUG_USER_STATE;
> +module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
> +
> +#define SB_INITIALIZED            (1U << 8)
> +#define SB_ACTIVE                 (1U << 9)
> +
> +static DEFINE_SPINLOCK(list_lock);
> +static DEFINE_SPINLOCK(state_lock);
> +static LIST_HEAD(inactive_blockers);
> +static LIST_HEAD(active_blockers);
> +static int current_event_num;
> +struct suspend_blocker main_suspend_blocker;
> +static suspend_state_t requested_suspend_state = PM_SUSPEND_MEM;
> +static bool enable_suspend_blockers;
> +
> +#define pr_info_time(fmt, args...) \
> +	do { \
> +		struct timespec ts; \
> +		struct rtc_time tm; \
> +		getnstimeofday(&ts); \
> +		rtc_time_to_tm(ts.tv_sec, &tm); \
> +		pr_info(fmt "(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n" , \
> +			args, \
> +			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, \
> +			tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec); \
> +	} while (0);
> +
> +static void print_active_blockers_locked(void)
> +{
> +	struct suspend_blocker *blocker;
> +
> +	list_for_each_entry(blocker, &active_blockers, link)
> +		pr_info("active suspend blocker %s\n", blocker->name);
> +}
> +
> +/**
> + * suspend_is_blocked() - Check if suspend should be blocked
> + *
> + * suspend_is_blocked can be used by generic power management code to abort
> + * suspend.
> + *
> + * To preserve backward compatibility suspend_is_blocked returns 0 unless it
> + * is called during suspend initiated from the suspend_block code.
> + */
> +bool suspend_is_blocked(void)
> +{
> +	if (!enable_suspend_blockers)
> +		return 0;
> +	return !list_empty(&active_blockers);
> +}
> +
> +static void suspend_worker(struct work_struct *work)
> +{
> +	int ret;
> +	int entry_event_num;
> +
> +	enable_suspend_blockers = true;
> +	while (!suspend_is_blocked()) {
> +		entry_event_num = current_event_num;
> +
> +		if (debug_mask & DEBUG_SUSPEND)
> +			pr_info("suspend: enter suspend\n");
> +
> +		ret = pm_suspend(requested_suspend_state);
> +
> +		if (debug_mask & DEBUG_EXIT_SUSPEND)
> +			pr_info_time("suspend: exit suspend, ret = %d ", ret);
> +
> +		if (current_event_num == entry_event_num)
> +			pr_info("suspend: pm_suspend returned with no event\n");
> +	}
> +	enable_suspend_blockers = false;
> +}
> +static DECLARE_WORK(suspend_work, suspend_worker);
> +
> +/**
> + * suspend_blocker_init() - Initialize a suspend blocker
> + * @blocker:	The suspend blocker to initialize.
> + * @name:	The name of the suspend blocker to show in debug messages.
> + *
> + * The suspend blocker struct and name must not be freed before calling
> + * suspend_blocker_destroy.
> + */
> +void suspend_blocker_init(struct suspend_blocker *blocker, const char *name)
> +{
> +	unsigned long irqflags = 0;
> +
> +	WARN_ON(!name);
> +
> +	if (debug_mask & DEBUG_SUSPEND_BLOCKER)
> +		pr_info("suspend_blocker_init name=%s\n", name);
> +
> +	blocker->name = name;
> +	blocker->flags = SB_INITIALIZED;
> +	INIT_LIST_HEAD(&blocker->link);
> +
> +	spin_lock_irqsave(&list_lock, irqflags);
> +	list_add(&blocker->link, &inactive_blockers);
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +}
> +EXPORT_SYMBOL(suspend_blocker_init);
> +
> +/**
> + * suspend_blocker_destroy() - Destroy a suspend blocker
> + * @blocker:	The suspend blocker to destroy.
> + */
> +void suspend_blocker_destroy(struct suspend_blocker *blocker)
> +{
> +	unsigned long irqflags;
> +	if (WARN_ON(!(blocker->flags & SB_INITIALIZED)))
> +		return;
> +
> +	if (debug_mask & DEBUG_SUSPEND_BLOCKER)
> +		pr_info("suspend_blocker_destroy name=%s\n", blocker->name);
> +
> +	spin_lock_irqsave(&list_lock, irqflags);
> +	blocker->flags &= ~SB_INITIALIZED;
> +	list_del(&blocker->link);
> +	if ((blocker->flags & SB_ACTIVE) && list_empty(&active_blockers))
> +		queue_work(pm_wq, &suspend_work);
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +}
> +EXPORT_SYMBOL(suspend_blocker_destroy);
> +
> +/**
> + * suspend_block() - Block suspend
> + * @blocker:	The suspend blocker to use
> + *
> + * It is safe to call this function from interrupt context.
> + */
> +void suspend_block(struct suspend_blocker *blocker)
> +{
> +	unsigned long irqflags;
> +
> +	if (WARN_ON(!(blocker->flags & SB_INITIALIZED)))
> +		return;
> +
> +	spin_lock_irqsave(&list_lock, irqflags);
> +
> +	if (debug_mask & DEBUG_SUSPEND_BLOCKER)
> +		pr_info("suspend_block: %s\n", blocker->name);
> +
> +	blocker->flags |= SB_ACTIVE;
> +	list_move(&blocker->link, &active_blockers);
> +	current_event_num++;
> +
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +}
> +EXPORT_SYMBOL(suspend_block);
> +
> +/**
> + * suspend_unblock() - Unblock suspend
> + * @blocker:	The suspend blocker to unblock.
> + *
> + * If no other suspend blockers block suspend, the system will suspend.
> + *
> + * It is safe to call this function from interrupt context.
> + */
> +void suspend_unblock(struct suspend_blocker *blocker)
> +{
> +	unsigned long irqflags;
> +
> +	if (WARN_ON(!(blocker->flags & SB_INITIALIZED)))
> +		return;
> +
> +	spin_lock_irqsave(&list_lock, irqflags);
> +
> +	if (debug_mask & DEBUG_SUSPEND_BLOCKER)
> +		pr_info("suspend_unblock: %s\n", blocker->name);
> +
> +	list_move(&blocker->link, &inactive_blockers);
> +
> +	if ((blocker->flags & SB_ACTIVE) && list_empty(&active_blockers))
> +		queue_work(pm_wq, &suspend_work);
> +	blocker->flags &= ~(SB_ACTIVE);
> +	if (blocker == &main_suspend_blocker) {
> +		if (debug_mask & DEBUG_SUSPEND)
> +			print_active_blockers_locked();
> +	}
> +	spin_unlock_irqrestore(&list_lock, irqflags);
> +}
> +EXPORT_SYMBOL(suspend_unblock);
> +
> +/**
> + * suspend_blocker_is_active() - Test if a suspend blocker is blocking suspend
> + * @blocker:	The suspend blocker to check.
> + *
> + * Returns true if the suspend_blocker is currently active.
> + */
> +bool suspend_blocker_is_active(struct suspend_blocker *blocker)
> +{
> +	WARN_ON(!(blocker->flags & SB_INITIALIZED));
> +
> +	return !!(blocker->flags & SB_ACTIVE);
> +}
> +EXPORT_SYMBOL(suspend_blocker_is_active);
> +
> +bool request_suspend_valid_state(suspend_state_t state)
> +{
> +	return (state == PM_SUSPEND_ON) || valid_state(state);
> +}
> +
> +int request_suspend_state(suspend_state_t state)
> +{
> +	unsigned long irqflags;
> +
> +	if (!request_suspend_valid_state(state))
> +		return -ENODEV;
> +
> +	spin_lock_irqsave(&state_lock, irqflags);
> +
> +	if (debug_mask & DEBUG_USER_STATE)
> +		pr_info_time("request_suspend_state: %s (%d->%d) at %lld ",
> +			     state != PM_SUSPEND_ON ? "sleep" : "wakeup",
> +			     requested_suspend_state, state,
> +			     ktime_to_ns(ktime_get()));
> +
> +	requested_suspend_state = state;
> +	if (state == PM_SUSPEND_ON)
> +		suspend_block(&main_suspend_blocker);
> +	else
> +		suspend_unblock(&main_suspend_blocker);
> +	spin_unlock_irqrestore(&state_lock, irqflags);
> +	return 0;
> +}
> +
> +void __init suspend_block_init(void)
> +{
> +	suspend_blocker_init(&main_suspend_blocker, "main");
> +	suspend_block(&main_suspend_blocker);
> +}

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

  parent reply	other threads:[~2010-05-02  7:01 UTC|newest]

Thread overview: 351+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-04-30 22:36 [PATCH 0/8] Suspend block api (version 6) Arve Hjønnevåg
2010-04-30 22:36 ` [PATCH 1/8] PM: Add suspend block api Arve Hjønnevåg
2010-04-30 22:36   ` [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space Arve Hjønnevåg
2010-04-30 22:36     ` [PATCH 3/8] PM: suspend_block: Abort task freezing if a suspend_blocker is active Arve Hjønnevåg
2010-04-30 22:36       ` [PATCH 4/8] PM: suspend_block: Add debugfs file Arve Hjønnevåg
2010-04-30 22:36         ` [PATCH 5/8] PM: suspend_block: Add suspend_blocker stats Arve Hjønnevåg
2010-04-30 22:36           ` [PATCH 6/8] PM: Add suspend blocking work Arve Hjønnevåg
2010-04-30 22:37             ` [PATCH 7/8] Input: Block suspend while event queue is not empty Arve Hjønnevåg
2010-04-30 22:37               ` [PATCH 8/8] power_supply: Block suspend while power supply change notifications are pending Arve Hjønnevåg
2010-05-01  6:14             ` [PATCH 6/8] PM: Add suspend blocking work Tejun Heo
2010-05-02  7:05             ` Pavel Machek
2010-05-04 11:16         ` [PATCH 4/8] PM: suspend_block: Add debugfs file Andi Kleen
2010-05-04 21:06           ` Arve Hjønnevåg
2010-05-02  6:57       ` [PATCH 3/8] PM: suspend_block: Abort task freezing if a suspend_blocker is active Pavel Machek
2010-05-02  7:04     ` [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space Pavel Machek
2010-05-02 21:23     ` Rafael J. Wysocki
2010-05-02 21:56       ` Alan Stern
2010-05-03 15:03         ` Rafael J. Wysocki
2010-05-03 21:26           ` Arve Hjønnevåg
2010-05-03 21:49             ` Rafael J. Wysocki
2010-05-03 22:01               ` Arve Hjønnevåg
2010-05-04 20:02                 ` Rafael J. Wysocki
2010-05-04  4:16           ` Pavel Machek
2010-05-02  6:56   ` [PATCH 1/8] PM: Add suspend block api Pavel Machek
2010-05-02 20:10     ` Rafael J. Wysocki
2010-05-02 20:52       ` Pavel Machek
2010-05-02 21:29         ` Rafael J. Wysocki
2010-05-03 19:01           ` Pavel Machek
2010-05-03 21:38             ` Rafael J. Wysocki
2010-05-03 22:11               ` Alan Stern
2010-05-03 22:24                 ` Arve Hjønnevåg
2010-05-02  7:01   ` Pavel Machek [this message]
2010-05-04  5:12   ` [linux-pm] " mark gross
2010-05-04 13:59     ` Alan Stern
2010-05-04 16:03       ` mark gross
2010-05-04 17:16         ` Alan Stern
2010-05-05  1:50           ` mark gross
2010-05-05 13:31             ` Matthew Garrett
2010-05-05 20:09               ` mark gross
2010-05-05 20:21                 ` Matthew Garrett
2010-05-05 15:44             ` Alan Stern
2010-05-05 20:28               ` mark gross
2010-05-05 21:12                 ` Alan Stern
2010-05-05 21:37                   ` Brian Swetland
2010-05-05 23:47                     ` Tony Lindgren
2010-05-05 23:56                       ` Brian Swetland
2010-05-06  0:05                         ` Tony Lindgren
2010-05-06  4:16                           ` Arve Hjønnevåg
2010-05-06 17:04                             ` Tony Lindgren
2010-05-07  0:10                               ` Arve Hjønnevåg
2010-05-07 15:54                                 ` Tony Lindgren
2010-05-28  6:43                                 ` Pavel Machek
2010-05-28  7:01                                   ` Arve Hjønnevåg
2010-05-06 13:40                       ` Matthew Garrett
2010-05-06 17:01                         ` Tony Lindgren
2010-05-06 17:09                           ` Matthew Garrett
2010-05-06 17:14                             ` Tony Lindgren
2010-05-06 17:22                               ` Matthew Garrett
2010-05-06 17:38                                 ` Tony Lindgren
2010-05-06 17:43                                   ` Matthew Garrett
2010-05-06 18:33                                     ` Tony Lindgren
2010-05-06 18:44                                       ` Matthew Garrett
2010-05-07  2:05                                         ` Tony Lindgren
2010-05-07 17:12                                           ` Matthew Garrett
2010-05-07 17:35                                             ` Tony Lindgren
2010-05-07 17:50                                               ` Matthew Garrett
2010-05-07 18:01                                                 ` Tony Lindgren
2010-05-07 18:28                                                   ` Matthew Garrett
2010-05-07 18:43                                                     ` Tony Lindgren
2010-05-07 18:46                                                       ` Matthew Garrett
2010-05-07 19:06                                                         ` Daniel Walker
2010-05-07 19:28                                                           ` Tony Lindgren
2010-05-07 19:33                                                             ` Matthew Garrett
2010-05-07 19:55                                                               ` Tony Lindgren
2010-05-07 20:28                                                                 ` Matthew Garrett
2010-05-07 20:53                                                                   ` Tony Lindgren
2010-05-07 21:03                                                                     ` Matthew Garrett
2010-05-07 21:25                                                                       ` Tony Lindgren
2010-05-07 21:32                                                                         ` Arve Hjønnevåg
2010-05-07 21:39                                                                         ` Matthew Garrett
2010-05-07 21:42                                                                           ` Tony Lindgren
2010-05-07 21:48                                                                             ` Matthew Garrett
2010-05-07 22:00                                                                               ` Tony Lindgren
2010-05-07 22:28                                                                                 ` Matthew Garrett
2010-05-07 21:30                                                                       ` Daniel Walker
2010-05-07 21:35                                                                         ` Arve Hjønnevåg
2010-05-07 21:43                                                                           ` Daniel Walker
2010-05-07 21:38                                                                         ` Matthew Garrett
2010-05-06 18:47                                       ` Alan Stern
2010-05-07  2:20                                         ` Tony Lindgren
2010-05-28 13:29                                   ` Pavel Machek
2010-05-28 13:42                                     ` Brian Swetland
2010-05-06 17:35                               ` Daniel Walker
2010-05-06 18:36                                 ` Tony Lindgren
2010-05-06 19:11                                   ` Daniel Walker
2010-05-07  2:00                                     ` Tony Lindgren
2010-05-07 17:20                                       ` Daniel Walker
2010-05-07 17:36                                         ` Matthew Garrett
2010-05-07 17:40                                           ` Daniel Walker
2010-05-07 17:51                                             ` Matthew Garrett
2010-05-07 18:00                                               ` Daniel Walker
2010-05-07 18:17                                                 ` Tony Lindgren
2010-05-07 17:50                                         ` Tony Lindgren
2010-05-07  3:45                               ` mgross
2010-05-07  3:45                             ` mgross
2010-05-07  4:10                               ` Arve Hjønnevåg
2010-05-04 20:40     ` Arve Hjønnevåg
2010-05-03 16:40 ` [PATCH 0/8] Suspend block api (version 6) Kevin Hilman
2010-05-03 17:12   ` Alan Stern
2010-05-03 18:17     ` Kevin Hilman
2010-05-03 18:07   ` Mark Brown
2010-05-03 21:18     ` Rafael J. Wysocki
2010-05-03 23:37       ` Kevin Hilman
2010-05-04  0:09         ` Arve Hjønnevåg
2010-05-04  0:43           ` Brian Swetland
2010-05-04 13:59             ` Mark Brown
2010-05-04 18:06               ` Kevin Hilman
2010-05-04 19:06                 ` Mark Brown
2010-05-04 20:37                   ` Rafael J. Wysocki
2010-05-04 23:14                     ` Kevin Hilman
2010-05-04 23:42                       ` Rafael J. Wysocki
2010-05-04 20:23                 ` Rafael J. Wysocki
2010-05-04 20:44                   ` Rafael J. Wysocki
2010-05-04 23:56                   ` Mark Brown
2010-05-05  0:22                     ` Rafael J. Wysocki
2010-05-05  1:11                       ` Brian Swetland
2010-05-05 11:06                       ` Mark Brown
2010-05-05 12:00                         ` Brian Swetland
2010-05-05 13:56                           ` Mark Brown
2010-05-05 17:33                             ` Matthew Garrett
2010-05-05 18:36                               ` Alan Stern
2010-05-05 18:52                                 ` Matthew Garrett
2010-05-05 19:13                                   ` Alan Stern
2010-05-05 19:22                                     ` Matthew Garrett
2010-05-05 19:52                                       ` Mark Brown
2010-05-05 19:55                                         ` tytso
2010-05-05 20:26                                           ` Mark Brown
2010-05-05 20:44                                             ` Rafael J. Wysocki
2010-05-05 21:57                                               ` Mark Brown
2010-05-05 22:03                                                 ` Brian Swetland
2010-05-05 22:05                                                 ` Rafael J. Wysocki
2010-05-05 23:09                                                   ` Mark Brown
2010-05-05 23:33                                                     ` Rafael J. Wysocki
2010-05-06  0:21                                                       ` Mark Brown
2010-05-06  0:51                                                         ` Rafael J. Wysocki
2010-05-05 20:02                                         ` Matthew Garrett
2010-05-05 20:09                                           ` Mark Brown
2010-05-05 19:39                                     ` Mark Brown
2010-05-05 20:56                                     ` Brian Swetland
2010-05-05 23:40                                       ` Mark Brown
2010-05-06  4:25                                         ` Arve Hjønnevåg
2010-05-07 10:04                                           ` Mark Brown
2010-05-07 10:57                                             ` Arve Hjønnevåg
2010-05-07 11:21                                               ` Mark Brown
2010-05-07 11:29                                                 ` Theodore Tso
2010-05-07 12:25                                                   ` Mark Brown
2010-05-07 12:37                                                     ` Brian Swetland
2010-05-07 13:30                                                       ` Mark Brown
2010-05-11 18:47                                                         ` Mark Brown
2010-05-07 11:41                                                 ` Arve Hjønnevåg
2010-05-07 14:00                                                   ` Mark Brown
2010-05-05 19:07                                 ` Mark Brown
2010-05-05 19:20                                   ` Alan Stern
2010-05-05 19:28                                     ` Matthew Garrett
2010-05-05 20:04                                       ` Alan Stern
2010-05-05 20:15                                         ` Mark Brown
2010-05-05 20:28                                         ` Rafael J. Wysocki
2010-05-05 23:03                                         ` Kevin Hilman
2010-05-05 23:16                                           ` Rafael J. Wysocki
2010-05-05 23:42                                           ` Brian Swetland
2010-05-06 14:08                                             ` Alan Stern
2010-05-06 19:26                                               ` Rafael J. Wysocki
2010-05-05 18:39                               ` Mark Brown
2010-05-05 15:35                     ` Alan Stern
2010-05-05 16:27                       ` Mark Brown
2010-05-04 18:04           ` Kevin Hilman
2010-05-04  0:43         ` Matthew Garrett
2010-05-04 13:51           ` Alan Stern
2010-05-04 14:53             ` Mark Brown
2010-05-04 15:13             ` Kevin Hilman
2010-05-04 15:27             ` Matthew Garrett
2010-05-06  1:40               ` Magnus Damm
2010-05-04 15:13           ` Kevin Hilman
2010-05-04 15:28             ` Matthew Garrett
2010-05-03 21:50   ` Matthew Garrett
     [not found]     ` <alpine.DEB.2.00.1005141408260.3348@utopia.booyaka.com>
     [not found]       ` <20100514203202.GA12409@srcf.ucam.org>
     [not found]         ` <87aas2azc5.fsf@deeprootsystems.com>
     [not found]           ` <20100514231510.GG16989@thunk.org>
     [not found]             ` <87r5laa4oc.fsf@deeprootsystems.com>
     [not found]               ` <AANLkTilL90pYVlquvMDAEPHj_AraEi9Qzk-0tTjw9Bkx@mail.gmail.com>
2010-05-17 20:07                 ` [linux-pm] " Mike Chan
2010-05-17 20:17                   ` Vitaly Wool
2010-05-17 21:04                     ` Mike Chan
2010-05-17 22:55                   ` Kevin Hilman
2010-05-17 23:04                     ` Brian Swetland
2010-05-24 18:57     ` Pavel Machek
2010-05-24 19:08       ` Matthew Garrett
2010-05-25  1:16       ` Arve Hjønnevåg
2010-05-26 17:32         ` Pavel Machek
2010-05-05 20:35   ` mark gross
2010-05-10 18:06   ` Kevin Hilman
2010-05-10 20:25     ` Rafael J. Wysocki
2010-05-11 16:12       ` Tony Lindgren
2010-05-11 16:14         ` Matthew Garrett
2010-05-11 16:36           ` Tony Lindgren
2010-05-11 16:45             ` Matthew Garrett
2010-05-11 16:58               ` Tony Lindgren
2010-05-11 17:03                 ` Matthew Garrett
2010-05-11 17:24                   ` Tony Lindgren
2010-05-11 17:30                     ` Matthew Garrett
2010-05-11 17:48                       ` Tony Lindgren
2010-05-11 18:01                         ` Matthew Garrett
2010-05-11 18:19                       ` Rafael J. Wysocki
2010-05-12  1:11     ` Arve Hjønnevåg
2010-05-12 11:22       ` Mark Brown
2010-05-13  3:35 ` [linux-pm] " Paul Walmsley
2010-05-13 12:17   ` Matthew Garrett
2010-05-13 17:33     ` Daniel Walker
2010-05-13 18:17       ` Brian Swetland
2010-05-13 18:25         ` Daniel Walker
2010-05-13 18:36           ` Matthew Garrett
2010-05-13 18:59             ` Daniel Walker
2010-05-13 19:11               ` Matthew Garrett
2010-05-13 19:36                 ` Daniel Walker
2010-05-13 19:48                   ` Matthew Garrett
2010-05-13 21:11                     ` Rafael J. Wysocki
2010-05-13 21:16                       ` Daniel Walker
2010-05-13 21:27                         ` Rafael J. Wysocki
2010-05-13 21:33                           ` Daniel Walker
2010-05-13 21:36                             ` Tony Lindgren
2010-05-13 21:54                               ` Rafael J. Wysocki
2010-05-13 21:46                             ` Greg KH
2010-05-13 22:27                               ` Mark Brown
2010-05-13 22:45                                 ` Greg KH
2010-05-14  0:03                                   ` Mark Brown
2010-05-13 22:46                                 ` Rafael J. Wysocki
2010-05-13 23:36                                   ` Mark Brown
2010-05-13 23:48                                     ` Brian Swetland
2010-05-14  0:29                                       ` Mark Brown
2010-05-13 22:33                               ` Woodruff, Richard
2010-05-13 22:46                                 ` Greg KH
2010-05-13 23:06                                   ` Arve Hjønnevåg
2010-05-13 23:28                                   ` Brian Swetland
2010-05-14 16:47                               ` Daniel Walker
2010-05-13 14:16   ` Alan Stern
2010-05-13 19:17     ` Tony Lindgren
2010-05-13 19:25       ` Matthew Garrett
2010-05-13 19:42         ` Tony Lindgren
2010-05-13 19:53           ` Matthew Garrett
2010-05-13 20:00             ` Tony Lindgren
2010-05-13 20:08               ` Matthew Garrett
2010-05-13 20:23                 ` Tony Lindgren
2010-05-13 20:34                   ` Matthew Garrett
2010-05-13 21:10                     ` Tony Lindgren
2010-05-13 21:21                       ` Matthew Garrett
2010-05-13 21:34                         ` Tony Lindgren
2010-05-15 19:54                           ` Matthew Garrett
2010-05-13 21:21                     ` Rafael J. Wysocki
2010-05-13 21:25                       ` Tony Lindgren
2010-05-13 21:56                         ` Rafael J. Wysocki
2010-05-14 20:41                           ` Kevin Hilman
2010-05-14 21:25                             ` Rafael J. Wysocki
2010-05-14 21:40                             ` Kevin Hilman
2010-05-14 21:50                               ` Rafael J. Wysocki
2010-05-14 22:45                                 ` Kevin Hilman
2010-05-14 22:59                                   ` Brian Swetland
2010-05-15  2:58                                     ` Alan Stern
2010-05-15  3:40                                       ` Brian Swetland
2010-05-15 21:19                                         ` Alan Stern
2010-05-17 15:40                                           ` Kevin Hilman
2010-05-17 17:04                                             ` James Bottomley
2010-05-17 17:47                                               ` Felipe Balbi
2010-05-17 17:58                                                 ` Matthew Garrett
2010-05-17 18:16                                                   ` Felipe Balbi
2010-05-17 17:59                                                 ` James Bottomley
2010-05-17 18:12                                                   ` Felipe Balbi
2010-05-17 18:26                                                     ` Brian Swetland
2010-05-17 18:39                                                       ` Felipe Balbi
2010-05-17 18:45                                                         ` Brian Swetland
2010-05-17 20:22                                                           ` Rafael J. Wysocki
2010-05-17 18:45                                                         ` Mark Brown
2010-05-17 18:47                                                         ` Mike Chan
2010-05-17 19:24                                                     ` James Bottomley
2010-05-17 19:38                                                       ` Felipe Balbi
2010-05-17 19:39                                                         ` Felipe Balbi
2010-05-17 19:49                                                           ` James Bottomley
2010-05-18  6:40                                                             ` Felipe Balbi
2010-05-18 13:59                                                               ` James Bottomley
2010-05-19  6:59                                                                 ` Felipe Balbi
2010-05-19 20:42                                                                   ` Rafael J. Wysocki
2010-05-20  4:49                                                                     ` Felipe Balbi
2010-05-20 11:27                                                                       ` Vladimir Pantelic
2010-05-20 11:29                                                                         ` Felipe Balbi
2010-05-20 17:40                                                                         ` David Brownell
2010-05-20 18:50                                                                           ` Felipe Balbi
2010-05-20 23:08                                                                             ` David Brownell
2010-05-20  5:15                                                                   ` Florian Mickler
2010-05-20  8:57                                                                     ` Felipe Balbi
2010-05-20  8:57                                                                       ` Felipe Balbi
2010-05-20 10:05                                                                       ` Florian Mickler
2010-05-20 10:15                                                                         ` Felipe Balbi
2010-05-17 18:54                                                   ` Kevin Hilman
2010-05-17 17:57                                               ` Daniel Walker
2010-05-15 20:14                                   ` Rafael J. Wysocki
2010-05-16 19:44                                     ` Mark Brown
2010-05-13 22:24                         ` tytso
2010-05-13 20:36                   ` Daniel Walker
2010-05-14 16:06                 ` Kevin Hilman
2010-05-24 21:25                 ` Pavel Machek
2010-05-13 21:41           ` Alan Stern
2010-05-13 21:54             ` Tony Lindgren
2010-05-13 22:07               ` Rafael J. Wysocki
2010-05-13 22:26           ` Arve Hjønnevåg
2010-05-13 21:14       ` Rafael J. Wysocki
2010-05-13 21:31         ` Tony Lindgren
2010-05-13 21:57           ` Rafael J. Wysocki
2010-05-13 21:37       ` Alan Stern
2010-05-13 21:47         ` Tony Lindgren
2010-05-13 22:01           ` Alan Stern
2010-05-13 22:08             ` Tony Lindgren
2010-05-13 22:28               ` Rafael J. Wysocki
2010-05-15  2:35                 ` Alan Stern
2010-05-15  4:04                   ` Arve Hjønnevåg
2010-05-13 22:04           ` Rafael J. Wysocki
2010-05-14  3:25           ` Magnus Damm
2010-05-14 16:18             ` Kevin Hilman
2010-05-15  2:47             ` Alan Stern
2010-05-24 21:24     ` Pavel Machek
  -- strict thread matches above, loose matches on Subject: below --
2010-05-14  4:11 [PATCH 0/8] Suspend block api (version 7) Arve Hjønnevåg
2010-05-14  4:11 ` [PATCH 1/8] PM: Add suspend block api Arve Hjønnevåg
2010-05-18 13:11   ` Pavel Machek
2010-05-20  9:11     ` Florian Mickler
2010-05-20  9:26       ` Florian Mickler
2010-05-20 22:18         ` Rafael J. Wysocki
2010-05-21  6:04           ` Florian Mickler
2010-05-27 15:41           ` Pavel Machek
2010-04-28  4:31 [PATCH 0/9] Suspend block api (version 5) Arve Hjønnevåg
2010-04-28  4:31 ` [PATCH 1/8] PM: Add suspend block api Arve Hjønnevåg
2010-04-28  6:07   ` Pavel Machek
2010-04-28 19:13   ` Alan Stern
2010-04-28 21:13     ` Rafael J. Wysocki
2010-04-28 23:35       ` Arve Hjønnevåg
2010-04-29 15:41         ` Alan Stern
2010-04-29 23:39           ` Arve Hjønnevåg
2010-04-30 14:41             ` Alan Stern
2010-04-28 20:50   ` Rafael J. Wysocki
2010-04-29  3:37     ` Arve Hjønnevåg
2010-04-29 21:16       ` Rafael J. Wysocki
2010-04-30  4:24         ` Tejun Heo
2010-04-30 17:26           ` Oleg Nesterov
2010-05-20  8:30             ` Tejun Heo
2010-05-20 22:27               ` Rafael J. Wysocki
2010-05-21  6:35                 ` Tejun Heo
2010-05-06 15:18   ` Alan Stern
2010-05-06 19:28     ` Rafael J. Wysocki
2010-05-06 19:40       ` Alan Stern
2010-05-06 23:48         ` Arve Hjønnevåg
2010-05-07 14:22           ` Alan Stern

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100502070145.GC1790@ucw.cz \
    --to=pavel@ucw.cz \
    --cc=akpm@linux-foundation.org \
    --cc=arve@android.com \
    --cc=cornelia.huck@de.ibm.com \
    --cc=damm@igel.co.jp \
    --cc=fengguang.wu@intel.com \
    --cc=jbarnes@virtuousgeek.org \
    --cc=len.brown@intel.com \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@lists.linux-foundation.org \
    --cc=maximlevitsky@gmail.com \
    --cc=nigel@tuxonice.net \
    --cc=oleg@redhat.com \
    --cc=rdunlap@xenotime.net \
    --cc=rjw@sisk.pl \
    --cc=stern@rowland.harvard.edu \
    --cc=tj@kernel.org \
    --cc=tom.leiming@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome