PM / ACPI: Remove references to pm_flags from bus.c
[linux-2.6.git] / kernel / power / main.c
1 /*
2  * kernel/power/main.c - PM subsystem core functionality.
3  *
4  * Copyright (c) 2003 Patrick Mochel
5  * Copyright (c) 2003 Open Source Development Lab
6  * 
7  * This file is released under the GPLv2
8  *
9  */
10
11 #include <linux/kobject.h>
12 #include <linux/string.h>
13 #include <linux/resume-trace.h>
14 #include <linux/workqueue.h>
15
16 #include "power.h"
17
18 DEFINE_MUTEX(pm_mutex);
19
20 #ifdef CONFIG_PM_SLEEP
21
22 unsigned int pm_flags;
23 EXPORT_SYMBOL(pm_flags);
24
25 bool pm_apm_enabled(void)
26 {
27         return !!(pm_flags & PM_APM);
28 }
29
30 void pm_set_acpi_flag(void)
31 {
32         pm_flags |= PM_ACPI;
33 }
34
35 /* Routines for PM-transition notifications */
36
37 static BLOCKING_NOTIFIER_HEAD(pm_chain_head);
38
39 int register_pm_notifier(struct notifier_block *nb)
40 {
41         return blocking_notifier_chain_register(&pm_chain_head, nb);
42 }
43 EXPORT_SYMBOL_GPL(register_pm_notifier);
44
45 int unregister_pm_notifier(struct notifier_block *nb)
46 {
47         return blocking_notifier_chain_unregister(&pm_chain_head, nb);
48 }
49 EXPORT_SYMBOL_GPL(unregister_pm_notifier);
50
51 int pm_notifier_call_chain(unsigned long val)
52 {
53         return (blocking_notifier_call_chain(&pm_chain_head, val, NULL)
54                         == NOTIFY_BAD) ? -EINVAL : 0;
55 }
56
57 /* If set, devices may be suspended and resumed asynchronously. */
58 int pm_async_enabled = 1;
59
60 static ssize_t pm_async_show(struct kobject *kobj, struct kobj_attribute *attr,
61                              char *buf)
62 {
63         return sprintf(buf, "%d\n", pm_async_enabled);
64 }
65
66 static ssize_t pm_async_store(struct kobject *kobj, struct kobj_attribute *attr,
67                               const char *buf, size_t n)
68 {
69         unsigned long val;
70
71         if (strict_strtoul(buf, 10, &val))
72                 return -EINVAL;
73
74         if (val > 1)
75                 return -EINVAL;
76
77         pm_async_enabled = val;
78         return n;
79 }
80
81 power_attr(pm_async);
82
83 #ifdef CONFIG_PM_DEBUG
84 int pm_test_level = TEST_NONE;
85
86 static const char * const pm_tests[__TEST_AFTER_LAST] = {
87         [TEST_NONE] = "none",
88         [TEST_CORE] = "core",
89         [TEST_CPUS] = "processors",
90         [TEST_PLATFORM] = "platform",
91         [TEST_DEVICES] = "devices",
92         [TEST_FREEZER] = "freezer",
93 };
94
95 static ssize_t pm_test_show(struct kobject *kobj, struct kobj_attribute *attr,
96                                 char *buf)
97 {
98         char *s = buf;
99         int level;
100
101         for (level = TEST_FIRST; level <= TEST_MAX; level++)
102                 if (pm_tests[level]) {
103                         if (level == pm_test_level)
104                                 s += sprintf(s, "[%s] ", pm_tests[level]);
105                         else
106                                 s += sprintf(s, "%s ", pm_tests[level]);
107                 }
108
109         if (s != buf)
110                 /* convert the last space to a newline */
111                 *(s-1) = '\n';
112
113         return (s - buf);
114 }
115
116 static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr,
117                                 const char *buf, size_t n)
118 {
119         const char * const *s;
120         int level;
121         char *p;
122         int len;
123         int error = -EINVAL;
124
125         p = memchr(buf, '\n', n);
126         len = p ? p - buf : n;
127
128         mutex_lock(&pm_mutex);
129
130         level = TEST_FIRST;
131         for (s = &pm_tests[level]; level <= TEST_MAX; s++, level++)
132                 if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) {
133                         pm_test_level = level;
134                         error = 0;
135                         break;
136                 }
137
138         mutex_unlock(&pm_mutex);
139
140         return error ? error : n;
141 }
142
143 power_attr(pm_test);
144 #endif /* CONFIG_PM_DEBUG */
145
146 #endif /* CONFIG_PM_SLEEP */
147
148 struct kobject *power_kobj;
149
150 /**
151  *      state - control system power state.
152  *
153  *      show() returns what states are supported, which is hard-coded to
154  *      'standby' (Power-On Suspend), 'mem' (Suspend-to-RAM), and
155  *      'disk' (Suspend-to-Disk).
156  *
157  *      store() accepts one of those strings, translates it into the 
158  *      proper enumerated value, and initiates a suspend transition.
159  */
160 static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
161                           char *buf)
162 {
163         char *s = buf;
164 #ifdef CONFIG_SUSPEND
165         int i;
166
167         for (i = 0; i < PM_SUSPEND_MAX; i++) {
168                 if (pm_states[i] && valid_state(i))
169                         s += sprintf(s,"%s ", pm_states[i]);
170         }
171 #endif
172 #ifdef CONFIG_HIBERNATION
173         s += sprintf(s, "%s\n", "disk");
174 #else
175         if (s != buf)
176                 /* convert the last space to a newline */
177                 *(s-1) = '\n';
178 #endif
179         return (s - buf);
180 }
181
182 static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
183                            const char *buf, size_t n)
184 {
185 #ifdef CONFIG_SUSPEND
186         suspend_state_t state = PM_SUSPEND_STANDBY;
187         const char * const *s;
188 #endif
189         char *p;
190         int len;
191         int error = -EINVAL;
192
193         p = memchr(buf, '\n', n);
194         len = p ? p - buf : n;
195
196         /* First, check if we are requested to hibernate */
197         if (len == 4 && !strncmp(buf, "disk", len)) {
198                 error = hibernate();
199   goto Exit;
200         }
201
202 #ifdef CONFIG_SUSPEND
203         for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
204                 if (*s && len == strlen(*s) && !strncmp(buf, *s, len))
205                         break;
206         }
207         if (state < PM_SUSPEND_MAX && *s)
208                 error = enter_state(state);
209 #endif
210
211  Exit:
212         return error ? error : n;
213 }
214
215 power_attr(state);
216
217 #ifdef CONFIG_PM_SLEEP
218 /*
219  * The 'wakeup_count' attribute, along with the functions defined in
220  * drivers/base/power/wakeup.c, provides a means by which wakeup events can be
221  * handled in a non-racy way.
222  *
223  * If a wakeup event occurs when the system is in a sleep state, it simply is
224  * woken up.  In turn, if an event that would wake the system up from a sleep
225  * state occurs when it is undergoing a transition to that sleep state, the
226  * transition should be aborted.  Moreover, if such an event occurs when the
227  * system is in the working state, an attempt to start a transition to the
228  * given sleep state should fail during certain period after the detection of
229  * the event.  Using the 'state' attribute alone is not sufficient to satisfy
230  * these requirements, because a wakeup event may occur exactly when 'state'
231  * is being written to and may be delivered to user space right before it is
232  * frozen, so the event will remain only partially processed until the system is
233  * woken up by another event.  In particular, it won't cause the transition to
234  * a sleep state to be aborted.
235  *
236  * This difficulty may be overcome if user space uses 'wakeup_count' before
237  * writing to 'state'.  It first should read from 'wakeup_count' and store
238  * the read value.  Then, after carrying out its own preparations for the system
239  * transition to a sleep state, it should write the stored value to
240  * 'wakeup_count'.  If that fails, at least one wakeup event has occured since
241  * 'wakeup_count' was read and 'state' should not be written to.  Otherwise, it
242  * is allowed to write to 'state', but the transition will be aborted if there
243  * are any wakeup events detected after 'wakeup_count' was written to.
244  */
245
246 static ssize_t wakeup_count_show(struct kobject *kobj,
247                                 struct kobj_attribute *attr,
248                                 char *buf)
249 {
250         unsigned int val;
251
252         return pm_get_wakeup_count(&val) ? sprintf(buf, "%u\n", val) : -EINTR;
253 }
254
255 static ssize_t wakeup_count_store(struct kobject *kobj,
256                                 struct kobj_attribute *attr,
257                                 const char *buf, size_t n)
258 {
259         unsigned int val;
260
261         if (sscanf(buf, "%u", &val) == 1) {
262                 if (pm_save_wakeup_count(val))
263                         return n;
264         }
265         return -EINVAL;
266 }
267
268 power_attr(wakeup_count);
269 #endif /* CONFIG_PM_SLEEP */
270
271 #ifdef CONFIG_PM_TRACE
272 int pm_trace_enabled;
273
274 static ssize_t pm_trace_show(struct kobject *kobj, struct kobj_attribute *attr,
275                              char *buf)
276 {
277         return sprintf(buf, "%d\n", pm_trace_enabled);
278 }
279
280 static ssize_t
281 pm_trace_store(struct kobject *kobj, struct kobj_attribute *attr,
282                const char *buf, size_t n)
283 {
284         int val;
285
286         if (sscanf(buf, "%d", &val) == 1) {
287                 pm_trace_enabled = !!val;
288                 return n;
289         }
290         return -EINVAL;
291 }
292
293 power_attr(pm_trace);
294
295 static ssize_t pm_trace_dev_match_show(struct kobject *kobj,
296                                        struct kobj_attribute *attr,
297                                        char *buf)
298 {
299         return show_trace_dev_match(buf, PAGE_SIZE);
300 }
301
302 static ssize_t
303 pm_trace_dev_match_store(struct kobject *kobj, struct kobj_attribute *attr,
304                          const char *buf, size_t n)
305 {
306         return -EINVAL;
307 }
308
309 power_attr(pm_trace_dev_match);
310
311 #endif /* CONFIG_PM_TRACE */
312
313 static struct attribute * g[] = {
314         &state_attr.attr,
315 #ifdef CONFIG_PM_TRACE
316         &pm_trace_attr.attr,
317         &pm_trace_dev_match_attr.attr,
318 #endif
319 #ifdef CONFIG_PM_SLEEP
320         &pm_async_attr.attr,
321         &wakeup_count_attr.attr,
322 #ifdef CONFIG_PM_DEBUG
323         &pm_test_attr.attr,
324 #endif
325 #endif
326         NULL,
327 };
328
329 static struct attribute_group attr_group = {
330         .attrs = g,
331 };
332
333 #ifdef CONFIG_PM_RUNTIME
334 struct workqueue_struct *pm_wq;
335 EXPORT_SYMBOL_GPL(pm_wq);
336
337 static int __init pm_start_workqueue(void)
338 {
339         pm_wq = alloc_workqueue("pm", WQ_FREEZABLE, 0);
340
341         return pm_wq ? 0 : -ENOMEM;
342 }
343 #else
344 static inline int pm_start_workqueue(void) { return 0; }
345 #endif
346
347 static int __init pm_init(void)
348 {
349         int error = pm_start_workqueue();
350         if (error)
351                 return error;
352         hibernate_image_size_init();
353         power_kobj = kobject_create_and_add("power", NULL);
354         if (!power_kobj)
355                 return -ENOMEM;
356         return sysfs_create_group(power_kobj, &attr_group);
357 }
358
359 core_initcall(pm_init);