aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-power13
-rw-r--r--drivers/base/power/main.c7
-rw-r--r--drivers/base/power/power.h6
-rw-r--r--kernel/power/main.c31
4 files changed, 50 insertions, 7 deletions
diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power
index dcff4d0623ad..d6a801f45b48 100644
--- a/Documentation/ABI/testing/sysfs-power
+++ b/Documentation/ABI/testing/sysfs-power
@@ -101,3 +101,16 @@ Description:
101 101
102 CAUTION: Using it will cause your machine's real-time (CMOS) 102 CAUTION: Using it will cause your machine's real-time (CMOS)
103 clock to be set to a random invalid time after a resume. 103 clock to be set to a random invalid time after a resume.
104
105What: /sys/power/pm_async
106Date: January 2009
107Contact: Rafael J. Wysocki <rjw@sisk.pl>
108Description:
109 The /sys/power/pm_async file controls the switch allowing the
110 user space to enable or disable asynchronous suspend and resume
111 of devices. If enabled, this feature will cause some device
112 drivers' suspend and resume callbacks to be executed in parallel
113 with each other and with the main suspend thread. It is enabled
114 if this file contains "1", which is the default. It may be
115 disabled by writing "0" to this file, in which case all devices
116 will be suspended and resumed synchronously.
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 3b44c201ddad..7e79201b09bb 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -201,7 +201,7 @@ static void dpm_wait(struct device *dev, bool async)
201 if (!dev) 201 if (!dev)
202 return; 202 return;
203 203
204 if (async || dev->power.async_suspend) 204 if (async || (pm_async_enabled && dev->power.async_suspend))
205 wait_for_completion(&dev->power.completion); 205 wait_for_completion(&dev->power.completion);
206} 206}
207 207
@@ -563,7 +563,8 @@ static int device_resume(struct device *dev)
563{ 563{
564 INIT_COMPLETION(dev->power.completion); 564 INIT_COMPLETION(dev->power.completion);
565 565
566 if (dev->power.async_suspend && !pm_trace_is_enabled()) { 566 if (pm_async_enabled && dev->power.async_suspend
567 && !pm_trace_is_enabled()) {
567 get_device(dev); 568 get_device(dev);
568 async_schedule(async_resume, dev); 569 async_schedule(async_resume, dev);
569 return 0; 570 return 0;
@@ -867,7 +868,7 @@ static int device_suspend(struct device *dev)
867{ 868{
868 INIT_COMPLETION(dev->power.completion); 869 INIT_COMPLETION(dev->power.completion);
869 870
870 if (dev->power.async_suspend) { 871 if (pm_async_enabled && dev->power.async_suspend) {
871 get_device(dev); 872 get_device(dev);
872 async_schedule(async_suspend, dev); 873 async_schedule(async_suspend, dev);
873 return 0; 874 return 0;
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index b8fa1aa5225a..c0bd03c83b9c 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -12,10 +12,10 @@ static inline void pm_runtime_remove(struct device *dev) {}
12 12
13#ifdef CONFIG_PM_SLEEP 13#ifdef CONFIG_PM_SLEEP
14 14
15/* 15/* kernel/power/main.c */
16 * main.c 16extern int pm_async_enabled;
17 */
18 17
18/* drivers/base/power/main.c */
19extern struct list_head dpm_list; /* The active device list */ 19extern struct list_head dpm_list; /* The active device list */
20 20
21static inline struct device *to_device(struct list_head *entry) 21static inline struct device *to_device(struct list_head *entry)
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 0998c7139053..b58800b21fc0 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -44,6 +44,32 @@ int pm_notifier_call_chain(unsigned long val)
44 == NOTIFY_BAD) ? -EINVAL : 0; 44 == NOTIFY_BAD) ? -EINVAL : 0;
45} 45}
46 46
47/* If set, devices may be suspended and resumed asynchronously. */
48int pm_async_enabled = 1;
49
50static ssize_t pm_async_show(struct kobject *kobj, struct kobj_attribute *attr,
51 char *buf)
52{
53 return sprintf(buf, "%d\n", pm_async_enabled);
54}
55
56static ssize_t pm_async_store(struct kobject *kobj, struct kobj_attribute *attr,
57 const char *buf, size_t n)
58{
59 unsigned long val;
60
61 if (strict_strtoul(buf, 10, &val))
62 return -EINVAL;
63
64 if (val > 1)
65 return -EINVAL;
66
67 pm_async_enabled = val;
68 return n;
69}
70
71power_attr(pm_async);
72
47#ifdef CONFIG_PM_DEBUG 73#ifdef CONFIG_PM_DEBUG
48int pm_test_level = TEST_NONE; 74int pm_test_level = TEST_NONE;
49 75
@@ -208,9 +234,12 @@ static struct attribute * g[] = {
208#ifdef CONFIG_PM_TRACE 234#ifdef CONFIG_PM_TRACE
209 &pm_trace_attr.attr, 235 &pm_trace_attr.attr,
210#endif 236#endif
211#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PM_DEBUG) 237#ifdef CONFIG_PM_SLEEP
238 &pm_async_attr.attr,
239#ifdef CONFIG_PM_DEBUG
212 &pm_test_attr.attr, 240 &pm_test_attr.attr,
213#endif 241#endif
242#endif
214 NULL, 243 NULL,
215}; 244};
216 245