1
2
3
4
5
6
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
19#include "power.h"
20
21#ifdef CONFIG_PM_SLEEP
22
23void lock_system_sleep(void)
24{
25 current->flags |= PF_FREEZER_SKIP;
26 mutex_lock(&system_transition_mutex);
27}
28EXPORT_SYMBOL_GPL(lock_system_sleep);
29
30void unlock_system_sleep(void)
31{
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 current->flags &= ~PF_FREEZER_SKIP;
49 mutex_unlock(&system_transition_mutex);
50}
51EXPORT_SYMBOL_GPL(unlock_system_sleep);
52
53void ksys_sync_helper(void)
54{
55 ktime_t start;
56 long elapsed_msecs;
57
58 start = ktime_get();
59 ksys_sync();
60 elapsed_msecs = ktime_to_ms(ktime_sub(ktime_get(), start));
61 pr_info("Filesystems sync: %ld.%03ld seconds\n",
62 elapsed_msecs / MSEC_PER_SEC, elapsed_msecs % MSEC_PER_SEC);
63}
64EXPORT_SYMBOL_GPL(ksys_sync_helper);
65
66
67
68static BLOCKING_NOTIFIER_HEAD(pm_chain_head);
69
70int register_pm_notifier(struct notifier_block *nb)
71{
72 return blocking_notifier_chain_register(&pm_chain_head, nb);
73}
74EXPORT_SYMBOL_GPL(register_pm_notifier);
75
76int unregister_pm_notifier(struct notifier_block *nb)
77{
78 return blocking_notifier_chain_unregister(&pm_chain_head, nb);
79}
80EXPORT_SYMBOL_GPL(unregister_pm_notifier);
81
82int __pm_notifier_call_chain(unsigned long val, int nr_to_call, int *nr_calls)
83{
84 int ret;
85
86 ret = __blocking_notifier_call_chain(&pm_chain_head, val, NULL,
87 nr_to_call, nr_calls);
88
89 return notifier_to_errno(ret);
90}
91int pm_notifier_call_chain(unsigned long val)
92{
93 return __pm_notifier_call_chain(val, -1, NULL);
94}
95
96
97int pm_async_enabled = 1;
98
99static ssize_t pm_async_show(struct kobject *kobj, struct kobj_attribute *attr,
100 char *buf)
101{
102 return sprintf(buf, "%d\n", pm_async_enabled);
103}
104
105static ssize_t pm_async_store(struct kobject *kobj, struct kobj_attribute *attr,
106 const char *buf, size_t n)
107{
108 unsigned long val;
109
110 if (kstrtoul(buf, 10, &val))
111 return -EINVAL;
112
113 if (val > 1)
114 return -EINVAL;
115
116 pm_async_enabled = val;
117 return n;
118}
119
120power_attr(pm_async);
121
122#ifdef CONFIG_SUSPEND
123static ssize_t mem_sleep_show(struct kobject *kobj, struct kobj_attribute *attr,
124 char *buf)
125{
126 char *s = buf;
127 suspend_state_t i;
128
129 for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++)
130 if (mem_sleep_states[i]) {
131 const char *label = mem_sleep_states[i];
132
133 if (mem_sleep_current == i)
134 s += sprintf(s, "[%s] ", label);
135 else
136 s += sprintf(s, "%s ", label);
137 }
138
139
140 if (s != buf)
141 *(s-1) = '\n';
142
143 return (s - buf);
144}
145
146static suspend_state_t decode_suspend_state(const char *buf, size_t n)
147{
148 suspend_state_t state;
149 char *p;
150 int len;
151
152 p = memchr(buf, '\n', n);
153 len = p ? p - buf : n;
154
155 for (state = PM_SUSPEND_MIN; state < PM_SUSPEND_MAX; state++) {
156 const char *label = mem_sleep_states[state];
157
158 if (label && len == strlen(label) && !strncmp(buf, label, len))
159 return state;
160 }
161
162 return PM_SUSPEND_ON;
163}
164
165static ssize_t mem_sleep_store(struct kobject *kobj, struct kobj_attribute *attr,
166 const char *buf, size_t n)
167{
168 suspend_state_t state;
169 int error;
170
171 error = pm_autosleep_lock();
172 if (error)
173 return error;
174
175 if (pm_autosleep_state() > PM_SUSPEND_ON) {
176 error = -EBUSY;
177 goto out;
178 }
179
180 state = decode_suspend_state(buf, n);
181 if (state < PM_SUSPEND_MAX && state > PM_SUSPEND_ON)
182 mem_sleep_current = state;
183 else
184 error = -EINVAL;
185
186 out:
187 pm_autosleep_unlock();
188 return error ? error : n;
189}
190
191power_attr(mem_sleep);
192#endif
193
194#ifdef CONFIG_PM_SLEEP_DEBUG
195int pm_test_level = TEST_NONE;
196
197static const char * const pm_tests[__TEST_AFTER_LAST] = {
198 [TEST_NONE] = "none",
199 [TEST_CORE] = "core",
200 [TEST_CPUS] = "processors",
201 [TEST_PLATFORM] = "platform",
202 [TEST_DEVICES] = "devices",
203 [TEST_FREEZER] = "freezer",
204};
205
206static ssize_t pm_test_show(struct kobject *kobj, struct kobj_attribute *attr,
207 char *buf)
208{
209 char *s = buf;
210 int level;
211
212 for (level = TEST_FIRST; level <= TEST_MAX; level++)
213 if (pm_tests[level]) {
214 if (level == pm_test_level)
215 s += sprintf(s, "[%s] ", pm_tests[level]);
216 else
217 s += sprintf(s, "%s ", pm_tests[level]);
218 }
219
220 if (s != buf)
221
222 *(s-1) = '\n';
223
224 return (s - buf);
225}
226
227static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr,
228 const char *buf, size_t n)
229{
230 const char * const *s;
231 int level;
232 char *p;
233 int len;
234 int error = -EINVAL;
235
236 p = memchr(buf, '\n', n);
237 len = p ? p - buf : n;
238
239 lock_system_sleep();
240
241 level = TEST_FIRST;
242 for (s = &pm_tests[level]; level <= TEST_MAX; s++, level++)
243 if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) {
244 pm_test_level = level;
245 error = 0;
246 break;
247 }
248
249 unlock_system_sleep();
250
251 return error ? error : n;
252}
253
254power_attr(pm_test);
255#endif
256
257#ifdef CONFIG_DEBUG_FS
258static 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
278static int suspend_stats_show(struct seq_file *s, void *unused)
279{
280 int i, index, last_dev, last_errno, last_step;
281
282 last_dev = suspend_stats.last_failed_dev + REC_FAILED_NUM - 1;
283 last_dev %= REC_FAILED_NUM;
284 last_errno = suspend_stats.last_failed_errno + REC_FAILED_NUM - 1;
285 last_errno %= REC_FAILED_NUM;
286 last_step = suspend_stats.last_failed_step + REC_FAILED_NUM - 1;
287 last_step %= REC_FAILED_NUM;
288 seq_printf(s, "%s: %d\n%s: %d\n%s: %d\n%s: %d\n%s: %d\n"
289 "%s: %d\n%s: %d\n%s: %d\n%s: %d\n%s: %d\n",
290 "success", suspend_stats.success,
291 "fail", suspend_stats.fail,
292 "failed_freeze", suspend_stats.failed_freeze,
293 "failed_prepare", suspend_stats.failed_prepare,
294 "failed_suspend", suspend_stats.failed_suspend,
295 "failed_suspend_late",
296 suspend_stats.failed_suspend_late,
297 "failed_suspend_noirq",
298 suspend_stats.failed_suspend_noirq,
299 "failed_resume", suspend_stats.failed_resume,
300 "failed_resume_early",
301 suspend_stats.failed_resume_early,
302 "failed_resume_noirq",
303 suspend_stats.failed_resume_noirq);
304 seq_printf(s, "failures:\n last_failed_dev:\t%-s\n",
305 suspend_stats.failed_devs[last_dev]);
306 for (i = 1; i < REC_FAILED_NUM; i++) {
307 index = last_dev + REC_FAILED_NUM - i;
308 index %= REC_FAILED_NUM;
309 seq_printf(s, "\t\t\t%-s\n",
310 suspend_stats.failed_devs[index]);
311 }
312 seq_printf(s, " last_failed_errno:\t%-d\n",
313 suspend_stats.errno[last_errno]);
314 for (i = 1; i < REC_FAILED_NUM; i++) {
315 index = last_errno + REC_FAILED_NUM - i;
316 index %= REC_FAILED_NUM;
317 seq_printf(s, "\t\t\t%-d\n",
318 suspend_stats.errno[index]);
319 }
320 seq_printf(s, " last_failed_step:\t%-s\n",
321 suspend_step_name(
322 suspend_stats.failed_steps[last_step]));
323 for (i = 1; i < REC_FAILED_NUM; i++) {
324 index = last_step + REC_FAILED_NUM - i;
325 index %= REC_FAILED_NUM;
326 seq_printf(s, "\t\t\t%-s\n",
327 suspend_step_name(
328 suspend_stats.failed_steps[index]));
329 }
330
331 return 0;
332}
333DEFINE_SHOW_ATTRIBUTE(suspend_stats);
334
335static int __init pm_debugfs_init(void)
336{
337 debugfs_create_file("suspend_stats", S_IFREG | S_IRUGO,
338 NULL, NULL, &suspend_stats_fops);
339 return 0;
340}
341
342late_initcall(pm_debugfs_init);
343#endif
344
345#endif
346
347#ifdef CONFIG_PM_SLEEP_DEBUG
348
349
350
351
352
353
354bool pm_print_times_enabled;
355
356static ssize_t pm_print_times_show(struct kobject *kobj,
357 struct kobj_attribute *attr, char *buf)
358{
359 return sprintf(buf, "%d\n", pm_print_times_enabled);
360}
361
362static ssize_t pm_print_times_store(struct kobject *kobj,
363 struct kobj_attribute *attr,
364 const char *buf, size_t n)
365{
366 unsigned long val;
367
368 if (kstrtoul(buf, 10, &val))
369 return -EINVAL;
370
371 if (val > 1)
372 return -EINVAL;
373
374 pm_print_times_enabled = !!val;
375 return n;
376}
377
378power_attr(pm_print_times);
379
380static inline void pm_print_times_init(void)
381{
382 pm_print_times_enabled = !!initcall_debug;
383}
384
385static ssize_t pm_wakeup_irq_show(struct kobject *kobj,
386 struct kobj_attribute *attr,
387 char *buf)
388{
389 return pm_wakeup_irq ? sprintf(buf, "%u\n", pm_wakeup_irq) : -ENODATA;
390}
391
392power_attr_ro(pm_wakeup_irq);
393
394bool pm_debug_messages_on __read_mostly;
395
396static ssize_t pm_debug_messages_show(struct kobject *kobj,
397 struct kobj_attribute *attr, char *buf)
398{
399 return sprintf(buf, "%d\n", pm_debug_messages_on);
400}
401
402static ssize_t pm_debug_messages_store(struct kobject *kobj,
403 struct kobj_attribute *attr,
404 const char *buf, size_t n)
405{
406 unsigned long val;
407
408 if (kstrtoul(buf, 10, &val))
409 return -EINVAL;
410
411 if (val > 1)
412 return -EINVAL;
413
414 pm_debug_messages_on = !!val;
415 return n;
416}
417
418power_attr(pm_debug_messages);
419
420
421
422
423
424
425
426
427
428void __pm_pr_dbg(bool defer, const char *fmt, ...)
429{
430 struct va_format vaf;
431 va_list args;
432
433 if (!pm_debug_messages_on)
434 return;
435
436 va_start(args, fmt);
437
438 vaf.fmt = fmt;
439 vaf.va = &args;
440
441 if (defer)
442 printk_deferred(KERN_DEBUG "PM: %pV", &vaf);
443 else
444 printk(KERN_DEBUG "PM: %pV", &vaf);
445
446 va_end(args);
447}
448
449#else
450static inline void pm_print_times_init(void) {}
451#endif
452
453struct kobject *power_kobj;
454
455
456
457
458
459
460
461
462
463
464
465
466static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
467 char *buf)
468{
469 char *s = buf;
470#ifdef CONFIG_SUSPEND
471 suspend_state_t i;
472
473 for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++)
474 if (pm_states[i])
475 s += sprintf(s,"%s ", pm_states[i]);
476
477#endif
478 if (hibernation_available())
479 s += sprintf(s, "disk ");
480 if (s != buf)
481
482 *(s-1) = '\n';
483 return (s - buf);
484}
485
486static suspend_state_t decode_state(const char *buf, size_t n)
487{
488#ifdef CONFIG_SUSPEND
489 suspend_state_t state;
490#endif
491 char *p;
492 int len;
493
494 p = memchr(buf, '\n', n);
495 len = p ? p - buf : n;
496
497
498 if (len == 4 && !strncmp(buf, "disk", len))
499 return PM_SUSPEND_MAX;
500
501#ifdef CONFIG_SUSPEND
502 for (state = PM_SUSPEND_MIN; state < PM_SUSPEND_MAX; state++) {
503 const char *label = pm_states[state];
504
505 if (label && len == strlen(label) && !strncmp(buf, label, len))
506 return state;
507 }
508#endif
509
510 return PM_SUSPEND_ON;
511}
512
513static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
514 const char *buf, size_t n)
515{
516 suspend_state_t state;
517 int error;
518
519 error = pm_autosleep_lock();
520 if (error)
521 return error;
522
523 if (pm_autosleep_state() > PM_SUSPEND_ON) {
524 error = -EBUSY;
525 goto out;
526 }
527
528 state = decode_state(buf, n);
529 if (state < PM_SUSPEND_MAX) {
530 if (state == PM_SUSPEND_MEM)
531 state = mem_sleep_current;
532
533 error = pm_suspend(state);
534 } else if (state == PM_SUSPEND_MAX) {
535 error = hibernate();
536 } else {
537 error = -EINVAL;
538 }
539
540 out:
541 pm_autosleep_unlock();
542 return error ? error : n;
543}
544
545power_attr(state);
546
547#ifdef CONFIG_PM_SLEEP
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576static ssize_t wakeup_count_show(struct kobject *kobj,
577 struct kobj_attribute *attr,
578 char *buf)
579{
580 unsigned int val;
581
582 return pm_get_wakeup_count(&val, true) ?
583 sprintf(buf, "%u\n", val) : -EINTR;
584}
585
586static ssize_t wakeup_count_store(struct kobject *kobj,
587 struct kobj_attribute *attr,
588 const char *buf, size_t n)
589{
590 unsigned int val;
591 int error;
592
593 error = pm_autosleep_lock();
594 if (error)
595 return error;
596
597 if (pm_autosleep_state() > PM_SUSPEND_ON) {
598 error = -EBUSY;
599 goto out;
600 }
601
602 error = -EINVAL;
603 if (sscanf(buf, "%u", &val) == 1) {
604 if (pm_save_wakeup_count(val))
605 error = n;
606 else
607 pm_print_active_wakeup_sources();
608 }
609
610 out:
611 pm_autosleep_unlock();
612 return error;
613}
614
615power_attr(wakeup_count);
616
617#ifdef CONFIG_PM_AUTOSLEEP
618static ssize_t autosleep_show(struct kobject *kobj,
619 struct kobj_attribute *attr,
620 char *buf)
621{
622 suspend_state_t state = pm_autosleep_state();
623
624 if (state == PM_SUSPEND_ON)
625 return sprintf(buf, "off\n");
626
627#ifdef CONFIG_SUSPEND
628 if (state < PM_SUSPEND_MAX)
629 return sprintf(buf, "%s\n", pm_states[state] ?
630 pm_states[state] : "error");
631#endif
632#ifdef CONFIG_HIBERNATION
633 return sprintf(buf, "disk\n");
634#else
635 return sprintf(buf, "error");
636#endif
637}
638
639static ssize_t autosleep_store(struct kobject *kobj,
640 struct kobj_attribute *attr,
641 const char *buf, size_t n)
642{
643 suspend_state_t state = decode_state(buf, n);
644 int error;
645
646 if (state == PM_SUSPEND_ON
647 && strcmp(buf, "off") && strcmp(buf, "off\n"))
648 return -EINVAL;
649
650 if (state == PM_SUSPEND_MEM)
651 state = mem_sleep_current;
652
653 error = pm_autosleep_set_state(state);
654 return error ? error : n;
655}
656
657power_attr(autosleep);
658#endif
659
660#ifdef CONFIG_PM_WAKELOCKS
661static ssize_t wake_lock_show(struct kobject *kobj,
662 struct kobj_attribute *attr,
663 char *buf)
664{
665 return pm_show_wakelocks(buf, true);
666}
667
668static ssize_t wake_lock_store(struct kobject *kobj,
669 struct kobj_attribute *attr,
670 const char *buf, size_t n)
671{
672 int error = pm_wake_lock(buf);
673 return error ? error : n;
674}
675
676power_attr(wake_lock);
677
678static ssize_t wake_unlock_show(struct kobject *kobj,
679 struct kobj_attribute *attr,
680 char *buf)
681{
682 return pm_show_wakelocks(buf, false);
683}
684
685static ssize_t wake_unlock_store(struct kobject *kobj,
686 struct kobj_attribute *attr,
687 const char *buf, size_t n)
688{
689 int error = pm_wake_unlock(buf);
690 return error ? error : n;
691}
692
693power_attr(wake_unlock);
694
695#endif
696#endif
697
698#ifdef CONFIG_PM_TRACE
699int pm_trace_enabled;
700
701static ssize_t pm_trace_show(struct kobject *kobj, struct kobj_attribute *attr,
702 char *buf)
703{
704 return sprintf(buf, "%d\n", pm_trace_enabled);
705}
706
707static ssize_t
708pm_trace_store(struct kobject *kobj, struct kobj_attribute *attr,
709 const char *buf, size_t n)
710{
711 int val;
712
713 if (sscanf(buf, "%d", &val) == 1) {
714 pm_trace_enabled = !!val;
715 if (pm_trace_enabled) {
716 pr_warn("PM: Enabling pm_trace changes system date and time during resume.\n"
717 "PM: Correct system time has to be restored manually after resume.\n");
718 }
719 return n;
720 }
721 return -EINVAL;
722}
723
724power_attr(pm_trace);
725
726static ssize_t pm_trace_dev_match_show(struct kobject *kobj,
727 struct kobj_attribute *attr,
728 char *buf)
729{
730 return show_trace_dev_match(buf, PAGE_SIZE);
731}
732
733power_attr_ro(pm_trace_dev_match);
734
735#endif
736
737#ifdef CONFIG_FREEZER
738static ssize_t pm_freeze_timeout_show(struct kobject *kobj,
739 struct kobj_attribute *attr, char *buf)
740{
741 return sprintf(buf, "%u\n", freeze_timeout_msecs);
742}
743
744static ssize_t pm_freeze_timeout_store(struct kobject *kobj,
745 struct kobj_attribute *attr,
746 const char *buf, size_t n)
747{
748 unsigned long val;
749
750 if (kstrtoul(buf, 10, &val))
751 return -EINVAL;
752
753 freeze_timeout_msecs = val;
754 return n;
755}
756
757power_attr(pm_freeze_timeout);
758
759#endif
760
761static struct attribute * g[] = {
762 &state_attr.attr,
763#ifdef CONFIG_PM_TRACE
764 &pm_trace_attr.attr,
765 &pm_trace_dev_match_attr.attr,
766#endif
767#ifdef CONFIG_PM_SLEEP
768 &pm_async_attr.attr,
769 &wakeup_count_attr.attr,
770#ifdef CONFIG_SUSPEND
771 &mem_sleep_attr.attr,
772#endif
773#ifdef CONFIG_PM_AUTOSLEEP
774 &autosleep_attr.attr,
775#endif
776#ifdef CONFIG_PM_WAKELOCKS
777 &wake_lock_attr.attr,
778 &wake_unlock_attr.attr,
779#endif
780#ifdef CONFIG_PM_SLEEP_DEBUG
781 &pm_test_attr.attr,
782 &pm_print_times_attr.attr,
783 &pm_wakeup_irq_attr.attr,
784 &pm_debug_messages_attr.attr,
785#endif
786#endif
787#ifdef CONFIG_FREEZER
788 &pm_freeze_timeout_attr.attr,
789#endif
790 NULL,
791};
792
793static const struct attribute_group attr_group = {
794 .attrs = g,
795};
796
797struct workqueue_struct *pm_wq;
798EXPORT_SYMBOL_GPL(pm_wq);
799
800static int __init pm_start_workqueue(void)
801{
802 pm_wq = alloc_workqueue("pm", WQ_FREEZABLE, 0);
803
804 return pm_wq ? 0 : -ENOMEM;
805}
806
807static int __init pm_init(void)
808{
809 int error = pm_start_workqueue();
810 if (error)
811 return error;
812 hibernate_image_size_init();
813 hibernate_reserved_size_init();
814 pm_states_init();
815 power_kobj = kobject_create_and_add("power", NULL);
816 if (!power_kobj)
817 return -ENOMEM;
818 error = sysfs_create_group(power_kobj, &attr_group);
819 if (error)
820 return error;
821 pm_print_times_init();
822 return pm_autosleep_init();
823}
824
825core_initcall(pm_init);
826