* [PATCH 1/8] PM: Add suspend block api. [not found] <1273810273-3039-1-git-send-email-arve@android.com> @ 2010-05-14 4:11 ` Arve Hjønnevåg 2010-05-14 4:11 ` [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space Arve Hjønnevåg ` (4 more replies) 2010-05-14 21:08 ` [PATCH 0/8] Suspend block api (version 7) Rafael J. Wysocki ` (3 subsequent siblings) 4 siblings, 5 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-14 4:11 UTC (permalink / raw) To: linux-pm, linux-kernel Cc: Len Brown, Andi Kleen, linux-doc, Jesse Barnes, Tejun Heo, Magnus Damm, Andrew Morton, Wu Fengguang 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> --- Documentation/power/opportunistic-suspend.txt | 129 +++++++++++ include/linux/suspend.h | 1 + include/linux/suspend_blocker.h | 74 +++++++ kernel/power/Kconfig | 16 ++ kernel/power/Makefile | 1 + kernel/power/main.c | 128 +++++++++++- kernel/power/opportunistic_suspend.c | 284 +++++++++++++++++++++++++ kernel/power/power.h | 9 + kernel/power/suspend.c | 3 +- 9 files changed, 637 insertions(+), 8 deletions(-) create mode 100644 Documentation/power/opportunistic-suspend.txt create mode 100755 include/linux/suspend_blocker.h create mode 100644 kernel/power/opportunistic_suspend.c diff --git a/Documentation/power/opportunistic-suspend.txt b/Documentation/power/opportunistic-suspend.txt new file mode 100644 index 0000000..4bee7bc --- /dev/null +++ b/Documentation/power/opportunistic-suspend.txt @@ -0,0 +1,129 @@ +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_unregister() +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, name); +} + +If the suspend_blocker variable is allocated statically, +DEFINE_SUSPEND_BLOCKER() should be used to initialize it, for example: + +static DEFINE_SUSPEND_BLOCKER(blocker, name); + +and suspend_blocker_register(&blocker) has to be called to make the suspend +blocker usable. + +Before freeing the memory in which a suspend_blocker variable is located, +suspend_blocker_unregister() must be called, for instance: + +uninit() { + suspend_blocker_unregister(&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.h b/include/linux/suspend.h index 5e781d8..07023d3 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -6,6 +6,7 @@ #include <linux/init.h> #include <linux/pm.h> #include <linux/mm.h> +#include <linux/suspend_blocker.h> #include <asm/errno.h> #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) diff --git a/include/linux/suspend_blocker.h b/include/linux/suspend_blocker.h new file mode 100755 index 0000000..8788302 --- /dev/null +++ b/include/linux/suspend_blocker.h @@ -0,0 +1,74 @@ +/* include/linux/suspend_blocker.h + * + * Copyright (C) 2007-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. + * + */ + +#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: Suspend blocker 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 +#define __SUSPEND_BLOCKER_INITIALIZER(blocker_name) \ + { .name = #blocker_name, } + +#define DEFINE_SUSPEND_BLOCKER(blocker, name) \ + struct suspend_blocker blocker = __SUSPEND_BLOCKER_INITIALIZER(name) + +extern void suspend_blocker_register(struct suspend_blocker *blocker); +extern void suspend_blocker_init(struct suspend_blocker *blocker, + const char *name); +extern void suspend_blocker_unregister(struct suspend_blocker *blocker); +extern void suspend_block(struct suspend_blocker *blocker); +extern void suspend_unblock(struct suspend_blocker *blocker); +extern bool suspend_blocker_is_active(struct suspend_blocker *blocker); +extern bool suspend_is_blocked(void); + +#else + +#define DEFINE_SUSPEND_BLOCKER(blocker, name) \ + struct suspend_blocker blocker + +static inline void suspend_blocker_register(struct suspend_blocker *bl) {} +static inline void suspend_blocker_init(struct suspend_blocker *bl, + const char *n) {} +static inline void suspend_blocker_unregister(struct suspend_blocker *bl) {} +static inline void suspend_block(struct suspend_blocker *bl) {} +static inline void suspend_unblock(struct suspend_blocker *bl) {} +static inline bool suspend_blocker_is_active(struct suspend_blocker *bl) +{ + return false; +} +static inline bool suspend_is_blocked(void) { return false; } +#endif + +#endif diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 5c36ea9..6d11a45 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 "Opportunistic suspend" + depends on SUSPEND + 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..95d8e6d 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) += opportunistic_suspend.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..afbb4dd 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -20,6 +20,58 @@ DEFINE_MUTEX(pm_mutex); unsigned int pm_flags; EXPORT_SYMBOL(pm_flags); +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND +struct pm_policy { + const char *name; + bool (*valid_state)(suspend_state_t state); + int (*set_state)(suspend_state_t state); +}; + +static struct pm_policy policies[] = { + { + .name = "forced", + .valid_state = valid_state, + .set_state = enter_state, + }, + { + .name = "opportunistic", + .valid_state = opportunistic_suspend_valid_state, + .set_state = opportunistic_suspend_state, + }, +}; + +static int policy; + +static inline bool hibernation_supported(void) +{ + return !strncmp(policies[policy].name, "forced", 6); +} + +static inline bool pm_state_valid(int state_idx) +{ + return pm_states[state_idx] && policies[policy].valid_state(state_idx); +} + +static inline int pm_enter_state(int state_idx) +{ + return policies[policy].set_state(state_idx); +} + +#else + +static inline bool hibernation_supported(void) { return true; } + +static inline bool pm_state_valid(int state_idx) +{ + return pm_states[state_idx] && valid_state(state_idx); +} + +static inline int pm_enter_state(int state_idx) +{ + return enter_state(state_idx); +} +#endif /* CONFIG_OPPORTUNISTIC_SUSPEND */ + #ifdef CONFIG_PM_SLEEP /* Routines for PM-transition notifications */ @@ -146,6 +198,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 disable. */ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) @@ -155,12 +213,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_state_valid(i)) s += sprintf(s,"%s ", pm_states[i]); } #endif #ifdef CONFIG_HIBERNATION - s += sprintf(s, "%s\n", "disk"); + if (hibernation_supported()) + s += sprintf(s, "%s\n", "disk"); #else if (s != buf) /* convert the last space to a newline */ @@ -173,7 +232,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; @@ -185,8 +244,9 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, /* First, check if we are requested to hibernate */ if (len == 4 && !strncmp(buf, "disk", len)) { - error = hibernate(); - goto Exit; + if (hibernation_supported()) + error = hibernate(); + goto Exit; } #ifdef CONFIG_SUSPEND @@ -195,7 +255,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 = pm_enter_state(state); #endif Exit: @@ -204,6 +264,56 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, power_attr(state); +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND +/** + * 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); +#endif /* CONFIG_OPPORTUNISTIC_SUSPEND */ + #ifdef CONFIG_PM_TRACE int pm_trace_enabled; @@ -236,6 +346,9 @@ static struct attribute * g[] = { #endif #ifdef CONFIG_PM_SLEEP &pm_async_attr.attr, +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND + &policy_attr.attr, +#endif #ifdef CONFIG_PM_DEBUG &pm_test_attr.attr, #endif @@ -247,7 +360,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 +379,7 @@ static int __init pm_init(void) int error = pm_start_workqueue(); if (error) return error; + opportunistic_suspend_init(); power_kobj = kobject_create_and_add("power", NULL); if (!power_kobj) return -ENOMEM; diff --git a/kernel/power/opportunistic_suspend.c b/kernel/power/opportunistic_suspend.c new file mode 100644 index 0000000..acc1651 --- /dev/null +++ b/kernel/power/opportunistic_suspend.c @@ -0,0 +1,284 @@ +/* + * kernel/power/opportunistic_suspend.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 "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) + +DEFINE_SUSPEND_BLOCKER(main_suspend_blocker, main); + +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; +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_suspend_blockers(void) +{ + struct suspend_blocker *blocker; + + list_for_each_entry(blocker, &active_blockers, link) + pr_info("PM: Active suspend blocker %s\n", blocker->name); +} + +/** + * suspend_is_blocked - Check if there are active suspend blockers. + * + * Return true if suspend blockers are enabled and there are active suspend + * blockers, in which case the system cannot be put to sleep opportunistically. + */ +bool suspend_is_blocked(void) +{ + return enable_suspend_blockers && !list_empty(&active_blockers); +} + +static void suspend_worker(struct work_struct *work) +{ + int ret; + int entry_event_num; + + enable_suspend_blockers = true; + + if (suspend_is_blocked()) { + if (debug_mask & DEBUG_SUSPEND) + pr_info("PM: Automatic suspend aborted\n"); + goto abort; + } + + entry_event_num = current_event_num; + + if (debug_mask & DEBUG_SUSPEND) + pr_info("PM: Automatic suspend\n"); + + ret = pm_suspend(requested_suspend_state); + + if (debug_mask & DEBUG_EXIT_SUSPEND) + pr_info_time("PM: Automatic suspend exit, ret = %d ", ret); + + if (current_event_num == entry_event_num) { + if (debug_mask & DEBUG_SUSPEND) + pr_info("PM: pm_suspend() returned with no event\n"); + queue_work(pm_wq, work); + } + +abort: + enable_suspend_blockers = false; +} +static DECLARE_WORK(suspend_work, suspend_worker); + +/** + * suspend_blocker_register - Prepare a suspend blocker for being used. + * @blocker: Suspend blocker to handle. + * + * The suspend blocker struct and name must not be freed before calling + * suspend_blocker_unregister(). + */ +void suspend_blocker_register(struct suspend_blocker *blocker) +{ + unsigned long irqflags = 0; + + WARN_ON(!blocker->name); + + if (debug_mask & DEBUG_SUSPEND_BLOCKER) + pr_info("%s: Registering %s\n", __func__, blocker->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_register); + +/** + * suspend_blocker_init - Initialize a suspend blocker's name and register it. + * @blocker: 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_unregister(). + */ +void suspend_blocker_init(struct suspend_blocker *blocker, const char *name) +{ + blocker->name = name; + suspend_blocker_register(blocker); +} +EXPORT_SYMBOL(suspend_blocker_init); + +/** + * suspend_blocker_unregister - Unregister a suspend blocker. + * @blocker: Suspend blocker to handle. + */ +void suspend_blocker_unregister(struct suspend_blocker *blocker) +{ + unsigned long irqflags; + + if (WARN_ON(!(blocker->flags & SB_INITIALIZED))) + return; + + 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); + + if (debug_mask & DEBUG_SUSPEND_BLOCKER) + pr_info("%s: Unregistered %s\n", __func__, blocker->name); +} +EXPORT_SYMBOL(suspend_blocker_unregister); + +/** + * suspend_block - Block system suspend. + * @blocker: 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("%s: %s\n", __func__, 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 - Allow system suspend to happen. + * @blocker: Suspend blocker to unblock. + * + * If no other suspend blockers are active, schedule suspend of the system. + * + * 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("%s: %s\n", __func__, 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 ((debug_mask & DEBUG_SUSPEND) && blocker == &main_suspend_blocker) + print_active_suspend_blockers(); + + spin_unlock_irqrestore(&list_lock, irqflags); +} +EXPORT_SYMBOL(suspend_unblock); + +/** + * suspend_blocker_is_active - Test if a suspend blocker is blocking suspend + * @blocker: 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 opportunistic_suspend_valid_state(suspend_state_t state) +{ + return (state == PM_SUSPEND_ON) || valid_state(state); +} + +int opportunistic_suspend_state(suspend_state_t state) +{ + unsigned long irqflags; + + if (!opportunistic_suspend_valid_state(state)) + return -ENODEV; + + spin_lock_irqsave(&state_lock, irqflags); + + if (debug_mask & DEBUG_USER_STATE) + pr_info_time("%s: %s (%d->%d) at %lld ", __func__, + 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 opportunistic_suspend_init(void) +{ + suspend_blocker_register(&main_suspend_blocker); + suspend_block(&main_suspend_blocker); +} diff --git a/kernel/power/power.h b/kernel/power/power.h index 46c5a26..2e9cfd5 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -236,3 +236,12 @@ static inline void suspend_thaw_processes(void) { } #endif + +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND +/* kernel/power/opportunistic_suspend.c */ +extern int opportunistic_suspend_state(suspend_state_t state); +extern bool opportunistic_suspend_valid_state(suspend_state_t state); +extern void __init opportunistic_suspend_init(void); +#else +static inline void opportunistic_suspend_init(void) {} +#endif diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 56e7dbb..9eb3876 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -20,6 +20,7 @@ #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 +158,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(); } -- 1.6.5.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] 89+ messages in thread
* [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space 2010-05-14 4:11 ` [PATCH 1/8] PM: Add suspend block api Arve Hjønnevåg @ 2010-05-14 4:11 ` Arve Hjønnevåg 2010-05-14 4:11 ` [PATCH 3/8] PM: suspend_block: Abort task freezing if a suspend_blocker is active Arve Hjønnevåg 2010-05-14 6:13 ` [PATCH 1/8] PM: Add suspend block api Paul Walmsley ` (3 subsequent siblings) 4 siblings, 1 reply; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-14 4:11 UTC (permalink / raw) To: linux-pm, linux-kernel Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, Avi Kivity, Ryusuke Konishi, Magnus Damm, Andrew Morton 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@android.com> --- Documentation/ioctl/ioctl-number.txt | 3 +- Documentation/power/opportunistic-suspend.txt | 27 +++++ include/linux/suspend_ioctls.h | 4 + kernel/power/Kconfig | 7 ++ kernel/power/Makefile | 1 + kernel/power/user_suspend_blocker.c | 143 +++++++++++++++++++++++++ 6 files changed, 184 insertions(+), 1 deletions(-) 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 4bee7bc..93f4c24 100644 --- a/Documentation/power/opportunistic-suspend.txt +++ b/Documentation/power/opportunistic-suspend.txt @@ -127,3 +127,30 @@ if (list_empty(&state->pending_work)) suspend_unblock(&state->suspend_blocker); else suspend_block(&state->suspend_blocker); + +User space API +============== + +To create a suspend blocker from user space, open the suspend_blocker special +device file: + + fd = open("/dev/suspend_blocker", O_RDWR | O_CLOEXEC); + +then optionally call: + + ioctl(fd, SUSPEND_BLOCKER_IOCTL_SET_NAME(strlen(name)), name); + +To activate the suspend blocker call: + + ioctl(fd, SUSPEND_BLOCKER_IOCTL_BLOCK); + +To deactivate it call: + + ioctl(fd, SUSPEND_BLOCKER_IOCTL_UNBLOCK); + +To destroy the suspend blocker, close the device: + + close(fd); + +If the first ioctl called is not SUSPEND_BLOCKER_IOCTL_SET_NAME the suspend +blocker will get the default name "(userspace)". diff --git a/include/linux/suspend_ioctls.h b/include/linux/suspend_ioctls.h index 0b30382..b95a6b2 100644 --- a/include/linux/suspend_ioctls.h +++ b/include/linux/suspend_ioctls.h @@ -30,4 +30,8 @@ struct resume_swap_area { #define SNAPSHOT_ALLOC_SWAP_PAGE _IOR(SNAPSHOT_IOC_MAGIC, 20, __kernel_loff_t) #define SNAPSHOT_IOC_MAXNR 20 +#define SUSPEND_BLOCKER_IOCTL_SET_NAME(len) _IOC(_IOC_WRITE, 's', 0, len) +#define SUSPEND_BLOCKER_IOCTL_BLOCK _IO('s', 1) +#define SUSPEND_BLOCKER_IOCTL_UNBLOCK _IO('s', 2) + #endif /* _LINUX_SUSPEND_IOCTLS_H */ diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 6d11a45..2e665cd 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -146,6 +146,13 @@ 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 "User space suspend blockers" + depends on OPPORTUNISTIC_SUSPEND + ---help--- + User space suspend blockers API. Creates a misc device allowing user + space to create, use and destroy suspend blockers. + config HIBERNATION_NVS bool diff --git a/kernel/power/Makefile b/kernel/power/Makefile index 95d8e6d..2015594 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) += opportunistic_suspend.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..d53f939 --- /dev/null +++ b/kernel/power/user_suspend_blocker.c @@ -0,0 +1,143 @@ +/* + * kernel/power/user_suspend_blocker.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.h> +#include <linux/suspend_ioctls.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); + +#define USER_SUSPEND_BLOCKER_NAME_LEN 31 + +struct user_suspend_blocker { + struct suspend_blocker blocker; + char name[USER_SUSPEND_BLOCKER_NAME_LEN + 1]; + bool registered; +}; + +static int user_suspend_blocker_open(struct inode *inode, struct file *filp) +{ + struct user_suspend_blocker *blocker; + + blocker = kzalloc(sizeof(*blocker), GFP_KERNEL); + if (!blocker) + return -ENOMEM; + + nonseekable_open(inode, filp); + strcpy(blocker->name, "(userspace)"); + blocker->blocker.name = blocker->name; + filp->private_data = blocker; + + return 0; +} + +static int suspend_blocker_set_name(struct user_suspend_blocker *blocker, + void __user *name, size_t name_len) +{ + if (blocker->registered) + return -EBUSY; + + if (name_len > USER_SUSPEND_BLOCKER_NAME_LEN) + name_len = USER_SUSPEND_BLOCKER_NAME_LEN; + + if (copy_from_user(blocker->name, name, name_len)) + return -EFAULT; + blocker->name[name_len] = '\0'; + + return 0; +} + +static long user_suspend_blocker_ioctl(struct file *filp, unsigned int cmd, + unsigned long _arg) +{ + void __user *arg = (void __user *)_arg; + struct user_suspend_blocker *blocker = filp->private_data; + long ret = 0; + + mutex_lock(&ioctl_lock); + if ((cmd & ~IOCSIZE_MASK) == SUSPEND_BLOCKER_IOCTL_SET_NAME(0)) { + ret = suspend_blocker_set_name(blocker, arg, _IOC_SIZE(cmd)); + goto done; + } + if (!blocker->registered) { + suspend_blocker_register(&blocker->blocker); + blocker->registered = true; + } + switch (cmd) { + case SUSPEND_BLOCKER_IOCTL_BLOCK: + suspend_block(&blocker->blocker); + break; + + case SUSPEND_BLOCKER_IOCTL_UNBLOCK: + suspend_unblock(&blocker->blocker); + break; + + default: + ret = -ENOTTY; + } +done: + if (ret && (debug_mask & DEBUG_FAILURE)) + pr_err("user_suspend_blocker_ioctl: cmd %x failed, %ld\n", + cmd, ret); + mutex_unlock(&ioctl_lock); + return ret; +} + +static int user_suspend_blocker_release(struct inode *inode, struct file *filp) +{ + struct user_suspend_blocker *blocker = filp->private_data; + + if (blocker->registered) + suspend_blocker_unregister(&blocker->blocker); + kfree(blocker); + + return 0; +} + +const struct file_operations user_suspend_blocker_fops = { + .open = user_suspend_blocker_open, + .release = user_suspend_blocker_release, + .unlocked_ioctl = user_suspend_blocker_ioctl, +}; + +struct miscdevice user_suspend_blocker_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "suspend_blocker", + .fops = &user_suspend_blocker_fops, +}; + +static int __init user_suspend_blocker_init(void) +{ + return misc_register(&user_suspend_blocker_device); +} + +static void __exit user_suspend_blocker_exit(void) +{ + misc_deregister(&user_suspend_blocker_device); +} + +module_init(user_suspend_blocker_init); +module_exit(user_suspend_blocker_exit); -- 1.6.5.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] 89+ messages in thread
* [PATCH 3/8] PM: suspend_block: Abort task freezing if a suspend_blocker is active. 2010-05-14 4:11 ` [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space Arve Hjønnevåg @ 2010-05-14 4:11 ` Arve Hjønnevåg 2010-05-14 4:11 ` [PATCH 4/8] PM: suspend_block: Add debugfs file Arve Hjønnevåg 0 siblings, 1 reply; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-14 4:11 UTC (permalink / raw) To: linux-pm, linux-kernel; +Cc: Len Brown, David Rientjes, Andrew Morton If a suspend_blocker is active, suspend will fail anyway. Since try_to_freeze_tasks can take up to 20 seconds to complete or fail, aborting as soon as someone blocks suspend (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. Signed-off-by: Arve Hjønnevåg <arve@android.com> Acked-by: Pavel Machek <pavel@ucw.cz> --- kernel/power/process.c | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-) diff --git a/kernel/power/process.c b/kernel/power/process.c index 71ae290..27d26d3 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -38,6 +38,7 @@ static int try_to_freeze_tasks(bool sig_only) struct timeval start, end; u64 elapsed_csecs64; unsigned int elapsed_csecs; + bool wakeup = false; do_gettimeofday(&start); @@ -63,6 +64,10 @@ static int try_to_freeze_tasks(bool sig_only) todo++; } while_each_thread(g, p); read_unlock(&tasklist_lock); + if (todo && suspend_is_blocked()) { + wakeup = true; + break; + } if (!todo || time_after(jiffies, end_time)) break; @@ -85,13 +90,15 @@ static int try_to_freeze_tasks(bool sig_only) * but it cleans up leftover PF_FREEZE requests. */ printk("\n"); - printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds " + printk(KERN_ERR "Freezing of tasks %s after %d.%02d seconds " "(%d tasks refusing to freeze):\n", + wakeup ? "aborted" : "failed", elapsed_csecs / 100, elapsed_csecs % 100, todo); read_lock(&tasklist_lock); do_each_thread(g, p) { task_lock(p); - if (freezing(p) && !freezer_should_skip(p)) + if (freezing(p) && !freezer_should_skip(p) + && elapsed_csecs > 100) sched_show_task(p); cancel_freezing(p); task_unlock(p); -- 1.6.5.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] 89+ messages in thread
* [PATCH 4/8] PM: suspend_block: Add debugfs file 2010-05-14 4:11 ` [PATCH 3/8] PM: suspend_block: Abort task freezing if a suspend_blocker is active Arve Hjønnevåg @ 2010-05-14 4:11 ` Arve Hjønnevåg 2010-05-14 4:11 ` [PATCH 5/8] PM: suspend_block: Add suspend_blocker stats Arve Hjønnevåg 0 siblings, 1 reply; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-14 4:11 UTC (permalink / raw) To: linux-pm, linux-kernel; +Cc: Len Brown, Tejun Heo Report active and inactive suspend blockers in /sys/kernel/debug/suspend_blockers. Signed-off-by: Arve Hjønnevåg <arve@android.com> --- kernel/power/opportunistic_suspend.c | 43 +++++++++++++++++++++++++++++++++- 1 files changed, 42 insertions(+), 1 deletions(-) diff --git a/kernel/power/opportunistic_suspend.c b/kernel/power/opportunistic_suspend.c index acc1651..c2dad76 100644 --- a/kernel/power/opportunistic_suspend.c +++ b/kernel/power/opportunistic_suspend.c @@ -17,6 +17,7 @@ #include <linux/module.h> #include <linux/rtc.h> #include <linux/suspend.h> +#include <linux/debugfs.h> #include "power.h" @@ -138,7 +139,8 @@ EXPORT_SYMBOL(suspend_blocker_register); /** * suspend_blocker_init - Initialize a suspend blocker's name and register it. * @blocker: Suspend blocker to initialize. - * @name: The name of the suspend blocker to show in debug messages. + * @name: The name of the suspend blocker to show in debug messages and + * /sys/kernel/debug/suspend_blockers. * * The suspend blocker struct and name must not be freed before calling * suspend_blocker_unregister(). @@ -282,3 +284,42 @@ void __init opportunistic_suspend_init(void) suspend_blocker_register(&main_suspend_blocker); suspend_block(&main_suspend_blocker); } + +static struct dentry *suspend_blocker_stats_dentry; + +static int suspend_blocker_stats_show(struct seq_file *m, void *unused) +{ + unsigned long irqflags; + struct suspend_blocker *blocker; + + seq_puts(m, "name\tactive\n"); + spin_lock_irqsave(&list_lock, irqflags); + list_for_each_entry(blocker, &inactive_blockers, link) + seq_printf(m, "\"%s\"\t0\n", blocker->name); + list_for_each_entry(blocker, &active_blockers, link) + seq_printf(m, "\"%s\"\t1\n", blocker->name); + spin_unlock_irqrestore(&list_lock, irqflags); + return 0; +} + +static int suspend_blocker_stats_open(struct inode *inode, struct file *file) +{ + return single_open(file, suspend_blocker_stats_show, NULL); +} + +static const struct file_operations suspend_blocker_stats_fops = { + .owner = THIS_MODULE, + .open = suspend_blocker_stats_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init suspend_blocker_debugfs_init(void) +{ + suspend_blocker_stats_dentry = debugfs_create_file("suspend_blockers", + S_IRUGO, NULL, NULL, &suspend_blocker_stats_fops); + return 0; +} + +postcore_initcall(suspend_blocker_debugfs_init); -- 1.6.5.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] 89+ messages in thread
* [PATCH 5/8] PM: suspend_block: Add suspend_blocker stats 2010-05-14 4:11 ` [PATCH 4/8] PM: suspend_block: Add debugfs file Arve Hjønnevåg @ 2010-05-14 4:11 ` Arve Hjønnevåg 2010-05-14 4:11 ` [PATCH 6/8] PM: Add suspend blocking work Arve Hjønnevåg [not found] ` <1273810273-3039-7-git-send-email-arve@android.com> 0 siblings, 2 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-14 4:11 UTC (permalink / raw) To: linux-pm, linux-kernel Cc: Len Brown, Jesse Barnes, Tejun Heo, Magnus Damm, Andrew Morton, Wu Fengguang Report suspend block stats in /sys/kernel/debug/suspend_blockers. Signed-off-by: Arve Hjønnevåg <arve@android.com> --- include/linux/suspend_blocker.h | 27 +++++- kernel/power/Kconfig | 8 ++ kernel/power/opportunistic_suspend.c | 200 +++++++++++++++++++++++++++++++++- kernel/power/power.h | 5 + kernel/power/suspend.c | 4 +- 5 files changed, 239 insertions(+), 5 deletions(-) diff --git a/include/linux/suspend_blocker.h b/include/linux/suspend_blocker.h index 8788302..256af15 100755 --- a/include/linux/suspend_blocker.h +++ b/include/linux/suspend_blocker.h @@ -17,11 +17,35 @@ #define _LINUX_SUSPEND_BLOCKER_H #include <linux/list.h> +#include <linux/ktime.h> + +/** + * struct suspend_blocker_stats - statistics for a suspend blocker + * + * @count: Number of times this blocker has been deacivated. + * @wakeup_count: Number of times this blocker was the first to block suspend + * after resume. + * @total_time: Total time this suspend blocker has prevented suspend. + * @prevent_suspend_time: Time this suspend blocker has prevented suspend while + * user-space requested suspend. + * @max_time: Max time this suspend blocker has been continuously active. + * @last_time: Monotonic clock when the active state last changed. + */ +struct suspend_blocker_stats { +#ifdef CONFIG_SUSPEND_BLOCKER_STATS + unsigned int count; + unsigned int wakeup_count; + ktime_t total_time; + ktime_t prevent_suspend_time; + ktime_t max_time; + ktime_t last_time; +#endif +}; /** * struct suspend_blocker - the basic suspend_blocker structure * @link: List entry for active or inactive list. - * @flags: Tracks initialized and active state. + * @flags: Tracks initialized and active state and statistics. * @name: Suspend blocker name used for debugging. * * When a suspend_blocker is active it prevents the system from entering @@ -34,6 +58,7 @@ struct suspend_blocker { struct list_head link; int flags; const char *name; + struct suspend_blocker_stats stat; #endif }; diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 2e665cd..16a2570 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -146,6 +146,14 @@ config OPPORTUNISTIC_SUSPEND determines the sleep state the system will be put into when there are no active suspend blockers. +config SUSPEND_BLOCKER_STATS + bool "Suspend blockers statistics" + depends on OPPORTUNISTIC_SUSPEND + default y + ---help--- + Use /sys/kernel/debug/suspend_blockers to report suspend blockers + statistics. + config USER_SUSPEND_BLOCKERS bool "User space suspend blockers" depends on OPPORTUNISTIC_SUSPEND diff --git a/kernel/power/opportunistic_suspend.c b/kernel/power/opportunistic_suspend.c index c2dad76..3f0153d 100644 --- a/kernel/power/opportunistic_suspend.c +++ b/kernel/power/opportunistic_suspend.c @@ -35,6 +35,7 @@ module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); #define SB_INITIALIZED (1U << 8) #define SB_ACTIVE (1U << 9) +#define SB_PREVENTING_SUSPEND (1U << 10) DEFINE_SUSPEND_BLOCKER(main_suspend_blocker, main); @@ -45,6 +46,118 @@ static LIST_HEAD(active_blockers); static int current_event_num; static suspend_state_t requested_suspend_state = PM_SUSPEND_MEM; static bool enable_suspend_blockers; +static DEFINE_SUSPEND_BLOCKER(unknown_wakeup, unknown_wakeups); + +#ifdef CONFIG_SUSPEND_BLOCKER_STATS +static struct suspend_blocker_stats dropped_suspend_blockers; +static ktime_t last_sleep_time_update; +static bool wait_for_wakeup; + +static void suspend_blocker_stat_init(struct suspend_blocker_stats *stat) +{ + stat->count = 0; + stat->wakeup_count = 0; + stat->total_time = ktime_set(0, 0); + stat->prevent_suspend_time = ktime_set(0, 0); + stat->max_time = ktime_set(0, 0); + stat->last_time = ktime_set(0, 0); +} + +static void init_dropped_suspend_blockers(void) +{ + suspend_blocker_stat_init(&dropped_suspend_blockers); +} + +static void suspend_blocker_stat_drop(struct suspend_blocker_stats *stat) +{ + if (!stat->count) + return; + + dropped_suspend_blockers.count += stat->count; + dropped_suspend_blockers.total_time = ktime_add( + dropped_suspend_blockers.total_time, stat->total_time); + dropped_suspend_blockers.prevent_suspend_time = ktime_add( + dropped_suspend_blockers.prevent_suspend_time, + stat->prevent_suspend_time); + dropped_suspend_blockers.max_time = ktime_add( + dropped_suspend_blockers.max_time, stat->max_time); +} + +static void suspend_unblock_stat(struct suspend_blocker *blocker) +{ + struct suspend_blocker_stats *stat = &blocker->stat; + ktime_t duration; + ktime_t now; + + if (!(blocker->flags & SB_ACTIVE)) + return; + + now = ktime_get(); + stat->count++; + duration = ktime_sub(now, stat->last_time); + stat->total_time = ktime_add(stat->total_time, duration); + if (ktime_to_ns(duration) > ktime_to_ns(stat->max_time)) + stat->max_time = duration; + + stat->last_time = ktime_get(); + if (blocker->flags & SB_PREVENTING_SUSPEND) { + duration = ktime_sub(now, last_sleep_time_update); + stat->prevent_suspend_time = ktime_add( + stat->prevent_suspend_time, duration); + blocker->flags &= ~SB_PREVENTING_SUSPEND; + } +} + +static void suspend_block_stat(struct suspend_blocker *blocker) +{ + if (wait_for_wakeup) { + if (debug_mask & DEBUG_WAKEUP) + pr_info("wakeup suspend blocker: %s\n", blocker->name); + + wait_for_wakeup = false; + blocker->stat.wakeup_count++; + } + if (!(blocker->flags & SB_ACTIVE)) + blocker->stat.last_time = ktime_get(); +} + +static void update_sleep_wait_stats(bool done) +{ + struct suspend_blocker *blocker; + ktime_t now, elapsed, add; + + now = ktime_get(); + elapsed = ktime_sub(now, last_sleep_time_update); + list_for_each_entry(blocker, &active_blockers, link) { + struct suspend_blocker_stats *stat = &blocker->stat; + + if (blocker->flags & SB_PREVENTING_SUSPEND) { + add = elapsed; + stat->prevent_suspend_time = ktime_add( + stat->prevent_suspend_time, add); + } + if (done) + blocker->flags &= ~SB_PREVENTING_SUSPEND; + else + blocker->flags |= SB_PREVENTING_SUSPEND; + } + last_sleep_time_update = now; +} + +void about_to_enter_suspend(void) +{ + wait_for_wakeup = true; +} + +#else /* !CONFIG_SUSPEND_BLOCKER_STATS */ + +static inline void init_dropped_suspend_blockers(void) {} +static inline void suspend_blocker_stat_init(struct suspend_blocker_stats *s) {} +static inline void suspend_blocker_stat_drop(struct suspend_blocker_stats *s) {} +static inline void suspend_unblock_stat(struct suspend_blocker *blocker) {} +static inline void suspend_block_stat(struct suspend_blocker *blocker) {} +static inline void update_sleep_wait_stats(bool done) {} +#endif /* !CONFIG_SUSPEND_BLOCKER_STATS */ #define pr_info_time(fmt, args...) \ do { \ @@ -103,7 +216,8 @@ static void suspend_worker(struct work_struct *work) if (current_event_num == entry_event_num) { if (debug_mask & DEBUG_SUSPEND) pr_info("PM: pm_suspend() returned with no event\n"); - queue_work(pm_wq, work); + suspend_block(&unknown_wakeup); + suspend_unblock(&unknown_wakeup); } abort: @@ -127,6 +241,8 @@ void suspend_blocker_register(struct suspend_blocker *blocker) if (debug_mask & DEBUG_SUSPEND_BLOCKER) pr_info("%s: Registering %s\n", __func__, blocker->name); + suspend_blocker_stat_init(&blocker->stat); + blocker->flags = SB_INITIALIZED; INIT_LIST_HEAD(&blocker->link); @@ -164,6 +280,10 @@ void suspend_blocker_unregister(struct suspend_blocker *blocker) return; spin_lock_irqsave(&list_lock, irqflags); + + suspend_unblock_stat(blocker); + suspend_blocker_stat_drop(&blocker->stat); + blocker->flags &= ~SB_INITIALIZED; list_del(&blocker->link); if ((blocker->flags & SB_ACTIVE) && list_empty(&active_blockers)) @@ -193,11 +313,18 @@ void suspend_block(struct suspend_blocker *blocker) if (debug_mask & DEBUG_SUSPEND_BLOCKER) pr_info("%s: %s\n", __func__, blocker->name); + suspend_block_stat(blocker); + blocker->flags |= SB_ACTIVE; list_move(&blocker->link, &active_blockers); current_event_num++; + if (blocker == &main_suspend_blocker) + update_sleep_wait_stats(true); + else if (!suspend_blocker_is_active(&main_suspend_blocker)) + update_sleep_wait_stats(false); + spin_unlock_irqrestore(&list_lock, irqflags); } EXPORT_SYMBOL(suspend_block); @@ -222,13 +349,19 @@ void suspend_unblock(struct suspend_blocker *blocker) if (debug_mask & DEBUG_SUSPEND_BLOCKER) pr_info("%s: %s\n", __func__, blocker->name); + suspend_unblock_stat(blocker); + 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 ((debug_mask & DEBUG_SUSPEND) && blocker == &main_suspend_blocker) - print_active_suspend_blockers(); + if (blocker == &main_suspend_blocker) { + if (debug_mask & DEBUG_SUSPEND) + print_active_suspend_blockers(); + + update_sleep_wait_stats(false); + } spin_unlock_irqrestore(&list_lock, irqflags); } @@ -283,10 +416,69 @@ void __init opportunistic_suspend_init(void) { suspend_blocker_register(&main_suspend_blocker); suspend_block(&main_suspend_blocker); + suspend_blocker_register(&unknown_wakeup); + init_dropped_suspend_blockers(); } static struct dentry *suspend_blocker_stats_dentry; +#ifdef CONFIG_SUSPEND_BLOCKER_STATS +static int print_blocker_stats(struct seq_file *m, const char *name, + struct suspend_blocker_stats *stat, int flags) +{ + int lock_count = stat->count; + ktime_t active_time = ktime_set(0, 0); + ktime_t total_time = stat->total_time; + ktime_t max_time = stat->max_time; + ktime_t prevent_suspend_time = stat->prevent_suspend_time; + + if (flags & SB_ACTIVE) { + ktime_t now, add_time; + + now = ktime_get(); + add_time = ktime_sub(now, stat->last_time); + lock_count++; + active_time = add_time; + total_time = ktime_add(total_time, add_time); + if (flags & SB_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 seq_printf(m, "\"%s\"\t%d\t%d\t%lld\t%lld\t%lld\t%lld\t%lld\n", + name, lock_count, 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(stat->last_time)); +} + +static int suspend_blocker_stats_show(struct seq_file *m, void *unused) +{ + unsigned long irqflags; + struct suspend_blocker *blocker; + + seq_puts(m, "name\tcount\twake_count\tactive_since" + "\ttotal_time\tsleep_time\tmax_time\tlast_change\n"); + + spin_lock_irqsave(&list_lock, irqflags); + list_for_each_entry(blocker, &active_blockers, link) + print_blocker_stats(m, + blocker->name, &blocker->stat, blocker->flags); + + list_for_each_entry(blocker, &inactive_blockers, link) + print_blocker_stats(m, + blocker->name, &blocker->stat, blocker->flags); + + print_blocker_stats(m, "deleted", &dropped_suspend_blockers, 0); + spin_unlock_irqrestore(&list_lock, irqflags); + return 0; +} + +#else + static int suspend_blocker_stats_show(struct seq_file *m, void *unused) { unsigned long irqflags; @@ -302,6 +494,8 @@ static int suspend_blocker_stats_show(struct seq_file *m, void *unused) return 0; } +#endif + static int suspend_blocker_stats_open(struct inode *inode, struct file *file) { return single_open(file, suspend_blocker_stats_show, NULL); diff --git a/kernel/power/power.h b/kernel/power/power.h index 2e9cfd5..e13c975 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -245,3 +245,8 @@ extern void __init opportunistic_suspend_init(void); #else static inline void opportunistic_suspend_init(void) {} #endif +#ifdef CONFIG_SUSPEND_BLOCKER_STATS +void about_to_enter_suspend(void); +#else +static inline void about_to_enter_suspend(void) {} +#endif diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 9eb3876..df694e7 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -158,8 +158,10 @@ static int suspend_enter(suspend_state_t state) error = sysdev_suspend(PMSG_SUSPEND); if (!error) { - if (!suspend_is_blocked() && !suspend_test(TEST_CORE)) + if (!suspend_is_blocked() && !suspend_test(TEST_CORE)) { + about_to_enter_suspend(); error = suspend_ops->enter(state); + } sysdev_resume(); } -- 1.6.5.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] 89+ messages in thread
* [PATCH 6/8] PM: Add suspend blocking work. 2010-05-14 4:11 ` [PATCH 5/8] PM: suspend_block: Add suspend_blocker stats Arve Hjønnevåg @ 2010-05-14 4:11 ` Arve Hjønnevåg [not found] ` <1273810273-3039-7-git-send-email-arve@android.com> 1 sibling, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-14 4:11 UTC (permalink / raw) To: linux-pm, linux-kernel; +Cc: Tejun Heo, Len Brown Allow work to be queued that will block suspend while it is pending or executing. To get the same functionality in the calling code often requires a separate suspend_blocker for pending and executing work, or additional state and locking. This implementation does add additional state and locking, but this can be removed later if we add support for suspend blocking work to the core workqueue code. Signed-off-by: Arve Hjønnevåg <arve@android.com> Reviewed-by: Tejun Heo <tj@kernel.org> Acked-by: Pavel Machek <pavel@ucw.cz> --- include/linux/suspend_blocker.h | 67 +++++++++++++++++++++ kernel/power/opportunistic_suspend.c | 109 ++++++++++++++++++++++++++++++++++ 2 files changed, 176 insertions(+), 0 deletions(-) diff --git a/include/linux/suspend_blocker.h b/include/linux/suspend_blocker.h index 256af15..bb90b45 100755 --- a/include/linux/suspend_blocker.h +++ b/include/linux/suspend_blocker.h @@ -18,6 +18,7 @@ #include <linux/list.h> #include <linux/ktime.h> +#include <linux/workqueue.h> /** * struct suspend_blocker_stats - statistics for a suspend blocker @@ -62,6 +63,38 @@ struct suspend_blocker { #endif }; +/** + * struct suspend_blocking_work - the basic suspend_blocking_work structure + * @work: Standard work struct. + * @suspend_blocker: Suspend blocker. + * @func: Callback. + * @lock: Spinlock protecting pending and running state. + * @active: Number of cpu workqueues where work is pending or + * callback is running. + * + * When suspend blocking work is pending or its callback is running it prevents + * the system from entering opportunistic suspend. + * + * The suspend_blocking_work structure must be initialized by + * suspend_blocking_work_init(). + */ + +struct suspend_blocking_work { + struct work_struct work; +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND + struct suspend_blocker suspend_blocker; + work_func_t func; + spinlock_t lock; + int active; +#endif +}; + +static inline struct suspend_blocking_work *to_suspend_blocking_work( + struct work_struct *work) +{ + return container_of(work, struct suspend_blocking_work, work); +} + #ifdef CONFIG_OPPORTUNISTIC_SUSPEND #define __SUSPEND_BLOCKER_INITIALIZER(blocker_name) \ { .name = #blocker_name, } @@ -78,6 +111,14 @@ extern void suspend_unblock(struct suspend_blocker *blocker); extern bool suspend_blocker_is_active(struct suspend_blocker *blocker); extern bool suspend_is_blocked(void); +void suspend_blocking_work_init(struct suspend_blocking_work *work, + work_func_t func, const char *name); +void suspend_blocking_work_destroy(struct suspend_blocking_work *work); +int queue_suspend_blocking_work(struct workqueue_struct *wq, + struct suspend_blocking_work *work); +int schedule_suspend_blocking_work(struct suspend_blocking_work *work); +int cancel_suspend_blocking_work_sync(struct suspend_blocking_work *work); + #else #define DEFINE_SUSPEND_BLOCKER(blocker, name) \ @@ -94,6 +135,32 @@ static inline bool suspend_blocker_is_active(struct suspend_blocker *bl) return false; } static inline bool suspend_is_blocked(void) { return false; } + +static inline void suspend_blocking_work_init( + struct suspend_blocking_work *work, work_func_t func, const char *name) +{ + INIT_WORK(&work->work, func); +} +static inline void suspend_blocking_work_destroy( + struct suspend_blocking_work *work) +{ + cancel_work_sync(&work->work); +} +static inline int queue_suspend_blocking_work( + struct workqueue_struct *wq, struct suspend_blocking_work *work) +{ + return queue_work(wq, &work->work); +} +static inline int schedule_suspend_blocking_work( + struct suspend_blocking_work *work) +{ + return schedule_work(&work->work); +} +static inline int cancel_suspend_blocking_work_sync( + struct suspend_blocking_work *work) +{ + return cancel_work_sync(&work->work); +} #endif #endif diff --git a/kernel/power/opportunistic_suspend.c b/kernel/power/opportunistic_suspend.c index 3f0153d..63be9ad 100644 --- a/kernel/power/opportunistic_suspend.c +++ b/kernel/power/opportunistic_suspend.c @@ -517,3 +517,112 @@ static int __init suspend_blocker_debugfs_init(void) } postcore_initcall(suspend_blocker_debugfs_init); + +static void suspend_blocking_work_complete(struct suspend_blocking_work *work) +{ + unsigned long flags; + + WARN_ON(!work->active); + spin_lock_irqsave(&work->lock, flags); + if (!--work->active) + suspend_unblock(&work->suspend_blocker); + spin_unlock_irqrestore(&work->lock, flags); +} + +static void suspend_blocking_work_func(struct work_struct *work) +{ + struct suspend_blocking_work *sbwork = to_suspend_blocking_work(work); + + sbwork->func(work); + suspend_blocking_work_complete(sbwork); +} + +/** + * suspend_blocking_work_init - Initialize a suspend-blocking work item. + * @work: Work item to initialize. + * @func: Callback. + * @name: Name for suspend blocker. + * + */ +void suspend_blocking_work_init(struct suspend_blocking_work *work, + work_func_t func, const char *name) +{ + INIT_WORK(&work->work, suspend_blocking_work_func); + suspend_blocker_init(&work->suspend_blocker, name); + work->func = func; + spin_lock_init(&work->lock); + work->active = 0; +} +EXPORT_SYMBOL_GPL(suspend_blocking_work_init); + +/** + * cancel_suspend_blocking_work_sync - Cancel a suspend-blocking work item. + * @work: Work item to handle. + */ +int cancel_suspend_blocking_work_sync(struct suspend_blocking_work *work) +{ + int ret; + + ret = cancel_work_sync(&work->work); + if (ret) + suspend_blocking_work_complete(work); + return ret; +} +EXPORT_SYMBOL_GPL(cancel_suspend_blocking_work_sync); + +/** + * suspend_blocking_work_destroy - Destroy a suspend-blocking work item. + * @work: The work item in question. + * + * If the work was ever queued on more then one workqueue all but the last + * workqueue must be flushed before calling suspend_blocking_work_destroy. + */ +void suspend_blocking_work_destroy(struct suspend_blocking_work *work) +{ + cancel_suspend_blocking_work_sync(work); + WARN_ON(work->active); + suspend_blocker_unregister(&work->suspend_blocker); +} +EXPORT_SYMBOL_GPL(suspend_blocking_work_destroy); + +/** + * queue_suspend_blocking_work - Queue a suspend-blocking work item. + * @wq: Workqueue to queue the work on. + * @work: Work item to queue. + */ +int queue_suspend_blocking_work(struct workqueue_struct *wq, + struct suspend_blocking_work *work) +{ + int ret; + unsigned long flags; + + spin_lock_irqsave(&work->lock, flags); + ret = queue_work(wq, &work->work); + if (ret) { + suspend_block(&work->suspend_blocker); + work->active++; + } + spin_unlock_irqrestore(&work->lock, flags); + return ret; +} +EXPORT_SYMBOL_GPL(queue_suspend_blocking_work); + +/** + * schedule_suspend_blocking_work - Schedule a suspend-blocking work item. + * @work: Work item to schedule. + */ +int schedule_suspend_blocking_work(struct suspend_blocking_work *work) +{ + int ret; + unsigned long flags; + + spin_lock_irqsave(&work->lock, flags); + ret = schedule_work(&work->work); + if (ret) { + suspend_block(&work->suspend_blocker); + work->active++; + } + spin_unlock_irqrestore(&work->lock, flags); + return ret; +} +EXPORT_SYMBOL_GPL(schedule_suspend_blocking_work); -- 1.6.5.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] 89+ messages in thread
[parent not found: <1273810273-3039-7-git-send-email-arve@android.com>]
* [PATCH 7/8] Input: Block suspend while event queue is not empty. [not found] ` <1273810273-3039-7-git-send-email-arve@android.com> @ 2010-05-14 4:11 ` Arve Hjønnevåg 2010-05-14 4:11 ` [PATCH 8/8] power_supply: Block suspend while power supply change notifications are pending Arve Hjønnevåg 0 siblings, 1 reply; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-14 4:11 UTC (permalink / raw) To: linux-pm, linux-kernel Cc: Márton Németh, Jiri Kosina, Dmitry Torokhov, Sven Neumann, Henrik Rydberg, linux-input, Alexey Dobriyan, Tero Saarni, Matthew Garrett Add an ioctl, EVIOCSSUSPENDBLOCK, to enable a suspend_blocker that will block suspend while the event queue is not empty. This 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 | 22 ++++++++++++++++++++++ include/linux/input.h | 3 +++ 2 files changed, 25 insertions(+), 0 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 2ee6c7a..bff2247 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -20,6 +20,7 @@ #include <linux/input.h> #include <linux/major.h> #include <linux/device.h> +#include <linux/suspend.h> #include "input-compat.h" struct evdev { @@ -43,6 +44,8 @@ struct evdev_client { struct fasync_struct *fasync; struct evdev *evdev; struct list_head node; + struct suspend_blocker suspend_blocker; + bool use_suspend_blocker; }; static struct evdev *evdev_table[EVDEV_MINORS]; @@ -55,6 +58,8 @@ static void evdev_pass_event(struct evdev_client *client, * Interrupts are disabled, just acquire the lock */ spin_lock(&client->buffer_lock); + if (client->use_suspend_blocker) + suspend_block(&client->suspend_blocker); client->buffer[client->head++] = *event; client->head &= EVDEV_BUFFER_SIZE - 1; spin_unlock(&client->buffer_lock); @@ -234,6 +239,8 @@ static int evdev_release(struct inode *inode, struct file *file) mutex_unlock(&evdev->mutex); evdev_detach_client(evdev, client); + if (client->use_suspend_blocker) + suspend_blocker_unregister(&client->suspend_blocker); kfree(client); evdev_close_device(evdev); @@ -335,6 +342,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->use_suspend_blocker && client->head == client->tail) + suspend_unblock(&client->suspend_blocker); } spin_unlock_irq(&client->buffer_lock); @@ -585,6 +594,19 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, else return evdev_ungrab(evdev, client); + case EVIOCGSUSPENDBLOCK: + return put_user(client->use_suspend_blocker, ip); + + case EVIOCSSUSPENDBLOCK: + spin_lock_irq(&client->buffer_lock); + if (!client->use_suspend_blocker && p) + suspend_blocker_init(&client->suspend_blocker, "evdev"); + else if (client->use_suspend_blocker && !p) + suspend_blocker_unregister(&client->suspend_blocker); + client->use_suspend_blocker = !!p; + spin_unlock_irq(&client->buffer_lock); + return 0; + default: if (_IOC_TYPE(cmd) != 'E') diff --git a/include/linux/input.h b/include/linux/input.h index 7ed2251..b2d93b4 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -82,6 +82,9 @@ struct input_absinfo { #define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */ +#define EVIOCGSUSPENDBLOCK _IOR('E', 0x91, int) /* get suspend block enable */ +#define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int) /* set suspend block enable */ + /* * Event types */ -- 1.6.5.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] 89+ messages in thread
* [PATCH 8/8] power_supply: Block suspend while power supply change notifications are pending 2010-05-14 4:11 ` [PATCH 7/8] Input: Block suspend while event queue is not empty Arve Hjønnevåg @ 2010-05-14 4:11 ` Arve Hjønnevåg 0 siblings, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-14 4:11 UTC (permalink / raw) To: linux-pm, linux-kernel Cc: Len Brown, Mark Brown, Andres Salomon, Anton Vorontsov, Daniel Mack, David Woodhouse When connecting usb or the charger the device would often go back to sleep before the charge led and screen turned on. Signed-off-by: Arve Hjønnevåg <arve@android.com> --- drivers/power/power_supply_core.c | 9 ++++++--- include/linux/power_supply.h | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c index cce75b4..577a131 100644 --- a/drivers/power/power_supply_core.c +++ b/drivers/power/power_supply_core.c @@ -39,7 +39,7 @@ static int __power_supply_changed_work(struct device *dev, void *data) static void power_supply_changed_work(struct work_struct *work) { struct power_supply *psy = container_of(work, struct power_supply, - changed_work); + changed_work.work); dev_dbg(psy->dev, "%s\n", __func__); @@ -55,7 +55,7 @@ void power_supply_changed(struct power_supply *psy) { dev_dbg(psy->dev, "%s\n", __func__); - schedule_work(&psy->changed_work); + schedule_suspend_blocking_work(&psy->changed_work); } EXPORT_SYMBOL_GPL(power_supply_changed); @@ -155,7 +155,8 @@ int power_supply_register(struct device *parent, struct power_supply *psy) goto dev_create_failed; } - INIT_WORK(&psy->changed_work, power_supply_changed_work); + suspend_blocking_work_init(&psy->changed_work, + power_supply_changed_work, "power-supply"); rc = power_supply_create_attrs(psy); if (rc) @@ -172,6 +173,7 @@ int power_supply_register(struct device *parent, struct power_supply *psy) create_triggers_failed: power_supply_remove_attrs(psy); create_attrs_failed: + suspend_blocking_work_destroy(&psy->changed_work); device_unregister(psy->dev); dev_create_failed: success: @@ -184,6 +186,7 @@ void power_supply_unregister(struct power_supply *psy) flush_scheduled_work(); power_supply_remove_triggers(psy); power_supply_remove_attrs(psy); + suspend_blocking_work_destroy(&psy->changed_work); device_unregister(psy->dev); } EXPORT_SYMBOL_GPL(power_supply_unregister); diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index ebd2b8f..f6412c8 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -14,6 +14,7 @@ #define __LINUX_POWER_SUPPLY_H__ #include <linux/device.h> +#include <linux/suspend.h> #include <linux/workqueue.h> #include <linux/leds.h> @@ -152,7 +153,7 @@ struct power_supply { /* private */ struct device *dev; - struct work_struct changed_work; + struct suspend_blocking_work changed_work; #ifdef CONFIG_LEDS_TRIGGERS struct led_trigger *charging_full_trig; -- 1.6.5.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] 89+ messages in thread
* Re: [PATCH 1/8] PM: Add suspend block api. 2010-05-14 4:11 ` [PATCH 1/8] PM: Add suspend block api Arve Hjønnevåg 2010-05-14 4:11 ` [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space Arve Hjønnevåg @ 2010-05-14 6:13 ` Paul Walmsley 2010-05-14 6:27 ` Paul Walmsley ` (2 subsequent siblings) 4 siblings, 0 replies; 89+ messages in thread From: Paul Walmsley @ 2010-05-14 6:13 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Dmitry Torokhov, Sven Neumann, Jesse Barnes, linux-kernel, Tero Saarni, linux-input, linux-pm, Liam Girdwood, Alexey Dobriyan, Matthew Garrett, Len Brown, Jacob Pan, Daniel Mack, Oleg Nesterov, linux-omap, Linus Walleij, Daniel Walker, Theodore Ts'o, Márton Németh, Brian Swetland [-- Attachment #1: Type: TEXT/PLAIN, Size: 5345 bytes --] Hello, some comments on the kernel-level suspend blocker API. On Thu, 13 May 2010, 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> Another problem with the suspend-block kernel API is that its primary use-case[1] is to work around the brokenness of patch 1's opportunistic suspend governor. The governor is broken because it intentionally ignores timers and the scheduler. To work around problems caused by this decision, suspend-blocks must be spread throughout the kernel (and userspace) to restore the previous behavior of the system. But if patch 1's opportunistic suspend governor were fixed, most of the need for a suspend blockers would disappear. [ This E-mail expands on some earlier comments[2] and is also related to other opportunistic suspend comments[3]. ] The suspend-block patches require already-working code to be patched to keep it working. This is a backwards approach. Instead, broken code should be patched to fix the brokenness. But the former approach is exactly what the suspend block API is intended to do. Patches 7 and 8 in this series are two clear cases. Patch 7 adds an ioctl to the input subsystem that will cause the system to stay running as long as there is an event in the event queue. Patch 8 adds a suspend-block call to the power_supply code that causes the system to stay running as long as power_supply's changed_work workqueue has work to do. Neither of these patches should be needed, since the default expectation of the mainline Linux kernel is that the system should run when there is work to be done. This longstanding expectation should be preserved, not broken and then patched around. But since patch 1 violates that expectation, there is no choice but to add patches 7 and 8 -- and ultimately many more patches -- to get a working system. Once the opportunistic suspend governor in patch 1 is introduced and enabled, the kernel will suspend the system immediately, even if the system has work to do. The only way to prevent that is to add suspend-blocks. Many suspend blocks will be needed throughout the kernel to keep things working. One might think that patches 7 and 8 are the only changes needed to get a working Android-style opportunistic suspend system. It turns out that many more changes are needed. This can be seen by looking at currently shipping Android kernels, such as the current current Android 'msm' kernel tree[4]. Suspend-blocker usage is spread through many drivers and subsystems: [paul@twilight msm]$ fgrep -r wake_lock . | egrep '(^./drivers|^./arch)' | cut -f1 -d: | sort -u ./arch/arm/mach-msm/htc_battery.c ./arch/arm/mach-msm/pm.c ./arch/arm/mach-msm/qdsp5/adsp.c ./arch/arm/mach-msm/qdsp5/audio_out.c ./arch/arm/mach-msm/smd_qmi.c ./arch/arm/mach-msm/smd_rpcrouter.c ./arch/arm/mach-msm/smd_rpcrouter.h ./arch/arm/mach-msm/smd_rpcrouter_servers.c ./arch/arm/mach-msm/smd_tty.c ./drivers/i2c/chips/mt9t013.c ./drivers/input/evdev.c ./drivers/input/misc/gpio_input.c ./drivers/input/misc/gpio_matrix.c ./drivers/mmc/core/core.c ./drivers/net/msm_rmnet.c ./drivers/rtc/alarm.c ./drivers/serial/msm_serial_hs.c ./drivers/usb/function/mass_storage.c ./drivers/usb/gadget/f_mass_storage.c ./drivers/video/msm/mddi.c ./drivers/video/msm/msm_fb.c I guess this is something like what kernel developers should eventually expect to see if suspend blockers are merged. There is a better way to make the system work as expected: these patch 1 shouldn't break general timer and scheduler assumptions. If patch 1's governor is fixed, most of these calls will be unnecessary. The apparent motivation is to prevent "untrusted" userspace processes from preventing the system from entering a low-power state. I agree that this is a problem. But it should be fixed by modifying the specific Linux code that determines when the idle loop is entered and when the next timer wakeup should occur, on a per-process basis. Such targeted changes would ensure that the rest of the kernel would continue to execute as expected. regards, - Paul 1. Arve Hjønnevåg E-mail to the linux-pm mailing list, dated Mon, 3 May 2010 17:09:22 -0700: http://www.spinics.net/lists/linux-pm/msg18432.html 2. Paul Walmsley E-mail to the linux-pm mailing list, dated Wed, 12 May 2010 21:35:30 -0600: http://lkml.org/lkml/2010/5/12/528 3. Paul Walmsley E-mail to the linux-pm mailing list, dated Thu, 13 May 2010 13:01:33 -0600: http://permalink.gmane.org/gmane.linux.power-management.general/18592 4. git://android.git.kernel.org/kernel/msm.git - as of commit c7f8bcecb06b937c45dd0e342450a3218b286b8d, "[ARM] msm: defconfig: Set mmap_min_addr to 32k" 5. http://android.git.kernel.org/?p=kernel/msm.git;a=blob;f=drivers/mmc/core/core.c;h=22f6ddad85c92f34c55035982049bb03b5abfc74;hb=c7f8bcecb06b937c45dd0e342450a3218b286b8d#l721 [-- Attachment #2: Type: text/plain, Size: 0 bytes --] ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 1/8] PM: Add suspend block api. 2010-05-14 4:11 ` [PATCH 1/8] PM: Add suspend block api Arve Hjønnevåg 2010-05-14 4:11 ` [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space Arve Hjønnevåg 2010-05-14 6:13 ` [PATCH 1/8] PM: Add suspend block api Paul Walmsley @ 2010-05-14 6:27 ` Paul Walmsley 2010-05-14 7:14 ` Arve Hjønnevåg 2010-05-18 13:11 ` Pavel Machek [not found] ` <20100518131111.GB1563@ucw.cz> 4 siblings, 1 reply; 89+ messages in thread From: Paul Walmsley @ 2010-05-14 6:27 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Jesse Barnes, linux-kernel, linux-pm, Liam Girdwood, Matthew Garrett, Len Brown, Jacob Pan, Oleg Nesterov, linux-omap, Linus Walleij, Daniel Walker, Theodore Ts'o, Brian Swetland, Mark Brown, Geoff Smith, Tejun Heo, Andrew Morton, Wu Fengguang, Arjan van de Ven [-- Attachment #1: Type: TEXT/PLAIN, Size: 3860 bytes --] Hello, Another comment on the kernel suspend-blocker API. On Thu, 13 May 2010, 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> Looking at the way that suspend-blocks are used in the current Android 'msm' kernel tree[1], they seem likely to cause layering violations, fragile kernel code with userspace dependencies, and code that consumes power unnecessarily. For example, in drivers/mmc/core/core.c:721, in mmc_rescan() [2], we find the following code: /* give userspace some time to react */ wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2); This is a layering violation. The MMC subsystem should have nothing to do with "giving userspace time to react." That is the responsibility of the Linux scheduler. This code is also intrinsically fragile and use-case dependent. What if userspace occasionally needs more than (HZ / 2) to react? If the distributor is lucky enough to catch this before the product ships, then the distributor can patch in a new magic number. But if the device makes it to the consumer, the result is an unstable device that unpredictably suspends. The above code will also waste power. Even if userspace takes less than (HZ / 2) to react, the system will still be prevented from entering a system-wide low power state for the duration of the remaining time. This is in contrast to an approach that uses the idle loop to enter a system-wide low power state. The moment that the system has no further work to do, it can start saving power. The problems with the above example are not isolated: [paul@twilight msm]$ fgrep -r wake_lock_timeout . | egrep '(^./drivers|^./arch)' ./arch/arm/mach-msm/htc_battery.c: wake_lock_timeout(&vbus_wake_lock, HZ / 2); ./arch/arm/mach-msm/smd_tty.c: wake_lock_timeout(&info->wake_lock, HZ / 2); ./arch/arm/mach-msm/smd_qmi.c: wake_lock_timeout(&ctxt->wake_lock, HZ / 2); ./drivers/rtc/alarm.c: wake_lock_timeout(&alarm_wake_lock, 5 * HZ); ./drivers/rtc/alarm.c: wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ); ./drivers/rtc/alarm.c: wake_lock_timeout(&alarm_rtc_wake_lock, 2 * HZ); ./drivers/mmc/core/core.c: wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2); ./drivers/net/msm_rmnet.c: wake_lock_timeout(&p->wake_lock, HZ / 2); ./drivers/video/msm/msm_fb.c: wake_lock_timeout(&msmfb->idle_lock, HZ/4); ./drivers/video/msm/msm_fb.c: wake_lock_timeout(&msmfb->idle_lock, HZ/4); ./drivers/video/msm/msm_fb.c: wake_lock_timeout(&msmfb->idle_lock, HZ); ./drivers/input/evdev.c: wake_lock_timeout(&client->wake_lock, 5 * HZ); ./drivers/serial/msm_serial_hs.c: wake_lock_timeout(&msm_uport->rx.wake_lock, HZ / 2); It is true that the current patch series does not propose the *_timeout() interface. But that raises the question of what it will be replaced with, in situations where the problem can't simply be pushed to userspace, as it is in Arve's evdev patch 7. Some of these cases seem difficult to handle without some sort of timer-based approach. Timer-based approaches are intrinsically problematic for the reasons mentioned above. - Paul 1. git://android.git.kernel.org/kernel/msm.git - as of commit c7f8bcecb06b937c45dd0e342450a3218b286b8d, "[ARM] msm: defconfig: Set mmap_min_addr to 32k" 2. http://android.git.kernel.org/?p=kernel/msm.git;a=blob;f=drivers/mmc/core/core.c;h=22f6ddad85c92f34c55035982049bb03b5abfc74;hb=c7f8bcecb06b937c45dd0e342450a3218b286b8d#l721 [-- Attachment #2: Type: text/plain, Size: 0 bytes --] ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 1/8] PM: Add suspend block api. 2010-05-14 6:27 ` Paul Walmsley @ 2010-05-14 7:14 ` Arve Hjønnevåg 2010-05-18 2:17 ` Paul Walmsley 0 siblings, 1 reply; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-14 7:14 UTC (permalink / raw) To: Paul Walmsley Cc: Jesse Barnes, linux-kernel, linux-pm, Liam Girdwood, Matthew Garrett, Len Brown, Jacob Pan, Oleg Nesterov, linux-omap, Linus Walleij, Daniel Walker, Theodore Ts'o, Brian Swetland, Mark Brown, Geoff Smith, Tejun Heo, Andrew Morton, Wu Fengguang, Arjan van de Ven On Thu, May 13, 2010 at 11:27 PM, Paul Walmsley <paul@pwsan.com> wrote: > > Hello, > > Another comment on the kernel suspend-blocker API. > > On Thu, 13 May 2010, 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> > > Looking at the way that suspend-blocks are used in the current Android > 'msm' kernel tree[1], they seem likely to cause layering violations, > fragile kernel code with userspace dependencies, and code that consumes > power unnecessarily. > > For example, in drivers/mmc/core/core.c:721, in mmc_rescan() [2], we find > the following code: > > /* give userspace some time to react */ > wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2); > > This is a layering violation. The MMC subsystem should have nothing to do > with "giving userspace time to react." That is the responsibility of the > Linux scheduler. > > This code is also intrinsically fragile and use-case dependent. What if > userspace occasionally needs more than (HZ / 2) to react? If the > distributor is lucky enough to catch this before the product ships, then > the distributor can patch in a new magic number. But if the device makes > it to the consumer, the result is an unstable device that unpredictably > suspends. > > The above code will also waste power. Even if userspace takes less than > (HZ / 2) to react, the system will still be prevented from entering a > system-wide low power state for the duration of the remaining time. This > is in contrast to an approach that uses the idle loop to enter a > system-wide low power state. The moment that the system has no further > work to do, it can start saving power. > Yes, preventing suspend for 1/2 second wastes some power, but are you seriously suggesting that it wastes more power then never suspending? Opportunitic suspend does not prevent entering low power modes from idle. -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 1/8] PM: Add suspend block api. 2010-05-14 7:14 ` Arve Hjønnevåg @ 2010-05-18 2:17 ` Paul Walmsley 2010-05-18 3:06 ` Arve Hjønnevåg 0 siblings, 1 reply; 89+ messages in thread From: Paul Walmsley @ 2010-05-18 2:17 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Jesse Barnes, linux-kernel, linux-pm, Liam Girdwood, Matthew Garrett, Len Brown, Jacob Pan, Oleg Nesterov, linux-omap, Linus Walleij, Daniel Walker, Theodore Ts'o, Brian Swetland, Mark Brown, Geoff Smith, Tejun Heo, Andrew Morton, Wu Fengguang, Arjan van de Ven [-- Attachment #1: Type: TEXT/PLAIN, Size: 3446 bytes --] Hello Arve, On Fri, 14 May 2010, Arve Hjønnevåg wrote: > On Thu, May 13, 2010 at 11:27 PM, Paul Walmsley <paul@pwsan.com> wrote: > > > > On Thu, 13 May 2010, 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> > > > > Looking at the way that suspend-blocks are used in the current Android > > 'msm' kernel tree[1], they seem likely to cause layering violations, > > fragile kernel code with userspace dependencies, and code that consumes > > power unnecessarily. > > > > For example, in drivers/mmc/core/core.c:721, in mmc_rescan() [2], we find > > the following code: > > > > /* give userspace some time to react */ > > wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2); > > > > This is a layering violation. The MMC subsystem should have nothing to do > > with "giving userspace time to react." That is the responsibility of the > > Linux scheduler. > > > > This code is also intrinsically fragile and use-case dependent. What if > > userspace occasionally needs more than (HZ / 2) to react? If the > > distributor is lucky enough to catch this before the product ships, then > > the distributor can patch in a new magic number. But if the device makes > > it to the consumer, the result is an unstable device that unpredictably > > suspends. > > > > The above code will also waste power. Even if userspace takes less than > > (HZ / 2) to react, the system will still be prevented from entering a > > system-wide low power state for the duration of the remaining time. This > > is in contrast to an approach that uses the idle loop to enter a > > system-wide low power state. The moment that the system has no further > > work to do, it can start saving power. > > > > Yes, preventing suspend for 1/2 second wastes some power, but are you > seriously suggesting that it wastes more power then never suspending? > Opportunitic suspend does not prevent entering low power modes from > idle. Sorry, my E-mail was unclear. Here is my intended point: The current Android opportunistic suspend governor does not enter full system suspend until all suspend-blocks are released. If the governor were modified to respect the scheduler, then it could enter suspend the moment that the system had no further work to do. So during part of the (HZ / 2) time interval in the above code, the system is running some kernel or userspace code. But after that work is done, an idle-loop-based opportunistic suspend governor could enter idle during the remaining portion of that (HZ / 2) time interval, while the current governor must keep the system out of suspend. Of course, to do this, a different method for freezing processes would be needed; one possible approach is described here[1]; others have proposed similar approaches. regards, - Paul 1. Paragraphs B4A and B4B of Paul Walmsley E-mail to the linux-pm mailing list, dated Mon May 17 18:39:44 PDT 2010: https://lists.linux-foundation.org/pipermail/linux-pm/2010-May/025663.html [-- Attachment #2: Type: text/plain, Size: 0 bytes --] ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 1/8] PM: Add suspend block api. 2010-05-18 2:17 ` Paul Walmsley @ 2010-05-18 3:06 ` Arve Hjønnevåg 2010-05-18 3:34 ` Paul Walmsley 0 siblings, 1 reply; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-18 3:06 UTC (permalink / raw) To: Paul Walmsley Cc: Jesse Barnes, linux-kernel, linux-pm, Liam Girdwood, Matthew Garrett, Len Brown, Jacob Pan, Oleg Nesterov, linux-omap, Linus Walleij, Daniel Walker, Theodore Ts'o, Brian Swetland, Mark Brown, Geoff Smith, Tejun Heo, Andrew Morton, Wu Fengguang, Arjan van de Ven On Mon, May 17, 2010 at 7:17 PM, Paul Walmsley <paul@pwsan.com> wrote: > Hello Arve, > > On Fri, 14 May 2010, Arve Hjønnevåg wrote: > >> On Thu, May 13, 2010 at 11:27 PM, Paul Walmsley <paul@pwsan.com> wrote: >> > >> > On Thu, 13 May 2010, 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> >> > >> > Looking at the way that suspend-blocks are used in the current Android >> > 'msm' kernel tree[1], they seem likely to cause layering violations, >> > fragile kernel code with userspace dependencies, and code that consumes >> > power unnecessarily. >> > >> > For example, in drivers/mmc/core/core.c:721, in mmc_rescan() [2], we find >> > the following code: >> > >> > /* give userspace some time to react */ >> > wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2); >> > >> > This is a layering violation. The MMC subsystem should have nothing to do >> > with "giving userspace time to react." That is the responsibility of the >> > Linux scheduler. >> > >> > This code is also intrinsically fragile and use-case dependent. What if >> > userspace occasionally needs more than (HZ / 2) to react? If the >> > distributor is lucky enough to catch this before the product ships, then >> > the distributor can patch in a new magic number. But if the device makes >> > it to the consumer, the result is an unstable device that unpredictably >> > suspends. >> > >> > The above code will also waste power. Even if userspace takes less than >> > (HZ / 2) to react, the system will still be prevented from entering a >> > system-wide low power state for the duration of the remaining time. This >> > is in contrast to an approach that uses the idle loop to enter a >> > system-wide low power state. The moment that the system has no further >> > work to do, it can start saving power. >> > >> >> Yes, preventing suspend for 1/2 second wastes some power, but are you >> seriously suggesting that it wastes more power then never suspending? >> Opportunitic suspend does not prevent entering low power modes from >> idle. > > Sorry, my E-mail was unclear. Here is my intended point: > > The current Android opportunistic suspend governor does not enter full > system suspend until all suspend-blocks are released. If the governor > were modified to respect the scheduler, then it could enter suspend the > moment that the system had no further work to do. > On the hardware that shipped we enter the same power state from idle and suspend, so the only power savings we get from suspend that we don't get in idle is from not respecting the scheduler and timers. > So during part of the (HZ / 2) time interval in the above code, the system > is running some kernel or userspace code. But after that work is done, an > idle-loop-based opportunistic suspend governor could enter idle during > the remaining portion of that (HZ / 2) time interval, while the current > governor must keep the system out of suspend. > Triggering a full suspend (that disregards normal timers) from idle does not work, since the system may temporarily enter idle while processing the event. > Of course, to do this, a different method for freezing processes would be > needed; one possible approach is described here[1]; others have proposed > similar approaches. > If you freeze processes you need something like a suspend blocker to prevent processes from being frozen. By having a process that never gets frozen you could implement this entirely in user space, but you would have to funnel all wakeup events though this process. > > regards, > > - Paul > > > 1. Paragraphs B4A and B4B of Paul Walmsley E-mail to the linux-pm mailing > list, dated Mon May 17 18:39:44 PDT 2010: > https://lists.linux-foundation.org/pipermail/linux-pm/2010-May/025663.html -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 1/8] PM: Add suspend block api. 2010-05-18 3:06 ` Arve Hjønnevåg @ 2010-05-18 3:34 ` Paul Walmsley 2010-05-18 3:51 ` Arve Hjønnevåg 0 siblings, 1 reply; 89+ messages in thread From: Paul Walmsley @ 2010-05-18 3:34 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Jesse Barnes, linux-kernel, linux-pm, Liam Girdwood, Matthew Garrett, Len Brown, Jacob Pan, Oleg Nesterov, linux-omap, Linus Walleij, Daniel Walker, Theodore Ts'o, Brian Swetland, Mark Brown, Geoff Smith, Tejun Heo, Andrew Morton, Wu Fengguang, Arjan van de Ven [-- Attachment #1: Type: TEXT/PLAIN, Size: 5241 bytes --] Hello Arve, On Mon, 17 May 2010, Arve Hjønnevåg wrote: > On Mon, May 17, 2010 at 7:17 PM, Paul Walmsley <paul@pwsan.com> wrote: > > On Fri, 14 May 2010, Arve Hjønnevåg wrote: > >> On Thu, May 13, 2010 at 11:27 PM, Paul Walmsley <paul@pwsan.com> wrote: > >> > On Thu, 13 May 2010, 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> > >> > > >> > Looking at the way that suspend-blocks are used in the current Android > >> > 'msm' kernel tree[1], they seem likely to cause layering violations, > >> > fragile kernel code with userspace dependencies, and code that consumes > >> > power unnecessarily. > >> > > >> > For example, in drivers/mmc/core/core.c:721, in mmc_rescan() [2], we find > >> > the following code: > >> > > >> > /* give userspace some time to react */ > >> > wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2); > >> > > >> > This is a layering violation. The MMC subsystem should have nothing to do > >> > with "giving userspace time to react." That is the responsibility of the > >> > Linux scheduler. > >> > > >> > This code is also intrinsically fragile and use-case dependent. What if > >> > userspace occasionally needs more than (HZ / 2) to react? If the > >> > distributor is lucky enough to catch this before the product ships, then > >> > the distributor can patch in a new magic number. But if the device makes > >> > it to the consumer, the result is an unstable device that unpredictably > >> > suspends. > >> > > >> > The above code will also waste power. Even if userspace takes less than > >> > (HZ / 2) to react, the system will still be prevented from entering a > >> > system-wide low power state for the duration of the remaining time. This > >> > is in contrast to an approach that uses the idle loop to enter a > >> > system-wide low power state. The moment that the system has no further > >> > work to do, it can start saving power. > >> > > >> > >> Yes, preventing suspend for 1/2 second wastes some power, but are you > >> seriously suggesting that it wastes more power then never suspending? > >> Opportunitic suspend does not prevent entering low power modes from > >> idle. > > > > Sorry, my E-mail was unclear. Here is my intended point: > > > > The current Android opportunistic suspend governor does not enter full > > system suspend until all suspend-blocks are released. If the governor > > were modified to respect the scheduler, then it could enter suspend the > > moment that the system had no further work to do. > > > > On the hardware that shipped we enter the same power state from idle > and suspend, so the only power savings we get from suspend that we > don't get in idle is from not respecting the scheduler and timers. Other people say that their hardware XXX. (This is probably likely for anything that supports ACPI.) > > So during part of the (HZ / 2) time interval in the above code, the system > > is running some kernel or userspace code. But after that work is done, an > > idle-loop-based opportunistic suspend governor could enter idle during > > the remaining portion of that (HZ / 2) time interval, while the current > > governor must keep the system out of suspend. > > > Triggering a full suspend (that disregards normal timers) from idle > does not work, since the system may temporarily enter idle while > processing the event. Could you provide an example? In such a case, how can the kernel guarantee that the system will process the event within (HZ / 2) seconds? > > Of course, to do this, a different method for freezing processes would be > > needed; one possible approach is described here[1]; others have proposed > > similar approaches. > > If you freeze processes you need something like a suspend blocker to > prevent processes from being frozen. (It occurs to me that "frozen" is the wrong terminology to use. Perhaps "paused" would be a better term, along the lines of [1].) The full set of processes does not need to be paused. For example, if "untrusted" processes are run in a cgroup, and only tasks in that cgroup are put into TASK_INTERRUPTIBLE, then "trusted" processes will not be paused. > By having a process that never gets frozen you could implement this > entirely in user space, but you would have to funnel all wakeup events > though this process. The proposal[2] does require a kernel change. No wakeup funnel process would be needed. The proposal is to put processes into TASK_INTERRUPTIBLE, not TASK_STOPPED (unlike most "freezers"). - Paul 1. Paragraph B4B of Paul Walmsley E-mail to the linux-pm mailing list, dated Mon May 17 18:39:44 PDT 2010: https://lists.linux-foundation.org/pipermail/linux-pm/2010-May/025663.html 2. ibid. [-- Attachment #2: Type: text/plain, Size: 0 bytes --] ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 1/8] PM: Add suspend block api. 2010-05-18 3:34 ` Paul Walmsley @ 2010-05-18 3:51 ` Arve Hjønnevåg 2010-05-19 15:55 ` Paul Walmsley 0 siblings, 1 reply; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-18 3:51 UTC (permalink / raw) To: Paul Walmsley Cc: Jesse Barnes, linux-kernel, linux-pm, Liam Girdwood, Matthew Garrett, Len Brown, Jacob Pan, Oleg Nesterov, linux-omap, Linus Walleij, Daniel Walker, Theodore Ts'o, Brian Swetland, Mark Brown, Geoff Smith, Tejun Heo, Andrew Morton, Wu Fengguang, Arjan van de Ven On Mon, May 17, 2010 at 8:34 PM, Paul Walmsley <paul@pwsan.com> wrote: > Hello Arve, > > On Mon, 17 May 2010, Arve Hjønnevåg wrote: > >> On Mon, May 17, 2010 at 7:17 PM, Paul Walmsley <paul@pwsan.com> wrote: >> > On Fri, 14 May 2010, Arve Hjønnevåg wrote: >> >> On Thu, May 13, 2010 at 11:27 PM, Paul Walmsley <paul@pwsan.com> wrote: >> >> > On Thu, 13 May 2010, 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> >> >> > >> >> > Looking at the way that suspend-blocks are used in the current Android >> >> > 'msm' kernel tree[1], they seem likely to cause layering violations, >> >> > fragile kernel code with userspace dependencies, and code that consumes >> >> > power unnecessarily. >> >> > >> >> > For example, in drivers/mmc/core/core.c:721, in mmc_rescan() [2], we find >> >> > the following code: >> >> > >> >> > /* give userspace some time to react */ >> >> > wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2); >> >> > >> >> > This is a layering violation. The MMC subsystem should have nothing to do >> >> > with "giving userspace time to react." That is the responsibility of the >> >> > Linux scheduler. >> >> > >> >> > This code is also intrinsically fragile and use-case dependent. What if >> >> > userspace occasionally needs more than (HZ / 2) to react? If the >> >> > distributor is lucky enough to catch this before the product ships, then >> >> > the distributor can patch in a new magic number. But if the device makes >> >> > it to the consumer, the result is an unstable device that unpredictably >> >> > suspends. >> >> > >> >> > The above code will also waste power. Even if userspace takes less than >> >> > (HZ / 2) to react, the system will still be prevented from entering a >> >> > system-wide low power state for the duration of the remaining time. This >> >> > is in contrast to an approach that uses the idle loop to enter a >> >> > system-wide low power state. The moment that the system has no further >> >> > work to do, it can start saving power. >> >> > >> >> >> >> Yes, preventing suspend for 1/2 second wastes some power, but are you >> >> seriously suggesting that it wastes more power then never suspending? >> >> Opportunitic suspend does not prevent entering low power modes from >> >> idle. >> > >> > Sorry, my E-mail was unclear. Here is my intended point: >> > >> > The current Android opportunistic suspend governor does not enter full >> > system suspend until all suspend-blocks are released. If the governor >> > were modified to respect the scheduler, then it could enter suspend the >> > moment that the system had no further work to do. >> > >> >> On the hardware that shipped we enter the same power state from idle >> and suspend, so the only power savings we get from suspend that we >> don't get in idle is from not respecting the scheduler and timers. > > Other people > say that their hardware XXX. (This is probably likely for anything that > supports ACPI.) > >> > So during part of the (HZ / 2) time interval in the above code, the system >> > is running some kernel or userspace code. But after that work is done, an >> > idle-loop-based opportunistic suspend governor could enter idle during >> > the remaining portion of that (HZ / 2) time interval, while the current >> > governor must keep the system out of suspend. >> > >> Triggering a full suspend (that disregards normal timers) from idle >> does not work, since the system may temporarily enter idle while >> processing the event. > > Could you provide an example? The code takes a pagefault. The system is idle while waiting for the dma to finish. > > In such a case, how can the kernel guarantee that the system will process > the event within (HZ / 2) seconds? > It can't, but in my opinion if the event did not start processing in 1/2 second it was probably not time critical. >> > Of course, to do this, a different method for freezing processes would be >> > needed; one possible approach is described here[1]; others have proposed >> > similar approaches. >> >> If you freeze processes you need something like a suspend blocker to >> prevent processes from being frozen. > > (It occurs to me that "frozen" is the wrong terminology to use. > Perhaps "paused" would be a better term, along the lines of [1].) > > The full set of processes does not need to be paused. For example, if > "untrusted" processes are run in a cgroup, and only tasks in that cgroup > are put into TASK_INTERRUPTIBLE, then "trusted" processes will not be > paused. > We want to freeze trusted processes. >> By having a process that never gets frozen you could implement this >> entirely in user space, but you would have to funnel all wakeup events >> though this process. > > The proposal[2] does require a kernel change. No wakeup funnel process > would be needed. The proposal is to put processes into > TASK_INTERRUPTIBLE, not TASK_STOPPED (unlike most "freezers"). > Why is the method used for pausing the processes relevant? If the process is paused it cannot process the wakeup event. The only way to get the wake event to the process is to funnel it though a process that never is paused. > > - Paul > > > 1. Paragraph B4B of Paul Walmsley E-mail to the linux-pm mailing > list, dated Mon May 17 18:39:44 PDT 2010: > https://lists.linux-foundation.org/pipermail/linux-pm/2010-May/025663.html > > 2. ibid. > > -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 1/8] PM: Add suspend block api. 2010-05-18 3:51 ` Arve Hjønnevåg @ 2010-05-19 15:55 ` Paul Walmsley 2010-05-20 0:35 ` Arve Hjønnevåg 0 siblings, 1 reply; 89+ messages in thread From: Paul Walmsley @ 2010-05-19 15:55 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Jesse Barnes, linux-kernel, linux-pm, Liam Girdwood, Matthew Garrett, Len Brown, Jacob Pan, Oleg Nesterov, linux-omap, Linus Walleij, Daniel Walker, Theodore Ts'o, Brian Swetland, Mark Brown, Geoff Smith, Tejun Heo, Andrew Morton, Wu Fengguang, Arjan van de Ven [-- Attachment #1: Type: TEXT/PLAIN, Size: 6871 bytes --] Hi Arve, On Mon, 17 May 2010, Arve Hjønnevåg wrote: > On Mon, May 17, 2010 at 8:34 PM, Paul Walmsley <paul@pwsan.com> wrote: > > On Mon, 17 May 2010, Arve Hjønnevåg wrote: > >> On Mon, May 17, 2010 at 7:17 PM, Paul Walmsley <paul@pwsan.com> wrote: > >> > On Fri, 14 May 2010, Arve Hjønnevåg wrote: > >> >> On Thu, May 13, 2010 at 11:27 PM, Paul Walmsley <paul@pwsan.com> wrote: > >> >> > On Thu, 13 May 2010, 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> > >> >> > > >> >> > Looking at the way that suspend-blocks are used in the current Android > >> >> > 'msm' kernel tree[1], they seem likely to cause layering violations, > >> >> > fragile kernel code with userspace dependencies, and code that consumes > >> >> > power unnecessarily. > >> >> > > >> >> > For example, in drivers/mmc/core/core.c:721, in mmc_rescan() [2], we find > >> >> > the following code: > >> >> > > >> >> > /* give userspace some time to react */ > >> >> > wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2); > >> >> > > >> >> > This is a layering violation. The MMC subsystem should have nothing to do > >> >> > with "giving userspace time to react." That is the responsibility of the > >> >> > Linux scheduler. > >> >> > > >> >> > This code is also intrinsically fragile and use-case dependent. What if > >> >> > userspace occasionally needs more than (HZ / 2) to react? If the > >> >> > distributor is lucky enough to catch this before the product ships, then > >> >> > the distributor can patch in a new magic number. But if the device makes > >> >> > it to the consumer, the result is an unstable device that unpredictably > >> >> > suspends. > >> >> > > >> >> > The above code will also waste power. Even if userspace takes less than > >> >> > (HZ / 2) to react, the system will still be prevented from entering a > >> >> > system-wide low power state for the duration of the remaining time. This > >> >> > is in contrast to an approach that uses the idle loop to enter a > >> >> > system-wide low power state. The moment that the system has no further > >> >> > work to do, it can start saving power. > >> >> > > >> >> > >> >> Yes, preventing suspend for 1/2 second wastes some power, but are you > >> >> seriously suggesting that it wastes more power then never suspending? > >> >> Opportunitic suspend does not prevent entering low power modes from > >> >> idle. > >> > > >> > Sorry, my E-mail was unclear. Here is my intended point: > >> > > >> > The current Android opportunistic suspend governor does not enter full > >> > system suspend until all suspend-blocks are released. If the governor > >> > were modified to respect the scheduler, then it could enter suspend the > >> > moment that the system had no further work to do. > >> > > >> > >> On the hardware that shipped we enter the same power state from idle > >> and suspend, so the only power savings we get from suspend that we > >> don't get in idle is from not respecting the scheduler and timers. > > > > Other people > > say that their hardware XXX. (This is probably likely for anything that > > supports ACPI.) Heh, looks like this part of my E-mail escaped a little too early. > >> > So during part of the (HZ / 2) time interval in the above code, the system > >> > is running some kernel or userspace code. But after that work is done, an > >> > idle-loop-based opportunistic suspend governor could enter idle during > >> > the remaining portion of that (HZ / 2) time interval, while the current > >> > governor must keep the system out of suspend. > >> > > >> Triggering a full suspend (that disregards normal timers) from idle > >> does not work, since the system may temporarily enter idle while > >> processing the event. > > > > Could you provide an example? > > The code takes a pagefault. The system is idle while waiting for the > dma to finish. OK. > > In such a case, how can the kernel guarantee that the system will process > > the event within (HZ / 2) seconds? > > It can't, but in my opinion if the event did not start processing in > 1/2 second it was probably not time critical. Thanks for the correction regarding the unit of the time interval. To use the pagefault example, wouldn't that be partially dependent on factors outside the control of the task that handles the input event? (e.g., the time needed to page back in, or other code running on the system.) > >> > Of course, to do this, a different method for freezing processes would be > >> > needed; one possible approach is described here[1]; others have proposed > >> > similar approaches. > >> > >> If you freeze processes you need something like a suspend blocker to > >> prevent processes from being frozen. > > > > (It occurs to me that "frozen" is the wrong terminology to use. > > Perhaps "paused" would be a better term, along the lines of [1].) > > > > The full set of processes does not need to be paused. For example, if > > "untrusted" processes are run in a cgroup, and only tasks in that cgroup > > are put into TASK_INTERRUPTIBLE, then "trusted" processes will not be > > paused. > > We want to freeze trusted processes. By "trusted," I mean processes that are run with a suspend block, as in your example to Tony[1]. Isn't it so that Android has processes that either run entirely under suspend-blocks, or which take suspend-blocks at some point in time during their execution? Wouldn't those processes need to be prevented from a force-pause or force-freeze? > >> By having a process that never gets frozen you could implement this > >> entirely in user space, but you would have to funnel all wakeup events > >> though this process. > > > > The proposal[2] does require a kernel change. No wakeup funnel process > > would be needed. The proposal is to put processes into > > TASK_INTERRUPTIBLE, not TASK_STOPPED (unlike most "freezers"). > > > > Why is the method used for pausing the processes relevant? If the > process is paused it cannot process the wakeup event. Tasks in TASK_INTERRUPTIBLE are woken back up when an event arrives, unlike tasks in TASK_STOPPED, which are stopped until a SIGCONT arrives. > The only way to get the wake event to the process is to funnel it though > a process that never is paused. - Paul 1. http://lkml.org/lkml/2010/5/7/420 [-- Attachment #2: Type: text/plain, Size: 0 bytes --] ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 1/8] PM: Add suspend block api. 2010-05-19 15:55 ` Paul Walmsley @ 2010-05-20 0:35 ` Arve Hjønnevåg 0 siblings, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-20 0:35 UTC (permalink / raw) To: Paul Walmsley Cc: Jesse Barnes, linux-kernel, linux-pm, Liam Girdwood, Matthew Garrett, Len Brown, Jacob Pan, Oleg Nesterov, linux-omap, Linus Walleij, Daniel Walker, Theodore Ts'o, Brian Swetland, Mark Brown, Geoff Smith, Tejun Heo, Andrew Morton, Wu Fengguang, Arjan van de Ven On Wed, May 19, 2010 at 8:55 AM, Paul Walmsley <paul@pwsan.com> wrote: > Hi Arve, > > On Mon, 17 May 2010, Arve Hjønnevåg wrote: > >> On Mon, May 17, 2010 at 8:34 PM, Paul Walmsley <paul@pwsan.com> wrote: >> > On Mon, 17 May 2010, Arve Hjønnevåg wrote: >> >> On Mon, May 17, 2010 at 7:17 PM, Paul Walmsley <paul@pwsan.com> wrote: >> >> > On Fri, 14 May 2010, Arve Hjønnevåg wrote: >> >> >> On Thu, May 13, 2010 at 11:27 PM, Paul Walmsley <paul@pwsan.com> wrote: >> >> >> > On Thu, 13 May 2010, 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> >> >> >> > >> >> >> > Looking at the way that suspend-blocks are used in the current Android >> >> >> > 'msm' kernel tree[1], they seem likely to cause layering violations, >> >> >> > fragile kernel code with userspace dependencies, and code that consumes >> >> >> > power unnecessarily. >> >> >> > >> >> >> > For example, in drivers/mmc/core/core.c:721, in mmc_rescan() [2], we find >> >> >> > the following code: >> >> >> > >> >> >> > /* give userspace some time to react */ >> >> >> > wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2); >> >> >> > >> >> >> > This is a layering violation. The MMC subsystem should have nothing to do >> >> >> > with "giving userspace time to react." That is the responsibility of the >> >> >> > Linux scheduler. >> >> >> > >> >> >> > This code is also intrinsically fragile and use-case dependent. What if >> >> >> > userspace occasionally needs more than (HZ / 2) to react? If the >> >> >> > distributor is lucky enough to catch this before the product ships, then >> >> >> > the distributor can patch in a new magic number. But if the device makes >> >> >> > it to the consumer, the result is an unstable device that unpredictably >> >> >> > suspends. >> >> >> > >> >> >> > The above code will also waste power. Even if userspace takes less than >> >> >> > (HZ / 2) to react, the system will still be prevented from entering a >> >> >> > system-wide low power state for the duration of the remaining time. This >> >> >> > is in contrast to an approach that uses the idle loop to enter a >> >> >> > system-wide low power state. The moment that the system has no further >> >> >> > work to do, it can start saving power. >> >> >> > >> >> >> >> >> >> Yes, preventing suspend for 1/2 second wastes some power, but are you >> >> >> seriously suggesting that it wastes more power then never suspending? >> >> >> Opportunitic suspend does not prevent entering low power modes from >> >> >> idle. >> >> > >> >> > Sorry, my E-mail was unclear. Here is my intended point: >> >> > >> >> > The current Android opportunistic suspend governor does not enter full >> >> > system suspend until all suspend-blocks are released. If the governor >> >> > were modified to respect the scheduler, then it could enter suspend the >> >> > moment that the system had no further work to do. >> >> > >> >> >> >> On the hardware that shipped we enter the same power state from idle >> >> and suspend, so the only power savings we get from suspend that we >> >> don't get in idle is from not respecting the scheduler and timers. >> > >> > Other people >> > say that their hardware XXX. (This is probably likely for anything that >> > supports ACPI.) > > Heh, looks like this part of my E-mail escaped a little too early. > >> >> > So during part of the (HZ / 2) time interval in the above code, the system >> >> > is running some kernel or userspace code. But after that work is done, an >> >> > idle-loop-based opportunistic suspend governor could enter idle during >> >> > the remaining portion of that (HZ / 2) time interval, while the current >> >> > governor must keep the system out of suspend. >> >> > >> >> Triggering a full suspend (that disregards normal timers) from idle >> >> does not work, since the system may temporarily enter idle while >> >> processing the event. >> > >> > Could you provide an example? >> >> The code takes a pagefault. The system is idle while waiting for the >> dma to finish. > > OK. > >> > In such a case, how can the kernel guarantee that the system will process >> > the event within (HZ / 2) seconds? >> >> It can't, but in my opinion if the event did not start processing in >> 1/2 second it was probably not time critical. > > Thanks for the correction regarding the unit of the time interval. > > To use the pagefault example, wouldn't that be partially dependent on > factors outside the control of the task that handles the input event? > (e.g., the time needed to page back in, or other code running on the > system.) > Yes (we don't need any timeouts to handle input events though). >> >> > Of course, to do this, a different method for freezing processes would be >> >> > needed; one possible approach is described here[1]; others have proposed >> >> > similar approaches. >> >> >> >> If you freeze processes you need something like a suspend blocker to >> >> prevent processes from being frozen. >> > >> > (It occurs to me that "frozen" is the wrong terminology to use. >> > Perhaps "paused" would be a better term, along the lines of [1].) >> > >> > The full set of processes does not need to be paused. For example, if >> > "untrusted" processes are run in a cgroup, and only tasks in that cgroup >> > are put into TASK_INTERRUPTIBLE, then "trusted" processes will not be >> > paused. >> >> We want to freeze trusted processes. > > By "trusted," I mean processes that are run with a suspend block, as in > your example to Tony[1]. Isn't it so that Android has processes that > either run entirely under suspend-blocks, or which take suspend-blocks at > some point in time during their execution? Wouldn't those processes need > to be prevented from a force-pause or force-freeze? > We don't freeze processes while any suspend blockers are active. >> >> By having a process that never gets frozen you could implement this >> >> entirely in user space, but you would have to funnel all wakeup events >> >> though this process. >> > >> > The proposal[2] does require a kernel change. No wakeup funnel process >> > would be needed. The proposal is to put processes into >> > TASK_INTERRUPTIBLE, not TASK_STOPPED (unlike most "freezers"). >> > >> >> Why is the method used for pausing the processes relevant? If the >> process is paused it cannot process the wakeup event. > > Tasks in TASK_INTERRUPTIBLE are woken back up when an event arrives, So you are not actually preventing them from. A task that wakes up 60 times a second will still drain the battery, unless you happened to pause it while it was active. > unlike tasks in TASK_STOPPED, which are stopped until a SIGCONT arrives. > >> The only way to get the wake event to the process is to funnel it though >> a process that never is paused. > > > - Paul > > 1. http://lkml.org/lkml/2010/5/7/420 > > -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 1/8] PM: Add suspend block api. 2010-05-14 4:11 ` [PATCH 1/8] PM: Add suspend block api Arve Hjønnevåg ` (2 preceding siblings ...) 2010-05-14 6:27 ` Paul Walmsley @ 2010-05-18 13:11 ` Pavel Machek [not found] ` <20100518131111.GB1563@ucw.cz> 4 siblings, 0 replies; 89+ messages in thread From: Pavel Machek @ 2010-05-18 13:11 UTC (permalink / raw) To: Arve Hj??nnev??g Cc: Len Brown, Andi Kleen, linux-doc, linux-kernel, Jesse Barnes, Tejun Heo, Magnus Damm, linux-pm, Wu Fengguang, Andrew Morton On Thu 2010-05-13 21:11:06, 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 Yeah, one file selects behavior of another file, and to read available states for opportunistic, you have to write to file first. I still don't like the 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] 89+ messages in thread
[parent not found: <20100518131111.GB1563@ucw.cz>]
* Re: [PATCH 1/8] PM: Add suspend block api. [not found] ` <20100518131111.GB1563@ucw.cz> @ 2010-05-20 9:11 ` Florian Mickler [not found] ` <20100520111111.333beb73@schatten.dmk.lab> 1 sibling, 0 replies; 89+ messages in thread From: Florian Mickler @ 2010-05-20 9:11 UTC (permalink / raw) To: Pavel Machek Cc: Len Brown, Kleen, Andi, linux-doc, Tejun, Jesse Barnes, linux-kernel, Heo, Magnus Damm, linux-pm, Wu Fengguang, Andrew Morton On Tue, 18 May 2010 15:11:11 +0200 Pavel Machek <pavel@ucw.cz> wrote: > On Thu 2010-05-13 21:11:06, 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 > > Yeah, one file selects behavior of another file, and to read available > states for opportunistic, you have to write to file first. > > I still don't like the interface. > Actually, what would be a better interface? I wonder why it is not like this: /sys/power/state no change, works with and without opportunistic suspend the same. Ignores suspend blockers. Really no change. (From user perspective) /sys/power/opportunistic On / Off While Off the opportunistic suspend is off. While On, the opportunistic suspend is on and if there are no suspend blockers the system goes to suspend. Cheers, Flo ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <20100520111111.333beb73@schatten.dmk.lab>]
* Re: [PATCH 1/8] PM: Add suspend block api. [not found] ` <20100520111111.333beb73@schatten.dmk.lab> @ 2010-05-20 9:26 ` Florian Mickler [not found] ` <20100520112642.74d93d26@schatten.dmk.lab> 1 sibling, 0 replies; 89+ messages in thread From: Florian Mickler @ 2010-05-20 9:26 UTC (permalink / raw) To: Pavel Machek Cc: Len Brown, Kleen, Andi, linux-doc, Tejun, Jesse Barnes, linux-kernel, Heo, Magnus Damm, linux-pm, Wu Fengguang, Andrew Morton On Thu, 20 May 2010 11:11:11 +0200 Florian Mickler <florian@mickler.org> wrote: > On Tue, 18 May 2010 15:11:11 +0200 > Pavel Machek <pavel@ucw.cz> wrote: > > > On Thu 2010-05-13 21:11:06, 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 > > > > Yeah, one file selects behavior of another file, and to read available > > states for opportunistic, you have to write to file first. > > > > I still don't like the interface. > > > > Actually, what would be a better interface? > > I wonder why it is not like this: > > /sys/power/state > no change, works with and without opportunistic suspend the > same. Ignores suspend blockers. Really no change. (From user > perspective) > > /sys/power/opportunistic > On / Off > While Off the opportunistic suspend is off. > While On, the opportunistic suspend is on and if there are no > suspend blockers the system goes to suspend. > I forgot, of course there needs to be another knob to implement the "on" behaviour in the opportunistic mode /sys/power/block_opportunistic_suspend There you have it. One file, one purpose. > Cheers, > Flo ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <20100520112642.74d93d26@schatten.dmk.lab>]
* Re: [PATCH 1/8] PM: Add suspend block api. [not found] ` <20100520112642.74d93d26@schatten.dmk.lab> @ 2010-05-20 22:18 ` Rafael J. Wysocki [not found] ` <201005210018.43576.rjw@sisk.pl> 1 sibling, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-20 22:18 UTC (permalink / raw) To: Florian Mickler Cc: Len Brown, Andi Kleen, linux-doc, Jesse Barnes, linux-kernel, Tejun Heo, Magnus Damm, linux-pm, Wu Fengguang, Andrew Morton On Thursday 20 May 2010, Florian Mickler wrote: > On Thu, 20 May 2010 11:11:11 +0200 > Florian Mickler <florian@mickler.org> wrote: > > > On Tue, 18 May 2010 15:11:11 +0200 > > Pavel Machek <pavel@ucw.cz> wrote: > > > > > On Thu 2010-05-13 21:11:06, 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 > > > > > > Yeah, one file selects behavior of another file, and to read available > > > states for opportunistic, you have to write to file first. > > > > > > I still don't like the interface. > > > > > > > Actually, what would be a better interface? > > > > I wonder why it is not like this: Because I think the "forced" and "opportunistic" suspend "modes" are mutually exclusive in practice and the interface as proposed reflects that quite well. > > /sys/power/state > > no change, works with and without opportunistic suspend the > > same. Ignores suspend blockers. Really no change. (From user > > perspective) > > > > /sys/power/opportunistic > > On / Off > > While Off the opportunistic suspend is off. > > While On, the opportunistic suspend is on and if there are no > > suspend blockers the system goes to suspend. > > > > I forgot, of course there needs to be another knob to implement the > "on" behaviour in the opportunistic mode > > /sys/power/block_opportunistic_suspend > > There you have it. One file, one purpose. That's getting messy IMHO. In addition to that you get a nice race when the user writes "mem" to /sys/power/state and opportunistic suspend happens at the same time. If the latter wins the race, the system will suspend again immediately after being woken up, which probably is not the result you'd like to get. Thanks, Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <201005210018.43576.rjw@sisk.pl>]
* Re: [PATCH 1/8] PM: Add suspend block api. [not found] ` <201005210018.43576.rjw@sisk.pl> @ 2010-05-21 6:04 ` Florian Mickler 2010-05-27 15:41 ` Pavel Machek 1 sibling, 0 replies; 89+ messages in thread From: Florian Mickler @ 2010-05-21 6:04 UTC (permalink / raw) To: Rafael J. Wysocki Cc: linux-doc, Barnes, Andi Kleen, Andrew, Len, linux-pm, Brown, Magnus Damm, Nigel, linux-kernel, Tejun Heo, Morton, Wu Fengguang, Jesse On Fri, 21 May 2010 00:18:43 +0200 "Rafael J. Wysocki" <rjw@sisk.pl> wrote: > > > Actually, what would be a better interface? > > > > > > I wonder why it is not like this: > > Because I think the "forced" and "opportunistic" suspend "modes" are mutually > exclusive in practice and the interface as proposed reflects that quite well. > > > > /sys/power/state > > > no change, works with and without opportunistic suspend the > > > same. Ignores suspend blockers. Really no change. (From user > > > perspective) > > > > > > /sys/power/opportunistic > > > On / Off > > > While Off the opportunistic suspend is off. > > > While On, the opportunistic suspend is on and if there are no > > > suspend blockers the system goes to suspend. > > > > > > > I forgot, of course there needs to be another knob to implement the > > "on" behaviour in the opportunistic mode > > > > /sys/power/block_opportunistic_suspend > > > > There you have it. One file, one purpose. > > That's getting messy IMHO. > > In addition to that you get a nice race when the user writes "mem" > to /sys/power/state and opportunistic suspend happens at the same time. > If the latter wins the race, the system will suspend again immediately after > being woken up, which probably is not the result you'd like to get. But I don't think there is a problem with that. If the system is 'awake' (suspend blocked) and you hit it with forced 'mem', the system _has_ to suspend. as that is what forced "mem" means. And if opportunistic won the race you would _expect_ the machine to suspend again after the wakeup (and this time for good). But perhaps this only makes sense if you can specify different wake-events for opportunistic and forced suspend. This is probably some kind of bikeshed by now. I'm alright with the status quo. For what it's worth (not much): You can add my Reviewed-By. Cheers, Flo ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 1/8] PM: Add suspend block api. [not found] ` <201005210018.43576.rjw@sisk.pl> 2010-05-21 6:04 ` Florian Mickler @ 2010-05-27 15:41 ` Pavel Machek 1 sibling, 0 replies; 89+ messages in thread From: Pavel Machek @ 2010-05-27 15:41 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Len Brown, Andi Kleen, linux-doc, Jesse Barnes, linux-kernel, Florian Mickler, Magnus Damm, Tejun Heo, linux-pm, Wu Fengguang, Andrew Morton Hi! > > > > Yeah, one file selects behavior of another file, and to read available > > > > states for opportunistic, you have to write to file first. > > > > > > > > I still don't like the interface. > > > > > > > > > > Actually, what would be a better interface? > > > > > > I wonder why it is not like this: > > Because I think the "forced" and "opportunistic" suspend "modes" are mutually > exclusive in practice and the interface as proposed reflects that quite well. Why should they be? Forced disk while opportunistic mem is active makes a lot of sense. If code can't support it now, just return -EINVAL, but please don't cripple the interface just because of that. > > > /sys/power/state > > > no change, works with and without opportunistic suspend the > > > same. Ignores suspend blockers. Really no change. (From user > > > perspective) > > > > > > /sys/power/opportunistic > > > On / Off > > > While Off the opportunistic suspend is off. > > > While On, the opportunistic suspend is on and if there are no > > > suspend blockers the system goes to suspend. > > > > > > > I forgot, of course there needs to be another knob to implement the > > "on" behaviour in the opportunistic mode > > > > /sys/power/block_opportunistic_suspend > > > > There you have it. One file, one purpose. > > That's getting messy IMHO. > > In addition to that you get a nice race when the user writes "mem" > to /sys/power/state and opportunistic suspend happens at the same > time. It should not opportunistically suspend when it has work to do (like entering forced suspend). 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] 89+ messages in thread
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] <1273810273-3039-1-git-send-email-arve@android.com> 2010-05-14 4:11 ` [PATCH 1/8] PM: Add suspend block api Arve Hjønnevåg @ 2010-05-14 21:08 ` Rafael J. Wysocki 2010-05-16 19:42 ` Rafael J. Wysocki ` (2 subsequent siblings) 4 siblings, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-14 21:08 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett On Friday 14 May 2010, Arve Hjønnevåg wrote: > This patch series adds a suspend-block api that provides the same > functionality as the android wakelock api. This version has some > changes from, or requested by, Rafael. The most notable changes are: > - DEFINE_SUSPEND_BLOCKER and suspend_blocker_register have been added > for statically allocated suspend blockers. > - suspend_blocker_destroy is now called suspend_blocker_unregister > - The user space mandatory _INIT ioctl has been replaced with an > optional _SET_NAME ioctl. > > I kept the ack and reviewed by tags on two of the patches even though > there were a few cosmetic changes. Thanks for the patches, I think they are in a pretty good shape now. That said, I'd like the changelogs to be a bit more descriptive, at least for patch [1/8]. I think it should explain (in a few words) what the purpose of the feature is and what problems it solves that generally a combination of runtime PM and cpuidle is not suitable for in your opinion. IOW, why you think we need that feature. The changelog of patch [2/8] appears to be outdated, that needs to be fixed. Also, it would be nice to explain in the changelog what the interface is needed for (in terms of the problems that it helps to handle). 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] 89+ messages in thread
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] <1273810273-3039-1-git-send-email-arve@android.com> 2010-05-14 4:11 ` [PATCH 1/8] PM: Add suspend block api Arve Hjønnevåg 2010-05-14 21:08 ` [PATCH 0/8] Suspend block api (version 7) Rafael J. Wysocki @ 2010-05-16 19:42 ` Rafael J. Wysocki [not found] ` <201005162142.39343.rjw@sisk.pl> [not found] ` <201005142308.48386.rjw@sisk.pl> 4 siblings, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-16 19:42 UTC (permalink / raw) To: Arve Hjønnevåg; +Cc: Brian Swetland, linux-pm, linux-kernel On Friday 14 May 2010, Arve Hjønnevåg wrote: > This patch series adds a suspend-block api that provides the same > functionality as the android wakelock api. This version has some > changes from, or requested by, Rafael. The most notable changes are: > - DEFINE_SUSPEND_BLOCKER and suspend_blocker_register have been added > for statically allocated suspend blockers. > - suspend_blocker_destroy is now called suspend_blocker_unregister > - The user space mandatory _INIT ioctl has been replaced with an > optional _SET_NAME ioctl. > > I kept the ack and reviewed by tags on two of the patches even though > there were a few cosmetic changes. I have one more comment, sorry for that. Namely, if /sys/power/policy is set to "opportunistic" and "mem" is written into /sys/power/state and there are no suspend blockers present except for the main blocker (and the blockers used only for statistics), the system won't be able to go out of an infinit suspend-resume loop (or at least it seems so from reading the code). I think we should prevent that from happening somehow. 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] 89+ messages in thread
[parent not found: <201005162142.39343.rjw@sisk.pl>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <201005162142.39343.rjw@sisk.pl> @ 2010-05-17 4:16 ` Arve Hjønnevåg [not found] ` <AANLkTinP68yHYfVCW-urCrRbeSb0Mlz8JsvAs-FKoUPZ@mail.gmail.com> 1 sibling, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-17 4:16 UTC (permalink / raw) To: Rafael J. Wysocki; +Cc: Brian Swetland, linux-pm, linux-kernel 2010/5/16 Rafael J. Wysocki <rjw@sisk.pl>: > On Friday 14 May 2010, Arve Hjønnevåg wrote: >> This patch series adds a suspend-block api that provides the same >> functionality as the android wakelock api. This version has some >> changes from, or requested by, Rafael. The most notable changes are: >> - DEFINE_SUSPEND_BLOCKER and suspend_blocker_register have been added >> for statically allocated suspend blockers. >> - suspend_blocker_destroy is now called suspend_blocker_unregister >> - The user space mandatory _INIT ioctl has been replaced with an >> optional _SET_NAME ioctl. >> >> I kept the ack and reviewed by tags on two of the patches even though >> there were a few cosmetic changes. > > I have one more comment, sorry for that. > > Namely, if /sys/power/policy is set to "opportunistic" and "mem" is written > into /sys/power/state and there are no suspend blockers present except for > the main blocker (and the blockers used only for statistics), the system won't > be able to go out of an infinit suspend-resume loop (or at least it seems > so from reading the code). > > I think we should prevent that from happening somehow. > It should get out of that loop as soon as someone blocks suspend. If someone is constantly aborting suspend without using a suspend blocker it will be very inefficient, but it should still work. -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <AANLkTinP68yHYfVCW-urCrRbeSb0Mlz8JsvAs-FKoUPZ@mail.gmail.com>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <AANLkTinP68yHYfVCW-urCrRbeSb0Mlz8JsvAs-FKoUPZ@mail.gmail.com> @ 2010-05-17 20:40 ` Rafael J. Wysocki [not found] ` <201005172240.35742.rjw@sisk.pl> 1 sibling, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-17 20:40 UTC (permalink / raw) To: Arve Hjønnevåg; +Cc: Brian Swetland, linux-pm, linux-kernel On Monday 17 May 2010, Arve Hjønnevåg wrote: > 2010/5/16 Rafael J. Wysocki <rjw@sisk.pl>: > > On Friday 14 May 2010, Arve Hjønnevåg wrote: > >> This patch series adds a suspend-block api that provides the same > >> functionality as the android wakelock api. This version has some > >> changes from, or requested by, Rafael. The most notable changes are: > >> - DEFINE_SUSPEND_BLOCKER and suspend_blocker_register have been added > >> for statically allocated suspend blockers. > >> - suspend_blocker_destroy is now called suspend_blocker_unregister > >> - The user space mandatory _INIT ioctl has been replaced with an > >> optional _SET_NAME ioctl. > >> > >> I kept the ack and reviewed by tags on two of the patches even though > >> there were a few cosmetic changes. > > > > I have one more comment, sorry for that. > > > > Namely, if /sys/power/policy is set to "opportunistic" and "mem" is written > > into /sys/power/state and there are no suspend blockers present except for > > the main blocker (and the blockers used only for statistics), the system won't > > be able to go out of an infinit suspend-resume loop (or at least it seems > > so from reading the code). > > > > I think we should prevent that from happening somehow. > > > > It should get out of that loop as soon as someone blocks suspend. If > someone is constantly aborting suspend without using a suspend blocker > it will be very inefficient, but it should still work. Well, the scenario I have in mind is the following. Someone wants to check the feature and simply writes "opportunistic" to /sys/power/policy and "mem" to /sys/power/state without any drivers or apps that use suspend blockers. How in that case is the system supposed to break out of the suspend-resume loop resulting from this? I don't see right now, because the main blocker is inactive, there are no other blockers that can be activated and it is next to impossible to write to /sys/power/state again. Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <201005172240.35742.rjw@sisk.pl>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <201005172240.35742.rjw@sisk.pl> @ 2010-05-17 20:51 ` Brian Swetland [not found] ` <AANLkTim2b8cKnzPgN7m5zImb0hVDfqVjRidKNVoYi1yO@mail.gmail.com> 1 sibling, 0 replies; 89+ messages in thread From: Brian Swetland @ 2010-05-17 20:51 UTC (permalink / raw) To: Rafael J. Wysocki; +Cc: linux-pm, linux-kernel On Mon, May 17, 2010 at 1:40 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > On Monday 17 May 2010, Arve Hjønnevåg wrote: >> >> It should get out of that loop as soon as someone blocks suspend. If >> someone is constantly aborting suspend without using a suspend blocker >> it will be very inefficient, but it should still work. > > Well, the scenario I have in mind is the following. Someone wants to check > the feature and simply writes "opportunistic" to /sys/power/policy and "mem" to > /sys/power/state without any drivers or apps that use suspend blockers. > > How in that case is the system supposed to break out of the suspend-resume loop > resulting from this? I don't see right now, because the main blocker is > inactive, there are no other blockers that can be activated and it is next to > impossible to write to /sys/power/state again. I guess we could set a flag when a suspend blocker is registered and refuse to enter opportunistic mode if no blockers have ever been registered. It does seem like extra effort to go through to handle a "don't do that" type scenario (entering into opportunistic suspend without anything that will prevent it). Brian _______________________________________________ linux-pm mailing list linux-pm@lists.linux-foundation.org https://lists.linux-foundation.org/mailman/listinfo/linux-pm ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <AANLkTim2b8cKnzPgN7m5zImb0hVDfqVjRidKNVoYi1yO@mail.gmail.com>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <AANLkTim2b8cKnzPgN7m5zImb0hVDfqVjRidKNVoYi1yO@mail.gmail.com> @ 2010-05-17 21:44 ` Rafael J. Wysocki [not found] ` <201005172344.46222.rjw@sisk.pl> 1 sibling, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-17 21:44 UTC (permalink / raw) To: Brian Swetland; +Cc: linux-pm, linux-kernel On Monday 17 May 2010, Brian Swetland wrote: > On Mon, May 17, 2010 at 1:40 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > > On Monday 17 May 2010, Arve Hjønnevåg wrote: > >> > >> It should get out of that loop as soon as someone blocks suspend. If > >> someone is constantly aborting suspend without using a suspend blocker > >> it will be very inefficient, but it should still work. > > > > Well, the scenario I have in mind is the following. Someone wants to check > > the feature and simply writes "opportunistic" to /sys/power/policy and "mem" to > > /sys/power/state without any drivers or apps that use suspend blockers. > > > > How in that case is the system supposed to break out of the suspend-resume loop > > resulting from this? I don't see right now, because the main blocker is > > inactive, there are no other blockers that can be activated and it is next to > > impossible to write to /sys/power/state again. > > I guess we could set a flag when a suspend blocker is registered and > refuse to enter opportunistic mode if no blockers have ever been > registered. > > It does seem like extra effort to go through to handle a "don't do > that" type scenario (entering into opportunistic suspend without > anything that will prevent it). I agree, but I think it's necessary. We shouldn't add interfaces that hurt users if not used with care. 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] 89+ messages in thread
[parent not found: <201005172344.46222.rjw@sisk.pl>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <201005172344.46222.rjw@sisk.pl> @ 2010-05-17 23:32 ` Arve Hjønnevåg [not found] ` <AANLkTikENyp0UOKP2NzwjKye1EiZitdE0o4k1Z4ygCsT@mail.gmail.com> 1 sibling, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-17 23:32 UTC (permalink / raw) To: Rafael J. Wysocki; +Cc: Brian Swetland, linux-pm, linux-kernel On Mon, May 17, 2010 at 2:44 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > On Monday 17 May 2010, Brian Swetland wrote: >> On Mon, May 17, 2010 at 1:40 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: >> > On Monday 17 May 2010, Arve Hjønnevåg wrote: >> >> >> >> It should get out of that loop as soon as someone blocks suspend. If >> >> someone is constantly aborting suspend without using a suspend blocker >> >> it will be very inefficient, but it should still work. >> > >> > Well, the scenario I have in mind is the following. Someone wants to check >> > the feature and simply writes "opportunistic" to /sys/power/policy and "mem" to >> > /sys/power/state without any drivers or apps that use suspend blockers. >> > >> > How in that case is the system supposed to break out of the suspend-resume loop >> > resulting from this? I don't see right now, because the main blocker is >> > inactive, there are no other blockers that can be activated and it is next to >> > impossible to write to /sys/power/state again. >> >> I guess we could set a flag when a suspend blocker is registered and >> refuse to enter opportunistic mode if no blockers have ever been >> registered. >> >> It does seem like extra effort to go through to handle a "don't do >> that" type scenario (entering into opportunistic suspend without >> anything that will prevent it). > > I agree, but I think it's necessary. We shouldn't add interfaces that hurt > users if not used with care. > I'm not sure this can be "fixed". The user asked that the system to suspend whenever possible, which is what it is doing. I don't think disabling opportunistic suspend if no suspend blockers have been registered will work. As soon as we register a suspend blocker we are back in the same situation. -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <AANLkTikENyp0UOKP2NzwjKye1EiZitdE0o4k1Z4ygCsT@mail.gmail.com>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <AANLkTikENyp0UOKP2NzwjKye1EiZitdE0o4k1Z4ygCsT@mail.gmail.com> @ 2010-05-18 19:38 ` Rafael J. Wysocki [not found] ` <201005182138.04610.rjw@sisk.pl> 1 sibling, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-18 19:38 UTC (permalink / raw) To: Arve Hjønnevåg; +Cc: Brian Swetland, linux-pm, linux-kernel On Tuesday 18 May 2010, Arve Hjønnevåg wrote: > On Mon, May 17, 2010 at 2:44 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > > On Monday 17 May 2010, Brian Swetland wrote: > >> On Mon, May 17, 2010 at 1:40 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > >> > On Monday 17 May 2010, Arve Hjønnevåg wrote: > >> >> > >> >> It should get out of that loop as soon as someone blocks suspend. If > >> >> someone is constantly aborting suspend without using a suspend blocker > >> >> it will be very inefficient, but it should still work. > >> > > >> > Well, the scenario I have in mind is the following. Someone wants to check > >> > the feature and simply writes "opportunistic" to /sys/power/policy and "mem" to > >> > /sys/power/state without any drivers or apps that use suspend blockers. > >> > > >> > How in that case is the system supposed to break out of the suspend-resume loop > >> > resulting from this? I don't see right now, because the main blocker is > >> > inactive, there are no other blockers that can be activated and it is next to > >> > impossible to write to /sys/power/state again. > >> > >> I guess we could set a flag when a suspend blocker is registered and > >> refuse to enter opportunistic mode if no blockers have ever been > >> registered. > >> > >> It does seem like extra effort to go through to handle a "don't do > >> that" type scenario (entering into opportunistic suspend without > >> anything that will prevent it). > > > > I agree, but I think it's necessary. We shouldn't add interfaces that hurt > > users if not used with care. > > > > I'm not sure this can be "fixed". Yes, it can, but perhaps a workaround would be sufficient (see below). > The user asked that the system to suspend whenever possible, which is what it > is doing. I don't think disabling opportunistic suspend if no suspend > blockers have been registered will work. As soon as we register a suspend > blocker we are back in the same situation. Not really, because the new suspend blocker is not added by the _framework_ _itself_. Now, to make it more "user-friendly", we can simply use queue_delayed_work() with a reasonable delay instead of queue_work() to queue the suspend work (the delay may be configurable via sysfs). Thanks, Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <201005182138.04610.rjw@sisk.pl>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <201005182138.04610.rjw@sisk.pl> @ 2010-05-18 20:35 ` Arve Hjønnevåg [not found] ` <AANLkTileYiu6pL4eX3lpvpYLuu76A8auZp4xrcDX94BQ@mail.gmail.com> 1 sibling, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-18 20:35 UTC (permalink / raw) To: Rafael J. Wysocki; +Cc: Brian Swetland, linux-pm, linux-kernel 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: >> On Mon, May 17, 2010 at 2:44 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: >> > On Monday 17 May 2010, Brian Swetland wrote: >> >> On Mon, May 17, 2010 at 1:40 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: >> >> > On Monday 17 May 2010, Arve Hjønnevåg wrote: >> >> >> >> >> >> It should get out of that loop as soon as someone blocks suspend. If >> >> >> someone is constantly aborting suspend without using a suspend blocker >> >> >> it will be very inefficient, but it should still work. >> >> > >> >> > Well, the scenario I have in mind is the following. Someone wants to check >> >> > the feature and simply writes "opportunistic" to /sys/power/policy and "mem" to >> >> > /sys/power/state without any drivers or apps that use suspend blockers. >> >> > >> >> > How in that case is the system supposed to break out of the suspend-resume loop >> >> > resulting from this? I don't see right now, because the main blocker is >> >> > inactive, there are no other blockers that can be activated and it is next to >> >> > impossible to write to /sys/power/state again. >> >> >> >> I guess we could set a flag when a suspend blocker is registered and >> >> refuse to enter opportunistic mode if no blockers have ever been >> >> registered. >> >> >> >> It does seem like extra effort to go through to handle a "don't do >> >> that" type scenario (entering into opportunistic suspend without >> >> anything that will prevent it). >> > >> > I agree, but I think it's necessary. We shouldn't add interfaces that hurt >> > users if not used with care. >> > >> >> I'm not sure this can be "fixed". > > Yes, it can, but perhaps a workaround would be sufficient (see below). > >> The user asked that the system to suspend whenever possible, which is what it >> is doing. I don't think disabling opportunistic suspend if no suspend >> blockers have been registered will work. As soon as we register a suspend >> blocker we are back in the same situation. > > Not really, because the new suspend blocker is not added by the _framework_ _itself_. > I'm not sure what you mean by this. If we add a workaround that is disabled when the first suspend blocker is registered, then we cannot add any suspend blockers without disabling the workaround (for instance the power supply framework patch later in this patch set). > Now, to make it more "user-friendly", we can simply use > queue_delayed_work() with a reasonable delay instead of queue_work() to queue > the suspend work (the delay may be configurable via sysfs). > I can add a delay (and the timeout support code does add a delay as an optimization) to the unknown wakeup case, but this does not fix the problem of a user turning on opportunistic suspend with a user space framework that does not use suspend blockers. If the kernel uses suspend blockers to make sure the wakeup event makes it to user space, but user space does not block suspend, then the system will suspend before the event is processed. -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <AANLkTileYiu6pL4eX3lpvpYLuu76A8auZp4xrcDX94BQ@mail.gmail.com>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <AANLkTileYiu6pL4eX3lpvpYLuu76A8auZp4xrcDX94BQ@mail.gmail.com> @ 2010-05-18 21:14 ` Rafael J. Wysocki [not found] ` <201005182314.08761.rjw@sisk.pl> 1 sibling, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-18 21:14 UTC (permalink / raw) To: Arve Hjønnevåg; +Cc: Brian Swetland, linux-pm, linux-kernel On Tuesday 18 May 2010, Arve Hjønnevåg wrote: > 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: > >> On Mon, May 17, 2010 at 2:44 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > >> > On Monday 17 May 2010, Brian Swetland wrote: > >> >> On Mon, May 17, 2010 at 1:40 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > >> >> > On Monday 17 May 2010, Arve Hjønnevåg wrote: > >> >> >> ... > > > Now, to make it more "user-friendly", we can simply use > > queue_delayed_work() with a reasonable delay instead of queue_work() to queue > > the suspend work (the delay may be configurable via sysfs). > > > > I can add a delay (and the timeout support code does add a delay as an > optimization) to the unknown wakeup case, but this does not fix the > problem of a user turning on opportunistic suspend with a user space > framework that does not use suspend blockers. If the kernel uses > suspend blockers to make sure the wakeup event makes it to user space, > but user space does not block suspend, then the system will suspend > before the event is processed. But the user can still manually write to /sys/power/state. :-) Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <201005182314.08761.rjw@sisk.pl>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <201005182314.08761.rjw@sisk.pl> @ 2010-05-18 22:21 ` Arve Hjønnevåg [not found] ` <AANLkTikm69OKbRUvqiqGh4KRMn7u166tyt4kx0-bjR3Z@mail.gmail.com> 1 sibling, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-18 22:21 UTC (permalink / raw) To: Rafael J. Wysocki; +Cc: Brian Swetland, linux-pm, linux-kernel 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: >> > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: >> >> On Mon, May 17, 2010 at 2:44 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: >> >> > On Monday 17 May 2010, Brian Swetland wrote: >> >> >> On Mon, May 17, 2010 at 1:40 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: >> >> >> > On Monday 17 May 2010, Arve Hjønnevåg wrote: >> >> >> >> > ... >> >> > Now, to make it more "user-friendly", we can simply use >> > queue_delayed_work() with a reasonable delay instead of queue_work() to queue >> > the suspend work (the delay may be configurable via sysfs). >> > >> >> I can add a delay (and the timeout support code does add a delay as an >> optimization) to the unknown wakeup case, but this does not fix the >> problem of a user turning on opportunistic suspend with a user space >> framework that does not use suspend blockers. If the kernel uses >> suspend blockers to make sure the wakeup event makes it to user space, >> but user space does not block suspend, then the system will suspend >> before the event is processed. > > But the user can still manually write to /sys/power/state. :-) > Does adding or removing a delay change this? It seems in only changes how quickly the user can finish that write. I'm not convinced adding a configurable delay here is necessary. Once the driver that enabled the wakeup event has been updated to block suspend until this event gets to user space, then this delay will never be triggered. The kernel cannot tell the difference between a user enabling opportunistic suspend but not wanting it and opportunistic suspend aware user space code deciding that this wakeup event should be ignored. -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <AANLkTikm69OKbRUvqiqGh4KRMn7u166tyt4kx0-bjR3Z@mail.gmail.com>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <AANLkTikm69OKbRUvqiqGh4KRMn7u166tyt4kx0-bjR3Z@mail.gmail.com> @ 2010-05-18 22:56 ` Rafael J. Wysocki [not found] ` <201005190056.36804.rjw@sisk.pl> 1 sibling, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-18 22:56 UTC (permalink / raw) To: Arve Hjønnevåg; +Cc: Brian Swetland, linux-pm, linux-kernel On Wednesday 19 May 2010, Arve Hjønnevåg wrote: > 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: > >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > >> > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: > >> >> On Mon, May 17, 2010 at 2:44 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > >> >> > On Monday 17 May 2010, Brian Swetland wrote: > >> >> >> On Mon, May 17, 2010 at 1:40 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > >> >> >> > On Monday 17 May 2010, Arve Hjønnevåg wrote: > >> >> >> >> > > ... > >> > >> > Now, to make it more "user-friendly", we can simply use > >> > queue_delayed_work() with a reasonable delay instead of queue_work() to queue > >> > the suspend work (the delay may be configurable via sysfs). > >> > > >> > >> I can add a delay (and the timeout support code does add a delay as an > >> optimization) to the unknown wakeup case, but this does not fix the > >> problem of a user turning on opportunistic suspend with a user space > >> framework that does not use suspend blockers. If the kernel uses > >> suspend blockers to make sure the wakeup event makes it to user space, > >> but user space does not block suspend, then the system will suspend > >> before the event is processed. > > > > But the user can still manually write to /sys/power/state. :-) > > > > Does adding or removing a delay change this? It seems in only changes > how quickly the user can finish that write. Yes, but that should allow the user to avoid rebooting the system if he does the "wrong thing". > I'm not convinced adding a configurable delay here is necessary. No, it's not, but it would be useful in some cases IMO. Pretty much the same way your debug features are useful. > Once the driver that enabled the wakeup event has been updated to block > suspend until this event gets to user space, then this delay will > never be triggered. The kernel cannot tell the difference between a > user enabling opportunistic suspend but not wanting it and > opportunistic suspend aware user space code deciding that this wakeup > event should be ignored. The point is, if there's a delay, it may be too aggressive for some users and too conservative for some other users, so it makes sense to provide a means to adjust it to the user's needs. Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <201005190056.36804.rjw@sisk.pl>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <201005190056.36804.rjw@sisk.pl> @ 2010-05-18 23:06 ` Arve Hjønnevåg [not found] ` <AANLkTikc9MmR_r1NkdCwDaPD4kJa9l9KUwcWAxilcs3l@mail.gmail.com> 1 sibling, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-18 23:06 UTC (permalink / raw) To: Rafael J. Wysocki; +Cc: Brian Swetland, linux-pm, linux-kernel 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > On Wednesday 19 May 2010, Arve Hjønnevåg wrote: >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: >> > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: >> >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: >> >> > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: >> >> >> On Mon, May 17, 2010 at 2:44 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: >> >> >> > On Monday 17 May 2010, Brian Swetland wrote: >> >> >> >> On Mon, May 17, 2010 at 1:40 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: >> >> >> >> > On Monday 17 May 2010, Arve Hjønnevåg wrote: >> >> >> >> >> >> > ... >> >> >> >> > Now, to make it more "user-friendly", we can simply use >> >> > queue_delayed_work() with a reasonable delay instead of queue_work() to queue >> >> > the suspend work (the delay may be configurable via sysfs). >> >> > >> >> >> >> I can add a delay (and the timeout support code does add a delay as an >> >> optimization) to the unknown wakeup case, but this does not fix the >> >> problem of a user turning on opportunistic suspend with a user space >> >> framework that does not use suspend blockers. If the kernel uses >> >> suspend blockers to make sure the wakeup event makes it to user space, >> >> but user space does not block suspend, then the system will suspend >> >> before the event is processed. >> > >> > But the user can still manually write to /sys/power/state. :-) >> > >> >> Does adding or removing a delay change this? It seems in only changes >> how quickly the user can finish that write. > > Yes, but that should allow the user to avoid rebooting the system if he does > the "wrong thing". > >> I'm not convinced adding a configurable delay here is necessary. > > No, it's not, but it would be useful in some cases IMO. Pretty much the same > way your debug features are useful. > >> Once the driver that enabled the wakeup event has been updated to block >> suspend until this event gets to user space, then this delay will >> never be triggered. The kernel cannot tell the difference between a >> user enabling opportunistic suspend but not wanting it and >> opportunistic suspend aware user space code deciding that this wakeup >> event should be ignored. > > The point is, if there's a delay, it may be too aggressive for some users and > too conservative for some other users, so it makes sense to provide a means > to adjust it to the user's needs. > My point is that the delay will not be used at all if the driver uses a suspend blocker (like it should). Why add a configuration option for opportunistic suspend that only works when the driver does not support opportunistic suspend. -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <AANLkTikc9MmR_r1NkdCwDaPD4kJa9l9KUwcWAxilcs3l@mail.gmail.com>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <AANLkTikc9MmR_r1NkdCwDaPD4kJa9l9KUwcWAxilcs3l@mail.gmail.com> @ 2010-05-19 20:40 ` Rafael J. Wysocki 0 siblings, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-19 20:40 UTC (permalink / raw) To: Arve Hjønnevåg; +Cc: Brian Swetland, linux-pm, linux-kernel On Wednesday 19 May 2010, Arve Hjønnevåg wrote: > 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > > On Wednesday 19 May 2010, Arve Hjønnevåg wrote: > >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > >> > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: > >> >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > >> >> > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: > >> >> >> On Mon, May 17, 2010 at 2:44 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > >> >> >> > On Monday 17 May 2010, Brian Swetland wrote: > >> >> >> >> On Mon, May 17, 2010 at 1:40 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > >> >> >> >> > On Monday 17 May 2010, Arve Hjønnevåg wrote: > >> >> >> >> >> > >> > ... > >> >> > >> >> > Now, to make it more "user-friendly", we can simply use > >> >> > queue_delayed_work() with a reasonable delay instead of queue_work() to queue > >> >> > the suspend work (the delay may be configurable via sysfs). > >> >> > > >> >> > >> >> I can add a delay (and the timeout support code does add a delay as an > >> >> optimization) to the unknown wakeup case, but this does not fix the > >> >> problem of a user turning on opportunistic suspend with a user space > >> >> framework that does not use suspend blockers. If the kernel uses > >> >> suspend blockers to make sure the wakeup event makes it to user space, > >> >> but user space does not block suspend, then the system will suspend > >> >> before the event is processed. > >> > > >> > But the user can still manually write to /sys/power/state. :-) > >> > > >> > >> Does adding or removing a delay change this? It seems in only changes > >> how quickly the user can finish that write. > > > > Yes, but that should allow the user to avoid rebooting the system if he does > > the "wrong thing". > > > >> I'm not convinced adding a configurable delay here is necessary. > > > > No, it's not, but it would be useful in some cases IMO. Pretty much the same > > way your debug features are useful. > > > >> Once the driver that enabled the wakeup event has been updated to block > >> suspend until this event gets to user space, then this delay will > >> never be triggered. The kernel cannot tell the difference between a > >> user enabling opportunistic suspend but not wanting it and > >> opportunistic suspend aware user space code deciding that this wakeup > >> event should be ignored. > > > > The point is, if there's a delay, it may be too aggressive for some users and > > too conservative for some other users, so it makes sense to provide a means > > to adjust it to the user's needs. > > > > My point is that the delay will not be used at all if the driver uses > a suspend blocker (like it should). Why add a configuration option for > opportunistic suspend that only works when the driver does not support > opportunistic suspend. Because on many systems there are no such drivers (yet, at least). Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <201005142308.48386.rjw@sisk.pl>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <201005142308.48386.rjw@sisk.pl> @ 2010-05-17 4:50 ` Arve Hjønnevåg [not found] ` <AANLkTilX0uhqrJtUSOC4smdH1M8V-h14J7YtRG4PPxOQ@mail.gmail.com> 1 sibling, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-17 4:50 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett 2010/5/14 Rafael J. Wysocki <rjw@sisk.pl>: > On Friday 14 May 2010, Arve Hjønnevåg wrote: >> This patch series adds a suspend-block api that provides the same >> functionality as the android wakelock api. This version has some >> changes from, or requested by, Rafael. The most notable changes are: >> - DEFINE_SUSPEND_BLOCKER and suspend_blocker_register have been added >> for statically allocated suspend blockers. >> - suspend_blocker_destroy is now called suspend_blocker_unregister >> - The user space mandatory _INIT ioctl has been replaced with an >> optional _SET_NAME ioctl. >> >> I kept the ack and reviewed by tags on two of the patches even though >> there were a few cosmetic changes. > > Thanks for the patches, I think they are in a pretty good shape now. > > That said, I'd like the changelogs to be a bit more descriptive, at least for > patch [1/8]. I think it should explain (in a few words) what the purpose of > the feature is and what problems it solves that generally a combination of > runtime PM and cpuidle is not suitable for in your opinion. IOW, why you > think we need that feature. > How about: PM: Add opportunistic suspend support. Adds a suspend block api that drivers can use to block opportunistic suspend. This is needed to avoid losing wakeup events that occur right after suspend is initiated. 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. Opportunistic suspend is most useful on systems that cannot enter their lowest power state from idle, but it is also useful on systems that enter the same power state from idle and suspend. Periodic timers can cause a significant power drain on these systems, and suspend will stop most of this. Opportunistic suspend can also reduce the harm caused by apps that never go idle. > The changelog of patch [2/8] appears to be outdated, that needs to be fixed. > Also, it would be nice to explain in the changelog what the interface is needed > for (in terms of the problems that it helps to handle). > How about: PM: suspend_block: Add driver to access suspend blockers from user-space Add a misc device, "suspend_blocker", that allows user-space processes to block auto suspend. Opening this device creates a suspend_blocker. ioctls are provided to name this suspend_blocker, and to block and unblock suspend. To delete the suspend_blocker, close the device. For example, when select or poll indicates that input event are available, this interface can be used to block suspend before reading those event. This allows the input driver to release its suspend blocker as soon as the event queue is empty. -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <AANLkTilX0uhqrJtUSOC4smdH1M8V-h14J7YtRG4PPxOQ@mail.gmail.com>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <AANLkTilX0uhqrJtUSOC4smdH1M8V-h14J7YtRG4PPxOQ@mail.gmail.com> @ 2010-05-17 19:01 ` Mike Snitzer 2010-05-17 21:42 ` Rafael J. Wysocki [not found] ` <201005172342.52660.rjw@sisk.pl> 2 siblings, 0 replies; 89+ messages in thread From: Mike Snitzer @ 2010-05-17 19:01 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett 2010/5/17 Arve Hjønnevåg <arve@android.com>: > 2010/5/14 Rafael J. Wysocki <rjw@sisk.pl>: >> On Friday 14 May 2010, Arve Hjønnevåg wrote: >>> This patch series adds a suspend-block api that provides the same >>> functionality as the android wakelock api. This version has some >>> changes from, or requested by, Rafael. The most notable changes are: >>> - DEFINE_SUSPEND_BLOCKER and suspend_blocker_register have been added >>> for statically allocated suspend blockers. >>> - suspend_blocker_destroy is now called suspend_blocker_unregister >>> - The user space mandatory _INIT ioctl has been replaced with an >>> optional _SET_NAME ioctl. >>> >>> I kept the ack and reviewed by tags on two of the patches even though >>> there were a few cosmetic changes. >> >> Thanks for the patches, I think they are in a pretty good shape now. >> >> That said, I'd like the changelogs to be a bit more descriptive, at least for >> patch [1/8]. I think it should explain (in a few words) what the purpose of >> the feature is and what problems it solves that generally a combination of >> runtime PM and cpuidle is not suitable for in your opinion. IOW, why you >> think we need that feature. >> > > How about: > > PM: Add opportunistic suspend support. > > Adds a suspend block api In the future I think it'd be ideal if you were to always use "suspend blocker" (rather than "suspend block"). This work has nothing to do with the block layer yet by the subject I thought it somehow did. ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <AANLkTilX0uhqrJtUSOC4smdH1M8V-h14J7YtRG4PPxOQ@mail.gmail.com> 2010-05-17 19:01 ` Mike Snitzer @ 2010-05-17 21:42 ` Rafael J. Wysocki [not found] ` <201005172342.52660.rjw@sisk.pl> 2 siblings, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-17 21:42 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett On Monday 17 May 2010, Arve Hjønnevåg wrote: > 2010/5/14 Rafael J. Wysocki <rjw@sisk.pl>: > > On Friday 14 May 2010, Arve Hjønnevåg wrote: > >> This patch series adds a suspend-block api that provides the same > >> functionality as the android wakelock api. This version has some > >> changes from, or requested by, Rafael. The most notable changes are: > >> - DEFINE_SUSPEND_BLOCKER and suspend_blocker_register have been added > >> for statically allocated suspend blockers. > >> - suspend_blocker_destroy is now called suspend_blocker_unregister > >> - The user space mandatory _INIT ioctl has been replaced with an > >> optional _SET_NAME ioctl. > >> > >> I kept the ack and reviewed by tags on two of the patches even though > >> there were a few cosmetic changes. > > > > Thanks for the patches, I think they are in a pretty good shape now. > > > > That said, I'd like the changelogs to be a bit more descriptive, at least for > > patch [1/8]. I think it should explain (in a few words) what the purpose of > > the feature is and what problems it solves that generally a combination of > > runtime PM and cpuidle is not suitable for in your opinion. IOW, why you > > think we need that feature. > > > > How about: > > PM: Add opportunistic suspend support. "PM: Opportunistic suspend support" would be sufficient IMO. Now, I'd start with the motivation. Like "Power management features present in the current mainline kernel are insufficient to get maximum possible energy savings on some platforms, such as Android, because ..." (here go explanations why this is the case in your opinion). Next, "To allow Android and similar platforms to save more energy than they currently can save using the mainline kernel, introduce a mechanism by which the system is automatically suspended (i.e. put into a system-wide sleep state) whenever it's not doing useful work, called opportunistic suspend". "For this purpose introduce the suspend blockers framework allowing the kernel's power management subsystem to decide when it is desirable to suspend the system (i.e. when useful work is not being done). Add an API that ..." > Adds a suspend block api that drivers can use to block opportunistic > suspend. This is needed to avoid losing wakeup events that occur > right after suspend is initiated. > > 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. > > Opportunistic suspend is most useful on systems that cannot enter their > lowest power state from idle, but it is also useful on systems that enter > the same power state from idle and suspend. Periodic timers can cause > a significant power drain on these systems, and suspend will stop most > of this. Opportunistic suspend can also reduce the harm caused by apps > that never go idle. > > > The changelog of patch [2/8] appears to be outdated, that needs to be fixed. > > Also, it would be nice to explain in the changelog what the interface is needed > > for (in terms of the problems that it helps to handle). > > > > How about: > > PM: suspend_block: Add driver to access suspend blockers from user-space > > Add a misc device, "suspend_blocker", that allows user-space processes > to block auto suspend. "automatic suspend" would be better IMO. > Opening this device creates a suspend_blocker. "suspend blocker that can be used by the opener to prevent automatic suspend from occuring. There are ioctls provided for blocking and unblocking suspend and for giving the suspend blocker a meaningful name. Closing the device special file causes the suspend blocker to be destroyed." > ioctls are provided to name this suspend_blocker, and to block and unblock > suspend. To delete the suspend_blocker, close the device. > > For example, when select or poll indicates that input event are available, this > interface can be used to block suspend before reading those event. This allows > the input driver to release its suspend blocker as soon as the event queue is > empty. I think you should explain in more detail how suspend blockers used by user space make that possible. Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <201005172342.52660.rjw@sisk.pl>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <201005172342.52660.rjw@sisk.pl> @ 2010-05-17 22:16 ` Kevin Hilman 2010-05-18 0:52 ` Arve Hjønnevåg 1 sibling, 0 replies; 89+ messages in thread From: Kevin Hilman @ 2010-05-17 22:16 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett "Rafael J. Wysocki" <rjw@sisk.pl> writes: > On Monday 17 May 2010, Arve Hjønnevåg wrote: >> >> How about: >> >> PM: Add opportunistic suspend support. > > "PM: Opportunistic suspend support" would be sufficient IMO. > > Now, I'd start with the motivation. Like "Power management features present > in the current mainline kernel are insufficient to get maximum possible energy > savings on some platforms, such as Android, because ..." (here go explanations > why this is the case in your opinion). Yes, this will be helpful. > Next, "To allow Android and similar platforms to save more energy than they > currently can save using the mainline kernel, introduce a mechanism by which > the system is automatically suspended (i.e. put into a system-wide sleep state) > whenever it's not doing useful work, called opportunistic suspend". Hopefully, a definition of "useful" will be given here, including by what standards on-going work is determined not to be useful. Kevin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <201005172342.52660.rjw@sisk.pl> 2010-05-17 22:16 ` Kevin Hilman @ 2010-05-18 0:52 ` Arve Hjønnevåg 2010-05-18 16:18 ` Kevin Hilman ` (4 more replies) 1 sibling, 5 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-18 0:52 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett 2010/5/17 Rafael J. Wysocki <rjw@sisk.pl>: > On Monday 17 May 2010, Arve Hjønnevåg wrote: >> 2010/5/14 Rafael J. Wysocki <rjw@sisk.pl>: >> > On Friday 14 May 2010, Arve Hjønnevåg wrote: >> >> This patch series adds a suspend-block api that provides the same >> >> functionality as the android wakelock api. This version has some >> >> changes from, or requested by, Rafael. The most notable changes are: >> >> - DEFINE_SUSPEND_BLOCKER and suspend_blocker_register have been added >> >> for statically allocated suspend blockers. >> >> - suspend_blocker_destroy is now called suspend_blocker_unregister >> >> - The user space mandatory _INIT ioctl has been replaced with an >> >> optional _SET_NAME ioctl. >> >> >> >> I kept the ack and reviewed by tags on two of the patches even though >> >> there were a few cosmetic changes. >> > >> > Thanks for the patches, I think they are in a pretty good shape now. >> > >> > That said, I'd like the changelogs to be a bit more descriptive, at least for >> > patch [1/8]. I think it should explain (in a few words) what the purpose of >> > the feature is and what problems it solves that generally a combination of >> > runtime PM and cpuidle is not suitable for in your opinion. IOW, why you >> > think we need that feature. >> > >> >> How about: >> >> PM: Add opportunistic suspend support. > > "PM: Opportunistic suspend support" would be sufficient IMO. > > Now, I'd start with the motivation. Like "Power management features present > in the current mainline kernel are insufficient to get maximum possible energy > savings on some platforms, such as Android, because ..." (here go explanations > why this is the case in your opinion). > > Next, "To allow Android and similar platforms to save more energy than they > currently can save using the mainline kernel, introduce a mechanism by which > the system is automatically suspended (i.e. put into a system-wide sleep state) > whenever it's not doing useful work, called opportunistic suspend". > > "For this purpose introduce the suspend blockers framework allowing the > kernel's power management subsystem to decide when it is desirable to suspend > the system (i.e. when useful work is not being done). Add an API that ..." > PM: Opportunistic suspend support. Power management features present in the current mainline kernel are insufficient to get maximum possible energy savings on some platforms, such as Android, because low power states can only safely be entered from idle. Suspend, in its current form, cannot be used, since wakeup events that occur right after initiating suspend will not be processed until another possibly unrelated event wake up the system again. On some systems idle combined with runtime PM can enter the same power state as suspend, but periodic wakeups increase the average power consumption. Suspending the system also reduces the harm caused by apps that never go idle. On other systems suspend can enter a much lower power state than idle. To allow Android and similar platforms to save more energy than they currently can save using the mainline kernel, we introduce a mechanism by which the system is automatically suspended (i.e. put into a system-wide sleep state) whenever it's not doing useful work, called opportunistic suspend. For this purpose introduce the suspend blockers framework allowing the kernel's power management subsystem to decide when it is desirable to suspend the system (i.e. when useful work is not being done). Add an API that that drivers can use to block opportunistic suspend. This is needed to avoid losing wakeup events that occur right after suspend is initiated. Adds /sys/power/policy that selects the behavior 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. >> Adds a suspend block api that drivers can use to block opportunistic >> suspend. This is needed to avoid losing wakeup events that occur >> right after suspend is initiated. >> >> 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. >> >> Opportunistic suspend is most useful on systems that cannot enter their >> lowest power state from idle, but it is also useful on systems that enter >> the same power state from idle and suspend. Periodic timers can cause >> a significant power drain on these systems, and suspend will stop most >> of this. Opportunistic suspend can also reduce the harm caused by apps >> that never go idle. >> >> > The changelog of patch [2/8] appears to be outdated, that needs to be fixed. >> > Also, it would be nice to explain in the changelog what the interface is needed >> > for (in terms of the problems that it helps to handle). >> > >> >> How about: >> >> PM: suspend_block: Add driver to access suspend blockers from user-space >> >> Add a misc device, "suspend_blocker", that allows user-space processes >> to block auto suspend. > > "automatic suspend" would be better IMO. > >> Opening this device creates a suspend_blocker. > > "suspend blocker that can be used by the opener to prevent automatic suspend > from occuring. There are ioctls provided for blocking and unblocking suspend > and for giving the suspend blocker a meaningful name. Closing the device > special file causes the suspend blocker to be destroyed." > >> ioctls are provided to name this suspend_blocker, and to block and unblock >> suspend. To delete the suspend_blocker, close the device. >> >> For example, when select or poll indicates that input event are available, this >> interface can be used to block suspend before reading those event. This allows >> the input driver to release its suspend blocker as soon as the event queue is >> empty. > > I think you should explain in more detail how suspend blockers used by user > space make that possible. > PM: suspend_block: Add driver to access suspend blockers from user-space Add a misc device, "suspend_blocker", that allows user-space processes to block automatic suspend. Opening this device creates a suspend blocker that can be used by the opener to prevent automatic suspend from occurring. There are ioctls provided for blocking and unblocking suspend and for giving the suspend blocker a meaningful name. Closing the device special file causes the suspend blocker to be destroyed. For example, when select or poll indicates that input event are available, this interface can be used by user space to block suspend before it reads those events. This allows the input driver to release its suspend blocker as soon as the event queue is empty. If user space could not use a suspend blocker here the input driver would need to delay the release of its suspend blocker until it knows (or assumes) that user space has finished processing the events. By careful use of suspend blockers in drivers and user space system code, one can arrange for the system to stay awake for extremely short periods of time in reaction to events, rapidly returning to a fully suspended state. -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 0/8] Suspend block api (version 7) 2010-05-18 0:52 ` Arve Hjønnevåg @ 2010-05-18 16:18 ` Kevin Hilman 2010-05-18 16:18 ` Kevin Hilman ` (3 subsequent siblings) 4 siblings, 0 replies; 89+ messages in thread From: Kevin Hilman @ 2010-05-18 16:18 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett Arve Hjønnevåg <arve@android.com> writes: > > PM: Opportunistic suspend support. > > Power management features present in the current mainline kernel are > insufficient to get maximum possible energy savings on some platforms, > such as Android, because low power states can only safely be entered > from idle. Suspend, in its current form, cannot be used, since wakeup > events that occur right after initiating suspend will not be processed > until another possibly unrelated event wake up the system again. I think the problems with wakeups in the current suspend path need to be described in more detail. In particular, why check_wakeup_irqs() is not enough etc. > On some systems idle combined with runtime PM can enter the same power > state as suspend, but periodic wakeups increase the average power > consumption. Suspending the system also reduces the harm caused by > apps that never go idle. On other systems suspend can enter a much > lower power state than idle. > > To allow Android and similar platforms to save more energy than they > currently can save using the mainline kernel, we introduce a mechanism > by which the system is automatically suspended (i.e. put into a > system-wide sleep state) whenever it's not doing useful work, called > opportunistic suspend. A definition of "useful work" here would provide clarity and would also help clarify by what criteria other on-going work is determined to be not useful. Kevin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 0/8] Suspend block api (version 7) 2010-05-18 0:52 ` Arve Hjønnevåg 2010-05-18 16:18 ` Kevin Hilman @ 2010-05-18 16:18 ` Kevin Hilman 2010-05-18 19:13 ` Rafael J. Wysocki ` (2 subsequent siblings) 4 siblings, 0 replies; 89+ messages in thread From: Kevin Hilman @ 2010-05-18 16:18 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett Arve Hjønnevåg <arve@android.com> writes: > > PM: Opportunistic suspend support. > > Power management features present in the current mainline kernel are > insufficient to get maximum possible energy savings on some platforms, > such as Android, because low power states can only safely be entered > from idle. Suspend, in its current form, cannot be used, since wakeup > events that occur right after initiating suspend will not be processed > until another possibly unrelated event wake up the system again. I think the problems with wakeups in the current suspend path need to be described in more detail. In particular, why check_wakeup_irqs() is not enough etc. > On some systems idle combined with runtime PM can enter the same power > state as suspend, but periodic wakeups increase the average power > consumption. Suspending the system also reduces the harm caused by > apps that never go idle. On other systems suspend can enter a much > lower power state than idle. > > To allow Android and similar platforms to save more energy than they > currently can save using the mainline kernel, we introduce a mechanism > by which the system is automatically suspended (i.e. put into a > system-wide sleep state) whenever it's not doing useful work, called > opportunistic suspend. A definition of "useful work" here would provide clarity and would also help clarify by what criteria other on-going work is determined to be not useful. Kevin ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 0/8] Suspend block api (version 7) 2010-05-18 0:52 ` Arve Hjønnevåg 2010-05-18 16:18 ` Kevin Hilman 2010-05-18 16:18 ` Kevin Hilman @ 2010-05-18 19:13 ` Rafael J. Wysocki [not found] ` <201005182113.10448.rjw@sisk.pl> [not found] ` <87tyq5qj3v.fsf@deeprootsystems.com> 4 siblings, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-18 19:13 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett On Tuesday 18 May 2010, Arve Hjønnevåg wrote: > 2010/5/17 Rafael J. Wysocki <rjw@sisk.pl>: > > On Monday 17 May 2010, Arve Hjønnevåg wrote: > >> 2010/5/14 Rafael J. Wysocki <rjw@sisk.pl>: > >> > On Friday 14 May 2010, Arve Hjønnevåg wrote: > >> >> This patch series adds a suspend-block api that provides the same > >> >> functionality as the android wakelock api. This version has some > >> >> changes from, or requested by, Rafael. The most notable changes are: > >> >> - DEFINE_SUSPEND_BLOCKER and suspend_blocker_register have been added > >> >> for statically allocated suspend blockers. > >> >> - suspend_blocker_destroy is now called suspend_blocker_unregister > >> >> - The user space mandatory _INIT ioctl has been replaced with an > >> >> optional _SET_NAME ioctl. > >> >> > >> >> I kept the ack and reviewed by tags on two of the patches even though > >> >> there were a few cosmetic changes. > >> > > >> > Thanks for the patches, I think they are in a pretty good shape now. > >> > > >> > That said, I'd like the changelogs to be a bit more descriptive, at least for > >> > patch [1/8]. I think it should explain (in a few words) what the purpose of > >> > the feature is and what problems it solves that generally a combination of > >> > runtime PM and cpuidle is not suitable for in your opinion. IOW, why you > >> > think we need that feature. > >> > > >> > >> How about: > >> > >> PM: Add opportunistic suspend support. > > > > "PM: Opportunistic suspend support" would be sufficient IMO. > > > > Now, I'd start with the motivation. Like "Power management features present > > in the current mainline kernel are insufficient to get maximum possible energy > > savings on some platforms, such as Android, because ..." (here go explanations > > why this is the case in your opinion). > > > > Next, "To allow Android and similar platforms to save more energy than they > > currently can save using the mainline kernel, introduce a mechanism by which > > the system is automatically suspended (i.e. put into a system-wide sleep state) > > whenever it's not doing useful work, called opportunistic suspend". > > > > "For this purpose introduce the suspend blockers framework allowing the > > kernel's power management subsystem to decide when it is desirable to suspend > > the system (i.e. when useful work is not being done). Add an API that ..." > > > > PM: Opportunistic suspend support. > > Power management features present in the current mainline kernel are > insufficient to get maximum possible energy savings on some platforms, > such as Android, because low power states can only safely be entered > from idle. Do you mean CPU low-power states or system low-power states here? I'd add more details here, because it may not be completely clear to the (interested) reader why entering these states only from idle affects the possibility to achieve maximum energy savings. I _guess_ you mean that using idle is not sufficient, because there are so many wakeups on the systems in question that more savings are still possible. Is that correct? > Suspend, in its current form, cannot be used, since wakeup > events that occur right after initiating suspend will not be processed > until another possibly unrelated event wake up the system again. I think the word "cannot" is too strong here. I'd say "not suitable" instead and I'd say what kind of wakeup events I meant more precisely (there are events that wake up a CPU from idle and events that wake up the system from suspend). > On some systems idle combined with runtime PM can enter the same power > state as suspend, but periodic wakeups increase the average power > consumption. Suspending the system also reduces the harm caused by > apps that never go idle. On other systems suspend can enter a much > lower power state than idle. > > To allow Android and similar platforms to save more energy than they > currently can save using the mainline kernel, we introduce a mechanism Just "introduce" without "we" works too. > by which the system is automatically suspended (i.e. put into a > system-wide sleep state) whenever it's not doing useful work, called > opportunistic suspend. I think we can address the Kevin's comment about "useful" and say "whenever it's only doing work that can be done later without noticeable effect on functionality". > For this purpose introduce the suspend blockers framework allowing the > kernel's power management subsystem to decide when it is desirable to > suspend the system (i.e. when useful work is not being done). Add an Perhaps remove the part in parens entirely. > API that that drivers can use to block opportunistic suspend. This is > needed to avoid losing wakeup events that occur right after suspend is > initiated. > > Adds /sys/power/policy that selects the behavior 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. ... > PM: suspend_block: Add driver to access suspend blockers from user-space > > Add a misc device, "suspend_blocker", that allows user-space processes > to block automatic suspend. > > Opening this device creates a suspend blocker that can be used by the > opener to prevent automatic suspend from occurring. There are ioctls > provided for blocking and unblocking suspend and for giving the > suspend blocker a meaningful name. Closing the device special file > causes the suspend blocker to be destroyed. > > For example, when select or poll indicates that input event are > available, this interface can be used by user space to block suspend > before it reads those events. This allows the input driver to release > its suspend blocker as soon as the event queue is empty. If user space > could not use a suspend blocker here the input driver would need to > delay the release of its suspend blocker until it knows (or assumes) > that user space has finished processing the events. > > By careful use of suspend blockers in drivers and user space system > code, one can arrange for the system to stay awake for extremely short > periods of time in reaction to events, rapidly returning to a fully > suspended state. That's fine by me. Thanks, Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <201005182113.10448.rjw@sisk.pl>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <201005182113.10448.rjw@sisk.pl> @ 2010-05-18 20:47 ` Arve Hjønnevåg [not found] ` <AANLkTinPC94F1wj-CEb3vvSo7__u625DsZxErlmTymEw@mail.gmail.com> 1 sibling, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-18 20:47 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: >> 2010/5/17 Rafael J. Wysocki <rjw@sisk.pl>: >> > On Monday 17 May 2010, Arve Hjønnevåg wrote: >> >> 2010/5/14 Rafael J. Wysocki <rjw@sisk.pl>: >> >> > On Friday 14 May 2010, Arve Hjønnevåg wrote: >> >> >> This patch series adds a suspend-block api that provides the same >> >> >> functionality as the android wakelock api. This version has some >> >> >> changes from, or requested by, Rafael. The most notable changes are: >> >> >> - DEFINE_SUSPEND_BLOCKER and suspend_blocker_register have been added >> >> >> for statically allocated suspend blockers. >> >> >> - suspend_blocker_destroy is now called suspend_blocker_unregister >> >> >> - The user space mandatory _INIT ioctl has been replaced with an >> >> >> optional _SET_NAME ioctl. >> >> >> >> >> >> I kept the ack and reviewed by tags on two of the patches even though >> >> >> there were a few cosmetic changes. >> >> > >> >> > Thanks for the patches, I think they are in a pretty good shape now. >> >> > >> >> > That said, I'd like the changelogs to be a bit more descriptive, at least for >> >> > patch [1/8]. I think it should explain (in a few words) what the purpose of >> >> > the feature is and what problems it solves that generally a combination of >> >> > runtime PM and cpuidle is not suitable for in your opinion. IOW, why you >> >> > think we need that feature. >> >> > >> >> >> >> How about: >> >> >> >> PM: Add opportunistic suspend support. >> > >> > "PM: Opportunistic suspend support" would be sufficient IMO. >> > >> > Now, I'd start with the motivation. Like "Power management features present >> > in the current mainline kernel are insufficient to get maximum possible energy >> > savings on some platforms, such as Android, because ..." (here go explanations >> > why this is the case in your opinion). >> > >> > Next, "To allow Android and similar platforms to save more energy than they >> > currently can save using the mainline kernel, introduce a mechanism by which >> > the system is automatically suspended (i.e. put into a system-wide sleep state) >> > whenever it's not doing useful work, called opportunistic suspend". >> > >> > "For this purpose introduce the suspend blockers framework allowing the >> > kernel's power management subsystem to decide when it is desirable to suspend >> > the system (i.e. when useful work is not being done). Add an API that ..." >> > >> >> PM: Opportunistic suspend support. >> >> Power management features present in the current mainline kernel are >> insufficient to get maximum possible energy savings on some platforms, >> such as Android, because low power states can only safely be entered >> from idle. > > Do you mean CPU low-power states or system low-power states here? > I think either. > I'd add more details here, because it may not be completely clear to the > (interested) reader why entering these states only from idle affects the > possibility to achieve maximum energy savings. I _guess_ you mean that > using idle is not sufficient, because there are so many wakeups on the > systems in question that more savings are still possible. Is that correct? > Yes, is this not what the next paragraph explains? >> Suspend, in its current form, cannot be used, since wakeup >> events that occur right after initiating suspend will not be processed >> until another possibly unrelated event wake up the system again. > > I think the word "cannot" is too strong here. I'd say "not suitable" instead I don't think it is too strong, but I can change it. > and I'd say what kind of wakeup events I meant more precisely (there are > events that wake up a CPU from idle and events that wake up the system from > suspend). When I say wakeup events I mean events that do both. Is there another term for this, or should I just add: "since wakeup events (events that wake the CPU from idle and the system from suspend)..." > >> On some systems idle combined with runtime PM can enter the same power >> state as suspend, but periodic wakeups increase the average power >> consumption. Suspending the system also reduces the harm caused by >> apps that never go idle. On other systems suspend can enter a much >> lower power state than idle. >> >> To allow Android and similar platforms to save more energy than they >> currently can save using the mainline kernel, we introduce a mechanism > > Just "introduce" without "we" works too. > >> by which the system is automatically suspended (i.e. put into a >> system-wide sleep state) whenever it's not doing useful work, called >> opportunistic suspend. > > I think we can address the Kevin's comment about "useful" and say "whenever > it's only doing work that can be done later without noticeable effect on > functionality". > >> For this purpose introduce the suspend blockers framework allowing the >> kernel's power management subsystem to decide when it is desirable to >> suspend the system (i.e. when useful work is not being done). Add an > > Perhaps remove the part in parens entirely. > >> API that that drivers can use to block opportunistic suspend. This is >> needed to avoid losing wakeup events that occur right after suspend is >> initiated. >> >> Adds /sys/power/policy that selects the behavior 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. > > ... > >> PM: suspend_block: Add driver to access suspend blockers from user-space >> >> Add a misc device, "suspend_blocker", that allows user-space processes >> to block automatic suspend. >> >> Opening this device creates a suspend blocker that can be used by the >> opener to prevent automatic suspend from occurring. There are ioctls >> provided for blocking and unblocking suspend and for giving the >> suspend blocker a meaningful name. Closing the device special file >> causes the suspend blocker to be destroyed. >> >> For example, when select or poll indicates that input event are >> available, this interface can be used by user space to block suspend >> before it reads those events. This allows the input driver to release >> its suspend blocker as soon as the event queue is empty. If user space >> could not use a suspend blocker here the input driver would need to >> delay the release of its suspend blocker until it knows (or assumes) >> that user space has finished processing the events. >> >> By careful use of suspend blockers in drivers and user space system >> code, one can arrange for the system to stay awake for extremely short >> periods of time in reaction to events, rapidly returning to a fully >> suspended state. > > That's fine by me. > > Thanks, > Rafael > -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <AANLkTinPC94F1wj-CEb3vvSo7__u625DsZxErlmTymEw@mail.gmail.com>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <AANLkTinPC94F1wj-CEb3vvSo7__u625DsZxErlmTymEw@mail.gmail.com> @ 2010-05-18 21:48 ` Rafael J. Wysocki [not found] ` <201005182348.16026.rjw@sisk.pl> 1 sibling, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-18 21:48 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett On Tuesday 18 May 2010, Arve Hjønnevåg wrote: > 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: > >> 2010/5/17 Rafael J. Wysocki <rjw@sisk.pl>: > >> > On Monday 17 May 2010, Arve Hjønnevåg wrote: > >> >> 2010/5/14 Rafael J. Wysocki <rjw@sisk.pl>: > >> >> > On Friday 14 May 2010, Arve Hjønnevåg wrote: > >> >> >> This patch series adds a suspend-block api that provides the same > >> >> >> functionality as the android wakelock api. This version has some > >> >> >> changes from, or requested by, Rafael. The most notable changes are: > >> >> >> - DEFINE_SUSPEND_BLOCKER and suspend_blocker_register have been added > >> >> >> for statically allocated suspend blockers. > >> >> >> - suspend_blocker_destroy is now called suspend_blocker_unregister > >> >> >> - The user space mandatory _INIT ioctl has been replaced with an > >> >> >> optional _SET_NAME ioctl. > >> >> >> > >> >> >> I kept the ack and reviewed by tags on two of the patches even though > >> >> >> there were a few cosmetic changes. > >> >> > > >> >> > Thanks for the patches, I think they are in a pretty good shape now. > >> >> > > >> >> > That said, I'd like the changelogs to be a bit more descriptive, at least for > >> >> > patch [1/8]. I think it should explain (in a few words) what the purpose of > >> >> > the feature is and what problems it solves that generally a combination of > >> >> > runtime PM and cpuidle is not suitable for in your opinion. IOW, why you > >> >> > think we need that feature. > >> >> > > >> >> > >> >> How about: > >> >> > >> >> PM: Add opportunistic suspend support. > >> > > >> > "PM: Opportunistic suspend support" would be sufficient IMO. > >> > > >> > Now, I'd start with the motivation. Like "Power management features present > >> > in the current mainline kernel are insufficient to get maximum possible energy > >> > savings on some platforms, such as Android, because ..." (here go explanations > >> > why this is the case in your opinion). > >> > > >> > Next, "To allow Android and similar platforms to save more energy than they > >> > currently can save using the mainline kernel, introduce a mechanism by which > >> > the system is automatically suspended (i.e. put into a system-wide sleep state) > >> > whenever it's not doing useful work, called opportunistic suspend". > >> > > >> > "For this purpose introduce the suspend blockers framework allowing the > >> > kernel's power management subsystem to decide when it is desirable to suspend > >> > the system (i.e. when useful work is not being done). Add an API that ..." > >> > > >> > >> PM: Opportunistic suspend support. > >> > >> Power management features present in the current mainline kernel are > >> insufficient to get maximum possible energy savings on some platforms, > >> such as Android, because low power states can only safely be entered > >> from idle. > > > > Do you mean CPU low-power states or system low-power states here? > > > I think either. The statement is not true for system low-power states (or sleep states), because generally (ie. on many platforms) they aren't entered from idle. Suspend is for entering them. So, there is a difference and the explanation can go like this: "... to achieve maximum energy savings one has to put all I/O devices and the CPU into low-power states, but the CPU can only be put into a low-power state from idle. This, in turn, means that the CPU leaves the low-power state on interrupts triggered by periodic timers and user space processes that use polling. It turns out, however, that many of these events causing the CPU to leave the low-power state aren't essential for the desired system functionality and from the power management point of view it would be better if they didn't occur". > > I'd add more details here, because it may not be completely clear to the > > (interested) reader why entering these states only from idle affects the > > possibility to achieve maximum energy savings. I _guess_ you mean that > > using idle is not sufficient, because there are so many wakeups on the > > systems in question that more savings are still possible. Is that correct? > > > Yes, is this not what the next paragraph explains? Well, it doesn't explain that. It explains why idle + runtime PM is generally insufficient and is using that as an argument (at least in my view). > >> Suspend, in its current form, cannot be used, since wakeup > >> events that occur right after initiating suspend will not be processed > >> until another possibly unrelated event wake up the system again. > > > > I think the word "cannot" is too strong here. I'd say "not suitable" instead > > I don't think it is too strong, but I can change it. > > > and I'd say what kind of wakeup events I meant more precisely (there are > > events that wake up a CPU from idle and events that wake up the system from > > suspend). > > When I say wakeup events I mean events that do both. Is there another > term for this, or should I just add: "since wakeup events (events that > wake the CPU from idle and the system from suspend)..." Yes, that would clarify things IMO. Thanks, Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <201005182348.16026.rjw@sisk.pl>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <201005182348.16026.rjw@sisk.pl> @ 2010-05-18 22:03 ` Arve Hjønnevåg [not found] ` <AANLkTin-A5eXvxDEo-vi2x2jjXtZbAl2526w62noNMIK@mail.gmail.com> 1 sibling, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-18 22:03 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: >> > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: >> >> 2010/5/17 Rafael J. Wysocki <rjw@sisk.pl>: >> >> > On Monday 17 May 2010, Arve Hjønnevåg wrote: >> >> >> 2010/5/14 Rafael J. Wysocki <rjw@sisk.pl>: >> >> >> > On Friday 14 May 2010, Arve Hjønnevåg wrote: >> >> >> >> This patch series adds a suspend-block api that provides the same >> >> >> >> functionality as the android wakelock api. This version has some >> >> >> >> changes from, or requested by, Rafael. The most notable changes are: >> >> >> >> - DEFINE_SUSPEND_BLOCKER and suspend_blocker_register have been added >> >> >> >> for statically allocated suspend blockers. >> >> >> >> - suspend_blocker_destroy is now called suspend_blocker_unregister >> >> >> >> - The user space mandatory _INIT ioctl has been replaced with an >> >> >> >> optional _SET_NAME ioctl. >> >> >> >> >> >> >> >> I kept the ack and reviewed by tags on two of the patches even though >> >> >> >> there were a few cosmetic changes. >> >> >> > >> >> >> > Thanks for the patches, I think they are in a pretty good shape now. >> >> >> > >> >> >> > That said, I'd like the changelogs to be a bit more descriptive, at least for >> >> >> > patch [1/8]. I think it should explain (in a few words) what the purpose of >> >> >> > the feature is and what problems it solves that generally a combination of >> >> >> > runtime PM and cpuidle is not suitable for in your opinion. IOW, why you >> >> >> > think we need that feature. >> >> >> > >> >> >> >> >> >> How about: >> >> >> >> >> >> PM: Add opportunistic suspend support. >> >> > >> >> > "PM: Opportunistic suspend support" would be sufficient IMO. >> >> > >> >> > Now, I'd start with the motivation. Like "Power management features present >> >> > in the current mainline kernel are insufficient to get maximum possible energy >> >> > savings on some platforms, such as Android, because ..." (here go explanations >> >> > why this is the case in your opinion). >> >> > >> >> > Next, "To allow Android and similar platforms to save more energy than they >> >> > currently can save using the mainline kernel, introduce a mechanism by which >> >> > the system is automatically suspended (i.e. put into a system-wide sleep state) >> >> > whenever it's not doing useful work, called opportunistic suspend". >> >> > >> >> > "For this purpose introduce the suspend blockers framework allowing the >> >> > kernel's power management subsystem to decide when it is desirable to suspend >> >> > the system (i.e. when useful work is not being done). Add an API that ..." >> >> > >> >> >> >> PM: Opportunistic suspend support. >> >> >> >> Power management features present in the current mainline kernel are >> >> insufficient to get maximum possible energy savings on some platforms, >> >> such as Android, because low power states can only safely be entered >> >> from idle. >> > >> > Do you mean CPU low-power states or system low-power states here? >> > >> I think either. > > The statement is not true for system low-power states (or sleep states), > because generally (ie. on many platforms) they aren't entered from idle. > Suspend is for entering them. > I don't think that makes my statement false. If you can only safely enter low power states from idle, but some low power states cannot be entered from idle, then it follows that you cannot safely enter those low power states. > So, there is a difference and the explanation can go like this: "... to achieve > maximum energy savings one has to put all I/O devices and the CPU into > low-power states, but the CPU can only be put into a low-power state from > idle. This, in turn, means that the CPU leaves the low-power state on > interrupts triggered by periodic timers and user space processes that use > polling. It turns out, however, that many of these events causing the CPU to > leave the low-power state aren't essential for the desired system functionality > and from the power management point of view it would be better if they didn't > occur". This only explain why we still want to use suspend on systems that can enter the same power states from idle and suspend. > >> > I'd add more details here, because it may not be completely clear to the >> > (interested) reader why entering these states only from idle affects the >> > possibility to achieve maximum energy savings. I _guess_ you mean that >> > using idle is not sufficient, because there are so many wakeups on the >> > systems in question that more savings are still possible. Is that correct? >> > >> Yes, is this not what the next paragraph explains? > > Well, it doesn't explain that. It explains why idle + runtime PM is generally > insufficient and is using that as an argument (at least in my view). > >> >> Suspend, in its current form, cannot be used, since wakeup >> >> events that occur right after initiating suspend will not be processed >> >> until another possibly unrelated event wake up the system again. >> > >> > I think the word "cannot" is too strong here. I'd say "not suitable" instead >> >> I don't think it is too strong, but I can change it. >> >> > and I'd say what kind of wakeup events I meant more precisely (there are >> > events that wake up a CPU from idle and events that wake up the system from >> > suspend). >> >> When I say wakeup events I mean events that do both. Is there another >> term for this, or should I just add: "since wakeup events (events that >> wake the CPU from idle and the system from suspend)..." > > Yes, that would clarify things IMO. > > Thanks, > Rafael > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ > -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <AANLkTin-A5eXvxDEo-vi2x2jjXtZbAl2526w62noNMIK@mail.gmail.com>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <AANLkTin-A5eXvxDEo-vi2x2jjXtZbAl2526w62noNMIK@mail.gmail.com> @ 2010-05-18 22:34 ` Rafael J. Wysocki [not found] ` <201005190034.26085.rjw@sisk.pl> 1 sibling, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-18 22:34 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett On Wednesday 19 May 2010, Arve Hjønnevåg wrote: > 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: > >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > >> > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: > >> >> 2010/5/17 Rafael J. Wysocki <rjw@sisk.pl>: > >> >> > On Monday 17 May 2010, Arve Hjønnevåg wrote: > >> >> >> 2010/5/14 Rafael J. Wysocki <rjw@sisk.pl>: > >> >> >> > On Friday 14 May 2010, Arve Hjønnevåg wrote: > >> >> >> >> This patch series adds a suspend-block api that provides the same > >> >> >> >> functionality as the android wakelock api. This version has some > >> >> >> >> changes from, or requested by, Rafael. The most notable changes are: > >> >> >> >> - DEFINE_SUSPEND_BLOCKER and suspend_blocker_register have been added > >> >> >> >> for statically allocated suspend blockers. > >> >> >> >> - suspend_blocker_destroy is now called suspend_blocker_unregister > >> >> >> >> - The user space mandatory _INIT ioctl has been replaced with an > >> >> >> >> optional _SET_NAME ioctl. > >> >> >> >> > >> >> >> >> I kept the ack and reviewed by tags on two of the patches even though > >> >> >> >> there were a few cosmetic changes. > >> >> >> > > >> >> >> > Thanks for the patches, I think they are in a pretty good shape now. > >> >> >> > > >> >> >> > That said, I'd like the changelogs to be a bit more descriptive, at least for > >> >> >> > patch [1/8]. I think it should explain (in a few words) what the purpose of > >> >> >> > the feature is and what problems it solves that generally a combination of > >> >> >> > runtime PM and cpuidle is not suitable for in your opinion. IOW, why you > >> >> >> > think we need that feature. > >> >> >> > > >> >> >> > >> >> >> How about: > >> >> >> > >> >> >> PM: Add opportunistic suspend support. > >> >> > > >> >> > "PM: Opportunistic suspend support" would be sufficient IMO. > >> >> > > >> >> > Now, I'd start with the motivation. Like "Power management features present > >> >> > in the current mainline kernel are insufficient to get maximum possible energy > >> >> > savings on some platforms, such as Android, because ..." (here go explanations > >> >> > why this is the case in your opinion). > >> >> > > >> >> > Next, "To allow Android and similar platforms to save more energy than they > >> >> > currently can save using the mainline kernel, introduce a mechanism by which > >> >> > the system is automatically suspended (i.e. put into a system-wide sleep state) > >> >> > whenever it's not doing useful work, called opportunistic suspend". > >> >> > > >> >> > "For this purpose introduce the suspend blockers framework allowing the > >> >> > kernel's power management subsystem to decide when it is desirable to suspend > >> >> > the system (i.e. when useful work is not being done). Add an API that ..." > >> >> > > >> >> > >> >> PM: Opportunistic suspend support. > >> >> > >> >> Power management features present in the current mainline kernel are > >> >> insufficient to get maximum possible energy savings on some platforms, > >> >> such as Android, because low power states can only safely be entered > >> >> from idle. > >> > > >> > Do you mean CPU low-power states or system low-power states here? > >> > > >> I think either. > > > > The statement is not true for system low-power states (or sleep states), > > because generally (ie. on many platforms) they aren't entered from idle. > > Suspend is for entering them. > > > I don't think that makes my statement false. If you can only safely > enter low power states from idle, but some low power states cannot be > entered from idle, then it follows that you cannot safely enter those > low power states. Define "safely", then. > > So, there is a difference and the explanation can go like this: "... to achieve > > maximum energy savings one has to put all I/O devices and the CPU into > > low-power states, but the CPU can only be put into a low-power state from > > idle. This, in turn, means that the CPU leaves the low-power state on > > interrupts triggered by periodic timers and user space processes that use > > polling. It turns out, however, that many of these events causing the CPU to > > leave the low-power state aren't essential for the desired system functionality > > and from the power management point of view it would be better if they didn't > > occur". > > This only explain why we still want to use suspend on systems that can > enter the same power states from idle and suspend. Sorry, I'm confused now. Isn't that why you do that on Android? AFACS, your hardware is capable of doing that, isn't it? Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <201005190034.26085.rjw@sisk.pl>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <201005190034.26085.rjw@sisk.pl> @ 2010-05-18 22:52 ` Arve Hjønnevåg [not found] ` <AANLkTime0yZ_t32m8WjqJEtSeNlBJYZy15X8HwKzMqOl@mail.gmail.com> 1 sibling, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-18 22:52 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > On Wednesday 19 May 2010, Arve Hjønnevåg wrote: >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: >> > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: >> >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: >> >> > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: >> >> >> 2010/5/17 Rafael J. Wysocki <rjw@sisk.pl>: >> >> >> > On Monday 17 May 2010, Arve Hjønnevåg wrote: >> >> >> >> 2010/5/14 Rafael J. Wysocki <rjw@sisk.pl>: >> >> >> >> > On Friday 14 May 2010, Arve Hjønnevåg wrote: >> >> >> >> >> This patch series adds a suspend-block api that provides the same >> >> >> >> >> functionality as the android wakelock api. This version has some >> >> >> >> >> changes from, or requested by, Rafael. The most notable changes are: >> >> >> >> >> - DEFINE_SUSPEND_BLOCKER and suspend_blocker_register have been added >> >> >> >> >> for statically allocated suspend blockers. >> >> >> >> >> - suspend_blocker_destroy is now called suspend_blocker_unregister >> >> >> >> >> - The user space mandatory _INIT ioctl has been replaced with an >> >> >> >> >> optional _SET_NAME ioctl. >> >> >> >> >> >> >> >> >> >> I kept the ack and reviewed by tags on two of the patches even though >> >> >> >> >> there were a few cosmetic changes. >> >> >> >> > >> >> >> >> > Thanks for the patches, I think they are in a pretty good shape now. >> >> >> >> > >> >> >> >> > That said, I'd like the changelogs to be a bit more descriptive, at least for >> >> >> >> > patch [1/8]. I think it should explain (in a few words) what the purpose of >> >> >> >> > the feature is and what problems it solves that generally a combination of >> >> >> >> > runtime PM and cpuidle is not suitable for in your opinion. IOW, why you >> >> >> >> > think we need that feature. >> >> >> >> > >> >> >> >> >> >> >> >> How about: >> >> >> >> >> >> >> >> PM: Add opportunistic suspend support. >> >> >> > >> >> >> > "PM: Opportunistic suspend support" would be sufficient IMO. >> >> >> > >> >> >> > Now, I'd start with the motivation. Like "Power management features present >> >> >> > in the current mainline kernel are insufficient to get maximum possible energy >> >> >> > savings on some platforms, such as Android, because ..." (here go explanations >> >> >> > why this is the case in your opinion). >> >> >> > >> >> >> > Next, "To allow Android and similar platforms to save more energy than they >> >> >> > currently can save using the mainline kernel, introduce a mechanism by which >> >> >> > the system is automatically suspended (i.e. put into a system-wide sleep state) >> >> >> > whenever it's not doing useful work, called opportunistic suspend". >> >> >> > >> >> >> > "For this purpose introduce the suspend blockers framework allowing the >> >> >> > kernel's power management subsystem to decide when it is desirable to suspend >> >> >> > the system (i.e. when useful work is not being done). Add an API that ..." >> >> >> > >> >> >> >> >> >> PM: Opportunistic suspend support. >> >> >> >> >> >> Power management features present in the current mainline kernel are >> >> >> insufficient to get maximum possible energy savings on some platforms, >> >> >> such as Android, because low power states can only safely be entered >> >> >> from idle. >> >> > >> >> > Do you mean CPU low-power states or system low-power states here? >> >> > >> >> I think either. >> > >> > The statement is not true for system low-power states (or sleep states), >> > because generally (ie. on many platforms) they aren't entered from idle. >> > Suspend is for entering them. >> > >> I don't think that makes my statement false. If you can only safely >> enter low power states from idle, but some low power states cannot be >> entered from idle, then it follows that you cannot safely enter those >> low power states. > > Define "safely", then. > OK. Is this clearer: Power management features present in the current mainline kernel are insufficient to get maximum possible energy savings on some platforms, such as Android, because some wakeup events must work at all times which means that low power states can only safely be entered from idle. Suspend, in its current form, cannot be used, since wakeup events that occur right after initiating suspend will not be processed until another possibly unrelated event wake up the system again. >> > So, there is a difference and the explanation can go like this: "... to achieve >> > maximum energy savings one has to put all I/O devices and the CPU into >> > low-power states, but the CPU can only be put into a low-power state from >> > idle. This, in turn, means that the CPU leaves the low-power state on >> > interrupts triggered by periodic timers and user space processes that use >> > polling. It turns out, however, that many of these events causing the CPU to >> > leave the low-power state aren't essential for the desired system functionality >> > and from the power management point of view it would be better if they didn't >> > occur". >> >> This only explain why we still want to use suspend on systems that can >> enter the same power states from idle and suspend. > > Sorry, I'm confused now. Isn't that why you do that on Android? > Yes, but it is not the only reason to use opportunistic support. It is way more important to have opportunistic suspend support if the hardware can enter lower power states from suspend than idle. > AFACS, your hardware is capable of doing that, isn't it? > The current hardware, yes, the hardware we started with, no. -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <AANLkTime0yZ_t32m8WjqJEtSeNlBJYZy15X8HwKzMqOl@mail.gmail.com>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <AANLkTime0yZ_t32m8WjqJEtSeNlBJYZy15X8HwKzMqOl@mail.gmail.com> @ 2010-05-18 23:19 ` Rafael J. Wysocki [not found] ` <201005190119.07710.rjw@sisk.pl> 1 sibling, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-18 23:19 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett On Wednesday 19 May 2010, Arve Hjønnevåg wrote: > 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > > On Wednesday 19 May 2010, Arve Hjønnevåg wrote: > >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > >> > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: > >> >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > >> >> > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: > >> >> >> 2010/5/17 Rafael J. Wysocki <rjw@sisk.pl>: > >> >> >> > On Monday 17 May 2010, Arve Hjønnevåg wrote: > >> >> >> >> 2010/5/14 Rafael J. Wysocki <rjw@sisk.pl>: > >> >> >> >> > On Friday 14 May 2010, Arve Hjønnevåg wrote: > >> >> >> >> >> This patch series adds a suspend-block api that provides the same > >> >> >> >> >> functionality as the android wakelock api. This version has some > >> >> >> >> >> changes from, or requested by, Rafael. The most notable changes are: > >> >> >> >> >> - DEFINE_SUSPEND_BLOCKER and suspend_blocker_register have been added > >> >> >> >> >> for statically allocated suspend blockers. > >> >> >> >> >> - suspend_blocker_destroy is now called suspend_blocker_unregister > >> >> >> >> >> - The user space mandatory _INIT ioctl has been replaced with an > >> >> >> >> >> optional _SET_NAME ioctl. > >> >> >> >> >> > >> >> >> >> >> I kept the ack and reviewed by tags on two of the patches even though > >> >> >> >> >> there were a few cosmetic changes. > >> >> >> >> > > >> >> >> >> > Thanks for the patches, I think they are in a pretty good shape now. > >> >> >> >> > > >> >> >> >> > That said, I'd like the changelogs to be a bit more descriptive, at least for > >> >> >> >> > patch [1/8]. I think it should explain (in a few words) what the purpose of > >> >> >> >> > the feature is and what problems it solves that generally a combination of > >> >> >> >> > runtime PM and cpuidle is not suitable for in your opinion. IOW, why you > >> >> >> >> > think we need that feature. > >> >> >> >> > > >> >> >> >> > >> >> >> >> How about: > >> >> >> >> > >> >> >> >> PM: Add opportunistic suspend support. > >> >> >> > > >> >> >> > "PM: Opportunistic suspend support" would be sufficient IMO. > >> >> >> > > >> >> >> > Now, I'd start with the motivation. Like "Power management features present > >> >> >> > in the current mainline kernel are insufficient to get maximum possible energy > >> >> >> > savings on some platforms, such as Android, because ..." (here go explanations > >> >> >> > why this is the case in your opinion). > >> >> >> > > >> >> >> > Next, "To allow Android and similar platforms to save more energy than they > >> >> >> > currently can save using the mainline kernel, introduce a mechanism by which > >> >> >> > the system is automatically suspended (i.e. put into a system-wide sleep state) > >> >> >> > whenever it's not doing useful work, called opportunistic suspend". > >> >> >> > > >> >> >> > "For this purpose introduce the suspend blockers framework allowing the > >> >> >> > kernel's power management subsystem to decide when it is desirable to suspend > >> >> >> > the system (i.e. when useful work is not being done). Add an API that ..." > >> >> >> > > >> >> >> > >> >> >> PM: Opportunistic suspend support. > >> >> >> > >> >> >> Power management features present in the current mainline kernel are > >> >> >> insufficient to get maximum possible energy savings on some platforms, > >> >> >> such as Android, because low power states can only safely be entered > >> >> >> from idle. > >> >> > > >> >> > Do you mean CPU low-power states or system low-power states here? > >> >> > > >> >> I think either. > >> > > >> > The statement is not true for system low-power states (or sleep states), > >> > because generally (ie. on many platforms) they aren't entered from idle. > >> > Suspend is for entering them. > >> > > >> I don't think that makes my statement false. If you can only safely > >> enter low power states from idle, but some low power states cannot be > >> entered from idle, then it follows that you cannot safely enter those > >> low power states. > > > > Define "safely", then. > > > OK. Is this clearer: Not really. > Power management features present in the current mainline kernel are > insufficient to get maximum possible energy savings on some platforms, > such as Android, because some wakeup events must work at all times > which means that low power states can only safely be entered from idle. It's not clear what you mean by "some wakeup events must work at all times" and what "safely" means. > Suspend, in its current form, cannot be used, since wakeup events that > occur right after initiating suspend will not be processed until another > possibly unrelated event wake up the system again. Well, I _guess_ I know what you're trying to say, but I'm not sure if that's the core of the problem the patchset is supposed to address. The problem, as I see it, is really two-fold. First, to save as much energy as reasonably possible you need to put everything except for memory (ie. I/O devices and CPUs) into low-power states and let that stay in these low-power states for as long as reasonably possible, right? Second, you need the system to _always_ respond to some _specific_ events regardless of its current state, correct? Now, at present, we can put I/O devices and the CPU into low-power states at the same time in two ways: (1) by using runtime PM and cpuidle and (2) by suspending the system. Unfortunately, none of these approaches is ideal, because (1) is vulnerable to periodic timers and polling apps (and CPU-bound apps) and (2) doesn't guarantee that all events you care about will be responded to. The proposed solution is to use suspend with an additional mechanism that will prevent the events that have to be responded to from being lost. This additional mechanism is suspend blockers. Is this correct? > >> > So, there is a difference and the explanation can go like this: "... to achieve > >> > maximum energy savings one has to put all I/O devices and the CPU into > >> > low-power states, but the CPU can only be put into a low-power state from > >> > idle. This, in turn, means that the CPU leaves the low-power state on > >> > interrupts triggered by periodic timers and user space processes that use > >> > polling. It turns out, however, that many of these events causing the CPU to > >> > leave the low-power state aren't essential for the desired system functionality > >> > and from the power management point of view it would be better if they didn't > >> > occur". > >> > >> This only explain why we still want to use suspend on systems that can > >> enter the same power states from idle and suspend. > > > > Sorry, I'm confused now. Isn't that why you do that on Android? > > > > Yes, but it is not the only reason to use opportunistic support. It is > way more important to have opportunistic suspend support if the > hardware can enter lower power states from suspend than idle. Sure, but you can add something like "There also are systems where some devices cannot be put into low-power states without suspending the entire system (or the low-power states available to them without suspending the entire system are substantially shallower than the low-power states they are put into when the entire system is suspended), so the system have to be suspended as a whole to achieve the maximum energy savings". Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <201005190119.07710.rjw@sisk.pl>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <201005190119.07710.rjw@sisk.pl> @ 2010-05-18 23:42 ` Arve Hjønnevåg [not found] ` <AANLkTimFbvbDZdAFFTk0VCYhDtDk9B_LcEO60ZP70vjS@mail.gmail.com> 1 sibling, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-18 23:42 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > On Wednesday 19 May 2010, Arve Hjønnevåg wrote: >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: >> > On Wednesday 19 May 2010, Arve Hjønnevåg wrote: >> >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: >> >> > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: >> >> >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: >> >> >> > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: >> >> >> >> 2010/5/17 Rafael J. Wysocki <rjw@sisk.pl>: >> >> >> >> > On Monday 17 May 2010, Arve Hjønnevåg wrote: >> >> >> >> >> 2010/5/14 Rafael J. Wysocki <rjw@sisk.pl>: >> >> >> >> >> > On Friday 14 May 2010, Arve Hjønnevåg wrote: >> >> >> >> >> >> This patch series adds a suspend-block api that provides the same >> >> >> >> >> >> functionality as the android wakelock api. This version has some >> >> >> >> >> >> changes from, or requested by, Rafael. The most notable changes are: >> >> >> >> >> >> - DEFINE_SUSPEND_BLOCKER and suspend_blocker_register have been added >> >> >> >> >> >> for statically allocated suspend blockers. >> >> >> >> >> >> - suspend_blocker_destroy is now called suspend_blocker_unregister >> >> >> >> >> >> - The user space mandatory _INIT ioctl has been replaced with an >> >> >> >> >> >> optional _SET_NAME ioctl. >> >> >> >> >> >> >> >> >> >> >> >> I kept the ack and reviewed by tags on two of the patches even though >> >> >> >> >> >> there were a few cosmetic changes. >> >> >> >> >> > >> >> >> >> >> > Thanks for the patches, I think they are in a pretty good shape now. >> >> >> >> >> > >> >> >> >> >> > That said, I'd like the changelogs to be a bit more descriptive, at least for >> >> >> >> >> > patch [1/8]. I think it should explain (in a few words) what the purpose of >> >> >> >> >> > the feature is and what problems it solves that generally a combination of >> >> >> >> >> > runtime PM and cpuidle is not suitable for in your opinion. IOW, why you >> >> >> >> >> > think we need that feature. >> >> >> >> >> > >> >> >> >> >> >> >> >> >> >> How about: >> >> >> >> >> >> >> >> >> >> PM: Add opportunistic suspend support. >> >> >> >> > >> >> >> >> > "PM: Opportunistic suspend support" would be sufficient IMO. >> >> >> >> > >> >> >> >> > Now, I'd start with the motivation. Like "Power management features present >> >> >> >> > in the current mainline kernel are insufficient to get maximum possible energy >> >> >> >> > savings on some platforms, such as Android, because ..." (here go explanations >> >> >> >> > why this is the case in your opinion). >> >> >> >> > >> >> >> >> > Next, "To allow Android and similar platforms to save more energy than they >> >> >> >> > currently can save using the mainline kernel, introduce a mechanism by which >> >> >> >> > the system is automatically suspended (i.e. put into a system-wide sleep state) >> >> >> >> > whenever it's not doing useful work, called opportunistic suspend". >> >> >> >> > >> >> >> >> > "For this purpose introduce the suspend blockers framework allowing the >> >> >> >> > kernel's power management subsystem to decide when it is desirable to suspend >> >> >> >> > the system (i.e. when useful work is not being done). Add an API that ..." >> >> >> >> > >> >> >> >> >> >> >> >> PM: Opportunistic suspend support. >> >> >> >> >> >> >> >> Power management features present in the current mainline kernel are >> >> >> >> insufficient to get maximum possible energy savings on some platforms, >> >> >> >> such as Android, because low power states can only safely be entered >> >> >> >> from idle. >> >> >> > >> >> >> > Do you mean CPU low-power states or system low-power states here? >> >> >> > >> >> >> I think either. >> >> > >> >> > The statement is not true for system low-power states (or sleep states), >> >> > because generally (ie. on many platforms) they aren't entered from idle. >> >> > Suspend is for entering them. >> >> > >> >> I don't think that makes my statement false. If you can only safely >> >> enter low power states from idle, but some low power states cannot be >> >> entered from idle, then it follows that you cannot safely enter those >> >> low power states. >> > >> > Define "safely", then. >> > >> OK. Is this clearer: > > Not really. > >> Power management features present in the current mainline kernel are >> insufficient to get maximum possible energy savings on some platforms, >> such as Android, because some wakeup events must work at all times >> which means that low power states can only safely be entered from idle. > > It's not clear what you mean by "some wakeup events must work at all times" > and what "safely" means. > >> Suspend, in its current form, cannot be used, since wakeup events that >> occur right after initiating suspend will not be processed until another >> possibly unrelated event wake up the system again. > > Well, I _guess_ I know what you're trying to say, but I'm not sure if that's > the core of the problem the patchset is supposed to address. > > The problem, as I see it, is really two-fold. > > First, to save as much energy as reasonably possible you need to put everything > except for memory (ie. I/O devices and CPUs) into low-power states and let that > stay in these low-power states for as long as reasonably possible, right? Memory should also be in a low power state, but yes, everything should be in the lowest power possible state for as long as possible. > > Second, you need the system to _always_ respond to some _specific_ events > regardless of its current state, correct? > > Now, at present, we can put I/O devices and the CPU into low-power states > at the same time in two ways: (1) by using runtime PM and cpuidle and (2) by > suspending the system. Unfortunately, none of these approaches is ideal, > because (1) is vulnerable to periodic timers and polling apps (and CPU-bound > apps) and (2) doesn't guarantee that all events you care about will be > responded to. > > The proposed solution is to use suspend with an additional mechanism that > will prevent the events that have to be responded to from being lost. This > additional mechanism is suspend blockers. > > Is this correct? Yes. > >> >> > So, there is a difference and the explanation can go like this: "... to achieve >> >> > maximum energy savings one has to put all I/O devices and the CPU into >> >> > low-power states, but the CPU can only be put into a low-power state from >> >> > idle. This, in turn, means that the CPU leaves the low-power state on >> >> > interrupts triggered by periodic timers and user space processes that use >> >> > polling. It turns out, however, that many of these events causing the CPU to >> >> > leave the low-power state aren't essential for the desired system functionality >> >> > and from the power management point of view it would be better if they didn't >> >> > occur". >> >> >> >> This only explain why we still want to use suspend on systems that can >> >> enter the same power states from idle and suspend. >> > >> > Sorry, I'm confused now. Isn't that why you do that on Android? >> > >> >> Yes, but it is not the only reason to use opportunistic support. It is >> way more important to have opportunistic suspend support if the >> hardware can enter lower power states from suspend than idle. > > Sure, but you can add something like "There also are systems where some > devices cannot be put into low-power states without suspending the entire > system (or the low-power states available to them without suspending the > entire system are substantially shallower than the low-power states they are > put into when the entire system is suspended), so the system have to be > suspended as a whole to achieve the maximum energy savings". > Does this work for you: PM: Opportunistic suspend support. Power management features present in the current mainline kernel are insufficient to get maximum possible energy savings on some platforms, such as Android, because the system must always respond to certain events. Suspend, in its current form, cannot be used on these platforms, since wakeup events (events that wake the CPU from idle and the system from suspend) that occur right after initiating suspend will not be processed until another possibly unrelated event wake up the system again. On hardware where idle can enter the same power state as suspend, idle combined with runtime PM can be used, but periodic wakeups increase the average power consumption. Suspending the system also reduces the harm caused by apps that never go idle. There also are systems where some devices cannot be put into low-power states without suspending the entire system (or the low-power states available to them without suspending the entire system are substantially shallower than the low-power states they are put into when the entire system is suspended), so the system have to be suspended as a whole to achieve the maximum energy savings. To allow Android and similar platforms to save more energy than they currently can save using the mainline kernel, introduce a mechanism by which the system is automatically suspended (i.e. put into a system-wide sleep state) whenever it's not doing useful work, called opportunistic suspend. For this purpose introduce the suspend blockers framework allowing the kernel's power management subsystem to decide when it is desirable to suspend the system (i.e. when the system is not doing anything the user really cares about at the moment and therefore it may be suspended). Add an API that that drivers can use to block opportunistic suspend. This is needed to avoid losing wakeup events that occur right after suspend is initiated. Adds /sys/power/policy that selects the behavior 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. -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <AANLkTimFbvbDZdAFFTk0VCYhDtDk9B_LcEO60ZP70vjS@mail.gmail.com>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <AANLkTimFbvbDZdAFFTk0VCYhDtDk9B_LcEO60ZP70vjS@mail.gmail.com> @ 2010-05-19 20:39 ` Rafael J. Wysocki [not found] ` <201005192239.25892.rjw@sisk.pl> 1 sibling, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-19 20:39 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett On Wednesday 19 May 2010, Arve Hjønnevåg wrote: > 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > > On Wednesday 19 May 2010, Arve Hjønnevåg wrote: > >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > >> > On Wednesday 19 May 2010, Arve Hjønnevåg wrote: > >> >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > >> >> > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: > >> >> >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > >> >> >> > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: > >> >> >> >> 2010/5/17 Rafael J. Wysocki <rjw@sisk.pl>: > >> >> >> >> > On Monday 17 May 2010, Arve Hjønnevåg wrote: > >> >> >> >> >> 2010/5/14 Rafael J. Wysocki <rjw@sisk.pl>: > >> >> >> >> >> > On Friday 14 May 2010, Arve Hjønnevåg wrote: > >> >> >> >> >> >> This patch series adds a suspend-block api that provides the same > >> >> >> >> >> >> functionality as the android wakelock api. This version has some > >> >> >> >> >> >> changes from, or requested by, Rafael. The most notable changes are: > >> >> >> >> >> >> - DEFINE_SUSPEND_BLOCKER and suspend_blocker_register have been added > >> >> >> >> >> >> for statically allocated suspend blockers. > >> >> >> >> >> >> - suspend_blocker_destroy is now called suspend_blocker_unregister > >> >> >> >> >> >> - The user space mandatory _INIT ioctl has been replaced with an > >> >> >> >> >> >> optional _SET_NAME ioctl. > >> >> >> >> >> >> > >> >> >> >> >> >> I kept the ack and reviewed by tags on two of the patches even though > >> >> >> >> >> >> there were a few cosmetic changes. > >> >> >> >> >> > > >> >> >> >> >> > Thanks for the patches, I think they are in a pretty good shape now. > >> >> >> >> >> > > >> >> >> >> >> > That said, I'd like the changelogs to be a bit more descriptive, at least for > >> >> >> >> >> > patch [1/8]. I think it should explain (in a few words) what the purpose of > >> >> >> >> >> > the feature is and what problems it solves that generally a combination of > >> >> >> >> >> > runtime PM and cpuidle is not suitable for in your opinion. IOW, why you > >> >> >> >> >> > think we need that feature. > >> >> >> >> >> > > >> >> >> >> >> > >> >> >> >> >> How about: > >> >> >> >> >> > >> >> >> >> >> PM: Add opportunistic suspend support. > >> >> >> >> > > >> >> >> >> > "PM: Opportunistic suspend support" would be sufficient IMO. > >> >> >> >> > > >> >> >> >> > Now, I'd start with the motivation. Like "Power management features present > >> >> >> >> > in the current mainline kernel are insufficient to get maximum possible energy > >> >> >> >> > savings on some platforms, such as Android, because ..." (here go explanations > >> >> >> >> > why this is the case in your opinion). > >> >> >> >> > > >> >> >> >> > Next, "To allow Android and similar platforms to save more energy than they > >> >> >> >> > currently can save using the mainline kernel, introduce a mechanism by which > >> >> >> >> > the system is automatically suspended (i.e. put into a system-wide sleep state) > >> >> >> >> > whenever it's not doing useful work, called opportunistic suspend". > >> >> >> >> > > >> >> >> >> > "For this purpose introduce the suspend blockers framework allowing the > >> >> >> >> > kernel's power management subsystem to decide when it is desirable to suspend > >> >> >> >> > the system (i.e. when useful work is not being done). Add an API that ..." > >> >> >> >> > > >> >> >> >> > >> >> >> >> PM: Opportunistic suspend support. > >> >> >> >> > >> >> >> >> Power management features present in the current mainline kernel are > >> >> >> >> insufficient to get maximum possible energy savings on some platforms, > >> >> >> >> such as Android, because low power states can only safely be entered > >> >> >> >> from idle. > >> >> >> > > >> >> >> > Do you mean CPU low-power states or system low-power states here? > >> >> >> > > >> >> >> I think either. > >> >> > > >> >> > The statement is not true for system low-power states (or sleep states), > >> >> > because generally (ie. on many platforms) they aren't entered from idle. > >> >> > Suspend is for entering them. > >> >> > > >> >> I don't think that makes my statement false. If you can only safely > >> >> enter low power states from idle, but some low power states cannot be > >> >> entered from idle, then it follows that you cannot safely enter those > >> >> low power states. > >> > > >> > Define "safely", then. > >> > > >> OK. Is this clearer: > > > > Not really. > > > >> Power management features present in the current mainline kernel are > >> insufficient to get maximum possible energy savings on some platforms, > >> such as Android, because some wakeup events must work at all times > >> which means that low power states can only safely be entered from idle. > > > > It's not clear what you mean by "some wakeup events must work at all times" > > and what "safely" means. > > > >> Suspend, in its current form, cannot be used, since wakeup events that > >> occur right after initiating suspend will not be processed until another > >> possibly unrelated event wake up the system again. > > > > Well, I _guess_ I know what you're trying to say, but I'm not sure if that's > > the core of the problem the patchset is supposed to address. > > > > The problem, as I see it, is really two-fold. > > > > First, to save as much energy as reasonably possible you need to put everything > > except for memory (ie. I/O devices and CPUs) into low-power states and let that > > stay in these low-power states for as long as reasonably possible, right? > > Memory should also be in a low power state, but yes, everything should > be in the lowest power possible state for as long as possible. > > > > > Second, you need the system to _always_ respond to some _specific_ events > > regardless of its current state, correct? > > > > Now, at present, we can put I/O devices and the CPU into low-power states > > at the same time in two ways: (1) by using runtime PM and cpuidle and (2) by > > suspending the system. Unfortunately, none of these approaches is ideal, > > because (1) is vulnerable to periodic timers and polling apps (and CPU-bound > > apps) and (2) doesn't guarantee that all events you care about will be > > responded to. > > > > The proposed solution is to use suspend with an additional mechanism that > > will prevent the events that have to be responded to from being lost. This > > additional mechanism is suspend blockers. > > > > Is this correct? > > Yes. > > > > >> >> > So, there is a difference and the explanation can go like this: "... to achieve > >> >> > maximum energy savings one has to put all I/O devices and the CPU into > >> >> > low-power states, but the CPU can only be put into a low-power state from > >> >> > idle. This, in turn, means that the CPU leaves the low-power state on > >> >> > interrupts triggered by periodic timers and user space processes that use > >> >> > polling. It turns out, however, that many of these events causing the CPU to > >> >> > leave the low-power state aren't essential for the desired system functionality > >> >> > and from the power management point of view it would be better if they didn't > >> >> > occur". > >> >> > >> >> This only explain why we still want to use suspend on systems that can > >> >> enter the same power states from idle and suspend. > >> > > >> > Sorry, I'm confused now. Isn't that why you do that on Android? > >> > > >> > >> Yes, but it is not the only reason to use opportunistic support. It is > >> way more important to have opportunistic suspend support if the > >> hardware can enter lower power states from suspend than idle. > > > > Sure, but you can add something like "There also are systems where some > > devices cannot be put into low-power states without suspending the entire > > system (or the low-power states available to them without suspending the > > entire system are substantially shallower than the low-power states they are > > put into when the entire system is suspended), so the system have to be > > suspended as a whole to achieve the maximum energy savings". > > > > Does this work for you: Well, almost. > PM: Opportunistic suspend support. > > Power management features present in the current mainline kernel are > insufficient to get maximum possible energy savings on some platforms, > such as Android, I'd finish the first sentence here. > because the system must always respond to certain > events. Suspend, in its current form, cannot be used on these > platforms, This doesn't seem to be correct. Surely you can suspend these systems, but you can't address the problem at hand using suspend as is. I'd say (in the second sentence) "The problem is that to save maximum amount of energy all system hardware components need to be in the lowest-power states available for as long as reasonably possible, but at the same time the system must always respond to certain events, regardless of the current state of the hardware. The first goal can be achieved either by using device runtime PM and cpuidle to put all hardware into low-power states, transparently from the user space point of view, or by suspending the whole system. However, system suspend, in its current form, does not guarantee that the events of interest will always be responded to, since wakeup events ..." > since wakeup events (events that wake the CPU from idle and > the system from suspend) that occur right after initiating suspend > will not be processed until another possibly unrelated event wake up "... wakes up ..." I guess. > the system again. > > On hardware where idle can enter the same power state as suspend, idle > combined with runtime PM can be used, but periodic wakeups increase > the average power consumption. Suspending the system also reduces the > harm caused by apps that never go idle. There also are systems where > some devices cannot be put into low-power states without suspending > the entire system (or the low-power states available to them without > suspending the entire system are substantially shallower than the > low-power states they are put into when the entire system is > suspended), so the system have to be suspended as a whole to achieve > the maximum energy savings. > > To allow Android and similar platforms to save more energy than they > currently can save using the mainline kernel, introduce a mechanism by > which the system is automatically suspended (i.e. put into a > system-wide sleep state) whenever it's not doing useful work, called > opportunistic suspend. I'd say "... whenever it's not doing work that's immediately useful to the user, called ..." or something like this. The rest is fine by me. Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <201005192239.25892.rjw@sisk.pl>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <201005192239.25892.rjw@sisk.pl> @ 2010-05-19 21:34 ` Arve Hjønnevåg [not found] ` <AANLkTimoU9BrzbAl7q-LZzGeRolO7gUKBoGjkPWtWn1G@mail.gmail.com> 1 sibling, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-19 21:34 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett 2010/5/19 Rafael J. Wysocki <rjw@sisk.pl>: > On Wednesday 19 May 2010, Arve Hjønnevåg wrote: >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: >> > On Wednesday 19 May 2010, Arve Hjønnevåg wrote: >> >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: >> >> > On Wednesday 19 May 2010, Arve Hjønnevåg wrote: >> >> >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: >> >> >> > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: >> >> >> >> 2010/5/18 Rafael J. Wysocki <rjw@sisk.pl>: >> >> >> >> > On Tuesday 18 May 2010, Arve Hjønnevåg wrote: >> >> >> >> >> 2010/5/17 Rafael J. Wysocki <rjw@sisk.pl>: >> >> >> >> >> > On Monday 17 May 2010, Arve Hjønnevåg wrote: >> >> >> >> >> >> 2010/5/14 Rafael J. Wysocki <rjw@sisk.pl>: >> >> >> >> >> >> > On Friday 14 May 2010, Arve Hjønnevåg wrote: >> >> >> >> >> >> >> This patch series adds a suspend-block api that provides the same >> >> >> >> >> >> >> functionality as the android wakelock api. This version has some >> >> >> >> >> >> >> changes from, or requested by, Rafael. The most notable changes are: >> >> >> >> >> >> >> - DEFINE_SUSPEND_BLOCKER and suspend_blocker_register have been added >> >> >> >> >> >> >> for statically allocated suspend blockers. >> >> >> >> >> >> >> - suspend_blocker_destroy is now called suspend_blocker_unregister >> >> >> >> >> >> >> - The user space mandatory _INIT ioctl has been replaced with an >> >> >> >> >> >> >> optional _SET_NAME ioctl. >> >> >> >> >> >> >> >> >> >> >> >> >> >> I kept the ack and reviewed by tags on two of the patches even though >> >> >> >> >> >> >> there were a few cosmetic changes. >> >> >> >> >> >> > >> >> >> >> >> >> > Thanks for the patches, I think they are in a pretty good shape now. >> >> >> >> >> >> > >> >> >> >> >> >> > That said, I'd like the changelogs to be a bit more descriptive, at least for >> >> >> >> >> >> > patch [1/8]. I think it should explain (in a few words) what the purpose of >> >> >> >> >> >> > the feature is and what problems it solves that generally a combination of >> >> >> >> >> >> > runtime PM and cpuidle is not suitable for in your opinion. IOW, why you >> >> >> >> >> >> > think we need that feature. >> >> >> >> >> >> > >> >> >> >> >> >> >> >> >> >> >> >> How about: >> >> >> >> >> >> >> >> >> >> >> >> PM: Add opportunistic suspend support. >> >> >> >> >> > >> >> >> >> >> > "PM: Opportunistic suspend support" would be sufficient IMO. >> >> >> >> >> > >> >> >> >> >> > Now, I'd start with the motivation. Like "Power management features present >> >> >> >> >> > in the current mainline kernel are insufficient to get maximum possible energy >> >> >> >> >> > savings on some platforms, such as Android, because ..." (here go explanations >> >> >> >> >> > why this is the case in your opinion). >> >> >> >> >> > >> >> >> >> >> > Next, "To allow Android and similar platforms to save more energy than they >> >> >> >> >> > currently can save using the mainline kernel, introduce a mechanism by which >> >> >> >> >> > the system is automatically suspended (i.e. put into a system-wide sleep state) >> >> >> >> >> > whenever it's not doing useful work, called opportunistic suspend". >> >> >> >> >> > >> >> >> >> >> > "For this purpose introduce the suspend blockers framework allowing the >> >> >> >> >> > kernel's power management subsystem to decide when it is desirable to suspend >> >> >> >> >> > the system (i.e. when useful work is not being done). Add an API that ..." >> >> >> >> >> > >> >> >> >> >> >> >> >> >> >> PM: Opportunistic suspend support. >> >> >> >> >> >> >> >> >> >> Power management features present in the current mainline kernel are >> >> >> >> >> insufficient to get maximum possible energy savings on some platforms, >> >> >> >> >> such as Android, because low power states can only safely be entered >> >> >> >> >> from idle. >> >> >> >> > >> >> >> >> > Do you mean CPU low-power states or system low-power states here? >> >> >> >> > >> >> >> >> I think either. >> >> >> > >> >> >> > The statement is not true for system low-power states (or sleep states), >> >> >> > because generally (ie. on many platforms) they aren't entered from idle. >> >> >> > Suspend is for entering them. >> >> >> > >> >> >> I don't think that makes my statement false. If you can only safely >> >> >> enter low power states from idle, but some low power states cannot be >> >> >> entered from idle, then it follows that you cannot safely enter those >> >> >> low power states. >> >> > >> >> > Define "safely", then. >> >> > >> >> OK. Is this clearer: >> > >> > Not really. >> > >> >> Power management features present in the current mainline kernel are >> >> insufficient to get maximum possible energy savings on some platforms, >> >> such as Android, because some wakeup events must work at all times >> >> which means that low power states can only safely be entered from idle. >> > >> > It's not clear what you mean by "some wakeup events must work at all times" >> > and what "safely" means. >> > >> >> Suspend, in its current form, cannot be used, since wakeup events that >> >> occur right after initiating suspend will not be processed until another >> >> possibly unrelated event wake up the system again. >> > >> > Well, I _guess_ I know what you're trying to say, but I'm not sure if that's >> > the core of the problem the patchset is supposed to address. >> > >> > The problem, as I see it, is really two-fold. >> > >> > First, to save as much energy as reasonably possible you need to put everything >> > except for memory (ie. I/O devices and CPUs) into low-power states and let that >> > stay in these low-power states for as long as reasonably possible, right? >> >> Memory should also be in a low power state, but yes, everything should >> be in the lowest power possible state for as long as possible. >> >> > >> > Second, you need the system to _always_ respond to some _specific_ events >> > regardless of its current state, correct? >> > >> > Now, at present, we can put I/O devices and the CPU into low-power states >> > at the same time in two ways: (1) by using runtime PM and cpuidle and (2) by >> > suspending the system. Unfortunately, none of these approaches is ideal, >> > because (1) is vulnerable to periodic timers and polling apps (and CPU-bound >> > apps) and (2) doesn't guarantee that all events you care about will be >> > responded to. >> > >> > The proposed solution is to use suspend with an additional mechanism that >> > will prevent the events that have to be responded to from being lost. This >> > additional mechanism is suspend blockers. >> > >> > Is this correct? >> >> Yes. >> >> > >> >> >> > So, there is a difference and the explanation can go like this: "... to achieve >> >> >> > maximum energy savings one has to put all I/O devices and the CPU into >> >> >> > low-power states, but the CPU can only be put into a low-power state from >> >> >> > idle. This, in turn, means that the CPU leaves the low-power state on >> >> >> > interrupts triggered by periodic timers and user space processes that use >> >> >> > polling. It turns out, however, that many of these events causing the CPU to >> >> >> > leave the low-power state aren't essential for the desired system functionality >> >> >> > and from the power management point of view it would be better if they didn't >> >> >> > occur". >> >> >> >> >> >> This only explain why we still want to use suspend on systems that can >> >> >> enter the same power states from idle and suspend. >> >> > >> >> > Sorry, I'm confused now. Isn't that why you do that on Android? >> >> > >> >> >> >> Yes, but it is not the only reason to use opportunistic support. It is >> >> way more important to have opportunistic suspend support if the >> >> hardware can enter lower power states from suspend than idle. >> > >> > Sure, but you can add something like "There also are systems where some >> > devices cannot be put into low-power states without suspending the entire >> > system (or the low-power states available to them without suspending the >> > entire system are substantially shallower than the low-power states they are >> > put into when the entire system is suspended), so the system have to be >> > suspended as a whole to achieve the maximum energy savings". >> > >> >> Does this work for you: > > Well, almost. > >> PM: Opportunistic suspend support. >> >> Power management features present in the current mainline kernel are >> insufficient to get maximum possible energy savings on some platforms, >> such as Android, > > I'd finish the first sentence here. > >> because the system must always respond to certain >> events. Suspend, in its current form, cannot be used on these >> platforms, > > This doesn't seem to be correct. Surely you can suspend these systems, but > you can't address the problem at hand using suspend as is. > > I'd say (in the second sentence) "The problem is that to save maximum amount of > energy all system hardware components need to be in the lowest-power states > available for as long as reasonably possible, but at the same time the system > must always respond to certain events, regardless of the current state of the > hardware. > > The first goal can be achieved either by using device runtime PM and cpuidle to > put all hardware into low-power states, transparently from the user space point > of view, or by suspending the whole system. However, system suspend, in its > current form, does not guarantee that the events of interest will always be > responded to, since wakeup events ..." > >> since wakeup events (events that wake the CPU from idle and >> the system from suspend) that occur right after initiating suspend >> will not be processed until another possibly unrelated event wake up > > "... wakes up ..." I guess. > >> the system again. >> >> On hardware where idle can enter the same power state as suspend, idle >> combined with runtime PM can be used, but periodic wakeups increase >> the average power consumption. Suspending the system also reduces the >> harm caused by apps that never go idle. There also are systems where >> some devices cannot be put into low-power states without suspending >> the entire system (or the low-power states available to them without >> suspending the entire system are substantially shallower than the >> low-power states they are put into when the entire system is >> suspended), so the system have to be suspended as a whole to achieve >> the maximum energy savings. >> >> To allow Android and similar platforms to save more energy than they >> currently can save using the mainline kernel, introduce a mechanism by >> which the system is automatically suspended (i.e. put into a >> system-wide sleep state) whenever it's not doing useful work, called >> opportunistic suspend. > > I'd say "... whenever it's not doing work that's immediately useful to the > user, called ..." or something like this. > > The rest is fine by me. > PM: Opportunistic suspend support. Power management features present in the current mainline kernel are insufficient to get maximum possible energy savings on some platforms, such as Android. The problem is that to save maximum amount of energy all system hardware components need to be in the lowest-power states available for as long as reasonably possible, but at the same time the system must always respond to certain events, regardless of the current state of the hardware. The first goal can be achieved either by using device runtime PM and cpuidle to put all hardware into low-power states, transparently from the user space point of view, or by suspending the whole system. However, system suspend, in its current form, does not guarantee that the events of interest will always be responded to, since wakeup events (events that wake the CPU from idle and the system from suspend) that occur right after initiating suspend will not be processed until another possibly unrelated event wakes the system up again. On hardware where idle can enter the same power state as suspend, idle combined with runtime PM can be used, but periodic wakeups increase the average power consumption. Suspending the system also reduces the harm caused by apps that never go idle. There also are systems where some devices cannot be put into low-power states without suspending the entire system (or the low-power states available to them without suspending the entire system are substantially shallower than the low-power states they are put into when the entire system is suspended), so the system has to be suspended as a whole to achieve the maximum energy savings. To allow Android and similar platforms to save more energy than they currently can save using the mainline kernel, introduce a mechanism by which the system is automatically suspended (i.e. put into a system-wide sleep state) whenever it's not doing work that's immediately useful to the user, called opportunistic suspend. For this purpose introduce the suspend blockers framework allowing the kernel's power management subsystem to decide when it is desirable to suspend the system (i.e. when the system is not doing anything the user really cares about at the moment and therefore it may be suspended). Add an API that that drivers can use to block opportunistic suspend. This is needed to avoid losing wakeup events that occur right after suspend is initiated. Add /sys/power/policy that selects the behavior 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. -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <AANLkTimoU9BrzbAl7q-LZzGeRolO7gUKBoGjkPWtWn1G@mail.gmail.com>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <AANLkTimoU9BrzbAl7q-LZzGeRolO7gUKBoGjkPWtWn1G@mail.gmail.com> @ 2010-05-20 22:21 ` Rafael J. Wysocki 0 siblings, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-20 22:21 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett On Wednesday 19 May 2010, Arve Hjønnevåg wrote: ... > PM: Opportunistic suspend support. > > Power management features present in the current mainline kernel are > insufficient to get maximum possible energy savings on some platforms, > such as Android. The problem is that to save maximum amount of energy > all system hardware components need to be in the lowest-power states > available for as long as reasonably possible, but at the same time the > system must always respond to certain events, regardless of the > current state of the hardware. > > The first goal can be achieved either by using device runtime PM and > cpuidle to put all hardware into low-power states, transparently from > the user space point of view, or by suspending the whole system. > However, system suspend, in its current form, does not guarantee that > the events of interest will always be responded to, since wakeup > events (events that wake the CPU from idle and the system from > suspend) that occur right after initiating suspend will not be > processed until another possibly unrelated event wakes the system up > again. > > On hardware where idle can enter the same power state as suspend, idle > combined with runtime PM can be used, but periodic wakeups increase > the average power consumption. Suspending the system also reduces the > harm caused by apps that never go idle. There also are systems where > some devices cannot be put into low-power states without suspending > the entire system (or the low-power states available to them without > suspending the entire system are substantially shallower than the > low-power states they are put into when the entire system is > suspended), so the system has to be suspended as a whole to achieve > the maximum energy savings. > > To allow Android and similar platforms to save more energy than they > currently can save using the mainline kernel, introduce a mechanism by > which the system is automatically suspended (i.e. put into a > system-wide sleep state) whenever it's not doing work that's > immediately useful to the user, called opportunistic suspend. > > For this purpose introduce the suspend blockers framework allowing the > kernel's power management subsystem to decide when it is desirable to > suspend the system (i.e. when the system is not doing anything the > user really cares about at the moment and therefore it may be > suspended). Add an API that that drivers can use to block > opportunistic suspend. This is needed to avoid losing wakeup events > that occur right after suspend is initiated. > > Add /sys/power/policy that selects the behavior 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. That looks good to me. Thanks, Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <87tyq5qj3v.fsf@deeprootsystems.com>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <87tyq5qj3v.fsf@deeprootsystems.com> @ 2010-05-18 18:52 ` Rafael J. Wysocki [not found] ` <201005182052.28778.rjw@sisk.pl> 2010-05-19 0:00 ` Arve Hjønnevåg 2 siblings, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-18 18:52 UTC (permalink / raw) To: Kevin Hilman Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett On Tuesday 18 May 2010, Kevin Hilman wrote: > Arve Hjønnevåg <arve@android.com> writes: > > > > > PM: Opportunistic suspend support. > > > > Power management features present in the current mainline kernel are > > insufficient to get maximum possible energy savings on some platforms, > > such as Android, because low power states can only safely be entered > > from idle. Suspend, in its current form, cannot be used, since wakeup > > events that occur right after initiating suspend will not be processed > > until another possibly unrelated event wake up the system again. > > I think the problems with wakeups in the current suspend path need to > be described in more detail. In particular, why check_wakeup_irqs() > is not enough etc. That one is really easy.: because some (the majority of?) architectures don't even implement it. > > On some systems idle combined with runtime PM can enter the same power > > state as suspend, but periodic wakeups increase the average power > > consumption. Suspending the system also reduces the harm caused by > > apps that never go idle. On other systems suspend can enter a much > > lower power state than idle. > > > > To allow Android and similar platforms to save more energy than they > > currently can save using the mainline kernel, we introduce a mechanism > > by which the system is automatically suspended (i.e. put into a > > system-wide sleep state) whenever it's not doing useful work, called > > opportunistic suspend. > > A definition of "useful work" here would provide clarity and would > also help clarify by what criteria other on-going work is determined > to be not useful. Probably "useful" is not the right word here. I guess it's more like "work that can be deferred without visible impact on functionality". Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <201005182052.28778.rjw@sisk.pl>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <201005182052.28778.rjw@sisk.pl> @ 2010-05-18 22:04 ` Kevin Hilman [not found] ` <87y6fgn9y1.fsf@deeprootsystems.com> 1 sibling, 0 replies; 89+ messages in thread From: Kevin Hilman @ 2010-05-18 22:04 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett "Rafael J. Wysocki" <rjw@sisk.pl> writes: > On Tuesday 18 May 2010, Kevin Hilman wrote: >> Arve Hjønnevåg <arve@android.com> writes: >> >> > >> > PM: Opportunistic suspend support. >> > >> > Power management features present in the current mainline kernel are >> > insufficient to get maximum possible energy savings on some platforms, >> > such as Android, because low power states can only safely be entered >> > from idle. Suspend, in its current form, cannot be used, since wakeup >> > events that occur right after initiating suspend will not be processed >> > until another possibly unrelated event wake up the system again. >> >> I think the problems with wakeups in the current suspend path need to >> be described in more detail. In particular, why check_wakeup_irqs() >> is not enough etc. > > That one is really easy.: because some (the majority of?) architectures > don't even implement it. OK, then this problem will still in traditional suspend even after this series, so calling it out as a the problem to be solved but not fixing it doesn't seem right. This problem needs an independent fix, namely implementing check_wakeup_irqs(). That being said, what exactly is there for architectures to implement for check_wakeup_irqs()? IIUC, this all handled by genirq as long as deferred disable (now the default) is used? I suspect the platforms that Android currently cares about already have this functionality. At least OMAP does already. >> > On some systems idle combined with runtime PM can enter the same power >> > state as suspend, but periodic wakeups increase the average power >> > consumption. Suspending the system also reduces the harm caused by >> > apps that never go idle. On other systems suspend can enter a much >> > lower power state than idle. >> > >> > To allow Android and similar platforms to save more energy than they >> > currently can save using the mainline kernel, we introduce a mechanism >> > by which the system is automatically suspended (i.e. put into a >> > system-wide sleep state) whenever it's not doing useful work, called >> > opportunistic suspend. >> >> A definition of "useful work" here would provide clarity and would >> also help clarify by what criteria other on-going work is determined >> to be not useful. > > Probably "useful" is not the right word here. I guess it's more like > "work that can be deferred without visible impact on functionality". OK, then a definition of "visible impact on functionality" should be provided and the critera for determining that. I know this sounds like splitting hairs, but what I'm getting at is that this series implements a brand new method for making decisions about when the system is idle. That fact should be clearly stated and the criteria for making this decision should be clearly described. Kevin ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <87y6fgn9y1.fsf@deeprootsystems.com>]
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <87y6fgn9y1.fsf@deeprootsystems.com> @ 2010-05-18 22:29 ` Rafael J. Wysocki 0 siblings, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-18 22:29 UTC (permalink / raw) To: Kevin Hilman Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett On Wednesday 19 May 2010, Kevin Hilman wrote: > "Rafael J. Wysocki" <rjw@sisk.pl> writes: > > > On Tuesday 18 May 2010, Kevin Hilman wrote: > >> Arve Hjønnevåg <arve@android.com> writes: > >> > >> > > >> > PM: Opportunistic suspend support. > >> > > >> > Power management features present in the current mainline kernel are > >> > insufficient to get maximum possible energy savings on some platforms, > >> > such as Android, because low power states can only safely be entered > >> > from idle. Suspend, in its current form, cannot be used, since wakeup > >> > events that occur right after initiating suspend will not be processed > >> > until another possibly unrelated event wake up the system again. > >> > >> I think the problems with wakeups in the current suspend path need to > >> be described in more detail. In particular, why check_wakeup_irqs() > >> is not enough etc. > > > > That one is really easy.: because some (the majority of?) architectures > > don't even implement it. > > OK, then this problem will still in traditional suspend even after > this series, so calling it out as a the problem to be solved but not > fixing it doesn't seem right. > > This problem needs an independent fix, namely implementing > check_wakeup_irqs(). No, it is not. There's nothing like wake-up interrupts on (ACPI-based) x86 PCs. > That being said, what exactly is there for architectures to implement > for check_wakeup_irqs()? IIUC, this all handled by genirq as long as > deferred disable (now the default) is used? No. Wakeup IRQs cause the system to wake up from sleep states. On a PC the only interrupts that can do that are PCIe root port PME interrupts, but they are not really "device" interrupts (ie. they come from a source that is different from a device signaling wakeup). > I suspect the platforms that Android currently cares about already > have this functionality. At least OMAP does already. ISTR there is an x86 Android port, so not all of them. Although that really doesn't matter. > >> > On some systems idle combined with runtime PM can enter the same power > >> > state as suspend, but periodic wakeups increase the average power > >> > consumption. Suspending the system also reduces the harm caused by > >> > apps that never go idle. On other systems suspend can enter a much > >> > lower power state than idle. > >> > > >> > To allow Android and similar platforms to save more energy than they > >> > currently can save using the mainline kernel, we introduce a mechanism > >> > by which the system is automatically suspended (i.e. put into a > >> > system-wide sleep state) whenever it's not doing useful work, called > >> > opportunistic suspend. > >> > >> A definition of "useful work" here would provide clarity and would > >> also help clarify by what criteria other on-going work is determined > >> to be not useful. > > > > Probably "useful" is not the right word here. I guess it's more like > > "work that can be deferred without visible impact on functionality". > > OK, then a definition of "visible impact on functionality" should be > provided and the critera for determining that. > > I know this sounds like splitting hairs, Yes, it does. > but what I'm getting at is that this series implements a brand new method > for making decisions about when the system is idle. Since we are splitting hairs, I'd be rather cautious about the word "idle". It would be safer to say "when the system is not doing anything the user really cares about at the moment and therefore it may be suspended". That actually is the whole point of the patch series. > That fact should be clearly stated and the criteria for making this decision > should be clearly described. Well, suspend blockers are the tool to define the criteria. Thanks, Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 0/8] Suspend block api (version 7) [not found] ` <87tyq5qj3v.fsf@deeprootsystems.com> 2010-05-18 18:52 ` Rafael J. Wysocki [not found] ` <201005182052.28778.rjw@sisk.pl> @ 2010-05-19 0:00 ` Arve Hjønnevåg 2 siblings, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-19 0:00 UTC (permalink / raw) To: Kevin Hilman Cc: Mark Brown, Theodore Ts'o, Brian Swetland, Greg KH, linux-kernel, linux-pm, Matthew Garrett 2010/5/18 Kevin Hilman <khilman@deeprootsystems.com>: > Arve Hjønnevåg <arve@android.com> writes: > >> >> PM: Opportunistic suspend support. >> >> Power management features present in the current mainline kernel are >> insufficient to get maximum possible energy savings on some platforms, >> such as Android, because low power states can only safely be entered >> from idle. Suspend, in its current form, cannot be used, since wakeup >> events that occur right after initiating suspend will not be processed >> until another possibly unrelated event wake up the system again. > > I think the problems with wakeups in the current suspend path need to > be described in more detail. In particular, why check_wakeup_irqs() > is not enough etc. > check_wakeup_irqs only handles interrupts that occurred after the interrupt was masked during suspend. If the interrupt occurred before it was masked, it will not be pending when check_wakeup_irqs is called. >> On some systems idle combined with runtime PM can enter the same power >> state as suspend, but periodic wakeups increase the average power >> consumption. Suspending the system also reduces the harm caused by >> apps that never go idle. On other systems suspend can enter a much >> lower power state than idle. >> >> To allow Android and similar platforms to save more energy than they >> currently can save using the mainline kernel, we introduce a mechanism >> by which the system is automatically suspended (i.e. put into a >> system-wide sleep state) whenever it's not doing useful work, called >> opportunistic suspend. > > A definition of "useful work" here would provide clarity and would > also help clarify by what criteria other on-going work is determined > to be not useful. > > Kevin > -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <Pine.LNX.4.44L0.1005261815480.1328-100000@iolanthe.rowland.org>]
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] <Pine.LNX.4.44L0.1005261815480.1328-100000@iolanthe.rowland.org> @ 2010-05-26 22:34 ` Rafael J. Wysocki 0 siblings, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-26 22:34 UTC (permalink / raw) To: Alan Stern Cc: Len Brown, Jim Collar, linux-doc, Peter Zijlstra, Greg Kroah-Hartman, linux-kernel, Avi Kivity, Ryusuke Konishi, Magnus Damm, linux-pm, Andrew Morton On Thursday 27 May 2010, Alan Stern wrote: > On Wed, 26 May 2010, Rafael J. Wysocki wrote: > > > On Wednesday 26 May 2010, Peter Zijlstra wrote: > > > On Fri, 2010-05-21 at 15:46 -0700, Arve Hjønnevåg wrote: > > > > +To create a suspend blocker from user space, open the suspend_blocker > > > > special > > > > +device file: > > > > + > > > > + fd = open("/dev/suspend_blocker", O_RDWR | O_CLOEXEC); > > > > + > > > > +then optionally call: > > > > + > > > > + ioctl(fd, SUSPEND_BLOCKER_IOCTL_SET_NAME(strlen(name)), name); > > > > + > > > > +To activate the suspend blocker call: > > > > + > > > > + ioctl(fd, SUSPEND_BLOCKER_IOCTL_BLOCK); > > > > + > > > > +To deactivate it call: > > > > + > > > > + ioctl(fd, SUSPEND_BLOCKER_IOCTL_UNBLOCK); > > > > + > > > > +To destroy the suspend blocker, close the device: > > > > + > > > > + close(fd); > > > > > > Urgh, please let the open() be BLOCK, the close() be UNBLOCK, and keep > > > the SET_NAME thing if you really care. > > > > SET_NAME wouldn't serve any purpose in that case. > > > > This whole thing is related to the statistics part, which Arve says is > > essential to him. He wants to collect statistics for each suspend blocker > > activated and deactivated so that he can tell who's causing problems by > > blocking suspend too often. The name also is a part of this. > > > > In fact, without the statistics part the whole thing might be implemented > > as a single reference counter such that suspend would happen when it went down > > to zero. > > There's also Arve's other main point: These suspend blockers tend to > get used quite a lot. Opening and closing a file each time has much > higher overhead than a simple ioctl. > > All these topics have been covered earlier in this discussion. Peter > should go back and read the emails in the linux-pm archive. Yeah. Although with a reference counter the special device file won't be necessary. Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <201005262357.28933.rjw@sisk.pl>]
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] <201005262357.28933.rjw@sisk.pl> @ 2010-05-26 22:18 ` Alan Stern 2010-05-26 22:18 ` Alan Stern 1 sibling, 0 replies; 89+ messages in thread From: Alan Stern @ 2010-05-26 22:18 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Len Brown, Jim Collar, linux-doc, Peter Zijlstra, Greg Kroah-Hartman, linux-kernel, Avi Kivity, Ryusuke Konishi, Magnus Damm, linux-pm, Andrew Morton On Wed, 26 May 2010, Rafael J. Wysocki wrote: > On Wednesday 26 May 2010, Peter Zijlstra wrote: > > On Fri, 2010-05-21 at 15:46 -0700, Arve Hjønnevåg wrote: > > > +To create a suspend blocker from user space, open the suspend_blocker > > > special > > > +device file: > > > + > > > + fd = open("/dev/suspend_blocker", O_RDWR | O_CLOEXEC); > > > + > > > +then optionally call: > > > + > > > + ioctl(fd, SUSPEND_BLOCKER_IOCTL_SET_NAME(strlen(name)), name); > > > + > > > +To activate the suspend blocker call: > > > + > > > + ioctl(fd, SUSPEND_BLOCKER_IOCTL_BLOCK); > > > + > > > +To deactivate it call: > > > + > > > + ioctl(fd, SUSPEND_BLOCKER_IOCTL_UNBLOCK); > > > + > > > +To destroy the suspend blocker, close the device: > > > + > > > + close(fd); > > > > Urgh, please let the open() be BLOCK, the close() be UNBLOCK, and keep > > the SET_NAME thing if you really care. > > SET_NAME wouldn't serve any purpose in that case. > > This whole thing is related to the statistics part, which Arve says is > essential to him. He wants to collect statistics for each suspend blocker > activated and deactivated so that he can tell who's causing problems by > blocking suspend too often. The name also is a part of this. > > In fact, without the statistics part the whole thing might be implemented > as a single reference counter such that suspend would happen when it went down > to zero. There's also Arve's other main point: These suspend blockers tend to get used quite a lot. Opening and closing a file each time has much higher overhead than a simple ioctl. All these topics have been covered earlier in this discussion. Peter should go back and read the emails in the linux-pm archive. Alan Stern ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] <201005262357.28933.rjw@sisk.pl> 2010-05-26 22:18 ` Alan Stern @ 2010-05-26 22:18 ` Alan Stern 1 sibling, 0 replies; 89+ messages in thread From: Alan Stern @ 2010-05-26 22:18 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Len Brown, Jim Collar, linux-doc, Peter Zijlstra, Greg Kroah-Hartman, linux-kernel, Avi Kivity, Ryusuke Konishi, Magnus Damm, linux-pm, Andrew Morton On Wed, 26 May 2010, Rafael J. Wysocki wrote: > On Wednesday 26 May 2010, Peter Zijlstra wrote: > > On Fri, 2010-05-21 at 15:46 -0700, Arve Hjønnevåg wrote: > > > +To create a suspend blocker from user space, open the suspend_blocker > > > special > > > +device file: > > > + > > > + fd = open("/dev/suspend_blocker", O_RDWR | O_CLOEXEC); > > > + > > > +then optionally call: > > > + > > > + ioctl(fd, SUSPEND_BLOCKER_IOCTL_SET_NAME(strlen(name)), name); > > > + > > > +To activate the suspend blocker call: > > > + > > > + ioctl(fd, SUSPEND_BLOCKER_IOCTL_BLOCK); > > > + > > > +To deactivate it call: > > > + > > > + ioctl(fd, SUSPEND_BLOCKER_IOCTL_UNBLOCK); > > > + > > > +To destroy the suspend blocker, close the device: > > > + > > > + close(fd); > > > > Urgh, please let the open() be BLOCK, the close() be UNBLOCK, and keep > > the SET_NAME thing if you really care. > > SET_NAME wouldn't serve any purpose in that case. > > This whole thing is related to the statistics part, which Arve says is > essential to him. He wants to collect statistics for each suspend blocker > activated and deactivated so that he can tell who's causing problems by > blocking suspend too often. The name also is a part of this. > > In fact, without the statistics part the whole thing might be implemented > as a single reference counter such that suspend would happen when it went down > to zero. There's also Arve's other main point: These suspend blockers tend to get used quite a lot. Opening and closing a file each time has much higher overhead than a simple ioctl. All these topics have been covered earlier in this discussion. Peter should go back and read the emails in the linux-pm archive. Alan Stern ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <1274482015-30899-1-git-send-email-arve@android.com>]
[parent not found: <1274482015-30899-2-git-send-email-arve@android.com>]
* [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <1274482015-30899-2-git-send-email-arve@android.com> @ 2010-05-21 22:46 ` Arve Hjønnevåg [not found] ` <1274482015-30899-3-git-send-email-arve@android.com> 1 sibling, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-21 22:46 UTC (permalink / raw) To: linux-pm, linux-kernel Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, Avi Kivity, Ryusuke Konishi, Magnus Damm, Andrew Morton Add a misc device, "suspend_blocker", that allows user-space processes to block automatic suspend. Opening this device creates a suspend blocker that can be used by the opener to prevent automatic suspend from occurring. There are ioctls provided for blocking and unblocking suspend and for giving the suspend blocker a meaningful name. Closing the device special file causes the suspend blocker to be destroyed. For example, when select or poll indicates that input event are available, this interface can be used by user space to block suspend before it reads those events. This allows the input driver to release its suspend blocker as soon as the event queue is empty. If user space could not use a suspend blocker here the input driver would need to delay the release of its suspend blocker until it knows (or assumes) that user space has finished processing the events. By careful use of suspend blockers in drivers and user space system code, one can arrange for the system to stay awake for extremely short periods of time in reaction to events, rapidly returning to a fully suspended state. Signed-off-by: Arve Hjønnevåg <arve@android.com> --- Documentation/ioctl/ioctl-number.txt | 3 +- Documentation/power/opportunistic-suspend.txt | 27 +++++ include/linux/suspend_ioctls.h | 4 + kernel/power/Kconfig | 7 ++ kernel/power/Makefile | 1 + kernel/power/user_suspend_blocker.c | 143 +++++++++++++++++++++++++ 6 files changed, 184 insertions(+), 1 deletions(-) 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 4bee7bc..93f4c24 100644 --- a/Documentation/power/opportunistic-suspend.txt +++ b/Documentation/power/opportunistic-suspend.txt @@ -127,3 +127,30 @@ if (list_empty(&state->pending_work)) suspend_unblock(&state->suspend_blocker); else suspend_block(&state->suspend_blocker); + +User space API +============== + +To create a suspend blocker from user space, open the suspend_blocker special +device file: + + fd = open("/dev/suspend_blocker", O_RDWR | O_CLOEXEC); + +then optionally call: + + ioctl(fd, SUSPEND_BLOCKER_IOCTL_SET_NAME(strlen(name)), name); + +To activate the suspend blocker call: + + ioctl(fd, SUSPEND_BLOCKER_IOCTL_BLOCK); + +To deactivate it call: + + ioctl(fd, SUSPEND_BLOCKER_IOCTL_UNBLOCK); + +To destroy the suspend blocker, close the device: + + close(fd); + +If the first ioctl called is not SUSPEND_BLOCKER_IOCTL_SET_NAME the suspend +blocker will get the default name "(userspace)". diff --git a/include/linux/suspend_ioctls.h b/include/linux/suspend_ioctls.h index 0b30382..b95a6b2 100644 --- a/include/linux/suspend_ioctls.h +++ b/include/linux/suspend_ioctls.h @@ -30,4 +30,8 @@ struct resume_swap_area { #define SNAPSHOT_ALLOC_SWAP_PAGE _IOR(SNAPSHOT_IOC_MAGIC, 20, __kernel_loff_t) #define SNAPSHOT_IOC_MAXNR 20 +#define SUSPEND_BLOCKER_IOCTL_SET_NAME(len) _IOC(_IOC_WRITE, 's', 0, len) +#define SUSPEND_BLOCKER_IOCTL_BLOCK _IO('s', 1) +#define SUSPEND_BLOCKER_IOCTL_UNBLOCK _IO('s', 2) + #endif /* _LINUX_SUSPEND_IOCTLS_H */ diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 6d11a45..2e665cd 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -146,6 +146,13 @@ 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 "User space suspend blockers" + depends on OPPORTUNISTIC_SUSPEND + ---help--- + User space suspend blockers API. Creates a misc device allowing user + space to create, use and destroy suspend blockers. + config HIBERNATION_NVS bool diff --git a/kernel/power/Makefile b/kernel/power/Makefile index 95d8e6d..2015594 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) += opportunistic_suspend.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..d53f939 --- /dev/null +++ b/kernel/power/user_suspend_blocker.c @@ -0,0 +1,143 @@ +/* + * kernel/power/user_suspend_blocker.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.h> +#include <linux/suspend_ioctls.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); + +#define USER_SUSPEND_BLOCKER_NAME_LEN 31 + +struct user_suspend_blocker { + struct suspend_blocker blocker; + char name[USER_SUSPEND_BLOCKER_NAME_LEN + 1]; + bool registered; +}; + +static int user_suspend_blocker_open(struct inode *inode, struct file *filp) +{ + struct user_suspend_blocker *blocker; + + blocker = kzalloc(sizeof(*blocker), GFP_KERNEL); + if (!blocker) + return -ENOMEM; + + nonseekable_open(inode, filp); + strcpy(blocker->name, "(userspace)"); + blocker->blocker.name = blocker->name; + filp->private_data = blocker; + + return 0; +} + +static int suspend_blocker_set_name(struct user_suspend_blocker *blocker, + void __user *name, size_t name_len) +{ + if (blocker->registered) + return -EBUSY; + + if (name_len > USER_SUSPEND_BLOCKER_NAME_LEN) + name_len = USER_SUSPEND_BLOCKER_NAME_LEN; + + if (copy_from_user(blocker->name, name, name_len)) + return -EFAULT; + blocker->name[name_len] = '\0'; + + return 0; +} + +static long user_suspend_blocker_ioctl(struct file *filp, unsigned int cmd, + unsigned long _arg) +{ + void __user *arg = (void __user *)_arg; + struct user_suspend_blocker *blocker = filp->private_data; + long ret = 0; + + mutex_lock(&ioctl_lock); + if ((cmd & ~IOCSIZE_MASK) == SUSPEND_BLOCKER_IOCTL_SET_NAME(0)) { + ret = suspend_blocker_set_name(blocker, arg, _IOC_SIZE(cmd)); + goto done; + } + if (!blocker->registered) { + suspend_blocker_register(&blocker->blocker); + blocker->registered = true; + } + switch (cmd) { + case SUSPEND_BLOCKER_IOCTL_BLOCK: + suspend_block(&blocker->blocker); + break; + + case SUSPEND_BLOCKER_IOCTL_UNBLOCK: + suspend_unblock(&blocker->blocker); + break; + + default: + ret = -ENOTTY; + } +done: + if (ret && (debug_mask & DEBUG_FAILURE)) + pr_err("user_suspend_blocker_ioctl: cmd %x failed, %ld\n", + cmd, ret); + mutex_unlock(&ioctl_lock); + return ret; +} + +static int user_suspend_blocker_release(struct inode *inode, struct file *filp) +{ + struct user_suspend_blocker *blocker = filp->private_data; + + if (blocker->registered) + suspend_blocker_unregister(&blocker->blocker); + kfree(blocker); + + return 0; +} + +const struct file_operations user_suspend_blocker_fops = { + .open = user_suspend_blocker_open, + .release = user_suspend_blocker_release, + .unlocked_ioctl = user_suspend_blocker_ioctl, +}; + +struct miscdevice user_suspend_blocker_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "suspend_blocker", + .fops = &user_suspend_blocker_fops, +}; + +static int __init user_suspend_blocker_init(void) +{ + return misc_register(&user_suspend_blocker_device); +} + +static void __exit user_suspend_blocker_exit(void) +{ + misc_deregister(&user_suspend_blocker_device); +} + +module_init(user_suspend_blocker_init); +module_exit(user_suspend_blocker_exit); -- 1.6.5.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] 89+ messages in thread
[parent not found: <1274482015-30899-3-git-send-email-arve@android.com>]
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <1274482015-30899-3-git-send-email-arve@android.com> @ 2010-05-26 8:43 ` Peter Zijlstra [not found] ` <1274863428.5882.4860.camel@twins> 1 sibling, 0 replies; 89+ messages in thread From: Peter Zijlstra @ 2010-05-26 8:43 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, linux-kernel, Avi Kivity, Ryusuke Konishi, Magnus Damm, linux-pm, Andrew Morton On Fri, 2010-05-21 at 15:46 -0700, Arve Hjønnevåg wrote: > +To create a suspend blocker from user space, open the suspend_blocker > special > +device file: > + > + fd = open("/dev/suspend_blocker", O_RDWR | O_CLOEXEC); > + > +then optionally call: > + > + ioctl(fd, SUSPEND_BLOCKER_IOCTL_SET_NAME(strlen(name)), name); > + > +To activate the suspend blocker call: > + > + ioctl(fd, SUSPEND_BLOCKER_IOCTL_BLOCK); > + > +To deactivate it call: > + > + ioctl(fd, SUSPEND_BLOCKER_IOCTL_UNBLOCK); > + > +To destroy the suspend blocker, close the device: > + > + close(fd); Urgh, please let the open() be BLOCK, the close() be UNBLOCK, and keep the SET_NAME thing if you really care. _______________________________________________ linux-pm mailing list linux-pm@lists.linux-foundation.org https://lists.linux-foundation.org/mailman/listinfo/linux-pm ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <1274863428.5882.4860.camel@twins>]
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <1274863428.5882.4860.camel@twins> @ 2010-05-26 10:47 ` Arve Hjønnevåg [not found] ` <AANLkTimTnzK1ByG2bE2gGjINxD_Pbvez7PFHo7Kzo9yk@mail.gmail.com> 2010-05-26 21:57 ` Rafael J. Wysocki 2 siblings, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-26 10:47 UTC (permalink / raw) To: Peter Zijlstra Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, linux-kernel, Avi Kivity, Ryusuke Konishi, Magnus Damm, linux-pm, Andrew Morton 2010/5/26 Peter Zijlstra <peterz@infradead.org>: > On Fri, 2010-05-21 at 15:46 -0700, Arve Hjønnevåg wrote: >> +To create a suspend blocker from user space, open the suspend_blocker >> special >> +device file: >> + >> + fd = open("/dev/suspend_blocker", O_RDWR | O_CLOEXEC); >> + >> +then optionally call: >> + >> + ioctl(fd, SUSPEND_BLOCKER_IOCTL_SET_NAME(strlen(name)), name); >> + >> +To activate the suspend blocker call: >> + >> + ioctl(fd, SUSPEND_BLOCKER_IOCTL_BLOCK); >> + >> +To deactivate it call: >> + >> + ioctl(fd, SUSPEND_BLOCKER_IOCTL_UNBLOCK); >> + >> +To destroy the suspend blocker, close the device: >> + >> + close(fd); > > Urgh, please let the open() be BLOCK, the close() be UNBLOCK, and keep > the SET_NAME thing if you really care. > That would be very inefficient. -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <AANLkTimTnzK1ByG2bE2gGjINxD_Pbvez7PFHo7Kzo9yk@mail.gmail.com>]
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <AANLkTimTnzK1ByG2bE2gGjINxD_Pbvez7PFHo7Kzo9yk@mail.gmail.com> @ 2010-05-26 10:50 ` Peter Zijlstra 2010-05-26 10:51 ` Florian Mickler ` (2 subsequent siblings) 3 siblings, 0 replies; 89+ messages in thread From: Peter Zijlstra @ 2010-05-26 10:50 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, linux-kernel, Avi Kivity, Ryusuke Konishi, Magnus Damm, linux-pm, Andrew Morton On Wed, 2010-05-26 at 03:47 -0700, Arve Hjønnevåg wrote: > 2010/5/26 Peter Zijlstra <peterz@infradead.org>: > > On Fri, 2010-05-21 at 15:46 -0700, Arve Hjønnevåg wrote: > >> +To create a suspend blocker from user space, open the suspend_blocker > >> special > >> +device file: > >> + > >> + fd = open("/dev/suspend_blocker", O_RDWR | O_CLOEXEC); > >> + > >> +then optionally call: > >> + > >> + ioctl(fd, SUSPEND_BLOCKER_IOCTL_SET_NAME(strlen(name)), name); > >> + > >> +To activate the suspend blocker call: > >> + > >> + ioctl(fd, SUSPEND_BLOCKER_IOCTL_BLOCK); > >> + > >> +To deactivate it call: > >> + > >> + ioctl(fd, SUSPEND_BLOCKER_IOCTL_UNBLOCK); > >> + > >> +To destroy the suspend blocker, close the device: > >> + > >> + close(fd); > > > > Urgh, please let the open() be BLOCK, the close() be UNBLOCK, and keep > > the SET_NAME thing if you really care. > > > > That would be very inefficient. How so? Anyway, since you admitted this thing isn't needed at all, I say we remove it altogether. _______________________________________________ linux-pm mailing list linux-pm@lists.linux-foundation.org https://lists.linux-foundation.org/mailman/listinfo/linux-pm ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <AANLkTimTnzK1ByG2bE2gGjINxD_Pbvez7PFHo7Kzo9yk@mail.gmail.com> 2010-05-26 10:50 ` Peter Zijlstra @ 2010-05-26 10:51 ` Florian Mickler [not found] ` <20100526125136.53f2dc82@schatten.dmk.lab> [not found] ` <1274871005.5882.5315.camel@twins> 3 siblings, 0 replies; 89+ messages in thread From: Florian Mickler @ 2010-05-26 10:51 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Len Brown, Jim Collar, Peter Zijlstra, Nigel, Kroah-Hartman, linux-doc, linux-kernel, Andrew, Greg, Avi Kivity, Ryusuke Konishi, Magnus Damm, linux-pm, Morton On Wed, 26 May 2010 03:47:27 -0700 Arve Hjønnevåg <arve@android.com> wrote: > 2010/5/26 Peter Zijlstra <peterz@infradead.org>: > > On Fri, 2010-05-21 at 15:46 -0700, Arve Hjønnevåg wrote: > >> +To create a suspend blocker from user space, open the suspend_blocker > >> special > >> +device file: > >> + > >> + fd = open("/dev/suspend_blocker", O_RDWR | O_CLOEXEC); > >> + > >> +then optionally call: > >> + > >> + ioctl(fd, SUSPEND_BLOCKER_IOCTL_SET_NAME(strlen(name)), name); > >> + > >> +To activate the suspend blocker call: > >> + > >> + ioctl(fd, SUSPEND_BLOCKER_IOCTL_BLOCK); > >> + > >> +To deactivate it call: > >> + > >> + ioctl(fd, SUSPEND_BLOCKER_IOCTL_UNBLOCK); > >> + > >> +To destroy the suspend blocker, close the device: > >> + > >> + close(fd); > > > > Urgh, please let the open() be BLOCK, the close() be UNBLOCK, and keep > > the SET_NAME thing if you really care. > > > > That would be very inefficient. > Also I think it is intended to enforce named suspend blockers. (For debugging/accounting purposes). Cheers, Flo ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <20100526125136.53f2dc82@schatten.dmk.lab>]
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <20100526125136.53f2dc82@schatten.dmk.lab> @ 2010-05-26 11:06 ` Peter Zijlstra 0 siblings, 0 replies; 89+ messages in thread From: Peter Zijlstra @ 2010-05-26 11:06 UTC (permalink / raw) To: Florian Mickler Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, linux-kernel, Avi Kivity, Ryusuke Konishi, Magnus Damm, linux-pm, Andrew Morton On Wed, 2010-05-26 at 12:51 +0200, Florian Mickler wrote: > On Wed, 26 May 2010 03:47:27 -0700 > Arve Hjønnevåg <arve@android.com> wrote: > > > 2010/5/26 Peter Zijlstra <peterz@infradead.org>: > > > On Fri, 2010-05-21 at 15:46 -0700, Arve Hjønnevåg wrote: > > >> +To create a suspend blocker from user space, open the suspend_blocker > > >> special > > >> +device file: > > >> + > > >> + fd = open("/dev/suspend_blocker", O_RDWR | O_CLOEXEC); > > >> + > > >> +then optionally call: > > >> + > > >> + ioctl(fd, SUSPEND_BLOCKER_IOCTL_SET_NAME(strlen(name)), name); > > >> + > > >> +To activate the suspend blocker call: > > >> + > > >> + ioctl(fd, SUSPEND_BLOCKER_IOCTL_BLOCK); > > >> + > > >> +To deactivate it call: > > >> + > > >> + ioctl(fd, SUSPEND_BLOCKER_IOCTL_UNBLOCK); > > >> + > > >> +To destroy the suspend blocker, close the device: > > >> + > > >> + close(fd); > > > > > > Urgh, please let the open() be BLOCK, the close() be UNBLOCK, and keep > > > the SET_NAME thing if you really care. > > > > > > > That would be very inefficient. > > > > Also I think it is intended to enforce named suspend blockers. (For > debugging/accounting purposes). I don't think the code as proposed mandates you SET_NAME, and I didn't propose killing that off, you can still SET_NAME after you open() and acquire the thing. Anyway, the whole point is moot since its simply not needed at all. _______________________________________________ linux-pm mailing list linux-pm@lists.linux-foundation.org https://lists.linux-foundation.org/mailman/listinfo/linux-pm ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <1274871005.5882.5315.camel@twins>]
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <1274871005.5882.5315.camel@twins> @ 2010-05-26 23:13 ` Arve Hjønnevåg 0 siblings, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-26 23:13 UTC (permalink / raw) To: Peter Zijlstra Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, linux-kernel, Avi Kivity, Ryusuke Konishi, Magnus Damm, linux-pm, Andrew Morton 2010/5/26 Peter Zijlstra <peterz@infradead.org>: > On Wed, 2010-05-26 at 03:47 -0700, Arve Hjønnevåg wrote: >> 2010/5/26 Peter Zijlstra <peterz@infradead.org>: >> > On Fri, 2010-05-21 at 15:46 -0700, Arve Hjønnevåg wrote: >> >> +To create a suspend blocker from user space, open the suspend_blocker >> >> special >> >> +device file: >> >> + >> >> + fd = open("/dev/suspend_blocker", O_RDWR | O_CLOEXEC); >> >> + >> >> +then optionally call: >> >> + >> >> + ioctl(fd, SUSPEND_BLOCKER_IOCTL_SET_NAME(strlen(name)), name); >> >> + >> >> +To activate the suspend blocker call: >> >> + >> >> + ioctl(fd, SUSPEND_BLOCKER_IOCTL_BLOCK); >> >> + >> >> +To deactivate it call: >> >> + >> >> + ioctl(fd, SUSPEND_BLOCKER_IOCTL_UNBLOCK); >> >> + >> >> +To destroy the suspend blocker, close the device: >> >> + >> >> + close(fd); >> > >> > Urgh, please let the open() be BLOCK, the close() be UNBLOCK, and keep >> > the SET_NAME thing if you really care. >> > >> >> That would be very inefficient. > > How so? Anyway, since you admitted this thing isn't needed at all, I say > we remove it altogether. > I also said it was useful. I don't think we should drop it just because we can work around its absence. -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <1274863428.5882.4860.camel@twins> 2010-05-26 10:47 ` Arve Hjønnevåg [not found] ` <AANLkTimTnzK1ByG2bE2gGjINxD_Pbvez7PFHo7Kzo9yk@mail.gmail.com> @ 2010-05-26 21:57 ` Rafael J. Wysocki 2 siblings, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-26 21:57 UTC (permalink / raw) To: Peter Zijlstra, Cornelia Huck Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, linux-kernel, Avi Kivity, Ryusuke Konishi, Magnus Damm, linux-pm, Andrew Morton On Wednesday 26 May 2010, Peter Zijlstra wrote: > On Fri, 2010-05-21 at 15:46 -0700, Arve Hjønnevåg wrote: > > +To create a suspend blocker from user space, open the suspend_blocker > > special > > +device file: > > + > > + fd = open("/dev/suspend_blocker", O_RDWR | O_CLOEXEC); > > + > > +then optionally call: > > + > > + ioctl(fd, SUSPEND_BLOCKER_IOCTL_SET_NAME(strlen(name)), name); > > + > > +To activate the suspend blocker call: > > + > > + ioctl(fd, SUSPEND_BLOCKER_IOCTL_BLOCK); > > + > > +To deactivate it call: > > + > > + ioctl(fd, SUSPEND_BLOCKER_IOCTL_UNBLOCK); > > + > > +To destroy the suspend blocker, close the device: > > + > > + close(fd); > > Urgh, please let the open() be BLOCK, the close() be UNBLOCK, and keep > the SET_NAME thing if you really care. SET_NAME wouldn't serve any purpose in that case. This whole thing is related to the statistics part, which Arve says is essential to him. He wants to collect statistics for each suspend blocker activated and deactivated so that he can tell who's causing problems by blocking suspend too often. The name also is a part of this. In fact, without the statistics part the whole thing might be implemented as a single reference counter such that suspend would happen when it went down to zero. 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] 89+ messages in thread
[parent not found: <Pine.LNX.4.44L0.1005021755320.30701-100000@netrider.rowland.org>]
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] <Pine.LNX.4.44L0.1005021755320.30701-100000@netrider.rowland.org> @ 2010-05-03 15:03 ` Rafael J. Wysocki [not found] ` <201005031703.11448.rjw@sisk.pl> 1 sibling, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-03 15:03 UTC (permalink / raw) To: Alan Stern Cc: Len Brown, Jim Collar, linux-doc, Kernel development list, Greg Kroah-Hartman, Oleg Nesterov, Avi Kivity, Ryusuke Konishi, Tejun Heo, Linux-pm mailing list, Andrew Morton On Sunday 02 May 2010, Alan Stern wrote: > On Sun, 2 May 2010, Rafael J. Wysocki wrote: > > > 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? > > Open the file twice, thereby obtaining two file handles. Well, that's what I thought. I must admit I'm not really comfortable with this interface. IMO it would be better if _open() created the suspend blocker giving it a name based on the name of the process that called it. Something like "<process name>_<timestamp>" might work at first sight. Alternatively, "<process_name><number>", where <number> is 0 for the first suspend blocker created by the given process, 1 for the second one etc., also seems to be doable. Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <201005031703.11448.rjw@sisk.pl>]
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <201005031703.11448.rjw@sisk.pl> @ 2010-05-03 21:26 ` Arve Hjønnevåg [not found] ` <m2yd6200be21005031426n87ea43a0k968fd5898ce0b873@mail.gmail.com> 2010-05-04 4:16 ` Pavel Machek 2 siblings, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-03 21:26 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, Kernel development list, Oleg Nesterov, Avi Kivity, Ryusuke Konishi, Tejun Heo, Linux-pm mailing list, Andrew Morton On Mon, May 3, 2010 at 8:03 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > On Sunday 02 May 2010, Alan Stern wrote: >> On Sun, 2 May 2010, Rafael J. Wysocki wrote: >> >> > 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? >> >> Open the file twice, thereby obtaining two file handles. > > Well, that's what I thought. > > I must admit I'm not really comfortable with this interface. IMO it would > be better if _open() created the suspend blocker giving it a name based on > the name of the process that called it. Something like > "<process name>_<timestamp>" might work at first sight. > > Alternatively, "<process_name><number>", where <number> is 0 for the first > suspend blocker created by the given process, 1 for the second one etc., also > seems to be doable. I think it is important to let user-space specify the name. If a process uses multiple suspend blockers, it is impossible to tell what each one is used for if they are automatically named. -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <m2yd6200be21005031426n87ea43a0k968fd5898ce0b873@mail.gmail.com>]
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <m2yd6200be21005031426n87ea43a0k968fd5898ce0b873@mail.gmail.com> @ 2010-05-03 21:49 ` Rafael J. Wysocki [not found] ` <201005032349.00876.rjw@sisk.pl> 1 sibling, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-03 21:49 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, Kernel development list, Oleg Nesterov, Avi Kivity, Ryusuke Konishi, Tejun Heo, Linux-pm mailing list, Andrew Morton On Monday 03 May 2010, Arve Hjønnevåg wrote: > On Mon, May 3, 2010 at 8:03 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > > On Sunday 02 May 2010, Alan Stern wrote: > >> On Sun, 2 May 2010, Rafael J. Wysocki wrote: > >> > >> > 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? > >> > >> Open the file twice, thereby obtaining two file handles. > > > > Well, that's what I thought. > > > > I must admit I'm not really comfortable with this interface. IMO it would > > be better if _open() created the suspend blocker giving it a name based on > > the name of the process that called it. Something like > > "<process name>_<timestamp>" might work at first sight. > > > > Alternatively, "<process_name><number>", where <number> is 0 for the first > > suspend blocker created by the given process, 1 for the second one etc., also > > seems to be doable. > > I think it is important to let user-space specify the name. If a > process uses multiple suspend blockers, it is impossible to tell what > each one is used for if they are automatically named. Well, the problem is the only purpose of this is user space debugging, isn't it? Now, while I don't think it's generally bad to provide kernel interfaces helping to debug user space, I'm not quite sure if that should be done at the expense of the clarity of kernel-user space interfaces. I wonder how many cases there are in which distinguishing between suspend blockers used by the same user space task is practically relevant. Thanks, Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <201005032349.00876.rjw@sisk.pl>]
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <201005032349.00876.rjw@sisk.pl> @ 2010-05-03 22:01 ` Arve Hjønnevåg [not found] ` <x2id6200be21005031501p7f151324wb8bbf928bc2cb25e@mail.gmail.com> 1 sibling, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-05-03 22:01 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, Kernel development list, Oleg Nesterov, Avi Kivity, Ryusuke Konishi, Tejun Heo, Linux-pm mailing list, Andrew Morton 2010/5/3 Rafael J. Wysocki <rjw@sisk.pl>: > On Monday 03 May 2010, Arve Hjønnevåg wrote: >> On Mon, May 3, 2010 at 8:03 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote: >> > On Sunday 02 May 2010, Alan Stern wrote: >> >> On Sun, 2 May 2010, Rafael J. Wysocki wrote: >> >> >> >> > 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? >> >> >> >> Open the file twice, thereby obtaining two file handles. >> > >> > Well, that's what I thought. >> > >> > I must admit I'm not really comfortable with this interface. IMO it would >> > be better if _open() created the suspend blocker giving it a name based on >> > the name of the process that called it. Something like >> > "<process name>_<timestamp>" might work at first sight. >> > >> > Alternatively, "<process_name><number>", where <number> is 0 for the first >> > suspend blocker created by the given process, 1 for the second one etc., also >> > seems to be doable. >> >> I think it is important to let user-space specify the name. If a >> process uses multiple suspend blockers, it is impossible to tell what >> each one is used for if they are automatically named. > > Well, the problem is the only purpose of this is user space debugging, isn't it? > At the moment, yes. But having an explicit init call also simplifies future expansion. If we ever need to add back multiple types of suspend blockers, we can add an init call with a type argument and have the current init call use the default type. If the past we have had types that keeps the screen on and prevented idle sleep modes. In the future we could for instance want to specify if a suspend blocker should prevent suspend when the battery is low or when the lid is closed. > Now, while I don't think it's generally bad to provide kernel interfaces > helping to debug user space, I'm not quite sure if that should be done at the > expense of the clarity of kernel-user space interfaces. > > I wonder how many cases there are in which distinguishing between suspend > blockers used by the same user space task is practically relevant. > I think all of them (when more than one suspend blocker is used). -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <x2id6200be21005031501p7f151324wb8bbf928bc2cb25e@mail.gmail.com>]
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <x2id6200be21005031501p7f151324wb8bbf928bc2cb25e@mail.gmail.com> @ 2010-05-04 20:02 ` Rafael J. Wysocki 0 siblings, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-04 20:02 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, Kernel development list, Oleg Nesterov, Avi Kivity, Ryusuke Konishi, Tejun Heo, Linux-pm mailing list, Andrew Morton On Tuesday 04 May 2010, Arve Hjønnevåg wrote: > 2010/5/3 Rafael J. Wysocki <rjw@sisk.pl>: > > On Monday 03 May 2010, Arve Hjønnevåg wrote: > >> On Mon, May 3, 2010 at 8:03 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > >> > On Sunday 02 May 2010, Alan Stern wrote: > >> >> On Sun, 2 May 2010, Rafael J. Wysocki wrote: > >> >> > >> >> > 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? > >> >> > >> >> Open the file twice, thereby obtaining two file handles. > >> > > >> > Well, that's what I thought. > >> > > >> > I must admit I'm not really comfortable with this interface. IMO it would > >> > be better if _open() created the suspend blocker giving it a name based on > >> > the name of the process that called it. Something like > >> > "<process name>_<timestamp>" might work at first sight. > >> > > >> > Alternatively, "<process_name><number>", where <number> is 0 for the first > >> > suspend blocker created by the given process, 1 for the second one etc., also > >> > seems to be doable. > >> > >> I think it is important to let user-space specify the name. If a > >> process uses multiple suspend blockers, it is impossible to tell what > >> each one is used for if they are automatically named. > > > > Well, the problem is the only purpose of this is user space debugging, isn't it? > > > At the moment, yes. OK > But having an explicit init call also simplifies future expansion. That's irrelevant. Let's focus _only_ on the "at the moment" part, please. And BTW, a "future expansion" is not relevant at all to the patchset at hand and let's work with this assumption from now on. OK? > If we ever need to add back multiple types of > suspend blockers, we can add an init call with a type argument and > have the current init call use the default type. If the past we have > had types that keeps the screen on and prevented idle sleep modes. In > the future we could for instance want to specify if a suspend blocker > should prevent suspend when the battery is low or when the lid is > closed. _If_ we ever do anything like thie, _then_ we will extend the interface. > > Now, while I don't think it's generally bad to provide kernel interfaces > > helping to debug user space, I'm not quite sure if that should be done at the > > expense of the clarity of kernel-user space interfaces. > > > > I wonder how many cases there are in which distinguishing between suspend > > blockers used by the same user space task is practically relevant. > > > > I think all of them (when more than one suspend blocker is used). So how many user space processes use more than one suspend blocker right now on Android? I'm interested only in the order of magnitude. Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <201005031703.11448.rjw@sisk.pl> 2010-05-03 21:26 ` Arve Hjønnevåg [not found] ` <m2yd6200be21005031426n87ea43a0k968fd5898ce0b873@mail.gmail.com> @ 2010-05-04 4:16 ` Pavel Machek 2 siblings, 0 replies; 89+ messages in thread From: Pavel Machek @ 2010-05-04 4:16 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, Oleg Nesterov, Kernel development list, Avi Kivity, Ryusuke Konishi, Tejun Heo, Linux-pm mailing list, Andrew Morton On Mon 2010-05-03 17:03:11, Rafael J. Wysocki wrote: > On Sunday 02 May 2010, Alan Stern wrote: > > On Sun, 2 May 2010, Rafael J. Wysocki wrote: > > > > > 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? > > > > Open the file twice, thereby obtaining two file handles. > > Well, that's what I thought. > > I must admit I'm not really comfortable with this interface. IMO it would > be better if _open() created the suspend blocker giving it a name based on > the name of the process that called it. Something like > "<process name>_<timestamp>" might work at first sight. > > Alternatively, "<process_name><number>", where <number> is 0 for the first > suspend blocker created by the given process, 1 for the second one etc., also > seems to be doable. Yes please. -- (english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <1272667021-21312-1-git-send-email-arve@android.com>]
[parent not found: <1272667021-21312-2-git-send-email-arve@android.com>]
* [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <1272667021-21312-2-git-send-email-arve@android.com> @ 2010-04-30 22:36 ` Arve Hjønnevåg 2010-05-02 7:04 ` Pavel Machek 2010-05-02 21:23 ` Rafael J. Wysocki 0 siblings, 2 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-04-30 22:36 UTC (permalink / raw) To: linux-pm, linux-kernel Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, Oleg Nesterov, Avi Kivity, Ryusuke Konishi, Tejun Heo, Magnus Damm, Andrew Morton 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@android.com> --- 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; + return 0; + +err_fault: + kfree(bl); + return -EFAULT; +} + +static long user_suspend_blocker_ioctl(struct file *file, unsigned int cmd, + unsigned long _arg) +{ + void __user *arg = (void __user *)_arg; + struct user_suspend_blocker *bl; + long ret; + + mutex_lock(&ioctl_lock); + if ((cmd & ~IOCSIZE_MASK) == SUSPEND_BLOCKER_IOCTL_INIT(0)) { + ret = create_user_suspend_blocker(file, arg, _IOC_SIZE(cmd)); + goto done; + } + bl = file->private_data; + if (!bl) { + ret = -ENOENT; + goto done; + } + switch (cmd) { + case SUSPEND_BLOCKER_IOCTL_BLOCK: + suspend_block(&bl->blocker); + ret = 0; + break; + case SUSPEND_BLOCKER_IOCTL_UNBLOCK: + suspend_unblock(&bl->blocker); + ret = 0; + break; + default: + ret = -ENOTSUPP; + } +done: + if (ret && (debug_mask & DEBUG_FAILURE)) + pr_err("user_suspend_blocker_ioctl: cmd %x failed, %ld\n", + cmd, ret); + mutex_unlock(&ioctl_lock); + return ret; +} + +static int user_suspend_blocker_release(struct inode *inode, struct file *file) +{ + struct user_suspend_blocker *bl = file->private_data; + if (!bl) + return 0; + suspend_blocker_destroy(&bl->blocker); + kfree(bl); + return 0; +} + +const struct file_operations user_suspend_blocker_fops = { + .release = user_suspend_blocker_release, + .unlocked_ioctl = user_suspend_blocker_ioctl, +}; + +struct miscdevice user_suspend_blocker_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "suspend_blocker", + .fops = &user_suspend_blocker_fops, +}; + +static int __init user_suspend_blocker_init(void) +{ + return misc_register(&user_suspend_blocker_device); +} + +static void __exit user_suspend_blocker_exit(void) +{ + misc_deregister(&user_suspend_blocker_device); +} + +module_init(user_suspend_blocker_init); +module_exit(user_suspend_blocker_exit); -- 1.6.5.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] 89+ messages in thread
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space 2010-04-30 22:36 ` Arve Hjønnevåg @ 2010-05-02 7:04 ` Pavel Machek 2010-05-02 21:23 ` Rafael J. Wysocki 1 sibling, 0 replies; 89+ messages in thread From: Pavel Machek @ 2010-05-02 7:04 UTC (permalink / raw) To: Arve Hj??nnev??g Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, linux-kernel, Oleg Nesterov, Avi Kivity, Ryusuke Konishi, Tejun Heo, Magnus Damm, linux-pm, Andrew Morton On Fri 2010-04-30 15:36:55, 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. Yeah, this one is overly complex; instead of having 'open blocks suspend' semantics and lsof listing active blockers, it adds strange ioctl based interface passing names, and then adds debugfs infrastructure listing those back. I guess this is why you are getying 'it should be in /proc, no in /sys, no in debugfs, no in /proc' kind of feedback. This should simply not exist in the first place... > Signed-off-by: Arve Hj??nnev??g <arve@android.com> NAK. > --- > 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; > + return 0; > + > +err_fault: > + kfree(bl); > + return -EFAULT; > +} > + > +static long user_suspend_blocker_ioctl(struct file *file, unsigned int cmd, > + unsigned long _arg) > +{ > + void __user *arg = (void __user *)_arg; > + struct user_suspend_blocker *bl; > + long ret; > + > + mutex_lock(&ioctl_lock); > + if ((cmd & ~IOCSIZE_MASK) == SUSPEND_BLOCKER_IOCTL_INIT(0)) { > + ret = create_user_suspend_blocker(file, arg, _IOC_SIZE(cmd)); > + goto done; > + } > + bl = file->private_data; > + if (!bl) { > + ret = -ENOENT; > + goto done; > + } > + switch (cmd) { > + case SUSPEND_BLOCKER_IOCTL_BLOCK: > + suspend_block(&bl->blocker); > + ret = 0; > + break; > + case SUSPEND_BLOCKER_IOCTL_UNBLOCK: > + suspend_unblock(&bl->blocker); > + ret = 0; > + break; > + default: > + ret = -ENOTSUPP; > + } > +done: > + if (ret && (debug_mask & DEBUG_FAILURE)) > + pr_err("user_suspend_blocker_ioctl: cmd %x failed, %ld\n", > + cmd, ret); > + mutex_unlock(&ioctl_lock); > + return ret; > +} > + > +static int user_suspend_blocker_release(struct inode *inode, struct file *file) > +{ > + struct user_suspend_blocker *bl = file->private_data; > + if (!bl) > + return 0; > + suspend_blocker_destroy(&bl->blocker); > + kfree(bl); > + return 0; > +} > + > +const struct file_operations user_suspend_blocker_fops = { > + .release = user_suspend_blocker_release, > + .unlocked_ioctl = user_suspend_blocker_ioctl, > +}; > + > +struct miscdevice user_suspend_blocker_device = { > + .minor = MISC_DYNAMIC_MINOR, > + .name = "suspend_blocker", > + .fops = &user_suspend_blocker_fops, > +}; > + > +static int __init user_suspend_blocker_init(void) > +{ > + return misc_register(&user_suspend_blocker_device); > +} > + > +static void __exit user_suspend_blocker_exit(void) > +{ > + misc_deregister(&user_suspend_blocker_device); > +} > + > +module_init(user_suspend_blocker_init); > +module_exit(user_suspend_blocker_exit); -- (english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space 2010-04-30 22:36 ` Arve Hjønnevåg 2010-05-02 7:04 ` Pavel Machek @ 2010-05-02 21:23 ` Rafael J. Wysocki 2010-05-02 21:56 ` Alan Stern 1 sibling, 1 reply; 89+ messages in thread From: Rafael J. Wysocki @ 2010-05-02 21:23 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, linux-kernel, Oleg Nesterov, Avi Kivity, Ryusuke Konishi, Tejun Heo, Magnus Damm, linux-pm, Andrew Morton 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@android.com> > --- > 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@lists.linux-foundation.org https://lists.linux-foundation.org/mailman/listinfo/linux-pm ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space 2010-05-02 21:23 ` Rafael J. Wysocki @ 2010-05-02 21:56 ` Alan Stern 0 siblings, 0 replies; 89+ messages in thread From: Alan Stern @ 2010-05-02 21:56 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Len Brown, Jim Collar, linux-doc, Kernel development list, Greg Kroah-Hartman, Oleg Nesterov, Avi Kivity, Ryusuke Konishi, Tejun Heo, Linux-pm mailing list, Andrew Morton On Sun, 2 May 2010, Rafael J. Wysocki wrote: > 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? Open the file twice, thereby obtaining two file handles. Alan Stern ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <1272429119-12103-1-git-send-email-arve@android.com>]
[parent not found: <1272429119-12103-2-git-send-email-arve@android.com>]
* [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <1272429119-12103-2-git-send-email-arve@android.com> @ 2010-04-28 4:31 ` Arve Hjønnevåg 2010-04-28 20:58 ` Rafael J. Wysocki [not found] ` <201004282258.51354.rjw@sisk.pl> 0 siblings, 2 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-04-28 4:31 UTC (permalink / raw) To: linux-pm, linux-kernel Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, Oleg Nesterov, Avi Kivity, Ryusuke Konishi, Tejun Heo, Magnus Damm, Andrew Morton 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@android.com> --- 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 1a29d10..639da73 100644 --- a/Documentation/power/opportunistic-suspend.txt +++ b/Documentation/power/opportunistic-suspend.txt @@ -112,3 +112,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..a9be6f4 --- /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; + return 0; + +err_fault: + kfree(bl); + return -EFAULT; +} + +static long user_suspend_blocker_ioctl(struct file *file, unsigned int cmd, + unsigned long _arg) +{ + void __user *arg = (void __user *)_arg; + struct user_suspend_blocker *bl; + long ret; + + mutex_lock(&ioctl_lock); + if ((cmd & ~IOCSIZE_MASK) == SUSPEND_BLOCKER_IOCTL_INIT(0)) { + ret = create_user_suspend_blocker(file, arg, _IOC_SIZE(cmd)); + goto done; + } + bl = file->private_data; + if (!bl) { + ret = -ENOENT; + goto done; + } + switch (cmd) { + case SUSPEND_BLOCKER_IOCTL_BLOCK: + suspend_block(&bl->blocker); + ret = 0; + break; + case SUSPEND_BLOCKER_IOCTL_UNBLOCK: + suspend_unblock(&bl->blocker); + ret = 0; + break; + default: + ret = -ENOTSUPP; + } +done: + if (ret && debug_mask & DEBUG_FAILURE) + pr_err("user_suspend_blocker_ioctl: cmd %x failed, %ld\n", + cmd, ret); + mutex_unlock(&ioctl_lock); + return ret; +} + +static int user_suspend_blocker_release(struct inode *inode, struct file *file) +{ + struct user_suspend_blocker *bl = file->private_data; + if (!bl) + return 0; + suspend_blocker_destroy(&bl->blocker); + kfree(bl); + return 0; +} + +const struct file_operations user_suspend_blocker_fops = { + .release = user_suspend_blocker_release, + .unlocked_ioctl = user_suspend_blocker_ioctl, +}; + +struct miscdevice user_suspend_blocker_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "suspend_blocker", + .fops = &user_suspend_blocker_fops, +}; + +static int __init user_suspend_blocker_init(void) +{ + return misc_register(&user_suspend_blocker_device); +} + +static void __exit user_suspend_blocker_exit(void) +{ + misc_deregister(&user_suspend_blocker_device); +} + +module_init(user_suspend_blocker_init); +module_exit(user_suspend_blocker_exit); -- 1.6.5.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] 89+ messages in thread
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space 2010-04-28 4:31 ` Arve Hjønnevåg @ 2010-04-28 20:58 ` Rafael J. Wysocki [not found] ` <201004282258.51354.rjw@sisk.pl> 1 sibling, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-04-28 20:58 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, linux-kernel, Oleg Nesterov, Avi Kivity, Ryusuke Konishi, Tejun Heo, Magnus Damm, linux-pm, Andrew Morton On Wednesday 28 April 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@android.com> ... > + > +#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; What's the exact purpose of this? > +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]; > +}; Why is this not in a header? 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] 89+ messages in thread
[parent not found: <201004282258.51354.rjw@sisk.pl>]
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <201004282258.51354.rjw@sisk.pl> @ 2010-04-28 22:31 ` Arve Hjønnevåg [not found] ` <k2gd6200be21004281531y270549d7g8383f2c8a55038d4@mail.gmail.com> 1 sibling, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-04-28 22:31 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, linux-kernel, Oleg Nesterov, Avi Kivity, Ryusuke Konishi, Tejun Heo, Magnus Damm, linux-pm, Andrew Morton 2010/4/28 Rafael J. Wysocki <rjw@sisk.pl>: > On Wednesday 28 April 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@android.com> > ... >> + >> +#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; > > What's the exact purpose of this? To show errors returned to user space. I can turn it off by default if you want. > >> +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]; >> +}; > > Why is this not in a header? It's private to this file. > > Rafael > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ > -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <k2gd6200be21004281531y270549d7g8383f2c8a55038d4@mail.gmail.com>]
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <k2gd6200be21004281531y270549d7g8383f2c8a55038d4@mail.gmail.com> @ 2010-04-28 23:05 ` Rafael J. Wysocki [not found] ` <201004290105.15707.rjw@sisk.pl> 1 sibling, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2010-04-28 23:05 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, linux-kernel, Oleg Nesterov, Avi Kivity, Ryusuke Konishi, Tejun Heo, Magnus Damm, linux-pm, Andrew Morton On Thursday 29 April 2010, Arve Hjønnevåg wrote: > 2010/4/28 Rafael J. Wysocki <rjw@sisk.pl>: > > On Wednesday 28 April 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@android.com> > > ... > >> + > >> +#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; > > > > What's the exact purpose of this? > > To show errors returned to user space. I can turn it off by default if you want. Not necessarily, but why is it a mask? It looks like a 0/1 thing would be sufficient. BTW, I'd put parens around (debug_mask & DEBUG_FAILURE) for clarity. Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <201004290105.15707.rjw@sisk.pl>]
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <201004290105.15707.rjw@sisk.pl> @ 2010-04-28 23:38 ` Arve Hjønnevåg [not found] ` <h2jd6200be21004281638y6b751abesfcf6416707e6fee4@mail.gmail.com> 1 sibling, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-04-28 23:38 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, linux-kernel, Oleg Nesterov, Avi Kivity, Ryusuke Konishi, Tejun Heo, Magnus Damm, linux-pm, Andrew Morton 2010/4/28 Rafael J. Wysocki <rjw@sisk.pl>: > On Thursday 29 April 2010, Arve Hjønnevåg wrote: >> 2010/4/28 Rafael J. Wysocki <rjw@sisk.pl>: >> > On Wednesday 28 April 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@android.com> >> > ... >> >> + >> >> +#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; >> > >> > What's the exact purpose of this? >> >> To show errors returned to user space. I can turn it off by default if you want. > > Not necessarily, but why is it a mask? It looks like a 0/1 thing would be > sufficient. I may want to add a bit to print all user-space block and unblock calls. > > BTW, I'd put parens around (debug_mask & DEBUG_FAILURE) for clarity. OK. -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
[parent not found: <h2jd6200be21004281638y6b751abesfcf6416707e6fee4@mail.gmail.com>]
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space [not found] ` <h2jd6200be21004281638y6b751abesfcf6416707e6fee4@mail.gmail.com> @ 2010-04-29 21:11 ` Rafael J. Wysocki 2010-04-29 23:41 ` Arve Hjønnevåg 0 siblings, 1 reply; 89+ messages in thread From: Rafael J. Wysocki @ 2010-04-29 21:11 UTC (permalink / raw) To: Arve Hjønnevåg Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, linux-kernel, Oleg Nesterov, Avi Kivity, Ryusuke Konishi, Tejun Heo, Magnus Damm, linux-pm, Andrew Morton On Thursday 29 April 2010, Arve Hjønnevåg wrote: > 2010/4/28 Rafael J. Wysocki <rjw@sisk.pl>: > > On Thursday 29 April 2010, Arve Hjønnevåg wrote: > >> 2010/4/28 Rafael J. Wysocki <rjw@sisk.pl>: > >> > On Wednesday 28 April 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@android.com> > >> > ... > >> >> + > >> >> +#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; > >> > > >> > What's the exact purpose of this? > >> > >> To show errors returned to user space. I can turn it off by default if you want. > > > > Not necessarily, but why is it a mask? It looks like a 0/1 thing would be > > sufficient. > > I may want to add a bit to print all user-space block and unblock calls. Alternatively, you can add a new parameter for that, which I think I would prefer. Rafael ^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space 2010-04-29 21:11 ` Rafael J. Wysocki @ 2010-04-29 23:41 ` Arve Hjønnevåg 0 siblings, 0 replies; 89+ messages in thread From: Arve Hjønnevåg @ 2010-04-29 23:41 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Len Brown, Jim Collar, linux-doc, Greg Kroah-Hartman, linux-kernel, Oleg Nesterov, Avi Kivity, Ryusuke Konishi, Tejun Heo, Magnus Damm, linux-pm, Andrew Morton 2010/4/29 Rafael J. Wysocki <rjw@sisk.pl>: > On Thursday 29 April 2010, Arve Hjønnevåg wrote: >> 2010/4/28 Rafael J. Wysocki <rjw@sisk.pl>: >> > On Thursday 29 April 2010, Arve Hjønnevåg wrote: >> >> 2010/4/28 Rafael J. Wysocki <rjw@sisk.pl>: >> >> > On Wednesday 28 April 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@android.com> >> >> > ... >> >> >> + >> >> >> +#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; >> >> > >> >> > What's the exact purpose of this? >> >> >> >> To show errors returned to user space. I can turn it off by default if you want. >> > >> > Not necessarily, but why is it a mask? It looks like a 0/1 thing would be >> > sufficient. >> >> I may want to add a bit to print all user-space block and unblock calls. > > Alternatively, you can add a new parameter for that, which I think I would prefer. > I use a bit-mask in the main suspend blocker code. This makes it easy to turn on or off all the messages. -- Arve Hjønnevåg ^ permalink raw reply [flat|nested] 89+ messages in thread
* [RFC][PATCH 0/8] Suspend block api @ 2009-04-15 1:41 Arve Hjønnevåg 2009-04-15 1:41 ` [PATCH 1/8] PM: Add suspend " Arve Hjønnevåg 0 siblings, 1 reply; 89+ messages in thread From: Arve Hjønnevåg @ 2009-04-15 1:41 UTC (permalink / raw) To: linux-pm; +Cc: ncunningham, u.luckas, swetland, r-woodruff2, @sisk.pl This patch series adds a suspend-block api that provides the same functionality as the android wakelock api from my last patch series, Android PM extensions (version 3). As requested, wake_lock has been renamed to suspend_block(er), and timeout support has been separated into its own patch. -- 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] 89+ messages in thread
* [PATCH 1/8] PM: Add suspend block api. 2009-04-15 1:41 [RFC][PATCH 0/8] Suspend block api Arve Hjønnevåg @ 2009-04-15 1:41 ` Arve Hjønnevåg 2009-04-15 1:41 ` [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space Arve Hjønnevåg 0 siblings, 1 reply; 89+ messages in thread From: Arve Hjønnevåg @ 2009-04-15 1:41 UTC (permalink / raw) To: linux-pm; +Cc: ncunningham, u.luckas, swetland, r-woodruff2, @sisk.pl Adds /sys/power/request_state, a non-blocking interface that specifies 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> --- Documentation/power/suspend-blockers.txt | 76 +++++++++ include/linux/suspend_block.h | 61 +++++++ kernel/power/Kconfig | 10 ++ kernel/power/Makefile | 1 + kernel/power/main.c | 62 +++++++ kernel/power/power.h | 6 + kernel/power/suspend_block.c | 257 ++++++++++++++++++++++++++++++ 7 files changed, 473 insertions(+), 0 deletions(-) create mode 100644 Documentation/power/suspend-blockers.txt create mode 100755 include/linux/suspend_block.h create mode 100644 kernel/power/suspend_block.c diff --git a/Documentation/power/suspend-blockers.txt b/Documentation/power/suspend-blockers.txt new file mode 100644 index 0000000..743b870 --- /dev/null +++ b/Documentation/power/suspend-blockers.txt @@ -0,0 +1,76 @@ +Suspend blockers +================ + +A suspend_blocker prevents the system from entering suspend. + +If the suspend operation has already started when calling suspend_block on a +suspend_blocker, it will abort the suspend operation as long it has not already +reached the sysdev suspend stage. This means that calling suspend_block from an +interrupt handler or a freezeable thread always works, but if you call +block_suspend from a sysdev suspend handler you must also return an error from +that handler to abort suspend. + +Suspend blockers 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 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. It determines that the + key should not wake up the full system, calls suspend_unblock on the + process-input-events suspend_blocker and calls select or poll. + + 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. 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_block.h b/include/linux/suspend_block.h new file mode 100755 index 0000000..7820c60 --- /dev/null +++ b/include/linux/suspend_block.h @@ -0,0 +1,61 @@ +/* include/linux/suspend_block.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_BLOCK_H +#define _LINUX_SUSPEND_BLOCK_H + +/* A suspend_blocker prevents the system from entering suspend when active. + */ + +struct suspend_blocker { +#ifdef CONFIG_SUSPEND_BLOCK + atomic_t flags; + const char *name; +#endif +}; + +#ifdef CONFIG_SUSPEND_BLOCK + +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); + +/* is_blocking_suspend returns true if the suspend_blocker is currently active. + */ +bool is_blocking_suspend(struct suspend_blocker *blocker); + +/* 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); + +#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 is_blocking_suspend(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 23bd4da..9d1df13 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -116,6 +116,16 @@ config SUSPEND_FREEZER Turning OFF this setting is NOT recommended! If in doubt, say Y. +config SUSPEND_BLOCK + bool "Suspend block" + depends on PM + select RTC_LIB + default n + ---help--- + Enable suspend_block. When user space requests a sleep state through + /sys/power/request_state, the requested sleep state will be entered + when no suspend_blockers are active. + 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 720ea4f..29cdc9e 100644 --- a/kernel/power/Makefile +++ b/kernel/power/Makefile @@ -6,6 +6,7 @@ endif obj-$(CONFIG_PM) += main.o obj-$(CONFIG_PM_SLEEP) += console.o obj-$(CONFIG_FREEZER) += process.o +obj-$(CONFIG_SUSPEND_BLOCK) += suspend_block.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/main.c b/kernel/power/main.c index c9632f8..e4c6b20 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/suspend_block.h> #include "power.h" @@ -392,6 +393,9 @@ static void suspend_finish(void) static const char * const pm_states[PM_SUSPEND_MAX] = { +#ifdef CONFIG_SUSPEND_BLOCK + [PM_SUSPEND_ON] = "on", +#endif [PM_SUSPEND_STANDBY] = "standby", [PM_SUSPEND_MEM] = "mem", }; @@ -540,6 +544,61 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, power_attr(state); +/** + * 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 + * requested. Suspend blockers are respected and the requested state will + * only be entered when no suspend blockers are active. + * Write "on" to cancel. + */ + +#ifdef CONFIG_SUSPEND_BLOCK +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] && (i == PM_SUSPEND_ON || 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; + request_suspend_state(state); + } + return error ? error : n; +} + +power_attr(request_state); +#endif /* CONFIG_SUSPEND_BLOCK */ + #ifdef CONFIG_PM_TRACE int pm_trace_enabled; @@ -567,6 +626,9 @@ power_attr(pm_trace); static struct attribute * g[] = { &state_attr.attr, +#ifdef CONFIG_SUSPEND_BLOCK + &request_state_attr.attr, +#endif #ifdef CONFIG_PM_TRACE &pm_trace_attr.attr, #endif diff --git a/kernel/power/power.h b/kernel/power/power.h index 46b5ec7..2414a74 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -223,3 +223,9 @@ static inline void suspend_thaw_processes(void) { } #endif + +#ifdef CONFIG_SUSPEND_BLOCK +/* kernel/power/suspend_block.c */ +void request_suspend_state(suspend_state_t state); +#endif + diff --git a/kernel/power/suspend_block.c b/kernel/power/suspend_block.c new file mode 100644 index 0000000..b4f2191 --- /dev/null +++ b/kernel/power/suspend_block.c @@ -0,0 +1,257 @@ +/* kernel/power/suspend_block.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/rtc.h> +#include <linux/suspend.h> +#include <linux/suspend_block.h> +#include <linux/sysdev.h> +#include "power.h" + +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(state_lock); +static atomic_t suspend_block_count; +static atomic_t current_event_num; +struct workqueue_struct *suspend_work_queue; +struct suspend_blocker main_suspend_blocker; +static suspend_state_t requested_suspend_state = PM_SUSPEND_MEM; +static bool enable_suspend_blockers; + +bool suspend_is_blocked(void) +{ + if (WARN_ONCE(!enable_suspend_blockers, "ignoring suspend blockers\n")) + return 0; + return !!atomic_read(&suspend_block_count); +} + +static void suspend_worker(struct work_struct *work) +{ + int ret; + int entry_event_num; + + enable_suspend_blockers = 1; + +retry: + if (suspend_is_blocked()) { + if (debug_mask & DEBUG_SUSPEND) + pr_info("suspend: abort suspend\n"); + goto abort; + } + + entry_event_num = atomic_read(¤t_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) { + 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 (atomic_read(¤t_event_num) == entry_event_num) { + if (debug_mask & DEBUG_SUSPEND) + pr_info("suspend: pm_suspend returned with no event\n"); + goto retry; + } +abort: + enable_suspend_blockers = 0; +} +static DECLARE_WORK(suspend_work, suspend_worker); + +static int suspend_block_suspend(struct sys_device *dev, pm_message_t state) +{ + int ret = suspend_is_blocked() ? -EAGAIN : 0; + if (debug_mask & DEBUG_SUSPEND) + pr_info("suspend_block_suspend return %d\n", ret); + return ret; +} + +static struct sysdev_class suspend_block_sysclass = { + .name = "suspend_block", + .suspend = suspend_block_suspend, +}; +static struct sys_device suspend_block_sysdev = { + .cls = &suspend_block_sysclass, +}; + +/** + * suspend_blocker_init() - Initialize a suspend blocker + * @blocker: The suspend blocker to initialize. + * @name: The name of the suspend blocker to show in + * /proc/suspend_blockers + */ +void suspend_blocker_init(struct suspend_blocker *blocker, const char *name) +{ + if (name) + blocker->name = name; + BUG_ON(!blocker->name); + + if (debug_mask & DEBUG_SUSPEND_BLOCKER) + pr_info("suspend_blocker_init name=%s\n", blocker->name); + + atomic_set(&blocker->flags, SB_INITIALIZED); +} +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) +{ + int flags; + if (debug_mask & DEBUG_SUSPEND_BLOCKER) + pr_info("suspend_blocker_destroy name=%s\n", blocker->name); + flags = atomic_xchg(&blocker->flags, 0); + WARN(!(flags & SB_INITIALIZED), "suspend_blocker_destroy called on " + "uninitialized suspend_blocker\n"); + if (flags == (SB_INITIALIZED | SB_ACTIVE)) + if (atomic_dec_and_test(&suspend_block_count)) + queue_work(suspend_work_queue, &suspend_work); +} +EXPORT_SYMBOL(suspend_blocker_destroy); + +/** + * suspend_block() - Block suspend + * @blocker: The suspend blocker to use + */ +void suspend_block(struct suspend_blocker *blocker) +{ + BUG_ON(!(atomic_read(&blocker->flags) & SB_INITIALIZED)); + + if (debug_mask & DEBUG_SUSPEND_BLOCKER) + pr_info("suspend_block: %s\n", blocker->name); + if (atomic_cmpxchg(&blocker->flags, SB_INITIALIZED, + SB_INITIALIZED | SB_ACTIVE) == SB_INITIALIZED) + atomic_inc(&suspend_block_count); + + atomic_inc(¤t_event_num); +} +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. + */ +void suspend_unblock(struct suspend_blocker *blocker) +{ + if (debug_mask & DEBUG_SUSPEND_BLOCKER) + pr_info("suspend_unblock: %s\n", blocker->name); + + if (atomic_cmpxchg(&blocker->flags, SB_INITIALIZED | SB_ACTIVE, + SB_INITIALIZED) == (SB_INITIALIZED | SB_ACTIVE)) + if (atomic_dec_and_test(&suspend_block_count)) + queue_work(suspend_work_queue, &suspend_work); +} +EXPORT_SYMBOL(suspend_unblock); + +/** + * is_blocking_suspend() - Test if a suspend blocker is blocking suspend + * @blocker: The suspend blocker to check. + */ +bool is_blocking_suspend(struct suspend_blocker *blocker) +{ + return !!(atomic_read(&blocker->flags) & SB_ACTIVE); +} +EXPORT_SYMBOL(is_blocking_suspend); + +void request_suspend_state(suspend_state_t state) +{ + unsigned long irqflags; + spin_lock_irqsave(&state_lock, irqflags); + 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", + state != PM_SUSPEND_ON ? "sleep" : "wakeup", + requested_suspend_state, 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); + } + 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); +} + +static int __init suspend_block_init(void) +{ + int ret; + + suspend_blocker_init(&main_suspend_blocker, "main"); + suspend_block(&main_suspend_blocker); + + ret = sysdev_class_register(&suspend_block_sysclass); + if (ret) { + pr_err("suspend_block_init: sysdev_class_register failed\n"); + goto err_sysdev_class_register; + } + ret = sysdev_register(&suspend_block_sysdev); + if (ret) { + pr_err("suspend_block_init: suspend_block_sysdev failed\n"); + goto err_sysdev_register; + } + + suspend_work_queue = create_singlethread_workqueue("suspend"); + if (suspend_work_queue == NULL) { + ret = -ENOMEM; + goto err_suspend_work_queue; + } + + return 0; + +err_suspend_work_queue: + sysdev_unregister(&suspend_block_sysdev); +err_sysdev_register: + sysdev_class_unregister(&suspend_block_sysclass); +err_sysdev_class_register: + suspend_blocker_destroy(&main_suspend_blocker); + return ret; +} + +static void __exit suspend_block_exit(void) +{ + destroy_workqueue(suspend_work_queue); + sysdev_unregister(&suspend_block_sysdev); + sysdev_class_unregister(&suspend_block_sysclass); + suspend_blocker_destroy(&main_suspend_blocker); +} + +core_initcall(suspend_block_init); +module_exit(suspend_block_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] 89+ messages in thread
* [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space 2009-04-15 1:41 ` [PATCH 1/8] PM: Add suspend " Arve Hjønnevåg @ 2009-04-15 1:41 ` Arve Hjønnevåg 2009-04-29 22:52 ` Rafael J. Wysocki 0 siblings, 1 reply; 89+ messages in thread From: Arve Hjønnevåg @ 2009-04-15 1:41 UTC (permalink / raw) To: linux-pm; +Cc: ncunningham, u.luckas, swetland, r-woodruff2, @sisk.pl Adds 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@android.com> --- Documentation/power/suspend-blockers.txt | 17 ++++ include/linux/suspend_block_dev.h | 25 ++++++ kernel/power/Kconfig | 9 ++ kernel/power/Makefile | 1 + kernel/power/user_suspend_block.c | 125 ++++++++++++++++++++++++++++++ 5 files changed, 177 insertions(+), 0 deletions(-) create mode 100644 include/linux/suspend_block_dev.h create mode 100644 kernel/power/user_suspend_block.c diff --git a/Documentation/power/suspend-blockers.txt b/Documentation/power/suspend-blockers.txt index 743b870..35bc713 100644 --- a/Documentation/power/suspend-blockers.txt +++ b/Documentation/power/suspend-blockers.txt @@ -74,3 +74,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..a7c0bf9 --- /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', 3) + +#endif diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 9d1df13..2cf4c4d 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -126,6 +126,15 @@ config SUSPEND_BLOCK /sys/power/request_state, the requested sleep state will be entered when no suspend_blockers are active. +config USER_SUSPEND_BLOCK + bool "Userspace suspend blockers" + depends on SUSPEND_BLOCK + 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 bool "Hibernation (aka 'suspend to disk')" depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE diff --git a/kernel/power/Makefile b/kernel/power/Makefile index 29cdc9e..5c524f1 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_BLOCK) += suspend_block.o +obj-$(CONFIG_USER_SUSPEND_BLOCK) += user_suspend_block.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/user_suspend_block.c b/kernel/power/user_suspend_block.c new file mode 100644 index 0000000..782407c --- /dev/null +++ b/kernel/power/user_suspend_block.c @@ -0,0 +1,125 @@ +/* kernel/power/user_suspend_block.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/suspend_block.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; + 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; + return 0; + +err_fault: + kfree(bl); + return -EFAULT; +} + +static long user_suspend_blocker_ioctl(struct file *file, unsigned int cmd, + unsigned long _arg) +{ + void __user *arg = (void __user *)_arg; + struct user_suspend_blocker *bl; + long ret; + + mutex_lock(&ioctl_lock); + if ((cmd & ~IOCSIZE_MASK) == SUSPEND_BLOCKER_IOCTL_INIT(0)) { + ret = create_user_suspend_blocker(file, arg, _IOC_SIZE(cmd)); + goto done; + } + bl = file->private_data; + if (!bl) { + ret = -ENOENT; + goto done; + } + switch (cmd) { + case SUSPEND_BLOCKER_IOCTL_BLOCK: + suspend_block(&bl->blocker); + ret = 0; + break; + case SUSPEND_BLOCKER_IOCTL_UNBLOCK: + suspend_unblock(&bl->blocker); + ret = 0; + break; + default: + ret = -ENOTSUPP; + } +done: + if (ret && debug_mask & DEBUG_FAILURE) + pr_err("user_suspend_blocker_ioctl: cmd %x failed, %ld\n", + cmd, ret); + mutex_unlock(&ioctl_lock); + return ret; +} + +static int user_suspend_blocker_release(struct inode *inode, struct file *file) +{ + struct user_suspend_blocker *bl = file->private_data; + if (!bl) + return 0; + suspend_blocker_destroy(&bl->blocker); + kfree(bl); + return 0; +} + +const struct file_operations user_suspend_blocker_fops = { + .release = user_suspend_blocker_release, + .unlocked_ioctl = user_suspend_blocker_ioctl, +}; + +struct miscdevice user_suspend_blocker_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "suspend_blocker", + .fops = &user_suspend_blocker_fops, +}; + +static int __init user_suspend_blocker_init(void) +{ + return misc_register(&user_suspend_blocker_device); +} + +static void __exit user_suspend_blocker_exit(void) +{ + misc_deregister(&user_suspend_blocker_device); +} + +module_init(user_suspend_blocker_init); +module_exit(user_suspend_blocker_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] 89+ messages in thread
* Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space 2009-04-15 1:41 ` [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space Arve Hjønnevåg @ 2009-04-29 22:52 ` Rafael J. Wysocki 0 siblings, 0 replies; 89+ messages in thread From: Rafael J. Wysocki @ 2009-04-29 22:52 UTC (permalink / raw) To: Arve Hjønnevåg; +Cc: ncunningham, u.luckas, swetland, linux-pm On Wednesday 15 April 2009, Arve Hjønnevåg wrote: > Adds ioctls to create a suspend_blocker, and to block and unblock suspend. > To delete the suspend_blocker, close the device. The changelog is minimalistic, so to speak. Can you please describe the idea in more detail in it? Also, perhaps you could use write() to initialize the suspend blocker? I don't know really, it's just a thought. You might not need ioctls() at all if you used write() like write(name) -> initialize write(1) -> activate write(0) -> deactivate write(1) -> activate write(0) -> deactivate etc. read() -> check status (0 -> inactive, 1 -> active) or something like this. It might be extended for timeouts too. ;-) > Signed-off-by: Arve Hjønnevåg <arve@android.com> > --- > Documentation/power/suspend-blockers.txt | 17 ++++ > include/linux/suspend_block_dev.h | 25 ++++++ > kernel/power/Kconfig | 9 ++ > kernel/power/Makefile | 1 + > kernel/power/user_suspend_block.c | 125 ++++++++++++++++++++++++++++++ > 5 files changed, 177 insertions(+), 0 deletions(-) > create mode 100644 include/linux/suspend_block_dev.h > create mode 100644 kernel/power/user_suspend_block.c > > diff --git a/Documentation/power/suspend-blockers.txt b/Documentation/power/suspend-blockers.txt > index 743b870..35bc713 100644 > --- a/Documentation/power/suspend-blockers.txt > +++ b/Documentation/power/suspend-blockers.txt > @@ -74,3 +74,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..a7c0bf9 > --- /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', 3) > + > +#endif > diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig > index 9d1df13..2cf4c4d 100644 > --- a/kernel/power/Kconfig > +++ b/kernel/power/Kconfig > @@ -126,6 +126,15 @@ config SUSPEND_BLOCK > /sys/power/request_state, the requested sleep state will be entered > when no suspend_blockers are active. > > +config USER_SUSPEND_BLOCK > + bool "Userspace suspend blockers" > + depends on SUSPEND_BLOCK > + 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 > bool "Hibernation (aka 'suspend to disk')" > depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE > diff --git a/kernel/power/Makefile b/kernel/power/Makefile > index 29cdc9e..5c524f1 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_BLOCK) += suspend_block.o > +obj-$(CONFIG_USER_SUSPEND_BLOCK) += user_suspend_block.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/user_suspend_block.c b/kernel/power/user_suspend_block.c > new file mode 100644 > index 0000000..782407c > --- /dev/null > +++ b/kernel/power/user_suspend_block.c > @@ -0,0 +1,125 @@ > +/* kernel/power/user_suspend_block.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/suspend_block.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; > + 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; > + return 0; > + > +err_fault: > + kfree(bl); > + return -EFAULT; > +} > + > +static long user_suspend_blocker_ioctl(struct file *file, unsigned int cmd, > + unsigned long _arg) > +{ > + void __user *arg = (void __user *)_arg; > + struct user_suspend_blocker *bl; > + long ret; > + > + mutex_lock(&ioctl_lock); > + if ((cmd & ~IOCSIZE_MASK) == SUSPEND_BLOCKER_IOCTL_INIT(0)) { > + ret = create_user_suspend_blocker(file, arg, _IOC_SIZE(cmd)); > + goto done; > + } > + bl = file->private_data; > + if (!bl) { > + ret = -ENOENT; > + goto done; > + } > + switch (cmd) { > + case SUSPEND_BLOCKER_IOCTL_BLOCK: > + suspend_block(&bl->blocker); > + ret = 0; > + break; > + case SUSPEND_BLOCKER_IOCTL_UNBLOCK: > + suspend_unblock(&bl->blocker); > + ret = 0; > + break; > + default: > + ret = -ENOTSUPP; > + } > +done: > + if (ret && debug_mask & DEBUG_FAILURE) > + pr_err("user_suspend_blocker_ioctl: cmd %x failed, %ld\n", > + cmd, ret); > + mutex_unlock(&ioctl_lock); > + return ret; > +} > + > +static int user_suspend_blocker_release(struct inode *inode, struct file *file) > +{ > + struct user_suspend_blocker *bl = file->private_data; > + if (!bl) > + return 0; > + suspend_blocker_destroy(&bl->blocker); > + kfree(bl); > + return 0; > +} > + > +const struct file_operations user_suspend_blocker_fops = { > + .release = user_suspend_blocker_release, > + .unlocked_ioctl = user_suspend_blocker_ioctl, > +}; > + > +struct miscdevice user_suspend_blocker_device = { > + .minor = MISC_DYNAMIC_MINOR, > + .name = "suspend_blocker", > + .fops = &user_suspend_blocker_fops, > +}; > + > +static int __init user_suspend_blocker_init(void) > +{ > + return misc_register(&user_suspend_blocker_device); > +} > + > +static void __exit user_suspend_blocker_exit(void) > +{ > + misc_deregister(&user_suspend_blocker_device); > +} > + > +module_init(user_suspend_blocker_init); > +module_exit(user_suspend_blocker_exit); -- Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it? --- Brian Kernighan _______________________________________________ linux-pm mailing list linux-pm@lists.linux-foundation.org https://lists.linux-foundation.org/mailman/listinfo/linux-pm ^ permalink raw reply [flat|nested] 89+ messages in thread
end of thread, other threads:[~2010-05-27 15:41 UTC | newest]
Thread overview: 89+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1273810273-3039-1-git-send-email-arve@android.com>
2010-05-14 4:11 ` [PATCH 1/8] PM: Add suspend block api Arve Hjønnevåg
2010-05-14 4:11 ` [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space Arve Hjønnevåg
2010-05-14 4:11 ` [PATCH 3/8] PM: suspend_block: Abort task freezing if a suspend_blocker is active Arve Hjønnevåg
2010-05-14 4:11 ` [PATCH 4/8] PM: suspend_block: Add debugfs file Arve Hjønnevåg
2010-05-14 4:11 ` [PATCH 5/8] PM: suspend_block: Add suspend_blocker stats Arve Hjønnevåg
2010-05-14 4:11 ` [PATCH 6/8] PM: Add suspend blocking work Arve Hjønnevåg
[not found] ` <1273810273-3039-7-git-send-email-arve@android.com>
2010-05-14 4:11 ` [PATCH 7/8] Input: Block suspend while event queue is not empty Arve Hjønnevåg
2010-05-14 4:11 ` [PATCH 8/8] power_supply: Block suspend while power supply change notifications are pending Arve Hjønnevåg
2010-05-14 6:13 ` [PATCH 1/8] PM: Add suspend block api Paul Walmsley
2010-05-14 6:27 ` Paul Walmsley
2010-05-14 7:14 ` Arve Hjønnevåg
2010-05-18 2:17 ` Paul Walmsley
2010-05-18 3:06 ` Arve Hjønnevåg
2010-05-18 3:34 ` Paul Walmsley
2010-05-18 3:51 ` Arve Hjønnevåg
2010-05-19 15:55 ` Paul Walmsley
2010-05-20 0:35 ` Arve Hjønnevåg
2010-05-18 13:11 ` Pavel Machek
[not found] ` <20100518131111.GB1563@ucw.cz>
2010-05-20 9:11 ` Florian Mickler
[not found] ` <20100520111111.333beb73@schatten.dmk.lab>
2010-05-20 9:26 ` Florian Mickler
[not found] ` <20100520112642.74d93d26@schatten.dmk.lab>
2010-05-20 22:18 ` Rafael J. Wysocki
[not found] ` <201005210018.43576.rjw@sisk.pl>
2010-05-21 6:04 ` Florian Mickler
2010-05-27 15:41 ` Pavel Machek
2010-05-14 21:08 ` [PATCH 0/8] Suspend block api (version 7) Rafael J. Wysocki
2010-05-16 19:42 ` Rafael J. Wysocki
[not found] ` <201005162142.39343.rjw@sisk.pl>
2010-05-17 4:16 ` Arve Hjønnevåg
[not found] ` <AANLkTinP68yHYfVCW-urCrRbeSb0Mlz8JsvAs-FKoUPZ@mail.gmail.com>
2010-05-17 20:40 ` Rafael J. Wysocki
[not found] ` <201005172240.35742.rjw@sisk.pl>
2010-05-17 20:51 ` Brian Swetland
[not found] ` <AANLkTim2b8cKnzPgN7m5zImb0hVDfqVjRidKNVoYi1yO@mail.gmail.com>
2010-05-17 21:44 ` Rafael J. Wysocki
[not found] ` <201005172344.46222.rjw@sisk.pl>
2010-05-17 23:32 ` Arve Hjønnevåg
[not found] ` <AANLkTikENyp0UOKP2NzwjKye1EiZitdE0o4k1Z4ygCsT@mail.gmail.com>
2010-05-18 19:38 ` Rafael J. Wysocki
[not found] ` <201005182138.04610.rjw@sisk.pl>
2010-05-18 20:35 ` Arve Hjønnevåg
[not found] ` <AANLkTileYiu6pL4eX3lpvpYLuu76A8auZp4xrcDX94BQ@mail.gmail.com>
2010-05-18 21:14 ` Rafael J. Wysocki
[not found] ` <201005182314.08761.rjw@sisk.pl>
2010-05-18 22:21 ` Arve Hjønnevåg
[not found] ` <AANLkTikm69OKbRUvqiqGh4KRMn7u166tyt4kx0-bjR3Z@mail.gmail.com>
2010-05-18 22:56 ` Rafael J. Wysocki
[not found] ` <201005190056.36804.rjw@sisk.pl>
2010-05-18 23:06 ` Arve Hjønnevåg
[not found] ` <AANLkTikc9MmR_r1NkdCwDaPD4kJa9l9KUwcWAxilcs3l@mail.gmail.com>
2010-05-19 20:40 ` Rafael J. Wysocki
[not found] ` <201005142308.48386.rjw@sisk.pl>
2010-05-17 4:50 ` Arve Hjønnevåg
[not found] ` <AANLkTilX0uhqrJtUSOC4smdH1M8V-h14J7YtRG4PPxOQ@mail.gmail.com>
2010-05-17 19:01 ` Mike Snitzer
2010-05-17 21:42 ` Rafael J. Wysocki
[not found] ` <201005172342.52660.rjw@sisk.pl>
2010-05-17 22:16 ` Kevin Hilman
2010-05-18 0:52 ` Arve Hjønnevåg
2010-05-18 16:18 ` Kevin Hilman
2010-05-18 16:18 ` Kevin Hilman
2010-05-18 19:13 ` Rafael J. Wysocki
[not found] ` <201005182113.10448.rjw@sisk.pl>
2010-05-18 20:47 ` Arve Hjønnevåg
[not found] ` <AANLkTinPC94F1wj-CEb3vvSo7__u625DsZxErlmTymEw@mail.gmail.com>
2010-05-18 21:48 ` Rafael J. Wysocki
[not found] ` <201005182348.16026.rjw@sisk.pl>
2010-05-18 22:03 ` Arve Hjønnevåg
[not found] ` <AANLkTin-A5eXvxDEo-vi2x2jjXtZbAl2526w62noNMIK@mail.gmail.com>
2010-05-18 22:34 ` Rafael J. Wysocki
[not found] ` <201005190034.26085.rjw@sisk.pl>
2010-05-18 22:52 ` Arve Hjønnevåg
[not found] ` <AANLkTime0yZ_t32m8WjqJEtSeNlBJYZy15X8HwKzMqOl@mail.gmail.com>
2010-05-18 23:19 ` Rafael J. Wysocki
[not found] ` <201005190119.07710.rjw@sisk.pl>
2010-05-18 23:42 ` Arve Hjønnevåg
[not found] ` <AANLkTimFbvbDZdAFFTk0VCYhDtDk9B_LcEO60ZP70vjS@mail.gmail.com>
2010-05-19 20:39 ` Rafael J. Wysocki
[not found] ` <201005192239.25892.rjw@sisk.pl>
2010-05-19 21:34 ` Arve Hjønnevåg
[not found] ` <AANLkTimoU9BrzbAl7q-LZzGeRolO7gUKBoGjkPWtWn1G@mail.gmail.com>
2010-05-20 22:21 ` Rafael J. Wysocki
[not found] ` <87tyq5qj3v.fsf@deeprootsystems.com>
2010-05-18 18:52 ` Rafael J. Wysocki
[not found] ` <201005182052.28778.rjw@sisk.pl>
2010-05-18 22:04 ` Kevin Hilman
[not found] ` <87y6fgn9y1.fsf@deeprootsystems.com>
2010-05-18 22:29 ` Rafael J. Wysocki
2010-05-19 0:00 ` Arve Hjønnevåg
[not found] <Pine.LNX.4.44L0.1005261815480.1328-100000@iolanthe.rowland.org>
2010-05-26 22:34 ` [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space Rafael J. Wysocki
[not found] <201005262357.28933.rjw@sisk.pl>
2010-05-26 22:18 ` Alan Stern
2010-05-26 22:18 ` Alan Stern
[not found] <1274482015-30899-1-git-send-email-arve@android.com>
[not found] ` <1274482015-30899-2-git-send-email-arve@android.com>
2010-05-21 22:46 ` Arve Hjønnevåg
[not found] ` <1274482015-30899-3-git-send-email-arve@android.com>
2010-05-26 8:43 ` Peter Zijlstra
[not found] ` <1274863428.5882.4860.camel@twins>
2010-05-26 10:47 ` Arve Hjønnevåg
[not found] ` <AANLkTimTnzK1ByG2bE2gGjINxD_Pbvez7PFHo7Kzo9yk@mail.gmail.com>
2010-05-26 10:50 ` Peter Zijlstra
2010-05-26 10:51 ` Florian Mickler
[not found] ` <20100526125136.53f2dc82@schatten.dmk.lab>
2010-05-26 11:06 ` Peter Zijlstra
[not found] ` <1274871005.5882.5315.camel@twins>
2010-05-26 23:13 ` Arve Hjønnevåg
2010-05-26 21:57 ` Rafael J. Wysocki
[not found] <Pine.LNX.4.44L0.1005021755320.30701-100000@netrider.rowland.org>
2010-05-03 15:03 ` Rafael J. Wysocki
[not found] ` <201005031703.11448.rjw@sisk.pl>
2010-05-03 21:26 ` Arve Hjønnevåg
[not found] ` <m2yd6200be21005031426n87ea43a0k968fd5898ce0b873@mail.gmail.com>
2010-05-03 21:49 ` Rafael J. Wysocki
[not found] ` <201005032349.00876.rjw@sisk.pl>
2010-05-03 22:01 ` Arve Hjønnevåg
[not found] ` <x2id6200be21005031501p7f151324wb8bbf928bc2cb25e@mail.gmail.com>
2010-05-04 20:02 ` Rafael J. Wysocki
2010-05-04 4:16 ` Pavel Machek
[not found] <1272667021-21312-1-git-send-email-arve@android.com>
[not found] ` <1272667021-21312-2-git-send-email-arve@android.com>
2010-04-30 22:36 ` Arve Hjønnevåg
2010-05-02 7:04 ` Pavel Machek
2010-05-02 21:23 ` Rafael J. Wysocki
2010-05-02 21:56 ` Alan Stern
[not found] <1272429119-12103-1-git-send-email-arve@android.com>
[not found] ` <1272429119-12103-2-git-send-email-arve@android.com>
2010-04-28 4:31 ` Arve Hjønnevåg
2010-04-28 20:58 ` Rafael J. Wysocki
[not found] ` <201004282258.51354.rjw@sisk.pl>
2010-04-28 22:31 ` Arve Hjønnevåg
[not found] ` <k2gd6200be21004281531y270549d7g8383f2c8a55038d4@mail.gmail.com>
2010-04-28 23:05 ` Rafael J. Wysocki
[not found] ` <201004290105.15707.rjw@sisk.pl>
2010-04-28 23:38 ` Arve Hjønnevåg
[not found] ` <h2jd6200be21004281638y6b751abesfcf6416707e6fee4@mail.gmail.com>
2010-04-29 21:11 ` Rafael J. Wysocki
2010-04-29 23:41 ` Arve Hjønnevåg
2009-04-15 1:41 [RFC][PATCH 0/8] Suspend block api Arve Hjønnevåg
2009-04-15 1:41 ` [PATCH 1/8] PM: Add suspend " Arve Hjønnevåg
2009-04-15 1:41 ` [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space Arve Hjønnevåg
2009-04-29 22:52 ` Rafael J. Wysocki
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox