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