Suspend block api (version 6)
Subsystems (6)
cover Suspend block api (version 6)
This patch series adds a suspend-block api that provides the same functionality as the android wakelock api. This version fixes a race in suspend blocking work, has some documentation changes and opportunistic suspend now uses the same workqueue as runtime pm.
--
Arve Hjønnevåg <[email protected]>
PATCH 1/8 PM: Add suspend block api.
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.
--- Documentation/power/opportunistic-suspend.txt | 119 +++++++++++ include/linux/suspend_blocker.h | 64 ++++++ kernel/power/Kconfig | 16 ++ kernel/power/Makefile | 1 + kernel/power/main.c | 92 ++++++++- kernel/power/power.h | 9 + kernel/power/suspend.c | 4 +- kernel/power/suspend_blocker.c | 261 +++++++++++++++++++++++++ 8 files changed, 559 insertions(+), 7 deletions(-) create mode 100644 Documentation/power/opportunistic-suspend.txt create mode 100755 include/linux/suspend_blocker.h create mode 100644 kernel/power/suspend_blocker.c
Documentation/power/opportunistic-suspend.txt new file +119 -0
@@ -0,0 +1,119 @@ +Opportunistic Suspend +===================== + +Opportunistic suspend is a feature allowing the system to be suspended (ie. put +into one of the available sleep states) automatically whenever it is regarded +as idle. The suspend blockers framework described below is used to determine +when that happens. + +The /sys/power/policy sysfs attribute is used to switch the system between the +opportunistic and "forced" suspend behavior, where in the latter case the +system is only suspended if a specific value, corresponding to one of the +available system sleep states, is written into /sys/power/state. However, in +the former, opportunistic, case the system is put into the sleep state +corresponding to the value written to /sys/power/state whenever there are no +active suspend blockers. The default policy is "forced". Also, suspend blockers +do not affect sleep states entered from idle. + +When the policy is "opportunisic", there is a special value, "on", that can be +written to /sys/power/state. This will block the automatic sleep request, as if +a suspend blocker was used by a device driver. This way the opportunistic +suspend may be blocked by user space whithout switching back to the "forced" +mode. + +A suspend blocker is an object used to inform the PM subsystem when the system +can or cannot be suspended in the "opportunistic" mode (the "forced" mode +ignores suspend blockers). To use it, a device driver creates a struct +suspend_blocker that must be initialized with suspend_blocker_init(). Before +freeing the suspend_blocker structure or its name, suspend_blocker_destroy() +must be called on it. + +A suspend blocker is activated using suspend_block(), which prevents the PM +subsystem from putting the system into the requested sleep state in the +"opportunistic" mode until the suspend blocker is deactivated with +suspend_unblock(). Multiple suspend blockers may be active simultaneously, and +the system will not suspend as long as at least one of them is active. + +If opportunistic suspend is already in progress when suspend_block() is called, +it will abort the suspend, unless suspend_ops->enter has already been +executed. If suspend is aborted this way, the system is usually not fully +operational at that point. The suspend callbacks of some drivers may still be +running and it usually takes time to restore the system to the fully operational +state. + +Here's an example showing how a cell phone or other embedded system can handle +keystrokes (or other input events) in the presence of suspend blockers. Use +set_irq_wake or a platform specific api to make sure the keypad interrupt wakes +up the cpu. Once the keypad driver has resumed, the sequence of events can look +like this: + +- The Keypad driver gets an interrupt. It then calls suspend_block on the + keypad-scan suspend_blocker and starts scanning the keypad matrix. +- The keypad-scan code detects a key change and reports it to the input-event + driver. +- The input-event driver sees the key change, enqueues an event, and calls + suspend_block on the input-event-queue suspend_blocker. +- The keypad-scan code detects that no keys are held and calls suspend_unblock + on the keypad-scan suspend_blocker. +- The user-space input-event thread returns from select/poll, calls + suspend_block on the process-input-events suspend_blocker and then calls read + on the input-event device. +- The input-event driver dequeues the key-event and, since the queue is now + empty, it calls suspend_unblock on the input-event-queue suspend_blocker. +- The user-space input-event thread returns from read. If it determines that + the key should be ignored, it calls suspend_unblock on the + process_input_events suspend_blocker and then calls select or poll. The + system will automatically suspend again, since now no suspend blockers are + active. + +If the key that was pressed instead should preform a simple action (for example, +adjusting the volume), this action can be performed right before calling +suspend_unblock on the process_input_events suspend_blocker. However, if the key +triggers a longer-running action, that action needs its own suspend_blocker and +suspend_block must be called on that suspend blocker before calling +suspend_unblock on the process_input_events suspend_blocker. + + Key pressed Key released + | | +keypad-scan ++++++++++++++++++ +input-event-queue +++ +++ +process-input-events +++ +++ + + +Driver API +========== + +A driver can use the suspend block api by adding a suspend_blocker variable to +its state and calling suspend_blocker_init. For instance: +struct state { + struct suspend_blocker suspend_blocker; +} + +init() { + suspend_blocker_init(&state->suspend_blocker, "suspend-blocker-name"); +} + +Before freeing the memory, suspend_blocker_destroy must be called: + +uninit() { + suspend_blocker_destroy(&state->suspend_blocker); +} + +When the driver determines that it needs to run (usually in an interrupt +handler) it calls suspend_block: + suspend_block(&state->suspend_blocker); + +When it no longer needs to run it calls suspend_unblock: + suspend_unblock(&state->suspend_blocker); + +Calling suspend_block when the suspend blocker is active or suspend_unblock when +it is not active has no effect (i.e., these functions don't nest). This allows +drivers to update their state and call suspend suspend_block or suspend_unblock +based on the result. +For instance: + +if (list_empty(&state->pending_work)) + suspend_unblock(&state->suspend_blocker); +else + suspend_block(&state->suspend_blocker); +
include/linux/suspend_blocker.h new file +64 -0
64 lines not on this page · raw message
kernel/power/Kconfig +16 -0
@@ -130,6 +130,22 @@ config SUSPEND_FREEZER Turning OFF this setting is NOT recommended! If in doubt, say Y. +config OPPORTUNISTIC_SUSPEND + bool "Suspend blockers" + depends on PM_SLEEP + select RTC_LIB + default n + ---help--- + Opportunistic sleep support. Allows the system to be put into a sleep + state opportunistically, if it doesn't do any useful work at the + moment. The PM subsystem is switched into this mode of operation by + writing "opportunistic" into /sys/power/policy, while writing + "forced" to this file turns the opportunistic suspend feature off. + In the "opportunistic" mode suspend blockers are used to determine + when to suspend the system and the value written to /sys/power/state + determines the sleep state the system will be put into when there are + no active suspend blockers. + config HIBERNATION_NVS bool
kernel/power/Makefile +1 -0
@@ -7,6 +7,7 @@ obj-$(CONFIG_PM) += main.o obj-$(CONFIG_PM_SLEEP) += console.o obj-$(CONFIG_FREEZER) += process.o obj-$(CONFIG_SUSPEND) += suspend.o +obj-$(CONFIG_OPPORTUNISTIC_SUSPEND) += suspend_blocker.o obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o obj-$(CONFIG_HIBERNATION_NVS) += hibernate_nvs.o
kernel/power/main.c +86 -6
162 lines not on this page · raw message
kernel/power/power.h +9 -0
@@ -236,3 +236,12 @@ static inline void suspend_thaw_processes(void) { }#endif + +/* kernel/power/suspend_block.c */ +extern int request_suspend_state (suspend_state_t state); +extern bool request_suspend_valid_state (suspend_state_t state); +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND +extern void __init suspend_block_init (void ); +#else +static inline void suspend_block_init (void ) {} +#endif
kernel/power/suspend.c +3 -1
@@ -16,10 +16,12 @@#include <linux/cpu.h> #include <linux/syscalls.h> #include <linux/gfp.h> +#include <linux/suspend_blocker.h> #include "power.h" const char *const pm_states[PM_SUSPEND_MAX ] = { + [PM_SUSPEND_ON ] ="on" , [PM_SUSPEND_STANDBY ] ="standby" , [PM_SUSPEND_MEM ] ="mem" , };
@@ -157,7 +159,7 @@ static int suspend_enter(suspend_state_t state) error =sysdev_suspend (PMSG_SUSPEND );if (!error) { -if (!suspend_test (TEST_CORE )) +if (!suspend_is_blocked () && !suspend_test (TEST_CORE )) error = suspend_ops->enter (state);sysdev_resume (); }
kernel/power/suspend_blocker.c new file +261 -0
261 lines not on this page · raw message
Signature · 6 lines
1.6.5.1 _______________________________________________ linux-pm mailing list [email protected] https://lists.linux-foundation.org/mailman/listinfo/linux-pm
PATCH 1/8 PM: Add suspend block api.
In reply to Arve HjønnevågAdds /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.
--- Documentation/power/opportunistic-suspend.txt | 119 +++++++++++ include/linux/suspend_blocker.h | 64 ++++++ kernel/power/Kconfig | 16 ++ kernel/power/Makefile | 1 + kernel/power/main.c | 92 ++++++++- kernel/power/power.h | 9 + kernel/power/suspend.c | 4 +- kernel/power/suspend_blocker.c | 261 +++++++++++++++++++++++++ 8 files changed, 559 insertions(+), 7 deletions(-) create mode 100644 Documentation/power/opportunistic-suspend.txt create mode 100755 include/linux/suspend_blocker.h create mode 100644 kernel/power/suspend_blocker.c
Documentation/power/opportunistic-suspend.txt new file +119 -0
@@ -0,0 +1,119 @@ +Opportunistic Suspend +===================== + +Opportunistic suspend is a feature allowing the system to be suspended (ie. put +into one of the available sleep states) automatically whenever it is regarded +as idle. The suspend blockers framework described below is used to determine +when that happens. + +The /sys/power/policy sysfs attribute is used to switch the system between the +opportunistic and "forced" suspend behavior, where in the latter case the +system is only suspended if a specific value, corresponding to one of the +available system sleep states, is written into /sys/power/state. However, in +the former, opportunistic, case the system is put into the sleep state +corresponding to the value written to /sys/power/state whenever there are no +active suspend blockers. The default policy is "forced". Also, suspend blockers +do not affect sleep states entered from idle. + +When the policy is "opportunisic", there is a special value, "on", that can be +written to /sys/power/state. This will block the automatic sleep request, as if +a suspend blocker was used by a device driver. This way the opportunistic +suspend may be blocked by user space whithout switching back to the "forced" +mode. + +A suspend blocker is an object used to inform the PM subsystem when the system +can or cannot be suspended in the "opportunistic" mode (the "forced" mode +ignores suspend blockers). To use it, a device driver creates a struct +suspend_blocker that must be initialized with suspend_blocker_init(). Before +freeing the suspend_blocker structure or its name, suspend_blocker_destroy() +must be called on it. + +A suspend blocker is activated using suspend_block(), which prevents the PM +subsystem from putting the system into the requested sleep state in the +"opportunistic" mode until the suspend blocker is deactivated with +suspend_unblock(). Multiple suspend blockers may be active simultaneously, and +the system will not suspend as long as at least one of them is active. + +If opportunistic suspend is already in progress when suspend_block() is called, +it will abort the suspend, unless suspend_ops->enter has already been +executed. If suspend is aborted this way, the system is usually not fully +operational at that point. The suspend callbacks of some drivers may still be +running and it usually takes time to restore the system to the fully operational +state. + +Here's an example showing how a cell phone or other embedded system can handle +keystrokes (or other input events) in the presence of suspend blockers. Use +set_irq_wake or a platform specific api to make sure the keypad interrupt wakes +up the cpu. Once the keypad driver has resumed, the sequence of events can look +like this: + +- The Keypad driver gets an interrupt. It then calls suspend_block on the + keypad-scan suspend_blocker and starts scanning the keypad matrix. +- The keypad-scan code detects a key change and reports it to the input-event + driver. +- The input-event driver sees the key change, enqueues an event, and calls + suspend_block on the input-event-queue suspend_blocker. +- The keypad-scan code detects that no keys are held and calls suspend_unblock + on the keypad-scan suspend_blocker. +- The user-space input-event thread returns from select/poll, calls + suspend_block on the process-input-events suspend_blocker and then calls read + on the input-event device. +- The input-event driver dequeues the key-event and, since the queue is now + empty, it calls suspend_unblock on the input-event-queue suspend_blocker. +- The user-space input-event thread returns from read. If it determines that + the key should be ignored, it calls suspend_unblock on the + process_input_events suspend_blocker and then calls select or poll. The + system will automatically suspend again, since now no suspend blockers are + active. + +If the key that was pressed instead should preform a simple action (for example, +adjusting the volume), this action can be performed right before calling +suspend_unblock on the process_input_events suspend_blocker. However, if the key +triggers a longer-running action, that action needs its own suspend_blocker and +suspend_block must be called on that suspend blocker before calling +suspend_unblock on the process_input_events suspend_blocker. + + Key pressed Key released + | | +keypad-scan ++++++++++++++++++ +input-event-queue +++ +++ +process-input-events +++ +++ + + +Driver API +========== + +A driver can use the suspend block api by adding a suspend_blocker variable to +its state and calling suspend_blocker_init. For instance: +struct state { + struct suspend_blocker suspend_blocker; +} + +init() { + suspend_blocker_init(&state->suspend_blocker, "suspend-blocker-name"); +} + +Before freeing the memory, suspend_blocker_destroy must be called: + +uninit() { + suspend_blocker_destroy(&state->suspend_blocker); +} + +When the driver determines that it needs to run (usually in an interrupt +handler) it calls suspend_block: + suspend_block(&state->suspend_blocker); + +When it no longer needs to run it calls suspend_unblock: + suspend_unblock(&state->suspend_blocker); + +Calling suspend_block when the suspend blocker is active or suspend_unblock when +it is not active has no effect (i.e., these functions don't nest). This allows +drivers to update their state and call suspend suspend_block or suspend_unblock +based on the result. +For instance: + +if (list_empty(&state->pending_work)) + suspend_unblock(&state->suspend_blocker); +else + suspend_block(&state->suspend_blocker); +
include/linux/suspend_blocker.h new file +64 -0
64 lines not on this page · raw message
kernel/power/Kconfig +16 -0
@@ -130,6 +130,22 @@ config SUSPEND_FREEZER Turning OFF this setting is NOT recommended! If in doubt, say Y. +config OPPORTUNISTIC_SUSPEND + bool "Suspend blockers" + depends on PM_SLEEP + select RTC_LIB + default n + ---help--- + Opportunistic sleep support. Allows the system to be put into a sleep + state opportunistically, if it doesn't do any useful work at the + moment. The PM subsystem is switched into this mode of operation by + writing "opportunistic" into /sys/power/policy, while writing + "forced" to this file turns the opportunistic suspend feature off. + In the "opportunistic" mode suspend blockers are used to determine + when to suspend the system and the value written to /sys/power/state + determines the sleep state the system will be put into when there are + no active suspend blockers. + config HIBERNATION_NVS bool
kernel/power/Makefile +1 -0
@@ -7,6 +7,7 @@ obj-$(CONFIG_PM) += main.o obj-$(CONFIG_PM_SLEEP) += console.o obj-$(CONFIG_FREEZER) += process.o obj-$(CONFIG_SUSPEND) += suspend.o +obj-$(CONFIG_OPPORTUNISTIC_SUSPEND) += suspend_blocker.o obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o obj-$(CONFIG_HIBERNATION_NVS) += hibernate_nvs.o
kernel/power/main.c +86 -6
162 lines not on this page · raw message
kernel/power/power.h +9 -0
@@ -236,3 +236,12 @@ static inline void suspend_thaw_processes(void) { }#endif + +/* kernel/power/suspend_block.c */ +extern int request_suspend_state (suspend_state_t state); +extern bool request_suspend_valid_state (suspend_state_t state); +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND +extern void __init suspend_block_init (void ); +#else +static inline void suspend_block_init (void ) {} +#endif
kernel/power/suspend.c +3 -1
@@ -16,10 +16,12 @@#include <linux/cpu.h> #include <linux/syscalls.h> #include <linux/gfp.h> +#include <linux/suspend_blocker.h> #include "power.h" const char *const pm_states[PM_SUSPEND_MAX ] = { + [PM_SUSPEND_ON ] ="on" , [PM_SUSPEND_STANDBY ] ="standby" , [PM_SUSPEND_MEM ] ="mem" , };
@@ -157,7 +159,7 @@ static int suspend_enter(suspend_state_t state) error =sysdev_suspend (PMSG_SUSPEND );if (!error) { -if (!suspend_test (TEST_CORE )) +if (!suspend_is_blocked () && !suspend_test (TEST_CORE )) error = suspend_ops->enter (state);sysdev_resume (); }
kernel/power/suspend_blocker.c new file +261 -0
261 lines not on this page · raw message
Signature · 1 line
1.6.5.1
PATCH 2/8 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. The device has ioctls to create a suspend_blocker, and to block and unblock suspend. To delete the suspend_blocker, close the device.
--- 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
Documentation/ioctl/ioctl-number.txt +2 -1
@@ -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
Documentation/power/opportunistic-suspend.txt +17 -0
@@ -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); +
include/linux/suspend_block_dev.h new file +25 -0
@@ -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
kernel/power/Kconfig +9 -0
@@ -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
kernel/power/Makefile +1 -0
@@ -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
kernel/power/user_suspend_blocker.c new file +128 -0
128 lines not on this page · raw message
Signature · 6 lines
1.6.5.1 _______________________________________________ linux-pm mailing list [email protected] https://lists.linux-foundation.org/mailman/listinfo/linux-pm
PATCH 3/8 PM: suspend_block: Abort task freezing if a suspend_blocker is active.
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.
--- kernel/power/process.c | 12 ++++++++++-- 1 files changed, 10 insertions(+), 2 deletions(-)
kernel/power/process.c +10 -2
@@ -15,6 +15,7 @@#include <linux/syscalls.h> #include <linux/freezer.h> #include <linux/delay.h> +#include <linux/suspend_blocker.h> /* * Timeout for stopping processes
@@ -38,6 +39,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 +65,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 +91,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);
Signature · 6 lines
1.6.5.1 _______________________________________________ linux-pm mailing list [email protected] https://lists.linux-foundation.org/mailman/listinfo/linux-pm
PATCH 4/8 PM: suspend_block: Add debugfs file
Report active and inactive suspend blockers in/sys/kernel/debug/suspend_blockers.
--- kernel/power/suspend_blocker.c | 43 ++++++++++++++++++++++++++++++++++++++- 1 files changed, 41 insertions(+), 2 deletions(-)
kernel/power/suspend_blocker.c +41 -2
@@ -17,6 +17,7 @@#include <linux/rtc.h> #include <linux/suspend.h> #include <linux/suspend_blocker.h> +#include <linux/debugfs.h> #include "power.h" extern struct workqueue_struct *pm_wq;
@@ -42,6 +43,7 @@ static int current_event_num;struct suspend_blocker main_suspend_blocker;static suspend_state_t requested_suspend_state =PM_SUSPEND_MEM ;static bool enable_suspend_blockers; +static struct dentry *suspend_blocker_stats_dentry; #define pr_info_time(fmt, args...) \ do { \
@@ -55,6 +57,21 @@ static bool enable_suspend_blockers; tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec); \ }while (0 ); +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 void print_active_blockers_locked (void ) {struct suspend_blocker *blocker;
@@ -106,8 +123,8 @@ static DECLARE_WORK(suspend_work, suspend_worker);/** * suspend_blocker_init() - Initialize a suspend blocker * @blocker: The suspend blocker to initialize. -* @name: The name of the suspend blocker to show in debug messages. -* +* @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_destroy. */
@@ -254,8 +271,30 @@ int request_suspend_state(suspend_state_t state)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, +}; +void __init suspend_block_init (void ) {suspend_blocker_init (&main_suspend_blocker,"main" );suspend_block (&main_suspend_blocker); } + +static int __init suspend_block_postcore_init (void ) +{ + suspend_blocker_stats_dentry =debugfs_create_file ("suspend_blockers" , +S_IRUGO ,NULL ,NULL , &suspend_blocker_stats_fops); +return 0 ; +} + +postcore_initcall (suspend_block_postcore_init);
Signature · 6 lines
1.6.5.1 _______________________________________________ linux-pm mailing list [email protected] https://lists.linux-foundation.org/mailman/listinfo/linux-pm
PATCH 5/8 PM: suspend_block: Add suspend_blocker stats
Report suspend block stats in /sys/kernel/debug/suspend_blockers.
--- include/linux/suspend_blocker.h | 21 ++++- kernel/power/Kconfig | 7 ++ kernel/power/power.h | 5 + kernel/power/suspend.c | 4 +- kernel/power/suspend_blocker.c | 190 +++++++++++++++++++++++++++++++++++++-- 5 files changed, 218 insertions(+), 9 deletions(-)
include/linux/suspend_blocker.h +20 -1
@@ -17,12 +17,21 @@#define _LINUX_SUSPEND_BLOCKER_H#include <linux/list.h> +#include <linux/ktime.h> /** * 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, active and stats state. * @name: Name used for debugging. +* @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. * * When a suspend_blocker is active it prevents the system from entering * opportunistic suspend.
@@ -35,6 +44,16 @@ struct suspend_blocker {struct list_head link;int flags;const char *name; +#ifdef CONFIG_SUSPEND_BLOCKER_STATS +struct { +int count; +int wakeup_count; +ktime_t total_time; +ktime_t prevent_suspend_time; +ktime_t max_time; +ktime_t last_time; + } stat; +#endif #endif };
kernel/power/Kconfig +7 -0
@@ -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 SUSPEND_BLOCKER_STATS + bool "Suspend block stats" + depends on OPPORTUNISTIC_SUSPEND + default y + ---help--- + Report suspend block stats in /sys/kernel/debug/suspend_blockers + config USER_SUSPEND_BLOCKERS bool "Userspace suspend blockers" depends on OPPORTUNISTIC_SUSPEND
kernel/power/power.h +5 -0
@@ -245,3 +245,8 @@ extern void __init suspend_block_init(void);#else static inline void suspend_block_init (void ) {}#endif +#ifdef CONFIG_SUSPEND_BLOCKER_STATS +void about_to_enter_suspend (void ); +#else +static inline void about_to_enter_suspend (void ) {} +#endif
kernel/power/suspend.c +3 -1
@@ -159,8 +159,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 (); }
kernel/power/suspend_blocker.c +183 -7
266 lines not on this page · raw message
Signature · 6 lines
1.6.5.1 _______________________________________________ linux-pm mailing list [email protected] https://lists.linux-foundation.org/mailman/listinfo/linux-pm
PATCH 6/8 PM: Add suspend blocking work.
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.
--- include/linux/suspend_blocker.h | 67 ++++++++++++++++++++++++ kernel/power/suspend_blocker.c | 109 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 176 insertions(+), 0 deletions(-)
include/linux/suspend_blocker.h +67 -0
@@ -18,6 +18,7 @@#include <linux/list.h> #include <linux/ktime.h> +#include <linux/workqueue.h> /** * struct suspend_blocker - the basic suspend_blocker structure
@@ -57,6 +58,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 void suspend_blocker_init (struct suspend_blocker *blocker,const char *name);
@@ -66,6 +99,14 @@ void suspend_unblock(struct suspend_blocker *blocker);bool suspend_blocker_is_active (struct suspend_blocker *blocker);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 static inline void suspend_blocker_init(struct suspend_blocker *blocker,
@@ -77,6 +118,32 @@ static inline bool suspend_blocker_is_active(struct suspend_blocker *bl) {return 0 ; }static inline bool suspend_is_blocked (void ) {return 0 ; } +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
kernel/power/suspend_blocker.c +109 -0
112 lines not on this page · raw message
Signature · 6 lines
1.6.5.1 _______________________________________________ linux-pm mailing list [email protected] https://lists.linux-foundation.org/mailman/listinfo/linux-pm
PATCH 7/8 Input: Block suspend while event queue is not empty.
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.
--- drivers/input/evdev.c | 22 ++++++++++++++++++++++ include/linux/input.h | 3 +++ 2 files changed, 25 insertions(+), 0 deletions(-)
drivers/input/evdev.c +22 -0
@@ -20,6 +20,7 @@#include <linux/input.h> #include <linux/major.h> #include <linux/device.h> +#include <linux/suspend_blocker.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_destroy (&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_destroy (&client->suspend_blocker); + client->use_suspend_blocker = !!p; +spin_unlock_irq (&client->buffer_lock); +return 0 ; +default :if (_IOC_TYPE (cmd) !='E' )
include/linux/input.h +3 -0
@@ -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 */
Signature · 1 line
1.6.5.1
PATCH 8/8 power_supply: Block suspend while power supply change notifications are pending
When connecting usb or the charger the device would often go back to sleep before the charge led and screen turned on.
--- drivers/power/power_supply_core.c | 9 ++++++--- include/linux/power_supply.h | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-)
drivers/power/power_supply_core.c +6 -3
@@ -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);
include/linux/power_supply.h +2 -1
@@ -14,6 +14,7 @@#define __LINUX_POWER_SUPPLY_H__#include <linux/device.h> +#include <linux/suspend_blocker.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;
Signature · 6 lines
1.6.5.1 _______________________________________________ linux-pm mailing list [email protected] https://lists.linux-foundation.org/mailman/listinfo/linux-pm
PATCH 7/8 Input: Block suspend while event queue is not empty.
In reply to Arve HjønnevågAdd 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.
--- drivers/input/evdev.c | 22 ++++++++++++++++++++++ include/linux/input.h | 3 +++ 2 files changed, 25 insertions(+), 0 deletions(-)
drivers/input/evdev.c +22 -0
@@ -20,6 +20,7 @@#include <linux/input.h> #include <linux/major.h> #include <linux/device.h> +#include <linux/suspend_blocker.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_destroy (&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_destroy (&client->suspend_blocker); + client->use_suspend_blocker = !!p; +spin_unlock_irq (&client->buffer_lock); +return 0 ; +default :if (_IOC_TYPE (cmd) !='E' )
include/linux/input.h +3 -0
@@ -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 */
Signature · 6 lines
1.6.5.1 _______________________________________________ linux-pm mailing list [email protected] https://lists.linux-foundation.org/mailman/listinfo/linux-pm
Re: [PATCH 6/8] PM: Add suspend blocking work.
In reply to Arve HjønnevågQuoted 8 lines · Arve Hjønnevåg
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_blockerfor 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 <[email protected]>
Thank you.
Signature · 5 lines
tejun _______________________________________________ linux-pm mailing list [email protected] https://lists.linux-foundation.org/mailman/listinfo/linux-pm
Re: [PATCH 6/8] PM: Add suspend blocking work.
In reply to Arve HjønnevågQuoted 8 lines · Arve Hj??nnev??g
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_blockerfor 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 <[email protected]>
Looks ok.
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 6/8] PM: Add suspend blocking work.
In reply to Arve HjønnevågQuoted 8 lines · Arve Hj??nnev??g
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_blockerfor 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 <[email protected]>
Looks ok.
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 4/8] PM: suspend_block: Add debugfs file
In reply to Arve Hjønnevågkernel/power/suspend_blocker.c static bool enable_suspend_blockers; · line 71
Quoted 13 lines · Arve Hjønnevåg
kernel/power/suspend_blocker.c +12
-0+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);
Could you report the pid here too?
The name set by the application might be meaningless or duplicated.
-Andi
Signature · 1 line
[email protected] -- Speaking for myself only.
Re: [PATCH 4/8] PM: suspend_block: Add debugfs file
In reply to Arve Hjønnevågkernel/power/suspend_blocker.c static bool enable_suspend_blockers; · line 71
Quoted 13 lines · Arve Hjønnevåg
kernel/power/suspend_blocker.c +12
-0+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);
Could you report the pid here too?
The name set by the application might be meaningless or duplicated.
-Andi
Signature · 1 line
[email protected] -- Speaking for myself only.
Re: [PATCH 4/8] PM: suspend_block: Add debugfs file
2010/5/4 Andi Kleen <[email protected]>:
Quoted 17 lines
kernel/power/suspend_blocker.c static bool enable_suspend_blockers; · line 71
Quoted 13 lines · Arve Hjønnevåg
kernel/power/suspend_blocker.c +12
-0+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);Could you report the pid here too?
Most of the suspend blockers are in the kernel, and does not have a pid.
Quoted 2 lines
The name set by the application might be meaningless or duplicated.
Currently all the names set by android user-space are unique but the pids are not. We can add columns, or extend the name of user space suspend blockers in the ioctl interface, later if needed.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 4/8] PM: suspend_block: Add debugfs file
In reply to Andi Kleen2010/5/4 Andi Kleen <[email protected]>:
Quoted 17 lines
kernel/power/suspend_blocker.c static bool enable_suspend_blockers; · line 71
Quoted 13 lines · Arve Hjønnevåg
kernel/power/suspend_blocker.c +12
-0+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);Could you report the pid here too?
Most of the suspend blockers are in the kernel, and does not have a pid.
Quoted 2 lines
The name set by the application might be meaningless or duplicated.
Currently all the names set by android user-space are unique but the pids are not. We can add columns, or extend the name of user space suspend blockers in the ioctl interface, later if needed.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 3/8] PM: suspend_block: Abort task freezing if a suspend_blocker is active.
In reply to Arve HjønnevågHi!
Quoted 10 lines
If a
suspend_blockeris active, suspend will fail anyway. Sincetry_to_freeze_taskscan 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 <[email protected]>
I acked this one before, please preserve such tags.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 3/8] PM: suspend_block: Abort task freezing if a suspend_blocker is active.
In reply to Arve HjønnevågHi!
Quoted 10 lines
If a
suspend_blockeris active, suspend will fail anyway. Sincetry_to_freeze_taskscan 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 <[email protected]>
I acked this one before, please preserve such tags.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Pavel Machek
NAKRe: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Arve HjønnevågQuoted 4 lines · Arve Hj??nnev??g
Add a misc device, "
suspend_blocker", that allows user-space processes to block auto suspend. The device has ioctls to create asuspend_blocker, and to block and unblock suspend. To delete thesuspend_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...
Quoted 1 line
Signed-off-by Arve Hj??nnev??g <[email protected]>
NAK.
Quoted 247 lines
--- 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.cDocumentation/ioctl/ioctl-number.txt +2
-1@@ -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.hDocumentation/power/opportunistic-suspend.txt +17
-0@@ -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); +include/linux/suspend_block_dev.h new file +25
-0@@ -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 kernel/power/Kconfig +9
-0@@ -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 boolkernel/power/Makefile +1
-0@@ -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.okernel/power/user_suspend_blocker.c new file +128
-0@@ -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);
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Pavel Machek
NAKRe: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Arve HjønnevågQuoted 4 lines · Arve Hj??nnev??g
Add a misc device, "
suspend_blocker", that allows user-space processes to block auto suspend. The device has ioctls to create asuspend_blocker, and to block and unblock suspend. To delete thesuspend_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...
Quoted 1 line
Signed-off-by Arve Hj??nnev??g <[email protected]>
NAK.
Quoted 247 lines
--- 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.cDocumentation/ioctl/ioctl-number.txt +2
-1@@ -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.hDocumentation/power/opportunistic-suspend.txt +17
-0@@ -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); +include/linux/suspend_block_dev.h new file +25
-0@@ -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 kernel/power/Kconfig +9
-0@@ -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 boolkernel/power/Makefile +1
-0@@ -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.okernel/power/user_suspend_blocker.c new file +128
-0@@ -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);
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Arve HjønnevågQuoted 166 lines · Arve Hjønnevåg
Add a misc device, "
suspend_blocker", that allows user-space processes to block auto suspend. The device has ioctls to create asuspend_blocker, and to block and unblock suspend. To delete thesuspend_blocker, close the device.Signed-off-by Arve Hjønnevåg <[email protected]>--- 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.cDocumentation/ioctl/ioctl-number.txt +2
-1@@ -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.hDocumentation/power/opportunistic-suspend.txt +17
-0@@ -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); +include/linux/suspend_block_dev.h new file +25
-0@@ -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 kernel/power/Kconfig +9
-0@@ -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 boolkernel/power/Makefile +1
-0@@ -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.okernel/power/user_suspend_blocker.c new file +41
-0@@ -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)
kernel/power/user_suspend_blocker.c line 51
Quoted 10 lines
kernel/power/user_suspend_blocker.c new file +10
-0+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
Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space
Quoted 3 lines · Rafael J. Wysocki
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
Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Rafael J. WysockiQuoted 3 lines · Rafael J. Wysocki
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
Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space
Quoted 7 lines · Alan Stern
Quoted 3 lines · Rafael J. Wysocki
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
Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Alan SternQuoted 7 lines · Alan Stern
Quoted 3 lines · Rafael J. Wysocki
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
Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space
Quoted 11 lines · Rafael J. Wysocki
Quoted 7 lines · Alan Stern
Quoted 3 lines · Rafael J. Wysocki
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.
Quoted 8 lines
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.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Rafael J. WysockiQuoted 11 lines · Rafael J. Wysocki
Quoted 7 lines · Alan Stern
Quoted 3 lines · Rafael J. Wysocki
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.
Quoted 8 lines
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.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space
Quoted 17 lines · Arve Hjønnevåg
Quoted 16 lines · Rafael J. Wysocki
Quoted 7 lines · Alan Stern
Quoted 3 lines · Rafael J. Wysocki
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.
Quoted 7 lines
Quoted 3 lines
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
Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space
2010/5/3 Rafael J. Wysocki <[email protected]>:
Quoted 22 lines · Arve Hjønnevåg
Quoted 21 lines · Rafael J. Wysocki
Quoted 19 lines · Alan Stern
Quoted 7 lines · Rafael J. Wysocki
Quoted 4 lines
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.
Quoted 6 lines
Quoted 3 lines
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.
Quoted 7 lines
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).
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Rafael J. Wysocki2010/5/3 Rafael J. Wysocki <[email protected]>:
Quoted 22 lines · Arve Hjønnevåg
Quoted 21 lines · Rafael J. Wysocki
Quoted 19 lines · Alan Stern
Quoted 7 lines · Rafael J. Wysocki
Quoted 4 lines
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.
Quoted 6 lines
Quoted 3 lines
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.
Quoted 7 lines
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).
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space
Quoted 23 lines · Arve Hjønnevåg
2010/5/3 Rafael J. Wysocki <[email protected]>:
Quoted 22 lines · Arve Hjønnevåg
Quoted 21 lines · Rafael J. Wysocki
Quoted 19 lines · Alan Stern
Quoted 7 lines · Rafael J. Wysocki
Quoted 4 lines
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.
Quoted 7 lines
Quoted 6 lines
Quoted 3 lines
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
Quoted 1 line
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?
Quoted 7 lines
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.
Quoted 9 lines
Quoted 7 lines
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
Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Arve HjønnevågQuoted 23 lines · Arve Hjønnevåg
2010/5/3 Rafael J. Wysocki <[email protected]>:
Quoted 22 lines · Arve Hjønnevåg
Quoted 21 lines · Rafael J. Wysocki
Quoted 19 lines · Alan Stern
Quoted 7 lines · Rafael J. Wysocki
Quoted 4 lines
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.
Quoted 7 lines
Quoted 6 lines
Quoted 3 lines
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
Quoted 1 line
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?
Quoted 7 lines
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.
Quoted 9 lines
Quoted 7 lines
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
Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Arve HjønnevågQuoted 17 lines · Arve Hjønnevåg
Quoted 16 lines · Rafael J. Wysocki
Quoted 7 lines · Alan Stern
Quoted 3 lines · Rafael J. Wysocki
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.
Quoted 7 lines
Quoted 3 lines
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
Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Rafael J. WysockiQuoted 11 lines · Rafael J. Wysocki
Quoted 7 lines · Alan Stern
Quoted 3 lines · Rafael J. Wysocki
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.
Quoted 8 lines
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.
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 2/8] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Rafael J. WysockiQuoted 11 lines · Rafael J. Wysocki
Quoted 7 lines · Alan Stern
Quoted 3 lines · Rafael J. Wysocki
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.
Quoted 8 lines
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.
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Pavel Machek
NAKRe: [PATCH 1/8] PM: Add suspend block api.
In reply to Arve HjønnevågHi!
Quoted 5 lines
Adds
/sys/power/policythat selects the behaviour of/sys/power/state. After setting the policy to opportunistic, writes to/sys/power/statebecome 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.
As I explained before (and got no reply), the proposed interface is ugly. It uses one sysfs file to change semantics of another one.
Quoted 1 line
Signed-off-by Arve Hj??nnev??g <[email protected]>
NAK.
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Pavel Machek
NAKRe: [PATCH 1/8] PM: Add suspend block api.
In reply to Arve HjønnevågHi!
Quoted 5 lines
Adds
/sys/power/policythat selects the behaviour of/sys/power/state. After setting the policy to opportunistic, writes to/sys/power/statebecome 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.
As I explained before (and got no reply), the proposed interface is ugly. It uses one sysfs file to change semantics of another one.
Quoted 1 line
Signed-off-by Arve Hj??nnev??g <[email protected]>
NAK.
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 10 lines · Pavel Machek
Hi!
Quoted 5 lines
Adds
/sys/power/policythat selects the behaviour of/sys/power/state. After setting the policy to opportunistic, writes to/sys/power/statebecome 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.As I explained before (and got no reply), the proposed interface is ugly. It uses one sysfs file to change semantics of another one.
In fact this behavior was discussed at the LF Collab Summit and no one involved had any problem with that.
Quoted 3 lines
Quoted 1 line
Signed-off-by Arve Hj??nnev??g <[email protected]>NAK.
Ignored.
Thanks,
Rafael
Re: [PATCH 1/8] PM: Add suspend block api.
In reply to Pavel MachekQuoted 10 lines · Pavel Machek
Hi!
Quoted 5 lines
Adds
/sys/power/policythat selects the behaviour of/sys/power/state. After setting the policy to opportunistic, writes to/sys/power/statebecome 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.As I explained before (and got no reply), the proposed interface is ugly. It uses one sysfs file to change semantics of another one.
In fact this behavior was discussed at the LF Collab Summit and no one involved had any problem with that.
Quoted 3 lines
Quoted 1 line
Signed-off-by Arve Hj??nnev??g <[email protected]>NAK.
Ignored.
Thanks,
Rafael
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 9 lines · Rafael J. Wysocki
Quoted 8 lines · Pavel Machek
Hi!
Quoted 5 lines
Adds
/sys/power/policythat selects the behaviour of/sys/power/state. After setting the policy to opportunistic, writes to/sys/power/statebecome 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.
Quoted 5 lines
Quoted 2 lines
As I explained before (and got no reply), the proposed interface is ugly. It uses one sysfs file to change semantics of another one.
In fact this behavior was discussed at the LF Collab Summit and no one involved had any problem with that.
Well, I explained why I disliked in previous mail in more details, and neither you nor Arve explained why it is good solution.
I was not on LF Collab summit, so unfortunately I can't comment on that.
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
Signed-off-by Arve Hj??nnev??g <[email protected]>NAK.
Ignored.
WTF?
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 1/8] PM: Add suspend block api.
In reply to Rafael J. WysockiQuoted 9 lines · Rafael J. Wysocki
Quoted 8 lines · Pavel Machek
Hi!
Quoted 5 lines
Adds
/sys/power/policythat selects the behaviour of/sys/power/state. After setting the policy to opportunistic, writes to/sys/power/statebecome 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.
Quoted 5 lines
Quoted 2 lines
As I explained before (and got no reply), the proposed interface is ugly. It uses one sysfs file to change semantics of another one.
In fact this behavior was discussed at the LF Collab Summit and no one involved had any problem with that.
Well, I explained why I disliked in previous mail in more details, and neither you nor Arve explained why it is good solution.
I was not on LF Collab summit, so unfortunately I can't comment on that.
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
Signed-off-by Arve Hj??nnev??g <[email protected]>NAK.
Ignored.
WTF?
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 10 lines · Pavel Machek
Quoted 9 lines · Rafael J. Wysocki
Quoted 8 lines · Pavel Machek
Hi!
Quoted 5 lines
Adds
/sys/power/policythat selects the behaviour of/sys/power/state. After setting the policy to opportunistic, writes to/sys/power/statebecome 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.
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
As I explained before (and got no reply), the proposed interface is ugly. It uses one sysfs file to change semantics of another one.
In fact this behavior was discussed at the LF Collab Summit and no one involved had any problem with that.
Well, I explained why I disliked in previous mail in more details,
We do exactly the same thing with 'pm_test', so I'm not sure what the problem is.
Quoted 1 line
and neither you nor Arve explained why it is good solution.
Because it's less confusing. Having two different attributes returning almost the same contents and working in a slightly different way wouldn't be too clean IMO.
Also it reduces code duplication slightly.
Quoted 9 lines
I was not on LF Collab summit, so unfortunately I can't comment on that.
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
Signed-off-by Arve Hj??nnev??g <[email protected]>NAK.
Ignored.
WTF?
Literally. I'm not going to take that NAK into consideration.
Rafael
Re: [PATCH 1/8] PM: Add suspend block api.
Hi!
Quoted 8 lines
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
As I explained before (and got no reply), the proposed interface is ugly. It uses one sysfs file to change semantics of another one.
In fact this behavior was discussed at the LF Collab Summit and no one involved had any problem with that.
Well, I explained why I disliked in previous mail in more details,
Quoted 7 lines
We do exactly the same thing with '
pm_test', so I'm not sure what the problem is.Quoted 1 line
and neither you nor Arve explained why it is good solution.
Because it's less confusing. Having two different attributes returning almost the same contents and working in a slightly different way wouldn't be too clean IMO.
No, I don't think it is similar to pm_test. pm_test is debug-only, and orthogonal to state -- all combinations make sense.
With 'oportunistic > policy', state changes from blocking to nonblocking (surprise!). Plus, it is not orthogonal:
(assume we added s-t-flash on android for powersaving... or imagine I get oportunistic suspend working on PC --I was there with limited config on x60).
policy: oportunistic forced
state: on mem disk
First disadvantage of proposed interface is that while 'opportunistic mem' is active, I can't do 'forced disk' to save bit more power.
Next, not all combinations make sense.
oportunistic on == forced <nothing>
oportunistic disk -- probably something that will not be implemented any time soon.
oportunistic mem -- makes sense.
forced on -- NOP
forced mem -- makes sense.
forced disk -- makes sense.
So we have matrix of 7 possibilities, but only 4 make sense... IMO its confusing.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 1/8] PM: Add suspend block api.
In reply to Rafael J. WysockiHi!
Quoted 8 lines
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
As I explained before (and got no reply), the proposed interface is ugly. It uses one sysfs file to change semantics of another one.
In fact this behavior was discussed at the LF Collab Summit and no one involved had any problem with that.
Well, I explained why I disliked in previous mail in more details,
Quoted 7 lines
We do exactly the same thing with '
pm_test', so I'm not sure what the problem is.Quoted 1 line
and neither you nor Arve explained why it is good solution.
Because it's less confusing. Having two different attributes returning almost the same contents and working in a slightly different way wouldn't be too clean IMO.
No, I don't think it is similar to pm_test. pm_test is debug-only, and orthogonal to state -- all combinations make sense.
With 'oportunistic > policy', state changes from blocking to nonblocking (surprise!). Plus, it is not orthogonal:
(assume we added s-t-flash on android for powersaving... or imagine I get oportunistic suspend working on PC --I was there with limited config on x60).
policy: oportunistic forced
state: on mem disk
First disadvantage of proposed interface is that while 'opportunistic mem' is active, I can't do 'forced disk' to save bit more power.
Next, not all combinations make sense.
oportunistic on == forced <nothing>
oportunistic disk -- probably something that will not be implemented any time soon.
oportunistic mem -- makes sense.
forced on -- NOP
forced mem -- makes sense.
forced disk -- makes sense.
So we have matrix of 7 possibilities, but only 4 make sense... IMO its confusing.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 30 lines · Pavel Machek
Hi!
Quoted 8 lines
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
As I explained before (and got no reply), the proposed interface is ugly. It uses one sysfs file to change semantics of another one.
In fact this behavior was discussed at the LF Collab Summit and no one involved had any problem with that.
Well, I explained why I disliked in previous mail in more details,
Quoted 7 lines
We do exactly the same thing with '
pm_test', so I'm not sure what the problem is.Quoted 1 line
and neither you nor Arve explained why it is good solution.
Because it's less confusing. Having two different attributes returning almost the same contents and working in a slightly different way wouldn't be too clean IMO.
No, I don't think it is similar to
pm_test.pm_testis debug-only, and orthogonal to state -- all combinations make sense.With 'oportunistic > policy', state changes from blocking to nonblocking (surprise!). Plus, it is not orthogonal:
(assume we added s-t-flash on android for powersaving... or imagine I get oportunistic suspend working on PC --I was there with limited config on x60).
policy: oportunistic forced
Quoted 8 lines
state: on mem disk
First disadvantage of proposed interface is that while 'opportunistic mem' is active, I can't do 'forced disk' to save bit more power.
Next, not all combinations make sense.
oportunistic on == forced <nothing>
That's correct, but the "opportunistic on" thing is there to avoid switching back and forth from "opportunistic" to "forced". So that's a matter of convenience rather than anything else.
Quoted 2 lines
oportunistic disk -- probably something that will not be implemented any time soon.
Yes, and that's why "disk" won't work with "opportunistic" for now.
Quoted 3 lines
oportunistic mem -- makes sense.
forced on -- NOP
There won't be "on" with "forced" (that probably needs changing at the moment).
Quoted 5 lines
forced mem -- makes sense.
forced disk -- makes sense.
So we have matrix of 7 possibilities, but only 4 make sense... IMO its confusing.
The main problem is that the entire suspend subsystem is going to work in a different way when suspend blockers are enforced. Thus IMO it makes sense to provide a switch between the "opportunistic" and "forced" modes, because that clearly indicates to the user (or user space in general) how the whole suspend subsystem actually works at the moment.
As long as it's "opportunistic", the system will autosuspend if suspend blockers are not active and the behavior of "state" reflects that. If you want to enforce a transition, switch to "forced" first.
That's not at all confusing if you know what you're doing. The defailt mode is "forced", so the suspend subsystem works "as usual" by default. You have to directly switch it to "opportunistic" to change the behavior and once you've done that, you shouldn't really be surprised that the behavior has changed. That's what you've requested after all.
So no, I don't really think it's confusing.
Thanks,
Rafael
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 10 lines · Rafael J. Wysocki
The main problem is that the entire suspend subsystem is going to work in a different way when suspend blockers are enforced. Thus IMO it makes sense to provide a switch between the "opportunistic" and "forced" modes, because that clearly indicates to the user (or user space in general) how the whole suspend subsystem actually works at the moment.
As long as it's "opportunistic", the system will autosuspend if suspend blockers are not active and the behavior of "state" reflects that. If you want to enforce a transition, switch to "forced" first.
Quoted 5 lines
That's not at all confusing if you know what you're doing. The defailt mode is "forced", so the suspend subsystem works "as usual" by default. You have to directly switch it to "opportunistic" to change the behavior and once you've done that, you shouldn't really be surprised that the behavior has changed. That's what you've requested after all.
How about changing the contents of /sys/power/state depending on the current policy? When the policy is "forced" it should look the same as it does now. When the policy is "opportunistic" it should contain "mem" and "on".
Alan Stern
Re: [PATCH 1/8] PM: Add suspend block api.
In reply to Rafael J. WysockiQuoted 10 lines · Rafael J. Wysocki
The main problem is that the entire suspend subsystem is going to work in a different way when suspend blockers are enforced. Thus IMO it makes sense to provide a switch between the "opportunistic" and "forced" modes, because that clearly indicates to the user (or user space in general) how the whole suspend subsystem actually works at the moment.
As long as it's "opportunistic", the system will autosuspend if suspend blockers are not active and the behavior of "state" reflects that. If you want to enforce a transition, switch to "forced" first.
Quoted 5 lines
That's not at all confusing if you know what you're doing. The defailt mode is "forced", so the suspend subsystem works "as usual" by default. You have to directly switch it to "opportunistic" to change the behavior and once you've done that, you shouldn't really be surprised that the behavior has changed. That's what you've requested after all.
How about changing the contents of /sys/power/state depending on the current policy? When the policy is "forced" it should look the same as it does now. When the policy is "opportunistic" it should contain "mem" and "on".
Alan Stern
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 18 lines · Alan Stern
Quoted 10 lines · Rafael J. Wysocki
The main problem is that the entire suspend subsystem is going to work in a different way when suspend blockers are enforced. Thus IMO it makes sense to provide a switch between the "opportunistic" and "forced" modes, because that clearly indicates to the user (or user space in general) how the whole suspend subsystem actually works at the moment.
As long as it's "opportunistic", the system will autosuspend if suspend blockers are not active and the behavior of "state" reflects that. If you want to enforce a transition, switch to "forced" first.
Quoted 5 lines
That's not at all confusing if you know what you're doing. The defailt mode is "forced", so the suspend subsystem works "as usual" by default. You have to directly switch it to "opportunistic" to change the behavior and once you've done that, you shouldn't really be surprised that the behavior has changed. That's what you've requested after all.
Quoted 4 lines
How about changing the contents of
/sys/power/statedepending on the current policy? When the policy is "forced" it should look the same as it does now. When the policy is "opportunistic" it should contain "mem" and "on".
It already does this.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 1/8] PM: Add suspend block api.
In reply to Alan SternQuoted 18 lines · Alan Stern
Quoted 10 lines · Rafael J. Wysocki
The main problem is that the entire suspend subsystem is going to work in a different way when suspend blockers are enforced. Thus IMO it makes sense to provide a switch between the "opportunistic" and "forced" modes, because that clearly indicates to the user (or user space in general) how the whole suspend subsystem actually works at the moment.
As long as it's "opportunistic", the system will autosuspend if suspend blockers are not active and the behavior of "state" reflects that. If you want to enforce a transition, switch to "forced" first.
Quoted 5 lines
That's not at all confusing if you know what you're doing. The defailt mode is "forced", so the suspend subsystem works "as usual" by default. You have to directly switch it to "opportunistic" to change the behavior and once you've done that, you shouldn't really be surprised that the behavior has changed. That's what you've requested after all.
Quoted 4 lines
How about changing the contents of
/sys/power/statedepending on the current policy? When the policy is "forced" it should look the same as it does now. When the policy is "opportunistic" it should contain "mem" and "on".
It already does this.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 1/8] PM: Add suspend block api.
In reply to Pavel MachekQuoted 30 lines · Pavel Machek
Hi!
Quoted 8 lines
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
As I explained before (and got no reply), the proposed interface is ugly. It uses one sysfs file to change semantics of another one.
In fact this behavior was discussed at the LF Collab Summit and no one involved had any problem with that.
Well, I explained why I disliked in previous mail in more details,
Quoted 7 lines
We do exactly the same thing with '
pm_test', so I'm not sure what the problem is.Quoted 1 line
and neither you nor Arve explained why it is good solution.
Because it's less confusing. Having two different attributes returning almost the same contents and working in a slightly different way wouldn't be too clean IMO.
No, I don't think it is similar to
pm_test.pm_testis debug-only, and orthogonal to state -- all combinations make sense.With 'oportunistic > policy', state changes from blocking to nonblocking (surprise!). Plus, it is not orthogonal:
(assume we added s-t-flash on android for powersaving... or imagine I get oportunistic suspend working on PC --I was there with limited config on x60).
policy: oportunistic forced
Quoted 8 lines
state: on mem disk
First disadvantage of proposed interface is that while 'opportunistic mem' is active, I can't do 'forced disk' to save bit more power.
Next, not all combinations make sense.
oportunistic on == forced <nothing>
That's correct, but the "opportunistic on" thing is there to avoid switching back and forth from "opportunistic" to "forced". So that's a matter of convenience rather than anything else.
Quoted 2 lines
oportunistic disk -- probably something that will not be implemented any time soon.
Yes, and that's why "disk" won't work with "opportunistic" for now.
Quoted 3 lines
oportunistic mem -- makes sense.
forced on -- NOP
There won't be "on" with "forced" (that probably needs changing at the moment).
Quoted 5 lines
forced mem -- makes sense.
forced disk -- makes sense.
So we have matrix of 7 possibilities, but only 4 make sense... IMO its confusing.
The main problem is that the entire suspend subsystem is going to work in a different way when suspend blockers are enforced. Thus IMO it makes sense to provide a switch between the "opportunistic" and "forced" modes, because that clearly indicates to the user (or user space in general) how the whole suspend subsystem actually works at the moment.
As long as it's "opportunistic", the system will autosuspend if suspend blockers are not active and the behavior of "state" reflects that. If you want to enforce a transition, switch to "forced" first.
That's not at all confusing if you know what you're doing. The defailt mode is "forced", so the suspend subsystem works "as usual" by default. You have to directly switch it to "opportunistic" to change the behavior and once you've done that, you shouldn't really be surprised that the behavior has changed. That's what you've requested after all.
So no, I don't really think it's confusing.
Thanks,
Rafael
Re: [PATCH 1/8] PM: Add suspend block api.
In reply to Pavel MachekQuoted 10 lines · Pavel Machek
Quoted 9 lines · Rafael J. Wysocki
Quoted 8 lines · Pavel Machek
Hi!
Quoted 5 lines
Adds
/sys/power/policythat selects the behaviour of/sys/power/state. After setting the policy to opportunistic, writes to/sys/power/statebecome 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.
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
As I explained before (and got no reply), the proposed interface is ugly. It uses one sysfs file to change semantics of another one.
In fact this behavior was discussed at the LF Collab Summit and no one involved had any problem with that.
Well, I explained why I disliked in previous mail in more details,
We do exactly the same thing with 'pm_test', so I'm not sure what the problem is.
Quoted 1 line
and neither you nor Arve explained why it is good solution.
Because it's less confusing. Having two different attributes returning almost the same contents and working in a slightly different way wouldn't be too clean IMO.
Also it reduces code duplication slightly.
Quoted 9 lines
I was not on LF Collab summit, so unfortunately I can't comment on that.
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
Signed-off-by Arve Hj??nnev??g <[email protected]>NAK.
Ignored.
WTF?
Literally. I'm not going to take that NAK into consideration.
Rafael
Re: [PATCH 1/8] PM: Add suspend block api.
In reply to Arve HjønnevågQuoted 7 lines · Arve Hj??nnev??g
Adds
/sys/power/policythat selects the behaviour of/sys/power/state. After setting the policy to opportunistic, writes to/sys/power/statebecome 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 <[email protected]>
Also note that this patch mixes up adding new in-kernel interface with adding new userland API.
The in-kernel interface seems to be sane and it would be nice to merge it soon, unfortunately the strange userland API is in the same patch :-(.
Quoted 735 lines
--- Documentation/power/opportunistic-suspend.txt | 119 +++++++++++ include/linux/suspend_blocker.h | 64 ++++++ kernel/power/Kconfig | 16 ++ kernel/power/Makefile | 1 + kernel/power/main.c | 92 ++++++++- kernel/power/power.h | 9 + kernel/power/suspend.c | 4 +- kernel/power/suspend_blocker.c | 261 +++++++++++++++++++++++++ 8 files changed, 559 insertions(+), 7 deletions(-) create mode 100644 Documentation/power/opportunistic-suspend.txt create mode 100755 include/linux/suspend_blocker.h create mode 100644 kernel/power/suspend_blocker.cDocumentation/power/opportunistic-suspend.txt new file +119
-0@@ -0,0 +1,119 @@ +Opportunistic Suspend +===================== + +Opportunistic suspend is a feature allowing the system to be suspended (ie. put +into one of the available sleep states) automatically whenever it is regarded +as idle. The suspend blockers framework described below is used to determine +when that happens. + +The /sys/power/policy sysfs attribute is used to switch the system between the +opportunistic and "forced" suspend behavior, where in the latter case the +system is only suspended if a specific value, corresponding to one of the +available system sleep states, is written into /sys/power/state. However, in +the former, opportunistic, case the system is put into the sleep state +corresponding to the value written to /sys/power/state whenever there are no +active suspend blockers. The default policy is "forced". Also, suspend blockers +do not affect sleep states entered from idle. + +When the policy is "opportunisic", there is a special value, "on", that can be +written to /sys/power/state. This will block the automatic sleep request, as if +a suspend blocker was used by a device driver. This way the opportunistic +suspend may be blocked by user space whithout switching back to the "forced" +mode. + +A suspend blocker is an object used to inform the PM subsystem when the system +can or cannot be suspended in the "opportunistic" mode (the "forced" mode +ignores suspend blockers). To use it, a device driver creates a struct +suspend_blocker that must be initialized with suspend_blocker_init(). Before +freeing the suspend_blocker structure or its name, suspend_blocker_destroy() +must be called on it. + +A suspend blocker is activated using suspend_block(), which prevents the PM +subsystem from putting the system into the requested sleep state in the +"opportunistic" mode until the suspend blocker is deactivated with +suspend_unblock(). Multiple suspend blockers may be active simultaneously, and +the system will not suspend as long as at least one of them is active. + +If opportunistic suspend is already in progress when suspend_block() is called, +it will abort the suspend, unless suspend_ops->enter has already been +executed. If suspend is aborted this way, the system is usually not fully +operational at that point. The suspend callbacks of some drivers may still be +running and it usually takes time to restore the system to the fully operational +state. + +Here's an example showing how a cell phone or other embedded system can handle +keystrokes (or other input events) in the presence of suspend blockers. Use +set_irq_wake or a platform specific api to make sure the keypad interrupt wakes +up the cpu. Once the keypad driver has resumed, the sequence of events can look +like this: + +- The Keypad driver gets an interrupt. It then calls suspend_block on the + keypad-scan suspend_blocker and starts scanning the keypad matrix. +- The keypad-scan code detects a key change and reports it to the input-event + driver. +- The input-event driver sees the key change, enqueues an event, and calls + suspend_block on the input-event-queue suspend_blocker. +- The keypad-scan code detects that no keys are held and calls suspend_unblock + on the keypad-scan suspend_blocker. +- The user-space input-event thread returns from select/poll, calls + suspend_block on the process-input-events suspend_blocker and then calls read + on the input-event device. +- The input-event driver dequeues the key-event and, since the queue is now + empty, it calls suspend_unblock on the input-event-queue suspend_blocker. +- The user-space input-event thread returns from read. If it determines that + the key should be ignored, it calls suspend_unblock on the + process_input_events suspend_blocker and then calls select or poll. The + system will automatically suspend again, since now no suspend blockers are + active. + +If the key that was pressed instead should preform a simple action (for example, +adjusting the volume), this action can be performed right before calling +suspend_unblock on the process_input_events suspend_blocker. However, if the key +triggers a longer-running action, that action needs its own suspend_blocker and +suspend_block must be called on that suspend blocker before calling +suspend_unblock on the process_input_events suspend_blocker. + + Key pressed Key released + | | +keypad-scan ++++++++++++++++++ +input-event-queue +++ +++ +process-input-events +++ +++ + + +Driver API +========== + +A driver can use the suspend block api by adding a suspend_blocker variable to +its state and calling suspend_blocker_init. For instance: +struct state { + struct suspend_blocker suspend_blocker; +} + +init() { + suspend_blocker_init(&state->suspend_blocker, "suspend-blocker-name"); +} + +Before freeing the memory, suspend_blocker_destroy must be called: + +uninit() { + suspend_blocker_destroy(&state->suspend_blocker); +} + +When the driver determines that it needs to run (usually in an interrupt +handler) it calls suspend_block: + suspend_block(&state->suspend_blocker); + +When it no longer needs to run it calls suspend_unblock: + suspend_unblock(&state->suspend_blocker); + +Calling suspend_block when the suspend blocker is active or suspend_unblock when +it is not active has no effect (i.e., these functions don't nest). This allows +drivers to update their state and call suspend suspend_block or suspend_unblock +based on the result. +For instance: + +if (list_empty(&state->pending_work)) + suspend_unblock(&state->suspend_blocker); +else + suspend_block(&state->suspend_blocker); +include/linux/suspend_blocker.h new file +64
-0@@ -0,0 +1,64 @@ +/* include/linux/suspend_blocker.h +* +* Copyright (C) 2007-2009 Google, Inc. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#ifndef _LINUX_SUSPEND_BLOCKER_H +#define _LINUX_SUSPEND_BLOCKER_H + +#include <linux/list.h> + +/** +* struct suspend_blocker - the basic suspend_blocker structure +* @link: List entry for active or inactive list. +* @flags: Tracks initialized and active state. +* @name: Name used for debugging. +* +* When a suspend_blocker is active it prevents the system from entering +* opportunistic suspend. +* +* The suspend_blocker structure must be initialized by suspend_blocker_init() +*/ + +struct suspend_blocker { +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND +struct list_head link; +int flags; +const char *name; +#endif +}; + +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND + +void suspend_blocker_init (struct suspend_blocker *blocker,const char *name); +void suspend_blocker_destroy (struct suspend_blocker *blocker); +void suspend_block (struct suspend_blocker *blocker); +void suspend_unblock (struct suspend_blocker *blocker); +bool suspend_blocker_is_active (struct suspend_blocker *blocker); +bool suspend_is_blocked (void ); + +#else + +static inline void suspend_blocker_init (struct suspend_blocker *blocker, +const char *name) {} +static inline void suspend_blocker_destroy (struct suspend_blocker *blocker) {} +static inline void suspend_block (struct suspend_blocker *blocker) {} +static inline void suspend_unblock (struct suspend_blocker *blocker) {} +static inline bool suspend_blocker_is_active (struct suspend_blocker *bl) + {return 0 ; } +static inline bool suspend_is_blocked (void ) {return 0 ; } + +#endif + +#endif +kernel/power/Kconfig +16
-0@@ -130,6 +130,22 @@ config SUSPEND_FREEZER Turning OFF this setting is NOT recommended! If in doubt, say Y. +config OPPORTUNISTIC_SUSPEND + bool "Suspend blockers" + depends on PM_SLEEP + select RTC_LIB + default n + ---help--- + Opportunistic sleep support. Allows the system to be put into a sleep + state opportunistically, if it doesn't do any useful work at the + moment. The PM subsystem is switched into this mode of operation by + writing "opportunistic" into /sys/power/policy, while writing + "forced" to this file turns the opportunistic suspend feature off. + In the "opportunistic" mode suspend blockers are used to determine + when to suspend the system and the value written to /sys/power/state + determines the sleep state the system will be put into when there are + no active suspend blockers. + config HIBERNATION_NVS boolkernel/power/Makefile +1
-0@@ -7,6 +7,7 @@ obj-$(CONFIG_PM) += main.o obj-$(CONFIG_PM_SLEEP) += console.o obj-$(CONFIG_FREEZER) += process.o obj-$(CONFIG_SUSPEND) += suspend.o +obj-$(CONFIG_OPPORTUNISTIC_SUSPEND) += suspend_blocker.o obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o obj-$(CONFIG_HIBERNATION_NVS) += hibernate_nvs.okernel/power/main.c +86
-6@@ -12,6 +12,7 @@#include <linux/string.h> #include <linux/resume-trace.h> #include <linux/workqueue.h> +#include <linux/suspend_blocker.h> #include "power.h" @@ -20,6 +21,27 @@ DEFINE_MUTEX(pm_mutex);unsigned int pm_flags;EXPORT_SYMBOL (pm_flags); +struct policy { +const char *name; +bool (*valid_state)(suspend_state_t state); +int (*set_state)(suspend_state_t state); +}; +static struct policy policies[] = { + { + .name ="forced" , + .valid_state = valid_state, + .set_state = enter_state, + }, +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND + { + .name ="opportunistic" , + .valid_state = request_suspend_valid_state, + .set_state = request_suspend_state, + }, +#endif +}; +static int policy; +#ifdef CONFIG_PM_SLEEP /* Routines for PM-transition notifications */ @@ -146,6 +168,12 @@ struct kobject *power_kobj;* * store() accepts one of those strings, translates it into the * proper enumerated value, and initiates a suspend transition. +* +* If policy is set to opportunistic, store() does not block until the +* system resumes, and it will try to re-enter the state until another +* state is requested. Suspend blockers are respected and the requested +* state will only be entered when no suspend blockers are active. +* Write "on" to cancel. */ static ssize_t state_show (struct kobject *kobj,struct kobj_attribute *attr,char *buf)@@ -155,12 +183,13 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,int i;for (i =0 ; i <PM_SUSPEND_MAX ; i++) { -if (pm_states[i] &&valid_state (i)) +if (pm_states[i] && policies[policy].valid_state (i)) s +=sprintf (s,"%s " , pm_states[i]); }#endif #ifdef CONFIG_HIBERNATION - s +=sprintf (s,"%s\n" ,"disk" ); +if (!policy) + s +=sprintf (s,"%s\n" ,"disk" );#else if (s != buf)/* convert the last space to a newline */ @@ -173,7 +202,7 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) {#ifdef CONFIG_SUSPEND -suspend_state_t state =PM_SUSPEND_STANDBY ; +suspend_state_t state =PM_SUSPEND_ON ;const char *const *s;#endif char *p;@@ -184,7 +213,7 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, len = p ? p - buf : n;/* First, check if we are requested to hibernate */ -if (len ==4 && !strncmp (buf,"disk" , len)) { +if (len ==4 && !strncmp (buf,"disk" , len) && !policy) { error =hibernate (); goto Exit; }@@ -195,7 +224,7 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, break; }if (state <PM_SUSPEND_MAX && *s) - error =enter_state (state); + error = policies[policy].set_state (state);#endif Exit:@@ -204,6 +233,55 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,power_attr (state); +/** +* policy - set policy for state +*/ + +static ssize_t policy_show (struct kobject *kobj, +struct kobj_attribute *attr,char *buf) +{ +char *s = buf; +int i; + +for (i =0 ; i <ARRAY_SIZE (policies); i++) { +if (i == policy) + s +=sprintf (s,"[%s] " , policies[i].name); +else + s +=sprintf (s,"%s " , policies[i].name); + } +if (s != buf) +/* convert the last space to a newline */ + *(s-1 ) ='\n' ; +return (s - buf); +} + +static ssize_t policy_store (struct kobject *kobj, +struct kobj_attribute *attr, +const char *buf,size_t n) +{ +const char *s; +char *p; +int len; +int i; + + p =memchr (buf,'\n' , n); + len = p ? p - buf : n; + +for (i =0 ; i <ARRAY_SIZE (policies); i++) { + s = policies[i].name; +if (s && len ==strlen (s) && !strncmp (buf, s, len)) { +mutex_lock (&pm_mutex); + policies[policy].set_state (PM_SUSPEND_ON ); + policy = i; +mutex_unlock (&pm_mutex); +return n; + } + } +return -EINVAL ; +} + +power_attr (policy); +#ifdef CONFIG_PM_TRACE int pm_trace_enabled;@@ -231,6 +309,7 @@ power_attr(pm_trace);static struct attribute * g[] = { &state_attr.attr, + &policy_attr.attr, #ifdef CONFIG_PM_TRACE &pm_trace_attr.attr, #endif@@ -247,7 +326,7 @@ static struct attribute_group attr_group = { .attrs = g, }; -#ifdef CONFIG_PM_RUNTIME +#if defined(CONFIG_PM_RUNTIME ) || defined(CONFIG_OPPORTUNISTIC_SUSPEND )struct workqueue_struct *pm_wq;EXPORT_SYMBOL_GPL (pm_wq);@@ -266,6 +345,7 @@ static int __init pm_init(void)int error =pm_start_workqueue ();if (error)return error; +suspend_block_init (); power_kobj =kobject_create_and_add ("power" ,NULL );if (!power_kobj)return -ENOMEM ;kernel/power/power.h +9
-0@@ -236,3 +236,12 @@ static inline void suspend_thaw_processes(void) { }#endif + +/* kernel/power/suspend_block.c */ +extern int request_suspend_state (suspend_state_t state); +extern bool request_suspend_valid_state (suspend_state_t state); +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND +extern void __init suspend_block_init (void ); +#else +static inline void suspend_block_init (void ) {} +#endif kernel/power/suspend.c +3
-1@@ -16,10 +16,12 @@#include <linux/cpu.h> #include <linux/syscalls.h> #include <linux/gfp.h> +#include <linux/suspend_blocker.h> #include "power.h" const char *const pm_states[PM_SUSPEND_MAX ] = { + [PM_SUSPEND_ON ] ="on" , [PM_SUSPEND_STANDBY ] ="standby" , [PM_SUSPEND_MEM ] ="mem" , };@@ -157,7 +159,7 @@ static int suspend_enter(suspend_state_t state) error =sysdev_suspend (PMSG_SUSPEND );if (!error) { -if (!suspend_test (TEST_CORE )) +if (!suspend_is_blocked () && !suspend_test (TEST_CORE )) error = suspend_ops->enter (state);sysdev_resume (); }kernel/power/suspend_blocker.c new file +261
-0@@ -0,0 +1,261 @@ +/* kernel/power/suspend_blocker.c +* +* Copyright (C) 2005-2010 Google, Inc. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#include <linux/module.h> +#include <linux/rtc.h> +#include <linux/suspend.h> +#include <linux/suspend_blocker.h> +#include "power.h" + +extern struct workqueue_struct *pm_wq; + +enum { +DEBUG_EXIT_SUSPEND =1U <<0 , +DEBUG_WAKEUP =1U <<1 , +DEBUG_USER_STATE =1U <<2 , +DEBUG_SUSPEND =1U <<3 , +DEBUG_SUSPEND_BLOCKER =1U <<4 , +}; +static int debug_mask =DEBUG_EXIT_SUSPEND |DEBUG_WAKEUP |DEBUG_USER_STATE ; +module_param_named (debug_mask, debug_mask, int,S_IRUGO |S_IWUSR |S_IWGRP ); + +#define SB_INITIALIZED (1U << 8) +#define SB_ACTIVE (1U << 9) + +static DEFINE_SPINLOCK (list_lock); +static DEFINE_SPINLOCK (state_lock); +static LIST_HEAD (inactive_blockers); +static LIST_HEAD (active_blockers); +static int current_event_num; +struct suspend_blocker main_suspend_blocker; +static suspend_state_t requested_suspend_state =PM_SUSPEND_MEM ; +static bool enable_suspend_blockers; + +#define pr_info_time(fmt, args...) \ + do { \ + struct timespec ts; \ + struct rtc_time tm; \ + getnstimeofday(&ts); \ + rtc_time_to_tm(ts.tv_sec, &tm); \ + pr_info(fmt "(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n" , \ + args, \ + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, \ + tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec); \ + } while (0); + +static void print_active_blockers_locked (void ) +{ +struct suspend_blocker *blocker; + +list_for_each_entry (blocker, &active_blockers, link) +pr_info ("active suspend blocker %s\n" , blocker->name); +} + +/** +* suspend_is_blocked() - Check if suspend should be blocked +* +* suspend_is_blocked can be used by generic power management code to abort +* suspend. +* +* To preserve backward compatibility suspend_is_blocked returns 0 unless it +* is called during suspend initiated from the suspend_block code. +*/ +bool suspend_is_blocked (void ) +{ +if (!enable_suspend_blockers) +return 0 ; +return !list_empty (&active_blockers); +} + +static void suspend_worker (struct work_struct *work) +{ +int ret; +int entry_event_num; + + enable_suspend_blockers = true; +while (!suspend_is_blocked ()) { + entry_event_num = current_event_num; + +if (debug_mask &DEBUG_SUSPEND ) +pr_info ("suspend: enter suspend\n" ); + + ret =pm_suspend (requested_suspend_state); + +if (debug_mask &DEBUG_EXIT_SUSPEND ) +pr_info_time ("suspend: exit suspend, ret = %d " , ret); + +if (current_event_num == entry_event_num) +pr_info ("suspend: pm_suspend returned with no event\n" ); + } + enable_suspend_blockers = false; +} +static DECLARE_WORK(suspend_work, suspend_worker); + +/** +* suspend_blocker_init() - Initialize a suspend blocker +* @blocker: The suspend blocker to initialize. +* @name: The name of the suspend blocker to show in debug messages. +* +* The suspend blocker struct and name must not be freed before calling +* suspend_blocker_destroy. +*/ +void suspend_blocker_init (struct suspend_blocker *blocker,const char *name) +{ +unsigned long irqflags =0 ; + +WARN_ON (!name); + +if (debug_mask &DEBUG_SUSPEND_BLOCKER ) +pr_info ("suspend_blocker_init name=%s\n" , name); + + blocker->name = name; + blocker->flags =SB_INITIALIZED ; +INIT_LIST_HEAD (&blocker->link); + +spin_lock_irqsave (&list_lock, irqflags); +list_add (&blocker->link, &inactive_blockers); +spin_unlock_irqrestore (&list_lock, irqflags); +} +EXPORT_SYMBOL (suspend_blocker_init); + +/** +* suspend_blocker_destroy() - Destroy a suspend blocker +* @blocker: The suspend blocker to destroy. +*/ +void suspend_blocker_destroy (struct suspend_blocker *blocker) +{ +unsigned long irqflags; +if (WARN_ON (!(blocker->flags &SB_INITIALIZED ))) +return ; + +if (debug_mask &DEBUG_SUSPEND_BLOCKER ) +pr_info ("suspend_blocker_destroy name=%s\n" , blocker->name); + +spin_lock_irqsave (&list_lock, irqflags); + blocker->flags &= ~SB_INITIALIZED ; +list_del (&blocker->link); +if ((blocker->flags &SB_ACTIVE ) &&list_empty (&active_blockers)) +queue_work (pm_wq, &suspend_work); +spin_unlock_irqrestore (&list_lock, irqflags); +} +EXPORT_SYMBOL (suspend_blocker_destroy); + +/** +* suspend_block() - Block suspend +* @blocker: The suspend blocker to use +* +* It is safe to call this function from interrupt context. +*/ +void suspend_block (struct suspend_blocker *blocker) +{ +unsigned long irqflags; + +if (WARN_ON (!(blocker->flags &SB_INITIALIZED ))) +return ; + +spin_lock_irqsave (&list_lock, irqflags); + +if (debug_mask &DEBUG_SUSPEND_BLOCKER ) +pr_info ("suspend_block: %s\n" , blocker->name); + + blocker->flags |=SB_ACTIVE ; +list_move (&blocker->link, &active_blockers); + current_event_num++; + +spin_unlock_irqrestore (&list_lock, irqflags); +} +EXPORT_SYMBOL (suspend_block); + +/** +* suspend_unblock() - Unblock suspend +* @blocker: The suspend blocker to unblock. +* +* If no other suspend blockers block suspend, the system will suspend. +* +* It is safe to call this function from interrupt context. +*/ +void suspend_unblock (struct suspend_blocker *blocker) +{ +unsigned long irqflags; + +if (WARN_ON (!(blocker->flags &SB_INITIALIZED ))) +return ; + +spin_lock_irqsave (&list_lock, irqflags); + +if (debug_mask &DEBUG_SUSPEND_BLOCKER ) +pr_info ("suspend_unblock: %s\n" , blocker->name); + +list_move (&blocker->link, &inactive_blockers); + +if ((blocker->flags &SB_ACTIVE ) &&list_empty (&active_blockers)) +queue_work (pm_wq, &suspend_work); + blocker->flags &= ~(SB_ACTIVE ); +if (blocker == &main_suspend_blocker) { +if (debug_mask &DEBUG_SUSPEND ) +print_active_blockers_locked (); + } +spin_unlock_irqrestore (&list_lock, irqflags); +} +EXPORT_SYMBOL (suspend_unblock); + +/** +* suspend_blocker_is_active() - Test if a suspend blocker is blocking suspend +* @blocker: The suspend blocker to check. +* +* Returns true if the suspend_blocker is currently active. +*/ +bool suspend_blocker_is_active (struct suspend_blocker *blocker) +{ +WARN_ON (!(blocker->flags &SB_INITIALIZED )); + +return !!(blocker->flags &SB_ACTIVE ); +} +EXPORT_SYMBOL (suspend_blocker_is_active); + +bool request_suspend_valid_state (suspend_state_t state) +{ +return (state ==PM_SUSPEND_ON ) ||valid_state (state); +} + +int request_suspend_state (suspend_state_t state) +{ +unsigned long irqflags; + +if (!request_suspend_valid_state (state)) +return -ENODEV ; + +spin_lock_irqsave (&state_lock, irqflags); + +if (debug_mask &DEBUG_USER_STATE ) +pr_info_time ("request_suspend_state: %s (%d->%d) at %lld " , + state !=PM_SUSPEND_ON ?"sleep" :"wakeup" , + requested_suspend_state, state, +ktime_to_ns (ktime_get ())); + + requested_suspend_state = state; +if (state ==PM_SUSPEND_ON ) +suspend_block (&main_suspend_blocker); +else +suspend_unblock (&main_suspend_blocker); +spin_unlock_irqrestore (&state_lock, irqflags); +return 0 ; +} + +void __init suspend_block_init (void ) +{ +suspend_blocker_init (&main_suspend_blocker,"main" ); +suspend_block (&main_suspend_blocker); +}
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 1/8] PM: Add suspend block api.
In reply to Arve HjønnevågQuoted 7 lines · Arve Hj??nnev??g
Adds
/sys/power/policythat selects the behaviour of/sys/power/state. After setting the policy to opportunistic, writes to/sys/power/statebecome 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 <[email protected]>
Also note that this patch mixes up adding new in-kernel interface with adding new userland API.
The in-kernel interface seems to be sane and it would be nice to merge it soon, unfortunately the strange userland API is in the same patch :-(.
Quoted 735 lines
--- Documentation/power/opportunistic-suspend.txt | 119 +++++++++++ include/linux/suspend_blocker.h | 64 ++++++ kernel/power/Kconfig | 16 ++ kernel/power/Makefile | 1 + kernel/power/main.c | 92 ++++++++- kernel/power/power.h | 9 + kernel/power/suspend.c | 4 +- kernel/power/suspend_blocker.c | 261 +++++++++++++++++++++++++ 8 files changed, 559 insertions(+), 7 deletions(-) create mode 100644 Documentation/power/opportunistic-suspend.txt create mode 100755 include/linux/suspend_blocker.h create mode 100644 kernel/power/suspend_blocker.cDocumentation/power/opportunistic-suspend.txt new file +119
-0@@ -0,0 +1,119 @@ +Opportunistic Suspend +===================== + +Opportunistic suspend is a feature allowing the system to be suspended (ie. put +into one of the available sleep states) automatically whenever it is regarded +as idle. The suspend blockers framework described below is used to determine +when that happens. + +The /sys/power/policy sysfs attribute is used to switch the system between the +opportunistic and "forced" suspend behavior, where in the latter case the +system is only suspended if a specific value, corresponding to one of the +available system sleep states, is written into /sys/power/state. However, in +the former, opportunistic, case the system is put into the sleep state +corresponding to the value written to /sys/power/state whenever there are no +active suspend blockers. The default policy is "forced". Also, suspend blockers +do not affect sleep states entered from idle. + +When the policy is "opportunisic", there is a special value, "on", that can be +written to /sys/power/state. This will block the automatic sleep request, as if +a suspend blocker was used by a device driver. This way the opportunistic +suspend may be blocked by user space whithout switching back to the "forced" +mode. + +A suspend blocker is an object used to inform the PM subsystem when the system +can or cannot be suspended in the "opportunistic" mode (the "forced" mode +ignores suspend blockers). To use it, a device driver creates a struct +suspend_blocker that must be initialized with suspend_blocker_init(). Before +freeing the suspend_blocker structure or its name, suspend_blocker_destroy() +must be called on it. + +A suspend blocker is activated using suspend_block(), which prevents the PM +subsystem from putting the system into the requested sleep state in the +"opportunistic" mode until the suspend blocker is deactivated with +suspend_unblock(). Multiple suspend blockers may be active simultaneously, and +the system will not suspend as long as at least one of them is active. + +If opportunistic suspend is already in progress when suspend_block() is called, +it will abort the suspend, unless suspend_ops->enter has already been +executed. If suspend is aborted this way, the system is usually not fully +operational at that point. The suspend callbacks of some drivers may still be +running and it usually takes time to restore the system to the fully operational +state. + +Here's an example showing how a cell phone or other embedded system can handle +keystrokes (or other input events) in the presence of suspend blockers. Use +set_irq_wake or a platform specific api to make sure the keypad interrupt wakes +up the cpu. Once the keypad driver has resumed, the sequence of events can look +like this: + +- The Keypad driver gets an interrupt. It then calls suspend_block on the + keypad-scan suspend_blocker and starts scanning the keypad matrix. +- The keypad-scan code detects a key change and reports it to the input-event + driver. +- The input-event driver sees the key change, enqueues an event, and calls + suspend_block on the input-event-queue suspend_blocker. +- The keypad-scan code detects that no keys are held and calls suspend_unblock + on the keypad-scan suspend_blocker. +- The user-space input-event thread returns from select/poll, calls + suspend_block on the process-input-events suspend_blocker and then calls read + on the input-event device. +- The input-event driver dequeues the key-event and, since the queue is now + empty, it calls suspend_unblock on the input-event-queue suspend_blocker. +- The user-space input-event thread returns from read. If it determines that + the key should be ignored, it calls suspend_unblock on the + process_input_events suspend_blocker and then calls select or poll. The + system will automatically suspend again, since now no suspend blockers are + active. + +If the key that was pressed instead should preform a simple action (for example, +adjusting the volume), this action can be performed right before calling +suspend_unblock on the process_input_events suspend_blocker. However, if the key +triggers a longer-running action, that action needs its own suspend_blocker and +suspend_block must be called on that suspend blocker before calling +suspend_unblock on the process_input_events suspend_blocker. + + Key pressed Key released + | | +keypad-scan ++++++++++++++++++ +input-event-queue +++ +++ +process-input-events +++ +++ + + +Driver API +========== + +A driver can use the suspend block api by adding a suspend_blocker variable to +its state and calling suspend_blocker_init. For instance: +struct state { + struct suspend_blocker suspend_blocker; +} + +init() { + suspend_blocker_init(&state->suspend_blocker, "suspend-blocker-name"); +} + +Before freeing the memory, suspend_blocker_destroy must be called: + +uninit() { + suspend_blocker_destroy(&state->suspend_blocker); +} + +When the driver determines that it needs to run (usually in an interrupt +handler) it calls suspend_block: + suspend_block(&state->suspend_blocker); + +When it no longer needs to run it calls suspend_unblock: + suspend_unblock(&state->suspend_blocker); + +Calling suspend_block when the suspend blocker is active or suspend_unblock when +it is not active has no effect (i.e., these functions don't nest). This allows +drivers to update their state and call suspend suspend_block or suspend_unblock +based on the result. +For instance: + +if (list_empty(&state->pending_work)) + suspend_unblock(&state->suspend_blocker); +else + suspend_block(&state->suspend_blocker); +include/linux/suspend_blocker.h new file +64
-0@@ -0,0 +1,64 @@ +/* include/linux/suspend_blocker.h +* +* Copyright (C) 2007-2009 Google, Inc. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#ifndef _LINUX_SUSPEND_BLOCKER_H +#define _LINUX_SUSPEND_BLOCKER_H + +#include <linux/list.h> + +/** +* struct suspend_blocker - the basic suspend_blocker structure +* @link: List entry for active or inactive list. +* @flags: Tracks initialized and active state. +* @name: Name used for debugging. +* +* When a suspend_blocker is active it prevents the system from entering +* opportunistic suspend. +* +* The suspend_blocker structure must be initialized by suspend_blocker_init() +*/ + +struct suspend_blocker { +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND +struct list_head link; +int flags; +const char *name; +#endif +}; + +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND + +void suspend_blocker_init (struct suspend_blocker *blocker,const char *name); +void suspend_blocker_destroy (struct suspend_blocker *blocker); +void suspend_block (struct suspend_blocker *blocker); +void suspend_unblock (struct suspend_blocker *blocker); +bool suspend_blocker_is_active (struct suspend_blocker *blocker); +bool suspend_is_blocked (void ); + +#else + +static inline void suspend_blocker_init (struct suspend_blocker *blocker, +const char *name) {} +static inline void suspend_blocker_destroy (struct suspend_blocker *blocker) {} +static inline void suspend_block (struct suspend_blocker *blocker) {} +static inline void suspend_unblock (struct suspend_blocker *blocker) {} +static inline bool suspend_blocker_is_active (struct suspend_blocker *bl) + {return 0 ; } +static inline bool suspend_is_blocked (void ) {return 0 ; } + +#endif + +#endif +kernel/power/Kconfig +16
-0@@ -130,6 +130,22 @@ config SUSPEND_FREEZER Turning OFF this setting is NOT recommended! If in doubt, say Y. +config OPPORTUNISTIC_SUSPEND + bool "Suspend blockers" + depends on PM_SLEEP + select RTC_LIB + default n + ---help--- + Opportunistic sleep support. Allows the system to be put into a sleep + state opportunistically, if it doesn't do any useful work at the + moment. The PM subsystem is switched into this mode of operation by + writing "opportunistic" into /sys/power/policy, while writing + "forced" to this file turns the opportunistic suspend feature off. + In the "opportunistic" mode suspend blockers are used to determine + when to suspend the system and the value written to /sys/power/state + determines the sleep state the system will be put into when there are + no active suspend blockers. + config HIBERNATION_NVS boolkernel/power/Makefile +1
-0@@ -7,6 +7,7 @@ obj-$(CONFIG_PM) += main.o obj-$(CONFIG_PM_SLEEP) += console.o obj-$(CONFIG_FREEZER) += process.o obj-$(CONFIG_SUSPEND) += suspend.o +obj-$(CONFIG_OPPORTUNISTIC_SUSPEND) += suspend_blocker.o obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o obj-$(CONFIG_HIBERNATION_NVS) += hibernate_nvs.okernel/power/main.c +86
-6@@ -12,6 +12,7 @@#include <linux/string.h> #include <linux/resume-trace.h> #include <linux/workqueue.h> +#include <linux/suspend_blocker.h> #include "power.h" @@ -20,6 +21,27 @@ DEFINE_MUTEX(pm_mutex);unsigned int pm_flags;EXPORT_SYMBOL (pm_flags); +struct policy { +const char *name; +bool (*valid_state)(suspend_state_t state); +int (*set_state)(suspend_state_t state); +}; +static struct policy policies[] = { + { + .name ="forced" , + .valid_state = valid_state, + .set_state = enter_state, + }, +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND + { + .name ="opportunistic" , + .valid_state = request_suspend_valid_state, + .set_state = request_suspend_state, + }, +#endif +}; +static int policy; +#ifdef CONFIG_PM_SLEEP /* Routines for PM-transition notifications */ @@ -146,6 +168,12 @@ struct kobject *power_kobj;* * store() accepts one of those strings, translates it into the * proper enumerated value, and initiates a suspend transition. +* +* If policy is set to opportunistic, store() does not block until the +* system resumes, and it will try to re-enter the state until another +* state is requested. Suspend blockers are respected and the requested +* state will only be entered when no suspend blockers are active. +* Write "on" to cancel. */ static ssize_t state_show (struct kobject *kobj,struct kobj_attribute *attr,char *buf)@@ -155,12 +183,13 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,int i;for (i =0 ; i <PM_SUSPEND_MAX ; i++) { -if (pm_states[i] &&valid_state (i)) +if (pm_states[i] && policies[policy].valid_state (i)) s +=sprintf (s,"%s " , pm_states[i]); }#endif #ifdef CONFIG_HIBERNATION - s +=sprintf (s,"%s\n" ,"disk" ); +if (!policy) + s +=sprintf (s,"%s\n" ,"disk" );#else if (s != buf)/* convert the last space to a newline */ @@ -173,7 +202,7 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) {#ifdef CONFIG_SUSPEND -suspend_state_t state =PM_SUSPEND_STANDBY ; +suspend_state_t state =PM_SUSPEND_ON ;const char *const *s;#endif char *p;@@ -184,7 +213,7 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, len = p ? p - buf : n;/* First, check if we are requested to hibernate */ -if (len ==4 && !strncmp (buf,"disk" , len)) { +if (len ==4 && !strncmp (buf,"disk" , len) && !policy) { error =hibernate (); goto Exit; }@@ -195,7 +224,7 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, break; }if (state <PM_SUSPEND_MAX && *s) - error =enter_state (state); + error = policies[policy].set_state (state);#endif Exit:@@ -204,6 +233,55 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,power_attr (state); +/** +* policy - set policy for state +*/ + +static ssize_t policy_show (struct kobject *kobj, +struct kobj_attribute *attr,char *buf) +{ +char *s = buf; +int i; + +for (i =0 ; i <ARRAY_SIZE (policies); i++) { +if (i == policy) + s +=sprintf (s,"[%s] " , policies[i].name); +else + s +=sprintf (s,"%s " , policies[i].name); + } +if (s != buf) +/* convert the last space to a newline */ + *(s-1 ) ='\n' ; +return (s - buf); +} + +static ssize_t policy_store (struct kobject *kobj, +struct kobj_attribute *attr, +const char *buf,size_t n) +{ +const char *s; +char *p; +int len; +int i; + + p =memchr (buf,'\n' , n); + len = p ? p - buf : n; + +for (i =0 ; i <ARRAY_SIZE (policies); i++) { + s = policies[i].name; +if (s && len ==strlen (s) && !strncmp (buf, s, len)) { +mutex_lock (&pm_mutex); + policies[policy].set_state (PM_SUSPEND_ON ); + policy = i; +mutex_unlock (&pm_mutex); +return n; + } + } +return -EINVAL ; +} + +power_attr (policy); +#ifdef CONFIG_PM_TRACE int pm_trace_enabled;@@ -231,6 +309,7 @@ power_attr(pm_trace);static struct attribute * g[] = { &state_attr.attr, + &policy_attr.attr, #ifdef CONFIG_PM_TRACE &pm_trace_attr.attr, #endif@@ -247,7 +326,7 @@ static struct attribute_group attr_group = { .attrs = g, }; -#ifdef CONFIG_PM_RUNTIME +#if defined(CONFIG_PM_RUNTIME ) || defined(CONFIG_OPPORTUNISTIC_SUSPEND )struct workqueue_struct *pm_wq;EXPORT_SYMBOL_GPL (pm_wq);@@ -266,6 +345,7 @@ static int __init pm_init(void)int error =pm_start_workqueue ();if (error)return error; +suspend_block_init (); power_kobj =kobject_create_and_add ("power" ,NULL );if (!power_kobj)return -ENOMEM ;kernel/power/power.h +9
-0@@ -236,3 +236,12 @@ static inline void suspend_thaw_processes(void) { }#endif + +/* kernel/power/suspend_block.c */ +extern int request_suspend_state (suspend_state_t state); +extern bool request_suspend_valid_state (suspend_state_t state); +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND +extern void __init suspend_block_init (void ); +#else +static inline void suspend_block_init (void ) {} +#endif kernel/power/suspend.c +3
-1@@ -16,10 +16,12 @@#include <linux/cpu.h> #include <linux/syscalls.h> #include <linux/gfp.h> +#include <linux/suspend_blocker.h> #include "power.h" const char *const pm_states[PM_SUSPEND_MAX ] = { + [PM_SUSPEND_ON ] ="on" , [PM_SUSPEND_STANDBY ] ="standby" , [PM_SUSPEND_MEM ] ="mem" , };@@ -157,7 +159,7 @@ static int suspend_enter(suspend_state_t state) error =sysdev_suspend (PMSG_SUSPEND );if (!error) { -if (!suspend_test (TEST_CORE )) +if (!suspend_is_blocked () && !suspend_test (TEST_CORE )) error = suspend_ops->enter (state);sysdev_resume (); }kernel/power/suspend_blocker.c new file +261
-0@@ -0,0 +1,261 @@ +/* kernel/power/suspend_blocker.c +* +* Copyright (C) 2005-2010 Google, Inc. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#include <linux/module.h> +#include <linux/rtc.h> +#include <linux/suspend.h> +#include <linux/suspend_blocker.h> +#include "power.h" + +extern struct workqueue_struct *pm_wq; + +enum { +DEBUG_EXIT_SUSPEND =1U <<0 , +DEBUG_WAKEUP =1U <<1 , +DEBUG_USER_STATE =1U <<2 , +DEBUG_SUSPEND =1U <<3 , +DEBUG_SUSPEND_BLOCKER =1U <<4 , +}; +static int debug_mask =DEBUG_EXIT_SUSPEND |DEBUG_WAKEUP |DEBUG_USER_STATE ; +module_param_named (debug_mask, debug_mask, int,S_IRUGO |S_IWUSR |S_IWGRP ); + +#define SB_INITIALIZED (1U << 8) +#define SB_ACTIVE (1U << 9) + +static DEFINE_SPINLOCK (list_lock); +static DEFINE_SPINLOCK (state_lock); +static LIST_HEAD (inactive_blockers); +static LIST_HEAD (active_blockers); +static int current_event_num; +struct suspend_blocker main_suspend_blocker; +static suspend_state_t requested_suspend_state =PM_SUSPEND_MEM ; +static bool enable_suspend_blockers; + +#define pr_info_time(fmt, args...) \ + do { \ + struct timespec ts; \ + struct rtc_time tm; \ + getnstimeofday(&ts); \ + rtc_time_to_tm(ts.tv_sec, &tm); \ + pr_info(fmt "(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n" , \ + args, \ + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, \ + tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec); \ + } while (0); + +static void print_active_blockers_locked (void ) +{ +struct suspend_blocker *blocker; + +list_for_each_entry (blocker, &active_blockers, link) +pr_info ("active suspend blocker %s\n" , blocker->name); +} + +/** +* suspend_is_blocked() - Check if suspend should be blocked +* +* suspend_is_blocked can be used by generic power management code to abort +* suspend. +* +* To preserve backward compatibility suspend_is_blocked returns 0 unless it +* is called during suspend initiated from the suspend_block code. +*/ +bool suspend_is_blocked (void ) +{ +if (!enable_suspend_blockers) +return 0 ; +return !list_empty (&active_blockers); +} + +static void suspend_worker (struct work_struct *work) +{ +int ret; +int entry_event_num; + + enable_suspend_blockers = true; +while (!suspend_is_blocked ()) { + entry_event_num = current_event_num; + +if (debug_mask &DEBUG_SUSPEND ) +pr_info ("suspend: enter suspend\n" ); + + ret =pm_suspend (requested_suspend_state); + +if (debug_mask &DEBUG_EXIT_SUSPEND ) +pr_info_time ("suspend: exit suspend, ret = %d " , ret); + +if (current_event_num == entry_event_num) +pr_info ("suspend: pm_suspend returned with no event\n" ); + } + enable_suspend_blockers = false; +} +static DECLARE_WORK(suspend_work, suspend_worker); + +/** +* suspend_blocker_init() - Initialize a suspend blocker +* @blocker: The suspend blocker to initialize. +* @name: The name of the suspend blocker to show in debug messages. +* +* The suspend blocker struct and name must not be freed before calling +* suspend_blocker_destroy. +*/ +void suspend_blocker_init (struct suspend_blocker *blocker,const char *name) +{ +unsigned long irqflags =0 ; + +WARN_ON (!name); + +if (debug_mask &DEBUG_SUSPEND_BLOCKER ) +pr_info ("suspend_blocker_init name=%s\n" , name); + + blocker->name = name; + blocker->flags =SB_INITIALIZED ; +INIT_LIST_HEAD (&blocker->link); + +spin_lock_irqsave (&list_lock, irqflags); +list_add (&blocker->link, &inactive_blockers); +spin_unlock_irqrestore (&list_lock, irqflags); +} +EXPORT_SYMBOL (suspend_blocker_init); + +/** +* suspend_blocker_destroy() - Destroy a suspend blocker +* @blocker: The suspend blocker to destroy. +*/ +void suspend_blocker_destroy (struct suspend_blocker *blocker) +{ +unsigned long irqflags; +if (WARN_ON (!(blocker->flags &SB_INITIALIZED ))) +return ; + +if (debug_mask &DEBUG_SUSPEND_BLOCKER ) +pr_info ("suspend_blocker_destroy name=%s\n" , blocker->name); + +spin_lock_irqsave (&list_lock, irqflags); + blocker->flags &= ~SB_INITIALIZED ; +list_del (&blocker->link); +if ((blocker->flags &SB_ACTIVE ) &&list_empty (&active_blockers)) +queue_work (pm_wq, &suspend_work); +spin_unlock_irqrestore (&list_lock, irqflags); +} +EXPORT_SYMBOL (suspend_blocker_destroy); + +/** +* suspend_block() - Block suspend +* @blocker: The suspend blocker to use +* +* It is safe to call this function from interrupt context. +*/ +void suspend_block (struct suspend_blocker *blocker) +{ +unsigned long irqflags; + +if (WARN_ON (!(blocker->flags &SB_INITIALIZED ))) +return ; + +spin_lock_irqsave (&list_lock, irqflags); + +if (debug_mask &DEBUG_SUSPEND_BLOCKER ) +pr_info ("suspend_block: %s\n" , blocker->name); + + blocker->flags |=SB_ACTIVE ; +list_move (&blocker->link, &active_blockers); + current_event_num++; + +spin_unlock_irqrestore (&list_lock, irqflags); +} +EXPORT_SYMBOL (suspend_block); + +/** +* suspend_unblock() - Unblock suspend +* @blocker: The suspend blocker to unblock. +* +* If no other suspend blockers block suspend, the system will suspend. +* +* It is safe to call this function from interrupt context. +*/ +void suspend_unblock (struct suspend_blocker *blocker) +{ +unsigned long irqflags; + +if (WARN_ON (!(blocker->flags &SB_INITIALIZED ))) +return ; + +spin_lock_irqsave (&list_lock, irqflags); + +if (debug_mask &DEBUG_SUSPEND_BLOCKER ) +pr_info ("suspend_unblock: %s\n" , blocker->name); + +list_move (&blocker->link, &inactive_blockers); + +if ((blocker->flags &SB_ACTIVE ) &&list_empty (&active_blockers)) +queue_work (pm_wq, &suspend_work); + blocker->flags &= ~(SB_ACTIVE ); +if (blocker == &main_suspend_blocker) { +if (debug_mask &DEBUG_SUSPEND ) +print_active_blockers_locked (); + } +spin_unlock_irqrestore (&list_lock, irqflags); +} +EXPORT_SYMBOL (suspend_unblock); + +/** +* suspend_blocker_is_active() - Test if a suspend blocker is blocking suspend +* @blocker: The suspend blocker to check. +* +* Returns true if the suspend_blocker is currently active. +*/ +bool suspend_blocker_is_active (struct suspend_blocker *blocker) +{ +WARN_ON (!(blocker->flags &SB_INITIALIZED )); + +return !!(blocker->flags &SB_ACTIVE ); +} +EXPORT_SYMBOL (suspend_blocker_is_active); + +bool request_suspend_valid_state (suspend_state_t state) +{ +return (state ==PM_SUSPEND_ON ) ||valid_state (state); +} + +int request_suspend_state (suspend_state_t state) +{ +unsigned long irqflags; + +if (!request_suspend_valid_state (state)) +return -ENODEV ; + +spin_lock_irqsave (&state_lock, irqflags); + +if (debug_mask &DEBUG_USER_STATE ) +pr_info_time ("request_suspend_state: %s (%d->%d) at %lld " , + state !=PM_SUSPEND_ON ?"sleep" :"wakeup" , + requested_suspend_state, state, +ktime_to_ns (ktime_get ())); + + requested_suspend_state = state; +if (state ==PM_SUSPEND_ON ) +suspend_block (&main_suspend_blocker); +else +suspend_unblock (&main_suspend_blocker); +spin_unlock_irqrestore (&state_lock, irqflags); +return 0 ; +} + +void __init suspend_block_init (void ) +{ +suspend_blocker_init (&main_suspend_blocker,"main" ); +suspend_block (&main_suspend_blocker); +}
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Arve HjønnevågQuoted 39 lines · Arve Hjønnevåg
Adds
/sys/power/policythat selects the behaviour of/sys/power/state. After setting the policy to opportunistic, writes to/sys/power/statebecome 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 <[email protected]>--- Documentation/power/opportunistic-suspend.txt | 119 +++++++++++ include/linux/suspend_blocker.h | 64 ++++++ kernel/power/Kconfig | 16 ++ kernel/power/Makefile | 1 + kernel/power/main.c | 92 ++++++++- kernel/power/power.h | 9 + kernel/power/suspend.c | 4 +- kernel/power/suspend_blocker.c | 261 +++++++++++++++++++++++++ 8 files changed, 559 insertions(+), 7 deletions(-) create mode 100644 Documentation/power/opportunistic-suspend.txt create mode 100755 include/linux/suspend_blocker.h create mode 100644 kernel/power/suspend_blocker.cDocumentation/power/opportunistic-suspend.txt new file +12
-0@@ -0,0 +1,119 @@ +Opportunistic Suspend +===================== + +Opportunistic suspend is a feature allowing the system to be suspended (ie. put +into one of the available sleep states) automatically whenever it is regarded +as idle. The suspend blockers framework described below is used to determine +when that happens. + +The /sys/power/policy sysfs attribute is used to switch the system between the +opportunistic and "forced" suspend behavior, where in the latter case the +system is only suspended if a specific value, corresponding to one of the +available system sleep states, is written into /sys/power/state. However, in
Documentation/power/opportunistic-suspend.txt line 22
Quoted 10 lines
Documentation/power/opportunistic-suspend.txt new file +10
-0+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.
You know things would be so much easier if the policy was a one-shot styled thing. i.e. when enabled it does what it does, but upon resume the policy must be re-enabled by user mode to get the opportunistic behavior. That way we don't need to grab the suspend blocker from the wake up irq handler all the way up to user mode as the example below calls out. I suppose doing this would put a burden on the user mode code to keep track of if it has no pending blockers registered after a wake up from the suspend. but that seems nicer to me than sprinkling overlapping blocker critical sections from the mettle up to user mode.
Please consider making the policy a one shot API that needs to be re-enabled after resume by user mode. That would remove my issue with the design.
--mgross
Quoted 700 lines
Documentation/power/opportunistic-suspend.txt new file +97
-0+ +A suspend blocker is an object used to inform the PM subsystem when the system +can or cannot be suspended in the "opportunistic" mode (the "forced" mode +ignores suspend blockers). To use it, a device driver creates a struct +suspend_blocker that must be initialized with suspend_blocker_init(). Before +freeing the suspend_blocker structure or its name, suspend_blocker_destroy() +must be called on it. + +A suspend blocker is activated using suspend_block(), which prevents the PM +subsystem from putting the system into the requested sleep state in the +"opportunistic" mode until the suspend blocker is deactivated with +suspend_unblock(). Multiple suspend blockers may be active simultaneously, and +the system will not suspend as long as at least one of them is active. + +If opportunistic suspend is already in progress when suspend_block() is called, +it will abort the suspend, unless suspend_ops->enter has already been +executed. If suspend is aborted this way, the system is usually not fully +operational at that point. The suspend callbacks of some drivers may still be +running and it usually takes time to restore the system to the fully operational +state. + +Here's an example showing how a cell phone or other embedded system can handle +keystrokes (or other input events) in the presence of suspend blockers. Use +set_irq_wake or a platform specific api to make sure the keypad interrupt wakes +up the cpu. Once the keypad driver has resumed, the sequence of events can look +like this: + +- The Keypad driver gets an interrupt. It then calls suspend_block on the + keypad-scan suspend_blocker and starts scanning the keypad matrix. +- The keypad-scan code detects a key change and reports it to the input-event + driver. +- The input-event driver sees the key change, enqueues an event, and calls + suspend_block on the input-event-queue suspend_blocker. +- The keypad-scan code detects that no keys are held and calls suspend_unblock + on the keypad-scan suspend_blocker. +- The user-space input-event thread returns from select/poll, calls + suspend_block on the process-input-events suspend_blocker and then calls read + on the input-event device. +- The input-event driver dequeues the key-event and, since the queue is now + empty, it calls suspend_unblock on the input-event-queue suspend_blocker. +- The user-space input-event thread returns from read. If it determines that + the key should be ignored, it calls suspend_unblock on the + process_input_events suspend_blocker and then calls select or poll. The + system will automatically suspend again, since now no suspend blockers are + active. + +If the key that was pressed instead should preform a simple action (for example, +adjusting the volume), this action can be performed right before calling +suspend_unblock on the process_input_events suspend_blocker. However, if the key +triggers a longer-running action, that action needs its own suspend_blocker and +suspend_block must be called on that suspend blocker before calling +suspend_unblock on the process_input_events suspend_blocker. + + Key pressed Key released + | | +keypad-scan ++++++++++++++++++ +input-event-queue +++ +++ +process-input-events +++ +++ + + +Driver API +========== + +A driver can use the suspend block api by adding a suspend_blocker variable to +its state and calling suspend_blocker_init. For instance: +struct state { + struct suspend_blocker suspend_blocker; +} + +init() { + suspend_blocker_init(&state->suspend_blocker, "suspend-blocker-name"); +} + +Before freeing the memory, suspend_blocker_destroy must be called: + +uninit() { + suspend_blocker_destroy(&state->suspend_blocker); +} + +When the driver determines that it needs to run (usually in an interrupt +handler) it calls suspend_block: + suspend_block(&state->suspend_blocker); + +When it no longer needs to run it calls suspend_unblock: + suspend_unblock(&state->suspend_blocker); + +Calling suspend_block when the suspend blocker is active or suspend_unblock when +it is not active has no effect (i.e., these functions don't nest). This allows +drivers to update their state and call suspend suspend_block or suspend_unblock +based on the result. +For instance: + +if (list_empty(&state->pending_work)) + suspend_unblock(&state->suspend_blocker); +else + suspend_block(&state->suspend_blocker); +include/linux/suspend_blocker.h new file +64
-0@@ -0,0 +1,64 @@ +/* include/linux/suspend_blocker.h +* +* Copyright (C) 2007-2009 Google, Inc. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#ifndef _LINUX_SUSPEND_BLOCKER_H +#define _LINUX_SUSPEND_BLOCKER_H + +#include <linux/list.h> + +/** +* struct suspend_blocker - the basic suspend_blocker structure +* @link: List entry for active or inactive list. +* @flags: Tracks initialized and active state. +* @name: Name used for debugging. +* +* When a suspend_blocker is active it prevents the system from entering +* opportunistic suspend. +* +* The suspend_blocker structure must be initialized by suspend_blocker_init() +*/ + +struct suspend_blocker { +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND +struct list_head link; +int flags; +const char *name; +#endif +}; + +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND + +void suspend_blocker_init (struct suspend_blocker *blocker,const char *name); +void suspend_blocker_destroy (struct suspend_blocker *blocker); +void suspend_block (struct suspend_blocker *blocker); +void suspend_unblock (struct suspend_blocker *blocker); +bool suspend_blocker_is_active (struct suspend_blocker *blocker); +bool suspend_is_blocked (void ); + +#else + +static inline void suspend_blocker_init (struct suspend_blocker *blocker, +const char *name) {} +static inline void suspend_blocker_destroy (struct suspend_blocker *blocker) {} +static inline void suspend_block (struct suspend_blocker *blocker) {} +static inline void suspend_unblock (struct suspend_blocker *blocker) {} +static inline bool suspend_blocker_is_active (struct suspend_blocker *bl) + {return 0 ; } +static inline bool suspend_is_blocked (void ) {return 0 ; } + +#endif + +#endif +kernel/power/Kconfig +16
-0@@ -130,6 +130,22 @@ config SUSPEND_FREEZER Turning OFF this setting is NOT recommended! If in doubt, say Y. +config OPPORTUNISTIC_SUSPEND + bool "Suspend blockers" + depends on PM_SLEEP + select RTC_LIB + default n + ---help--- + Opportunistic sleep support. Allows the system to be put into a sleep + state opportunistically, if it doesn't do any useful work at the + moment. The PM subsystem is switched into this mode of operation by + writing "opportunistic" into /sys/power/policy, while writing + "forced" to this file turns the opportunistic suspend feature off. + In the "opportunistic" mode suspend blockers are used to determine + when to suspend the system and the value written to /sys/power/state + determines the sleep state the system will be put into when there are + no active suspend blockers. + config HIBERNATION_NVS boolkernel/power/Makefile +1
-0@@ -7,6 +7,7 @@ obj-$(CONFIG_PM) += main.o obj-$(CONFIG_PM_SLEEP) += console.o obj-$(CONFIG_FREEZER) += process.o obj-$(CONFIG_SUSPEND) += suspend.o +obj-$(CONFIG_OPPORTUNISTIC_SUSPEND) += suspend_blocker.o obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o obj-$(CONFIG_HIBERNATION_NVS) += hibernate_nvs.okernel/power/main.c +86
-6@@ -12,6 +12,7 @@#include <linux/string.h> #include <linux/resume-trace.h> #include <linux/workqueue.h> +#include <linux/suspend_blocker.h> #include "power.h" @@ -20,6 +21,27 @@ DEFINE_MUTEX(pm_mutex);unsigned int pm_flags;EXPORT_SYMBOL (pm_flags); +struct policy { +const char *name; +bool (*valid_state)(suspend_state_t state); +int (*set_state)(suspend_state_t state); +}; +static struct policy policies[] = { + { + .name ="forced" , + .valid_state = valid_state, + .set_state = enter_state, + }, +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND + { + .name ="opportunistic" , + .valid_state = request_suspend_valid_state, + .set_state = request_suspend_state, + }, +#endif +}; +static int policy; +#ifdef CONFIG_PM_SLEEP /* Routines for PM-transition notifications */ @@ -146,6 +168,12 @@ struct kobject *power_kobj;* * store() accepts one of those strings, translates it into the * proper enumerated value, and initiates a suspend transition. +* +* If policy is set to opportunistic, store() does not block until the +* system resumes, and it will try to re-enter the state until another +* state is requested. Suspend blockers are respected and the requested +* state will only be entered when no suspend blockers are active. +* Write "on" to cancel. */ static ssize_t state_show (struct kobject *kobj,struct kobj_attribute *attr,char *buf)@@ -155,12 +183,13 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,int i;for (i =0 ; i <PM_SUSPEND_MAX ; i++) { -if (pm_states[i] &&valid_state (i)) +if (pm_states[i] && policies[policy].valid_state (i)) s +=sprintf (s,"%s " , pm_states[i]); }#endif #ifdef CONFIG_HIBERNATION - s +=sprintf (s,"%s\n" ,"disk" ); +if (!policy) + s +=sprintf (s,"%s\n" ,"disk" );#else if (s != buf)/* convert the last space to a newline */ @@ -173,7 +202,7 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) {#ifdef CONFIG_SUSPEND -suspend_state_t state =PM_SUSPEND_STANDBY ; +suspend_state_t state =PM_SUSPEND_ON ;const char *const *s;#endif char *p;@@ -184,7 +213,7 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, len = p ? p - buf : n;/* First, check if we are requested to hibernate */ -if (len ==4 && !strncmp (buf,"disk" , len)) { +if (len ==4 && !strncmp (buf,"disk" , len) && !policy) { error =hibernate (); goto Exit; }@@ -195,7 +224,7 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, break; }if (state <PM_SUSPEND_MAX && *s) - error =enter_state (state); + error = policies[policy].set_state (state);#endif Exit:@@ -204,6 +233,55 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,power_attr (state); +/** +* policy - set policy for state +*/ + +static ssize_t policy_show (struct kobject *kobj, +struct kobj_attribute *attr,char *buf) +{ +char *s = buf; +int i; + +for (i =0 ; i <ARRAY_SIZE (policies); i++) { +if (i == policy) + s +=sprintf (s,"[%s] " , policies[i].name); +else + s +=sprintf (s,"%s " , policies[i].name); + } +if (s != buf) +/* convert the last space to a newline */ + *(s-1 ) ='\n' ; +return (s - buf); +} + +static ssize_t policy_store (struct kobject *kobj, +struct kobj_attribute *attr, +const char *buf,size_t n) +{ +const char *s; +char *p; +int len; +int i; + + p =memchr (buf,'\n' , n); + len = p ? p - buf : n; + +for (i =0 ; i <ARRAY_SIZE (policies); i++) { + s = policies[i].name; +if (s && len ==strlen (s) && !strncmp (buf, s, len)) { +mutex_lock (&pm_mutex); + policies[policy].set_state (PM_SUSPEND_ON ); + policy = i; +mutex_unlock (&pm_mutex); +return n; + } + } +return -EINVAL ; +} + +power_attr (policy); +#ifdef CONFIG_PM_TRACE int pm_trace_enabled;@@ -231,6 +309,7 @@ power_attr(pm_trace);static struct attribute * g[] = { &state_attr.attr, + &policy_attr.attr, #ifdef CONFIG_PM_TRACE &pm_trace_attr.attr, #endif@@ -247,7 +326,7 @@ static struct attribute_group attr_group = { .attrs = g, }; -#ifdef CONFIG_PM_RUNTIME +#if defined(CONFIG_PM_RUNTIME ) || defined(CONFIG_OPPORTUNISTIC_SUSPEND )struct workqueue_struct *pm_wq;EXPORT_SYMBOL_GPL (pm_wq);@@ -266,6 +345,7 @@ static int __init pm_init(void)int error =pm_start_workqueue ();if (error)return error; +suspend_block_init (); power_kobj =kobject_create_and_add ("power" ,NULL );if (!power_kobj)return -ENOMEM ;kernel/power/power.h +9
-0@@ -236,3 +236,12 @@ static inline void suspend_thaw_processes(void) { }#endif + +/* kernel/power/suspend_block.c */ +extern int request_suspend_state (suspend_state_t state); +extern bool request_suspend_valid_state (suspend_state_t state); +#ifdef CONFIG_OPPORTUNISTIC_SUSPEND +extern void __init suspend_block_init (void ); +#else +static inline void suspend_block_init (void ) {} +#endif kernel/power/suspend.c +3
-1@@ -16,10 +16,12 @@#include <linux/cpu.h> #include <linux/syscalls.h> #include <linux/gfp.h> +#include <linux/suspend_blocker.h> #include "power.h" const char *const pm_states[PM_SUSPEND_MAX ] = { + [PM_SUSPEND_ON ] ="on" , [PM_SUSPEND_STANDBY ] ="standby" , [PM_SUSPEND_MEM ] ="mem" , };@@ -157,7 +159,7 @@ static int suspend_enter(suspend_state_t state) error =sysdev_suspend (PMSG_SUSPEND );if (!error) { -if (!suspend_test (TEST_CORE )) +if (!suspend_is_blocked () && !suspend_test (TEST_CORE )) error = suspend_ops->enter (state);sysdev_resume (); }kernel/power/suspend_blocker.c new file +261
-0@@ -0,0 +1,261 @@ +/* kernel/power/suspend_blocker.c +* +* Copyright (C) 2005-2010 Google, Inc. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#include <linux/module.h> +#include <linux/rtc.h> +#include <linux/suspend.h> +#include <linux/suspend_blocker.h> +#include "power.h" + +extern struct workqueue_struct *pm_wq; + +enum { +DEBUG_EXIT_SUSPEND =1U <<0 , +DEBUG_WAKEUP =1U <<1 , +DEBUG_USER_STATE =1U <<2 , +DEBUG_SUSPEND =1U <<3 , +DEBUG_SUSPEND_BLOCKER =1U <<4 , +}; +static int debug_mask =DEBUG_EXIT_SUSPEND |DEBUG_WAKEUP |DEBUG_USER_STATE ; +module_param_named (debug_mask, debug_mask, int,S_IRUGO |S_IWUSR |S_IWGRP ); + +#define SB_INITIALIZED (1U << 8) +#define SB_ACTIVE (1U << 9) + +static DEFINE_SPINLOCK (list_lock); +static DEFINE_SPINLOCK (state_lock); +static LIST_HEAD (inactive_blockers); +static LIST_HEAD (active_blockers); +static int current_event_num; +struct suspend_blocker main_suspend_blocker; +static suspend_state_t requested_suspend_state =PM_SUSPEND_MEM ; +static bool enable_suspend_blockers; + +#define pr_info_time(fmt, args...) \ + do { \ + struct timespec ts; \ + struct rtc_time tm; \ + getnstimeofday(&ts); \ + rtc_time_to_tm(ts.tv_sec, &tm); \ + pr_info(fmt "(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n" , \ + args, \ + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, \ + tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec); \ + } while (0); + +static void print_active_blockers_locked (void ) +{ +struct suspend_blocker *blocker; + +list_for_each_entry (blocker, &active_blockers, link) +pr_info ("active suspend blocker %s\n" , blocker->name); +} + +/** +* suspend_is_blocked() - Check if suspend should be blocked +* +* suspend_is_blocked can be used by generic power management code to abort +* suspend. +* +* To preserve backward compatibility suspend_is_blocked returns 0 unless it +* is called during suspend initiated from the suspend_block code. +*/ +bool suspend_is_blocked (void ) +{ +if (!enable_suspend_blockers) +return 0 ; +return !list_empty (&active_blockers); +} + +static void suspend_worker (struct work_struct *work) +{ +int ret; +int entry_event_num; + + enable_suspend_blockers = true; +while (!suspend_is_blocked ()) { + entry_event_num = current_event_num; + +if (debug_mask &DEBUG_SUSPEND ) +pr_info ("suspend: enter suspend\n" ); + + ret =pm_suspend (requested_suspend_state); + +if (debug_mask &DEBUG_EXIT_SUSPEND ) +pr_info_time ("suspend: exit suspend, ret = %d " , ret); + +if (current_event_num == entry_event_num) +pr_info ("suspend: pm_suspend returned with no event\n" ); + } + enable_suspend_blockers = false; +} +static DECLARE_WORK(suspend_work, suspend_worker); + +/** +* suspend_blocker_init() - Initialize a suspend blocker +* @blocker: The suspend blocker to initialize. +* @name: The name of the suspend blocker to show in debug messages. +* +* The suspend blocker struct and name must not be freed before calling +* suspend_blocker_destroy. +*/ +void suspend_blocker_init (struct suspend_blocker *blocker,const char *name) +{ +unsigned long irqflags =0 ; + +WARN_ON (!name); + +if (debug_mask &DEBUG_SUSPEND_BLOCKER ) +pr_info ("suspend_blocker_init name=%s\n" , name); + + blocker->name = name; + blocker->flags =SB_INITIALIZED ; +INIT_LIST_HEAD (&blocker->link); + +spin_lock_irqsave (&list_lock, irqflags); +list_add (&blocker->link, &inactive_blockers); +spin_unlock_irqrestore (&list_lock, irqflags); +} +EXPORT_SYMBOL (suspend_blocker_init); + +/** +* suspend_blocker_destroy() - Destroy a suspend blocker +* @blocker: The suspend blocker to destroy. +*/ +void suspend_blocker_destroy (struct suspend_blocker *blocker) +{ +unsigned long irqflags; +if (WARN_ON (!(blocker->flags &SB_INITIALIZED ))) +return ; + +if (debug_mask &DEBUG_SUSPEND_BLOCKER ) +pr_info ("suspend_blocker_destroy name=%s\n" , blocker->name); + +spin_lock_irqsave (&list_lock, irqflags); + blocker->flags &= ~SB_INITIALIZED ; +list_del (&blocker->link); +if ((blocker->flags &SB_ACTIVE ) &&list_empty (&active_blockers)) +queue_work (pm_wq, &suspend_work); +spin_unlock_irqrestore (&list_lock, irqflags); +} +EXPORT_SYMBOL (suspend_blocker_destroy); + +/** +* suspend_block() - Block suspend +* @blocker: The suspend blocker to use +* +* It is safe to call this function from interrupt context. +*/ +void suspend_block (struct suspend_blocker *blocker) +{ +unsigned long irqflags; + +if (WARN_ON (!(blocker->flags &SB_INITIALIZED ))) +return ; + +spin_lock_irqsave (&list_lock, irqflags); + +if (debug_mask &DEBUG_SUSPEND_BLOCKER ) +pr_info ("suspend_block: %s\n" , blocker->name); + + blocker->flags |=SB_ACTIVE ; +list_move (&blocker->link, &active_blockers); + current_event_num++; + +spin_unlock_irqrestore (&list_lock, irqflags); +} +EXPORT_SYMBOL (suspend_block); + +/** +* suspend_unblock() - Unblock suspend +* @blocker: The suspend blocker to unblock. +* +* If no other suspend blockers block suspend, the system will suspend. +* +* It is safe to call this function from interrupt context. +*/ +void suspend_unblock (struct suspend_blocker *blocker) +{ +unsigned long irqflags; + +if (WARN_ON (!(blocker->flags &SB_INITIALIZED ))) +return ; + +spin_lock_irqsave (&list_lock, irqflags); + +if (debug_mask &DEBUG_SUSPEND_BLOCKER ) +pr_info ("suspend_unblock: %s\n" , blocker->name); + +list_move (&blocker->link, &inactive_blockers); + +if ((blocker->flags &SB_ACTIVE ) &&list_empty (&active_blockers)) +queue_work (pm_wq, &suspend_work); + blocker->flags &= ~(SB_ACTIVE ); +if (blocker == &main_suspend_blocker) { +if (debug_mask &DEBUG_SUSPEND ) +print_active_blockers_locked (); + } +spin_unlock_irqrestore (&list_lock, irqflags); +} +EXPORT_SYMBOL (suspend_unblock); + +/** +* suspend_blocker_is_active() - Test if a suspend blocker is blocking suspend +* @blocker: The suspend blocker to check. +* +* Returns true if the suspend_blocker is currently active. +*/ +bool suspend_blocker_is_active (struct suspend_blocker *blocker) +{ +WARN_ON (!(blocker->flags &SB_INITIALIZED )); + +return !!(blocker->flags &SB_ACTIVE ); +} +EXPORT_SYMBOL (suspend_blocker_is_active); + +bool request_suspend_valid_state (suspend_state_t state) +{ +return (state ==PM_SUSPEND_ON ) ||valid_state (state); +} + +int request_suspend_state (suspend_state_t state) +{ +unsigned long irqflags; + +if (!request_suspend_valid_state (state)) +return -ENODEV ; + +spin_lock_irqsave (&state_lock, irqflags); + +if (debug_mask &DEBUG_USER_STATE ) +pr_info_time ("request_suspend_state: %s (%d->%d) at %lld " , + state !=PM_SUSPEND_ON ?"sleep" :"wakeup" , + requested_suspend_state, state, +ktime_to_ns (ktime_get ())); + + requested_suspend_state = state; +if (state ==PM_SUSPEND_ON ) +suspend_block (&main_suspend_blocker); +else +suspend_unblock (&main_suspend_blocker); +spin_unlock_irqrestore (&state_lock, irqflags); +return 0 ; +} + +void __init suspend_block_init (void ) +{ +suspend_blocker_init (&main_suspend_blocker,"main" ); +suspend_block (&main_suspend_blocker); +}Signature · 6 lines
1.6.5.1 _______________________________________________ linux-pm mailing list [email protected] https://lists.linux-foundation.org/mailman/listinfo/linux-pm
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 10 lines · mark gross
You know things would be so much easier if the policy was a one-shot styled thing. i.e. when enabled it does what it does, but upon resume the policy must be re-enabled by user mode to get the opportunistic behavior. That way we don't need to grab the suspend blocker from the wake up irq handler all the way up to user mode as the example below calls out. I suppose doing this would put a burden on the user mode code to keep track of if it has no pending blockers registered after a wake up from the suspend. but that seems nicer to me than sprinkling overlapping blocker critical sections from the mettle up to user mode.
Quoted 3 lines
Please consider making the policy a one shot API that needs to be re-enabled after resume by user mode. That would remove my issue with the design.
This won't work right if a second IRQ arrives while the first is being processed. Suppose the kernel driver for the second IRQ doesn't activate a suspend blocker, and suppose all the userspace handlers for the first IRQ end (and the opportunistic policy is re-enabled) before the userspace handler for the second IRQ can start. Then the system will go back to sleep before userspace can handle the second IRQ.
Alan Stern
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to mark grossQuoted 10 lines · mark gross
You know things would be so much easier if the policy was a one-shot styled thing. i.e. when enabled it does what it does, but upon resume the policy must be re-enabled by user mode to get the opportunistic behavior. That way we don't need to grab the suspend blocker from the wake up irq handler all the way up to user mode as the example below calls out. I suppose doing this would put a burden on the user mode code to keep track of if it has no pending blockers registered after a wake up from the suspend. but that seems nicer to me than sprinkling overlapping blocker critical sections from the mettle up to user mode.
Quoted 3 lines
Please consider making the policy a one shot API that needs to be re-enabled after resume by user mode. That would remove my issue with the design.
This won't work right if a second IRQ arrives while the first is being processed. Suppose the kernel driver for the second IRQ doesn't activate a suspend blocker, and suppose all the userspace handlers for the first IRQ end (and the opportunistic policy is re-enabled) before the userspace handler for the second IRQ can start. Then the system will go back to sleep before userspace can handle the second IRQ.
Alan Stern
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 16 lines · Alan Stern
Quoted 10 lines · mark gross
You know things would be so much easier if the policy was a one-shot styled thing. i.e. when enabled it does what it does, but upon resume the policy must be re-enabled by user mode to get the opportunistic behavior. That way we don't need to grab the suspend blocker from the wake up irq handler all the way up to user mode as the example below calls out. I suppose doing this would put a burden on the user mode code to keep track of if it has no pending blockers registered after a wake up from the suspend. but that seems nicer to me than sprinkling overlapping blocker critical sections from the mettle up to user mode.
Quoted 3 lines
Please consider making the policy a one shot API that needs to be re-enabled after resume by user mode. That would remove my issue with the design.
Quoted 7 lines
This won't work right if a second IRQ arrives while the first is being processed. Suppose the kernel driver for the second IRQ doesn't activate a suspend blocker, and suppose all the userspace handlers for the first IRQ end (and the opportunistic policy is re-enabled) before the userspace handler for the second IRQ can start. Then the system will go back to sleep before userspace can handle the second IRQ.
What? If the suspend blocker API was a one shot styled api, after the suspend, the one shot is over and the behavior is that you do not fall back into suspend again until user mode re-enables the one-shot behavior.
With what I am proposing the next suspend would not happen until the user mode code re-enables the suspend blocking behavior. It would much cleaner for everyone and I see zero down side WRT the example you just posted.
If user mode triggers a suspend by releasing the last blocker, you have until pm_suspend('mem') turns off interrupts to cancel it. That race will never go away.
Let me think this through, please check that I'm understanding the issue please:
1) one-shot policy enable blocker PM suspend behavior;
2) release last blocker and call pm_suspend('mem') and suspend all the way down.
3) get wake up event, one-shot policy over, no-blockers in list
4) go all the way to user mode,
5) user mode decides to not grab a blocker, and re-enables one-shot policy
6) pm_suspend('mem') called
7) interrupt comes in (say the modem rings)
8) modem driver handler needs to returns fail from pm_suspend call back, device resumes (I am proposing changing the posted api for doing this.)
9) user mode figures out one-shot needs to be re-enabled and it grabs a blocker to handle the call and re-enables the one-shot.
So the real problem grabbing blockers from ISR's trying to solve is to reduce the window of time where a pm_suspend('mem') can be canceled.
My proposal is to;
1) change the kernel blocker api to be "cancel-one-shot-policy-enable" that can be called from the ISR's for the wake up devices before the IRQ's are disabled to cancel an in-flight suspend. I would make it 2 macros one goes in the pm_suspend callback to return fail, and the other in the ISR to disable the one-shot-policy.
2) make the policy a one shot that user mode must re-enable after each suspend attempted.
Would it help if I coded up the above proposal as patch to the current (rev-6) of the blocker patchset? I'm offering.
Because this part of the current design is broken, in that it demands the sprinkling of blocker critical sections from the hardware up to the user mode. Its ugly, hard to get right and if more folks would take a look at how well it worked out for the existing kernels on android.git.kernel.org/kernels/ perhaps it would get more attention.
Finally, as an aside, lets look at the problem with the posted rev-6 patches:
1) enable suspend blocker policy
2) release user-mode blocker
3) start suspend
4) get a modem interrupt (incoming call)
5) ooops, IRQ came in after pm_suspend('mem') turned off interrupts. bummer for you, thats life with this design. Better hope your modem hardware is modified to keep pulling on that wake up line because you're past the point of no return now and going to suspend.
Grabbing a blocker in the ISR doesn't solve this. So your hardware needs to have a persistent wake up trigger that is robust against this scenario. And, if you have such hardware then why are we killing ourselves to maximize the window of time between pm_suspend('mem') and platform suspend where you can cancel the suspend? The hardware will simply wake up anyway.
(further, on my hardware I would modify the platform suspend call back to make one last check to see if an IRQ came in, and cancel the suspend there as a last chance.)
--mgross
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Alan SternQuoted 16 lines · Alan Stern
Quoted 10 lines · mark gross
You know things would be so much easier if the policy was a one-shot styled thing. i.e. when enabled it does what it does, but upon resume the policy must be re-enabled by user mode to get the opportunistic behavior. That way we don't need to grab the suspend blocker from the wake up irq handler all the way up to user mode as the example below calls out. I suppose doing this would put a burden on the user mode code to keep track of if it has no pending blockers registered after a wake up from the suspend. but that seems nicer to me than sprinkling overlapping blocker critical sections from the mettle up to user mode.
Quoted 3 lines
Please consider making the policy a one shot API that needs to be re-enabled after resume by user mode. That would remove my issue with the design.
Quoted 7 lines
This won't work right if a second IRQ arrives while the first is being processed. Suppose the kernel driver for the second IRQ doesn't activate a suspend blocker, and suppose all the userspace handlers for the first IRQ end (and the opportunistic policy is re-enabled) before the userspace handler for the second IRQ can start. Then the system will go back to sleep before userspace can handle the second IRQ.
What? If the suspend blocker API was a one shot styled api, after the suspend, the one shot is over and the behavior is that you do not fall back into suspend again until user mode re-enables the one-shot behavior.
With what I am proposing the next suspend would not happen until the user mode code re-enables the suspend blocking behavior. It would much cleaner for everyone and I see zero down side WRT the example you just posted.
If user mode triggers a suspend by releasing the last blocker, you have until pm_suspend('mem') turns off interrupts to cancel it. That race will never go away.
Let me think this through, please check that I'm understanding the issue please:
1) one-shot policy enable blocker PM suspend behavior;
2) release last blocker and call pm_suspend('mem') and suspend all the way down.
3) get wake up event, one-shot policy over, no-blockers in list
4) go all the way to user mode,
5) user mode decides to not grab a blocker, and re-enables one-shot policy
6) pm_suspend('mem') called
7) interrupt comes in (say the modem rings)
8) modem driver handler needs to returns fail from pm_suspend call back, device resumes (I am proposing changing the posted api for doing this.)
9) user mode figures out one-shot needs to be re-enabled and it grabs a blocker to handle the call and re-enables the one-shot.
So the real problem grabbing blockers from ISR's trying to solve is to reduce the window of time where a pm_suspend('mem') can be canceled.
My proposal is to;
1) change the kernel blocker api to be "cancel-one-shot-policy-enable" that can be called from the ISR's for the wake up devices before the IRQ's are disabled to cancel an in-flight suspend. I would make it 2 macros one goes in the pm_suspend callback to return fail, and the other in the ISR to disable the one-shot-policy.
2) make the policy a one shot that user mode must re-enable after each suspend attempted.
Would it help if I coded up the above proposal as patch to the current (rev-6) of the blocker patchset? I'm offering.
Because this part of the current design is broken, in that it demands the sprinkling of blocker critical sections from the hardware up to the user mode. Its ugly, hard to get right and if more folks would take a look at how well it worked out for the existing kernels on android.git.kernel.org/kernels/ perhaps it would get more attention.
Finally, as an aside, lets look at the problem with the posted rev-6 patches:
1) enable suspend blocker policy
2) release user-mode blocker
3) start suspend
4) get a modem interrupt (incoming call)
5) ooops, IRQ came in after pm_suspend('mem') turned off interrupts. bummer for you, thats life with this design. Better hope your modem hardware is modified to keep pulling on that wake up line because you're past the point of no return now and going to suspend.
Grabbing a blocker in the ISR doesn't solve this. So your hardware needs to have a persistent wake up trigger that is robust against this scenario. And, if you have such hardware then why are we killing ourselves to maximize the window of time between pm_suspend('mem') and platform suspend where you can cancel the suspend? The hardware will simply wake up anyway.
(further, on my hardware I would modify the platform suspend call back to make one last check to see if an IRQ came in, and cancel the suspend there as a last chance.)
--mgross
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 25 lines · mark gross
Quoted 16 lines · Alan Stern
Quoted 10 lines · mark gross
You know things would be so much easier if the policy was a one-shot styled thing. i.e. when enabled it does what it does, but upon resume the policy must be re-enabled by user mode to get the opportunistic behavior. That way we don't need to grab the suspend blocker from the wake up irq handler all the way up to user mode as the example below calls out. I suppose doing this would put a burden on the user mode code to keep track of if it has no pending blockers registered after a wake up from the suspend. but that seems nicer to me than sprinkling overlapping blocker critical sections from the mettle up to user mode.
Quoted 3 lines
Please consider making the policy a one shot API that needs to be re-enabled after resume by user mode. That would remove my issue with the design.
Quoted 7 lines
This won't work right if a second IRQ arrives while the first is being processed. Suppose the kernel driver for the second IRQ doesn't activate a suspend blocker, and suppose all the userspace handlers for the first IRQ end (and the opportunistic policy is re-enabled) before the userspace handler for the second IRQ can start. Then the system will go back to sleep before userspace can handle the second IRQ.
Quoted 4 lines
What? If the suspend blocker API was a one shot styled api, after the suspend, the one shot is over and the behavior is that you do not fall back into suspend again until user mode re-enables the one-shot behavior.
I was referring to your sentence: "That way we don't need to grab the suspend blocker from the wake up irq handler all the way up to user mode..." The problem arises when kernel handlers don't do _something_ to prevent another suspend from occurring too soon.
Quoted 8 lines
With what I am proposing the next suspend would not happen until the user mode code re-enables the suspend blocking behavior. It would much cleaner for everyone and I see zero down side WRT the example you just posted.
If user mode triggers a suspend by releasing the last blocker, you have until
pm_suspend('mem')turns off interrupts to cancel it. That race will never go away.
(Actually the kernel can cancel the suspend even after interrupts are turned off, if it has a reason to do so.)
In theory the race between interrupts and suspend don't need to be a problem. In practice it still is -- the PM core needs a few changes to allow wakeup interrupts to cancel a suspend in progress. Regardless, that's not what I was talking about.
Quoted 7 lines
Let me think this through, please check that I'm understanding the issue please:
1) one-shot policy enable blocker PM suspend behavior;
2) release last blocker and callpm_suspend('mem')and suspend all the way down.
3) get wake up event, one-shot policy over, no-blockers in list
4) go all the way to user mode,
Quoted 8 lines
5) user mode decides to not grab a blocker, and re-enables one-shot policy
6)pm_suspend('mem')called
7) interrupt comes in (say the modem rings)
8) modem driver handler needs to returns fail frompm_suspendcall back, device resumes (I am proposing changing the posted api for doing this.)
9) user mode figures out one-shot needs to be re-enabled and it grabs a blocker to handle the call and re-enables the one-shot.
This is not the scenario I was describing. Here's what I had in mind:
1) The system is asleep
2) Wakeup event occurs, one-shot policy over
3) Go all the way to user mode
4) A second wakeup interrupt occurs (say the modem rings)
5) The modem driver does not enable any suspend blockers
6) The modem driver queues an input event for userspace
7) The userspace handler invoked during 3) finishes and re-enables the one-shot policy
8) No suspend blockers are enabled, so the system goes to sleep
9) The userspace handler for the input event in 6) doesn't get to run
Quoted 2 lines
So the real problem grabbing blockers from ISR's trying to solve is to reduce the window of time where a
pm_suspend('mem')can be canceled.
No. The real problem is how ISRs should prevent the system from suspending before the events they generate can be handled by userspace.
Quoted 9 lines
My proposal is to;
1) change the kernel blocker api to be "cancel-one-shot-policy-enable" that can be called from the ISR's for the wake up devices before the IRQ's are disabled to cancel an in-flight suspend. I would make it 2 macros one goes in thepm_suspendcallback to return fail, and the other in the ISR to disable the one-shot-policy.2) make the policy a one shot that user mode must re-enable after each suspend attempted.
Neither of these solves the race I described.
Quoted 8 lines
Would it help if I coded up the above proposal as patch to the current (rev-6) of the blocker patchset? I'm offering.
Because this part of the current design is broken, in that it demands the sprinkling of blocker critical sections from the hardware up to the user mode. Its ugly, hard to get right and if more folks would take a look at how well it worked out for the existing kernels on android.git.kernel.org/kernels/ perhaps it would get more attention.
I agree, it is ugly and probably hard to get right. But something like it is necessary to solve this race.
Quoted 10 lines
Finally, as an aside, lets look at the problem with the posted rev-6 patches:
1) enable suspend blocker policy
2) release user-mode blocker
3) start suspend
4) get a modem interrupt (incoming call)
5) ooops, IRQ came in afterpm_suspend('mem')turned off interrupts. bummer for you, thats life with this design. Better hope your modem hardware is modified to keep pulling on that wake up line because you're past the point of no return now and going to suspend.
That is not a problem for level-sensitive IRQs. If interrupts have been turned off then the modem will not receive any commands telling it to stop requesting an interrupt. So the IRQ line will remain active until the system goes to sleep, at which point it will immediately wake up the system.
For edge-sensitive interrupts the situation isn't as simple. The low-level IRQ code must handle this somehow.
Quoted 6 lines
Grabbing a blocker in the ISR doesn't solve this. So your hardware needs to have a persistent wake up trigger that is robust against this scenario. And, if you have such hardware then why are we killing ourselves to maximize the window of time between
pm_suspend('mem')and platform suspend where you can cancel the suspend? The hardware will simply wake up anyway.
That's not what we are killing ourselves for. The point of suspend blockers is not to prevent races with the hardware. It is to prevent userspace from being frozen while there's still work to be done.
Alan Stern
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to mark grossQuoted 25 lines · mark gross
Quoted 16 lines · Alan Stern
Quoted 10 lines · mark gross
You know things would be so much easier if the policy was a one-shot styled thing. i.e. when enabled it does what it does, but upon resume the policy must be re-enabled by user mode to get the opportunistic behavior. That way we don't need to grab the suspend blocker from the wake up irq handler all the way up to user mode as the example below calls out. I suppose doing this would put a burden on the user mode code to keep track of if it has no pending blockers registered after a wake up from the suspend. but that seems nicer to me than sprinkling overlapping blocker critical sections from the mettle up to user mode.
Quoted 3 lines
Please consider making the policy a one shot API that needs to be re-enabled after resume by user mode. That would remove my issue with the design.
Quoted 7 lines
This won't work right if a second IRQ arrives while the first is being processed. Suppose the kernel driver for the second IRQ doesn't activate a suspend blocker, and suppose all the userspace handlers for the first IRQ end (and the opportunistic policy is re-enabled) before the userspace handler for the second IRQ can start. Then the system will go back to sleep before userspace can handle the second IRQ.
Quoted 4 lines
What? If the suspend blocker API was a one shot styled api, after the suspend, the one shot is over and the behavior is that you do not fall back into suspend again until user mode re-enables the one-shot behavior.
I was referring to your sentence: "That way we don't need to grab the suspend blocker from the wake up irq handler all the way up to user mode..." The problem arises when kernel handlers don't do _something_ to prevent another suspend from occurring too soon.
Quoted 8 lines
With what I am proposing the next suspend would not happen until the user mode code re-enables the suspend blocking behavior. It would much cleaner for everyone and I see zero down side WRT the example you just posted.
If user mode triggers a suspend by releasing the last blocker, you have until
pm_suspend('mem')turns off interrupts to cancel it. That race will never go away.
(Actually the kernel can cancel the suspend even after interrupts are turned off, if it has a reason to do so.)
In theory the race between interrupts and suspend don't need to be a problem. In practice it still is -- the PM core needs a few changes to allow wakeup interrupts to cancel a suspend in progress. Regardless, that's not what I was talking about.
Quoted 7 lines
Let me think this through, please check that I'm understanding the issue please:
1) one-shot policy enable blocker PM suspend behavior;
2) release last blocker and callpm_suspend('mem')and suspend all the way down.
3) get wake up event, one-shot policy over, no-blockers in list
4) go all the way to user mode,
Quoted 8 lines
5) user mode decides to not grab a blocker, and re-enables one-shot policy
6)pm_suspend('mem')called
7) interrupt comes in (say the modem rings)
8) modem driver handler needs to returns fail frompm_suspendcall back, device resumes (I am proposing changing the posted api for doing this.)
9) user mode figures out one-shot needs to be re-enabled and it grabs a blocker to handle the call and re-enables the one-shot.
This is not the scenario I was describing. Here's what I had in mind:
1) The system is asleep
2) Wakeup event occurs, one-shot policy over
3) Go all the way to user mode
4) A second wakeup interrupt occurs (say the modem rings)
5) The modem driver does not enable any suspend blockers
6) The modem driver queues an input event for userspace
7) The userspace handler invoked during 3) finishes and re-enables the one-shot policy
8) No suspend blockers are enabled, so the system goes to sleep
9) The userspace handler for the input event in 6) doesn't get to run
Quoted 2 lines
So the real problem grabbing blockers from ISR's trying to solve is to reduce the window of time where a
pm_suspend('mem')can be canceled.
No. The real problem is how ISRs should prevent the system from suspending before the events they generate can be handled by userspace.
Quoted 9 lines
My proposal is to;
1) change the kernel blocker api to be "cancel-one-shot-policy-enable" that can be called from the ISR's for the wake up devices before the IRQ's are disabled to cancel an in-flight suspend. I would make it 2 macros one goes in thepm_suspendcallback to return fail, and the other in the ISR to disable the one-shot-policy.2) make the policy a one shot that user mode must re-enable after each suspend attempted.
Neither of these solves the race I described.
Quoted 8 lines
Would it help if I coded up the above proposal as patch to the current (rev-6) of the blocker patchset? I'm offering.
Because this part of the current design is broken, in that it demands the sprinkling of blocker critical sections from the hardware up to the user mode. Its ugly, hard to get right and if more folks would take a look at how well it worked out for the existing kernels on android.git.kernel.org/kernels/ perhaps it would get more attention.
I agree, it is ugly and probably hard to get right. But something like it is necessary to solve this race.
Quoted 10 lines
Finally, as an aside, lets look at the problem with the posted rev-6 patches:
1) enable suspend blocker policy
2) release user-mode blocker
3) start suspend
4) get a modem interrupt (incoming call)
5) ooops, IRQ came in afterpm_suspend('mem')turned off interrupts. bummer for you, thats life with this design. Better hope your modem hardware is modified to keep pulling on that wake up line because you're past the point of no return now and going to suspend.
That is not a problem for level-sensitive IRQs. If interrupts have been turned off then the modem will not receive any commands telling it to stop requesting an interrupt. So the IRQ line will remain active until the system goes to sleep, at which point it will immediately wake up the system.
For edge-sensitive interrupts the situation isn't as simple. The low-level IRQ code must handle this somehow.
Quoted 6 lines
Grabbing a blocker in the ISR doesn't solve this. So your hardware needs to have a persistent wake up trigger that is robust against this scenario. And, if you have such hardware then why are we killing ourselves to maximize the window of time between
pm_suspend('mem')and platform suspend where you can cancel the suspend? The hardware will simply wake up anyway.
That's not what we are killing ourselves for. The point of suspend blockers is not to prevent races with the hardware. It is to prevent userspace from being frozen while there's still work to be done.
Alan Stern
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 72 lines · Alan Stern
Quoted 25 lines · mark gross
Quoted 16 lines · Alan Stern
Quoted 10 lines · mark gross
You know things would be so much easier if the policy was a one-shot styled thing. i.e. when enabled it does what it does, but upon resume the policy must be re-enabled by user mode to get the opportunistic behavior. That way we don't need to grab the suspend blocker from the wake up irq handler all the way up to user mode as the example below calls out. I suppose doing this would put a burden on the user mode code to keep track of if it has no pending blockers registered after a wake up from the suspend. but that seems nicer to me than sprinkling overlapping blocker critical sections from the mettle up to user mode.
Quoted 3 lines
Please consider making the policy a one shot API that needs to be re-enabled after resume by user mode. That would remove my issue with the design.
Quoted 7 lines
This won't work right if a second IRQ arrives while the first is being processed. Suppose the kernel driver for the second IRQ doesn't activate a suspend blocker, and suppose all the userspace handlers for the first IRQ end (and the opportunistic policy is re-enabled) before the userspace handler for the second IRQ can start. Then the system will go back to sleep before userspace can handle the second IRQ.
Quoted 4 lines
What? If the suspend blocker API was a one shot styled api, after the suspend, the one shot is over and the behavior is that you do not fall back into suspend again until user mode re-enables the one-shot behavior.
I was referring to your sentence: "That way we don't need to grab the suspend blocker from the wake up irq handler all the way up to user mode..." The problem arises when kernel handlers don't do _something_ to prevent another suspend from occurring too soon.
Quoted 8 lines
With what I am proposing the next suspend would not happen until the user mode code re-enables the suspend blocking behavior. It would much cleaner for everyone and I see zero down side WRT the example you just posted.
If user mode triggers a suspend by releasing the last blocker, you have until
pm_suspend('mem')turns off interrupts to cancel it. That race will never go away.(Actually the kernel can cancel the suspend even after interrupts are turned off, if it has a reason to do so.)
In theory the race between interrupts and suspend don't need to be a problem. In practice it still is -- the PM core needs a few changes to allow wakeup interrupts to cancel a suspend in progress. Regardless, that's not what I was talking about.
Quoted 7 lines
Let me think this through, please check that I'm understanding the issue please:
1) one-shot policy enable blocker PM suspend behavior;
2) release last blocker and callpm_suspend('mem')and suspend all the way down.
3) get wake up event, one-shot policy over, no-blockers in list
4) go all the way to user mode,Quoted 8 lines
5) user mode decides to not grab a blocker, and re-enables one-shot policy
6)pm_suspend('mem')called
7) interrupt comes in (say the modem rings)
8) modem driver handler needs to returns fail frompm_suspendcall back, device resumes (I am proposing changing the posted api for doing this.)
9) user mode figures out one-shot needs to be re-enabled and it grabs a blocker to handle the call and re-enables the one-shot.This is not the scenario I was describing. Here's what I had in mind:
Quoted 9 lines
1) The system is asleep
2) Wakeup event occurs, one-shot policy over
3) Go all the way to user mode
4) A second wakeup interrupt occurs (say the modem rings)
5) The modem driver does not enable any suspend blockers
6) The modem driver queues an input event for userspace
7) The userspace handler invoked during 3) finishes and re-enables the one-shot policy
8) No suspend blockers are enabled, so the system goes to sleep
In my sequence above I had the modem driver "magically" knowing to fail this suspend attempt. (that "magic" wasn't fully thought out though.)
Quoted 7 lines
9) The userspace handler for the input event in 6) doesn't get to run
Quoted 2 lines
So the real problem grabbing blockers from ISR's trying to solve is to reduce the window of time where a
pm_suspend('mem')can be canceled.No. The real problem is how ISRs should prevent the system from suspending before the events they generate can be handled by userspace.
Thanks, I think I'm starting to get it. From this it seems that the system integrator needs to identify those wake up sources that need to be able to block a suspend, and figure out a way of acknowledging from user mode, that its now ok to allow a suspend to happen.
The rev-6 proposed way is for the integrator to implement overlapping blocker sections from ISR up to user mode for selected wake up devices (i.e. the modem)
There *has* to be a better way.
Can't we have some notification based thing that supports user mode
acks through a misc device or sysfs thing? Anything to avoid the
overlapping blocker sections.
Quoted 11 lines
Quoted 9 lines
My proposal is to;
1) change the kernel blocker api to be "cancel-one-shot-policy-enable" that can be called from the ISR's for the wake up devices before the IRQ's are disabled to cancel an in-flight suspend. I would make it 2 macros one goes in thepm_suspendcallback to return fail, and the other in the ISR to disable the one-shot-policy.2) make the policy a one shot that user mode must re-enable after each suspend attempted.
Neither of these solves the race I described.
True, you need an ack back from user mode for when its ok to allow suspend to happen. This ack is device specific and needs to be custom built per product to its wake up sources.
Quoted 40 lines
Quoted 9 lines
Would it help if I coded up the above proposal as patch to the current (rev-6) of the blocker patchset? I'm offering.
Because this part of the current design is broken, in that it demands the sprinkling of blocker critical sections from the hardware up to the user mode. Its ugly, hard to get right and if more folks would take a look at how well it worked out for the existing kernels on android.git.kernel.org/kernels/ perhaps it would get more attention.
I agree, it is ugly and probably hard to get right. But something like it is necessary to solve this race.
Quoted 10 lines
Finally, as an aside, lets look at the problem with the posted rev-6 patches:
1) enable suspend blocker policy
2) release user-mode blocker
3) start suspend
4) get a modem interrupt (incoming call)
5) ooops, IRQ came in afterpm_suspend('mem')turned off interrupts. bummer for you, thats life with this design. Better hope your modem hardware is modified to keep pulling on that wake up line because you're past the point of no return now and going to suspend.That is not a problem for level-sensitive IRQs. If interrupts have been turned off then the modem will not receive any commands telling it to stop requesting an interrupt. So the IRQ line will remain active until the system goes to sleep, at which point it will immediately wake up the system.
For edge-sensitive interrupts the situation isn't as simple. The low-level IRQ code must handle this somehow.
Quoted 6 lines
Grabbing a blocker in the ISR doesn't solve this. So your hardware needs to have a persistent wake up trigger that is robust against this scenario. And, if you have such hardware then why are we killing ourselves to maximize the window of time between
pm_suspend('mem')and platform suspend where you can cancel the suspend? The hardware will simply wake up anyway.
Quoted 3 lines
That's not what we are killing ourselves for. The point of suspend blockers is not to prevent races with the hardware. It is to prevent userspace from being frozen while there's still work to be done.
ok.
I'm going to think on this some more. There must be a cleaner way to do this.
--mgross
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Alan SternQuoted 72 lines · Alan Stern
Quoted 25 lines · mark gross
Quoted 16 lines · Alan Stern
Quoted 10 lines · mark gross
You know things would be so much easier if the policy was a one-shot styled thing. i.e. when enabled it does what it does, but upon resume the policy must be re-enabled by user mode to get the opportunistic behavior. That way we don't need to grab the suspend blocker from the wake up irq handler all the way up to user mode as the example below calls out. I suppose doing this would put a burden on the user mode code to keep track of if it has no pending blockers registered after a wake up from the suspend. but that seems nicer to me than sprinkling overlapping blocker critical sections from the mettle up to user mode.
Quoted 3 lines
Please consider making the policy a one shot API that needs to be re-enabled after resume by user mode. That would remove my issue with the design.
Quoted 7 lines
This won't work right if a second IRQ arrives while the first is being processed. Suppose the kernel driver for the second IRQ doesn't activate a suspend blocker, and suppose all the userspace handlers for the first IRQ end (and the opportunistic policy is re-enabled) before the userspace handler for the second IRQ can start. Then the system will go back to sleep before userspace can handle the second IRQ.
Quoted 4 lines
What? If the suspend blocker API was a one shot styled api, after the suspend, the one shot is over and the behavior is that you do not fall back into suspend again until user mode re-enables the one-shot behavior.
I was referring to your sentence: "That way we don't need to grab the suspend blocker from the wake up irq handler all the way up to user mode..." The problem arises when kernel handlers don't do _something_ to prevent another suspend from occurring too soon.
Quoted 8 lines
With what I am proposing the next suspend would not happen until the user mode code re-enables the suspend blocking behavior. It would much cleaner for everyone and I see zero down side WRT the example you just posted.
If user mode triggers a suspend by releasing the last blocker, you have until
pm_suspend('mem')turns off interrupts to cancel it. That race will never go away.(Actually the kernel can cancel the suspend even after interrupts are turned off, if it has a reason to do so.)
In theory the race between interrupts and suspend don't need to be a problem. In practice it still is -- the PM core needs a few changes to allow wakeup interrupts to cancel a suspend in progress. Regardless, that's not what I was talking about.
Quoted 7 lines
Let me think this through, please check that I'm understanding the issue please:
1) one-shot policy enable blocker PM suspend behavior;
2) release last blocker and callpm_suspend('mem')and suspend all the way down.
3) get wake up event, one-shot policy over, no-blockers in list
4) go all the way to user mode,Quoted 8 lines
5) user mode decides to not grab a blocker, and re-enables one-shot policy
6)pm_suspend('mem')called
7) interrupt comes in (say the modem rings)
8) modem driver handler needs to returns fail frompm_suspendcall back, device resumes (I am proposing changing the posted api for doing this.)
9) user mode figures out one-shot needs to be re-enabled and it grabs a blocker to handle the call and re-enables the one-shot.This is not the scenario I was describing. Here's what I had in mind:
Quoted 9 lines
1) The system is asleep
2) Wakeup event occurs, one-shot policy over
3) Go all the way to user mode
4) A second wakeup interrupt occurs (say the modem rings)
5) The modem driver does not enable any suspend blockers
6) The modem driver queues an input event for userspace
7) The userspace handler invoked during 3) finishes and re-enables the one-shot policy
8) No suspend blockers are enabled, so the system goes to sleep
In my sequence above I had the modem driver "magically" knowing to fail this suspend attempt. (that "magic" wasn't fully thought out though.)
Quoted 7 lines
9) The userspace handler for the input event in 6) doesn't get to run
Quoted 2 lines
So the real problem grabbing blockers from ISR's trying to solve is to reduce the window of time where a
pm_suspend('mem')can be canceled.No. The real problem is how ISRs should prevent the system from suspending before the events they generate can be handled by userspace.
Thanks, I think I'm starting to get it. From this it seems that the system integrator needs to identify those wake up sources that need to be able to block a suspend, and figure out a way of acknowledging from user mode, that its now ok to allow a suspend to happen.
The rev-6 proposed way is for the integrator to implement overlapping blocker sections from ISR up to user mode for selected wake up devices (i.e. the modem)
There *has* to be a better way.
Can't we have some notification based thing that supports user mode
acks through a misc device or sysfs thing? Anything to avoid the
overlapping blocker sections.
Quoted 11 lines
Quoted 9 lines
My proposal is to;
1) change the kernel blocker api to be "cancel-one-shot-policy-enable" that can be called from the ISR's for the wake up devices before the IRQ's are disabled to cancel an in-flight suspend. I would make it 2 macros one goes in thepm_suspendcallback to return fail, and the other in the ISR to disable the one-shot-policy.2) make the policy a one shot that user mode must re-enable after each suspend attempted.
Neither of these solves the race I described.
True, you need an ack back from user mode for when its ok to allow suspend to happen. This ack is device specific and needs to be custom built per product to its wake up sources.
Quoted 40 lines
Quoted 9 lines
Would it help if I coded up the above proposal as patch to the current (rev-6) of the blocker patchset? I'm offering.
Because this part of the current design is broken, in that it demands the sprinkling of blocker critical sections from the hardware up to the user mode. Its ugly, hard to get right and if more folks would take a look at how well it worked out for the existing kernels on android.git.kernel.org/kernels/ perhaps it would get more attention.
I agree, it is ugly and probably hard to get right. But something like it is necessary to solve this race.
Quoted 10 lines
Finally, as an aside, lets look at the problem with the posted rev-6 patches:
1) enable suspend blocker policy
2) release user-mode blocker
3) start suspend
4) get a modem interrupt (incoming call)
5) ooops, IRQ came in afterpm_suspend('mem')turned off interrupts. bummer for you, thats life with this design. Better hope your modem hardware is modified to keep pulling on that wake up line because you're past the point of no return now and going to suspend.That is not a problem for level-sensitive IRQs. If interrupts have been turned off then the modem will not receive any commands telling it to stop requesting an interrupt. So the IRQ line will remain active until the system goes to sleep, at which point it will immediately wake up the system.
For edge-sensitive interrupts the situation isn't as simple. The low-level IRQ code must handle this somehow.
Quoted 6 lines
Grabbing a blocker in the ISR doesn't solve this. So your hardware needs to have a persistent wake up trigger that is robust against this scenario. And, if you have such hardware then why are we killing ourselves to maximize the window of time between
pm_suspend('mem')and platform suspend where you can cancel the suspend? The hardware will simply wake up anyway.
Quoted 3 lines
That's not what we are killing ourselves for. The point of suspend blockers is not to prevent races with the hardware. It is to prevent userspace from being frozen while there's still work to be done.
ok.
I'm going to think on this some more. There must be a cleaner way to do this.
--mgross
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 2 lines · mark gross
In my sequence above I had the modem driver "magically" knowing to fail this suspend attempt. (that "magic" wasn't fully thought out though.)
If the modem driver knows to "magically" fail a suspend attempt until it knows that userspace has consumed the event, you have something that looks awfully like suspend blockers.
Quoted 1 line
There *has* to be a better way.
But nobody has reasonably proposed one and demonstrated that it works. We've had over a year to do so and failed, and I think it's pretty unreasonable to ask Google to attempt to rearchitect based on a hypothetical.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to mark grossQuoted 2 lines · mark gross
In my sequence above I had the modem driver "magically" knowing to fail this suspend attempt. (that "magic" wasn't fully thought out though.)
If the modem driver knows to "magically" fail a suspend attempt until it knows that userspace has consumed the event, you have something that looks awfully like suspend blockers.
Quoted 1 line
There *has* to be a better way.
But nobody has reasonably proposed one and demonstrated that it works. We've had over a year to do so and failed, and I think it's pretty unreasonable to ask Google to attempt to rearchitect based on a hypothetical.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 9 lines · Matthew Garrett
Quoted 2 lines · mark gross
In my sequence above I had the modem driver "magically" knowing to fail this suspend attempt. (that "magic" wasn't fully thought out though.)
If the modem driver knows to "magically" fail a suspend attempt until it knows that userspace has consumed the event, you have something that looks awfully like suspend blockers.
Quoted 7 lines
Quoted 1 line
There *has* to be a better way.
But nobody has reasonably proposed one and demonstrated that it works. We've had over a year to do so and failed, and I think it's pretty unreasonable to ask Google to attempt to rearchitect based on a hypothetical.
These are not new issues being raised. They've had over a year to address them, and all thats really happened was some sed script changes from wake_lock to suspend_blocker. Nothing is really different here.
Rearchitecting out of tree code is as silly thing for you to expect from a community member.
sigh, lets stop wasting time and just merge it then.
I'm finished with this thread until I do some rearchecting and post something that looks better to me. I'll look for this stuff in 2.6.34 or 35.
--mgross
ps It think the name suspend blocker is worse than wake-lock. I'd change it back.
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Matthew GarrettQuoted 9 lines · Matthew Garrett
Quoted 2 lines · mark gross
In my sequence above I had the modem driver "magically" knowing to fail this suspend attempt. (that "magic" wasn't fully thought out though.)
If the modem driver knows to "magically" fail a suspend attempt until it knows that userspace has consumed the event, you have something that looks awfully like suspend blockers.
Quoted 7 lines
Quoted 1 line
There *has* to be a better way.
But nobody has reasonably proposed one and demonstrated that it works. We've had over a year to do so and failed, and I think it's pretty unreasonable to ask Google to attempt to rearchitect based on a hypothetical.
These are not new issues being raised. They've had over a year to address them, and all thats really happened was some sed script changes from wake_lock to suspend_blocker. Nothing is really different here.
Rearchitecting out of tree code is as silly thing for you to expect from a community member.
sigh, lets stop wasting time and just merge it then.
I'm finished with this thread until I do some rearchecting and post something that looks better to me. I'll look for this stuff in 2.6.34 or 35.
--mgross
ps It think the name suspend blocker is worse than wake-lock. I'd change it back.
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 11 lines · mark gross
Quoted 5 lines · Matthew Garrett
But nobody has reasonably proposed one and demonstrated that it works. We've had over a year to do so and failed, and I think it's pretty unreasonable to ask Google to attempt to rearchitect based on a hypothetical.
These are not new issues being raised. They've had over a year to address them, and all thats really happened was some sed script changes from
wake_locktosuspend_blocker. Nothing is really different here.
Our issues haven't been addressed because we've given no indication as to how they can be addressed. For better or worse, our runtime powermanagement story isn't sufficient to satisfy Google's usecases. That would be fine, if we could tell them what changes needed to be made to satisfy their usecases. The Android people have said that they don't see a cleaner way of doing this. Are we seriously saying that they should prove themselves wrong, and if they can't they don't get their code in the kernel? This seems... problematic.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to mark grossQuoted 11 lines · mark gross
Quoted 5 lines · Matthew Garrett
But nobody has reasonably proposed one and demonstrated that it works. We've had over a year to do so and failed, and I think it's pretty unreasonable to ask Google to attempt to rearchitect based on a hypothetical.
These are not new issues being raised. They've had over a year to address them, and all thats really happened was some sed script changes from
wake_locktosuspend_blocker. Nothing is really different here.
Our issues haven't been addressed because we've given no indication as to how they can be addressed. For better or worse, our runtime powermanagement story isn't sufficient to satisfy Google's usecases. That would be fine, if we could tell them what changes needed to be made to satisfy their usecases. The Android people have said that they don't see a cleaner way of doing this. Are we seriously saying that they should prove themselves wrong, and if they can't they don't get their code in the kernel? This seems... problematic.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
In reply to mark grossQuoted 4 lines · mark gross
Thanks, I think I'm starting to get it. From this it seems that the system integrator needs to identify those wake up sources that need to be able to block a suspend, and figure out a way of acknowledging from user mode, that its now ok to allow a suspend to happen.
The second part is easy. Userspace doesn't need to do anything special to acknowledge that a suspend is now okay; it just has to remove the conditions that led the driver to block suspends in the first place.
For example, if suspends are blocked because some input event has been queued, emptying the input event queue should unblock suspends.
Quoted 5 lines
The rev-6 proposed way is for the integrator to implement overlapping blocker sections from ISR up to user mode for selected wake up devices (i.e. the modem)
There *has* to be a better way.
Why? What's wrong with overlapping blockers? It's a very common idiom. For example, the same sort of thing is used when locking subtrees of a tree: You lock the root node, and then use overlapping locks on the nodes leading down to the subtree you're interested in.
Quoted 3 lines
Can't we have some notification based thing that supports user mode
acks through a misc device or sysfs thing? Anything to avoid the
overlapping blocker sections.
Userspace acks aren't the issue; the issue is how (and when) kernel drivers should initiate a blocker. Switching to notifications, misc devices, or sysfs won't help solve this issue.
Quoted 3 lines
True, you need an ack back from user mode for when its ok to allow suspend to happen. This ack is device specific and needs to be custom built per product to its wake up sources.
No and no. Nothing special is needed. All userspace needs to do is remove the condition that led to the blocker being enabled initially -- which is exactly what userspace would do normally anyway.
Alan Stern
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to mark grossQuoted 4 lines · mark gross
Thanks, I think I'm starting to get it. From this it seems that the system integrator needs to identify those wake up sources that need to be able to block a suspend, and figure out a way of acknowledging from user mode, that its now ok to allow a suspend to happen.
The second part is easy. Userspace doesn't need to do anything special to acknowledge that a suspend is now okay; it just has to remove the conditions that led the driver to block suspends in the first place.
For example, if suspends are blocked because some input event has been queued, emptying the input event queue should unblock suspends.
Quoted 5 lines
The rev-6 proposed way is for the integrator to implement overlapping blocker sections from ISR up to user mode for selected wake up devices (i.e. the modem)
There *has* to be a better way.
Why? What's wrong with overlapping blockers? It's a very common idiom. For example, the same sort of thing is used when locking subtrees of a tree: You lock the root node, and then use overlapping locks on the nodes leading down to the subtree you're interested in.
Quoted 3 lines
Can't we have some notification based thing that supports user mode
acks through a misc device or sysfs thing? Anything to avoid the
overlapping blocker sections.
Userspace acks aren't the issue; the issue is how (and when) kernel drivers should initiate a blocker. Switching to notifications, misc devices, or sysfs won't help solve this issue.
Quoted 3 lines
True, you need an ack back from user mode for when its ok to allow suspend to happen. This ack is device specific and needs to be custom built per product to its wake up sources.
No and no. Nothing special is needed. All userspace needs to do is remove the condition that led to the blocker being enabled initially -- which is exactly what userspace would do normally anyway.
Alan Stern
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 18 lines · Alan Stern
Quoted 4 lines · mark gross
Thanks, I think I'm starting to get it. From this it seems that the system integrator needs to identify those wake up sources that need to be able to block a suspend, and figure out a way of acknowledging from user mode, that its now ok to allow a suspend to happen.
The second part is easy. Userspace doesn't need to do anything special to acknowledge that a suspend is now okay; it just has to remove the conditions that led the driver to block suspends in the first place.
For example, if suspends are blocked because some input event has been queued, emptying the input event queue should unblock suspends.
Quoted 4 lines
The rev-6 proposed way is for the integrator to implement overlapping blocker sections from ISR up to user mode for selected wake up devices (i.e. the modem)
Quoted 6 lines
Quoted 1 line
There *has* to be a better way.
Why? What's wrong with overlapping blockers? It's a very common idiom. For example, the same sort of thing is used when locking subtrees of a tree: You lock the root node, and then use overlapping locks on the nodes leading down to the subtree you're interested in.
Because in the kenel there is only a partial ordering of calling sequences from IRQ to usermode. I see a lot of custom out of tree code being developed to deal with getting the overlapping blocker sections right, per device.
Quoted 7 lines
Quoted 3 lines
Can't we have some notification based thing that supports user mode
acks through a misc device or sysfs thing? Anything to avoid the
overlapping blocker sections.Userspace acks aren't the issue; the issue is how (and when) kernel drivers should initiate a blocker. Switching to notifications, misc devices, or sysfs won't help solve this issue.
communicating non-local knowledge back down to the blocking object to tell it that it can unblock is the issue
Quoted 7 lines
Quoted 3 lines
True, you need an ack back from user mode for when its ok to allow suspend to happen. This ack is device specific and needs to be custom built per product to its wake up sources.
No and no. Nothing special is needed. All userspace needs to do is remove the condition that led to the blocker being enabled initially -- which is exactly what userspace would do normally anyway.
Oh, like tell the modem that user mode has handled the ring event and its ok to un-block?
--mgross
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Alan SternQuoted 18 lines · Alan Stern
Quoted 4 lines · mark gross
Thanks, I think I'm starting to get it. From this it seems that the system integrator needs to identify those wake up sources that need to be able to block a suspend, and figure out a way of acknowledging from user mode, that its now ok to allow a suspend to happen.
The second part is easy. Userspace doesn't need to do anything special to acknowledge that a suspend is now okay; it just has to remove the conditions that led the driver to block suspends in the first place.
For example, if suspends are blocked because some input event has been queued, emptying the input event queue should unblock suspends.
Quoted 4 lines
The rev-6 proposed way is for the integrator to implement overlapping blocker sections from ISR up to user mode for selected wake up devices (i.e. the modem)
Quoted 6 lines
Quoted 1 line
There *has* to be a better way.
Why? What's wrong with overlapping blockers? It's a very common idiom. For example, the same sort of thing is used when locking subtrees of a tree: You lock the root node, and then use overlapping locks on the nodes leading down to the subtree you're interested in.
Because in the kenel there is only a partial ordering of calling sequences from IRQ to usermode. I see a lot of custom out of tree code being developed to deal with getting the overlapping blocker sections right, per device.
Quoted 7 lines
Quoted 3 lines
Can't we have some notification based thing that supports user mode
acks through a misc device or sysfs thing? Anything to avoid the
overlapping blocker sections.Userspace acks aren't the issue; the issue is how (and when) kernel drivers should initiate a blocker. Switching to notifications, misc devices, or sysfs won't help solve this issue.
communicating non-local knowledge back down to the blocking object to tell it that it can unblock is the issue
Quoted 7 lines
Quoted 3 lines
True, you need an ack back from user mode for when its ok to allow suspend to happen. This ack is device specific and needs to be custom built per product to its wake up sources.
No and no. Nothing special is needed. All userspace needs to do is remove the condition that led to the blocker being enabled initially -- which is exactly what userspace would do normally anyway.
Oh, like tell the modem that user mode has handled the ring event and its ok to un-block?
--mgross
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 10 lines · mark gross
Quoted 7 lines
Quoted 3 lines
True, you need an ack back from user mode for when its ok to allow suspend to happen. This ack is device specific and needs to be custom built per product to its wake up sources.
No and no. Nothing special is needed. All userspace needs to do is remove the condition that led to the blocker being enabled initially -- which is exactly what userspace would do normally anyway.
Oh, like tell the modem that user mode has handled the ring event and its ok to un-block?
No, that's not how it works. It would go like this:
The modem IRQ handler queues its event to the input subsystem. As it does so the input subsystem enables a suspend blocker, causing the system to stay awake after the IRQ is done.
The user program enables its own suspend blocker before reading the input queue. When the queue is empty, the input subsystem releases its suspend blocker.
When the user program finishes processing the event, it releases its suspend blocker. Now the system can go back to sleep.
At no point does the user program have to communicate anything to the modem driver, and at no point does it have to do anything out of the ordinary except to enable and disable a suspend blocker.
Alan Stern
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to mark grossQuoted 10 lines · mark gross
Quoted 7 lines
Quoted 3 lines
True, you need an ack back from user mode for when its ok to allow suspend to happen. This ack is device specific and needs to be custom built per product to its wake up sources.
No and no. Nothing special is needed. All userspace needs to do is remove the condition that led to the blocker being enabled initially -- which is exactly what userspace would do normally anyway.
Oh, like tell the modem that user mode has handled the ring event and its ok to un-block?
No, that's not how it works. It would go like this:
The modem IRQ handler queues its event to the input subsystem. As it does so the input subsystem enables a suspend blocker, causing the system to stay awake after the IRQ is done.
The user program enables its own suspend blocker before reading the input queue. When the queue is empty, the input subsystem releases its suspend blocker.
When the user program finishes processing the event, it releases its suspend blocker. Now the system can go back to sleep.
At no point does the user program have to communicate anything to the modem driver, and at no point does it have to do anything out of the ordinary except to enable and disable a suspend blocker.
Alan Stern
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 14 lines · Alan Stern
Quoted 3 lines
Oh, like tell the modem that user mode has handled the ring event and its ok to un-block?
No, that's not how it works. It would go like this:
The modem IRQ handler queues its event to the input subsystem. As it does so the input subsystem enables a suspend blocker, causing the system to stay awake after the IRQ is done.
The user program enables its own suspend blocker before reading the input queue. When the queue is empty, the input subsystem releases its suspend blocker.
Quoted 7 lines
When the user program finishes processing the event, it releases its suspend blocker. Now the system can go back to sleep.
At no point does the user program have to communicate anything to the modem driver, and at no point does it have to do anything out of the ordinary except to enable and disable a suspend blocker.
Exactly -- and you can use the same style of overlapping suspend blockers with other drivers than input, if the input interface is not suitable for the particular interaction.
Brian
_______________________________________________
linux-pm mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/linux-pm
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Alan SternQuoted 14 lines · Alan Stern
Quoted 3 lines
Oh, like tell the modem that user mode has handled the ring event and its ok to un-block?
No, that's not how it works. It would go like this:
The modem IRQ handler queues its event to the input subsystem. As it does so the input subsystem enables a suspend blocker, causing the system to stay awake after the IRQ is done.
The user program enables its own suspend blocker before reading the input queue. When the queue is empty, the input subsystem releases its suspend blocker.
Quoted 7 lines
When the user program finishes processing the event, it releases its suspend blocker. Now the system can go back to sleep.
At no point does the user program have to communicate anything to the modem driver, and at no point does it have to do anything out of the ordinary except to enable and disable a suspend blocker.
Exactly -- and you can use the same style of overlapping suspend blockers with other drivers than input, if the input interface is not suitable for the particular interaction.
Brian
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 10 lines · Brian Swetland
Quoted 9 lines · Alan Stern
Quoted 3 lines
Oh, like tell the modem that user mode has handled the ring event and its ok to un-block?
No, that's not how it works. It would go like this:
The modem IRQ handler queues its event to the input subsystem. As it does so the input subsystem enables a suspend blocker, causing the system to stay awake after the IRQ is done.
How about instead the modem driver fails to suspend until it's done?
Each driver could have a suspend_policy sysfs entry with options such as [ forced | safe ]. The default would be forced. Forced would be the current behaviour, while safe would refuse suspend until the driver is done processing.
Quoted 3 lines
Quoted 3 lines
The user program enables its own suspend blocker before reading the input queue. When the queue is empty, the input subsystem releases its suspend blocker.
And also the input layer could refuse to suspend until it's done.
Quoted 3 lines
Quoted 3 lines
When the user program finishes processing the event, it releases its suspend blocker. Now the system can go back to sleep.
And here the user space just tries to suspend again when it's done? It's not like you're trying to suspend all the time, so it should be OK to retry a few times.
Quoted 7 lines
Quoted 3 lines
At no point does the user program have to communicate anything to the modem driver, and at no point does it have to do anything out of the ordinary except to enable and disable a suspend blocker.
Exactly -- and you can use the same style of overlapping suspend blockers with other drivers than input, if the input interface is not suitable for the particular interaction.
Would the suspend blockers still be needed somewhere in the example above?
Regards,
Tony
_______________________________________________
linux-pm mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/linux-pm
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Brian SwetlandQuoted 10 lines · Brian Swetland
Quoted 9 lines · Alan Stern
Quoted 3 lines
Oh, like tell the modem that user mode has handled the ring event and its ok to un-block?
No, that's not how it works. It would go like this:
The modem IRQ handler queues its event to the input subsystem. As it does so the input subsystem enables a suspend blocker, causing the system to stay awake after the IRQ is done.
How about instead the modem driver fails to suspend until it's done?
Each driver could have a suspend_policy sysfs entry with options such as [ forced | safe ]. The default would be forced. Forced would be the current behaviour, while safe would refuse suspend until the driver is done processing.
Quoted 3 lines
Quoted 3 lines
The user program enables its own suspend blocker before reading the input queue. When the queue is empty, the input subsystem releases its suspend blocker.
And also the input layer could refuse to suspend until it's done.
Quoted 3 lines
Quoted 3 lines
When the user program finishes processing the event, it releases its suspend blocker. Now the system can go back to sleep.
And here the user space just tries to suspend again when it's done? It's not like you're trying to suspend all the time, so it should be OK to retry a few times.
Quoted 7 lines
Quoted 3 lines
At no point does the user program have to communicate anything to the modem driver, and at no point does it have to do anything out of the ordinary except to enable and disable a suspend blocker.
Exactly -- and you can use the same style of overlapping suspend blockers with other drivers than input, if the input interface is not suitable for the particular interaction.
Would the suspend blockers still be needed somewhere in the example above?
Regards,
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 25 lines · Tony Lindgren
Quoted 10 lines · Brian Swetland
Quoted 9 lines · Alan Stern
Quoted 3 lines
Oh, like tell the modem that user mode has handled the ring event and its ok to un-block?
No, that's not how it works. It would go like this:
The modem IRQ handler queues its event to the input subsystem. As it does so the input subsystem enables a suspend blocker, causing the system to stay awake after the IRQ is done.
How about instead the modem driver fails to suspend until it's done?
Each driver could have a
suspend_policysysfs entry with options such as [ forced | safe ]. The default would be forced. Forced would be the current behaviour, while safe would refuse suspend until the driver is done processing.Quoted 3 lines
Quoted 3 lines
The user program enables its own suspend blocker before reading the input queue. When the queue is empty, the input subsystem releases its suspend blocker.
And also the input layer could refuse to suspend until it's done.
Quoted 7 lines
Quoted 3 lines
Quoted 3 lines
When the user program finishes processing the event, it releases its suspend blocker. Now the system can go back to sleep.
And here the user space just tries to suspend again when it's done? It's not like you're trying to suspend all the time, so it should be OK to retry a few times.
We actually are trying to suspend all the time -- that's our basic model -- suspend whenever we can when something doesn't prevent it.
Quoted 10 lines
Quoted 7 lines
Quoted 3 lines
At no point does the user program have to communicate anything to the modem driver, and at no point does it have to do anything out of the ordinary except to enable and disable a suspend blocker.
Exactly -- and you can use the same style of overlapping suspend blockers with other drivers than input, if the input interface is not suitable for the particular interaction.
Would the suspend blockers still be needed somewhere in the example above?
How often would we retry suspending?
If we fail to suspend, don't we have to resume all the drivers that suspended before the one that failed? (Maybe I'm mistaken here)
With the suspend block model we know the moment we're capable of suspending and then can suspend at that moment. Continually trying to suspend seems like it'd be inefficient power-wise (we're going to be doing a lot more work as we try to suspend over and over, or we're going to retry after a timeout and spend extra time not suspended).
We can often spend minutes (possibly many) at a time preventing suspend when the system is doing work that would be interrupted by a full suspend.
Brian
_______________________________________________
linux-pm mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/linux-pm
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 25 lines · Tony Lindgren
Quoted 10 lines · Brian Swetland
Quoted 9 lines · Alan Stern
Quoted 3 lines
Oh, like tell the modem that user mode has handled the ring event and its ok to un-block?
No, that's not how it works. It would go like this:
The modem IRQ handler queues its event to the input subsystem. As it does so the input subsystem enables a suspend blocker, causing the system to stay awake after the IRQ is done.
How about instead the modem driver fails to suspend until it's done?
Each driver could have a
suspend_policysysfs entry with options such as [ forced | safe ]. The default would be forced. Forced would be the current behaviour, while safe would refuse suspend until the driver is done processing.Quoted 3 lines
Quoted 3 lines
The user program enables its own suspend blocker before reading the input queue. When the queue is empty, the input subsystem releases its suspend blocker.
And also the input layer could refuse to suspend until it's done.
Quoted 7 lines
Quoted 3 lines
Quoted 3 lines
When the user program finishes processing the event, it releases its suspend blocker. Now the system can go back to sleep.
And here the user space just tries to suspend again when it's done? It's not like you're trying to suspend all the time, so it should be OK to retry a few times.
We actually are trying to suspend all the time -- that's our basic model -- suspend whenever we can when something doesn't prevent it.
Quoted 10 lines
Quoted 7 lines
Quoted 3 lines
At no point does the user program have to communicate anything to the modem driver, and at no point does it have to do anything out of the ordinary except to enable and disable a suspend blocker.
Exactly -- and you can use the same style of overlapping suspend blockers with other drivers than input, if the input interface is not suitable for the particular interaction.
Would the suspend blockers still be needed somewhere in the example above?
How often would we retry suspending?
If we fail to suspend, don't we have to resume all the drivers that suspended before the one that failed? (Maybe I'm mistaken here)
With the suspend block model we know the moment we're capable of suspending and then can suspend at that moment. Continually trying to suspend seems like it'd be inefficient power-wise (we're going to be doing a lot more work as we try to suspend over and over, or we're going to retry after a timeout and spend extra time not suspended).
We can often spend minutes (possibly many) at a time preventing suspend when the system is doing work that would be interrupted by a full suspend.
Brian
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 30 lines · Brian Swetland
Quoted 29 lines · Tony Lindgren
Quoted 10 lines · Brian Swetland
Quoted 9 lines · Alan Stern
Quoted 3 lines
Oh, like tell the modem that user mode has handled the ring event and its ok to un-block?
No, that's not how it works. It would go like this:
The modem IRQ handler queues its event to the input subsystem. As it does so the input subsystem enables a suspend blocker, causing the system to stay awake after the IRQ is done.
How about instead the modem driver fails to suspend until it's done?
Each driver could have a
suspend_policysysfs entry with options such as [ forced | safe ]. The default would be forced. Forced would be the current behaviour, while safe would refuse suspend until the driver is done processing.Quoted 3 lines
Quoted 3 lines
The user program enables its own suspend blocker before reading the input queue. When the queue is empty, the input subsystem releases its suspend blocker.
And also the input layer could refuse to suspend until it's done.
Quoted 3 lines
Quoted 3 lines
When the user program finishes processing the event, it releases its suspend blocker. Now the system can go back to sleep.
Quoted 6 lines
Quoted 3 lines
And here the user space just tries to suspend again when it's done? It's not like you're trying to suspend all the time, so it should be OK to retry a few times.
We actually are trying to suspend all the time -- that's our basic model -- suspend whenever we can when something doesn't prevent it.
Maybe that state could be kept in some userspace suspend policy manager?
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
At no point does the user program have to communicate anything to the modem driver, and at no point does it have to do anything out of the ordinary except to enable and disable a suspend blocker.
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Exactly -- and you can use the same style of overlapping suspend blockers with other drivers than input, if the input interface is not suitable for the particular interaction.
Would the suspend blockers still be needed somewhere in the example above?
How often would we retry suspending?
Well based on some timer, the same way the screen blanks? Or five seconds of no audio play? So if the suspend fails, then reset whatever userspace suspend policy timers.
Quoted 2 lines
If we fail to suspend, don't we have to resume all the drivers that suspended before the one that failed? (Maybe I'm mistaken here)
Sure, but I guess that should be a rare event that only happens when you try to suspend and something interrupts the suspend.
Quoted 9 lines
With the suspend block model we know the moment we're capable of suspending and then can suspend at that moment. Continually trying to suspend seems like it'd be inefficient power-wise (we're going to be doing a lot more work as we try to suspend over and over, or we're going to retry after a timeout and spend extra time not suspended).
We can often spend minutes (possibly many) at a time preventing suspend when the system is doing work that would be interrupted by a full suspend.
Maybe you a userspace suspend policy manager would do the trick if it knows when the screen is blanked and no audio has been played for five seconds etc?
Regards,
Tony
_______________________________________________
linux-pm mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/linux-pm
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Brian SwetlandQuoted 30 lines · Brian Swetland
Quoted 29 lines · Tony Lindgren
Quoted 10 lines · Brian Swetland
Quoted 9 lines · Alan Stern
Quoted 3 lines
Oh, like tell the modem that user mode has handled the ring event and its ok to un-block?
No, that's not how it works. It would go like this:
The modem IRQ handler queues its event to the input subsystem. As it does so the input subsystem enables a suspend blocker, causing the system to stay awake after the IRQ is done.
How about instead the modem driver fails to suspend until it's done?
Each driver could have a
suspend_policysysfs entry with options such as [ forced | safe ]. The default would be forced. Forced would be the current behaviour, while safe would refuse suspend until the driver is done processing.Quoted 3 lines
Quoted 3 lines
The user program enables its own suspend blocker before reading the input queue. When the queue is empty, the input subsystem releases its suspend blocker.
And also the input layer could refuse to suspend until it's done.
Quoted 3 lines
Quoted 3 lines
When the user program finishes processing the event, it releases its suspend blocker. Now the system can go back to sleep.
Quoted 6 lines
Quoted 3 lines
And here the user space just tries to suspend again when it's done? It's not like you're trying to suspend all the time, so it should be OK to retry a few times.
We actually are trying to suspend all the time -- that's our basic model -- suspend whenever we can when something doesn't prevent it.
Maybe that state could be kept in some userspace suspend policy manager?
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
At no point does the user program have to communicate anything to the modem driver, and at no point does it have to do anything out of the ordinary except to enable and disable a suspend blocker.
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Exactly -- and you can use the same style of overlapping suspend blockers with other drivers than input, if the input interface is not suitable for the particular interaction.
Would the suspend blockers still be needed somewhere in the example above?
How often would we retry suspending?
Well based on some timer, the same way the screen blanks? Or five seconds of no audio play? So if the suspend fails, then reset whatever userspace suspend policy timers.
Quoted 2 lines
If we fail to suspend, don't we have to resume all the drivers that suspended before the one that failed? (Maybe I'm mistaken here)
Sure, but I guess that should be a rare event that only happens when you try to suspend and something interrupts the suspend.
Quoted 9 lines
With the suspend block model we know the moment we're capable of suspending and then can suspend at that moment. Continually trying to suspend seems like it'd be inefficient power-wise (we're going to be doing a lot more work as we try to suspend over and over, or we're going to retry after a timeout and spend extra time not suspended).
We can often spend minutes (possibly many) at a time preventing suspend when the system is doing work that would be interrupted by a full suspend.
Maybe you a userspace suspend policy manager would do the trick if it knows when the screen is blanked and no audio has been played for five seconds etc?
Regards,
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 57 lines · Tony Lindgren
Quoted 30 lines · Brian Swetland
Quoted 29 lines · Tony Lindgren
Quoted 10 lines · Brian Swetland
Quoted 9 lines · Alan Stern
Quoted 3 lines
Oh, like tell the modem that user mode has handled the ring event and its ok to un-block?
No, that's not how it works. It would go like this:
The modem IRQ handler queues its event to the input subsystem. As it does so the input subsystem enables a suspend blocker, causing the system to stay awake after the IRQ is done.
How about instead the modem driver fails to suspend until it's done?
Each driver could have a
suspend_policysysfs entry with options such as [ forced | safe ]. The default would be forced. Forced would be the current behaviour, while safe would refuse suspend until the driver is done processing.Quoted 3 lines
Quoted 3 lines
The user program enables its own suspend blocker before reading the input queue. When the queue is empty, the input subsystem releases its suspend blocker.
And also the input layer could refuse to suspend until it's done.
Quoted 3 lines
Quoted 3 lines
When the user program finishes processing the event, it releases its suspend blocker. Now the system can go back to sleep.
Quoted 6 lines
Quoted 3 lines
And here the user space just tries to suspend again when it's done? It's not like you're trying to suspend all the time, so it should be OK to retry a few times.
We actually are trying to suspend all the time -- that's our basic model -- suspend whenever we can when something doesn't prevent it.
Maybe that state could be kept in some userspace suspend policy manager?
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
At no point does the user program have to communicate anything to the modem driver, and at no point does it have to do anything out of the ordinary except to enable and disable a suspend blocker.
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Exactly -- and you can use the same style of overlapping suspend blockers with other drivers than input, if the input interface is not suitable for the particular interaction.
Would the suspend blockers still be needed somewhere in the example above?
How often would we retry suspending?
Well based on some timer, the same way the screen blanks? Or five seconds of no audio play? So if the suspend fails, then reset whatever userspace suspend policy timers.
Quoted 6 lines
Quoted 2 lines
If we fail to suspend, don't we have to resume all the drivers that suspended before the one that failed? (Maybe I'm mistaken here)
Sure, but I guess that should be a rare event that only happens when you try to suspend and something interrupts the suspend.
This is not a rare event. For example, the matrix keypad driver blocks suspend when a key is down so it can scan the matrix.
Quoted 6 lines
Quoted 6 lines
With the suspend block model we know the moment we're capable of suspending and then can suspend at that moment. Continually trying to suspend seems like it'd be inefficient power-wise (we're going to be doing a lot more work as we try to suspend over and over, or we're going to retry after a timeout and spend extra time not suspended).
Quoted 8 lines
Quoted 3 lines
We can often spend minutes (possibly many) at a time preventing suspend when the system is doing work that would be interrupted by a full suspend.
Maybe you a userspace suspend policy manager would do the trick if it knows when the screen is blanked and no audio has been played for five seconds etc?
If user space has to initiate every suspend attempt, then you are forcing it to poll whenever a driver needs to block suspend.
Signature · 1 line
Arve Hjønnevåg
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 57 lines · Tony Lindgren
Quoted 30 lines · Brian Swetland
Quoted 29 lines · Tony Lindgren
Quoted 10 lines · Brian Swetland
Quoted 9 lines · Alan Stern
Quoted 3 lines
Oh, like tell the modem that user mode has handled the ring event and its ok to un-block?
No, that's not how it works. It would go like this:
The modem IRQ handler queues its event to the input subsystem. As it does so the input subsystem enables a suspend blocker, causing the system to stay awake after the IRQ is done.
How about instead the modem driver fails to suspend until it's done?
Each driver could have a
suspend_policysysfs entry with options such as [ forced | safe ]. The default would be forced. Forced would be the current behaviour, while safe would refuse suspend until the driver is done processing.Quoted 3 lines
Quoted 3 lines
The user program enables its own suspend blocker before reading the input queue. When the queue is empty, the input subsystem releases its suspend blocker.
And also the input layer could refuse to suspend until it's done.
Quoted 3 lines
Quoted 3 lines
When the user program finishes processing the event, it releases its suspend blocker. Now the system can go back to sleep.
Quoted 6 lines
Quoted 3 lines
And here the user space just tries to suspend again when it's done? It's not like you're trying to suspend all the time, so it should be OK to retry a few times.
We actually are trying to suspend all the time -- that's our basic model -- suspend whenever we can when something doesn't prevent it.
Maybe that state could be kept in some userspace suspend policy manager?
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
At no point does the user program have to communicate anything to the modem driver, and at no point does it have to do anything out of the ordinary except to enable and disable a suspend blocker.
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Exactly -- and you can use the same style of overlapping suspend blockers with other drivers than input, if the input interface is not suitable for the particular interaction.
Would the suspend blockers still be needed somewhere in the example above?
How often would we retry suspending?
Well based on some timer, the same way the screen blanks? Or five seconds of no audio play? So if the suspend fails, then reset whatever userspace suspend policy timers.
Quoted 6 lines
Quoted 2 lines
If we fail to suspend, don't we have to resume all the drivers that suspended before the one that failed? (Maybe I'm mistaken here)
Sure, but I guess that should be a rare event that only happens when you try to suspend and something interrupts the suspend.
This is not a rare event. For example, the matrix keypad driver blocks suspend when a key is down so it can scan the matrix.
Quoted 6 lines
Quoted 6 lines
With the suspend block model we know the moment we're capable of suspending and then can suspend at that moment. Continually trying to suspend seems like it'd be inefficient power-wise (we're going to be doing a lot more work as we try to suspend over and over, or we're going to retry after a timeout and spend extra time not suspended).
Quoted 8 lines
Quoted 3 lines
We can often spend minutes (possibly many) at a time preventing suspend when the system is doing work that would be interrupted by a full suspend.
Maybe you a userspace suspend policy manager would do the trick if it knows when the screen is blanked and no audio has been played for five seconds etc?
If user space has to initiate every suspend attempt, then you are forcing it to poll whenever a driver needs to block suspend.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 61 lines · Arve Hjønnevåg
Quoted 60 lines · Tony Lindgren
Quoted 30 lines · Brian Swetland
Quoted 29 lines · Tony Lindgren
Quoted 10 lines · Brian Swetland
Quoted 9 lines · Alan Stern
Quoted 3 lines
Oh, like tell the modem that user mode has handled the ring event and its ok to un-block?
No, that's not how it works. It would go like this:
The modem IRQ handler queues its event to the input subsystem. As it does so the input subsystem enables a suspend blocker, causing the system to stay awake after the IRQ is done.
How about instead the modem driver fails to suspend until it's done?
Each driver could have a
suspend_policysysfs entry with options such as [ forced | safe ]. The default would be forced. Forced would be the current behaviour, while safe would refuse suspend until the driver is done processing.Quoted 3 lines
Quoted 3 lines
The user program enables its own suspend blocker before reading the input queue. When the queue is empty, the input subsystem releases its suspend blocker.
And also the input layer could refuse to suspend until it's done.
Quoted 3 lines
Quoted 3 lines
When the user program finishes processing the event, it releases its suspend blocker. Now the system can go back to sleep.
Quoted 6 lines
Quoted 3 lines
And here the user space just tries to suspend again when it's done? It's not like you're trying to suspend all the time, so it should be OK to retry a few times.
We actually are trying to suspend all the time -- that's our basic model -- suspend whenever we can when something doesn't prevent it.
Maybe that state could be kept in some userspace suspend policy manager?
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
At no point does the user program have to communicate anything to the modem driver, and at no point does it have to do anything out of the ordinary except to enable and disable a suspend blocker.
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Exactly -- and you can use the same style of overlapping suspend blockers with other drivers than input, if the input interface is not suitable for the particular interaction.
Would the suspend blockers still be needed somewhere in the example above?
How often would we retry suspending?
Well based on some timer, the same way the screen blanks? Or five seconds of no audio play? So if the suspend fails, then reset whatever userspace suspend policy timers.
Quoted 2 lines
If we fail to suspend, don't we have to resume all the drivers that suspended before the one that failed? (Maybe I'm mistaken here)
Quoted 6 lines
Quoted 3 lines
Sure, but I guess that should be a rare event that only happens when you try to suspend and something interrupts the suspend.
This is not a rare event. For example, the matrix keypad driver blocks suspend when a key is down so it can scan the matrix.
Sure, but how many times per day are you suspending?
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
With the suspend block model we know the moment we're capable of suspending and then can suspend at that moment. Continually trying to suspend seems like it'd be inefficient power-wise (we're going to be doing a lot more work as we try to suspend over and over, or we're going to retry after a timeout and spend extra time not suspended).
We can often spend minutes (possibly many) at a time preventing suspend when the system is doing work that would be interrupted by a full suspend.
Quoted 7 lines
Quoted 4 lines
Maybe you a userspace suspend policy manager would do the trick if it knows when the screen is blanked and no audio has been played for five seconds etc?
If user space has to initiate every suspend attempt, then you are forcing it to poll whenever a driver needs to block suspend.
Hmm I don't follow you. If the userspace policy daemon timer times out, the device suspends. If the device does not suspend because of a blocking driver, then the timers get reset and you try again based on some event such as when the screen blanks.
Regards,
Tony
_______________________________________________
linux-pm mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/linux-pm
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Arve HjønnevågQuoted 61 lines · Arve Hjønnevåg
Quoted 60 lines · Tony Lindgren
Quoted 30 lines · Brian Swetland
Quoted 29 lines · Tony Lindgren
Quoted 10 lines · Brian Swetland
Quoted 9 lines · Alan Stern
Quoted 3 lines
Oh, like tell the modem that user mode has handled the ring event and its ok to un-block?
No, that's not how it works. It would go like this:
The modem IRQ handler queues its event to the input subsystem. As it does so the input subsystem enables a suspend blocker, causing the system to stay awake after the IRQ is done.
How about instead the modem driver fails to suspend until it's done?
Each driver could have a
suspend_policysysfs entry with options such as [ forced | safe ]. The default would be forced. Forced would be the current behaviour, while safe would refuse suspend until the driver is done processing.Quoted 3 lines
Quoted 3 lines
The user program enables its own suspend blocker before reading the input queue. When the queue is empty, the input subsystem releases its suspend blocker.
And also the input layer could refuse to suspend until it's done.
Quoted 3 lines
Quoted 3 lines
When the user program finishes processing the event, it releases its suspend blocker. Now the system can go back to sleep.
Quoted 6 lines
Quoted 3 lines
And here the user space just tries to suspend again when it's done? It's not like you're trying to suspend all the time, so it should be OK to retry a few times.
We actually are trying to suspend all the time -- that's our basic model -- suspend whenever we can when something doesn't prevent it.
Maybe that state could be kept in some userspace suspend policy manager?
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
At no point does the user program have to communicate anything to the modem driver, and at no point does it have to do anything out of the ordinary except to enable and disable a suspend blocker.
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Exactly -- and you can use the same style of overlapping suspend blockers with other drivers than input, if the input interface is not suitable for the particular interaction.
Would the suspend blockers still be needed somewhere in the example above?
How often would we retry suspending?
Well based on some timer, the same way the screen blanks? Or five seconds of no audio play? So if the suspend fails, then reset whatever userspace suspend policy timers.
Quoted 2 lines
If we fail to suspend, don't we have to resume all the drivers that suspended before the one that failed? (Maybe I'm mistaken here)
Quoted 6 lines
Quoted 3 lines
Sure, but I guess that should be a rare event that only happens when you try to suspend and something interrupts the suspend.
This is not a rare event. For example, the matrix keypad driver blocks suspend when a key is down so it can scan the matrix.
Sure, but how many times per day are you suspending?
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
With the suspend block model we know the moment we're capable of suspending and then can suspend at that moment. Continually trying to suspend seems like it'd be inefficient power-wise (we're going to be doing a lot more work as we try to suspend over and over, or we're going to retry after a timeout and spend extra time not suspended).
We can often spend minutes (possibly many) at a time preventing suspend when the system is doing work that would be interrupted by a full suspend.
Quoted 7 lines
Quoted 4 lines
Maybe you a userspace suspend policy manager would do the trick if it knows when the screen is blanked and no audio has been played for five seconds etc?
If user space has to initiate every suspend attempt, then you are forcing it to poll whenever a driver needs to block suspend.
Hmm I don't follow you. If the userspace policy daemon timer times out, the device suspends. If the device does not suspend because of a blocking driver, then the timers get reset and you try again based on some event such as when the screen blanks.
Regards,
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
2010/5/6 Tony Lindgren <[email protected]>:
Quoted 62 lines · Arve Hjønnevåg
Quoted 61 lines · Tony Lindgren
Quoted 60 lines · Brian Swetland
Quoted 30 lines · Tony Lindgren
Quoted 29 lines · Brian Swetland
Quoted 10 lines · Alan Stern
Quoted 9 lines
Quoted 3 lines
Oh, like tell the modem that user mode has handled the ring event and its ok to un-block?
No, that's not how it works. It would go like this:
The modem IRQ handler queues its event to the input subsystem. As it does so the input subsystem enables a suspend blocker, causing the system to stay awake after the IRQ is done.
How about instead the modem driver fails to suspend until it's done?
Each driver could have a
suspend_policysysfs entry with options such as [ forced | safe ]. The default would be forced. Forced would be the current behaviour, while safe would refuse suspend until the driver is done processing.Quoted 3 lines
Quoted 3 lines
The user program enables its own suspend blocker before reading the input queue. When the queue is empty, the input subsystem releases its suspend blocker.
And also the input layer could refuse to suspend until it's done.
Quoted 3 lines
Quoted 3 lines
When the user program finishes processing the event, it releases its suspend blocker. Now the system can go back to sleep.
Quoted 6 lines
Quoted 3 lines
And here the user space just tries to suspend again when it's done? It's not like you're trying to suspend all the time, so it should be OK to retry a few times.
We actually are trying to suspend all the time -- that's our basic model -- suspend whenever we can when something doesn't prevent it.
Maybe that state could be kept in some userspace suspend policy manager?
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
At no point does the user program have to communicate anything to the modem driver, and at no point does it have to do anything out of the ordinary except to enable and disable a suspend blocker.
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Exactly -- and you can use the same style of overlapping suspend blockers with other drivers than input, if the input interface is not suitable for the particular interaction.
Would the suspend blockers still be needed somewhere in the example above?
How often would we retry suspending?
Well based on some timer, the same way the screen blanks? Or five seconds of no audio play? So if the suspend fails, then reset whatever userspace suspend policy timers.
Quoted 2 lines
If we fail to suspend, don't we have to resume all the drivers that suspended before the one that failed? (Maybe I'm mistaken here)
Quoted 9 lines
Quoted 6 lines
Quoted 3 lines
Sure, but I guess that should be a rare event that only happens when you try to suspend and something interrupts the suspend.
This is not a rare event. For example, the matrix keypad driver blocks suspend when a key is down so it can scan the matrix.
Sure, but how many times per day are you suspending?
How many times we successfully suspend is irrelevant here. If the driver blocks suspend the number of suspend attempts depend on your poll frequency.
Quoted 15 lines
Quoted 15 lines
Quoted 14 lines
Quoted 9 lines
With the suspend block model we know the moment we're capable of suspending and then can suspend at that moment. Continually trying to suspend seems like it'd be inefficient power-wise (we're going to be doing a lot more work as we try to suspend over and over, or we're going to retry after a timeout and spend extra time not suspended).
We can often spend minutes (possibly many) at a time preventing suspend when the system is doing work that would be interrupted by a full suspend.
Maybe you a userspace suspend policy manager would do the trick if it knows when the screen is blanked and no audio has been played for five seconds etc?
Quoted 8 lines
Quoted 2 lines
If user space has to initiate every suspend attempt, then you are forcing it to poll whenever a driver needs to block suspend.
Hmm I don't follow you. If the userspace policy daemon timer times out, the device suspends. If the device does not suspend because of a blocking driver, then the timers get reset and you try again based on some event such as when the screen blanks.
This retry is what I call polling. You have to keep retrying until you succeed. Also, using the screen blank timeout for this polling is not a good idea. You do not want to toggle the screen off and on with with every suspend attempt.
Signature · 1 line
Arve Hjønnevåg
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony Lindgren2010/5/6 Tony Lindgren <[email protected]>:
Quoted 62 lines · Arve Hjønnevåg
Quoted 61 lines · Tony Lindgren
Quoted 60 lines · Brian Swetland
Quoted 30 lines · Tony Lindgren
Quoted 29 lines · Brian Swetland
Quoted 10 lines · Alan Stern
Quoted 9 lines
Quoted 3 lines
Oh, like tell the modem that user mode has handled the ring event and its ok to un-block?
No, that's not how it works. It would go like this:
The modem IRQ handler queues its event to the input subsystem. As it does so the input subsystem enables a suspend blocker, causing the system to stay awake after the IRQ is done.
How about instead the modem driver fails to suspend until it's done?
Each driver could have a
suspend_policysysfs entry with options such as [ forced | safe ]. The default would be forced. Forced would be the current behaviour, while safe would refuse suspend until the driver is done processing.Quoted 3 lines
Quoted 3 lines
The user program enables its own suspend blocker before reading the input queue. When the queue is empty, the input subsystem releases its suspend blocker.
And also the input layer could refuse to suspend until it's done.
Quoted 3 lines
Quoted 3 lines
When the user program finishes processing the event, it releases its suspend blocker. Now the system can go back to sleep.
Quoted 6 lines
Quoted 3 lines
And here the user space just tries to suspend again when it's done? It's not like you're trying to suspend all the time, so it should be OK to retry a few times.
We actually are trying to suspend all the time -- that's our basic model -- suspend whenever we can when something doesn't prevent it.
Maybe that state could be kept in some userspace suspend policy manager?
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
At no point does the user program have to communicate anything to the modem driver, and at no point does it have to do anything out of the ordinary except to enable and disable a suspend blocker.
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Exactly -- and you can use the same style of overlapping suspend blockers with other drivers than input, if the input interface is not suitable for the particular interaction.
Would the suspend blockers still be needed somewhere in the example above?
How often would we retry suspending?
Well based on some timer, the same way the screen blanks? Or five seconds of no audio play? So if the suspend fails, then reset whatever userspace suspend policy timers.
Quoted 2 lines
If we fail to suspend, don't we have to resume all the drivers that suspended before the one that failed? (Maybe I'm mistaken here)
Quoted 9 lines
Quoted 6 lines
Quoted 3 lines
Sure, but I guess that should be a rare event that only happens when you try to suspend and something interrupts the suspend.
This is not a rare event. For example, the matrix keypad driver blocks suspend when a key is down so it can scan the matrix.
Sure, but how many times per day are you suspending?
How many times we successfully suspend is irrelevant here. If the driver blocks suspend the number of suspend attempts depend on your poll frequency.
Quoted 15 lines
Quoted 15 lines
Quoted 14 lines
Quoted 9 lines
With the suspend block model we know the moment we're capable of suspending and then can suspend at that moment. Continually trying to suspend seems like it'd be inefficient power-wise (we're going to be doing a lot more work as we try to suspend over and over, or we're going to retry after a timeout and spend extra time not suspended).
We can often spend minutes (possibly many) at a time preventing suspend when the system is doing work that would be interrupted by a full suspend.
Maybe you a userspace suspend policy manager would do the trick if it knows when the screen is blanked and no audio has been played for five seconds etc?
Quoted 8 lines
Quoted 2 lines
If user space has to initiate every suspend attempt, then you are forcing it to poll whenever a driver needs to block suspend.
Hmm I don't follow you. If the userspace policy daemon timer times out, the device suspends. If the device does not suspend because of a blocking driver, then the timers get reset and you try again based on some event such as when the screen blanks.
This retry is what I call polling. You have to keep retrying until you succeed. Also, using the screen blank timeout for this polling is not a good idea. You do not want to toggle the screen off and on with with every suspend attempt.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 2 lines · Arve Hjønnevåg
2010/5/6 Tony Lindgren <[email protected]>:
Quoted 1 line · Arve Hjønnevåg
<snip>
Quoted 9 lines
Quoted 5 lines
Quoted 2 lines
This is not a rare event. For example, the matrix keypad driver blocks suspend when a key is down so it can scan the matrix.
Sure, but how many times per day are you suspending?
How many times we successfully suspend is irrelevant here. If the driver blocks suspend the number of suspend attempts depend on your poll frequency.
I guess what I'm trying to say is that a failed suspend should be a rare event.
Quoted 24 lines
Quoted 15 lines
Quoted 15 lines
Quoted 14 lines
Quoted 9 lines
With the suspend block model we know the moment we're capable of suspending and then can suspend at that moment. Continually trying to suspend seems like it'd be inefficient power-wise (we're going to be doing a lot more work as we try to suspend over and over, or we're going to retry after a timeout and spend extra time not suspended).
We can often spend minutes (possibly many) at a time preventing suspend when the system is doing work that would be interrupted by a full suspend.
Maybe you a userspace suspend policy manager would do the trick if it knows when the screen is blanked and no audio has been played for five seconds etc?
Quoted 8 lines
Quoted 2 lines
If user space has to initiate every suspend attempt, then you are forcing it to poll whenever a driver needs to block suspend.
Hmm I don't follow you. If the userspace policy daemon timer times out, the device suspends. If the device does not suspend because of a blocking driver, then the timers get reset and you try again based on some event such as when the screen blanks.
Quoted 4 lines
This retry is what I call polling. You have to keep retrying until you succeed. Also, using the screen blank timeout for this polling is not a good idea. You do not want to toggle the screen off and on with with every suspend attempt.
The number of retries depends on the power management policy for your device. And that is often device and use specific.
So having to retry suspend should be a rare event. The userspace should mostly know when it's OK to suspend.
Regards,
Tony
_______________________________________________
linux-pm mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/linux-pm
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Arve HjønnevågQuoted 2 lines · Arve Hjønnevåg
2010/5/6 Tony Lindgren <[email protected]>:
Quoted 1 line · Arve Hjønnevåg
<snip>
Quoted 9 lines
Quoted 5 lines
Quoted 2 lines
This is not a rare event. For example, the matrix keypad driver blocks suspend when a key is down so it can scan the matrix.
Sure, but how many times per day are you suspending?
How many times we successfully suspend is irrelevant here. If the driver blocks suspend the number of suspend attempts depend on your poll frequency.
I guess what I'm trying to say is that a failed suspend should be a rare event.
Quoted 24 lines
Quoted 15 lines
Quoted 15 lines
Quoted 14 lines
Quoted 9 lines
With the suspend block model we know the moment we're capable of suspending and then can suspend at that moment. Continually trying to suspend seems like it'd be inefficient power-wise (we're going to be doing a lot more work as we try to suspend over and over, or we're going to retry after a timeout and spend extra time not suspended).
We can often spend minutes (possibly many) at a time preventing suspend when the system is doing work that would be interrupted by a full suspend.
Maybe you a userspace suspend policy manager would do the trick if it knows when the screen is blanked and no audio has been played for five seconds etc?
Quoted 8 lines
Quoted 2 lines
If user space has to initiate every suspend attempt, then you are forcing it to poll whenever a driver needs to block suspend.
Hmm I don't follow you. If the userspace policy daemon timer times out, the device suspends. If the device does not suspend because of a blocking driver, then the timers get reset and you try again based on some event such as when the screen blanks.
Quoted 4 lines
This retry is what I call polling. You have to keep retrying until you succeed. Also, using the screen blank timeout for this polling is not a good idea. You do not want to toggle the screen off and on with with every suspend attempt.
The number of retries depends on the power management policy for your device. And that is often device and use specific.
So having to retry suspend should be a rare event. The userspace should mostly know when it's OK to suspend.
Regards,
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
In reply to Arve HjønnevågHi!
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Quoted 12 lines
Quoted 1 line
How often would we retry suspending?
Well based on some timer, the same way the screen blanks? Or five seconds of no audio play? So if the suspend fails, then reset whatever userspace suspend policy timers.
Quoted 2 lines
If we fail to suspend, don't we have to resume all the drivers that suspended before the one that failed? (Maybe I'm mistaken here)
Sure, but I guess that should be a rare event that only happens when you try to suspend and something interrupts the suspend.
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
This is not a rare event. For example, the matrix keypad driver blocks suspend when a key is down so it can scan the matrix.
Sure, but how many times per day are you suspending?
How many times we successfully suspend is irrelevant here. If the driver blocks suspend the number of suspend attempts depend on your poll frequency.
Actually, this is quite interesting question I'd like answer here:
"Sure, but how many times per day are you suspending?"
I suspect it may be in 1000s, but it would be cool to get better answer -- so that people knew what we are talking about here.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Arve HjønnevågHi!
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Quoted 12 lines
Quoted 1 line
How often would we retry suspending?
Well based on some timer, the same way the screen blanks? Or five seconds of no audio play? So if the suspend fails, then reset whatever userspace suspend policy timers.
Quoted 2 lines
If we fail to suspend, don't we have to resume all the drivers that suspended before the one that failed? (Maybe I'm mistaken here)
Sure, but I guess that should be a rare event that only happens when you try to suspend and something interrupts the suspend.
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
This is not a rare event. For example, the matrix keypad driver blocks suspend when a key is down so it can scan the matrix.
Sure, but how many times per day are you suspending?
How many times we successfully suspend is irrelevant here. If the driver blocks suspend the number of suspend attempts depend on your poll frequency.
Actually, this is quite interesting question I'd like answer here:
"Sure, but how many times per day are you suspending?"
I suspect it may be in 1000s, but it would be cool to get better answer -- so that people knew what we are talking about here.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 24 lines · Pavel Machek
Hi!
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Quoted 12 lines
Quoted 1 line
How often would we retry suspending?
Well based on some timer, the same way the screen blanks? Or five seconds of no audio play? So if the suspend fails, then reset whatever userspace suspend policy timers.
Quoted 2 lines
If we fail to suspend, don't we have to resume all the drivers that suspended before the one that failed? (Maybe I'm mistaken here)
Sure, but I guess that should be a rare event that only happens when you try to suspend and something interrupts the suspend.
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
This is not a rare event. For example, the matrix keypad driver blocks suspend when a key is down so it can scan the matrix.
Sure, but how many times per day are you suspending?
How many times we successfully suspend is irrelevant here. If the driver blocks suspend the number of suspend attempts depend on your poll frequency.
Quoted 6 lines
Actually, this is quite interesting question I'd like answer here:
"Sure, but how many times per day are you suspending?"
I suspect it may be in 1000s, but it would be cool to get better answer -- so that people knew what we are talking about here.
This is highly variable. 1000s would mean that you wake about once every minute which is not uncommon, but more often than what typically happens on an idle device. The nexus one has to wake up every 10 minutes to check the battery status check means your at least in the 100s, but the G1 could stay suspended for much longer than that.
The original question was about a driver blocking suspend though, and if we were to just retry suspend until it succeeds in that case you could easily get to 100000s suspend attempts in a day.
Signature · 1 line
Arve Hjønnevåg
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Pavel MachekQuoted 24 lines · Pavel Machek
Hi!
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Quoted 12 lines
Quoted 1 line
How often would we retry suspending?
Well based on some timer, the same way the screen blanks? Or five seconds of no audio play? So if the suspend fails, then reset whatever userspace suspend policy timers.
Quoted 2 lines
If we fail to suspend, don't we have to resume all the drivers that suspended before the one that failed? (Maybe I'm mistaken here)
Sure, but I guess that should be a rare event that only happens when you try to suspend and something interrupts the suspend.
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
This is not a rare event. For example, the matrix keypad driver blocks suspend when a key is down so it can scan the matrix.
Sure, but how many times per day are you suspending?
How many times we successfully suspend is irrelevant here. If the driver blocks suspend the number of suspend attempts depend on your poll frequency.
Quoted 6 lines
Actually, this is quite interesting question I'd like answer here:
"Sure, but how many times per day are you suspending?"
I suspect it may be in 1000s, but it would be cool to get better answer -- so that people knew what we are talking about here.
This is highly variable. 1000s would mean that you wake about once every minute which is not uncommon, but more often than what typically happens on an idle device. The nexus one has to wake up every 10 minutes to check the battery status check means your at least in the 100s, but the G1 could stay suspended for much longer than that.
The original question was about a driver blocking suspend though, and if we were to just retry suspend until it succeeds in that case you could easily get to 100000s suspend attempts in a day.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 1 line · Tony Lindgren
How about instead the modem driver fails to suspend until it's done?
Because every attempted suspend requires freezing userspace, suspending devices until you hit one that refuses to suspend, resuming the devies that did suspend and then unfreezing userspace. That's not an attractive option.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 1 line · Tony Lindgren
How about instead the modem driver fails to suspend until it's done?
Because every attempted suspend requires freezing userspace, suspending devices until you hit one that refuses to suspend, resuming the devies that did suspend and then unfreezing userspace. That's not an attractive option.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 8 lines · Matthew Garrett
Quoted 1 line · Tony Lindgren
How about instead the modem driver fails to suspend until it's done?
Because every attempted suspend requires freezing userspace, suspending devices until you hit one that refuses to suspend, resuming the devies that did suspend and then unfreezing userspace. That's not an attractive option.
But how many times per day are you really suspending? Maybe few tens of times at most if it's based on some user activity?
Or are you suspending constantly, tens of times per minute even if there's no user activity?
Regards,
Tony
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Matthew GarrettQuoted 8 lines · Matthew Garrett
Quoted 1 line · Tony Lindgren
How about instead the modem driver fails to suspend until it's done?
Because every attempted suspend requires freezing userspace, suspending devices until you hit one that refuses to suspend, resuming the devies that did suspend and then unfreezing userspace. That's not an attractive option.
But how many times per day are you really suspending? Maybe few tens of times at most if it's based on some user activity?
Or are you suspending constantly, tens of times per minute even if there's no user activity?
Regards,
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 2 lines · Tony Lindgren
Or are you suspending constantly, tens of times per minute even if there's no user activity?
In this case you'd be repeatedly trying to suspend until the modem driver stopped blocking it. It's pretty much a waste.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 2 lines · Tony Lindgren
Or are you suspending constantly, tens of times per minute even if there's no user activity?
In this case you'd be repeatedly trying to suspend until the modem driver stopped blocking it. It's pretty much a waste.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 7 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
Or are you suspending constantly, tens of times per minute even if there's no user activity?
In this case you'd be repeatedly trying to suspend until the modem driver stopped blocking it. It's pretty much a waste.
But then the userspace knows you're getting data from the modem, and it can kick some inactivity timer that determines when to try to suspend next.
Why would you need to constantly try to suspend in that case?
Regards,
Tony
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Matthew GarrettQuoted 7 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
Or are you suspending constantly, tens of times per minute even if there's no user activity?
In this case you'd be repeatedly trying to suspend until the modem driver stopped blocking it. It's pretty much a waste.
But then the userspace knows you're getting data from the modem, and it can kick some inactivity timer that determines when to try to suspend next.
Why would you need to constantly try to suspend in that case?
Regards,
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 1 line · Tony Lindgren
Why would you need to constantly try to suspend in that case?
Because otherwise you're awake for longer than you need to be.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 1 line · Tony Lindgren
Why would you need to constantly try to suspend in that case?
Because otherwise you're awake for longer than you need to be.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 5 lines · Matthew Garrett
Quoted 1 line · Tony Lindgren
Why would you need to constantly try to suspend in that case?
Because otherwise you're awake for longer than you need to be.
If your system is idle and your hardware supports off-while-idle, then that really does not matter. There's not much of a difference in power savings, we're already talking over 10 days on batteries with just off-while-idle on omaps.
If your userspace keeps polling and has runaway timers, then you could suspend it's parent process to idle the system?
Regards,
Tony
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Matthew GarrettQuoted 5 lines · Matthew Garrett
Quoted 1 line · Tony Lindgren
Why would you need to constantly try to suspend in that case?
Because otherwise you're awake for longer than you need to be.
If your system is idle and your hardware supports off-while-idle, then that really does not matter. There's not much of a difference in power savings, we're already talking over 10 days on batteries with just off-while-idle on omaps.
If your userspace keeps polling and has runaway timers, then you could suspend it's parent process to idle the system?
Regards,
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 2 lines · Tony Lindgren
If your userspace keeps polling and has runaway timers, then you could suspend it's parent process to idle the system?
If your userspace is suspended, how does it process the events that generated a system wakeup? If we had a good answer to that then suspend blockers would be much less necessary.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 2 lines · Tony Lindgren
If your userspace keeps polling and has runaway timers, then you could suspend it's parent process to idle the system?
If your userspace is suspended, how does it process the events that generated a system wakeup? If we had a good answer to that then suspend blockers would be much less necessary.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 8 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
If your userspace keeps polling and has runaway timers, then you could suspend it's parent process to idle the system?
If your userspace is suspended, how does it process the events that generated a system wakeup? If we had a good answer to that then suspend blockers would be much less necessary.
Well if your hardware runs off-while-idle or even just retention-while-idle, then the basic shell works just fine waking up every few seconds or so.
Then you could keep init/shell/suspend policy deamon running until it's time to suspend the whole device. To cut down runaway timers, you could already freeze the desktop/GUI/whatever earlier.
Regards,
Tony
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Matthew GarrettQuoted 8 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
If your userspace keeps polling and has runaway timers, then you could suspend it's parent process to idle the system?
If your userspace is suspended, how does it process the events that generated a system wakeup? If we had a good answer to that then suspend blockers would be much less necessary.
Well if your hardware runs off-while-idle or even just retention-while-idle, then the basic shell works just fine waking up every few seconds or so.
Then you could keep init/shell/suspend policy deamon running until it's time to suspend the whole device. To cut down runaway timers, you could already freeze the desktop/GUI/whatever earlier.
Regards,
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 6 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
If your userspace keeps polling and has runaway timers, then you could suspend it's parent process to idle the system?
Quoted 7 lines
Quoted 3 lines
If your userspace is suspended, how does it process the events that generated a system wakeup? If we had a good answer to that then suspend blockers would be much less necessary.
Well if your hardware runs off-while-idle or even just retention-while-idle, then the basic shell works just fine waking up every few seconds or so.
And the untrusted userspace code that's waiting for a network packet? Adding a few seconds of latency isn't an option here.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 6 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
If your userspace keeps polling and has runaway timers, then you could suspend it's parent process to idle the system?
Quoted 7 lines
Quoted 3 lines
If your userspace is suspended, how does it process the events that generated a system wakeup? If we had a good answer to that then suspend blockers would be much less necessary.
Well if your hardware runs off-while-idle or even just retention-while-idle, then the basic shell works just fine waking up every few seconds or so.
And the untrusted userspace code that's waiting for a network packet? Adding a few seconds of latency isn't an option here.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 11 lines · Matthew Garrett
Quoted 10 lines · Tony Lindgren
Quoted 8 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
If your userspace keeps polling and has runaway timers, then you could suspend it's parent process to idle the system?
If your userspace is suspended, how does it process the events that generated a system wakeup? If we had a good answer to that then suspend blockers would be much less necessary.
Quoted 6 lines
Quoted 3 lines
Well if your hardware runs off-while-idle or even just retention-while-idle, then the basic shell works just fine waking up every few seconds or so.
And the untrusted userspace code that's waiting for a network packet? Adding a few seconds of latency isn't an option here.
Hmm well hitting retention and wake you can basically do between jiffies. Hitting off mode in idle has way longer latencies, but still in few hundred milliseconds or so, not seconds.
And cpuidle pretty much takes care of hitting the desired C state for you. This setup is totally working on Nokia N900 for example, it's hitting off modes in idle and running all the time, it never suspends.
Regards,
Tony
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Matthew GarrettQuoted 11 lines · Matthew Garrett
Quoted 10 lines · Tony Lindgren
Quoted 8 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
If your userspace keeps polling and has runaway timers, then you could suspend it's parent process to idle the system?
If your userspace is suspended, how does it process the events that generated a system wakeup? If we had a good answer to that then suspend blockers would be much less necessary.
Quoted 6 lines
Quoted 3 lines
Well if your hardware runs off-while-idle or even just retention-while-idle, then the basic shell works just fine waking up every few seconds or so.
And the untrusted userspace code that's waiting for a network packet? Adding a few seconds of latency isn't an option here.
Hmm well hitting retention and wake you can basically do between jiffies. Hitting off mode in idle has way longer latencies, but still in few hundred milliseconds or so, not seconds.
And cpuidle pretty much takes care of hitting the desired C state for you. This setup is totally working on Nokia N900 for example, it's hitting off modes in idle and running all the time, it never suspends.
Regards,
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 7 lines · Tony Lindgren
Quoted 2 lines · Matthew Garrett
And the untrusted userspace code that's waiting for a network packet? Adding a few seconds of latency isn't an option here.
Hmm well hitting retention and wake you can basically do between jiffies. Hitting off mode in idle has way longer latencies, but still in few hundred milliseconds or so, not seconds.
The situation is this. You've frozen most of your userspace because you don't trust the applications. One of those applications has an open network socket, and policy indicates that receiving a network packet should generate a wakeup, allow the userspace application to handle the packet and then return to sleep. What mechanism do you use to do that?
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 7 lines · Tony Lindgren
Quoted 2 lines · Matthew Garrett
And the untrusted userspace code that's waiting for a network packet? Adding a few seconds of latency isn't an option here.
Hmm well hitting retention and wake you can basically do between jiffies. Hitting off mode in idle has way longer latencies, but still in few hundred milliseconds or so, not seconds.
The situation is this. You've frozen most of your userspace because you don't trust the applications. One of those applications has an open network socket, and policy indicates that receiving a network packet should generate a wakeup, allow the userspace application to handle the packet and then return to sleep. What mechanism do you use to do that?
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 9 lines · Matthew Garrett
Quoted 7 lines · Tony Lindgren
Quoted 2 lines · Matthew Garrett
And the untrusted userspace code that's waiting for a network packet? Adding a few seconds of latency isn't an option here.
Hmm well hitting retention and wake you can basically do between jiffies. Hitting off mode in idle has way longer latencies, but still in few hundred milliseconds or so, not seconds.
Quoted 5 lines
The situation is this. You've frozen most of your userspace because you don't trust the applications. One of those applications has an open network socket, and policy indicates that receiving a network packet should generate a wakeup, allow the userspace application to handle the packet and then return to sleep. What mechanism do you use to do that?
I think the ideal way of doing this would be to have the system running and hitting some deeper idle states using cpuidle. Then fix the apps so timers don't wake up the system too often. Then everything would just run in a normal way.
For the misbehaving stopped apps, maybe they could be woken to deal with the incoming network data with sysfs_notify?
Regards,
Tony
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Matthew GarrettQuoted 9 lines · Matthew Garrett
Quoted 7 lines · Tony Lindgren
Quoted 2 lines · Matthew Garrett
And the untrusted userspace code that's waiting for a network packet? Adding a few seconds of latency isn't an option here.
Hmm well hitting retention and wake you can basically do between jiffies. Hitting off mode in idle has way longer latencies, but still in few hundred milliseconds or so, not seconds.
Quoted 5 lines
The situation is this. You've frozen most of your userspace because you don't trust the applications. One of those applications has an open network socket, and policy indicates that receiving a network packet should generate a wakeup, allow the userspace application to handle the packet and then return to sleep. What mechanism do you use to do that?
I think the ideal way of doing this would be to have the system running and hitting some deeper idle states using cpuidle. Then fix the apps so timers don't wake up the system too often. Then everything would just run in a normal way.
For the misbehaving stopped apps, maybe they could be woken to deal with the incoming network data with sysfs_notify?
Regards,
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 11 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
The situation is this. You've frozen most of your userspace because you don't trust the applications. One of those applications has an open network socket, and policy indicates that receiving a network packet should generate a wakeup, allow the userspace application to handle the packet and then return to sleep. What mechanism do you use to do that?
I think the ideal way of doing this would be to have the system running and hitting some deeper idle states using cpuidle. Then fix the apps so timers don't wake up the system too often. Then everything would just run in a normal way.
Effective power management in the face of real-world applications is a reasonable usecase.
Quoted 2 lines
For the misbehaving stopped apps, maybe they could be woken to deal with the incoming network data with
sysfs_notify?
How would that work? Have the kernel send a sysfs_notify on every netwrk packet and have a monitor app listen for it and unfreeze the rest of userspace if it's frozen? That sounds expensive.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 11 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
The situation is this. You've frozen most of your userspace because you don't trust the applications. One of those applications has an open network socket, and policy indicates that receiving a network packet should generate a wakeup, allow the userspace application to handle the packet and then return to sleep. What mechanism do you use to do that?
I think the ideal way of doing this would be to have the system running and hitting some deeper idle states using cpuidle. Then fix the apps so timers don't wake up the system too often. Then everything would just run in a normal way.
Effective power management in the face of real-world applications is a reasonable usecase.
Quoted 2 lines
For the misbehaving stopped apps, maybe they could be woken to deal with the incoming network data with
sysfs_notify?
How would that work? Have the kernel send a sysfs_notify on every netwrk packet and have a monitor app listen for it and unfreeze the rest of userspace if it's frozen? That sounds expensive.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 8 lines · Matthew Garrett
Quoted 7 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
The situation is this. You've frozen most of your userspace because you don't trust the applications. One of those applications has an open network socket, and policy indicates that receiving a network packet should generate a wakeup, allow the userspace application to handle the packet and then return to sleep. What mechanism do you use to do that?
Quoted 7 lines
Quoted 4 lines
I think the ideal way of doing this would be to have the system running and hitting some deeper idle states using cpuidle. Then fix the apps so timers don't wake up the system too often. Then everything would just run in a normal way.
Effective power management in the face of real-world applications is a reasonable usecase.
Sure there's no easy solution to misbehaving apps.
Quoted 6 lines
Quoted 2 lines
For the misbehaving stopped apps, maybe they could be woken to deal with the incoming network data with
sysfs_notify?How would that work? Have the kernel send a
sysfs_notifyon every netwrk packet and have a monitor app listen for it and unfreeze the rest of userspace if it's frozen? That sounds expensive.
Yeah maybe there are better ways of dealing with this.
Maybe deferred timers would help some so all the apps could be allowed to run until some power management policy decides to suspend the whole device.
Regards,
Tony
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Matthew GarrettQuoted 8 lines · Matthew Garrett
Quoted 7 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
The situation is this. You've frozen most of your userspace because you don't trust the applications. One of those applications has an open network socket, and policy indicates that receiving a network packet should generate a wakeup, allow the userspace application to handle the packet and then return to sleep. What mechanism do you use to do that?
Quoted 7 lines
Quoted 4 lines
I think the ideal way of doing this would be to have the system running and hitting some deeper idle states using cpuidle. Then fix the apps so timers don't wake up the system too often. Then everything would just run in a normal way.
Effective power management in the face of real-world applications is a reasonable usecase.
Sure there's no easy solution to misbehaving apps.
Quoted 6 lines
Quoted 2 lines
For the misbehaving stopped apps, maybe they could be woken to deal with the incoming network data with
sysfs_notify?How would that work? Have the kernel send a
sysfs_notifyon every netwrk packet and have a monitor app listen for it and unfreeze the rest of userspace if it's frozen? That sounds expensive.
Yeah maybe there are better ways of dealing with this.
Maybe deferred timers would help some so all the apps could be allowed to run until some power management policy decides to suspend the whole device.
Regards,
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 5 lines · Tony Lindgren
Quoted 2 lines · Matthew Garrett
Effective power management in the face of real-world applications is a reasonable usecase.
Sure there's no easy solution to misbehaving apps.
That's the point of the suspend blockers.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 5 lines · Tony Lindgren
Quoted 2 lines · Matthew Garrett
Effective power management in the face of real-world applications is a reasonable usecase.
Sure there's no easy solution to misbehaving apps.
That's the point of the suspend blockers.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
Quoted 8 lines · Matthew Garrett
Quoted 5 lines · Tony Lindgren
Quoted 2 lines · Matthew Garrett
Effective power management in the face of real-world applications is a reasonable usecase.
Sure there's no easy solution to misbehaving apps.
That's the point of the suspend blockers.
To me it sounds like suspending the whole system to deal with some misbehaving apps is an overkill. Sounds like kill -STOP the misbehaving apps should do the trick?
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 6 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
Quoted 4 lines · Tony Lindgren
Quoted 2 lines · Matthew Garrett
Effective power management in the face of real-world applications is a reasonable usecase.
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
Sure there's no easy solution to misbehaving apps.
That's the point of the suspend blockers.
To me it sounds like suspending the whole system to deal with some misbehaving apps is an overkill. Sounds like kill -STOP the misbehaving apps should do the trick?
Freezer cgroups would work better, but it doesn't really change the point - if that application has an open network socket, how do you know to resume that application when a packet comes in?
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 6 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
Quoted 4 lines · Tony Lindgren
Quoted 2 lines · Matthew Garrett
Effective power management in the face of real-world applications is a reasonable usecase.
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
Sure there's no easy solution to misbehaving apps.
That's the point of the suspend blockers.
To me it sounds like suspending the whole system to deal with some misbehaving apps is an overkill. Sounds like kill -STOP the misbehaving apps should do the trick?
Freezer cgroups would work better, but it doesn't really change the point - if that application has an open network socket, how do you know to resume that application when a packet comes in?
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 11 lines · Matthew Garrett
Quoted 10 lines · Tony Lindgren
Quoted 8 lines · Matthew Garrett
Quoted 5 lines · Tony Lindgren
Quoted 2 lines · Matthew Garrett
Effective power management in the face of real-world applications is a reasonable usecase.
Sure there's no easy solution to misbehaving apps.
That's the point of the suspend blockers.
Quoted 7 lines
Quoted 3 lines
To me it sounds like suspending the whole system to deal with some misbehaving apps is an overkill. Sounds like kill -STOP the misbehaving apps should do the trick?
Freezer cgroups would work better, but it doesn't really change the point - if that application has an open network socket, how do you know to resume that application when a packet comes in?
suspend blockers can get abused also .. I had my phone in my pocket and accidentally ran "Google Talk" or something. It must have kept the screen on or kept the phone from suspending, so the battery drained completely over the course of an hour or so.
Daniel
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Matthew GarrettQuoted 11 lines · Matthew Garrett
Quoted 10 lines · Tony Lindgren
Quoted 8 lines · Matthew Garrett
Quoted 5 lines · Tony Lindgren
Quoted 2 lines · Matthew Garrett
Effective power management in the face of real-world applications is a reasonable usecase.
Sure there's no easy solution to misbehaving apps.
That's the point of the suspend blockers.
Quoted 7 lines
Quoted 3 lines
To me it sounds like suspending the whole system to deal with some misbehaving apps is an overkill. Sounds like kill -STOP the misbehaving apps should do the trick?
Freezer cgroups would work better, but it doesn't really change the point - if that application has an open network socket, how do you know to resume that application when a packet comes in?
suspend blockers can get abused also .. I had my phone in my pocket and accidentally ran "Google Talk" or something. It must have kept the screen on or kept the phone from suspending, so the battery drained completely over the course of an hour or so.
Daniel
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 12 lines · Daniel Walker
Quoted 11 lines · Matthew Garrett
Quoted 10 lines · Tony Lindgren
Quoted 8 lines · Matthew Garrett
Quoted 5 lines · Tony Lindgren
Quoted 2 lines · Matthew Garrett
Effective power management in the face of real-world applications is a reasonable usecase.
Sure there's no easy solution to misbehaving apps.
That's the point of the suspend blockers.
Quoted 7 lines
Quoted 7 lines
Quoted 3 lines
To me it sounds like suspending the whole system to deal with some misbehaving apps is an overkill. Sounds like kill -STOP the misbehaving apps should do the trick?
Freezer cgroups would work better, but it doesn't really change the point - if that application has an open network socket, how do you know to resume that application when a packet comes in?
No idea, but that still sounds a better situation to me than trying to deal with that for a suspended system! :)
Quoted 4 lines
suspend blockers can get abused also .. I had my phone in my pocket and accidentally ran "Google Talk" or something. It must have kept the screen on or kept the phone from suspending, so the battery drained completely over the course of an hour or so.
Yeah I guess there's nothing stopping that.
Tony
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Daniel WalkerQuoted 12 lines · Daniel Walker
Quoted 11 lines · Matthew Garrett
Quoted 10 lines · Tony Lindgren
Quoted 8 lines · Matthew Garrett
Quoted 5 lines · Tony Lindgren
Quoted 2 lines · Matthew Garrett
Effective power management in the face of real-world applications is a reasonable usecase.
Sure there's no easy solution to misbehaving apps.
That's the point of the suspend blockers.
Quoted 7 lines
Quoted 7 lines
Quoted 3 lines
To me it sounds like suspending the whole system to deal with some misbehaving apps is an overkill. Sounds like kill -STOP the misbehaving apps should do the trick?
Freezer cgroups would work better, but it doesn't really change the point - if that application has an open network socket, how do you know to resume that application when a packet comes in?
No idea, but that still sounds a better situation to me than trying to deal with that for a suspended system! :)
Quoted 4 lines
suspend blockers can get abused also .. I had my phone in my pocket and accidentally ran "Google Talk" or something. It must have kept the screen on or kept the phone from suspending, so the battery drained completely over the course of an hour or so.
Yeah I guess there's nothing stopping that.
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 8 lines · Tony Lindgren
Quoted 4 lines · Daniel Walker
Quoted 3 lines · Matthew Garrett
Freezer cgroups would work better, but it doesn't really change the point - if that application has an open network socket, how do you know to resume that application when a packet comes in?
No idea, but that still sounds a better situation to me than trying to deal with that for a suspended system! :)
Suspend blocks deal with that problem. Nobody has yet demonstrated a workable alternative solution.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 8 lines · Tony Lindgren
Quoted 4 lines · Daniel Walker
Quoted 3 lines · Matthew Garrett
Freezer cgroups would work better, but it doesn't really change the point - if that application has an open network socket, how do you know to resume that application when a packet comes in?
No idea, but that still sounds a better situation to me than trying to deal with that for a suspended system! :)
Suspend blocks deal with that problem. Nobody has yet demonstrated a workable alternative solution.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 7 lines · Matthew Garrett
Quoted 6 lines · Tony Lindgren
Quoted 4 lines · Daniel Walker
Quoted 3 lines · Matthew Garrett
Freezer cgroups would work better, but it doesn't really change the point - if that application has an open network socket, how do you know to resume that application when a packet comes in?
Quoted 5 lines
Quoted 2 lines
No idea, but that still sounds a better situation to me than trying to deal with that for a suspended system! :)
Suspend blocks deal with that problem. Nobody has yet demonstrated a workable alternative solution.
Well there are obviously two paths to take, I think both of them should work. The alternative to suspend blockers is:
- Implement a decent kernel idle function for the hardware and use cpuidle to change the c states. The dyntick stuff should already work for most hardware.
- Fix the core userspace apps to minimize timers.
- Deal with broken apps whichever way you want in the userspace.
- Optionally, do echo mem > /sys/power/state based on some product specific logic in the userspace.
The advantage of this is that no kernel changes are needed, except for implementing the custom idle function for the hardware. And this kind of setup has been in use for about five years.
And, you can keep the system running constantly if you have hardware that supports good idle modes, then you don't even need to suspend at all.
The core problems I see with suspend blockers are following, please correct me if I'm wrong:
- It is caching the value of echo mem > /sys/power/state and misusing it for runtime power management as the system still keeps running after trying to suspend. Instead, the kernel idle function and cpuidle should be used if the kernel keeps running.
- They require patching all over the drivers and userspace.
- Once the system is suspended, it does not run. And the apps don't behave in a standard way because the system does not wake to timer interrupts.
I agree that we need to be able to echo mem > /sys/power/state in an atomic way. So if there are problems with that, those issues should be fixed.
Cheers,
Tony
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Matthew GarrettQuoted 7 lines · Matthew Garrett
Quoted 6 lines · Tony Lindgren
Quoted 4 lines · Daniel Walker
Quoted 3 lines · Matthew Garrett
Freezer cgroups would work better, but it doesn't really change the point - if that application has an open network socket, how do you know to resume that application when a packet comes in?
Quoted 5 lines
Quoted 2 lines
No idea, but that still sounds a better situation to me than trying to deal with that for a suspended system! :)
Suspend blocks deal with that problem. Nobody has yet demonstrated a workable alternative solution.
Well there are obviously two paths to take, I think both of them should work. The alternative to suspend blockers is:
- Implement a decent kernel idle function for the hardware and use cpuidle to change the c states. The dyntick stuff should already work for most hardware.
- Fix the core userspace apps to minimize timers.
- Deal with broken apps whichever way you want in the userspace.
- Optionally, do echo mem > /sys/power/state based on some product specific logic in the userspace.
The advantage of this is that no kernel changes are needed, except for implementing the custom idle function for the hardware. And this kind of setup has been in use for about five years.
And, you can keep the system running constantly if you have hardware that supports good idle modes, then you don't even need to suspend at all.
The core problems I see with suspend blockers are following, please correct me if I'm wrong:
- It is caching the value of echo mem > /sys/power/state and misusing it for runtime power management as the system still keeps running after trying to suspend. Instead, the kernel idle function and cpuidle should be used if the kernel keeps running.
- They require patching all over the drivers and userspace.
- Once the system is suspended, it does not run. And the apps don't behave in a standard way because the system does not wake to timer interrupts.
I agree that we need to be able to echo mem > /sys/power/state in an atomic way. So if there are problems with that, those issues should be fixed.
Cheers,
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 1 line · Tony Lindgren
- Deal with broken apps whichever way you want in the userspace.
If we could do this then there would be no real need for suspend blockers.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 1 line · Tony Lindgren
- Deal with broken apps whichever way you want in the userspace.
If we could do this then there would be no real need for suspend blockers.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 6 lines · Matthew Garrett
Quoted 1 line · Tony Lindgren
- Deal with broken apps whichever way you want in the userspace.
If we could do this then there would be no real need for suspend blockers.
OK, I guess I don't understand all the details, need some kind of common example I guess.
So for example, if I leave ping running in a a terminal, do you have some way of preventing that from eating the battery?
In my scenario that program would keep on running until the battery runs out, or something stops the program. But the system keeps hitting retention mode in the idle loop.
How do you deal with programs like that?
Do you just suspend the whole system anyways at some point, or do you have some other trick?
Regards,
Tony
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Matthew GarrettQuoted 6 lines · Matthew Garrett
Quoted 1 line · Tony Lindgren
- Deal with broken apps whichever way you want in the userspace.
If we could do this then there would be no real need for suspend blockers.
OK, I guess I don't understand all the details, need some kind of common example I guess.
So for example, if I leave ping running in a a terminal, do you have some way of preventing that from eating the battery?
In my scenario that program would keep on running until the battery runs out, or something stops the program. But the system keeps hitting retention mode in the idle loop.
How do you deal with programs like that?
Do you just suspend the whole system anyways at some point, or do you have some other trick?
Regards,
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 2 lines · Tony Lindgren
So for example, if I leave ping running in a a terminal, do you have some way of preventing that from eating the battery?
It depends on policy. If all network packets generate wakeup events then no, that will carry on eating battery. If ICMP doesn't generate a wakeup event then the process won't be run.
Quoted 2 lines
Do you just suspend the whole system anyways at some point, or do you have some other trick?
If nothing's holding any suspend blocks then the system will enter suspend. If the packet generates a wakeup then the kernel would block suspend until userspace has had the opportunity to do so. Once userspace has handled the packet then it could release the block and the system will immediately transition back into suspend.
Here's a different example. A process is waiting for a keypress, but because it's badly written it's also drawing to the screen at 60 frames per second and preventing the system from every going to idle. How do you quiesce the system while still ensuring that the keypress will be delivered to the application?
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 2 lines · Tony Lindgren
So for example, if I leave ping running in a a terminal, do you have some way of preventing that from eating the battery?
It depends on policy. If all network packets generate wakeup events then no, that will carry on eating battery. If ICMP doesn't generate a wakeup event then the process won't be run.
Quoted 2 lines
Do you just suspend the whole system anyways at some point, or do you have some other trick?
If nothing's holding any suspend blocks then the system will enter suspend. If the packet generates a wakeup then the kernel would block suspend until userspace has had the opportunity to do so. Once userspace has handled the packet then it could release the block and the system will immediately transition back into suspend.
Here's a different example. A process is waiting for a keypress, but because it's badly written it's also drawing to the screen at 60 frames per second and preventing the system from every going to idle. How do you quiesce the system while still ensuring that the keypress will be delivered to the application?
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 9 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
So for example, if I leave ping running in a a terminal, do you have some way of preventing that from eating the battery?
It depends on policy. If all network packets generate wakeup events then no, that will carry on eating battery. If ICMP doesn't generate a wakeup event then the process won't be run.
Quoted 8 lines
Quoted 2 lines
Do you just suspend the whole system anyways at some point, or do you have some other trick?
If nothing's holding any suspend blocks then the system will enter suspend. If the packet generates a wakeup then the kernel would block suspend until userspace has had the opportunity to do so. Once userspace has handled the packet then it could release the block and the system will immediately transition back into suspend.
OK, then what would I need to do to keep that ping running if I wanted to?
Quoted 5 lines
Here's a different example. A process is waiting for a keypress, but because it's badly written it's also drawing to the screen at 60 frames per second and preventing the system from every going to idle. How do you quiesce the system while still ensuring that the keypress will be delivered to the application?
I guess it depends. If it's a game and I'm waiting to hit the fire button, then I don't want the system to suspend!
It's starting to sound like you're really using suspend blocks to "certify" that the app is safe to keep running.
Maybe it could be done with some kind of process flag instead that would tell "this process is safe to keep running from timer point of view" and if that flag is not set, then assume it's OK to stop the process at any point?
Regards,
Tony
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Matthew GarrettQuoted 9 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
So for example, if I leave ping running in a a terminal, do you have some way of preventing that from eating the battery?
It depends on policy. If all network packets generate wakeup events then no, that will carry on eating battery. If ICMP doesn't generate a wakeup event then the process won't be run.
Quoted 8 lines
Quoted 2 lines
Do you just suspend the whole system anyways at some point, or do you have some other trick?
If nothing's holding any suspend blocks then the system will enter suspend. If the packet generates a wakeup then the kernel would block suspend until userspace has had the opportunity to do so. Once userspace has handled the packet then it could release the block and the system will immediately transition back into suspend.
OK, then what would I need to do to keep that ping running if I wanted to?
Quoted 5 lines
Here's a different example. A process is waiting for a keypress, but because it's badly written it's also drawing to the screen at 60 frames per second and preventing the system from every going to idle. How do you quiesce the system while still ensuring that the keypress will be delivered to the application?
I guess it depends. If it's a game and I'm waiting to hit the fire button, then I don't want the system to suspend!
It's starting to sound like you're really using suspend blocks to "certify" that the app is safe to keep running.
Maybe it could be done with some kind of process flag instead that would tell "this process is safe to keep running from timer point of view" and if that flag is not set, then assume it's OK to stop the process at any point?
Regards,
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 13 lines · Tony Lindgren
Quoted 12 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
So for example, if I leave ping running in a a terminal, do you have some way of preventing that from eating the battery?
It depends on policy. If all network packets generate wakeup events then no, that will carry on eating battery. If ICMP doesn't generate a wakeup event then the process won't be run.
Quoted 2 lines
Do you just suspend the whole system anyways at some point, or do you have some other trick?
Quoted 8 lines
Quoted 5 lines
If nothing's holding any suspend blocks then the system will enter suspend. If the packet generates a wakeup then the kernel would block suspend until userspace has had the opportunity to do so. Once userspace has handled the packet then it could release the block and the system will immediately transition back into suspend.
OK, then what would I need to do to keep that ping running if I wanted to?
Use a suspend blocker. For instance: "runsuspendblock ping <addr>".
Quoted 9 lines
Quoted 5 lines
Here's a different example. A process is waiting for a keypress, but because it's badly written it's also drawing to the screen at 60 frames per second and preventing the system from every going to idle. How do you quiesce the system while still ensuring that the keypress will be delivered to the application?
I guess it depends. If it's a game and I'm waiting to hit the fire button, then I don't want the system to suspend!
We don't suspend while the screen is on. If the user pressed the power button to turn the screen off, then I would not want the game to prevent suspend.
Quoted 16 lines
It's starting to sound like you're really using suspend blocks to "certify" that the app is safe to keep running.
Maybe it could be done with some kind of process flag instead that would tell "this process is safe to keep running from timer point of view" and if that flag is not set, then assume it's OK to stop the process at any point?
Regards,
Tony
_______________________________________________
linux-pm mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/linux-pm
Signature · 1 line
Arve Hjønnevåg
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 13 lines · Tony Lindgren
Quoted 12 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
So for example, if I leave ping running in a a terminal, do you have some way of preventing that from eating the battery?
It depends on policy. If all network packets generate wakeup events then no, that will carry on eating battery. If ICMP doesn't generate a wakeup event then the process won't be run.
Quoted 2 lines
Do you just suspend the whole system anyways at some point, or do you have some other trick?
Quoted 8 lines
Quoted 5 lines
If nothing's holding any suspend blocks then the system will enter suspend. If the packet generates a wakeup then the kernel would block suspend until userspace has had the opportunity to do so. Once userspace has handled the packet then it could release the block and the system will immediately transition back into suspend.
OK, then what would I need to do to keep that ping running if I wanted to?
Use a suspend blocker. For instance: "runsuspendblock ping <addr>".
Quoted 9 lines
Quoted 5 lines
Here's a different example. A process is waiting for a keypress, but because it's badly written it's also drawing to the screen at 60 frames per second and preventing the system from every going to idle. How do you quiesce the system while still ensuring that the keypress will be delivered to the application?
I guess it depends. If it's a game and I'm waiting to hit the fire button, then I don't want the system to suspend!
We don't suspend while the screen is on. If the user pressed the power button to turn the screen off, then I would not want the game to prevent suspend.
Quoted 16 lines
It's starting to sound like you're really using suspend blocks to "certify" that the app is safe to keep running.
Maybe it could be done with some kind of process flag instead that would tell "this process is safe to keep running from timer point of view" and if that flag is not set, then assume it's OK to stop the process at any point?
Regards,
Tony
_______________________________________________
linux-pm mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/linux-pm
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 10 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
Here's a different example. A process is waiting for a keypress, but because it's badly written it's also drawing to the screen at 60 frames per second and preventing the system from every going to idle. How do you quiesce the system while still ensuring that the keypress will be delivered to the application?
I guess it depends. If it's a game and I'm waiting to hit the fire button, then I don't want the system to suspend!
Quoted 7 lines
It's starting to sound like you're really using suspend blocks to "certify" that the app is safe to keep running.
Maybe it could be done with some kind of process flag instead that would tell "this process is safe to keep running from timer point of view" and if that flag is not set, then assume it's OK to stop the process at any point?
How do you know to wake the process up in response to the keypress?
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 10 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
Here's a different example. A process is waiting for a keypress, but because it's badly written it's also drawing to the screen at 60 frames per second and preventing the system from every going to idle. How do you quiesce the system while still ensuring that the keypress will be delivered to the application?
I guess it depends. If it's a game and I'm waiting to hit the fire button, then I don't want the system to suspend!
Quoted 7 lines
It's starting to sound like you're really using suspend blocks to "certify" that the app is safe to keep running.
Maybe it could be done with some kind of process flag instead that would tell "this process is safe to keep running from timer point of view" and if that flag is not set, then assume it's OK to stop the process at any point?
How do you know to wake the process up in response to the keypress?
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 14 lines · Matthew Garrett
Quoted 13 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
Here's a different example. A process is waiting for a keypress, but because it's badly written it's also drawing to the screen at 60 frames per second and preventing the system from every going to idle. How do you quiesce the system while still ensuring that the keypress will be delivered to the application?
I guess it depends. If it's a game and I'm waiting to hit the fire button, then I don't want the system to suspend!
It's starting to sound like you're really using suspend blocks to "certify" that the app is safe to keep running.
Quoted 6 lines
Quoted 4 lines
Maybe it could be done with some kind of process flag instead that would tell "this process is safe to keep running from timer point of view" and if that flag is not set, then assume it's OK to stop the process at any point?
How do you know to wake the process up in response to the keypress?
Does it matter for processes that are not "certified"? Maybe you could assume that you can keep it stopped until the screen is on again, or some other policy.
Tony
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Matthew GarrettQuoted 14 lines · Matthew Garrett
Quoted 13 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
Here's a different example. A process is waiting for a keypress, but because it's badly written it's also drawing to the screen at 60 frames per second and preventing the system from every going to idle. How do you quiesce the system while still ensuring that the keypress will be delivered to the application?
I guess it depends. If it's a game and I'm waiting to hit the fire button, then I don't want the system to suspend!
It's starting to sound like you're really using suspend blocks to "certify" that the app is safe to keep running.
Quoted 6 lines
Quoted 4 lines
Maybe it could be done with some kind of process flag instead that would tell "this process is safe to keep running from timer point of view" and if that flag is not set, then assume it's OK to stop the process at any point?
How do you know to wake the process up in response to the keypress?
Does it matter for processes that are not "certified"? Maybe you could assume that you can keep it stopped until the screen is on again, or some other policy.
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 6 lines · Tony Lindgren
Quoted 1 line · Matthew Garrett
How do you know to wake the process up in response to the keypress?
Does it matter for processes that are not "certified"? Maybe you could assume that you can keep it stopped until the screen is on again, or some other policy.
Yes, it matters. You don't necessarily know whether to turn the screen on until the app has had an opportunity to process the event. This is exactly the kind of use case that suspend blocks are intended to allow, so alternatives that don't permit that kind of use case aren't really adequate alternatives.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 6 lines · Tony Lindgren
Quoted 1 line · Matthew Garrett
How do you know to wake the process up in response to the keypress?
Does it matter for processes that are not "certified"? Maybe you could assume that you can keep it stopped until the screen is on again, or some other policy.
Yes, it matters. You don't necessarily know whether to turn the screen on until the app has had an opportunity to process the event. This is exactly the kind of use case that suspend blocks are intended to allow, so alternatives that don't permit that kind of use case aren't really adequate alternatives.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 8 lines · Matthew Garrett
Quoted 6 lines · Tony Lindgren
Quoted 1 line · Matthew Garrett
How do you know to wake the process up in response to the keypress?
Does it matter for processes that are not "certified"? Maybe you could assume that you can keep it stopped until the screen is on again, or some other policy.
Quoted 5 lines
Yes, it matters. You don't necessarily know whether to turn the screen on until the app has had an opportunity to process the event. This is exactly the kind of use case that suspend blocks are intended to allow, so alternatives that don't permit that kind of use case aren't really adequate alternatives.
Hmm, I'm thinking there would not be any need to turn the screen on for the broken apps until some other event such as a tap on the screen triggers the need to turn the screen on.
If it's a critical app, then it should be fixed so it's safe to keep running.
And yeah, I guess you could cgroups to categorize "timer certified" and "broken" apps.
Regards,
Tony
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Matthew GarrettQuoted 8 lines · Matthew Garrett
Quoted 6 lines · Tony Lindgren
Quoted 1 line · Matthew Garrett
How do you know to wake the process up in response to the keypress?
Does it matter for processes that are not "certified"? Maybe you could assume that you can keep it stopped until the screen is on again, or some other policy.
Quoted 5 lines
Yes, it matters. You don't necessarily know whether to turn the screen on until the app has had an opportunity to process the event. This is exactly the kind of use case that suspend blocks are intended to allow, so alternatives that don't permit that kind of use case aren't really adequate alternatives.
Hmm, I'm thinking there would not be any need to turn the screen on for the broken apps until some other event such as a tap on the screen triggers the need to turn the screen on.
If it's a critical app, then it should be fixed so it's safe to keep running.
And yeah, I guess you could cgroups to categorize "timer certified" and "broken" apps.
Regards,
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 9 lines · Tony Lindgren
Hmm, I'm thinking there would not be any need to turn the screen on for the broken apps until some other event such as a tap on the screen triggers the need to turn the screen on.
If it's a critical app, then it should be fixed so it's safe to keep running.
And yeah, I guess you could cgroups to categorize "timer certified" and "broken" apps.
This is a perfectly valid model, but it's not one that matches Android.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 9 lines · Tony Lindgren
Hmm, I'm thinking there would not be any need to turn the screen on for the broken apps until some other event such as a tap on the screen triggers the need to turn the screen on.
If it's a critical app, then it should be fixed so it's safe to keep running.
And yeah, I guess you could cgroups to categorize "timer certified" and "broken" apps.
This is a perfectly valid model, but it's not one that matches Android.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
In reply to Matthew GarrettQuoted 5 lines · Matthew Garrett
Here's a different example. A process is waiting for a keypress, but because it's badly written it's also drawing to the screen at 60 frames per second and preventing the system from every going to idle. How do you quiesce the system while still ensuring that the keypress will be delivered to the application?
To me it's somewhat of a negative for suspend blockers. Since to solve the problem you give above you would have to use a suspend blocker in an asynchronous way (locked in an interrupt, released in a thread too) assuming I understand your example. I've had my share of semaphore nightmares, and I'm not too excited to see a protection scheme (i.e. a lock) which allows asynchronous usage like suspend blockers.
Daniel
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Matthew GarrettQuoted 5 lines · Matthew Garrett
Here's a different example. A process is waiting for a keypress, but because it's badly written it's also drawing to the screen at 60 frames per second and preventing the system from every going to idle. How do you quiesce the system while still ensuring that the keypress will be delivered to the application?
To me it's somewhat of a negative for suspend blockers. Since to solve the problem you give above you would have to use a suspend blocker in an asynchronous way (locked in an interrupt, released in a thread too) assuming I understand your example. I've had my share of semaphore nightmares, and I'm not too excited to see a protection scheme (i.e. a lock) which allows asynchronous usage like suspend blockers.
Daniel
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 8 lines · Daniel Walker
Quoted 5 lines · Matthew Garrett
Here's a different example. A process is waiting for a keypress, but because it's badly written it's also drawing to the screen at 60 frames per second and preventing the system from every going to idle. How do you quiesce the system while still ensuring that the keypress will be delivered to the application?
Quoted 7 lines
To me it's somewhat of a negative for suspend blockers. Since to solve the problem you give above you would have to use a suspend blocker in an asynchronous way (locked in an interrupt, released in a thread too) assuming I understand your example. I've had my share of semaphore nightmares, and I'm not too excited to see a protection scheme (i.e. a lock) which allows asynchronous usage like suspend blockers.
Why do you think this? The example in the documentation describe how we handle key events.
Signature · 1 line
Arve Hjønnevåg
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Daniel WalkerQuoted 8 lines · Daniel Walker
Quoted 5 lines · Matthew Garrett
Here's a different example. A process is waiting for a keypress, but because it's badly written it's also drawing to the screen at 60 frames per second and preventing the system from every going to idle. How do you quiesce the system while still ensuring that the keypress will be delivered to the application?
Quoted 7 lines
To me it's somewhat of a negative for suspend blockers. Since to solve the problem you give above you would have to use a suspend blocker in an asynchronous way (locked in an interrupt, released in a thread too) assuming I understand your example. I've had my share of semaphore nightmares, and I'm not too excited to see a protection scheme (i.e. a lock) which allows asynchronous usage like suspend blockers.
Why do you think this? The example in the documentation describe how we handle key events.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 17 lines · Arve Hjønnevåg
Quoted 8 lines · Daniel Walker
Quoted 5 lines · Matthew Garrett
Here's a different example. A process is waiting for a keypress, but because it's badly written it's also drawing to the screen at 60 frames per second and preventing the system from every going to idle. How do you quiesce the system while still ensuring that the keypress will be delivered to the application?
Quoted 7 lines
To me it's somewhat of a negative for suspend blockers. Since to solve the problem you give above you would have to use a suspend blocker in an asynchronous way (locked in an interrupt, released in a thread too) assuming I understand your example. I've had my share of semaphore nightmares, and I'm not too excited to see a protection scheme (i.e. a lock) which allows asynchronous usage like suspend blockers.
Quoted 2 lines
Why do you think this? The example in the documentation describe how we handle key events.
+- 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 leave the screen off, 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.
This? Isn't this asynchronous on the input-event-queue since it's taken in the interrupt , and release in the userspace thread?
Daniel
_______________________________________________
linux-pm mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/linux-pm
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Arve HjønnevågQuoted 17 lines · Arve Hjønnevåg
Quoted 8 lines · Daniel Walker
Quoted 5 lines · Matthew Garrett
Here's a different example. A process is waiting for a keypress, but because it's badly written it's also drawing to the screen at 60 frames per second and preventing the system from every going to idle. How do you quiesce the system while still ensuring that the keypress will be delivered to the application?
Quoted 7 lines
To me it's somewhat of a negative for suspend blockers. Since to solve the problem you give above you would have to use a suspend blocker in an asynchronous way (locked in an interrupt, released in a thread too) assuming I understand your example. I've had my share of semaphore nightmares, and I'm not too excited to see a protection scheme (i.e. a lock) which allows asynchronous usage like suspend blockers.
Quoted 2 lines
Why do you think this? The example in the documentation describe how we handle key events.
+- 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 leave the screen off, 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.
This? Isn't this asynchronous on the input-event-queue since it's taken in the interrupt , and release in the userspace thread?
Daniel
Re: [PATCH 1/8] PM: Add suspend block api.
In reply to Daniel WalkerQuoted 8 lines · Daniel Walker
Quoted 5 lines · Matthew Garrett
Here's a different example. A process is waiting for a keypress, but because it's badly written it's also drawing to the screen at 60 frames per second and preventing the system from every going to idle. How do you quiesce the system while still ensuring that the keypress will be delivered to the application?
Quoted 6 lines
To me it's somewhat of a negative for suspend blockers. Since to solve the problem you give above you would have to use a suspend blocker in an asynchronous way (locked in an interrupt, released in a thread too) assuming I understand your example. I've had my share of semaphore nightmares, and I'm not too excited to see a protection scheme (i.e. a lock) which allows asynchronous usage like suspend blockers.
Check the input patch for an example of this.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Daniel WalkerQuoted 8 lines · Daniel Walker
Quoted 5 lines · Matthew Garrett
Here's a different example. A process is waiting for a keypress, but because it's badly written it's also drawing to the screen at 60 frames per second and preventing the system from every going to idle. How do you quiesce the system while still ensuring that the keypress will be delivered to the application?
Quoted 6 lines
To me it's somewhat of a negative for suspend blockers. Since to solve the problem you give above you would have to use a suspend blocker in an asynchronous way (locked in an interrupt, released in a thread too) assuming I understand your example. I've had my share of semaphore nightmares, and I'm not too excited to see a protection scheme (i.e. a lock) which allows asynchronous usage like suspend blockers.
Check the input patch for an example of this.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 7 lines · Tony Lindgren
Well if your hardware runs off-while-idle or even just retention-while-idle, then the basic shell works just fine waking up every few seconds or so.
Then you could keep
init/shell/suspendpolicy deamon running until it's time to suspend the whole device. To cut down runaway timers, you could already freeze the desktop/GUI/whatever earlier.
This comes down mostly to efficiency. Although the suspend blocker patch does the actual suspending in a workqueue thread, AFAIK there's no reason it couldn't use a user thread instead.
The important difference lies in what happens when a suspend fails because a driver is busy. Without suspend blockers, the kernel has to go through the whole procedure of freezing userspace and kernel threads and then suspending a bunch of drivers before hitting the one that's busy. Then all that work has to be undone. By contrast, with suspend blockers the suspend attempt can fail right away with minimal overhead.
There's also a question of reliability. With suspends controlled by userspace there is a possibility of races, which could lead the system to suspend when it shouldn't. With control in the kernel, these races can be eliminated.
Alan Stern
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 7 lines · Tony Lindgren
Well if your hardware runs off-while-idle or even just retention-while-idle, then the basic shell works just fine waking up every few seconds or so.
Then you could keep
init/shell/suspendpolicy deamon running until it's time to suspend the whole device. To cut down runaway timers, you could already freeze the desktop/GUI/whatever earlier.
This comes down mostly to efficiency. Although the suspend blocker patch does the actual suspending in a workqueue thread, AFAIK there's no reason it couldn't use a user thread instead.
The important difference lies in what happens when a suspend fails because a driver is busy. Without suspend blockers, the kernel has to go through the whole procedure of freezing userspace and kernel threads and then suspending a bunch of drivers before hitting the one that's busy. Then all that work has to be undone. By contrast, with suspend blockers the suspend attempt can fail right away with minimal overhead.
There's also a question of reliability. With suspends controlled by userspace there is a possibility of races, which could lead the system to suspend when it shouldn't. With control in the kernel, these races can be eliminated.
Alan Stern
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 14 lines · Alan Stern
Quoted 7 lines · Tony Lindgren
Well if your hardware runs off-while-idle or even just retention-while-idle, then the basic shell works just fine waking up every few seconds or so.
Then you could keep
init/shell/suspendpolicy deamon running until it's time to suspend the whole device. To cut down runaway timers, you could already freeze the desktop/GUI/whatever earlier.This comes down mostly to efficiency. Although the suspend blocker patch does the actual suspending in a workqueue thread, AFAIK there's no reason it couldn't use a user thread instead.
Quoted 6 lines
The important difference lies in what happens when a suspend fails because a driver is busy. Without suspend blockers, the kernel has to go through the whole procedure of freezing userspace and kernel threads and then suspending a bunch of drivers before hitting the one that's busy. Then all that work has to be undone. By contrast, with suspend blockers the suspend attempt can fail right away with minimal overhead.
But does that really matter if you're only few tens of times times per day or so? I don't understand why you would want to try to suspend except after some timeout of no user or network activity.
Quoted 4 lines
There's also a question of reliability. With suspends controlled by userspace there is a possibility of races, which could lead the system to suspend when it shouldn't. With control in the kernel, these races can be eliminated.
I agree the suspend needs to happen without races. But I think the logic for when to suspend should be done in the userspace as it can be device or user specific.
Regards,
Tony
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Alan SternQuoted 14 lines · Alan Stern
Quoted 7 lines · Tony Lindgren
Well if your hardware runs off-while-idle or even just retention-while-idle, then the basic shell works just fine waking up every few seconds or so.
Then you could keep
init/shell/suspendpolicy deamon running until it's time to suspend the whole device. To cut down runaway timers, you could already freeze the desktop/GUI/whatever earlier.This comes down mostly to efficiency. Although the suspend blocker patch does the actual suspending in a workqueue thread, AFAIK there's no reason it couldn't use a user thread instead.
Quoted 6 lines
The important difference lies in what happens when a suspend fails because a driver is busy. Without suspend blockers, the kernel has to go through the whole procedure of freezing userspace and kernel threads and then suspending a bunch of drivers before hitting the one that's busy. Then all that work has to be undone. By contrast, with suspend blockers the suspend attempt can fail right away with minimal overhead.
But does that really matter if you're only few tens of times times per day or so? I don't understand why you would want to try to suspend except after some timeout of no user or network activity.
Quoted 4 lines
There's also a question of reliability. With suspends controlled by userspace there is a possibility of races, which could lead the system to suspend when it shouldn't. With control in the kernel, these races can be eliminated.
I agree the suspend needs to happen without races. But I think the logic for when to suspend should be done in the userspace as it can be device or user specific.
Regards,
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenHi!
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Why would you need to constantly try to suspend in that case?
Because otherwise you're awake for longer than you need to be.
If your system is idle and your hardware supports off-while-idle, then that really does not matter. There's not much of a difference in power savings, we're already talking over 10 days on batteries with just off-while-idle on omaps.
Makes me wish g1 was omap based... it looks like you have superior hw.
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenHi!
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Why would you need to constantly try to suspend in that case?
Because otherwise you're awake for longer than you need to be.
If your system is idle and your hardware supports off-while-idle, then that really does not matter. There's not much of a difference in power savings, we're already talking over 10 days on batteries with just off-while-idle on omaps.
Makes me wish g1 was omap based... it looks like you have superior hw.
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 4 lines · Pavel Machek
Hi!
Quoted 2 lines
Quoted 2 lines
Quoted 1 line
Why would you need to constantly try to suspend in that case?
Quoted 8 lines
Quoted 6 lines
Quoted 1 line
Because otherwise you're awake for longer than you need to be.
If your system is idle and your hardware supports off-while-idle, then that really does not matter. There's not much of a difference in power savings, we're already talking over 10 days on batteries with just off-while-idle on omaps.
Makes me wish g1 was omap based... it looks like you have superior hw.
G1 will happily do 10 days idle (radio on) under typical network conditions (roughly 4-5mA draw at the battery average in paging mode) if you have data disabled and there's no reason for it to wake up, process events, chat on the data network etc. It'll go 25-30 days in "airplane mode" (radio off) provided there are not excessive wakeups.
If you happen to be running a perfect userspace where every thread in every process is blocked on something, it'll hit the exact same power state out of idle. If you have a less optimal userspace or random third party nonoptimal apps, this becomes much harder, of course. Which is why we do the wakelock thing.
OMAP does have a lot of nice auto-clock-down features compared to some other SoCs, sometimes simplifying other parts of power management.
Brian
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Pavel MachekQuoted 4 lines · Pavel Machek
Hi!
Quoted 2 lines
Quoted 2 lines
Quoted 1 line
Why would you need to constantly try to suspend in that case?
Quoted 8 lines
Quoted 6 lines
Quoted 1 line
Because otherwise you're awake for longer than you need to be.
If your system is idle and your hardware supports off-while-idle, then that really does not matter. There's not much of a difference in power savings, we're already talking over 10 days on batteries with just off-while-idle on omaps.
Makes me wish g1 was omap based... it looks like you have superior hw.
G1 will happily do 10 days idle (radio on) under typical network conditions (roughly 4-5mA draw at the battery average in paging mode) if you have data disabled and there's no reason for it to wake up, process events, chat on the data network etc. It'll go 25-30 days in "airplane mode" (radio off) provided there are not excessive wakeups.
If you happen to be running a perfect userspace where every thread in every process is blocked on something, it'll hit the exact same power state out of idle. If you have a less optimal userspace or random third party nonoptimal apps, this becomes much harder, of course. Which is why we do the wakelock thing.
OMAP does have a lot of nice auto-clock-down features compared to some other SoCs, sometimes simplifying other parts of power management.
Brian
Re: [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 6 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
Or are you suspending constantly, tens of times per minute even if there's no user activity?
Quoted 6 lines
Quoted 2 lines
In this case you'd be repeatedly trying to suspend until the modem driver stopped blocking it. It's pretty much a waste.
But then the userspace knows you're getting data from the modem, and it can kick some inactivity timer that determines when to try to suspend next.
If the idle thread was doing the suspending then the inactivity timer by it's self could block suspend. As long as the idle thread was setup to check for timers. I'm sure that _isn't_ the point your trying to make. It just makes gobs more sense to me that the idle thread does the suspending .. Your idle, so depending on how long your idle then you suspend.
Daniel
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 6 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
Or are you suspending constantly, tens of times per minute even if there's no user activity?
Quoted 6 lines
Quoted 2 lines
In this case you'd be repeatedly trying to suspend until the modem driver stopped blocking it. It's pretty much a waste.
But then the userspace knows you're getting data from the modem, and it can kick some inactivity timer that determines when to try to suspend next.
If the idle thread was doing the suspending then the inactivity timer by it's self could block suspend. As long as the idle thread was setup to check for timers. I'm sure that _isn't_ the point your trying to make. It just makes gobs more sense to me that the idle thread does the suspending .. Your idle, so depending on how long your idle then you suspend.
Daniel
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 14 lines · Daniel Walker
Quoted 6 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
Or are you suspending constantly, tens of times per minute even if there's no user activity?
Quoted 6 lines
Quoted 2 lines
In this case you'd be repeatedly trying to suspend until the modem driver stopped blocking it. It's pretty much a waste.
But then the userspace knows you're getting data from the modem, and it can kick some inactivity timer that determines when to try to suspend next.
Quoted 6 lines
If the idle thread was doing the suspending then the inactivity timer by it's self could block suspend. As long as the idle thread was setup to check for timers. I'm sure that _isn't_ the point your trying to make. It just makes gobs more sense to me that the idle thread does the suspending .. Your idle, so depending on how long your idle then you suspend.
The alternative logic I'm suggesting is get the GUI into idle mode as soon as possible, then limp along with off-while-idle or retention-while-idle until some timer expires, then suspend the whole device.
Tony
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Daniel WalkerQuoted 14 lines · Daniel Walker
Quoted 6 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
Or are you suspending constantly, tens of times per minute even if there's no user activity?
Quoted 6 lines
Quoted 2 lines
In this case you'd be repeatedly trying to suspend until the modem driver stopped blocking it. It's pretty much a waste.
But then the userspace knows you're getting data from the modem, and it can kick some inactivity timer that determines when to try to suspend next.
Quoted 6 lines
If the idle thread was doing the suspending then the inactivity timer by it's self could block suspend. As long as the idle thread was setup to check for timers. I'm sure that _isn't_ the point your trying to make. It just makes gobs more sense to me that the idle thread does the suspending .. Your idle, so depending on how long your idle then you suspend.
The alternative logic I'm suggesting is get the GUI into idle mode as soon as possible, then limp along with off-while-idle or retention-while-idle until some timer expires, then suspend the whole device.
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 22 lines · Tony Lindgren
Quoted 14 lines · Daniel Walker
Quoted 6 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
Or are you suspending constantly, tens of times per minute even if there's no user activity?
Quoted 6 lines
Quoted 2 lines
In this case you'd be repeatedly trying to suspend until the modem driver stopped blocking it. It's pretty much a waste.
But then the userspace knows you're getting data from the modem, and it can kick some inactivity timer that determines when to try to suspend next.
Quoted 6 lines
If the idle thread was doing the suspending then the inactivity timer by it's self could block suspend. As long as the idle thread was setup to check for timers. I'm sure that _isn't_ the point your trying to make. It just makes gobs more sense to me that the idle thread does the suspending .. Your idle, so depending on how long your idle then you suspend.
Quoted 4 lines
The alternative logic I'm suggesting is get the GUI into idle mode as soon as possible, then limp along with off-while-idle or retention-while-idle until some timer expires, then suspend the whole device.
Could you elaborate on "off-while-idle" and "retention-while-idle" ? I'm not sure I follow what you mean.
Daniel
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 22 lines · Tony Lindgren
Quoted 14 lines · Daniel Walker
Quoted 6 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
Or are you suspending constantly, tens of times per minute even if there's no user activity?
Quoted 6 lines
Quoted 2 lines
In this case you'd be repeatedly trying to suspend until the modem driver stopped blocking it. It's pretty much a waste.
But then the userspace knows you're getting data from the modem, and it can kick some inactivity timer that determines when to try to suspend next.
Quoted 6 lines
If the idle thread was doing the suspending then the inactivity timer by it's self could block suspend. As long as the idle thread was setup to check for timers. I'm sure that _isn't_ the point your trying to make. It just makes gobs more sense to me that the idle thread does the suspending .. Your idle, so depending on how long your idle then you suspend.
Quoted 4 lines
The alternative logic I'm suggesting is get the GUI into idle mode as soon as possible, then limp along with off-while-idle or retention-while-idle until some timer expires, then suspend the whole device.
Could you elaborate on "off-while-idle" and "retention-while-idle" ? I'm not sure I follow what you mean.
Daniel
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 23 lines · Daniel Walker
Quoted 22 lines · Tony Lindgren
Quoted 20 lines · Daniel Walker
Quoted 6 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
Or are you suspending constantly, tens of times per minute even if there's no user activity?
Quoted 6 lines
Quoted 2 lines
In this case you'd be repeatedly trying to suspend until the modem driver stopped blocking it. It's pretty much a waste.
But then the userspace knows you're getting data from the modem, and it can kick some inactivity timer that determines when to try to suspend next.
If the idle thread was doing the suspending then the inactivity timer by it's self could block suspend. As long as the idle thread was setup to check for timers. I'm sure that _isn't_ the point your trying to make. It just makes gobs more sense to me that the idle thread does the suspending .. Your idle, so depending on how long your idle then you suspend.
Quoted 7 lines
Quoted 4 lines
The alternative logic I'm suggesting is get the GUI into idle mode as soon as possible, then limp along with off-while-idle or retention-while-idle until some timer expires, then suspend the whole device.
Could you elaborate on "off-while-idle" and "retention-while-idle" ? I'm not sure I follow what you mean.
Oh some SoC devices like omap hit retention or off modes in the idle loop. That brings down the idle consumption of a running system to minimal levels. It's basically the same as suspending the device in every idle loop.
The system wakes up every few seconds or so, but that already provides battery life of over ten days or so on an idle system. Of course the wakeup latencies are in milliseconds then.
Regards,
Tony
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Daniel WalkerQuoted 23 lines · Daniel Walker
Quoted 22 lines · Tony Lindgren
Quoted 20 lines · Daniel Walker
Quoted 6 lines · Tony Lindgren
Quoted 5 lines · Matthew Garrett
Quoted 2 lines · Tony Lindgren
Or are you suspending constantly, tens of times per minute even if there's no user activity?
Quoted 6 lines
Quoted 2 lines
In this case you'd be repeatedly trying to suspend until the modem driver stopped blocking it. It's pretty much a waste.
But then the userspace knows you're getting data from the modem, and it can kick some inactivity timer that determines when to try to suspend next.
If the idle thread was doing the suspending then the inactivity timer by it's self could block suspend. As long as the idle thread was setup to check for timers. I'm sure that _isn't_ the point your trying to make. It just makes gobs more sense to me that the idle thread does the suspending .. Your idle, so depending on how long your idle then you suspend.
Quoted 7 lines
Quoted 4 lines
The alternative logic I'm suggesting is get the GUI into idle mode as soon as possible, then limp along with off-while-idle or retention-while-idle until some timer expires, then suspend the whole device.
Could you elaborate on "off-while-idle" and "retention-while-idle" ? I'm not sure I follow what you mean.
Oh some SoC devices like omap hit retention or off modes in the idle loop. That brings down the idle consumption of a running system to minimal levels. It's basically the same as suspending the device in every idle loop.
The system wakes up every few seconds or so, but that already provides battery life of over ten days or so on an idle system. Of course the wakeup latencies are in milliseconds then.
Regards,
Tony
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 7 lines · Tony Lindgren
Oh some SoC devices like omap hit retention or off modes in the idle loop. That brings down the idle consumption of a running system to minimal levels. It's basically the same as suspending the device in every idle loop.
The system wakes up every few seconds or so, but that already provides battery life of over ten days or so on an idle system. Of course the wakeup latencies are in milliseconds then.
MSM doesn't have those power states unfortunately .. Your kind of suggesting what I was suggesting in that we should suspend in idle. Your hardware can do it easier tho since your have power states that are equal to suspend.
Daniel
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Tony LindgrenQuoted 7 lines · Tony Lindgren
Oh some SoC devices like omap hit retention or off modes in the idle loop. That brings down the idle consumption of a running system to minimal levels. It's basically the same as suspending the device in every idle loop.
The system wakes up every few seconds or so, but that already provides battery life of over ten days or so on an idle system. Of course the wakeup latencies are in milliseconds then.
MSM doesn't have those power states unfortunately .. Your kind of suggesting what I was suggesting in that we should suspend in idle. Your hardware can do it easier tho since your have power states that are equal to suspend.
Daniel
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 4 lines · Daniel Walker
MSM doesn't have those power states unfortunately .. Your kind of suggesting what I was suggesting in that we should suspend in idle. Your hardware can do it easier tho since your have power states that are equal to suspend.
If your wakeup latencies are sufficiently low and you have fine-grained enough control over your hardware then suspend in idle is a reasonable thing to do - but if you have a userspace app that's spinning then that doesn't solve the issue.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Daniel WalkerQuoted 4 lines · Daniel Walker
MSM doesn't have those power states unfortunately .. Your kind of suggesting what I was suggesting in that we should suspend in idle. Your hardware can do it easier tho since your have power states that are equal to suspend.
If your wakeup latencies are sufficiently low and you have fine-grained enough control over your hardware then suspend in idle is a reasonable thing to do - but if you have a userspace app that's spinning then that doesn't solve the issue.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 11 lines · Matthew Garrett
Quoted 4 lines · Daniel Walker
MSM doesn't have those power states unfortunately .. Your kind of suggesting what I was suggesting in that we should suspend in idle. Your hardware can do it easier tho since your have power states that are equal to suspend.
If your wakeup latencies are sufficiently low and you have fine-grained enough control over your hardware then suspend in idle is a reasonable thing to do - but if you have a userspace app that's spinning then that doesn't solve the issue.
If there's a userspace app spinning then you don't go idle (or that's my assumption anyway). You mean like repeatedly blocking and unblocking right?
Daniel
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Matthew GarrettQuoted 11 lines · Matthew Garrett
Quoted 4 lines · Daniel Walker
MSM doesn't have those power states unfortunately .. Your kind of suggesting what I was suggesting in that we should suspend in idle. Your hardware can do it easier tho since your have power states that are equal to suspend.
If your wakeup latencies are sufficiently low and you have fine-grained enough control over your hardware then suspend in idle is a reasonable thing to do - but if you have a userspace app that's spinning then that doesn't solve the issue.
If there's a userspace app spinning then you don't go idle (or that's my assumption anyway). You mean like repeatedly blocking and unblocking right?
Daniel
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 9 lines · Daniel Walker
Quoted 4 lines · Matthew Garrett
If your wakeup latencies are sufficiently low and you have fine-grained enough control over your hardware then suspend in idle is a reasonable thing to do - but if you have a userspace app that's spinning then that doesn't solve the issue.
If there's a userspace app spinning then you don't go idle (or that's my assumption anyway). You mean like repeatedly blocking and unblocking right?
Right, that's the problem. idle-based suspend works fine if your applications let the system go idle, but if your applications are anything other than absolutely perfect in this respect then you consume significant power even if the device is sitting unused in someone's pocket.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Daniel WalkerQuoted 9 lines · Daniel Walker
Quoted 4 lines · Matthew Garrett
If your wakeup latencies are sufficiently low and you have fine-grained enough control over your hardware then suspend in idle is a reasonable thing to do - but if you have a userspace app that's spinning then that doesn't solve the issue.
If there's a userspace app spinning then you don't go idle (or that's my assumption anyway). You mean like repeatedly blocking and unblocking right?
Right, that's the problem. idle-based suspend works fine if your applications let the system go idle, but if your applications are anything other than absolutely perfect in this respect then you consume significant power even if the device is sitting unused in someone's pocket.
Signature · 1 line
Matthew Garrett | [email protected]
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 11 lines · Matthew Garrett
Quoted 9 lines · Daniel Walker
Quoted 4 lines · Matthew Garrett
If your wakeup latencies are sufficiently low and you have fine-grained enough control over your hardware then suspend in idle is a reasonable thing to do - but if you have a userspace app that's spinning then that doesn't solve the issue.
If there's a userspace app spinning then you don't go idle (or that's my assumption anyway). You mean like repeatedly blocking and unblocking right?
Quoted 5 lines
Right, that's the problem. idle-based suspend works fine if your applications let the system go idle, but if your applications are anything other than absolutely perfect in this respect then you consume significant power even if the device is sitting unused in someone's pocket.
True .. I'd wonder how an OMAP based devices deal with that issue, since they would have that exact problem. According to what Tony is telling us. Actually a bogus userspace can do a lot more than just consume power you could hang the system too.
Daniel
Re: [linux-pm] [PATCH 1/8] PM: Add suspend block api.
In reply to Matthew GarrettQuoted 11 lines · Matthew Garrett
Quoted 9 lines · Daniel Walker
Quoted 4 lines · Matthew Garrett
If your wakeup latencies are sufficiently low and you have fine-grained enough control over your hardware then suspend in idle is a reasonable thing to do - but if you have a userspace app that's spinning then that doesn't solve the issue.
If there's a userspace app spinning then you don't go idle (or that's my assumption anyway). You mean like repeatedly blocking and unblocking right?
Quoted 5 lines
Right, that's the problem. idle-based suspend works fine if your applications let the system go idle, but if your applications are anything other than absolutely perfect in this respect then you consume significant power even if the device is sitting unused in someone's pocket.
True .. I'd wonder how an OMAP based devices deal with that issue, since they would have that exact problem. According to what Tony is telling us. Actually a bogus userspace can do a lot more than just consume power you could hang the system too.
Daniel
Re: [PATCH 1/8] PM: Add suspend block api.
Quoted 18 lines · Daniel Walker
Quoted 11 lines · Matthew Garrett
Quoted 9 lines · Daniel Walker
Quoted 4 lines · Matthew Garrett
If your wakeup latencies are sufficiently low and you have fine-grained enough control over your hardware then suspend in idle is a reasonable thing to do - but if you have a userspace app that's spinning then that doesn't solve the issue.
If there's a userspace app spinning then you don't go idle (or that's my assumption anyway). You mean like repeatedly blocking and unblocking right?
Quoted 5 lines
Right, that's the problem. idle-based suspend works fine if your applications let the system go idle, but if your applications are anything other than absolutely perfect in this respect then you consume significant power even if the device is sitting unused in someone's pocket.
Quoted 4 lines
True .. I'd wonder how an OMAP based devices deal with that issue, since they would have that exact problem. According to what Tony is telling us. Actually a bogus userspace can do a lot more than just consume power you could hang the system too.
There's nothing being done on omaps specifically, up to the device user space to deal with that. From the kernel point of view the omaps just run, and if idle enough, the device starts hitting the retention and off modes in idle. But the system keeps on running all the time, no need to suspend really.
I don't think there's a generic solution to the misbehaving apps. I know a lot of work has been done over past five years or so to minimize the timer usage in various apps. But if I installed some app that keeps the system busy, it would drain the battery.
I guess some apps could be just stopped when the screen blanks unless somehow certified for the timer usage or something similar..
Regards,
Tony