Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only
2 : : /*
3 : : * kernel/power/main.c - PM subsystem core functionality.
4 : : *
5 : : * Copyright (c) 2003 Patrick Mochel
6 : : * Copyright (c) 2003 Open Source Development Lab
7 : : */
8 : :
9 : : #include <linux/export.h>
10 : : #include <linux/kobject.h>
11 : : #include <linux/string.h>
12 : : #include <linux/pm-trace.h>
13 : : #include <linux/workqueue.h>
14 : : #include <linux/debugfs.h>
15 : : #include <linux/seq_file.h>
16 : : #include <linux/suspend.h>
17 : : #include <linux/syscalls.h>
18 : : #include <linux/pm_runtime.h>
19 : :
20 : : #include "power.h"
21 : :
22 : : #ifdef CONFIG_PM_SLEEP
23 : :
24 : : void lock_system_sleep(void)
25 : : {
26 : : current->flags |= PF_FREEZER_SKIP;
27 : : mutex_lock(&system_transition_mutex);
28 : : }
29 : : EXPORT_SYMBOL_GPL(lock_system_sleep);
30 : :
31 : : void unlock_system_sleep(void)
32 : : {
33 : : /*
34 : : * Don't use freezer_count() because we don't want the call to
35 : : * try_to_freeze() here.
36 : : *
37 : : * Reason:
38 : : * Fundamentally, we just don't need it, because freezing condition
39 : : * doesn't come into effect until we release the
40 : : * system_transition_mutex lock, since the freezer always works with
41 : : * system_transition_mutex held.
42 : : *
43 : : * More importantly, in the case of hibernation,
44 : : * unlock_system_sleep() gets called in snapshot_read() and
45 : : * snapshot_write() when the freezing condition is still in effect.
46 : : * Which means, if we use try_to_freeze() here, it would make them
47 : : * enter the refrigerator, thus causing hibernation to lockup.
48 : : */
49 : : current->flags &= ~PF_FREEZER_SKIP;
50 : : mutex_unlock(&system_transition_mutex);
51 : : }
52 : : EXPORT_SYMBOL_GPL(unlock_system_sleep);
53 : :
54 : : void ksys_sync_helper(void)
55 : : {
56 : : ktime_t start;
57 : : long elapsed_msecs;
58 : :
59 : : start = ktime_get();
60 : : ksys_sync();
61 : : elapsed_msecs = ktime_to_ms(ktime_sub(ktime_get(), start));
62 : : pr_info("Filesystems sync: %ld.%03ld seconds\n",
63 : : elapsed_msecs / MSEC_PER_SEC, elapsed_msecs % MSEC_PER_SEC);
64 : : }
65 : : EXPORT_SYMBOL_GPL(ksys_sync_helper);
66 : :
67 : : /* Routines for PM-transition notifications */
68 : :
69 : : static BLOCKING_NOTIFIER_HEAD(pm_chain_head);
70 : :
71 : : int register_pm_notifier(struct notifier_block *nb)
72 : : {
73 : : return blocking_notifier_chain_register(&pm_chain_head, nb);
74 : : }
75 : : EXPORT_SYMBOL_GPL(register_pm_notifier);
76 : :
77 : : int unregister_pm_notifier(struct notifier_block *nb)
78 : : {
79 : : return blocking_notifier_chain_unregister(&pm_chain_head, nb);
80 : : }
81 : : EXPORT_SYMBOL_GPL(unregister_pm_notifier);
82 : :
83 : : int __pm_notifier_call_chain(unsigned long val, int nr_to_call, int *nr_calls)
84 : : {
85 : : int ret;
86 : :
87 : : ret = __blocking_notifier_call_chain(&pm_chain_head, val, NULL,
88 : : nr_to_call, nr_calls);
89 : :
90 : : return notifier_to_errno(ret);
91 : : }
92 : : int pm_notifier_call_chain(unsigned long val)
93 : : {
94 : : return __pm_notifier_call_chain(val, -1, NULL);
95 : : }
96 : :
97 : : /* If set, devices may be suspended and resumed asynchronously. */
98 : : int pm_async_enabled = 1;
99 : :
100 : : static ssize_t pm_async_show(struct kobject *kobj, struct kobj_attribute *attr,
101 : : char *buf)
102 : : {
103 : : return sprintf(buf, "%d\n", pm_async_enabled);
104 : : }
105 : :
106 : : static ssize_t pm_async_store(struct kobject *kobj, struct kobj_attribute *attr,
107 : : const char *buf, size_t n)
108 : : {
109 : : unsigned long val;
110 : :
111 : : if (kstrtoul(buf, 10, &val))
112 : : return -EINVAL;
113 : :
114 : : if (val > 1)
115 : : return -EINVAL;
116 : :
117 : : pm_async_enabled = val;
118 : : return n;
119 : : }
120 : :
121 : : power_attr(pm_async);
122 : :
123 : : #ifdef CONFIG_SUSPEND
124 : : static ssize_t mem_sleep_show(struct kobject *kobj, struct kobj_attribute *attr,
125 : : char *buf)
126 : : {
127 : : char *s = buf;
128 : : suspend_state_t i;
129 : :
130 : : for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++)
131 : : if (mem_sleep_states[i]) {
132 : : const char *label = mem_sleep_states[i];
133 : :
134 : : if (mem_sleep_current == i)
135 : : s += sprintf(s, "[%s] ", label);
136 : : else
137 : : s += sprintf(s, "%s ", label);
138 : : }
139 : :
140 : : /* Convert the last space to a newline if needed. */
141 : : if (s != buf)
142 : : *(s-1) = '\n';
143 : :
144 : : return (s - buf);
145 : : }
146 : :
147 : : static suspend_state_t decode_suspend_state(const char *buf, size_t n)
148 : : {
149 : : suspend_state_t state;
150 : : char *p;
151 : : int len;
152 : :
153 : : p = memchr(buf, '\n', n);
154 : : len = p ? p - buf : n;
155 : :
156 : : for (state = PM_SUSPEND_MIN; state < PM_SUSPEND_MAX; state++) {
157 : : const char *label = mem_sleep_states[state];
158 : :
159 : : if (label && len == strlen(label) && !strncmp(buf, label, len))
160 : : return state;
161 : : }
162 : :
163 : : return PM_SUSPEND_ON;
164 : : }
165 : :
166 : : static ssize_t mem_sleep_store(struct kobject *kobj, struct kobj_attribute *attr,
167 : : const char *buf, size_t n)
168 : : {
169 : : suspend_state_t state;
170 : : int error;
171 : :
172 : : error = pm_autosleep_lock();
173 : : if (error)
174 : : return error;
175 : :
176 : : if (pm_autosleep_state() > PM_SUSPEND_ON) {
177 : : error = -EBUSY;
178 : : goto out;
179 : : }
180 : :
181 : : state = decode_suspend_state(buf, n);
182 : : if (state < PM_SUSPEND_MAX && state > PM_SUSPEND_ON)
183 : : mem_sleep_current = state;
184 : : else
185 : : error = -EINVAL;
186 : :
187 : : out:
188 : : pm_autosleep_unlock();
189 : : return error ? error : n;
190 : : }
191 : :
192 : : power_attr(mem_sleep);
193 : : #endif /* CONFIG_SUSPEND */
194 : :
195 : : #ifdef CONFIG_PM_SLEEP_DEBUG
196 : : int pm_test_level = TEST_NONE;
197 : :
198 : : static const char * const pm_tests[__TEST_AFTER_LAST] = {
199 : : [TEST_NONE] = "none",
200 : : [TEST_CORE] = "core",
201 : : [TEST_CPUS] = "processors",
202 : : [TEST_PLATFORM] = "platform",
203 : : [TEST_DEVICES] = "devices",
204 : : [TEST_FREEZER] = "freezer",
205 : : };
206 : :
207 : : static ssize_t pm_test_show(struct kobject *kobj, struct kobj_attribute *attr,
208 : : char *buf)
209 : : {
210 : : char *s = buf;
211 : : int level;
212 : :
213 : : for (level = TEST_FIRST; level <= TEST_MAX; level++)
214 : : if (pm_tests[level]) {
215 : : if (level == pm_test_level)
216 : : s += sprintf(s, "[%s] ", pm_tests[level]);
217 : : else
218 : : s += sprintf(s, "%s ", pm_tests[level]);
219 : : }
220 : :
221 : : if (s != buf)
222 : : /* convert the last space to a newline */
223 : : *(s-1) = '\n';
224 : :
225 : : return (s - buf);
226 : : }
227 : :
228 : : static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr,
229 : : const char *buf, size_t n)
230 : : {
231 : : const char * const *s;
232 : : int level;
233 : : char *p;
234 : : int len;
235 : : int error = -EINVAL;
236 : :
237 : : p = memchr(buf, '\n', n);
238 : : len = p ? p - buf : n;
239 : :
240 : : lock_system_sleep();
241 : :
242 : : level = TEST_FIRST;
243 : : for (s = &pm_tests[level]; level <= TEST_MAX; s++, level++)
244 : : if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) {
245 : : pm_test_level = level;
246 : : error = 0;
247 : : break;
248 : : }
249 : :
250 : : unlock_system_sleep();
251 : :
252 : : return error ? error : n;
253 : : }
254 : :
255 : : power_attr(pm_test);
256 : : #endif /* CONFIG_PM_SLEEP_DEBUG */
257 : :
258 : : static char *suspend_step_name(enum suspend_stat_step step)
259 : : {
260 : : switch (step) {
261 : : case SUSPEND_FREEZE:
262 : : return "freeze";
263 : : case SUSPEND_PREPARE:
264 : : return "prepare";
265 : : case SUSPEND_SUSPEND:
266 : : return "suspend";
267 : : case SUSPEND_SUSPEND_NOIRQ:
268 : : return "suspend_noirq";
269 : : case SUSPEND_RESUME_NOIRQ:
270 : : return "resume_noirq";
271 : : case SUSPEND_RESUME:
272 : : return "resume";
273 : : default:
274 : : return "";
275 : : }
276 : : }
277 : :
278 : : #define suspend_attr(_name) \
279 : : static ssize_t _name##_show(struct kobject *kobj, \
280 : : struct kobj_attribute *attr, char *buf) \
281 : : { \
282 : : return sprintf(buf, "%d\n", suspend_stats._name); \
283 : : } \
284 : : static struct kobj_attribute _name = __ATTR_RO(_name)
285 : :
286 : : suspend_attr(success);
287 : : suspend_attr(fail);
288 : : suspend_attr(failed_freeze);
289 : : suspend_attr(failed_prepare);
290 : : suspend_attr(failed_suspend);
291 : : suspend_attr(failed_suspend_late);
292 : : suspend_attr(failed_suspend_noirq);
293 : : suspend_attr(failed_resume);
294 : : suspend_attr(failed_resume_early);
295 : : suspend_attr(failed_resume_noirq);
296 : :
297 : : static ssize_t last_failed_dev_show(struct kobject *kobj,
298 : : struct kobj_attribute *attr, char *buf)
299 : : {
300 : : int index;
301 : : char *last_failed_dev = NULL;
302 : :
303 : : index = suspend_stats.last_failed_dev + REC_FAILED_NUM - 1;
304 : : index %= REC_FAILED_NUM;
305 : : last_failed_dev = suspend_stats.failed_devs[index];
306 : :
307 : : return sprintf(buf, "%s\n", last_failed_dev);
308 : : }
309 : : static struct kobj_attribute last_failed_dev = __ATTR_RO(last_failed_dev);
310 : :
311 : : static ssize_t last_failed_errno_show(struct kobject *kobj,
312 : : struct kobj_attribute *attr, char *buf)
313 : : {
314 : : int index;
315 : : int last_failed_errno;
316 : :
317 : : index = suspend_stats.last_failed_errno + REC_FAILED_NUM - 1;
318 : : index %= REC_FAILED_NUM;
319 : : last_failed_errno = suspend_stats.errno[index];
320 : :
321 : : return sprintf(buf, "%d\n", last_failed_errno);
322 : : }
323 : : static struct kobj_attribute last_failed_errno = __ATTR_RO(last_failed_errno);
324 : :
325 : : static ssize_t last_failed_step_show(struct kobject *kobj,
326 : : struct kobj_attribute *attr, char *buf)
327 : : {
328 : : int index;
329 : : enum suspend_stat_step step;
330 : : char *last_failed_step = NULL;
331 : :
332 : : index = suspend_stats.last_failed_step + REC_FAILED_NUM - 1;
333 : : index %= REC_FAILED_NUM;
334 : : step = suspend_stats.failed_steps[index];
335 : : last_failed_step = suspend_step_name(step);
336 : :
337 : : return sprintf(buf, "%s\n", last_failed_step);
338 : : }
339 : : static struct kobj_attribute last_failed_step = __ATTR_RO(last_failed_step);
340 : :
341 : : static struct attribute *suspend_attrs[] = {
342 : : &success.attr,
343 : : &fail.attr,
344 : : &failed_freeze.attr,
345 : : &failed_prepare.attr,
346 : : &failed_suspend.attr,
347 : : &failed_suspend_late.attr,
348 : : &failed_suspend_noirq.attr,
349 : : &failed_resume.attr,
350 : : &failed_resume_early.attr,
351 : : &failed_resume_noirq.attr,
352 : : &last_failed_dev.attr,
353 : : &last_failed_errno.attr,
354 : : &last_failed_step.attr,
355 : : NULL,
356 : : };
357 : :
358 : : static struct attribute_group suspend_attr_group = {
359 : : .name = "suspend_stats",
360 : : .attrs = suspend_attrs,
361 : : };
362 : :
363 : : #ifdef CONFIG_DEBUG_FS
364 : : static int suspend_stats_show(struct seq_file *s, void *unused)
365 : : {
366 : : int i, index, last_dev, last_errno, last_step;
367 : :
368 : : last_dev = suspend_stats.last_failed_dev + REC_FAILED_NUM - 1;
369 : : last_dev %= REC_FAILED_NUM;
370 : : last_errno = suspend_stats.last_failed_errno + REC_FAILED_NUM - 1;
371 : : last_errno %= REC_FAILED_NUM;
372 : : last_step = suspend_stats.last_failed_step + REC_FAILED_NUM - 1;
373 : : last_step %= REC_FAILED_NUM;
374 : : seq_printf(s, "%s: %d\n%s: %d\n%s: %d\n%s: %d\n%s: %d\n"
375 : : "%s: %d\n%s: %d\n%s: %d\n%s: %d\n%s: %d\n",
376 : : "success", suspend_stats.success,
377 : : "fail", suspend_stats.fail,
378 : : "failed_freeze", suspend_stats.failed_freeze,
379 : : "failed_prepare", suspend_stats.failed_prepare,
380 : : "failed_suspend", suspend_stats.failed_suspend,
381 : : "failed_suspend_late",
382 : : suspend_stats.failed_suspend_late,
383 : : "failed_suspend_noirq",
384 : : suspend_stats.failed_suspend_noirq,
385 : : "failed_resume", suspend_stats.failed_resume,
386 : : "failed_resume_early",
387 : : suspend_stats.failed_resume_early,
388 : : "failed_resume_noirq",
389 : : suspend_stats.failed_resume_noirq);
390 : : seq_printf(s, "failures:\n last_failed_dev:\t%-s\n",
391 : : suspend_stats.failed_devs[last_dev]);
392 : : for (i = 1; i < REC_FAILED_NUM; i++) {
393 : : index = last_dev + REC_FAILED_NUM - i;
394 : : index %= REC_FAILED_NUM;
395 : : seq_printf(s, "\t\t\t%-s\n",
396 : : suspend_stats.failed_devs[index]);
397 : : }
398 : : seq_printf(s, " last_failed_errno:\t%-d\n",
399 : : suspend_stats.errno[last_errno]);
400 : : for (i = 1; i < REC_FAILED_NUM; i++) {
401 : : index = last_errno + REC_FAILED_NUM - i;
402 : : index %= REC_FAILED_NUM;
403 : : seq_printf(s, "\t\t\t%-d\n",
404 : : suspend_stats.errno[index]);
405 : : }
406 : : seq_printf(s, " last_failed_step:\t%-s\n",
407 : : suspend_step_name(
408 : : suspend_stats.failed_steps[last_step]));
409 : : for (i = 1; i < REC_FAILED_NUM; i++) {
410 : : index = last_step + REC_FAILED_NUM - i;
411 : : index %= REC_FAILED_NUM;
412 : : seq_printf(s, "\t\t\t%-s\n",
413 : : suspend_step_name(
414 : : suspend_stats.failed_steps[index]));
415 : : }
416 : :
417 : : return 0;
418 : : }
419 : : DEFINE_SHOW_ATTRIBUTE(suspend_stats);
420 : :
421 : : static int __init pm_debugfs_init(void)
422 : : {
423 : : debugfs_create_file("suspend_stats", S_IFREG | S_IRUGO,
424 : : NULL, NULL, &suspend_stats_fops);
425 : : return 0;
426 : : }
427 : :
428 : : late_initcall(pm_debugfs_init);
429 : : #endif /* CONFIG_DEBUG_FS */
430 : :
431 : : #endif /* CONFIG_PM_SLEEP */
432 : :
433 : : #ifdef CONFIG_PM_SLEEP_DEBUG
434 : : /*
435 : : * pm_print_times: print time taken by devices to suspend and resume.
436 : : *
437 : : * show() returns whether printing of suspend and resume times is enabled.
438 : : * store() accepts 0 or 1. 0 disables printing and 1 enables it.
439 : : */
440 : : bool pm_print_times_enabled;
441 : :
442 : : static ssize_t pm_print_times_show(struct kobject *kobj,
443 : : struct kobj_attribute *attr, char *buf)
444 : : {
445 : : return sprintf(buf, "%d\n", pm_print_times_enabled);
446 : : }
447 : :
448 : : static ssize_t pm_print_times_store(struct kobject *kobj,
449 : : struct kobj_attribute *attr,
450 : : const char *buf, size_t n)
451 : : {
452 : : unsigned long val;
453 : :
454 : : if (kstrtoul(buf, 10, &val))
455 : : return -EINVAL;
456 : :
457 : : if (val > 1)
458 : : return -EINVAL;
459 : :
460 : : pm_print_times_enabled = !!val;
461 : : return n;
462 : : }
463 : :
464 : : power_attr(pm_print_times);
465 : :
466 : : static inline void pm_print_times_init(void)
467 : : {
468 : : pm_print_times_enabled = !!initcall_debug;
469 : : }
470 : :
471 : : static ssize_t pm_wakeup_irq_show(struct kobject *kobj,
472 : : struct kobj_attribute *attr,
473 : : char *buf)
474 : : {
475 : : return pm_wakeup_irq ? sprintf(buf, "%u\n", pm_wakeup_irq) : -ENODATA;
476 : : }
477 : :
478 : : power_attr_ro(pm_wakeup_irq);
479 : :
480 : : bool pm_debug_messages_on __read_mostly;
481 : :
482 : : static ssize_t pm_debug_messages_show(struct kobject *kobj,
483 : : struct kobj_attribute *attr, char *buf)
484 : : {
485 : : return sprintf(buf, "%d\n", pm_debug_messages_on);
486 : : }
487 : :
488 : : static ssize_t pm_debug_messages_store(struct kobject *kobj,
489 : : struct kobj_attribute *attr,
490 : : const char *buf, size_t n)
491 : : {
492 : : unsigned long val;
493 : :
494 : : if (kstrtoul(buf, 10, &val))
495 : : return -EINVAL;
496 : :
497 : : if (val > 1)
498 : : return -EINVAL;
499 : :
500 : : pm_debug_messages_on = !!val;
501 : : return n;
502 : : }
503 : :
504 : : power_attr(pm_debug_messages);
505 : :
506 : : /**
507 : : * __pm_pr_dbg - Print a suspend debug message to the kernel log.
508 : : * @defer: Whether or not to use printk_deferred() to print the message.
509 : : * @fmt: Message format.
510 : : *
511 : : * The message will be emitted if enabled through the pm_debug_messages
512 : : * sysfs attribute.
513 : : */
514 : : void __pm_pr_dbg(bool defer, const char *fmt, ...)
515 : : {
516 : : struct va_format vaf;
517 : : va_list args;
518 : :
519 : : if (!pm_debug_messages_on)
520 : : return;
521 : :
522 : : va_start(args, fmt);
523 : :
524 : : vaf.fmt = fmt;
525 : : vaf.va = &args;
526 : :
527 : : if (defer)
528 : : printk_deferred(KERN_DEBUG "PM: %pV", &vaf);
529 : : else
530 : : printk(KERN_DEBUG "PM: %pV", &vaf);
531 : :
532 : : va_end(args);
533 : : }
534 : :
535 : : #else /* !CONFIG_PM_SLEEP_DEBUG */
536 : : static inline void pm_print_times_init(void) {}
537 : : #endif /* CONFIG_PM_SLEEP_DEBUG */
538 : :
539 : : struct kobject *power_kobj;
540 : :
541 : : /**
542 : : * state - control system sleep states.
543 : : *
544 : : * show() returns available sleep state labels, which may be "mem", "standby",
545 : : * "freeze" and "disk" (hibernation).
546 : : * See Documentation/admin-guide/pm/sleep-states.rst for a description of
547 : : * what they mean.
548 : : *
549 : : * store() accepts one of those strings, translates it into the proper
550 : : * enumerated value, and initiates a suspend transition.
551 : : */
552 : 0 : static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
553 : : char *buf)
554 : : {
555 : : char *s = buf;
556 : : #ifdef CONFIG_SUSPEND
557 : : suspend_state_t i;
558 : :
559 : : for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++)
560 : : if (pm_states[i])
561 : : s += sprintf(s,"%s ", pm_states[i]);
562 : :
563 : : #endif
564 : : if (hibernation_available())
565 : : s += sprintf(s, "disk ");
566 : : if (s != buf)
567 : : /* convert the last space to a newline */
568 : : *(s-1) = '\n';
569 : 0 : return (s - buf);
570 : : }
571 : :
572 : 0 : static suspend_state_t decode_state(const char *buf, size_t n)
573 : : {
574 : : #ifdef CONFIG_SUSPEND
575 : : suspend_state_t state;
576 : : #endif
577 : : char *p;
578 : : int len;
579 : :
580 : 0 : p = memchr(buf, '\n', n);
581 [ # # ]: 0 : len = p ? p - buf : n;
582 : :
583 : : /* Check hibernation first. */
584 [ # # # # ]: 0 : if (len == 4 && str_has_prefix(buf, "disk"))
585 : : return PM_SUSPEND_MAX;
586 : :
587 : : #ifdef CONFIG_SUSPEND
588 : : for (state = PM_SUSPEND_MIN; state < PM_SUSPEND_MAX; state++) {
589 : : const char *label = pm_states[state];
590 : :
591 : : if (label && len == strlen(label) && !strncmp(buf, label, len))
592 : : return state;
593 : : }
594 : : #endif
595 : :
596 : 0 : return PM_SUSPEND_ON;
597 : : }
598 : :
599 : 0 : static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
600 : : const char *buf, size_t n)
601 : : {
602 : : suspend_state_t state;
603 : : int error;
604 : :
605 : : error = pm_autosleep_lock();
606 : : if (error)
607 : : return error;
608 : :
609 : : if (pm_autosleep_state() > PM_SUSPEND_ON) {
610 : : error = -EBUSY;
611 : : goto out;
612 : : }
613 : :
614 : 0 : state = decode_state(buf, n);
615 [ # # ]: 0 : if (state < PM_SUSPEND_MAX) {
616 : : if (state == PM_SUSPEND_MEM)
617 : : state = mem_sleep_current;
618 : :
619 : : error = pm_suspend(state);
620 [ # # ]: 0 : } else if (state == PM_SUSPEND_MAX) {
621 : : error = hibernate();
622 : : } else {
623 : : error = -EINVAL;
624 : : }
625 : :
626 : : out:
627 : : pm_autosleep_unlock();
628 : : return error ? error : n;
629 : : }
630 : :
631 : : power_attr(state);
632 : :
633 : : #ifdef CONFIG_PM_SLEEP
634 : : /*
635 : : * The 'wakeup_count' attribute, along with the functions defined in
636 : : * drivers/base/power/wakeup.c, provides a means by which wakeup events can be
637 : : * handled in a non-racy way.
638 : : *
639 : : * If a wakeup event occurs when the system is in a sleep state, it simply is
640 : : * woken up. In turn, if an event that would wake the system up from a sleep
641 : : * state occurs when it is undergoing a transition to that sleep state, the
642 : : * transition should be aborted. Moreover, if such an event occurs when the
643 : : * system is in the working state, an attempt to start a transition to the
644 : : * given sleep state should fail during certain period after the detection of
645 : : * the event. Using the 'state' attribute alone is not sufficient to satisfy
646 : : * these requirements, because a wakeup event may occur exactly when 'state'
647 : : * is being written to and may be delivered to user space right before it is
648 : : * frozen, so the event will remain only partially processed until the system is
649 : : * woken up by another event. In particular, it won't cause the transition to
650 : : * a sleep state to be aborted.
651 : : *
652 : : * This difficulty may be overcome if user space uses 'wakeup_count' before
653 : : * writing to 'state'. It first should read from 'wakeup_count' and store
654 : : * the read value. Then, after carrying out its own preparations for the system
655 : : * transition to a sleep state, it should write the stored value to
656 : : * 'wakeup_count'. If that fails, at least one wakeup event has occurred since
657 : : * 'wakeup_count' was read and 'state' should not be written to. Otherwise, it
658 : : * is allowed to write to 'state', but the transition will be aborted if there
659 : : * are any wakeup events detected after 'wakeup_count' was written to.
660 : : */
661 : :
662 : : static ssize_t wakeup_count_show(struct kobject *kobj,
663 : : struct kobj_attribute *attr,
664 : : char *buf)
665 : : {
666 : : unsigned int val;
667 : :
668 : : return pm_get_wakeup_count(&val, true) ?
669 : : sprintf(buf, "%u\n", val) : -EINTR;
670 : : }
671 : :
672 : : static ssize_t wakeup_count_store(struct kobject *kobj,
673 : : struct kobj_attribute *attr,
674 : : const char *buf, size_t n)
675 : : {
676 : : unsigned int val;
677 : : int error;
678 : :
679 : : error = pm_autosleep_lock();
680 : : if (error)
681 : : return error;
682 : :
683 : : if (pm_autosleep_state() > PM_SUSPEND_ON) {
684 : : error = -EBUSY;
685 : : goto out;
686 : : }
687 : :
688 : : error = -EINVAL;
689 : : if (sscanf(buf, "%u", &val) == 1) {
690 : : if (pm_save_wakeup_count(val))
691 : : error = n;
692 : : else
693 : : pm_print_active_wakeup_sources();
694 : : }
695 : :
696 : : out:
697 : : pm_autosleep_unlock();
698 : : return error;
699 : : }
700 : :
701 : : power_attr(wakeup_count);
702 : :
703 : : #ifdef CONFIG_PM_AUTOSLEEP
704 : : static ssize_t autosleep_show(struct kobject *kobj,
705 : : struct kobj_attribute *attr,
706 : : char *buf)
707 : : {
708 : : suspend_state_t state = pm_autosleep_state();
709 : :
710 : : if (state == PM_SUSPEND_ON)
711 : : return sprintf(buf, "off\n");
712 : :
713 : : #ifdef CONFIG_SUSPEND
714 : : if (state < PM_SUSPEND_MAX)
715 : : return sprintf(buf, "%s\n", pm_states[state] ?
716 : : pm_states[state] : "error");
717 : : #endif
718 : : #ifdef CONFIG_HIBERNATION
719 : : return sprintf(buf, "disk\n");
720 : : #else
721 : : return sprintf(buf, "error");
722 : : #endif
723 : : }
724 : :
725 : : static ssize_t autosleep_store(struct kobject *kobj,
726 : : struct kobj_attribute *attr,
727 : : const char *buf, size_t n)
728 : : {
729 : : suspend_state_t state = decode_state(buf, n);
730 : : int error;
731 : :
732 : : if (state == PM_SUSPEND_ON
733 : : && strcmp(buf, "off") && strcmp(buf, "off\n"))
734 : : return -EINVAL;
735 : :
736 : : if (state == PM_SUSPEND_MEM)
737 : : state = mem_sleep_current;
738 : :
739 : : error = pm_autosleep_set_state(state);
740 : : return error ? error : n;
741 : : }
742 : :
743 : : power_attr(autosleep);
744 : : #endif /* CONFIG_PM_AUTOSLEEP */
745 : :
746 : : #ifdef CONFIG_PM_WAKELOCKS
747 : : static ssize_t wake_lock_show(struct kobject *kobj,
748 : : struct kobj_attribute *attr,
749 : : char *buf)
750 : : {
751 : : return pm_show_wakelocks(buf, true);
752 : : }
753 : :
754 : : static ssize_t wake_lock_store(struct kobject *kobj,
755 : : struct kobj_attribute *attr,
756 : : const char *buf, size_t n)
757 : : {
758 : : int error = pm_wake_lock(buf);
759 : : return error ? error : n;
760 : : }
761 : :
762 : : power_attr(wake_lock);
763 : :
764 : : static ssize_t wake_unlock_show(struct kobject *kobj,
765 : : struct kobj_attribute *attr,
766 : : char *buf)
767 : : {
768 : : return pm_show_wakelocks(buf, false);
769 : : }
770 : :
771 : : static ssize_t wake_unlock_store(struct kobject *kobj,
772 : : struct kobj_attribute *attr,
773 : : const char *buf, size_t n)
774 : : {
775 : : int error = pm_wake_unlock(buf);
776 : : return error ? error : n;
777 : : }
778 : :
779 : : power_attr(wake_unlock);
780 : :
781 : : #endif /* CONFIG_PM_WAKELOCKS */
782 : : #endif /* CONFIG_PM_SLEEP */
783 : :
784 : : #ifdef CONFIG_PM_TRACE
785 : : int pm_trace_enabled;
786 : :
787 : : static ssize_t pm_trace_show(struct kobject *kobj, struct kobj_attribute *attr,
788 : : char *buf)
789 : : {
790 : : return sprintf(buf, "%d\n", pm_trace_enabled);
791 : : }
792 : :
793 : : static ssize_t
794 : : pm_trace_store(struct kobject *kobj, struct kobj_attribute *attr,
795 : : const char *buf, size_t n)
796 : : {
797 : : int val;
798 : :
799 : : if (sscanf(buf, "%d", &val) == 1) {
800 : : pm_trace_enabled = !!val;
801 : : if (pm_trace_enabled) {
802 : : pr_warn("PM: Enabling pm_trace changes system date and time during resume.\n"
803 : : "PM: Correct system time has to be restored manually after resume.\n");
804 : : }
805 : : return n;
806 : : }
807 : : return -EINVAL;
808 : : }
809 : :
810 : : power_attr(pm_trace);
811 : :
812 : : static ssize_t pm_trace_dev_match_show(struct kobject *kobj,
813 : : struct kobj_attribute *attr,
814 : : char *buf)
815 : : {
816 : : return show_trace_dev_match(buf, PAGE_SIZE);
817 : : }
818 : :
819 : : power_attr_ro(pm_trace_dev_match);
820 : :
821 : : #endif /* CONFIG_PM_TRACE */
822 : :
823 : : #ifdef CONFIG_FREEZER
824 : 0 : static ssize_t pm_freeze_timeout_show(struct kobject *kobj,
825 : : struct kobj_attribute *attr, char *buf)
826 : : {
827 : 0 : return sprintf(buf, "%u\n", freeze_timeout_msecs);
828 : : }
829 : :
830 : 0 : static ssize_t pm_freeze_timeout_store(struct kobject *kobj,
831 : : struct kobj_attribute *attr,
832 : : const char *buf, size_t n)
833 : : {
834 : : unsigned long val;
835 : :
836 [ # # ]: 0 : if (kstrtoul(buf, 10, &val))
837 : : return -EINVAL;
838 : :
839 : 0 : freeze_timeout_msecs = val;
840 : 0 : return n;
841 : : }
842 : :
843 : : power_attr(pm_freeze_timeout);
844 : :
845 : : #endif /* CONFIG_FREEZER*/
846 : :
847 : : static struct attribute * g[] = {
848 : : &state_attr.attr,
849 : : #ifdef CONFIG_PM_TRACE
850 : : &pm_trace_attr.attr,
851 : : &pm_trace_dev_match_attr.attr,
852 : : #endif
853 : : #ifdef CONFIG_PM_SLEEP
854 : : &pm_async_attr.attr,
855 : : &wakeup_count_attr.attr,
856 : : #ifdef CONFIG_SUSPEND
857 : : &mem_sleep_attr.attr,
858 : : #endif
859 : : #ifdef CONFIG_PM_AUTOSLEEP
860 : : &autosleep_attr.attr,
861 : : #endif
862 : : #ifdef CONFIG_PM_WAKELOCKS
863 : : &wake_lock_attr.attr,
864 : : &wake_unlock_attr.attr,
865 : : #endif
866 : : #ifdef CONFIG_PM_SLEEP_DEBUG
867 : : &pm_test_attr.attr,
868 : : &pm_print_times_attr.attr,
869 : : &pm_wakeup_irq_attr.attr,
870 : : &pm_debug_messages_attr.attr,
871 : : #endif
872 : : #endif
873 : : #ifdef CONFIG_FREEZER
874 : : &pm_freeze_timeout_attr.attr,
875 : : #endif
876 : : NULL,
877 : : };
878 : :
879 : : static const struct attribute_group attr_group = {
880 : : .attrs = g,
881 : : };
882 : :
883 : : static const struct attribute_group *attr_groups[] = {
884 : : &attr_group,
885 : : #ifdef CONFIG_PM_SLEEP
886 : : &suspend_attr_group,
887 : : #endif
888 : : NULL,
889 : : };
890 : :
891 : : struct workqueue_struct *pm_wq;
892 : : EXPORT_SYMBOL_GPL(pm_wq);
893 : :
894 : 207 : static int __init pm_start_workqueue(void)
895 : : {
896 : 207 : pm_wq = alloc_workqueue("pm", WQ_FREEZABLE, 0);
897 : :
898 [ - + ]: 207 : return pm_wq ? 0 : -ENOMEM;
899 : : }
900 : :
901 : 207 : static int __init pm_init(void)
902 : : {
903 : 207 : int error = pm_start_workqueue();
904 [ + - ]: 207 : if (error)
905 : : return error;
906 : : hibernate_image_size_init();
907 : : hibernate_reserved_size_init();
908 : : pm_states_init();
909 : 207 : power_kobj = kobject_create_and_add("power", NULL);
910 [ + - ]: 207 : if (!power_kobj)
911 : : return -ENOMEM;
912 : 207 : error = sysfs_create_groups(power_kobj, attr_groups);
913 [ - + ]: 207 : if (error)
914 : 0 : return error;
915 : : pm_print_times_init();
916 : : return pm_autosleep_init();
917 : : }
918 : :
919 : : core_initcall(pm_init);
|