Skip to contentSkip to conversation

Suspend block api (version 4)

PATCH In review Arve Hjønnevåg 12 participants 116 messages Apr 23, 2010 – Apr 27, 2010

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

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]>

#1 lore raw

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
new file mode 100644
index 0000000..1c48514
@@ -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
index 5c36ea9..f8fa246 100644
@@ -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
index 4319181..f570801 100644
@@ -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
index 46c5a26..9b468d7 100644
@@ -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
index 56e7dbb..dc42006 100644
@@ -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
#2 lore raw

PATCH 1/9 PM: Add suspend block api.

In reply to Arve Hjønnevåg

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
new file mode 100644
index 0000000..1c48514
@@ -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
index 5c36ea9..f8fa246 100644
@@ -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
index 4319181..f570801 100644
@@ -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
index 46c5a26..9b468d7 100644
@@ -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
index 56e7dbb..dc42006 100644
@@ -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
#3 lore raw

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
index 1c48514..877bd8c 100644
@@ -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
new file mode 100644
index 0000000..24bc5c7
@@ -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
index f8fa246..1ac50ee 100644
@@ -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
index f570801..80086c6 100644
@@ -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
#4 lore raw

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
index 71ae290..d8ebd50 100644
@@ -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
#5 lore raw

PATCH 3/9 PM: suspend_block: Abort task freezing if a suspend_blocker is active.

In reply to Arve Hjønnevåg

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
index 71ae290..d8ebd50 100644
@@ -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
#6 lore raw

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
index 21689cd..1faa433 100755
@@ -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
#7 lore raw

PATCH 4/9 PM: suspend_block: Switch to list of active and inactive suspend blockers

In reply to Arve Hjønnevåg

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
index 21689cd..1faa433 100755
@@ -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
#8 lore raw

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
index 868e8f1..047e910 100644
@@ -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
#9 lore raw

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
index 1faa433..3bb8a6a 100755
@@ -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
index 1ac50ee..3fa2d33 100644
@@ -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
index 9b468d7..75b8849 100644
@@ -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
index dc42006..6d327ea 100644
@@ -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
#10 lore raw

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
index 9466e86..9c5a078 100644
@@ -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
index dee4865..b2aba90 100644
@@ -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
#11 lore raw

PATCH 7/9 PM: Add suspend blocking work.

In reply to 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_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
index 9466e86..9c5a078 100644
@@ -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
index dee4865..b2aba90 100644
@@ -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
#12 lore raw

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
index 2ee6c7a..66e0d16 100644
@@ -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
index 7ed2251..b2d93b4 100644
@@ -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
#13 lore raw

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
index cce75b4..fdf30ba 100644
@@ -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
index ebd2b8f..2232a9d 100644
@@ -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
#14 lore raw

PATCH 9/9 power_supply: Block suspend while power supply change notifications are pending

In reply to Arve Hjønnevåg

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
index cce75b4..fdf30ba 100644
@@ -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
index ebd2b8f..2232a9d 100644
@@ -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
#15 lore raw

Re: [PATCH 8/9] Input: Block suspend while event queue is not empty.

In reply to Arve Hjønnevåg
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_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.

All new ioctls need to be added to Documentation/ioctl/ioctl-number.txt, please.

Quoted 36 lines
---
 drivers/input/evdev.c |   22 ++++++++++++++++++++++
 include/linux/input.h |    3 +++
 2 files changed, 25 insertions(+), 0 deletions(-)
drivers/input/evdev.c +13 -0
index 2ee6c7a..66e0d16 100644
@@ -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
index 7ed2251..b2d93b4 100644

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 ***

maintainer
#16 lore raw

Re: [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_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.

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

---

 drivers/input/evdev.c |   22 ++++++++++++++++++++++
 include/linux/input.h |    3 +++
 2 files changed, 25 insertions(+), 0 deletions(-)
drivers/input/evdev.c +13 -0
index 2ee6c7a..66e0d16 100644
@@ -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 -0
 	default:
 		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
index 7ed2251..b2d93b4 100644
@@ -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 use Documentation/SubmitChecklist when 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
maintainer
#17 lore raw

Re: [PATCH 8/9] Input: Block suspend while event queue is not empty.

In reply to Randy Dunlap
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_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.

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

---

 drivers/input/evdev.c |   22 ++++++++++++++++++++++
 include/linux/input.h |    3 +++
 2 files changed, 25 insertions(+), 0 deletions(-)
drivers/input/evdev.c +13 -0
index 2ee6c7a..66e0d16 100644
@@ -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 -0
 	default:
 		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
index 7ed2251..b2d93b4 100644
@@ -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 use Documentation/SubmitChecklist when 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
#18 lore raw

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_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.

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
#19 lore raw

Re: [PATCH 8/9] Input: Block suspend while event queue is not empty.

In reply to Dmitry Torokhov
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_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.

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
#20 lore raw

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_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.

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

#21 lore raw

Re: [linux-pm] [PATCH 8/9] Input: Block suspend while event queue is not empty.

In reply to Arve Hjønnevåg
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_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.

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

#22 lore raw

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_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.

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

#23 lore raw

Re: [linux-pm] [PATCH 8/9] Input: Block suspend while event queue is not empty.

In reply to Alan Stern
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_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.

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

#24 lore raw

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_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.

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

#25 lore raw

Re: [linux-pm] [PATCH 8/9] Input: Block suspend while event queue is not empty.

In reply to Rafael J. Wysocki
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_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.

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

#26 lore raw

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_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.

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
#27 lore raw

Re: [linux-pm] [PATCH 8/9] Input: Block suspend while event queue is not empty.

In reply to Alan Stern
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_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.

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
#28 lore raw

Re: [PATCH 8/9] Input: Block suspend while event queue is not empty.

In reply to Randy Dunlap

2010/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_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.

All new ioctls need to be added to Documentation/ioctl/ioctl-number.txt, please.

These two appear to already be covered by "'E' all
linux/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
#29 lore raw

Re: [PATCH 8/9] Input: Block suspend while event queue is not empty.

In reply to Randy Dunlap

2010/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_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.

All new ioctls need to be added to Documentation/ioctl/ioctl-number.txt, please.

These two appear to already be covered by "'E' all
linux/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
#30 lore raw

Re: [PATCH 8/9] Input: Block suspend while event queue is not empty.

In reply to Arve Hjønnevåg
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_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.

All new ioctls need to be added to Documentation/ioctl/ioctl-number.txt, please.

Quoted 36 lines
---
 drivers/input/evdev.c |   22 ++++++++++++++++++++++
 include/linux/input.h |    3 +++
 2 files changed, 25 insertions(+), 0 deletions(-)
drivers/input/evdev.c +13 -0
index 2ee6c7a..66e0d16 100644
@@ -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
index 7ed2251..b2d93b4 100644

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 ***

#31 lore raw

PATCH 8/9 Input: Block suspend while event queue is not empty.

In reply to Arve Hjønnevåg

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
index 2ee6c7a..66e0d16 100644
@@ -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
index 7ed2251..b2d93b4 100644
@@ -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
maintainer
#32 lore raw

Re: [PATCH 7/9] PM: Add suspend blocking work.

In reply to Arve Hjønnevåg

Hello,

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_blocker for 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
maintainer
#33 lore raw

Re: [PATCH 7/9] PM: Add suspend blocking work.

In reply to Arve Hjønnevåg

Hello,

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_blocker for 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
#34 lore raw

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_blocker for 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_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.

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.

#35 lore raw

Re: [PATCH 7/9] PM: Add suspend blocking work.

In reply to Tejun Heo
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_blocker for 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_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.

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.

#36 lore raw

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_blocker for 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_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.

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 use cancel_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_BLOCKING needs to ensure that cpu_workqueue_struct has 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->lock can'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
#37 lore raw

Re: [PATCH 7/9] PM: Add suspend blocking work.

In reply to Oleg Nesterov
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_blocker for 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_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.

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 use cancel_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_BLOCKING needs to ensure that cpu_workqueue_struct has 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->lock can'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
#38 lore raw

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_blocker for 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.

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
#39 lore raw

Re: [PATCH 7/9] PM: Add suspend blocking work.

In reply to Arve Hjønnevåg

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_blocker for 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.

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
maintainer
#40 lore raw

Re: [PATCH 7/9] PM: Add suspend blocking work.

In reply to Arve Hjønnevåg

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.

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)", 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.

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_work and cancel_work_sync for 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
maintainer
#41 lore raw

Re: [PATCH 7/9] PM: Add suspend blocking work.

In reply to Arve Hjønnevåg

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.

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)", 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.

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_work and cancel_work_sync for 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
#42 lore raw

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)", 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.

Quoted 6 lines

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.

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_work and cancel_work_sync for 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 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.

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_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.

OK.

Signature · 1 line
Arve Hjønnevåg
#43 lore raw

Re: [PATCH 7/9] PM: Add suspend blocking work.

In reply to Tejun Heo

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)", 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.

Quoted 6 lines

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.

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_work and cancel_work_sync for 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 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.

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_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.

OK.

Signature · 1 line
Arve Hjønnevåg
maintainer
#44 lore raw

Re: [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
#45 lore raw

Re: [PATCH 7/9] PM: Add suspend blocking work.

In reply to Arve Hjønnevåg
Quoted 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->lock can'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)", 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.

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.

#46 lore raw

Re: [PATCH 7/9] PM: Add suspend blocking work.

In reply to Arve Hjønnevåg
Quoted 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->lock can'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)", 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.

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.

#47 lore raw

Re: [PATCH 5/9] PM: suspend_block: Add debugfs file

In reply to Arve Hjønnevåg
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 84 lines
---
 kernel/power/suspend_blocker.c |   44 ++++++++++++++++++++++++++++++++++++++-
 1 files changed, 42 insertions(+), 2 deletions(-)
kernel/power/suspend_blocker.c +33 -2
index 868e8f1..047e910 100644
@@ -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 ***

#48 lore raw

Re: [PATCH 5/9] PM: suspend_block: Add debugfs file

In reply to Arve Hjønnevåg
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 84 lines
---
 kernel/power/suspend_blocker.c |   44 ++++++++++++++++++++++++++++++++++++++-
 1 files changed, 42 insertions(+), 2 deletions(-)
kernel/power/suspend_blocker.c +33 -2
index 868e8f1..047e910 100644
@@ -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 ***

#49 lore raw

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
#50 lore raw

Re: [PATCH 5/9] PM: suspend_block: Add debugfs file

In reply to Randy Dunlap

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
#51 lore raw

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 ***
#52 lore raw

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
#53 lore raw

Re: [PATCH 5/9] PM: suspend_block: Add debugfs file

In reply to Randy Dunlap

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
#54 lore raw

Re: [PATCH 5/9] PM: suspend_block: Add debugfs file

In reply to Randy Dunlap
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.

thanks,

greg k-h

#55 lore raw

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 ***
#56 lore raw

Re: [PATCH 5/9] PM: suspend_block: Add debugfs file

In reply to Greg KH
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 ***
#57 lore raw

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

#58 lore raw

Re: [PATCH 5/9] PM: suspend_block: Add debugfs file

In reply to Randy Dunlap
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

#59 lore raw

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 ***
#60 lore raw

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 ***
#61 lore raw

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

#62 lore raw

Re: [PATCH 5/9] PM: suspend_block: Add debugfs file

In reply to Randy Dunlap
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

#63 lore raw

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 ***
#64 lore raw

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 ***
#65 lore raw

Re: [PATCH 5/9] PM: suspend_block: Add debugfs file

In reply to Randy Dunlap
Quoted 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

#66 lore raw

Re: [linux-pm] [PATCH 5/9] PM: suspend_block: Add debugfs file

In reply to Randy Dunlap
Quoted 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

#67 lore raw

Re: [PATCH 5/9] PM: suspend_block: Add debugfs file

In reply to Randy Dunlap
Quoted 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

#68 lore raw

Re: [PATCH 5/9] PM: suspend_block: Add debugfs file

In reply to Randy Dunlap
Quoted 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

#69 lore raw

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 ***
#70 lore raw

Re: [PATCH 5/9] PM: suspend_block: Add debugfs file

In reply to Brian Swetland
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 ***
#71 lore raw

Re: [PATCH 5/9] PM: suspend_block: Add debugfs file

In reply to Randy Dunlap
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.

thanks,

greg k-h

#72 lore raw

Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Arve Hjønnevåg
Quoted 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 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 +0 -0
index 1c48514..877bd8c 100644

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
new file mode 100644
index 0000000..a9be6f4
@@ -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

#73 lore raw

Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Arve Hjønnevåg
Quoted 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 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 +0 -0
index 1c48514..877bd8c 100644

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
new file mode 100644
index 0000000..a9be6f4
@@ -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

#74 lore raw

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_blocker struct? 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
#75 lore raw

Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Matt Helsley

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_blocker struct? 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
#76 lore raw

Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Matt Helsley
Quoted 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

#77 lore raw

Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Matt Helsley
Quoted 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

#78 lore raw

Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Arve Hjønnevåg

Hi!

Quoted 10 lines

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 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
#79 lore raw

Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Arve Hjønnevåg

Hi!

Quoted 10 lines

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 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
#80 lore raw

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 a suspend_blocker, and to block and unblock suspend. To delete the suspend_blocker, close the device.

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

#81 lore raw

Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Pavel Machek
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 a suspend_blocker, and to block and unblock suspend. To delete the suspend_blocker, close the device.

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

#82 lore raw

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 a suspend_blocker, and to block and unblock suspend. To delete the suspend_blocker, close the device.

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 an ioctl()?

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
#83 lore raw

Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Alan Stern
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 a suspend_blocker, and to block and unblock suspend. To delete the suspend_blocker, close the device.

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 an ioctl()?

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
#84 lore raw

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 a suspend_blocker, and to block and unblock suspend. To delete the suspend_blocker, close the device.

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 an ioctl()?

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
#85 lore raw

Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Arve Hjønnevåg
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 a suspend_blocker, and to block and unblock suspend. To delete the suspend_blocker, close the device.

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 an ioctl()?

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
#86 lore raw

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 a suspend_blocker, and to block and unblock suspend. To delete the suspend_blocker, close the device.

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()?

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

#87 lore raw

Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Pavel Machek
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 a suspend_blocker, and to block and unblock suspend. To delete the suspend_blocker, close the device.

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()?

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

#88 lore raw

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 a suspend_blocker, and to block and unblock suspend. To delete the suspend_blocker, close the device.

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 an ioctl()?

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() and write() 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
#89 lore raw

Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Alan Stern
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 a suspend_blocker, and to block and unblock suspend. To delete the suspend_blocker, close the device.

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 an ioctl()?

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() and write() 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
#90 lore raw

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 an ioctl()?

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() and write() 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

#91 lore raw

Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Arve Hjønnevåg
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 an ioctl()?

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() and write() 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

#92 lore raw

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 an ioctl()?

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() and write() 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
#93 lore raw

Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Alan Stern

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 an ioctl()?

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() and write() 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
#94 lore raw

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 _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.

You're right. Okay, I withdraw my objection.

Alan Stern

#95 lore raw

Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Arve Hjønnevåg
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 _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.

You're right. Okay, I withdraw my objection.

Alan Stern

#96 lore raw

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 _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.

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

#97 lore raw

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 _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.

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
#98 lore raw

Re: [linux-pm] [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Rafael J. Wysocki

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 _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.

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
#99 lore raw

Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Alan Stern
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 _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.

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

#100 lore raw

Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Pavel Machek
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.

Yep, and there's nothing wrong with that IMHO. It's a clever use of the _IOC encoding scheme.

- Ted

#101 lore raw

Re: [PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

In reply to Pavel Machek
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.

Yep, and there's nothing wrong with that IMHO. It's a clever use of the _IOC encoding scheme.

- Ted

#102 lore raw

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 _IOC encoding 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
#103 lore raw

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 _IOC encoding 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
#104 lore raw

Re: [PATCH 1/9] PM: Add suspend block api.

In reply to Arve Hjønnevåg
Quoted 9 lines · On Thu, 22 Apr 2010, [UTF-8] Arve HjønnevÃ¥g wrote:

Adds /sys/power/policy that selects the behaviour of /sys/power/state. After setting the policy to opportunistic, writes to /sys/power/state become non-blocking requests that specify which suspend state to enter when no suspend blockers are active. A special state, "on", stops the process by activating the "main" suspend blocker.

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_wake or 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

#105 lore raw

Re: [PATCH 1/9] PM: Add suspend block api.

In reply to Arve Hjønnevåg
Quoted 9 lines · On Thu, 22 Apr 2010, [UTF-8] Arve HjønnevÃ¥g wrote:

Adds /sys/power/policy that selects the behaviour of /sys/power/state. After setting the policy to opportunistic, writes to /sys/power/state become non-blocking requests that specify which suspend state to enter when no suspend blockers are active. A special state, "on", stops the process by activating the "main" suspend blocker.

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_wake or 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

#106 lore raw

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 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().

Quoted 5 lines

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?

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

#107 lore raw

Re: [linux-pm] [PATCH 1/9] PM: Add suspend block api.

In reply to Alan Stern
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 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().

Quoted 5 lines

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?

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

#108 lore raw

Re: [PATCH 1/9] PM: Add suspend block api.

In reply to Alan Stern

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() and suspend_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
#109 lore raw

Re: [PATCH 1/9] PM: Add suspend block api.

In reply to Alan Stern

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() and suspend_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
#110 lore raw

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() and suspend_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

#111 lore raw

Re: [PATCH 1/9] PM: Add suspend block api.

In reply to Arve Hjønnevåg
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() and suspend_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

#112 lore raw

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() and suspend_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_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 ...

OK.

Signature · 1 line
Arve Hjønnevåg
#113 lore raw

Re: [PATCH 1/9] PM: Add suspend block api.

In reply to Alan Stern

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() and suspend_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_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 ...

OK.

Signature · 1 line
Arve Hjønnevåg
#114 lore raw
In reply to 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/state with a new /sys/power/policy to 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

#115 lore raw
In reply to 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/state with a new /sys/power/policy to 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