Suspend block api (version 4)
Subsystems (6)
cover Suspend block api (version 4)
This patch series adds a suspend-block api that provides the same functionality as the android wakelock api. The code is mostly the same as version 3 posted last year, but the main entry point has changed back to /sys/power/state with a new /sys/power/policy to alter its behavior. Timeout support is not included in this initial patchset.
--
Arve Hjønnevåg <[email protected]>
PATCH 1/9 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/suspend-blockers.txt | 97 +++++++++++++ include/linux/suspend_blocker.h | 60 ++++++++ kernel/power/Kconfig | 11 ++ kernel/power/Makefile | 1 + kernel/power/main.c | 84 +++++++++++- kernel/power/power.h | 5 + kernel/power/suspend.c | 4 +- kernel/power/suspend_blocker.c | 219 ++++++++++++++++++++++++++++++ 8 files changed, 477 insertions(+), 4 deletions(-) create mode 100644 Documentation/power/suspend-blockers.txt create mode 100755 include/linux/suspend_blocker.h create mode 100644 kernel/power/suspend_blocker.c
Documentation/power/suspend-blockers.txt new file +97 -0
@@ -0,0 +1,97 @@ +Suspend blockers +================ + +Suspend blockers provide a mechanism for device drivers and user-space processes +to prevent the system from entering suspend. By default writing to +/sys/power/state will ignore suspend blockers. Writing "opportunistic" to +/sys/power/policy will change the behaviour of /sys/power/state to repeatedly +enter the requested state when no suspend blockers are active. Writing "on" to +/sys/power/state will cancel the automatic sleep request. Suspend blockers do +not affect sleep states entered from idle. + +To use a suspend blocker, a device driver needs a struct suspend_blocker object +that has to be initialized with suspend_blocker_init. When no longer needed, +the suspend blocker must be destroyed with suspend_blocker_destroy. + +A suspend blocker is activated using suspend_block, which prevents the system +from entering suspend until the suspend blocker is deactivated with +suspend_unblock. Many suspend blockers may be used simultaneously, and the +system is prevented from entering suspend as long as at least one of them is +active. + +If the suspend operation has already started when calling suspend_block on a +suspend_blocker, it will abort the suspend operation as long it has not already +reached called suspend_ops->enter. This means that calling suspend_block from an +interrupt handler or a freezeable thread always works, but some or all drivers +may be temporarily suspended. + +In cell phones or other embedded systems where powering the screen is a +significant drain on the battery, suspend blockers can be used to allow +user-space to decide whether a keystroke received while the system is suspended +should cause the screen to be turned back on or allow the system to go back into +suspend. 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 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. + + Key pressed Key released + | | +keypad-scan ++++++++++++++++++ +input-event-queue +++ +++ +process-input-events +++ +++ + + +Driver API +========== + +A driver can use the suspend block api by adding a suspend_blocker variable to +its state and calling suspend_blocker_init. For instance: +struct state { + struct suspend_blocker suspend_blocker; +} + +init() { + suspend_blocker_init(&state->suspend_blocker, "suspend-blocker-name"); +} + +Before freeing the memory, suspend_blocker_destroy must be called: + +uninit() { + suspend_blocker_destroy(&state->suspend_blocker); +} + +When the driver determines that it needs to run (usually in an interrupt +handler) it calls suspend_block: + suspend_block(&state->suspend_blocker); + +When it no longer needs to run it calls suspend_unblock: + suspend_unblock(&state->suspend_blocker); + +Calling suspend_block when the suspend blocker is active or suspend_unblock when +it is not active has no effect. This allows drivers to update their state and +call suspend suspend_block or suspend_unblock based on the result. +For instance: + +if (list_empty(&state->pending_work)) + suspend_unblock(&state->suspend_blocker); +else + suspend_block(&state->suspend_blocker); +
include/linux/suspend_blocker.h new file +60 -0
60 lines not on this page · raw message
kernel/power/Kconfig +11 -0
@@ -130,6 +130,17 @@ config SUSPEND_FREEZER Turning OFF this setting is NOT recommended! If in doubt, say Y. +config SUSPEND_BLOCKERS + bool "Suspend blockers" + depends on PM + select RTC_LIB + default n + ---help--- + Suspend blocker support. Write "opportunistic" to /sys/power/policy + to enable suspend blockers. Then, when user space requests a sleep + state through /sys/power/state, the requested sleep state will be + entered when no suspend blockers are active. + 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_SUSPEND_BLOCKERS) += 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 +81 -3
132 lines not on this page · raw message
kernel/power/power.h +5 -0
@@ -236,3 +236,8 @@ 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); +
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 +219 -0
219 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/9 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/suspend-blockers.txt | 97 +++++++++++++ include/linux/suspend_blocker.h | 60 ++++++++ kernel/power/Kconfig | 11 ++ kernel/power/Makefile | 1 + kernel/power/main.c | 84 +++++++++++- kernel/power/power.h | 5 + kernel/power/suspend.c | 4 +- kernel/power/suspend_blocker.c | 219 ++++++++++++++++++++++++++++++ 8 files changed, 477 insertions(+), 4 deletions(-) create mode 100644 Documentation/power/suspend-blockers.txt create mode 100755 include/linux/suspend_blocker.h create mode 100644 kernel/power/suspend_blocker.c
Documentation/power/suspend-blockers.txt new file +97 -0
@@ -0,0 +1,97 @@ +Suspend blockers +================ + +Suspend blockers provide a mechanism for device drivers and user-space processes +to prevent the system from entering suspend. By default writing to +/sys/power/state will ignore suspend blockers. Writing "opportunistic" to +/sys/power/policy will change the behaviour of /sys/power/state to repeatedly +enter the requested state when no suspend blockers are active. Writing "on" to +/sys/power/state will cancel the automatic sleep request. Suspend blockers do +not affect sleep states entered from idle. + +To use a suspend blocker, a device driver needs a struct suspend_blocker object +that has to be initialized with suspend_blocker_init. When no longer needed, +the suspend blocker must be destroyed with suspend_blocker_destroy. + +A suspend blocker is activated using suspend_block, which prevents the system +from entering suspend until the suspend blocker is deactivated with +suspend_unblock. Many suspend blockers may be used simultaneously, and the +system is prevented from entering suspend as long as at least one of them is +active. + +If the suspend operation has already started when calling suspend_block on a +suspend_blocker, it will abort the suspend operation as long it has not already +reached called suspend_ops->enter. This means that calling suspend_block from an +interrupt handler or a freezeable thread always works, but some or all drivers +may be temporarily suspended. + +In cell phones or other embedded systems where powering the screen is a +significant drain on the battery, suspend blockers can be used to allow +user-space to decide whether a keystroke received while the system is suspended +should cause the screen to be turned back on or allow the system to go back into +suspend. 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 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. + + Key pressed Key released + | | +keypad-scan ++++++++++++++++++ +input-event-queue +++ +++ +process-input-events +++ +++ + + +Driver API +========== + +A driver can use the suspend block api by adding a suspend_blocker variable to +its state and calling suspend_blocker_init. For instance: +struct state { + struct suspend_blocker suspend_blocker; +} + +init() { + suspend_blocker_init(&state->suspend_blocker, "suspend-blocker-name"); +} + +Before freeing the memory, suspend_blocker_destroy must be called: + +uninit() { + suspend_blocker_destroy(&state->suspend_blocker); +} + +When the driver determines that it needs to run (usually in an interrupt +handler) it calls suspend_block: + suspend_block(&state->suspend_blocker); + +When it no longer needs to run it calls suspend_unblock: + suspend_unblock(&state->suspend_blocker); + +Calling suspend_block when the suspend blocker is active or suspend_unblock when +it is not active has no effect. This allows drivers to update their state and +call suspend suspend_block or suspend_unblock based on the result. +For instance: + +if (list_empty(&state->pending_work)) + suspend_unblock(&state->suspend_blocker); +else + suspend_block(&state->suspend_blocker); +
include/linux/suspend_blocker.h new file +60 -0
60 lines not on this page · raw message
kernel/power/Kconfig +11 -0
@@ -130,6 +130,17 @@ config SUSPEND_FREEZER Turning OFF this setting is NOT recommended! If in doubt, say Y. +config SUSPEND_BLOCKERS + bool "Suspend blockers" + depends on PM + select RTC_LIB + default n + ---help--- + Suspend blocker support. Write "opportunistic" to /sys/power/policy + to enable suspend blockers. Then, when user space requests a sleep + state through /sys/power/state, the requested sleep state will be + entered when no suspend blockers are active. + 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_SUSPEND_BLOCKERS) += 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 +81 -3
132 lines not on this page · raw message
kernel/power/power.h +5 -0
@@ -236,3 +236,8 @@ 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); +
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 +219 -0
219 lines not on this page · raw message
Signature · 1 line
1.6.5.1
PATCH 2/9 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/power/suspend-blockers.txt | 17 ++++ include/linux/suspend_block_dev.h | 25 ++++++ kernel/power/Kconfig | 9 ++ kernel/power/Makefile | 1 + kernel/power/user_suspend_blocker.c | 128 ++++++++++++++++++++++++++++++ 5 files changed, 180 insertions(+), 0 deletions(-) create mode 100644 include/linux/suspend_block_dev.h create mode 100644 kernel/power/user_suspend_blocker.c
Documentation/power/suspend-blockers.txt +17 -0
@@ -95,3 +95,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
@@ -141,6 +141,15 @@ config SUSPEND_BLOCKERS state through /sys/power/state, the requested sleep state will be entered when no suspend blockers are active. +config USER_SUSPEND_BLOCKERS + bool "Userspace suspend blockers" + depends on SUSPEND_BLOCKERS + 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_SUSPEND_BLOCKERS) += 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/9 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 3/9 PM: suspend_block: Abort task freezing if a suspend_blocker is active.
In reply to Arve HjønnevågIf 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 · 1 line
1.6.5.1
PATCH 4/9 PM: suspend_block: Switch to list of active and inactive suspend blockers
This allows active suspend blockers to be listed
--- include/linux/suspend_blocker.h | 6 ++- kernel/power/suspend_blocker.c | 85 +++++++++++++++++++++++++++----------- 2 files changed, 65 insertions(+), 26 deletions(-)
include/linux/suspend_blocker.h +5 -1
@@ -16,8 +16,11 @@#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. *
@@ -29,7 +32,8 @@struct suspend_blocker {#ifdef CONFIG_SUSPEND_BLOCKERS -atomic_t flags; +struct list_head link; +int flags;const char *name;#endif };
kernel/power/suspend_blocker.c +60 -25
162 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 4/9 PM: suspend_block: Switch to list of active and inactive suspend blockers
In reply to Arve HjønnevågThis allows active suspend blockers to be listed
--- include/linux/suspend_blocker.h | 6 ++- kernel/power/suspend_blocker.c | 85 +++++++++++++++++++++++++++----------- 2 files changed, 65 insertions(+), 26 deletions(-)
include/linux/suspend_blocker.h +5 -1
@@ -16,8 +16,11 @@#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. *
@@ -29,7 +32,8 @@struct suspend_blocker {#ifdef CONFIG_SUSPEND_BLOCKERS -atomic_t flags; +struct list_head link; +int flags;const char *name;#endif };
kernel/power/suspend_blocker.c +60 -25
162 lines not on this page · raw message
Signature · 1 line
1.6.5.1
PATCH 5/9 PM: suspend_block: Add debugfs file
Report active and inactive suspend blockers in/sys/kernel/debug/suspend_blockers.
--- kernel/power/suspend_blocker.c | 44 ++++++++++++++++++++++++++++++++++++++- 1 files changed, 42 insertions(+), 2 deletions(-)
kernel/power/suspend_blocker.c +42 -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" enum {
@@ -41,6 +42,7 @@ struct workqueue_struct *suspend_work_queue;struct suspend_blocker main_suspend_blocker;static suspend_state_t requested_suspend_state =PM_SUSPEND_MEM ;static bool enable_suspend_blockers; +static struct dentry *suspend_blocker_stats_dentry; #define pr_info_time(fmt, args...) \ do { \
@@ -54,6 +56,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;
@@ -101,8 +118,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. */
@@ -240,6 +257,19 @@ 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, +}; +static int __init suspend_block_init (void ) { suspend_work_queue =create_singlethread_workqueue ("suspend" );
@@ -251,4 +281,14 @@ static int __init suspend_block_init(void)return 0 ; } +static int __init suspend_block_postcore_init (void ) +{ +if (!suspend_work_queue) +return 0 ; + suspend_blocker_stats_dentry =debugfs_create_file ("suspend_blockers" , +S_IRUGO ,NULL ,NULL , &suspend_blocker_stats_fops); +return 0 ; +} +core_initcall (suspend_block_init); +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 6/9 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 | 6 +- kernel/power/suspend.c | 4 +- kernel/power/suspend_blocker.c | 190 +++++++++++++++++++++++++++++++++++++-- 5 files changed, 218 insertions(+), 10 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 * 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
@@ -141,6 +141,13 @@ config SUSPEND_BLOCKERS state through /sys/power/state, the requested sleep state will be entered when no suspend blockers are active. +config SUSPEND_BLOCKER_STATS + bool "Suspend block stats" + depends on SUSPEND_BLOCKERS + default y + ---help--- + Report suspend block stats in /sys/kernel/debug/suspend_blockers + config USER_SUSPEND_BLOCKERS bool "Userspace suspend blockers" depends on SUSPEND_BLOCKERS
kernel/power/power.h +5 -1
@@ -240,4 +240,8 @@ static inline void suspend_thaw_processes(void)/* 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_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
265 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/9 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.
--- include/linux/workqueue.h | 45 ++++++++++++++++++++++++++++++++++++++++++++- kernel/workqueue.c | 19 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletions(-)
include/linux/workqueue.h +44 -1
@@ -9,6 +9,7 @@#include <linux/linkage.h> #include <linux/bitops.h> #include <linux/lockdep.h> +#include <linux/suspend_blocker.h> #include <asm/atomic.h> struct workqueue_struct ;
@@ -26,7 +27,8 @@ struct work_struct {atomic_long_t data;#define WORK_STRUCT_PENDING 0/* T if work item pending execution */ #define WORK_STRUCT_STATIC 1/* static initializer (debugobjects) */ -#define WORK_STRUCT_FLAG_MASK (3UL) +#define WORK_STRUCT_SUSPEND_BLOCKING 2/* suspend blocking work */ +#define WORK_STRUCT_FLAG_MASK (7UL)#define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK)struct list_head entry;work_func_t func;
@@ -48,6 +50,23 @@ static inline struct delayed_work *to_delayed_work(struct work_struct *work) return container_of(work, struct delayed_work, work); } +struct suspend_blocking_work { +struct work_struct work; +struct suspend_blocker suspend_blocker; +}; + +static inline struct suspend_blocking_work * +to_suspend_blocking_work (struct work_struct *work) +{ + return container_of(work, struct suspend_blocking_work, work); +} + +static inline struct suspend_blocker * +work_to_suspend_blocker (struct work_struct *work) +{ +return &to_suspend_blocking_work (work)->suspend_blocker; +} +struct execute_work {struct work_struct work; };
@@ -157,6 +176,30 @@ static inline void destroy_work_on_stack(struct work_struct *work) { }init_timer_deferrable (&(_work)->timer); \ }while (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); +suspend_blocker_init (&work->suspend_blocker, name); +set_bit (WORK_STRUCT_SUSPEND_BLOCKING ,work_data_bits (&work->work)); +} + +/** +* suspend_blocking_work_destroy - Destroy suspend_blocking_work +* @work: The work item in question +* +* If the work was ever queued on more then one workqueue or on a multithreaded +* workqueue all these workqueues must be flushed before calling +* suspend_blocking_work_destroy. If only a single singlethreaded workqueue +* was used flush_work or cancel_work_sync can be used instead. +*/ + +static inline void +suspend_blocking_work_destroy (struct suspend_blocking_work *work) +{ +suspend_blocker_destroy (&work->suspend_blocker); +} +/** * work_pending - Find out whether a work item is currently pending * @work: The work item in question
kernel/workqueue.c +19 -0
@@ -68,6 +68,15 @@ struct workqueue_struct {#endif }; +static inline int work_blocks_suspend (struct work_struct *work) +{ +#ifdef CONFIG_SUSPEND_BLOCKERS +return test_bit (WORK_STRUCT_SUSPEND_BLOCKING ,work_data_bits (work)); +#else +return false; +#endif +} +#ifdef CONFIG_DEBUG_OBJECTS_WORK static struct debug_obj_descr work_debug_descr;
@@ -257,6 +266,10 @@ static void __queue_work(struct cpu_workqueue_struct *cwq,debug_work_activate (work);spin_lock_irqsave (&cwq->lock, flags); + +if (work_blocks_suspend (work)) +suspend_block (work_to_suspend_blocker (work)); +insert_work (cwq, work, &cwq->worklist);spin_unlock_irqrestore (&cwq->lock, flags); }
@@ -379,6 +392,7 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq)struct work_struct *work =list_entry (cwq->worklist.next, struct work_struct, entry);work_func_t f = work->func; +bool current_work_blocks_suspend =work_blocks_suspend (work);#ifdef CONFIG_LOCKDEP /* * It is permissible to free the struct work_struct
@@ -416,6 +430,9 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq) }spin_lock_irq (&cwq->lock); +if (current_work_blocks_suspend && + (get_wq_data (work) == cwq) && !work_pending (work)) +suspend_unblock (work_to_suspend_blocker (work)); cwq->current_work =NULL ; }spin_unlock_irq (&cwq->lock);
@@ -671,6 +688,8 @@ static int __cancel_work_timer(struct work_struct *work,wait_on_work (work); }while (unlikely (ret <0 )); +if (work_blocks_suspend (work)) +suspend_unblock (work_to_suspend_blocker (work));work_clear_pending (work);return ret; }
Signature · 6 lines
1.6.5.1 _______________________________________________ linux-pm mailing list [email protected] https://lists.linux-foundation.org/mailman/listinfo/linux-pm
PATCH 7/9 PM: Add suspend blocking work.
In reply to Arve HjønnevågAllow 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.
--- include/linux/workqueue.h | 45 ++++++++++++++++++++++++++++++++++++++++++++- kernel/workqueue.c | 19 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletions(-)
include/linux/workqueue.h +44 -1
@@ -9,6 +9,7 @@#include <linux/linkage.h> #include <linux/bitops.h> #include <linux/lockdep.h> +#include <linux/suspend_blocker.h> #include <asm/atomic.h> struct workqueue_struct ;
@@ -26,7 +27,8 @@ struct work_struct {atomic_long_t data;#define WORK_STRUCT_PENDING 0/* T if work item pending execution */ #define WORK_STRUCT_STATIC 1/* static initializer (debugobjects) */ -#define WORK_STRUCT_FLAG_MASK (3UL) +#define WORK_STRUCT_SUSPEND_BLOCKING 2/* suspend blocking work */ +#define WORK_STRUCT_FLAG_MASK (7UL)#define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK)struct list_head entry;work_func_t func;
@@ -48,6 +50,23 @@ static inline struct delayed_work *to_delayed_work(struct work_struct *work) return container_of(work, struct delayed_work, work); } +struct suspend_blocking_work { +struct work_struct work; +struct suspend_blocker suspend_blocker; +}; + +static inline struct suspend_blocking_work * +to_suspend_blocking_work (struct work_struct *work) +{ + return container_of(work, struct suspend_blocking_work, work); +} + +static inline struct suspend_blocker * +work_to_suspend_blocker (struct work_struct *work) +{ +return &to_suspend_blocking_work (work)->suspend_blocker; +} +struct execute_work {struct work_struct work; };
@@ -157,6 +176,30 @@ static inline void destroy_work_on_stack(struct work_struct *work) { }init_timer_deferrable (&(_work)->timer); \ }while (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); +suspend_blocker_init (&work->suspend_blocker, name); +set_bit (WORK_STRUCT_SUSPEND_BLOCKING ,work_data_bits (&work->work)); +} + +/** +* suspend_blocking_work_destroy - Destroy suspend_blocking_work +* @work: The work item in question +* +* If the work was ever queued on more then one workqueue or on a multithreaded +* workqueue all these workqueues must be flushed before calling +* suspend_blocking_work_destroy. If only a single singlethreaded workqueue +* was used flush_work or cancel_work_sync can be used instead. +*/ + +static inline void +suspend_blocking_work_destroy (struct suspend_blocking_work *work) +{ +suspend_blocker_destroy (&work->suspend_blocker); +} +/** * work_pending - Find out whether a work item is currently pending * @work: The work item in question
kernel/workqueue.c +19 -0
@@ -68,6 +68,15 @@ struct workqueue_struct {#endif }; +static inline int work_blocks_suspend (struct work_struct *work) +{ +#ifdef CONFIG_SUSPEND_BLOCKERS +return test_bit (WORK_STRUCT_SUSPEND_BLOCKING ,work_data_bits (work)); +#else +return false; +#endif +} +#ifdef CONFIG_DEBUG_OBJECTS_WORK static struct debug_obj_descr work_debug_descr;
@@ -257,6 +266,10 @@ static void __queue_work(struct cpu_workqueue_struct *cwq,debug_work_activate (work);spin_lock_irqsave (&cwq->lock, flags); + +if (work_blocks_suspend (work)) +suspend_block (work_to_suspend_blocker (work)); +insert_work (cwq, work, &cwq->worklist);spin_unlock_irqrestore (&cwq->lock, flags); }
@@ -379,6 +392,7 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq)struct work_struct *work =list_entry (cwq->worklist.next, struct work_struct, entry);work_func_t f = work->func; +bool current_work_blocks_suspend =work_blocks_suspend (work);#ifdef CONFIG_LOCKDEP /* * It is permissible to free the struct work_struct
@@ -416,6 +430,9 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq) }spin_lock_irq (&cwq->lock); +if (current_work_blocks_suspend && + (get_wq_data (work) == cwq) && !work_pending (work)) +suspend_unblock (work_to_suspend_blocker (work)); cwq->current_work =NULL ; }spin_unlock_irq (&cwq->lock);
@@ -671,6 +688,8 @@ static int __cancel_work_timer(struct work_struct *work,wait_on_work (work); }while (unlikely (ret <0 )); +if (work_blocks_suspend (work)) +suspend_unblock (work_to_suspend_blocker (work));work_clear_pending (work);return ret; }
Signature · 1 line
1.6.5.1
PATCH 8/9 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 9/9 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 | 2 +- 2 files changed, 7 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_work (&psy->changed_work.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 +1 -1
@@ -152,7 +152,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 9/9 power_supply: Block suspend while power supply change notifications are pending
In reply to Arve HjønnevågWhen 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 | 2 +- 2 files changed, 7 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_work (&psy->changed_work.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 +1 -1
@@ -152,7 +152,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 · 1 line
1.6.5.1
Re: [PATCH 8/9] Input: Block suspend while event queue is not empty.
In reply to Arve HjønnevågQuoted 3 lines · On Thu, 22 Apr 2010 18:08:57 -0700 Arve Hjønnevåg wrote:
Add an ioctl, EVIOCSSUSPENDBLOCK, to enable a
suspend_blockerthat 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.
All new ioctls need to be added to Documentation/ioctl/ioctl-number.txt, please.
Quoted 36 lines
Signed-off-by Arve Hjønnevåg <[email protected]>--- drivers/input/evdev.c | 22 ++++++++++++++++++++++ include/linux/input.h | 3 +++ 2 files changed, 25 insertions(+), 0 deletions(-)drivers/input/evdev.c +13
-0@@ -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 +0
-0
include/linux/input.h struct input_absinfo { · line 90
Quoted 9 lines
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 */
thanks,
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
Dmitry Torokhov
maintainerRe: [PATCH 8/9] Input: Block suspend while event queue is not empty.
Quoted 7 lines · Randy Dunlap
Quoted 3 lines · On Thu, 22 Apr 2010 18:08:57 -0700 Arve Hjønnevåg wrote:
Add an ioctl, EVIOCSSUSPENDBLOCK, to enable a
suspend_blockerthat 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.All new ioctls need to be added to
Documentation/ioctl/ioctl-number.txt, please.
I do not see the reason for it to be in the kernel still. Have a process that listens to all input devices (or subset of them), once events stop coming initiate suspend.
Quoted 36 lines
Quoted 36 lines
Signed-off-by Arve Hjønnevåg <[email protected]>---
drivers/input/evdev.c | 22 ++++++++++++++++++++++ include/linux/input.h | 3 +++ 2 files changed, 25 insertions(+), 0 deletions(-)drivers/input/evdev.c +13
-0@@ -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 ; +drivers/input/evdev.c +0
-0default :if (_IOC_TYPE (cmd) !='E' )
Quoted 7 lines
include/linux/input.h struct input_absinfo { · line 83
Quoted 7 lines
include/linux/input.h +0
-0@@ -82,6 +82,9 @@ struct input_absinfo {#define EVIOCGRAB _IOW('E', 0x90, int)/* Grab/Release
device */
Quoted 2 lines
include/linux/input.h struct input_absinfo { · line 84
Quoted 2 lines
include/linux/input.h +1
-0+#define EVIOCGSUSPENDBLOCK _IOR('E', 0x91, int)/* get
suspend block
Quoted 1 line
Quoted 1 line
enable */ +#define EVIOCSSUSPENDBLOCK
_IOW('E', 0x91, int)/*
set
Quoted 16 lines
Quoted 6 lines
suspend block enable */ +
/*
* Event types
*/thanks,
---
~Randy
*** Remember to useDocumentation/SubmitChecklistwhen testing your code *** --
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Signature · 1 line
Dmitry
Dmitry Torokhov
maintainerRe: [PATCH 8/9] Input: Block suspend while event queue is not empty.
In reply to Randy DunlapQuoted 7 lines · Randy Dunlap
Quoted 3 lines · On Thu, 22 Apr 2010 18:08:57 -0700 Arve Hjønnevåg wrote:
Add an ioctl, EVIOCSSUSPENDBLOCK, to enable a
suspend_blockerthat 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.All new ioctls need to be added to
Documentation/ioctl/ioctl-number.txt, please.
I do not see the reason for it to be in the kernel still. Have a process that listens to all input devices (or subset of them), once events stop coming initiate suspend.
Quoted 36 lines
Quoted 36 lines
Signed-off-by Arve Hjønnevåg <[email protected]>---
drivers/input/evdev.c | 22 ++++++++++++++++++++++ include/linux/input.h | 3 +++ 2 files changed, 25 insertions(+), 0 deletions(-)drivers/input/evdev.c +13
-0@@ -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 ; +drivers/input/evdev.c +0
-0default :if (_IOC_TYPE (cmd) !='E' )
Quoted 7 lines
include/linux/input.h struct input_absinfo { · line 83
Quoted 7 lines
include/linux/input.h +0
-0@@ -82,6 +82,9 @@ struct input_absinfo {#define EVIOCGRAB _IOW('E', 0x90, int)/* Grab/Release
device */
Quoted 2 lines
include/linux/input.h struct input_absinfo { · line 84
Quoted 2 lines
include/linux/input.h +1
-0+#define EVIOCGSUSPENDBLOCK _IOR('E', 0x91, int)/* get
suspend block
Quoted 1 line
Quoted 1 line
enable */ +#define EVIOCSSUSPENDBLOCK
_IOW('E', 0x91, int)/*
set
Quoted 16 lines
Quoted 6 lines
suspend block enable */ +
/*
* Event types
*/thanks,
---
~Randy
*** Remember to useDocumentation/SubmitChecklistwhen testing your code *** --
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Signature · 5 lines
Dmitry -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 8/9] Input: Block suspend while event queue is not empty.
Quoted 6 lines · Dmitry Torokhov
Quoted 5 lines · Randy Dunlap
Quoted 3 lines · On Thu, 22 Apr 2010 18:08:57 -0700 Arve Hjønnevåg wrote:
Add an ioctl, EVIOCSSUSPENDBLOCK, to enable a
suspend_blockerthat 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.
Quoted 7 lines
Quoted 2 lines
All new ioctls need to be added to
Documentation/ioctl/ioctl-number.txt, please.I do not see the reason for it to be in the kernel still. Have a process that listens to all input devices (or subset of them), once events stop coming initiate suspend.
I think the document added by the first patch explains this. The solution you propose above will ignore a wakeup key pressed right after user space decides to initiate suspend.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 8/9] Input: Block suspend while event queue is not empty.
In reply to Dmitry TorokhovQuoted 6 lines · Dmitry Torokhov
Quoted 5 lines · Randy Dunlap
Quoted 3 lines · On Thu, 22 Apr 2010 18:08:57 -0700 Arve Hjønnevåg wrote:
Add an ioctl, EVIOCSSUSPENDBLOCK, to enable a
suspend_blockerthat 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.
Quoted 7 lines
Quoted 2 lines
All new ioctls need to be added to
Documentation/ioctl/ioctl-number.txt, please.I do not see the reason for it to be in the kernel still. Have a process that listens to all input devices (or subset of them), once events stop coming initiate suspend.
I think the document added by the first patch explains this. The solution you propose above will ignore a wakeup key pressed right after user space decides to initiate suspend.
Signature · 5 lines
Arve Hjønnevåg -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 8/9] Input: Block suspend while event queue is not empty.
Quoted 11 lines · Arve Hjønnevåg
Quoted 9 lines · Dmitry Torokhov
Quoted 7 lines · Randy Dunlap
Quoted 3 lines · On Thu, 22 Apr 2010 18:08:57 -0700 Arve Hjønnevåg wrote:
Add an ioctl, EVIOCSSUSPENDBLOCK, to enable a
suspend_blockerthat 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.All new ioctls need to be added to
Documentation/ioctl/ioctl-number.txt, please.
Quoted 8 lines
Quoted 4 lines
I do not see the reason for it to be in the kernel still. Have a process that listens to all input devices (or subset of them), once events stop coming initiate suspend.
I think the document added by the first patch explains this. The solution you propose above will ignore a wakeup key pressed right after user space decides to initiate suspend.
Is there some reason why this feature needs to be enabled by an ioctl? Why not make this suspend blocker permanently enabled?
Alan Stern
Re: [linux-pm] [PATCH 8/9] Input: Block suspend while event queue is not empty.
In reply to Arve HjønnevågQuoted 11 lines · Arve Hjønnevåg
Quoted 9 lines · Dmitry Torokhov
Quoted 7 lines · Randy Dunlap
Quoted 3 lines · On Thu, 22 Apr 2010 18:08:57 -0700 Arve Hjønnevåg wrote:
Add an ioctl, EVIOCSSUSPENDBLOCK, to enable a
suspend_blockerthat 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.All new ioctls need to be added to
Documentation/ioctl/ioctl-number.txt, please.
Quoted 8 lines
Quoted 4 lines
I do not see the reason for it to be in the kernel still. Have a process that listens to all input devices (or subset of them), once events stop coming initiate suspend.
I think the document added by the first patch explains this. The solution you propose above will ignore a wakeup key pressed right after user space decides to initiate suspend.
Is there some reason why this feature needs to be enabled by an ioctl? Why not make this suspend blocker permanently enabled?
Alan Stern
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 8/9] Input: Block suspend while event queue is not empty.
Quoted 10 lines · Alan Stern
Quoted 8 lines · Arve Hjønnevåg
Quoted 6 lines · Dmitry Torokhov
Quoted 5 lines · Randy Dunlap
Quoted 3 lines · On Thu, 22 Apr 2010 18:08:57 -0700 Arve Hjønnevåg wrote:
Add an ioctl, EVIOCSSUSPENDBLOCK, to enable a
suspend_blockerthat 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.
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 2 lines
All new ioctls need to be added to
Documentation/ioctl/ioctl-number.txt, please.I do not see the reason for it to be in the kernel still. Have a process that listens to all input devices (or subset of them), once events stop coming initiate suspend.
This solution is not practical with the Android user space AFAICT.
Quoted 6 lines
Quoted 3 lines
I think the document added by the first patch explains this. The solution you propose above will ignore a wakeup key pressed right after user space decides to initiate suspend.
Is there some reason why this feature needs to be enabled by an ioctl? Why not make this suspend blocker permanently enabled?
The ioctl is there so that user space can use suspend blockers, which is needed because only user space know that some activities are going to continue and therefore the system should not be suspended (like playing music "in the background").
Quoted 1 line
From all of the interfaces that could be used for this purpose ioctl appears to
be the most convenient (we need something that is per process and allows us to carry out four operations: creat, destroy, activate, deactivate).
Rafael
Re: [linux-pm] [PATCH 8/9] Input: Block suspend while event queue is not empty.
In reply to Alan SternQuoted 10 lines · Alan Stern
Quoted 8 lines · Arve Hjønnevåg
Quoted 6 lines · Dmitry Torokhov
Quoted 5 lines · Randy Dunlap
Quoted 3 lines · On Thu, 22 Apr 2010 18:08:57 -0700 Arve Hjønnevåg wrote:
Add an ioctl, EVIOCSSUSPENDBLOCK, to enable a
suspend_blockerthat 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.
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 2 lines
All new ioctls need to be added to
Documentation/ioctl/ioctl-number.txt, please.I do not see the reason for it to be in the kernel still. Have a process that listens to all input devices (or subset of them), once events stop coming initiate suspend.
This solution is not practical with the Android user space AFAICT.
Quoted 6 lines
Quoted 3 lines
I think the document added by the first patch explains this. The solution you propose above will ignore a wakeup key pressed right after user space decides to initiate suspend.
Is there some reason why this feature needs to be enabled by an ioctl? Why not make this suspend blocker permanently enabled?
The ioctl is there so that user space can use suspend blockers, which is needed because only user space know that some activities are going to continue and therefore the system should not be suspended (like playing music "in the background").
From all of the interfaces that could be used for this purpose ioctl appears to be the most convenient (we need something that is per process and allows us to carry out four operations: creat, destroy, activate, deactivate).
Rafael
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 8/9] Input: Block suspend while event queue is not empty.
Quoted 11 lines · Rafael J. Wysocki
Quoted 9 lines · Alan Stern
Quoted 7 lines · Arve Hjønnevåg
Quoted 5 lines · Dmitry Torokhov
Quoted 4 lines · Randy Dunlap
Quoted 3 lines · On Thu, 22 Apr 2010 18:08:57 -0700 Arve Hjønnevåg wrote:
Add an ioctl, EVIOCSSUSPENDBLOCK, to enable a
suspend_blockerthat 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.
Quoted 7 lines
Quoted 2 lines
Is there some reason why this feature needs to be enabled by an ioctl? Why not make this suspend blocker permanently enabled?
The ioctl is there so that user space can use suspend blockers, which is needed because only user space know that some activities are going to continue and therefore the system should not be suspended (like playing music "in the background").
No, you're thinking of a different ioctl: SUSPEND_BLOCKER_IOCTL_BLOCK. This one (EVIOCSSUSPENDBLOCK) is present _only_ to enable one specific suspend blocker, which is activated when the input event queue is non-empty. I don't see any reason why it shouldn't be enabled all the time.
Alan Stern
Re: [linux-pm] [PATCH 8/9] Input: Block suspend while event queue is not empty.
In reply to Rafael J. WysockiQuoted 11 lines · Rafael J. Wysocki
Quoted 9 lines · Alan Stern
Quoted 7 lines · Arve Hjønnevåg
Quoted 5 lines · Dmitry Torokhov
Quoted 4 lines · Randy Dunlap
Quoted 3 lines · On Thu, 22 Apr 2010 18:08:57 -0700 Arve Hjønnevåg wrote:
Add an ioctl, EVIOCSSUSPENDBLOCK, to enable a
suspend_blockerthat 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.
Quoted 7 lines
Quoted 2 lines
Is there some reason why this feature needs to be enabled by an ioctl? Why not make this suspend blocker permanently enabled?
The ioctl is there so that user space can use suspend blockers, which is needed because only user space know that some activities are going to continue and therefore the system should not be suspended (like playing music "in the background").
No, you're thinking of a different ioctl: SUSPEND_BLOCKER_IOCTL_BLOCK. This one (EVIOCSSUSPENDBLOCK) is present _only_ to enable one specific suspend blocker, which is activated when the input event queue is non-empty. I don't see any reason why it shouldn't be enabled all the time.
Alan Stern
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 8/9] Input: Block suspend while event queue is not empty.
Quoted 21 lines · Alan Stern
Quoted 11 lines · Rafael J. Wysocki
Quoted 9 lines · Alan Stern
Quoted 7 lines · Arve Hjønnevåg
Quoted 5 lines · Dmitry Torokhov
Quoted 4 lines · Randy Dunlap
Quoted 3 lines · On Thu, 22 Apr 2010 18:08:57 -0700 Arve Hjønnevåg wrote:
Add an ioctl, EVIOCSSUSPENDBLOCK, to enable a
suspend_blockerthat 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.Quoted 7 lines
Quoted 2 lines
Is there some reason why this feature needs to be enabled by an ioctl? Why not make this suspend blocker permanently enabled?
The ioctl is there so that user space can use suspend blockers, which is needed because only user space know that some activities are going to continue and therefore the system should not be suspended (like playing music "in the background").
Quoted 6 lines
No, you're thinking of a different ioctl:
SUSPEND_BLOCKER_IOCTL_BLOCK. This one (EVIOCSSUSPENDBLOCK) is present _only_ to enable one specific suspend blocker, which is activated when the input event queue is non-empty. I don't see any reason why it shouldn't be enabled all the time.
Some user space processes keep input devices open that they don't currently read from. The current android kernel use a wakelock with a timeout limit the damage caused by this code, but not blocking suspend at all by default will handle this case better. Also, not all input devices are used for wakeup events, so there is no need to block suspend when their event queue is not empty.
Signature · 1 line
Arve Hjønnevåg
Re: [linux-pm] [PATCH 8/9] Input: Block suspend while event queue is not empty.
In reply to Alan SternQuoted 21 lines · Alan Stern
Quoted 11 lines · Rafael J. Wysocki
Quoted 9 lines · Alan Stern
Quoted 7 lines · Arve Hjønnevåg
Quoted 5 lines · Dmitry Torokhov
Quoted 4 lines · Randy Dunlap
Quoted 3 lines · On Thu, 22 Apr 2010 18:08:57 -0700 Arve Hjønnevåg wrote:
Add an ioctl, EVIOCSSUSPENDBLOCK, to enable a
suspend_blockerthat 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.Quoted 7 lines
Quoted 2 lines
Is there some reason why this feature needs to be enabled by an ioctl? Why not make this suspend blocker permanently enabled?
The ioctl is there so that user space can use suspend blockers, which is needed because only user space know that some activities are going to continue and therefore the system should not be suspended (like playing music "in the background").
Quoted 6 lines
No, you're thinking of a different ioctl:
SUSPEND_BLOCKER_IOCTL_BLOCK. This one (EVIOCSSUSPENDBLOCK) is present _only_ to enable one specific suspend blocker, which is activated when the input event queue is non-empty. I don't see any reason why it shouldn't be enabled all the time.
Some user space processes keep input devices open that they don't currently read from. The current android kernel use a wakelock with a timeout limit the damage caused by this code, but not blocking suspend at all by default will handle this case better. Also, not all input devices are used for wakeup events, so there is no need to block suspend when their event queue is not empty.
Signature · 5 lines
Arve Hjønnevåg -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 8/9] Input: Block suspend while event queue is not empty.
In reply to Randy Dunlap2010/4/23 Randy Dunlap <[email protected]>:
Quoted 9 lines · On Thu, 22 Apr 2010 18:08:57 -0700 Arve Hjønnevåg wrote:
Quoted 4 lines
Add an ioctl, EVIOCSSUSPENDBLOCK, to enable a
suspend_blockerthat 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.All new ioctls need to be added to
Documentation/ioctl/ioctl-number.txt, please.
These two appear to already be covered by "'E' alllinux/input.h conflict!", but I will add a line the user
space suspend blocker ioctls added earlier in this patch set.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 8/9] Input: Block suspend while event queue is not empty.
In reply to Randy Dunlap2010/4/23 Randy Dunlap <[email protected]>:
Quoted 9 lines · On Thu, 22 Apr 2010 18:08:57 -0700 Arve Hjønnevåg wrote:
Quoted 4 lines
Add an ioctl, EVIOCSSUSPENDBLOCK, to enable a
suspend_blockerthat 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.All new ioctls need to be added to
Documentation/ioctl/ioctl-number.txt, please.
These two appear to already be covered by "'E' alllinux/input.h conflict!", but I will add a line the user
space suspend blocker ioctls added earlier in this patch set.
Signature · 5 lines
Arve Hjønnevåg -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 8/9] Input: Block suspend while event queue is not empty.
In reply to Arve HjønnevågQuoted 3 lines · On Thu, 22 Apr 2010 18:08:57 -0700 Arve Hjønnevåg wrote:
Add an ioctl, EVIOCSSUSPENDBLOCK, to enable a
suspend_blockerthat 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.
All new ioctls need to be added to Documentation/ioctl/ioctl-number.txt, please.
Quoted 36 lines
Signed-off-by Arve Hjønnevåg <[email protected]>--- drivers/input/evdev.c | 22 ++++++++++++++++++++++ include/linux/input.h | 3 +++ 2 files changed, 25 insertions(+), 0 deletions(-)drivers/input/evdev.c +13
-0@@ -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 +0
-0
include/linux/input.h struct input_absinfo { · line 90
Quoted 9 lines
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 */
thanks,
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
PATCH 8/9 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
Tejun Heo
maintainerRe: [PATCH 7/9] PM: Add suspend blocking work.
In reply to Arve HjønnevågHello,
Quoted 4 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.
Hmm... I think this can be implemented as pure wrapper around workqueue instead of injecting a flag and code into workqueue core. Adding @fn field to suspend_blocking_work struct and using a custom work function to call it and then invoke suspend_unblock() should be enough, right? Oh, dedicated queue functions will be needed too. I don't think it's wise to meddle with workqueue core code for this.
Thanks.
Signature · 5 lines
tejun _______________________________________________ linux-pm mailing list [email protected] https://lists.linux-foundation.org/mailman/listinfo/linux-pm
Tejun Heo
maintainerRe: [PATCH 7/9] PM: Add suspend blocking work.
In reply to Arve HjønnevågHello,
Quoted 4 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.
Hmm... I think this can be implemented as pure wrapper around workqueue instead of injecting a flag and code into workqueue core. Adding @fn field to suspend_blocking_work struct and using a custom work function to call it and then invoke suspend_unblock() should be enough, right? Oh, dedicated queue functions will be needed too. I don't think it's wise to meddle with workqueue core code for this.
Thanks.
Signature · 1 line
tejun
Re: [PATCH 7/9] PM: Add suspend blocking work.
Quoted 7 lines · Tejun Heo
Quoted 4 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.
Quoted 6 lines
Hmm... I think this can be implemented as pure wrapper around workqueue instead of injecting a flag and code into workqueue core. Adding @fn field to
suspend_blocking_workstruct and using a custom work function to call it and then invokesuspend_unblock()should be enough, right? Oh, dedicated queue functions will be needed too. I don't think it's wise to meddle with workqueue core code for this.
Completely agreed. The patch adds very "strange" hacks into workqueue code to solve the very specific problems.
Besides, the patch doesn't look right. suspend_unblock() can be called twice if you use cancel_work(). Perhaps this is not a problem, I dunno. WORK_STRUCT_SUSPEND_BLOCKING needs to ensure that cpu_workqueue_struct has a proper alignment. The unblock code in run_workqueue() is racy, it can unblock after the work was queued on another CPU, cwq->lock can't help.
Oleg.
Re: [PATCH 7/9] PM: Add suspend blocking work.
In reply to Tejun HeoQuoted 7 lines · Tejun Heo
Quoted 4 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.
Quoted 6 lines
Hmm... I think this can be implemented as pure wrapper around workqueue instead of injecting a flag and code into workqueue core. Adding @fn field to
suspend_blocking_workstruct and using a custom work function to call it and then invokesuspend_unblock()should be enough, right? Oh, dedicated queue functions will be needed too. I don't think it's wise to meddle with workqueue core code for this.
Completely agreed. The patch adds very "strange" hacks into workqueue code to solve the very specific problems.
Besides, the patch doesn't look right. suspend_unblock() can be called twice if you use cancel_work(). Perhaps this is not a problem, I dunno. WORK_STRUCT_SUSPEND_BLOCKING needs to ensure that cpu_workqueue_struct has a proper alignment. The unblock code in run_workqueue() is racy, it can unblock after the work was queued on another CPU, cwq->lock can't help.
Oleg.
Re: [PATCH 7/9] PM: Add suspend blocking work.
Quoted 15 lines · Oleg Nesterov
Quoted 7 lines · Tejun Heo
Quoted 4 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.Quoted 6 lines
Hmm... I think this can be implemented as pure wrapper around workqueue instead of injecting a flag and code into workqueue core. Adding @fn field to
suspend_blocking_workstruct and using a custom work function to call it and then invokesuspend_unblock()should be enough, right? Oh, dedicated queue functions will be needed too. I don't think it's wise to meddle with workqueue core code for this.
Quoted 3 lines
Completely agreed. The patch adds very "strange" hacks into workqueue code to solve the very specific problems.
I want the suspend blocker active when the work is pending or running. I did not see a way to do this on top of the workqueue api without adding additional locking.
Quoted 3 lines
Besides, the patch doesn't look right.
suspend_unblock()can be called twice if you usecancel_work(). Perhaps this is not a problem, I dunno.
Calling suspend_unblock() twice is not a problem as long as "unblocked" is the expected final state.
Quoted 2 lines
WORK_STRUCT_SUSPEND_BLOCKINGneeds to ensure thatcpu_workqueue_structhas a proper alignment.
OK.
Quoted 3 lines
The unblock code in
run_workqueue()is racy,
it can unblock after the work was queued on another CPU,cwq->lockcan't help.
If the work is both queued and starts running on another workqueue between "get_wq_data(work) == cwq" and "!work_pending(work)", then suspend_unblock will be called when it shouldn't. It should work fine if I change to it check pending first though, since it cannot move back to the current workqueue without locking cwq->lock first.
Or are you talking about the race when the callback is running on multiple (cpu) workqueues at the same time. In that case the suspend blocker is released when the callback returns from the last workqueue is was queued on, not when all the callbacks have returned. On that note, is it ever safe to use flush_work and cancel_work_sync for work queues on anything other than a single single threaded workqueue?
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 7/9] PM: Add suspend blocking work.
In reply to Oleg NesterovQuoted 15 lines · Oleg Nesterov
Quoted 7 lines · Tejun Heo
Quoted 4 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.Quoted 6 lines
Hmm... I think this can be implemented as pure wrapper around workqueue instead of injecting a flag and code into workqueue core. Adding @fn field to
suspend_blocking_workstruct and using a custom work function to call it and then invokesuspend_unblock()should be enough, right? Oh, dedicated queue functions will be needed too. I don't think it's wise to meddle with workqueue core code for this.
Quoted 3 lines
Completely agreed. The patch adds very "strange" hacks into workqueue code to solve the very specific problems.
I want the suspend blocker active when the work is pending or running. I did not see a way to do this on top of the workqueue api without adding additional locking.
Quoted 3 lines
Besides, the patch doesn't look right.
suspend_unblock()can be called twice if you usecancel_work(). Perhaps this is not a problem, I dunno.
Calling suspend_unblock() twice is not a problem as long as "unblocked" is the expected final state.
Quoted 2 lines
WORK_STRUCT_SUSPEND_BLOCKINGneeds to ensure thatcpu_workqueue_structhas a proper alignment.
OK.
Quoted 3 lines
The unblock code in
run_workqueue()is racy,
it can unblock after the work was queued on another CPU,cwq->lockcan't help.
If the work is both queued and starts running on another workqueue between "get_wq_data(work) == cwq" and "!work_pending(work)", then suspend_unblock will be called when it shouldn't. It should work fine if I change to it check pending first though, since it cannot move back to the current workqueue without locking cwq->lock first.
Or are you talking about the race when the callback is running on multiple (cpu) workqueues at the same time. In that case the suspend blocker is released when the callback returns from the last workqueue is was queued on, not when all the callbacks have returned. On that note, is it ever safe to use flush_work and cancel_work_sync for work queues on anything other than a single single threaded workqueue?
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 7/9] PM: Add suspend blocking work.
2010/4/23 Arve Hjønnevåg <[email protected]>:
Quoted 16 lines · Oleg Nesterov
Quoted 15 lines · Tejun Heo
Quoted 13 lines · Arve Hjønnevåg
Quoted 4 lines
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.Hmm... I think this can be implemented as pure wrapper around workqueue instead of injecting a flag and code into workqueue core. Adding @fn field to
suspend_blocking_workstruct and using a custom work function to call it and then invokesuspend_unblock()should be enough, right? Oh, dedicated queue functions will be needed too. I don't think it's wise to meddle with workqueue core code for this.
Quoted 8 lines
Quoted 3 lines
Completely agreed. The patch adds very "strange" hacks into workqueue code to solve the very specific problems.
I want the suspend blocker active when the work is pending or running. I did not see a way to do this on top of the workqueue api without adding additional locking.
I can remove the WORK_STRUCT_SUSPEND_BLOCKING flag and instead add an argument to __queue_work and __cancel_work_timer (or use separate copies) if you think that would be better. It would avoid increasing the alignment requirement of cpu_workqueue_struct, but it will probably add more code than the current patch.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 7/9] PM: Add suspend blocking work.
In reply to Arve Hjønnevåg2010/4/23 Arve Hjønnevåg <[email protected]>:
Quoted 16 lines · Oleg Nesterov
Quoted 15 lines · Tejun Heo
Quoted 13 lines · Arve Hjønnevåg
Quoted 4 lines
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.Hmm... I think this can be implemented as pure wrapper around workqueue instead of injecting a flag and code into workqueue core. Adding @fn field to
suspend_blocking_workstruct and using a custom work function to call it and then invokesuspend_unblock()should be enough, right? Oh, dedicated queue functions will be needed too. I don't think it's wise to meddle with workqueue core code for this.
Quoted 8 lines
Quoted 3 lines
Completely agreed. The patch adds very "strange" hacks into workqueue code to solve the very specific problems.
I want the suspend blocker active when the work is pending or running. I did not see a way to do this on top of the workqueue api without adding additional locking.
I can remove the WORK_STRUCT_SUSPEND_BLOCKING flag and instead add an argument to __queue_work and __cancel_work_timer (or use separate copies) if you think that would be better. It would avoid increasing the alignment requirement of cpu_workqueue_struct, but it will probably add more code than the current patch.
Signature · 1 line
Arve Hjønnevåg
Tejun Heo
maintainerRe: [PATCH 7/9] PM: Add suspend blocking work.
In reply to Arve HjønnevågHello,
Quoted 3 lines · Arve Hjønnevåg
I want the suspend blocker active when the work is pending or running. I did not see a way to do this on top of the workqueue api without adding additional locking.
Well, then add additional locking. suspend_blocker is far away from being a hot path and there's nothing wrong with additional locking as long as everything is wrapped inside proper APIs. Adding stuff to the core code for things as specific as this is much worse.
Quoted 5 lines
If the work is both queued and starts running on another workqueue between "
get_wq_data(work)== cwq" and "!work_pending(work)", thensuspend_unblockwill be called when it shouldn't. It should work fine if I change to it check pending first though, since it cannot move back to the current workqueue without lockingcwq->lockfirst.
The code is more fundamentally broken. Once work->func has started executing, the work pointer can't be dereferenced as work callback is allowed to free or re-purpose the work data structure and in the same manner you can't check for pending status after execution has completed.
Quoted 6 lines
Or are you talking about the race when the callback is running on multiple (cpu) workqueues at the same time. In that case the suspend blocker is released when the callback returns from the last workqueue is was queued on, not when all the callbacks have returned. On that note, is it ever safe to use
flush_workandcancel_work_syncfor work queues on anything other than a single single threaded workqueue?
flush_work() is guaranteed only to flush from the last queued cpu but cancel_work_sync() will guarantee that no cpu is executing or holding onto the work. So, yeah, as long as the limitations of flush_work() is understood, it's safe.
Going back to the original subject, just add simplistic outside locking in suspend_blocker_work API (or whatever other name you prefer). That will be much cleaner and safer. Let's think about moving them into workqueue implementation proper after the number of the API users grows to hundreds.
Thanks.
Signature · 1 line
tejun
Tejun Heo
maintainerRe: [PATCH 7/9] PM: Add suspend blocking work.
In reply to Arve HjønnevågHello,
Quoted 3 lines · Arve Hjønnevåg
I want the suspend blocker active when the work is pending or running. I did not see a way to do this on top of the workqueue api without adding additional locking.
Well, then add additional locking. suspend_blocker is far away from being a hot path and there's nothing wrong with additional locking as long as everything is wrapped inside proper APIs. Adding stuff to the core code for things as specific as this is much worse.
Quoted 5 lines
If the work is both queued and starts running on another workqueue between "
get_wq_data(work)== cwq" and "!work_pending(work)", thensuspend_unblockwill be called when it shouldn't. It should work fine if I change to it check pending first though, since it cannot move back to the current workqueue without lockingcwq->lockfirst.
The code is more fundamentally broken. Once work->func has started executing, the work pointer can't be dereferenced as work callback is allowed to free or re-purpose the work data structure and in the same manner you can't check for pending status after execution has completed.
Quoted 6 lines
Or are you talking about the race when the callback is running on multiple (cpu) workqueues at the same time. In that case the suspend blocker is released when the callback returns from the last workqueue is was queued on, not when all the callbacks have returned. On that note, is it ever safe to use
flush_workandcancel_work_syncfor work queues on anything other than a single single threaded workqueue?
flush_work() is guaranteed only to flush from the last queued cpu but cancel_work_sync() will guarantee that no cpu is executing or holding onto the work. So, yeah, as long as the limitations of flush_work() is understood, it's safe.
Going back to the original subject, just add simplistic outside locking in suspend_blocker_work API (or whatever other name you prefer). That will be much cleaner and safer. Let's think about moving them into workqueue implementation proper after the number of the API users grows to hundreds.
Thanks.
Signature · 1 line
tejun
Re: [PATCH 7/9] PM: Add suspend blocking work.
2010/4/23 Tejun Heo <[email protected]>:
Quoted 12 lines
Hello,
Quoted 3 lines · Arve Hjønnevåg
I want the suspend blocker active when the work is pending or running. I did not see a way to do this on top of the workqueue api without adding additional locking.
Well, then add additional locking. suspend_blocker is far away from being a hot path and there's nothing wrong with additional locking as long as everything is wrapped inside proper APIs. Adding stuff to the core code for things as specific as this is much worse.
OK, I'll try to do this. Do you want it in a separate header file as well?
Quoted 6 lines
Quoted 5 lines
If the work is both queued and starts running on another workqueue between "
get_wq_data(work)== cwq" and "!work_pending(work)", thensuspend_unblockwill be called when it shouldn't. It should work fine if I change to it check pending first though, since it cannot move back to the current workqueue without lockingcwq->lockfirst.
Quoted 6 lines
The code is more fundamentally broken. Once
work->funchas started executing, the work pointer can't be dereferenced as work callback is allowed to free or re-purpose the work data structure and in the same manner you can't check for pending status after execution has completed.
I only touch the work structure after the callback has returned for suspend blocking work, which does not allow that.
Quoted 7 lines
Quoted 6 lines
Or are you talking about the race when the callback is running on multiple (cpu) workqueues at the same time. In that case the suspend blocker is released when the callback returns from the last workqueue is was queued on, not when all the callbacks have returned. On that note, is it ever safe to use
flush_workandcancel_work_syncfor work queues on anything other than a single single threaded workqueue?
Quoted 5 lines
flush_work()is guaranteed only to flush from the last queued cpu butcancel_work_sync()will guarantee that no cpu is executing or holding onto the work. So, yeah, as long as the limitations offlush_work()is understood, it's safe.
Sorry, I didn't see the for_each_cpu(cpu, cpu_map) part of wait_on_work(). cancel_work_sync() does look safe as long as the work has not moved to completely different workqueue.
Quoted 6 lines
Going back to the original subject, just add simplistic outside locking in
suspend_blocker_workAPI (or whatever other name you prefer). That will be much cleaner and safer. Let's think about moving them into workqueue implementation proper after the number of the API users grows to hundreds.
OK.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 7/9] PM: Add suspend blocking work.
In reply to Tejun Heo2010/4/23 Tejun Heo <[email protected]>:
Quoted 12 lines
Hello,
Quoted 3 lines · Arve Hjønnevåg
I want the suspend blocker active when the work is pending or running. I did not see a way to do this on top of the workqueue api without adding additional locking.
Well, then add additional locking. suspend_blocker is far away from being a hot path and there's nothing wrong with additional locking as long as everything is wrapped inside proper APIs. Adding stuff to the core code for things as specific as this is much worse.
OK, I'll try to do this. Do you want it in a separate header file as well?
Quoted 6 lines
Quoted 5 lines
If the work is both queued and starts running on another workqueue between "
get_wq_data(work)== cwq" and "!work_pending(work)", thensuspend_unblockwill be called when it shouldn't. It should work fine if I change to it check pending first though, since it cannot move back to the current workqueue without lockingcwq->lockfirst.
Quoted 6 lines
The code is more fundamentally broken. Once
work->funchas started executing, the work pointer can't be dereferenced as work callback is allowed to free or re-purpose the work data structure and in the same manner you can't check for pending status after execution has completed.
I only touch the work structure after the callback has returned for suspend blocking work, which does not allow that.
Quoted 7 lines
Quoted 6 lines
Or are you talking about the race when the callback is running on multiple (cpu) workqueues at the same time. In that case the suspend blocker is released when the callback returns from the last workqueue is was queued on, not when all the callbacks have returned. On that note, is it ever safe to use
flush_workandcancel_work_syncfor work queues on anything other than a single single threaded workqueue?
Quoted 5 lines
flush_work()is guaranteed only to flush from the last queued cpu butcancel_work_sync()will guarantee that no cpu is executing or holding onto the work. So, yeah, as long as the limitations offlush_work()is understood, it's safe.
Sorry, I didn't see the for_each_cpu(cpu, cpu_map) part of wait_on_work(). cancel_work_sync() does look safe as long as the work has not moved to completely different workqueue.
Quoted 6 lines
Going back to the original subject, just add simplistic outside locking in
suspend_blocker_workAPI (or whatever other name you prefer). That will be much cleaner and safer. Let's think about moving them into workqueue implementation proper after the number of the API users grows to hundreds.
OK.
Signature · 1 line
Arve Hjønnevåg
Tejun Heo
maintainerRe: [PATCH 7/9] PM: Add suspend blocking work.
Hello,
Quoted 1 line · Arve Hjønnevåg
OK, I'll try to do this. Do you want it in a separate header file as well?
I think it would fit better with the rest of suspend_blocker.h APIs but it's not like I thought about it hard and long, so please take my preference with a grain of salt.
Quoted 2 lines
I only touch the work structure after the callback has returned for suspend blocking work, which does not allow that.
Oh, you're right. I missed the current_work_blocks_suspend test. Sorry about that.
Thanks.
Signature · 1 line
tejun
Re: [PATCH 7/9] PM: Add suspend blocking work.
In reply to Arve HjønnevågQuoted 7 lines · Arve Hjønnevåg
Quoted 3 lines · Oleg Nesterov
The unblock code in
run_workqueue()is racy,
it can unblock after the work was queued on another CPU,cwq->lockcan't help.
Quoted 5 lines
If the work is both queued and starts running on another workqueue between "
get_wq_data(work)== cwq" and "!work_pending(work)", thensuspend_unblockwill be called when it shouldn't. It should work fine if I change to it check pending first though, since it cannot move back to the current workqueue without lockingcwq->lockfirst.
It can be queued on the same or different workqueue on another CPU, right before run_workqueue() does unblock.
But I guess this doesn't matter. You already discussed this all with Tejun while I was sleeping ;) And I agree very much, the new plan looks much better imho.
Oleg.
Re: [PATCH 7/9] PM: Add suspend blocking work.
In reply to Arve HjønnevågQuoted 7 lines · Arve Hjønnevåg
Quoted 3 lines · Oleg Nesterov
The unblock code in
run_workqueue()is racy,
it can unblock after the work was queued on another CPU,cwq->lockcan't help.
Quoted 5 lines
If the work is both queued and starts running on another workqueue between "
get_wq_data(work)== cwq" and "!work_pending(work)", thensuspend_unblockwill be called when it shouldn't. It should work fine if I change to it check pending first though, since it cannot move back to the current workqueue without lockingcwq->lockfirst.
It can be queued on the same or different workqueue on another CPU, right before run_workqueue() does unblock.
But I guess this doesn't matter. You already discussed this all with Tejun while I was sleeping ;) And I agree very much, the new plan looks much better imho.
Oleg.
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
In reply to Arve HjønnevågQuoted 2 lines · On Thu, 22 Apr 2010 18:08:54 -0700 Arve Hjønnevåg wrote:
Report active and inactive suspend blockers in
/sys/kernel/debug/suspend_blockers.
This looks more like user interface information than it does debug information. If that's correct, it shouldn't be in debugfs.
Quoted 84 lines
Signed-off-by Arve Hjønnevåg <[email protected]>--- kernel/power/suspend_blocker.c | 44 ++++++++++++++++++++++++++++++++++++++- 1 files changed, 42 insertions(+), 2 deletions(-)kernel/power/suspend_blocker.c +33
-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" enum {@@ -41,6 +42,7 @@ struct workqueue_struct *suspend_work_queue;struct suspend_blocker main_suspend_blocker;static suspend_state_t requested_suspend_state =PM_SUSPEND_MEM ;static bool enable_suspend_blockers; +static struct dentry *suspend_blocker_stats_dentry; #define pr_info_time(fmt, args...) \ do { \@@ -54,6 +56,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;@@ -101,8 +118,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. */ @@ -240,6 +257,19 @@ 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, +}; +static int __init suspend_block_init (void ) { suspend_work_queue =create_singlethread_workqueue ("suspend" );@@ -251,4 +281,14 @@ static int __init suspend_block_init(void)return 0 ; } +static int __init suspend_block_postcore_init (void )
kernel/power/suspend_blocker.c static int __init suspend_block_init(void) · line 294
Quoted 10 lines
kernel/power/suspend_blocker.c +9
-0+{ +if (!suspend_work_queue) +return 0 ; + suspend_blocker_stats_dentry =debugfs_create_file ("suspend_blockers" , +S_IRUGO ,NULL ,NULL , &suspend_blocker_stats_fops); +return 0 ; +} +core_initcall (suspend_block_init); +postcore_initcall (suspend_block_postcore_init);
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
In reply to Arve HjønnevågQuoted 2 lines · On Thu, 22 Apr 2010 18:08:54 -0700 Arve Hjønnevåg wrote:
Report active and inactive suspend blockers in
/sys/kernel/debug/suspend_blockers.
This looks more like user interface information than it does debug information. If that's correct, it shouldn't be in debugfs.
Quoted 84 lines
Signed-off-by Arve Hjønnevåg <[email protected]>--- kernel/power/suspend_blocker.c | 44 ++++++++++++++++++++++++++++++++++++++- 1 files changed, 42 insertions(+), 2 deletions(-)kernel/power/suspend_blocker.c +33
-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" enum {@@ -41,6 +42,7 @@ struct workqueue_struct *suspend_work_queue;struct suspend_blocker main_suspend_blocker;static suspend_state_t requested_suspend_state =PM_SUSPEND_MEM ;static bool enable_suspend_blockers; +static struct dentry *suspend_blocker_stats_dentry; #define pr_info_time(fmt, args...) \ do { \@@ -54,6 +56,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;@@ -101,8 +118,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. */ @@ -240,6 +257,19 @@ 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, +}; +static int __init suspend_block_init (void ) { suspend_work_queue =create_singlethread_workqueue ("suspend" );@@ -251,4 +281,14 @@ static int __init suspend_block_init(void)return 0 ; } +static int __init suspend_block_postcore_init (void )
kernel/power/suspend_blocker.c static int __init suspend_block_init(void) · line 294
Quoted 10 lines
kernel/power/suspend_blocker.c +9
-0+{ +if (!suspend_work_queue) +return 0 ; + suspend_blocker_stats_dentry =debugfs_create_file ("suspend_blockers" , +S_IRUGO ,NULL ,NULL , &suspend_blocker_stats_fops); +return 0 ; +} +core_initcall (suspend_block_init); +postcore_initcall (suspend_block_postcore_init);
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
2010/4/23 Randy Dunlap <[email protected]>:
Quoted 8 lines · On Thu, 22 Apr 2010 18:08:54 -0700 Arve Hjønnevåg wrote:
Quoted 3 lines
Report active and inactive suspend blockers in
/sys/kernel/debug/suspend_blockers.This looks more like user interface information than it does debug information. If that's correct, it shouldn't be in debugfs.
Where should it be? It is not allowed in sysfs, and procfs does not appear to be open to new files.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
In reply to Randy Dunlap2010/4/23 Randy Dunlap <[email protected]>:
Quoted 8 lines · On Thu, 22 Apr 2010 18:08:54 -0700 Arve Hjønnevåg wrote:
Quoted 3 lines
Report active and inactive suspend blockers in
/sys/kernel/debug/suspend_blockers.This looks more like user interface information than it does debug information. If that's correct, it shouldn't be in debugfs.
Where should it be? It is not allowed in sysfs, and procfs does not appear to be open to new files.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
Quoted 7 lines · Arve Hjønnevåg
2010/4/23 Randy Dunlap <[email protected]>:
Quoted 6 lines · On Thu, 22 Apr 2010 18:08:54 -0700 Arve Hjønnevåg wrote:
Quoted 3 lines
Report active and inactive suspend blockers in
/sys/kernel/debug/suspend_blockers.
Quoted 5 lines
Quoted 2 lines
This looks more like user interface information than it does debug information. If that's correct, it shouldn't be in debugfs.
Where should it be? It is not allowed in sysfs, and procfs does not appear to be open to new files.
Why is it not allowed in sysfs? due to more than one value per file or something else?
I don't think that procfs is closed to new files, but you may have to justify why it should be used.
Signature · 2 lines
~Randy *** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
2010/4/23 Randy Dunlap <[email protected]>:
Quoted 8 lines · Arve Hjønnevåg
Quoted 7 lines
2010/4/23 Randy Dunlap <[email protected]>:
Quoted 6 lines · On Thu, 22 Apr 2010 18:08:54 -0700 Arve Hjønnevåg wrote:
Quoted 3 lines
Report active and inactive suspend blockers in
/sys/kernel/debug/suspend_blockers.
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
This looks more like user interface information than it does debug information. If that's correct, it shouldn't be in debugfs.
Where should it be? It is not allowed in sysfs, and procfs does not appear to be open to new files.
Why is it not allowed in sysfs? due to more than one value per file
Yes.
Quoted 5 lines
or something else?
I don't think that procfs is closed to new files, but you may have to justify why it should be used.
I used procfs in the original version and there were a lot of objections to this, so I moved it to debugfs.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
In reply to Randy Dunlap2010/4/23 Randy Dunlap <[email protected]>:
Quoted 8 lines · Arve Hjønnevåg
Quoted 7 lines
2010/4/23 Randy Dunlap <[email protected]>:
Quoted 6 lines · On Thu, 22 Apr 2010 18:08:54 -0700 Arve Hjønnevåg wrote:
Quoted 3 lines
Report active and inactive suspend blockers in
/sys/kernel/debug/suspend_blockers.
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
This looks more like user interface information than it does debug information. If that's correct, it shouldn't be in debugfs.
Where should it be? It is not allowed in sysfs, and procfs does not appear to be open to new files.
Why is it not allowed in sysfs? due to more than one value per file
Yes.
Quoted 5 lines
or something else?
I don't think that procfs is closed to new files, but you may have to justify why it should be used.
I used procfs in the original version and there were a lot of objections to this, so I moved it to debugfs.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
In reply to Randy DunlapQuoted 8 lines · Randy Dunlap
Quoted 2 lines · On Thu, 22 Apr 2010 18:08:54 -0700 Arve Hj?nnev?g wrote:
Report active and inactive suspend blockers in
/sys/kernel/debug/suspend_blockers.This looks more like user interface information than it does debug information. If that's correct, it shouldn't be in debugfs.
It's debug-like information, and has more than one value per file, so debugfs seems like the proper place for it. I have no objection to it going there.
thanks,
greg k-h
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
Quoted 7 lines · Greg KH
Quoted 6 lines · Randy Dunlap
Quoted 2 lines · On Thu, 22 Apr 2010 18:08:54 -0700 Arve Hj?nnev?g wrote:
Report active and inactive suspend blockers in
/sys/kernel/debug/suspend_blockers.
Quoted 6 lines
Quoted 2 lines
This looks more like user interface information than it does debug information. If that's correct, it shouldn't be in debugfs.
It's debug-like information, and has more than one value per file, so debugfs seems like the proper place for it. I have no objection to it going there.
I have no objection if it really is debug info, but I'm not convinced of that yet.
Signature · 2 lines
~Randy *** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
In reply to Greg KHQuoted 7 lines · Greg KH
Quoted 6 lines · Randy Dunlap
Quoted 2 lines · On Thu, 22 Apr 2010 18:08:54 -0700 Arve Hj?nnev?g wrote:
Report active and inactive suspend blockers in
/sys/kernel/debug/suspend_blockers.
Quoted 6 lines
Quoted 2 lines
This looks more like user interface information than it does debug information. If that's correct, it shouldn't be in debugfs.
It's debug-like information, and has more than one value per file, so debugfs seems like the proper place for it. I have no objection to it going there.
I have no objection if it really is debug info, but I'm not convinced of that yet.
Signature · 2 lines
~Randy *** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
Quoted 6 lines · Randy Dunlap
Quoted 3 lines
It's debug-like information, and has more than one value per file, so debugfs seems like the proper place for it. I have no objection to it going there.
I have no objection if it really is debug info, but I'm not convinced of that yet.
Well, I'll note right now we have a somewhat annoying gap. If you need to export multiple values such that they are consistent with each other, what's the choice? /proc, where some (but not all) kernel developers will say, "eeeeeeviilllll". /sys is explicitly for single value per files only. And then we have /debugfs, where some pendants are kvetching about whether something is "really" debug information.
One of the things that we sometimes have to tell people who are trying to navigate the maze of upstream submission is that sometimes you need to know who to ignore, and that sometimes rules are guidelines (despite pendants who will NACK based on rules like, "/proc, eeeeewwww", or "/debugfs must only strictly be for debug information".
Telling embedded developers who only want to submit their driver that they must create a whole new pseudo-filesystem just to export a single file that in older, simpler times, would have just been thrown into /proc is really not fair, and is precisely the sort of thing that may cause them to say, "f*ck it, these is one too many flaming hoops to jump through". If we throw up too many barriers, in the long run it's not actually doing Linux a service.
Sure, we need to make sure is code doesn't become a future burden, but does a new file in /proc or something that might not _really_ be debug information showing up in /debugfs really such a terrible thing in terms of making the kernel less maintainable in the future?
Regards,
- Ted
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
In reply to Randy DunlapQuoted 6 lines · Randy Dunlap
Quoted 3 lines
It's debug-like information, and has more than one value per file, so debugfs seems like the proper place for it. I have no objection to it going there.
I have no objection if it really is debug info, but I'm not convinced of that yet.
Well, I'll note right now we have a somewhat annoying gap. If you need to export multiple values such that they are consistent with each other, what's the choice? /proc, where some (but not all) kernel developers will say, "eeeeeeviilllll". /sys is explicitly for single value per files only. And then we have /debugfs, where some pendants are kvetching about whether something is "really" debug information.
One of the things that we sometimes have to tell people who are trying to navigate the maze of upstream submission is that sometimes you need to know who to ignore, and that sometimes rules are guidelines (despite pendants who will NACK based on rules like, "/proc, eeeeewwww", or "/debugfs must only strictly be for debug information".
Telling embedded developers who only want to submit their driver that they must create a whole new pseudo-filesystem just to export a single file that in older, simpler times, would have just been thrown into /proc is really not fair, and is precisely the sort of thing that may cause them to say, "f*ck it, these is one too many flaming hoops to jump through". If we throw up too many barriers, in the long run it's not actually doing Linux a service.
Sure, we need to make sure is code doesn't become a future burden, but does a new file in /proc or something that might not _really_ be debug information showing up in /debugfs really such a terrible thing in terms of making the kernel less maintainable in the future?
Regards,
- Ted
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
Quoted 8 lines · On 04/25/10 17:00, [email protected] wrote:
Quoted 6 lines · Randy Dunlap
Quoted 3 lines
It's debug-like information, and has more than one value per file, so debugfs seems like the proper place for it. I have no objection to it going there.
I have no objection if it really is debug info, but I'm not convinced of that yet.
Quoted 6 lines
Well, I'll note right now we have a somewhat annoying gap. If you need to export multiple values such that they are consistent with each other, what's the choice? /proc, where some (but not all) kernel developers will say, "eeeeeeviilllll". /sys is explicitly for single value per files only. And then we have /debugfs, where some pendants are kvetching about whether something is "really" debug information.
First of all, I am not a pendant.
Quoted 6 lines
One of the things that we sometimes have to tell people who are trying to navigate the maze of upstream submission is that sometimes you need to know who to ignore, and that sometimes rules are guidelines (despite pendants who will NACK based on rules like, "/proc, eeeeewwww", or "/debugfs must only strictly be for debug information".
Quoted 7 lines
Telling embedded developers who only want to submit their driver that they must create a whole new pseudo-filesystem just to export a single file that in older, simpler times, would have just been thrown into /proc is really not fair, and is precisely the sort of thing that may cause them to say, "f*ck it, these is one too many flaming hoops to jump through". If we throw up too many barriers, in the long run it's not actually doing Linux a service.
Yeah, I think that it should be in procfs. It's not strictly closed to new files. (IOW, I'm sure that we can find a bunch of recent files added to procfs.)
Quoted 4 lines
Sure, we need to make sure is code doesn't become a future burden, but does a new file in /proc or something that might not _really_ be debug information showing up in /debugfs really such a terrible thing in terms of making the kernel less maintainable in the future?
I don't think that we want to make debugfs required to get decent tuning info/stats from the kernel. That's all.
Signature · 2 lines
~Randy *** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
In reply to [email protected]Quoted 8 lines · On 04/25/10 17:00, [email protected] wrote:
Quoted 6 lines · Randy Dunlap
Quoted 3 lines
It's debug-like information, and has more than one value per file, so debugfs seems like the proper place for it. I have no objection to it going there.
I have no objection if it really is debug info, but I'm not convinced of that yet.
Quoted 6 lines
Well, I'll note right now we have a somewhat annoying gap. If you need to export multiple values such that they are consistent with each other, what's the choice? /proc, where some (but not all) kernel developers will say, "eeeeeeviilllll". /sys is explicitly for single value per files only. And then we have /debugfs, where some pendants are kvetching about whether something is "really" debug information.
First of all, I am not a pendant.
Quoted 6 lines
One of the things that we sometimes have to tell people who are trying to navigate the maze of upstream submission is that sometimes you need to know who to ignore, and that sometimes rules are guidelines (despite pendants who will NACK based on rules like, "/proc, eeeeewwww", or "/debugfs must only strictly be for debug information".
Quoted 7 lines
Telling embedded developers who only want to submit their driver that they must create a whole new pseudo-filesystem just to export a single file that in older, simpler times, would have just been thrown into /proc is really not fair, and is precisely the sort of thing that may cause them to say, "f*ck it, these is one too many flaming hoops to jump through". If we throw up too many barriers, in the long run it's not actually doing Linux a service.
Yeah, I think that it should be in procfs. It's not strictly closed to new files. (IOW, I'm sure that we can find a bunch of recent files added to procfs.)
Quoted 4 lines
Sure, we need to make sure is code doesn't become a future burden, but does a new file in /proc or something that might not _really_ be debug information showing up in /debugfs really such a terrible thing in terms of making the kernel less maintainable in the future?
I don't think that we want to make debugfs required to get decent tuning info/stats from the kernel. That's all.
Signature · 2 lines
~Randy *** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
Quoted 3 lines · Randy Dunlap
Yeah, I think that it should be in procfs. It's not strictly closed to new files. (IOW, I'm sure that we can find a bunch of recent files added to procfs.)
That's reasonable (I think the whole /proc is evil crusade is really dumb) --- but at the same time, remember how frustrating it is for the poor embedded developer who doesn't know who to ignore and what "rules" to ignore. They were told months ago /proc is evil, and so they moved it to /debugfs, precisely because it was billed as "it has no rules". For all I know some helpful community developer may have even suggested that to them.
It is extremely frustrating to embedded developers when they get conflicting advice, especially in this case, when it was *in* /proc in the first place. I'm not sure what to do about this --- my approach is to sometimes say, "f*ck it, that's stupid advice", and ship it to Linus, who tends to be *much* less of a pendant than most of the people who review code --- but that's because I know what I can ignore. (I seriously doubt Linus cares much about whether it ends up the file ends up /debugfs or /proc, and would take the code either way.) But for someone who doesn't understand when you can do this, and who tries to follow every single piece of criticism they get, the end result can often be a huge amount fo wasted time and frustration.
It would be nice if we could get better at this, since I'm sure this is not the only time when embedded code submissions have gotten what the submitting developers might consider to be a runaround....
(And just to be clear, I'm not criticising your commends; my personal preference is slightly in favor of /proc, but more than anythign else, I consider it a very minor point. I just want to point out that they _started_ with the file in /proc and changed it to /debugfs based on someone NACK'ing their patch, with a "/proc, eeeeewwww" comment. Sometimes I think some code reviewers get too much of a sense of power trip by thinking they can NACK other people's code over their own pet peeves.... instead of approaching it from a somewhat more collegial point of view trying to make the code better. Present company excepted, of course. :-)
- Ted
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
In reply to Randy DunlapQuoted 3 lines · Randy Dunlap
Yeah, I think that it should be in procfs. It's not strictly closed to new files. (IOW, I'm sure that we can find a bunch of recent files added to procfs.)
That's reasonable (I think the whole /proc is evil crusade is really dumb) --- but at the same time, remember how frustrating it is for the poor embedded developer who doesn't know who to ignore and what "rules" to ignore. They were told months ago /proc is evil, and so they moved it to /debugfs, precisely because it was billed as "it has no rules". For all I know some helpful community developer may have even suggested that to them.
It is extremely frustrating to embedded developers when they get conflicting advice, especially in this case, when it was *in* /proc in the first place. I'm not sure what to do about this --- my approach is to sometimes say, "f*ck it, that's stupid advice", and ship it to Linus, who tends to be *much* less of a pendant than most of the people who review code --- but that's because I know what I can ignore. (I seriously doubt Linus cares much about whether it ends up the file ends up /debugfs or /proc, and would take the code either way.) But for someone who doesn't understand when you can do this, and who tries to follow every single piece of criticism they get, the end result can often be a huge amount fo wasted time and frustration.
It would be nice if we could get better at this, since I'm sure this is not the only time when embedded code submissions have gotten what the submitting developers might consider to be a runaround....
(And just to be clear, I'm not criticising your commends; my personal preference is slightly in favor of /proc, but more than anythign else, I consider it a very minor point. I just want to point out that they _started_ with the file in /proc and changed it to /debugfs based on someone NACK'ing their patch, with a "/proc, eeeeewwww" comment. Sometimes I think some code reviewers get too much of a sense of power trip by thinking they can NACK other people's code over their own pet peeves.... instead of approaching it from a somewhat more collegial point of view trying to make the code better. Present company excepted, of course. :-)
- Ted
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
Quoted 25 lines · On 04/25/10 17:45, [email protected] wrote:
Quoted 3 lines · Randy Dunlap
Yeah, I think that it should be in procfs. It's not strictly closed to new files. (IOW, I'm sure that we can find a bunch of recent files added to procfs.)
That's reasonable (I think the whole /proc is evil crusade is really dumb) --- but at the same time, remember how frustrating it is for the poor embedded developer who doesn't know who to ignore and what "rules" to ignore. They were told months ago /proc is evil, and so they moved it to /debugfs, precisely because it was billed as "it has no rules". For all I know some helpful community developer may have even suggested that to them.
It is extremely frustrating to embedded developers when they get conflicting advice, especially in this case, when it was *in* /proc in the first place. I'm not sure what to do about this --- my approach is to sometimes say, "f*ck it, that's stupid advice", and ship it to Linus, who tends to be *much* less of a pendant than most of the people who review code --- but that's because I know what I can ignore. (I seriously doubt Linus cares much about whether it ends up the file ends up /debugfs or /proc, and would take the code either way.) But for someone who doesn't understand when you can do this, and who tries to follow every single piece of criticism they get, the end result can often be a huge amount fo wasted time and frustration.
Quoted 3 lines
It would be nice if we could get better at this, since I'm sure this is not the only time when embedded code submissions have gotten what the submitting developers might consider to be a runaround....
Agreed, we could/should do much better.
Agreed, I'm sure that it is frustrating to the contributors. Agreed about Linus taking it either way. :)
Thanks for your summary and bringing it up (yet again).
Quoted 10 lines
(And just to be clear, I'm not criticising your commends; my personal preference is slightly in favor of /proc, but more than anythign else, I consider it a very minor point. I just want to point out that they _started_ with the file in /proc and changed it to /debugfs based on someone NACK'ing their patch, with a "/proc, eeeeewwww" comment. Sometimes I think some code reviewers get too much of a sense of power trip by thinking they can NACK other people's code over their own pet peeves.... instead of approaching it from a somewhat more collegial point of view trying to make the code better. Present company excepted, of course. :-)
Signature · 2 lines
~Randy *** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
In reply to [email protected]Quoted 25 lines · On 04/25/10 17:45, [email protected] wrote:
Quoted 3 lines · Randy Dunlap
Yeah, I think that it should be in procfs. It's not strictly closed to new files. (IOW, I'm sure that we can find a bunch of recent files added to procfs.)
That's reasonable (I think the whole /proc is evil crusade is really dumb) --- but at the same time, remember how frustrating it is for the poor embedded developer who doesn't know who to ignore and what "rules" to ignore. They were told months ago /proc is evil, and so they moved it to /debugfs, precisely because it was billed as "it has no rules". For all I know some helpful community developer may have even suggested that to them.
It is extremely frustrating to embedded developers when they get conflicting advice, especially in this case, when it was *in* /proc in the first place. I'm not sure what to do about this --- my approach is to sometimes say, "f*ck it, that's stupid advice", and ship it to Linus, who tends to be *much* less of a pendant than most of the people who review code --- but that's because I know what I can ignore. (I seriously doubt Linus cares much about whether it ends up the file ends up /debugfs or /proc, and would take the code either way.) But for someone who doesn't understand when you can do this, and who tries to follow every single piece of criticism they get, the end result can often be a huge amount fo wasted time and frustration.
Quoted 3 lines
It would be nice if we could get better at this, since I'm sure this is not the only time when embedded code submissions have gotten what the submitting developers might consider to be a runaround....
Agreed, we could/should do much better.
Agreed, I'm sure that it is frustrating to the contributors. Agreed about Linus taking it either way. :)
Thanks for your summary and bringing it up (yet again).
Quoted 10 lines
(And just to be clear, I'm not criticising your commends; my personal preference is slightly in favor of /proc, but more than anythign else, I consider it a very minor point. I just want to point out that they _started_ with the file in /proc and changed it to /debugfs based on someone NACK'ing their patch, with a "/proc, eeeeewwww" comment. Sometimes I think some code reviewers get too much of a sense of power trip by thinking they can NACK other people's code over their own pet peeves.... instead of approaching it from a somewhat more collegial point of view trying to make the code better. Present company excepted, of course. :-)
Signature · 2 lines
~Randy *** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
In reply to Randy DunlapQuoted 8 lines · Randy Dunlap
Quoted 6 lines
Well, I'll note right now we have a somewhat annoying gap. If you need to export multiple values such that they are consistent with each other, what's the choice? /proc, where some (but not all) kernel developers will say, "eeeeeeviilllll". /sys is explicitly for single value per files only. And then we have /debugfs, where some pendants are kvetching about whether something is "really" debug information.
First of all, I am not a pendant.
Are you sure about that? At the moment, Arve may feel that you're hanging around his neck (although perhaps not looking very pretty!). :-)
Alan Stern
Re: [linux-pm] [PATCH 5/9] PM: suspend_block: Add debugfs file
In reply to Randy DunlapQuoted 8 lines · Randy Dunlap
Quoted 6 lines
Well, I'll note right now we have a somewhat annoying gap. If you need to export multiple values such that they are consistent with each other, what's the choice? /proc, where some (but not all) kernel developers will say, "eeeeeeviilllll". /sys is explicitly for single value per files only. And then we have /debugfs, where some pendants are kvetching about whether something is "really" debug information.
First of all, I am not a pendant.
Are you sure about that? At the moment, Arve may feel that you're hanging around his neck (although perhaps not looking very pretty!). :-)
Alan Stern
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
In reply to Randy DunlapQuoted 11 lines · Randy Dunlap
Quoted 10 lines · Greg KH
Quoted 8 lines · Randy Dunlap
Quoted 2 lines · On Thu, 22 Apr 2010 18:08:54 -0700 Arve Hj?nnev?g wrote:
Report active and inactive suspend blockers in
/sys/kernel/debug/suspend_blockers.This looks more like user interface information than it does debug information. If that's correct, it shouldn't be in debugfs.
Quoted 6 lines
Quoted 3 lines
It's debug-like information, and has more than one value per file, so debugfs seems like the proper place for it. I have no objection to it going there.
I have no objection if it really is debug info, but I'm not convinced of that yet.
Our most common use of this information is to capture it in bugreports (along with process lists, system/radio logs, memory stats, etc) as one additional piece of data used to diagnose a misbehaving device (most commonly to answer the "why does the battery seem to be draining too quickly?" question).
Brian
_______________________________________________
linux-pm mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/linux-pm
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
In reply to Randy DunlapQuoted 11 lines · Randy Dunlap
Quoted 10 lines · Greg KH
Quoted 8 lines · Randy Dunlap
Quoted 2 lines · On Thu, 22 Apr 2010 18:08:54 -0700 Arve Hj?nnev?g wrote:
Report active and inactive suspend blockers in
/sys/kernel/debug/suspend_blockers.This looks more like user interface information than it does debug information. If that's correct, it shouldn't be in debugfs.
Quoted 6 lines
Quoted 3 lines
It's debug-like information, and has more than one value per file, so debugfs seems like the proper place for it. I have no objection to it going there.
I have no objection if it really is debug info, but I'm not convinced of that yet.
Our most common use of this information is to capture it in bugreports (along with process lists, system/radio logs, memory stats, etc) as one additional piece of data used to diagnose a misbehaving device (most commonly to answer the "why does the battery seem to be draining too quickly?" question).
Brian
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
Quoted 16 lines · Brian Swetland
Quoted 15 lines · Randy Dunlap
Quoted 13 lines · Greg KH
Quoted 8 lines · Randy Dunlap
Quoted 2 lines · On Thu, 22 Apr 2010 18:08:54 -0700 Arve Hj?nnev?g wrote:
Report active and inactive suspend blockers in
/sys/kernel/debug/suspend_blockers.This looks more like user interface information than it does debug information. If that's correct, it shouldn't be in debugfs.
It's debug-like information, and has more than one value per file, so debugfs seems like the proper place for it. I have no objection to it going there.
Quoted 8 lines
Quoted 2 lines
I have no objection if it really is debug info, but I'm not convinced of that yet.
Our most common use of this information is to capture it in bugreports (along with process lists, system/radio logs, memory stats, etc) as one additional piece of data used to diagnose a misbehaving device (most commonly to answer the "why does the battery seem to be draining too quickly?" question).
OK, thanks for the info. Sounds good (i.e., it is debug info).
Signature · 2 lines
~Randy *** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
In reply to Brian SwetlandQuoted 16 lines · Brian Swetland
Quoted 15 lines · Randy Dunlap
Quoted 13 lines · Greg KH
Quoted 8 lines · Randy Dunlap
Quoted 2 lines · On Thu, 22 Apr 2010 18:08:54 -0700 Arve Hj?nnev?g wrote:
Report active and inactive suspend blockers in
/sys/kernel/debug/suspend_blockers.This looks more like user interface information than it does debug information. If that's correct, it shouldn't be in debugfs.
It's debug-like information, and has more than one value per file, so debugfs seems like the proper place for it. I have no objection to it going there.
Quoted 8 lines
Quoted 2 lines
I have no objection if it really is debug info, but I'm not convinced of that yet.
Our most common use of this information is to capture it in bugreports (along with process lists, system/radio logs, memory stats, etc) as one additional piece of data used to diagnose a misbehaving device (most commonly to answer the "why does the battery seem to be draining too quickly?" question).
OK, thanks for the info. Sounds good (i.e., it is debug info).
Signature · 2 lines
~Randy *** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file
In reply to Randy DunlapQuoted 8 lines · Randy Dunlap
Quoted 2 lines · On Thu, 22 Apr 2010 18:08:54 -0700 Arve Hj?nnev?g wrote:
Report active and inactive suspend blockers in
/sys/kernel/debug/suspend_blockers.This looks more like user interface information than it does debug information. If that's correct, it shouldn't be in debugfs.
It's debug-like information, and has more than one value per file, so debugfs seems like the proper place for it. I have no objection to it going there.
thanks,
greg k-h
Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Arve HjønnevågQuoted 21 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/power/suspend-blockers.txt | 17 ++++ include/linux/suspend_block_dev.h | 25 ++++++ kernel/power/Kconfig | 9 ++ kernel/power/Makefile | 1 + kernel/power/user_suspend_blocker.c | 128 ++++++++++++++++++++++++++++++ 5 files changed, 180 insertions(+), 0 deletions(-) create mode 100644 include/linux/suspend_block_dev.h create mode 100644 kernel/power/user_suspend_blocker.cDocumentation/power/suspend-blockers.txt +0
-0
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 10 lines
Documentation/power/suspend-blockers.txt +7
-0@@ -95,3 +95,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);
Why not initialize the user suspend blocker struct by default and then allow each BLOCK to specify the name? Also, my guess is it's not really a name so much as a description of why we're blocking suspend, right?
Should the kernel reject empty strings or strings composed only of "non-printing" characters?
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 110
Quoted 6 lines
Documentation/power/suspend-blockers.txt +6
-0+ +To activate a suspend_blocker call: + ioctl(fd, SUSPEND_BLOCKER_IOCTL_BLOCK); + +To unblock call: + ioctl(fd, SUSPEND_BLOCKER_IOCTL_UNBLOCK);
lsof will show which tasks hold the device open but not which ones are blocking suspend. If merely keeping the device open corresponded to blocking suspend then this would be obvious and no ioctls would be necessary -- just write() the name/description.
Do you block/unblock often enough that frequent open/close of the device are a problem? Or has this idea been considered and discarded for other reasons?
Quoted 4 lines
Documentation/power/suspend-blockers.txt +4
-0+ +To destroy the suspend_blocker, close the device: + close(fd); +
<snip>
Quoted 26 lines
kernel/power/user_suspend_blocker.c new file +20
-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>
kernel/power/user_suspend_blocker.c line 30
Quoted 10 lines
kernel/power/user_suspend_blocker.c new file +10
-0+#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);
nit: Usually locks protect data -- not functions.
Couldn't this be part of the user_suspend_blocker struct? That would allow the description/name to change as described above.
kernel/power/user_suspend_blocker.c line 35
Quoted 5 lines
kernel/power/user_suspend_blocker.c new file +5
-0+ +struct user_suspend_blocker { +struct suspend_blocker blocker; +char name[0 ]; +};
<snip>
Cheers,
-Matt Helsley
Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Arve HjønnevågQuoted 21 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/power/suspend-blockers.txt | 17 ++++ include/linux/suspend_block_dev.h | 25 ++++++ kernel/power/Kconfig | 9 ++ kernel/power/Makefile | 1 + kernel/power/user_suspend_blocker.c | 128 ++++++++++++++++++++++++++++++ 5 files changed, 180 insertions(+), 0 deletions(-) create mode 100644 include/linux/suspend_block_dev.h create mode 100644 kernel/power/user_suspend_blocker.cDocumentation/power/suspend-blockers.txt +0
-0
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 10 lines
Documentation/power/suspend-blockers.txt +7
-0@@ -95,3 +95,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);
Why not initialize the user suspend blocker struct by default and then allow each BLOCK to specify the name? Also, my guess is it's not really a name so much as a description of why we're blocking suspend, right?
Should the kernel reject empty strings or strings composed only of "non-printing" characters?
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 110
Quoted 6 lines
Documentation/power/suspend-blockers.txt +6
-0+ +To activate a suspend_blocker call: + ioctl(fd, SUSPEND_BLOCKER_IOCTL_BLOCK); + +To unblock call: + ioctl(fd, SUSPEND_BLOCKER_IOCTL_UNBLOCK);
lsof will show which tasks hold the device open but not which ones are blocking suspend. If merely keeping the device open corresponded to blocking suspend then this would be obvious and no ioctls would be necessary -- just write() the name/description.
Do you block/unblock often enough that frequent open/close of the device are a problem? Or has this idea been considered and discarded for other reasons?
Quoted 4 lines
Documentation/power/suspend-blockers.txt +4
-0+ +To destroy the suspend_blocker, close the device: + close(fd); +
<snip>
Quoted 26 lines
kernel/power/user_suspend_blocker.c new file +20
-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>
kernel/power/user_suspend_blocker.c line 30
Quoted 10 lines
kernel/power/user_suspend_blocker.c new file +10
-0+#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);
nit: Usually locks protect data -- not functions.
Couldn't this be part of the user_suspend_blocker struct? That would allow the description/name to change as described above.
kernel/power/user_suspend_blocker.c line 35
Quoted 5 lines
kernel/power/user_suspend_blocker.c new file +5
-0+ +struct user_suspend_blocker { +struct suspend_blocker blocker; +char name[0 ]; +};
<snip>
Cheers,
-Matt Helsley
Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
2010/4/22 Matt Helsley <[email protected]>:
...
Quoted 11 lines · Arve Hjønnevåg
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 4 lines
Documentation/power/suspend-blockers.txt +4
-0+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);Why not initialize the user suspend blocker struct by default and then allow each BLOCK to specify the name? Also, my guess is it's not really a name so much as a description of why we're blocking suspend, right?
There are stats tracked as long as the suspend blocker exists. Specifying a new name every time you block suspend would make this less useful.
Quoted 3 lines
Should the kernel reject empty strings or strings composed only of "non-printing" characters?
Is there an existing function that check if a sting is "unsafe". If so, I can add a call to this.
Quoted 11 lines
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 110
Quoted 6 lines
Documentation/power/suspend-blockers.txt +6
-0+ +To activate a suspend_blocker call: + ioctl(fd, SUSPEND_BLOCKER_IOCTL_BLOCK); + +To unblock call: + ioctl(fd, SUSPEND_BLOCKER_IOCTL_UNBLOCK);lsof will show which tasks hold the device open but not which ones are blocking suspend. If merely keeping the device open corresponded to blocking suspend then this would be obvious and no ioctls would be necessary -- just
write()the name/description.
We track more information about suspend blockers than this.
Quoted 3 lines
Do you block/unblock often enough that frequent open/close of the device are a problem?
Yes.
...
Quoted 7 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ +static DEFINE_MUTEX(ioctl_lock);nit: Usually locks protect data -- not functions.
Couldn't this be part of the
user_suspend_blockerstruct? That would allow the description/name to change as described above.
It mainly protects the allocation of that struct, so no. Allocating a separate struct in open would work, but does not seem worth it at the moment.
Quoted 12 lines
kernel/power/user_suspend_blocker.c line 35
Quoted 6 lines
kernel/power/user_suspend_blocker.c new file +5
-0+ +struct user_suspend_blocker { + struct suspend_blocker blocker; + char name[0]; +};<snip>
Cheers,
-Matt Helsley
Signature · 1 line
Arve Hjønnevåg
Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Matt Helsley2010/4/22 Matt Helsley <[email protected]>:
...
Quoted 11 lines · Arve Hjønnevåg
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 4 lines
Documentation/power/suspend-blockers.txt +4
-0+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);Why not initialize the user suspend blocker struct by default and then allow each BLOCK to specify the name? Also, my guess is it's not really a name so much as a description of why we're blocking suspend, right?
There are stats tracked as long as the suspend blocker exists. Specifying a new name every time you block suspend would make this less useful.
Quoted 3 lines
Should the kernel reject empty strings or strings composed only of "non-printing" characters?
Is there an existing function that check if a sting is "unsafe". If so, I can add a call to this.
Quoted 11 lines
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 110
Quoted 6 lines
Documentation/power/suspend-blockers.txt +6
-0+ +To activate a suspend_blocker call: + ioctl(fd, SUSPEND_BLOCKER_IOCTL_BLOCK); + +To unblock call: + ioctl(fd, SUSPEND_BLOCKER_IOCTL_UNBLOCK);lsof will show which tasks hold the device open but not which ones are blocking suspend. If merely keeping the device open corresponded to blocking suspend then this would be obvious and no ioctls would be necessary -- just
write()the name/description.
We track more information about suspend blockers than this.
Quoted 3 lines
Do you block/unblock often enough that frequent open/close of the device are a problem?
Yes.
...
Quoted 7 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ +static DEFINE_MUTEX(ioctl_lock);nit: Usually locks protect data -- not functions.
Couldn't this be part of the
user_suspend_blockerstruct? That would allow the description/name to change as described above.
It mainly protects the allocation of that struct, so no. Allocating a separate struct in open would work, but does not seem worth it at the moment.
Quoted 12 lines
kernel/power/user_suspend_blocker.c line 35
Quoted 6 lines
kernel/power/user_suspend_blocker.c new file +5
-0+ +struct user_suspend_blocker { + struct suspend_blocker blocker; + char name[0]; +};<snip>
Cheers,
-Matt Helsley
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Matt HelsleyQuoted 2 lines · Matt Helsley
Should the kernel reject empty strings or strings composed only of "non-printing" characters?
The kernel doesn't care, if you want to use non-printing characters, who is it to complain? :)
thanks,
greg k-h
Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Matt HelsleyQuoted 2 lines · Matt Helsley
Should the kernel reject empty strings or strings composed only of "non-printing" characters?
The kernel doesn't care, if you want to use non-printing characters, who is it to complain? :)
thanks,
greg k-h
Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Arve HjønnevågHi!
Quoted 10 lines
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/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 10 lines
Documentation/power/suspend-blockers.txt +7
-0@@ -95,3 +95,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);
This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
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/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Arve HjønnevågHi!
Quoted 10 lines
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/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 10 lines
Documentation/power/suspend-blockers.txt +7
-0@@ -95,3 +95,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);
This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
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/9] PM: suspend_block: Add driver to access suspend blockers from user-space
Quoted 15 lines · Pavel Machek
Hi!
Quoted 13 lines
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/power/suspend-blockers.txt +0
-0@@ -95,3 +95,20 @@ if (list_empty(&state->pending_work)) else suspend_block(&state->suspend_blocker);
Quoted 11 lines
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 7 lines
Documentation/power/suspend-blockers.txt +7
-0+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);This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
How about specifying the name by an ordinary write() call instead of by an ioctl()?
Alan Stern
Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Pavel MachekQuoted 15 lines · Pavel Machek
Hi!
Quoted 13 lines
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/power/suspend-blockers.txt +0
-0@@ -95,3 +95,20 @@ if (list_empty(&state->pending_work)) else suspend_block(&state->suspend_blocker);
Quoted 11 lines
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 7 lines
Documentation/power/suspend-blockers.txt +7
-0+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);This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
How about specifying the name by an ordinary write() call instead of by an ioctl()?
Alan Stern
Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
Quoted 29 lines · Alan Stern
Quoted 15 lines · Pavel Machek
Hi!
Quoted 13 lines
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/power/suspend-blockers.txt +0
-0@@ -95,3 +95,20 @@ if (list_empty(&state->pending_work))else
suspend_block(&state->suspend_blocker);Quoted 11 lines
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 7 lines
Documentation/power/suspend-blockers.txt +7
-0+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);This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
Quoted 3 lines
How about specifying the name by an ordinary
write()call instead of by anioctl()?
I prefer using ioctls. We have three operations at the moment. Init, block and unblock. If we do init with write but block and unblock using ioctls, it would be pretty strange. Specifying a command and argument in a string to write is more complicated to parse than using ioctls. Or did you have something else in mind?
Signature · 1 line
Arve Hjønnevåg
Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Alan SternQuoted 29 lines · Alan Stern
Quoted 15 lines · Pavel Machek
Hi!
Quoted 13 lines
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/power/suspend-blockers.txt +0
-0@@ -95,3 +95,20 @@ if (list_empty(&state->pending_work))else
suspend_block(&state->suspend_blocker);Quoted 11 lines
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 7 lines
Documentation/power/suspend-blockers.txt +7
-0+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);This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
Quoted 3 lines
How about specifying the name by an ordinary
write()call instead of by anioctl()?
I prefer using ioctls. We have three operations at the moment. Init, block and unblock. If we do init with write but block and unblock using ioctls, it would be pretty strange. Specifying a command and argument in a string to write is more complicated to parse than using ioctls. Or did you have something else in mind?
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
Quoted 30 lines · Arve Hj?nnev?g
Quoted 29 lines · Alan Stern
Quoted 26 lines · Pavel Machek
Hi!
Quoted 13 lines
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/power/suspend-blockers.txt +0
-0@@ -95,3 +95,20 @@ if (list_empty(&state->pending_work))else
suspend_block(&state->suspend_blocker);Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 7 lines
Documentation/power/suspend-blockers.txt +7
-0+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);This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
Quoted 7 lines
Quoted 3 lines
How about specifying the name by an ordinary
write()call instead of by anioctl()?I prefer using ioctls. We have three operations at the moment. Init, block and unblock. If we do init with write but block and unblock using ioctls, it would be pretty strange. Specifying a command and
Why would it be "strange"?
Quoted 2 lines
argument in a string to write is more complicated to parse than using ioctls.
More complicated to parse?
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 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Arve HjønnevågQuoted 30 lines · Arve Hj?nnev?g
Quoted 29 lines · Alan Stern
Quoted 26 lines · Pavel Machek
Hi!
Quoted 13 lines
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/power/suspend-blockers.txt +0
-0@@ -95,3 +95,20 @@ if (list_empty(&state->pending_work))else
suspend_block(&state->suspend_blocker);Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 7 lines
Documentation/power/suspend-blockers.txt +7
-0+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);This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
Quoted 7 lines
Quoted 3 lines
How about specifying the name by an ordinary
write()call instead of by anioctl()?I prefer using ioctls. We have three operations at the moment. Init, block and unblock. If we do init with write but block and unblock using ioctls, it would be pretty strange. Specifying a command and
Why would it be "strange"?
Quoted 2 lines
argument in a string to write is more complicated to parse than using ioctls.
More complicated to parse?
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/9] PM: suspend_block: Add driver to access suspend blockers from user-space
Quoted 35 lines · Pavel Machek
Quoted 34 lines · Arve Hj?nnev?g
Quoted 32 lines · Alan Stern
Quoted 15 lines · Pavel Machek
Hi!
Quoted 13 lines
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/power/suspend-blockers.txt +0
-0@@ -95,3 +95,20 @@ if (list_empty(&state->pending_work))else
suspend_block(&state->suspend_blocker);Quoted 11 lines
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 7 lines
Documentation/power/suspend-blockers.txt +7
-0+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);This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
How about specifying the name by an ordinary
write()call instead of by anioctl()?
Quoted 5 lines
Quoted 3 lines
I prefer using ioctls. We have three operations at the moment. Init, block and unblock. If we do init with write but block and unblock using ioctls, it would be pretty strange. Specifying a command and
Why would it be "strange"?
Why indeed? Using write() is the natural way to pass a data buffer into the kernel, especially a variable-length buffer.
Mixing ioctl() and write() might seem strange at first, but it has plenty of precedent. Consider adjusting the settings for a serial port, for example.
Quoted 4 lines
Quoted 2 lines
argument in a string to write is more complicated to parse than using ioctls.
More complicated to parse?
It shouldn't be -- especially if you assume that the init action must always come first. The first write would contain the suspend blocker's name; all following writes would have to be either "on" or "off". That's not hard to parse.
Alan Stern
Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Pavel MachekQuoted 35 lines · Pavel Machek
Quoted 34 lines · Arve Hj?nnev?g
Quoted 32 lines · Alan Stern
Quoted 15 lines · Pavel Machek
Hi!
Quoted 13 lines
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/power/suspend-blockers.txt +0
-0@@ -95,3 +95,20 @@ if (list_empty(&state->pending_work))else
suspend_block(&state->suspend_blocker);Quoted 11 lines
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 7 lines
Documentation/power/suspend-blockers.txt +7
-0+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);This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
How about specifying the name by an ordinary
write()call instead of by anioctl()?
Quoted 5 lines
Quoted 3 lines
I prefer using ioctls. We have three operations at the moment. Init, block and unblock. If we do init with write but block and unblock using ioctls, it would be pretty strange. Specifying a command and
Why would it be "strange"?
Why indeed? Using write() is the natural way to pass a data buffer into the kernel, especially a variable-length buffer.
Mixing ioctl() and write() might seem strange at first, but it has plenty of precedent. Consider adjusting the settings for a serial port, for example.
Quoted 4 lines
Quoted 2 lines
argument in a string to write is more complicated to parse than using ioctls.
More complicated to parse?
It shouldn't be -- especially if you assume that the init action must always come first. The first write would contain the suspend blocker's name; all following writes would have to be either "on" or "off". That's not hard to parse.
Alan Stern
Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
Quoted 41 lines · Alan Stern
Quoted 39 lines · Pavel Machek
Quoted 37 lines · Arve Hj?nnev?g
Quoted 29 lines · Alan Stern
Quoted 15 lines · Pavel Machek
Hi!
Quoted 13 lines
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/power/suspend-blockers.txt +0
-0@@ -95,3 +95,20 @@ if (list_empty(&state->pending_work))else
suspend_block(&state->suspend_blocker);Quoted 11 lines
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 7 lines
Documentation/power/suspend-blockers.txt +7
-0+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);This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
Quoted 3 lines
How about specifying the name by an ordinary
write()call instead of by anioctl()?I prefer using ioctls. We have three operations at the moment. Init, block and unblock. If we do init with write but block and unblock using ioctls, it would be pretty strange. Specifying a command and
Quoted 9 lines
Quoted 1 line
Why would it be "strange"?
Why indeed? Using
write()is the natural way to pass a data buffer into the kernel, especially a variable-length buffer.Mixing
ioctl()andwrite()might seem strange at first, but it has plenty of precedent. Consider adjusting the settings for a serial port, for example.
That sound like to opposite situation to me. It uses ioctls for setup and read/write access the data stream.
Quoted 10 lines
Quoted 4 lines
Quoted 2 lines
argument in a string to write is more complicated to parse than using ioctls.
More complicated to parse?
It shouldn't be -- especially if you assume that the init action must always come first. The first write would contain the suspend blocker's name; all following writes would have to be either "on" or "off". That's not hard to parse.
Why should I have to parse a string at all? We already have a control interface, ioctl, where user space can pass a command with data. If we later want to add other commands we can easily add them without breaking existing command. With your interface, where the first write is a name, adding more initialization data later becomes harder. I also don't like that wring the same string twice has a different meaning the second time. With the ioctl interface, you forget to initialize the suspend blocker, it block and unblock operations will fail. With your interface you create a suspend blocker call "on" or "off".
Signature · 1 line
Arve Hjønnevåg
Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Alan SternQuoted 41 lines · Alan Stern
Quoted 39 lines · Pavel Machek
Quoted 37 lines · Arve Hj?nnev?g
Quoted 29 lines · Alan Stern
Quoted 15 lines · Pavel Machek
Hi!
Quoted 13 lines
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/power/suspend-blockers.txt +0
-0@@ -95,3 +95,20 @@ if (list_empty(&state->pending_work))else
suspend_block(&state->suspend_blocker);Quoted 11 lines
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 7 lines
Documentation/power/suspend-blockers.txt +7
-0+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);This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
Quoted 3 lines
How about specifying the name by an ordinary
write()call instead of by anioctl()?I prefer using ioctls. We have three operations at the moment. Init, block and unblock. If we do init with write but block and unblock using ioctls, it would be pretty strange. Specifying a command and
Quoted 9 lines
Quoted 1 line
Why would it be "strange"?
Why indeed? Using
write()is the natural way to pass a data buffer into the kernel, especially a variable-length buffer.Mixing
ioctl()andwrite()might seem strange at first, but it has plenty of precedent. Consider adjusting the settings for a serial port, for example.
That sound like to opposite situation to me. It uses ioctls for setup and read/write access the data stream.
Quoted 10 lines
Quoted 4 lines
Quoted 2 lines
argument in a string to write is more complicated to parse than using ioctls.
More complicated to parse?
It shouldn't be -- especially if you assume that the init action must always come first. The first write would contain the suspend blocker's name; all following writes would have to be either "on" or "off". That's not hard to parse.
Why should I have to parse a string at all? We already have a control interface, ioctl, where user space can pass a command with data. If we later want to add other commands we can easily add them without breaking existing command. With your interface, where the first write is a name, adding more initialization data later becomes harder. I also don't like that wring the same string twice has a different meaning the second time. With the ioctl interface, you forget to initialize the suspend blocker, it block and unblock operations will fail. With your interface you create a suspend blocker call "on" or "off".
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
Quoted 25 lines · Arve Hjønnevåg
Quoted 25 lines
Quoted 16 lines
Quoted 16 lines
Quoted 15 lines
Quoted 11 lines
Review
Quoted 7 lines
(quoted diff) +7
-0+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);This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
How about specifying the name by an ordinary
write()call instead of by anioctl()?Quoted 5 lines
Quoted 3 lines
I prefer using ioctls. We have three operations at the moment. Init, block and unblock. If we do init with write but block and unblock using ioctls, it would be pretty strange. Specifying a command and
Why would it be "strange"?
Why indeed? Using
write()is the natural way to pass a data buffer into the kernel, especially a variable-length buffer.
Quoted 6 lines
Quoted 4 lines
Mixing
ioctl()andwrite()might seem strange at first, but it has plenty of precedent. Consider adjusting the settings for a serial port, for example.That sound like to opposite situation to me. It uses ioctls for setup and read/write access the data stream.
Or you could say that it uses ioctls to send commands and read/write to pass data. That's pretty much what you would be doing.
Let's put it another way: You find it excessively strange to do init using write and to send commands via ioctl, but you don't find it strange to abuse the ioctl number code for passing the string length? The old saying about motes and beams applies here...
If you insist on using ioctl for init, you should use the standard convention for passing variable-length data. The userspace program sets up a fixed-size buffer containing a pointer to the name and the name's length, and it passes the buffer's address as the ioctl argument.
Alan Stern
Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Arve HjønnevågQuoted 25 lines · Arve Hjønnevåg
Quoted 25 lines
Quoted 16 lines
Quoted 16 lines
Quoted 15 lines
Quoted 11 lines
Review
Quoted 7 lines
(quoted diff) +7
-0+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);This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
How about specifying the name by an ordinary
write()call instead of by anioctl()?Quoted 5 lines
Quoted 3 lines
I prefer using ioctls. We have three operations at the moment. Init, block and unblock. If we do init with write but block and unblock using ioctls, it would be pretty strange. Specifying a command and
Why would it be "strange"?
Why indeed? Using
write()is the natural way to pass a data buffer into the kernel, especially a variable-length buffer.
Quoted 6 lines
Quoted 4 lines
Mixing
ioctl()andwrite()might seem strange at first, but it has plenty of precedent. Consider adjusting the settings for a serial port, for example.That sound like to opposite situation to me. It uses ioctls for setup and read/write access the data stream.
Or you could say that it uses ioctls to send commands and read/write to pass data. That's pretty much what you would be doing.
Let's put it another way: You find it excessively strange to do init using write and to send commands via ioctl, but you don't find it strange to abuse the ioctl number code for passing the string length? The old saying about motes and beams applies here...
If you insist on using ioctl for init, you should use the standard convention for passing variable-length data. The userspace program sets up a fixed-size buffer containing a pointer to the name and the name's length, and it passes the buffer's address as the ioctl argument.
Alan Stern
Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
2010/4/26 Alan Stern <[email protected]>:
Quoted 42 lines · Arve Hjønnevåg
Quoted 26 lines
Quoted 26 lines
Quoted 17 lines
Quoted 17 lines
Quoted 16 lines
Quoted 12 lines
Review
Quoted 8 lines
(quoted diff) +7
-0+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);This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
How about specifying the name by an ordinary
write()call instead of by anioctl()?Quoted 5 lines
Quoted 3 lines
I prefer using ioctls. We have three operations at the moment. Init, block and unblock. If we do init with write but block and unblock using ioctls, it would be pretty strange. Specifying a command and
Why would it be "strange"?
Why indeed? Using
write()is the natural way to pass a data buffer into the kernel, especially a variable-length buffer.Quoted 6 lines
Quoted 4 lines
Mixing
ioctl()andwrite()might seem strange at first, but it has plenty of precedent. Consider adjusting the settings for a serial port, for example.That sound like to opposite situation to me. It uses ioctls for setup and read/write access the data stream.
Or you could say that it uses ioctls to send commands and read/write to pass data. That's pretty much what you would be doing.
Let's put it another way: You find it excessively strange to do init using write and to send commands via ioctl, but you don't find it strange to abuse the ioctl number code for passing the string length? The old saying about motes and beams applies here...
Quoted 5 lines
If you insist on using ioctl for init, you should use the standard convention for passing variable-length data. The userspace program sets up a fixed-size buffer containing a pointer to the name and the name's length, and it passes the buffer's address as the ioctl argument.
Are you sure that is the standard? I searched for ioctls with NAME in their name and only found one that passed the name that way. The rest used fixed length string buffers, or passed the buffersize to _IOC like I do. For instance, input.h has ioctls to read string and bitmasks where user space specify the buffer size as an argument to the ioctl macro. These pass data from the kernel to user space, but I don't passing a string length is any worse than passing a buffer size.
Signature · 1 line
Arve Hjønnevåg
Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Alan Stern2010/4/26 Alan Stern <[email protected]>:
Quoted 42 lines · Arve Hjønnevåg
Quoted 26 lines
Quoted 26 lines
Quoted 17 lines
Quoted 17 lines
Quoted 16 lines
Quoted 12 lines
Review
Quoted 8 lines
(quoted diff) +7
-0+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);This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
How about specifying the name by an ordinary
write()call instead of by anioctl()?Quoted 5 lines
Quoted 3 lines
I prefer using ioctls. We have three operations at the moment. Init, block and unblock. If we do init with write but block and unblock using ioctls, it would be pretty strange. Specifying a command and
Why would it be "strange"?
Why indeed? Using
write()is the natural way to pass a data buffer into the kernel, especially a variable-length buffer.Quoted 6 lines
Quoted 4 lines
Mixing
ioctl()andwrite()might seem strange at first, but it has plenty of precedent. Consider adjusting the settings for a serial port, for example.That sound like to opposite situation to me. It uses ioctls for setup and read/write access the data stream.
Or you could say that it uses ioctls to send commands and read/write to pass data. That's pretty much what you would be doing.
Let's put it another way: You find it excessively strange to do init using write and to send commands via ioctl, but you don't find it strange to abuse the ioctl number code for passing the string length? The old saying about motes and beams applies here...
Quoted 5 lines
If you insist on using ioctl for init, you should use the standard convention for passing variable-length data. The userspace program sets up a fixed-size buffer containing a pointer to the name and the name's length, and it passes the buffer's address as the ioctl argument.
Are you sure that is the standard? I searched for ioctls with NAME in their name and only found one that passed the name that way. The rest used fixed length string buffers, or passed the buffersize to _IOC like I do. For instance, input.h has ioctls to read string and bitmasks where user space specify the buffer size as an argument to the ioctl macro. These pass data from the kernel to user space, but I don't passing a string length is any worse than passing a buffer size.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
Quoted 6 lines · Arve Hjønnevåg
Quoted 5 lines
If you insist on using ioctl for init, you should use the standard convention for passing variable-length data. The userspace program sets up a fixed-size buffer containing a pointer to the name and the name's length, and it passes the buffer's address as the ioctl argument.
Quoted 7 lines
Are you sure that is the standard? I searched for ioctls with NAME in their name and only found one that passed the name that way. The rest used fixed length string buffers, or passed the buffersize to
_IOClike I do. For instance,input.hhas ioctls to read string and bitmasks where user space specify the buffer size as an argument to the ioctl macro. These pass data from the kernel to user space, but I don't passing a string length is any worse than passing a buffer size.
You're right. Okay, I withdraw my objection.
Alan Stern
Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Arve HjønnevågQuoted 6 lines · Arve Hjønnevåg
Quoted 5 lines
If you insist on using ioctl for init, you should use the standard convention for passing variable-length data. The userspace program sets up a fixed-size buffer containing a pointer to the name and the name's length, and it passes the buffer's address as the ioctl argument.
Quoted 7 lines
Are you sure that is the standard? I searched for ioctls with NAME in their name and only found one that passed the name that way. The rest used fixed length string buffers, or passed the buffersize to
_IOClike I do. For instance,input.hhas ioctls to read string and bitmasks where user space specify the buffer size as an argument to the ioctl macro. These pass data from the kernel to user space, but I don't passing a string length is any worse than passing a buffer size.
You're right. Okay, I withdraw my objection.
Alan Stern
Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
Quoted 16 lines · Alan Stern
Quoted 6 lines · Arve Hjønnevåg
Quoted 5 lines
If you insist on using ioctl for init, you should use the standard convention for passing variable-length data. The userspace program sets up a fixed-size buffer containing a pointer to the name and the name's length, and it passes the buffer's address as the ioctl argument.
Quoted 7 lines
Are you sure that is the standard? I searched for ioctls with NAME in their name and only found one that passed the name that way. The rest used fixed length string buffers, or passed the buffersize to
_IOClike I do. For instance,input.hhas ioctls to read string and bitmasks where user space specify the buffer size as an argument to the ioctl macro. These pass data from the kernel to user space, but I don't passing a string length is any worse than passing a buffer size.
Quoted 1 line
You're right. Okay, I withdraw my objection.
In the meantime, though, I thought that the suspend blocker might be created by _open() if we found a way to automatically choose a name for it. That'd be kind of logical, since it's later destroyed by _release().
So, what about using the name of the process that opened the special device file (or that name with'0' appended, or generally with a number appended) as the suspend blocker name?
Rafael
Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
2010/4/27 Rafael J. Wysocki <[email protected]>:
Quoted 19 lines · Alan Stern
Quoted 16 lines · Arve Hjønnevåg
Quoted 7 lines
Quoted 6 lines
If you insist on using ioctl for init, you should use the standard convention for passing variable-length data. The userspace program sets up a fixed-size buffer containing a pointer to the name and the name's length, and it passes the buffer's address as the ioctl argument.
Quoted 7 lines
Are you sure that is the standard? I searched for ioctls with NAME in their name and only found one that passed the name that way. The rest used fixed length string buffers, or passed the buffersize to
_IOClike I do. For instance,input.hhas ioctls to read string and bitmasks where user space specify the buffer size as an argument to the ioctl macro. These pass data from the kernel to user space, but I don't passing a string length is any worse than passing a buffer size.Quoted 1 line
You're right. Okay, I withdraw my objection.
Quoted 8 lines
In the meantime, though, I thought that the suspend blocker might be created by
_open()if we found a way to automatically choose a name for it. That'd be kind of logical, since it's later destroyed by_release().So, what about using the name of the process that opened the special device file (or that name with'0' appended, or generally with a number appended) as the suspend blocker name?
I prefer to let user space choose the name since we use more than one suspend blocker in the same process.
Signature · 1 line
Arve Hjønnevåg
Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Rafael J. Wysocki2010/4/27 Rafael J. Wysocki <[email protected]>:
Quoted 19 lines · Alan Stern
Quoted 16 lines · Arve Hjønnevåg
Quoted 7 lines
Quoted 6 lines
If you insist on using ioctl for init, you should use the standard convention for passing variable-length data. The userspace program sets up a fixed-size buffer containing a pointer to the name and the name's length, and it passes the buffer's address as the ioctl argument.
Quoted 7 lines
Are you sure that is the standard? I searched for ioctls with NAME in their name and only found one that passed the name that way. The rest used fixed length string buffers, or passed the buffersize to
_IOClike I do. For instance,input.hhas ioctls to read string and bitmasks where user space specify the buffer size as an argument to the ioctl macro. These pass data from the kernel to user space, but I don't passing a string length is any worse than passing a buffer size.Quoted 1 line
You're right. Okay, I withdraw my objection.
Quoted 8 lines
In the meantime, though, I thought that the suspend blocker might be created by
_open()if we found a way to automatically choose a name for it. That'd be kind of logical, since it's later destroyed by_release().So, what about using the name of the process that opened the special device file (or that name with'0' appended, or generally with a number appended) as the suspend blocker name?
I prefer to let user space choose the name since we use more than one suspend blocker in the same process.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Alan SternQuoted 16 lines · Alan Stern
Quoted 6 lines · Arve Hjønnevåg
Quoted 5 lines
If you insist on using ioctl for init, you should use the standard convention for passing variable-length data. The userspace program sets up a fixed-size buffer containing a pointer to the name and the name's length, and it passes the buffer's address as the ioctl argument.
Quoted 7 lines
Are you sure that is the standard? I searched for ioctls with NAME in their name and only found one that passed the name that way. The rest used fixed length string buffers, or passed the buffersize to
_IOClike I do. For instance,input.hhas ioctls to read string and bitmasks where user space specify the buffer size as an argument to the ioctl macro. These pass data from the kernel to user space, but I don't passing a string length is any worse than passing a buffer size.
Quoted 1 line
You're right. Okay, I withdraw my objection.
In the meantime, though, I thought that the suspend blocker might be created by _open() if we found a way to automatically choose a name for it. That'd be kind of logical, since it's later destroyed by _release().
So, what about using the name of the process that opened the special device file (or that name with'0' appended, or generally with a number appended) as the suspend blocker name?
Rafael
Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Pavel MachekQuoted 8 lines · Pavel Machek
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 4 lines
Documentation/power/suspend-blockers.txt +4
-0+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);This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
Yep, and there's nothing wrong with that IMHO. It's a clever use of the _IOC encoding scheme.
- Ted
Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to Pavel MachekQuoted 8 lines · Pavel Machek
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 4 lines
Documentation/power/suspend-blockers.txt +4
-0+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);This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
Yep, and there's nothing wrong with that IMHO. It's a clever use of the _IOC encoding scheme.
- Ted
Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
Quoted 10 lines · On Fri 2010-04-23 21:53:34, [email protected] wrote:
Quoted 8 lines · Pavel Machek
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 4 lines
Documentation/power/suspend-blockers.txt +4
-0+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);This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
Quoted 2 lines
Yep, and there's nothing wrong with that IMHO. It's a clever use of the
_IOCencoding scheme.
I'm not sure if "clever" is right word. So what if strlen is in 2GB range, will macros still work correctly?
Will it be easy for strace to display such ioctls?
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 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space
In reply to [email protected]Quoted 10 lines · On Fri 2010-04-23 21:53:34, [email protected] wrote:
Quoted 8 lines · Pavel Machek
Documentation/power/suspend-blockers.txt if (list_empty(&state->pending_work)) · line 104
Quoted 4 lines
Documentation/power/suspend-blockers.txt +4
-0+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);This seems like very wrong idea -- it uses different ioctl number for each length AFAICT.
Quoted 2 lines
Yep, and there's nothing wrong with that IMHO. It's a clever use of the
_IOCencoding scheme.
I'm not sure if "clever" is right word. So what if strlen is in 2GB range, will macros still work correctly?
Will it be easy for strace to display such ioctls?
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/9] PM: Add suspend block api.
In reply to Arve HjønnevågQuoted 9 lines · On Thu, 22 Apr 2010, [UTF-8] Arve HjønnevÃ¥g wrote:
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.
Documentation/power/suspend-blockers.txt line 10
Quoted 10 lines
Documentation/power/suspend-blockers.txt new file +10
-0@@ -0,0 +1,97 @@ +Suspend blockers +================ + +Suspend blockers provide a mechanism for device drivers and user-space processes +to prevent the system from entering suspend. By default writing to +/sys/power/state will ignore suspend blockers. Writing "opportunistic" to +/sys/power/policy will change the behaviour of /sys/power/state to repeatedly +enter the requested state when no suspend blockers are active. Writing "on" to +/sys/power/state will cancel the automatic sleep request. Suspend blockers do +not affect sleep states entered from idle.
You should document that writing "forced" to /sys/power/policy causes the /sys/power/state to return to normal operation (i.e., ignoring suspend blockers).
Documentation/power/suspend-blockers.txt
Quoted 5 lines
Documentation/power/suspend-blockers.txt new file +5
-0+In cell phones or other embedded systems where powering the screen is a +significant drain on the battery, suspend blockers can be used to allow +user-space to decide whether a keystroke received while the system is suspended +should cause the screen to be turned back on or allow the system to go back into +suspend.
The description below is incomplete and consequently doesn't make sense.
Quoted 2 lines
Use
set_irq_wakeor a platform specific api to make sure the keypad
+interrupt wakes up the cpu.
And as part of waking up the CPU, the screen driver's resume method is called. Presumably this will turn the screen back on. If it doesn't, you need to explain why not.
Quoted 11 lines
Once the keypad driver has resumed, the sequence of
Documentation/power/suspend-blockers.txt new file +10
-0+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.
Documentation/power/suspend-blockers.txt line 53
Quoted 10 lines
Documentation/power/suspend-blockers.txt new file +10
-0+- 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 is highly misleading. Although you _say_ this decision is about whether or not to leave the screen off, it _really_ is about whether or not to let the system automatically suspend again. In other words, the exposition confuses suspending the system with turning off the screen. Unless you can keep the two notions separate and explain more clearly what's going on, this whole section should be removed from the documentation.
Quoted 19 lines
Documentation/power/suspend-blockers.txt new file +19
-0+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); +} +
Documentation/power/suspend-blockers.txt line 90
Quoted 10 lines
Documentation/power/suspend-blockers.txt new file +10
-0+When the driver determines that it needs to run (usually in an interrupt +handler) it calls suspend_block: + suspend_block(&state->suspend_blocker); + +When it no longer needs to run it calls suspend_unblock: + suspend_unblock(&state->suspend_blocker); + +Calling suspend_block when the suspend blocker is active or suspend_unblock when +it is not active has no effect. This allows drivers to update their state and +call suspend suspend_block or suspend_unblock based on the result.
But suspend_block() and suspend_unblock() don't nest. You should mention this.
Quoted 3 lines
include/linux/suspend_blocker.h new file +0
-0@@ -0,0 +1,60 @@
...
Quoted 6 lines
include/linux/suspend_blocker.h new file +6
-0+/** +* struct suspend_blocker - the basic suspend_blocker structure +* @flags: Tracks initialized and active state. +* @name: Name used for debugging. +* +* When a suspend_blocker is active it prevents the system from entering
include/linux/suspend_blocker.h line 34
Quoted 10 lines
include/linux/suspend_blocker.h new file +10
-0+* suspend. +* +* The suspend_blocker structure must be initialized by suspend_blocker_init() +*/ + +struct suspend_blocker { +#ifdef CONFIG_SUSPEND_BLOCKERS +atomic_t flags; +const char *name; +#endif
Why is flags an atomic_t? Are you worried that drivers might try to activate a suspend_blocker at the same time that it is being destroyed? If this happens, does the code do the right thing? I don't think it does -- if a race occurs, suspend_block() will leave flags set to the wrong value. The same goes for suspend_unblock().
Since these routines don't nest, there is also the possibility of a race between suspend_block() and suspend_unblock(). If the race goes one way the blocker is active; the other way it isn't. Given that such problems already exist, why worry about what happens when the suspend blocker is destroyed?
Alan Stern
Re: [PATCH 1/9] PM: Add suspend block api.
In reply to Arve HjønnevågQuoted 9 lines · On Thu, 22 Apr 2010, [UTF-8] Arve HjønnevÃ¥g wrote:
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.
Documentation/power/suspend-blockers.txt line 10
Quoted 10 lines
Documentation/power/suspend-blockers.txt new file +10
-0@@ -0,0 +1,97 @@ +Suspend blockers +================ + +Suspend blockers provide a mechanism for device drivers and user-space processes +to prevent the system from entering suspend. By default writing to +/sys/power/state will ignore suspend blockers. Writing "opportunistic" to +/sys/power/policy will change the behaviour of /sys/power/state to repeatedly +enter the requested state when no suspend blockers are active. Writing "on" to +/sys/power/state will cancel the automatic sleep request. Suspend blockers do +not affect sleep states entered from idle.
You should document that writing "forced" to /sys/power/policy causes the /sys/power/state to return to normal operation (i.e., ignoring suspend blockers).
Documentation/power/suspend-blockers.txt
Quoted 5 lines
Documentation/power/suspend-blockers.txt new file +5
-0+In cell phones or other embedded systems where powering the screen is a +significant drain on the battery, suspend blockers can be used to allow +user-space to decide whether a keystroke received while the system is suspended +should cause the screen to be turned back on or allow the system to go back into +suspend.
The description below is incomplete and consequently doesn't make sense.
Quoted 2 lines
Use
set_irq_wakeor a platform specific api to make sure the keypad
+interrupt wakes up the cpu.
And as part of waking up the CPU, the screen driver's resume method is called. Presumably this will turn the screen back on. If it doesn't, you need to explain why not.
Quoted 11 lines
Once the keypad driver has resumed, the sequence of
Documentation/power/suspend-blockers.txt new file +10
-0+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.
Documentation/power/suspend-blockers.txt line 53
Quoted 10 lines
Documentation/power/suspend-blockers.txt new file +10
-0+- 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 is highly misleading. Although you _say_ this decision is about whether or not to leave the screen off, it _really_ is about whether or not to let the system automatically suspend again. In other words, the exposition confuses suspending the system with turning off the screen. Unless you can keep the two notions separate and explain more clearly what's going on, this whole section should be removed from the documentation.
Quoted 19 lines
Documentation/power/suspend-blockers.txt new file +19
-0+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); +} +
Documentation/power/suspend-blockers.txt line 90
Quoted 10 lines
Documentation/power/suspend-blockers.txt new file +10
-0+When the driver determines that it needs to run (usually in an interrupt +handler) it calls suspend_block: + suspend_block(&state->suspend_blocker); + +When it no longer needs to run it calls suspend_unblock: + suspend_unblock(&state->suspend_blocker); + +Calling suspend_block when the suspend blocker is active or suspend_unblock when +it is not active has no effect. This allows drivers to update their state and +call suspend suspend_block or suspend_unblock based on the result.
But suspend_block() and suspend_unblock() don't nest. You should mention this.
Quoted 3 lines
include/linux/suspend_blocker.h new file +0
-0@@ -0,0 +1,60 @@
...
Quoted 6 lines
include/linux/suspend_blocker.h new file +6
-0+/** +* struct suspend_blocker - the basic suspend_blocker structure +* @flags: Tracks initialized and active state. +* @name: Name used for debugging. +* +* When a suspend_blocker is active it prevents the system from entering
include/linux/suspend_blocker.h line 34
Quoted 10 lines
include/linux/suspend_blocker.h new file +10
-0+* suspend. +* +* The suspend_blocker structure must be initialized by suspend_blocker_init() +*/ + +struct suspend_blocker { +#ifdef CONFIG_SUSPEND_BLOCKERS +atomic_t flags; +const char *name; +#endif
Why is flags an atomic_t? Are you worried that drivers might try to activate a suspend_blocker at the same time that it is being destroyed? If this happens, does the code do the right thing? I don't think it does -- if a race occurs, suspend_block() will leave flags set to the wrong value. The same goes for suspend_unblock().
Since these routines don't nest, there is also the possibility of a race between suspend_block() and suspend_unblock(). If the race goes one way the blocker is active; the other way it isn't. Given that such problems already exist, why worry about what happens when the suspend blocker is destroyed?
Alan Stern
Re: [PATCH 1/9] PM: Add suspend block api.
Quoted 14 lines · Alan Stern
include/linux/suspend_blocker.h line 34
Quoted 5 lines · On Thu, 22 Apr 2010, [UTF-8] Arve HjønnevÃ¥g wrote:
include/linux/suspend_blocker.h new file +5
-0+struct suspend_blocker { +#ifdef CONFIG_SUSPEND_BLOCKERS +atomic_t flags; +const char *name; +#endif Why is flags an
atomic_t? Are you worried that drivers might try to activate asuspend_blockerat the same time that it is being destroyed? If this happens, does the code do the right thing? I don't think it does -- if a race occurs,suspend_block()will leave flags set to the wrong value. The same goes forsuspend_unblock().
Quoted 5 lines
Since these routines don't nest, there is also the possibility of a race between
suspend_block()andsuspend_unblock(). If the race goes one way the blocker is active; the other way it isn't. Given that such problems already exist, why worry about what happens when the suspend blocker is destroyed?
Having now read the later patches, I see that you switch over to using a spinlock instead of an atomic_t. My suggestion is to use a spinlock right from the start. It will be less confusing.
Alan Stern
Re: [linux-pm] [PATCH 1/9] PM: Add suspend block api.
In reply to Alan SternQuoted 14 lines · Alan Stern
include/linux/suspend_blocker.h line 34
Quoted 5 lines · On Thu, 22 Apr 2010, [UTF-8] Arve HjønnevÃ¥g wrote:
include/linux/suspend_blocker.h new file +5
-0+struct suspend_blocker { +#ifdef CONFIG_SUSPEND_BLOCKERS +atomic_t flags; +const char *name; +#endif Why is flags an
atomic_t? Are you worried that drivers might try to activate asuspend_blockerat the same time that it is being destroyed? If this happens, does the code do the right thing? I don't think it does -- if a race occurs,suspend_block()will leave flags set to the wrong value. The same goes forsuspend_unblock().
Quoted 5 lines
Since these routines don't nest, there is also the possibility of a race between
suspend_block()andsuspend_unblock(). If the race goes one way the blocker is active; the other way it isn't. Given that such problems already exist, why worry about what happens when the suspend blocker is destroyed?
Having now read the later patches, I see that you switch over to using a spinlock instead of an atomic_t. My suggestion is to use a spinlock right from the start. It will be less confusing.
Alan Stern
Re: [PATCH 1/9] PM: Add suspend block api.
In reply to Alan Stern2010/4/23 Alan Stern <[email protected]>:
Quoted 1 line · On Thu, 22 Apr 2010, [UTF-8] Arve Hjønnevåg wrote:
...
Quoted 7 lines
Documentation/power/suspend-blockers.txt line 90
Quoted 3 lines
Documentation/power/suspend-blockers.txt new file +3
-0+Calling suspend_block when the suspend blocker is active or suspend_unblock when +it is not active has no effect. This allows drivers to update their state and +call suspend suspend_block or suspend_unblock based on the result.But
suspend_block()andsuspend_unblock()don't nest. You should mention this.
I'm not sure what you mean by this? I think the first sentence dictates nesting is not supported.
I think the rest of your comments will be addressed in the next version of the document, that I worked with Rafael on.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 1/9] PM: Add suspend block api.
In reply to Alan Stern2010/4/23 Alan Stern <[email protected]>:
Quoted 1 line · On Thu, 22 Apr 2010, [UTF-8] Arve Hjønnevåg wrote:
...
Quoted 7 lines
Documentation/power/suspend-blockers.txt line 90
Quoted 3 lines
Documentation/power/suspend-blockers.txt new file +3
-0+Calling suspend_block when the suspend blocker is active or suspend_unblock when +it is not active has no effect. This allows drivers to update their state and +call suspend suspend_block or suspend_unblock based on the result.But
suspend_block()andsuspend_unblock()don't nest. You should mention this.
I'm not sure what you mean by this? I think the first sentence dictates nesting is not supported.
I think the rest of your comments will be addressed in the next version of the document, that I worked with Rafael on.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 1/9] PM: Add suspend block api.
Quoted 11 lines · Arve Hjønnevåg
2010/4/23 Alan Stern <[email protected]>:
Quoted 1 line · On Thu, 22 Apr 2010, [UTF-8] Arve Hjønnevåg wrote:
...
Quoted 7 lines
Documentation/power/suspend-blockers.txt line 90
Quoted 3 lines
Documentation/power/suspend-blockers.txt new file +3
-0+Calling suspend_block when the suspend blocker is active or suspend_unblock when +it is not active has no effect. This allows drivers to update their state and +call suspend suspend_block or suspend_unblock based on the result.But
suspend_block()andsuspend_unblock()don't nest. You should mention this.
Quoted 2 lines
I'm not sure what you mean by this? I think the first sentence dictates nesting is not supported.
That fact is implicit from the first sentence. Mentioning it _explicitly_ will help people to understand more easily. You don't have to add much; a parenthetical remark would be enough:
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 ...
Alan Stern
Re: [PATCH 1/9] PM: Add suspend block api.
In reply to Arve HjønnevågQuoted 11 lines · Arve Hjønnevåg
2010/4/23 Alan Stern <[email protected]>:
Quoted 1 line · On Thu, 22 Apr 2010, [UTF-8] Arve Hjønnevåg wrote:
...
Quoted 7 lines
Documentation/power/suspend-blockers.txt line 90
Quoted 3 lines
Documentation/power/suspend-blockers.txt new file +3
-0+Calling suspend_block when the suspend blocker is active or suspend_unblock when +it is not active has no effect. This allows drivers to update their state and +call suspend suspend_block or suspend_unblock based on the result.But
suspend_block()andsuspend_unblock()don't nest. You should mention this.
Quoted 2 lines
I'm not sure what you mean by this? I think the first sentence dictates nesting is not supported.
That fact is implicit from the first sentence. Mentioning it _explicitly_ will help people to understand more easily. You don't have to add much; a parenthetical remark would be enough:
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 ...
Alan Stern
Re: [PATCH 1/9] PM: Add suspend block api.
2010/4/23 Alan Stern <[email protected]>:
Quoted 16 lines · Arve Hjønnevåg
Quoted 12 lines
2010/4/23 Alan Stern <[email protected]>:
Quoted 1 line · On Thu, 22 Apr 2010, [UTF-8] Arve Hjønnevåg wrote:
...
Quoted 7 lines
Documentation/power/suspend-blockers.txt line 90
Quoted 3 lines
Documentation/power/suspend-blockers.txt new file +3
-0+Calling suspend_block when the suspend blocker is active or suspend_unblock when +it is not active has no effect. This allows drivers to update their state and +call suspend suspend_block or suspend_unblock based on the result.But
suspend_block()andsuspend_unblock()don't nest. You should mention this.Quoted 2 lines
I'm not sure what you mean by this? I think the first sentence dictates nesting is not supported.
Quoted 8 lines
That fact is implicit from the first sentence. Mentioning it _explicitly_ will help people to understand more easily. You don't have to add much; a parenthetical remark would be enough:
Calling
suspend_blockwhen the suspend blocker is active orsuspend_unblockwhen it is not active has no effect (i.e., these functions don't nest). This allows drivers to ...
OK.
Signature · 1 line
Arve Hjønnevåg
Re: [PATCH 1/9] PM: Add suspend block api.
In reply to Alan Stern2010/4/23 Alan Stern <[email protected]>:
Quoted 16 lines · Arve Hjønnevåg
Quoted 12 lines
2010/4/23 Alan Stern <[email protected]>:
Quoted 1 line · On Thu, 22 Apr 2010, [UTF-8] Arve Hjønnevåg wrote:
...
Quoted 7 lines
Documentation/power/suspend-blockers.txt line 90
Quoted 3 lines
Documentation/power/suspend-blockers.txt new file +3
-0+Calling suspend_block when the suspend blocker is active or suspend_unblock when +it is not active has no effect. This allows drivers to update their state and +call suspend suspend_block or suspend_unblock based on the result.But
suspend_block()andsuspend_unblock()don't nest. You should mention this.Quoted 2 lines
I'm not sure what you mean by this? I think the first sentence dictates nesting is not supported.
Quoted 8 lines
That fact is implicit from the first sentence. Mentioning it _explicitly_ will help people to understand more easily. You don't have to add much; a parenthetical remark would be enough:
Calling
suspend_blockwhen the suspend blocker is active orsuspend_unblockwhen it is not active has no effect (i.e., these functions don't nest). This allows drivers to ...
OK.
Signature · 1 line
Arve Hjønnevåg
Quoted 6 lines · Arve Hj??nnev??g
This patch series adds a suspend-block api that provides the same functionality as the android wakelock api. The code is mostly the same as version 3 posted last year, but the main entry point has changed back to
/sys/power/statewith a new/sys/power/policyto alter its behavior. Timeout support is not included in this initial patchset.
Yeah! Thanks for respining this and pushing it out. This should help lots of drivers get merged after this is in-tree.
thanks again,
greg k-h
Quoted 6 lines · Arve Hj??nnev??g
This patch series adds a suspend-block api that provides the same functionality as the android wakelock api. The code is mostly the same as version 3 posted last year, but the main entry point has changed back to
/sys/power/statewith a new/sys/power/policyto alter its behavior. Timeout support is not included in this initial patchset.
Yeah! Thanks for respining this and pushing it out. This should help lots of drivers get merged after this is in-tree.
thanks again,
greg k-h