This source file includes following definitions.
- split_counters
- wakeup_source_create
- wakeup_source_record
- wakeup_source_free
- wakeup_source_destroy
- wakeup_source_add
- wakeup_source_remove
- wakeup_source_register
- wakeup_source_unregister
- device_wakeup_attach
- device_wakeup_enable
- device_wakeup_attach_irq
- device_wakeup_detach_irq
- device_wakeup_arm_wake_irqs
- device_wakeup_disarm_wake_irqs
- device_wakeup_detach
- device_wakeup_disable
- device_set_wakeup_capable
- device_init_wakeup
- device_set_wakeup_enable
- wakeup_source_not_registered
- wakeup_source_activate
- wakeup_source_report_event
- __pm_stay_awake
- pm_stay_awake
- update_prevent_sleep_time
- update_prevent_sleep_time
- wakeup_source_deactivate
- __pm_relax
- pm_relax
- pm_wakeup_timer_fn
- pm_wakeup_ws_event
- pm_wakeup_dev_event
- pm_print_active_wakeup_sources
- pm_wakeup_pending
- pm_system_wakeup
- pm_system_cancel_wakeup
- pm_wakeup_clear
- pm_system_irq_wakeup
- pm_get_wakeup_count
- pm_save_wakeup_count
- pm_wakep_autosleep_enabled
- print_wakeup_source_stats
- wakeup_sources_stats_seq_start
- wakeup_sources_stats_seq_next
- wakeup_sources_stats_seq_stop
- wakeup_sources_stats_seq_show
- wakeup_sources_stats_open
- wakeup_sources_debugfs_init
1
2
3
4
5
6
7 #define pr_fmt(fmt) "PM: " fmt
8
9 #include <linux/device.h>
10 #include <linux/slab.h>
11 #include <linux/sched/signal.h>
12 #include <linux/capability.h>
13 #include <linux/export.h>
14 #include <linux/suspend.h>
15 #include <linux/seq_file.h>
16 #include <linux/debugfs.h>
17 #include <linux/pm_wakeirq.h>
18 #include <trace/events/power.h>
19
20 #include "power.h"
21
22 #ifndef CONFIG_SUSPEND
23 suspend_state_t pm_suspend_target_state;
24 #define pm_suspend_target_state (PM_SUSPEND_ON)
25 #endif
26
27
28
29
30
31 bool events_check_enabled __read_mostly;
32
33
34 unsigned int pm_wakeup_irq __read_mostly;
35
36
37 static atomic_t pm_abort_suspend __read_mostly;
38
39
40
41
42
43
44 static atomic_t combined_event_count = ATOMIC_INIT(0);
45
46 #define IN_PROGRESS_BITS (sizeof(int) * 4)
47 #define MAX_IN_PROGRESS ((1 << IN_PROGRESS_BITS) - 1)
48
49 static void split_counters(unsigned int *cnt, unsigned int *inpr)
50 {
51 unsigned int comb = atomic_read(&combined_event_count);
52
53 *cnt = (comb >> IN_PROGRESS_BITS);
54 *inpr = comb & MAX_IN_PROGRESS;
55 }
56
57
58 static unsigned int saved_count;
59
60 static DEFINE_RAW_SPINLOCK(events_lock);
61
62 static void pm_wakeup_timer_fn(struct timer_list *t);
63
64 static LIST_HEAD(wakeup_sources);
65
66 static DECLARE_WAIT_QUEUE_HEAD(wakeup_count_wait_queue);
67
68 DEFINE_STATIC_SRCU(wakeup_srcu);
69
70 static struct wakeup_source deleted_ws = {
71 .name = "deleted",
72 .lock = __SPIN_LOCK_UNLOCKED(deleted_ws.lock),
73 };
74
75 static DEFINE_IDA(wakeup_ida);
76
77
78
79
80
81 struct wakeup_source *wakeup_source_create(const char *name)
82 {
83 struct wakeup_source *ws;
84 const char *ws_name;
85 int id;
86
87 ws = kzalloc(sizeof(*ws), GFP_KERNEL);
88 if (!ws)
89 goto err_ws;
90
91 ws_name = kstrdup_const(name, GFP_KERNEL);
92 if (!ws_name)
93 goto err_name;
94 ws->name = ws_name;
95
96 id = ida_alloc(&wakeup_ida, GFP_KERNEL);
97 if (id < 0)
98 goto err_id;
99 ws->id = id;
100
101 return ws;
102
103 err_id:
104 kfree_const(ws->name);
105 err_name:
106 kfree(ws);
107 err_ws:
108 return NULL;
109 }
110 EXPORT_SYMBOL_GPL(wakeup_source_create);
111
112
113
114
115 static void wakeup_source_record(struct wakeup_source *ws)
116 {
117 unsigned long flags;
118
119 spin_lock_irqsave(&deleted_ws.lock, flags);
120
121 if (ws->event_count) {
122 deleted_ws.total_time =
123 ktime_add(deleted_ws.total_time, ws->total_time);
124 deleted_ws.prevent_sleep_time =
125 ktime_add(deleted_ws.prevent_sleep_time,
126 ws->prevent_sleep_time);
127 deleted_ws.max_time =
128 ktime_compare(deleted_ws.max_time, ws->max_time) > 0 ?
129 deleted_ws.max_time : ws->max_time;
130 deleted_ws.event_count += ws->event_count;
131 deleted_ws.active_count += ws->active_count;
132 deleted_ws.relax_count += ws->relax_count;
133 deleted_ws.expire_count += ws->expire_count;
134 deleted_ws.wakeup_count += ws->wakeup_count;
135 }
136
137 spin_unlock_irqrestore(&deleted_ws.lock, flags);
138 }
139
140 static void wakeup_source_free(struct wakeup_source *ws)
141 {
142 ida_free(&wakeup_ida, ws->id);
143 kfree_const(ws->name);
144 kfree(ws);
145 }
146
147
148
149
150
151
152
153 void wakeup_source_destroy(struct wakeup_source *ws)
154 {
155 if (!ws)
156 return;
157
158 __pm_relax(ws);
159 wakeup_source_record(ws);
160 wakeup_source_free(ws);
161 }
162 EXPORT_SYMBOL_GPL(wakeup_source_destroy);
163
164
165
166
167
168 void wakeup_source_add(struct wakeup_source *ws)
169 {
170 unsigned long flags;
171
172 if (WARN_ON(!ws))
173 return;
174
175 spin_lock_init(&ws->lock);
176 timer_setup(&ws->timer, pm_wakeup_timer_fn, 0);
177 ws->active = false;
178
179 raw_spin_lock_irqsave(&events_lock, flags);
180 list_add_rcu(&ws->entry, &wakeup_sources);
181 raw_spin_unlock_irqrestore(&events_lock, flags);
182 }
183 EXPORT_SYMBOL_GPL(wakeup_source_add);
184
185
186
187
188
189 void wakeup_source_remove(struct wakeup_source *ws)
190 {
191 unsigned long flags;
192
193 if (WARN_ON(!ws))
194 return;
195
196 raw_spin_lock_irqsave(&events_lock, flags);
197 list_del_rcu(&ws->entry);
198 raw_spin_unlock_irqrestore(&events_lock, flags);
199 synchronize_srcu(&wakeup_srcu);
200
201 del_timer_sync(&ws->timer);
202
203
204
205
206 ws->timer.function = NULL;
207 }
208 EXPORT_SYMBOL_GPL(wakeup_source_remove);
209
210
211
212
213
214
215 struct wakeup_source *wakeup_source_register(struct device *dev,
216 const char *name)
217 {
218 struct wakeup_source *ws;
219 int ret;
220
221 ws = wakeup_source_create(name);
222 if (ws) {
223 if (!dev || device_is_registered(dev)) {
224 ret = wakeup_source_sysfs_add(dev, ws);
225 if (ret) {
226 wakeup_source_free(ws);
227 return NULL;
228 }
229 }
230 wakeup_source_add(ws);
231 }
232 return ws;
233 }
234 EXPORT_SYMBOL_GPL(wakeup_source_register);
235
236
237
238
239
240 void wakeup_source_unregister(struct wakeup_source *ws)
241 {
242 if (ws) {
243 wakeup_source_remove(ws);
244 if (ws->dev)
245 wakeup_source_sysfs_remove(ws);
246
247 wakeup_source_destroy(ws);
248 }
249 }
250 EXPORT_SYMBOL_GPL(wakeup_source_unregister);
251
252
253
254
255
256
257
258
259 static int device_wakeup_attach(struct device *dev, struct wakeup_source *ws)
260 {
261 spin_lock_irq(&dev->power.lock);
262 if (dev->power.wakeup) {
263 spin_unlock_irq(&dev->power.lock);
264 return -EEXIST;
265 }
266 dev->power.wakeup = ws;
267 if (dev->power.wakeirq)
268 device_wakeup_attach_irq(dev, dev->power.wakeirq);
269 spin_unlock_irq(&dev->power.lock);
270 return 0;
271 }
272
273
274
275
276
277
278
279 int device_wakeup_enable(struct device *dev)
280 {
281 struct wakeup_source *ws;
282 int ret;
283
284 if (!dev || !dev->power.can_wakeup)
285 return -EINVAL;
286
287 if (pm_suspend_target_state != PM_SUSPEND_ON)
288 dev_dbg(dev, "Suspicious %s() during system transition!\n", __func__);
289
290 ws = wakeup_source_register(dev, dev_name(dev));
291 if (!ws)
292 return -ENOMEM;
293
294 ret = device_wakeup_attach(dev, ws);
295 if (ret)
296 wakeup_source_unregister(ws);
297
298 return ret;
299 }
300 EXPORT_SYMBOL_GPL(device_wakeup_enable);
301
302
303
304
305
306
307
308
309
310
311
312
313 void device_wakeup_attach_irq(struct device *dev,
314 struct wake_irq *wakeirq)
315 {
316 struct wakeup_source *ws;
317
318 ws = dev->power.wakeup;
319 if (!ws)
320 return;
321
322 if (ws->wakeirq)
323 dev_err(dev, "Leftover wakeup IRQ found, overriding\n");
324
325 ws->wakeirq = wakeirq;
326 }
327
328
329
330
331
332
333
334
335
336 void device_wakeup_detach_irq(struct device *dev)
337 {
338 struct wakeup_source *ws;
339
340 ws = dev->power.wakeup;
341 if (ws)
342 ws->wakeirq = NULL;
343 }
344
345
346
347
348
349
350 void device_wakeup_arm_wake_irqs(void)
351 {
352 struct wakeup_source *ws;
353 int srcuidx;
354
355 srcuidx = srcu_read_lock(&wakeup_srcu);
356 list_for_each_entry_rcu(ws, &wakeup_sources, entry)
357 dev_pm_arm_wake_irq(ws->wakeirq);
358 srcu_read_unlock(&wakeup_srcu, srcuidx);
359 }
360
361
362
363
364
365
366 void device_wakeup_disarm_wake_irqs(void)
367 {
368 struct wakeup_source *ws;
369 int srcuidx;
370
371 srcuidx = srcu_read_lock(&wakeup_srcu);
372 list_for_each_entry_rcu(ws, &wakeup_sources, entry)
373 dev_pm_disarm_wake_irq(ws->wakeirq);
374 srcu_read_unlock(&wakeup_srcu, srcuidx);
375 }
376
377
378
379
380
381
382
383 static struct wakeup_source *device_wakeup_detach(struct device *dev)
384 {
385 struct wakeup_source *ws;
386
387 spin_lock_irq(&dev->power.lock);
388 ws = dev->power.wakeup;
389 dev->power.wakeup = NULL;
390 spin_unlock_irq(&dev->power.lock);
391 return ws;
392 }
393
394
395
396
397
398
399
400
401 int device_wakeup_disable(struct device *dev)
402 {
403 struct wakeup_source *ws;
404
405 if (!dev || !dev->power.can_wakeup)
406 return -EINVAL;
407
408 ws = device_wakeup_detach(dev);
409 wakeup_source_unregister(ws);
410 return 0;
411 }
412 EXPORT_SYMBOL_GPL(device_wakeup_disable);
413
414
415
416
417
418
419
420
421
422
423
424
425
426 void device_set_wakeup_capable(struct device *dev, bool capable)
427 {
428 if (!!dev->power.can_wakeup == !!capable)
429 return;
430
431 dev->power.can_wakeup = capable;
432 if (device_is_registered(dev) && !list_empty(&dev->power.entry)) {
433 if (capable) {
434 int ret = wakeup_sysfs_add(dev);
435
436 if (ret)
437 dev_info(dev, "Wakeup sysfs attributes not added\n");
438 } else {
439 wakeup_sysfs_remove(dev);
440 }
441 }
442 }
443 EXPORT_SYMBOL_GPL(device_set_wakeup_capable);
444
445
446
447
448
449
450
451
452
453
454
455
456 int device_init_wakeup(struct device *dev, bool enable)
457 {
458 int ret = 0;
459
460 if (!dev)
461 return -EINVAL;
462
463 if (enable) {
464 device_set_wakeup_capable(dev, true);
465 ret = device_wakeup_enable(dev);
466 } else {
467 device_wakeup_disable(dev);
468 device_set_wakeup_capable(dev, false);
469 }
470
471 return ret;
472 }
473 EXPORT_SYMBOL_GPL(device_init_wakeup);
474
475
476
477
478
479 int device_set_wakeup_enable(struct device *dev, bool enable)
480 {
481 return enable ? device_wakeup_enable(dev) : device_wakeup_disable(dev);
482 }
483 EXPORT_SYMBOL_GPL(device_set_wakeup_enable);
484
485
486
487
488
489 static bool wakeup_source_not_registered(struct wakeup_source *ws)
490 {
491
492
493
494
495 return ws->timer.function != pm_wakeup_timer_fn;
496 }
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534 static void wakeup_source_activate(struct wakeup_source *ws)
535 {
536 unsigned int cec;
537
538 if (WARN_ONCE(wakeup_source_not_registered(ws),
539 "unregistered wakeup source\n"))
540 return;
541
542 ws->active = true;
543 ws->active_count++;
544 ws->last_time = ktime_get();
545 if (ws->autosleep_enabled)
546 ws->start_prevent_time = ws->last_time;
547
548
549 cec = atomic_inc_return(&combined_event_count);
550
551 trace_wakeup_source_activate(ws->name, cec);
552 }
553
554
555
556
557
558
559 static void wakeup_source_report_event(struct wakeup_source *ws, bool hard)
560 {
561 ws->event_count++;
562
563 if (events_check_enabled)
564 ws->wakeup_count++;
565
566 if (!ws->active)
567 wakeup_source_activate(ws);
568
569 if (hard)
570 pm_system_wakeup();
571 }
572
573
574
575
576
577
578
579 void __pm_stay_awake(struct wakeup_source *ws)
580 {
581 unsigned long flags;
582
583 if (!ws)
584 return;
585
586 spin_lock_irqsave(&ws->lock, flags);
587
588 wakeup_source_report_event(ws, false);
589 del_timer(&ws->timer);
590 ws->timer_expires = 0;
591
592 spin_unlock_irqrestore(&ws->lock, flags);
593 }
594 EXPORT_SYMBOL_GPL(__pm_stay_awake);
595
596
597
598
599
600
601
602
603
604
605
606
607 void pm_stay_awake(struct device *dev)
608 {
609 unsigned long flags;
610
611 if (!dev)
612 return;
613
614 spin_lock_irqsave(&dev->power.lock, flags);
615 __pm_stay_awake(dev->power.wakeup);
616 spin_unlock_irqrestore(&dev->power.lock, flags);
617 }
618 EXPORT_SYMBOL_GPL(pm_stay_awake);
619
620 #ifdef CONFIG_PM_AUTOSLEEP
621 static void update_prevent_sleep_time(struct wakeup_source *ws, ktime_t now)
622 {
623 ktime_t delta = ktime_sub(now, ws->start_prevent_time);
624 ws->prevent_sleep_time = ktime_add(ws->prevent_sleep_time, delta);
625 }
626 #else
627 static inline void update_prevent_sleep_time(struct wakeup_source *ws,
628 ktime_t now) {}
629 #endif
630
631
632
633
634
635
636
637
638
639 static void wakeup_source_deactivate(struct wakeup_source *ws)
640 {
641 unsigned int cnt, inpr, cec;
642 ktime_t duration;
643 ktime_t now;
644
645 ws->relax_count++;
646
647
648
649
650
651
652
653
654
655 if (ws->relax_count != ws->active_count) {
656 ws->relax_count--;
657 return;
658 }
659
660 ws->active = false;
661
662 now = ktime_get();
663 duration = ktime_sub(now, ws->last_time);
664 ws->total_time = ktime_add(ws->total_time, duration);
665 if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time))
666 ws->max_time = duration;
667
668 ws->last_time = now;
669 del_timer(&ws->timer);
670 ws->timer_expires = 0;
671
672 if (ws->autosleep_enabled)
673 update_prevent_sleep_time(ws, now);
674
675
676
677
678
679 cec = atomic_add_return(MAX_IN_PROGRESS, &combined_event_count);
680 trace_wakeup_source_deactivate(ws->name, cec);
681
682 split_counters(&cnt, &inpr);
683 if (!inpr && waitqueue_active(&wakeup_count_wait_queue))
684 wake_up(&wakeup_count_wait_queue);
685 }
686
687
688
689
690
691
692
693
694
695
696 void __pm_relax(struct wakeup_source *ws)
697 {
698 unsigned long flags;
699
700 if (!ws)
701 return;
702
703 spin_lock_irqsave(&ws->lock, flags);
704 if (ws->active)
705 wakeup_source_deactivate(ws);
706 spin_unlock_irqrestore(&ws->lock, flags);
707 }
708 EXPORT_SYMBOL_GPL(__pm_relax);
709
710
711
712
713
714
715
716 void pm_relax(struct device *dev)
717 {
718 unsigned long flags;
719
720 if (!dev)
721 return;
722
723 spin_lock_irqsave(&dev->power.lock, flags);
724 __pm_relax(dev->power.wakeup);
725 spin_unlock_irqrestore(&dev->power.lock, flags);
726 }
727 EXPORT_SYMBOL_GPL(pm_relax);
728
729
730
731
732
733
734
735
736
737 static void pm_wakeup_timer_fn(struct timer_list *t)
738 {
739 struct wakeup_source *ws = from_timer(ws, t, timer);
740 unsigned long flags;
741
742 spin_lock_irqsave(&ws->lock, flags);
743
744 if (ws->active && ws->timer_expires
745 && time_after_eq(jiffies, ws->timer_expires)) {
746 wakeup_source_deactivate(ws);
747 ws->expire_count++;
748 }
749
750 spin_unlock_irqrestore(&ws->lock, flags);
751 }
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766 void pm_wakeup_ws_event(struct wakeup_source *ws, unsigned int msec, bool hard)
767 {
768 unsigned long flags;
769 unsigned long expires;
770
771 if (!ws)
772 return;
773
774 spin_lock_irqsave(&ws->lock, flags);
775
776 wakeup_source_report_event(ws, hard);
777
778 if (!msec) {
779 wakeup_source_deactivate(ws);
780 goto unlock;
781 }
782
783 expires = jiffies + msecs_to_jiffies(msec);
784 if (!expires)
785 expires = 1;
786
787 if (!ws->timer_expires || time_after(expires, ws->timer_expires)) {
788 mod_timer(&ws->timer, expires);
789 ws->timer_expires = expires;
790 }
791
792 unlock:
793 spin_unlock_irqrestore(&ws->lock, flags);
794 }
795 EXPORT_SYMBOL_GPL(pm_wakeup_ws_event);
796
797
798
799
800
801
802
803
804
805 void pm_wakeup_dev_event(struct device *dev, unsigned int msec, bool hard)
806 {
807 unsigned long flags;
808
809 if (!dev)
810 return;
811
812 spin_lock_irqsave(&dev->power.lock, flags);
813 pm_wakeup_ws_event(dev->power.wakeup, msec, hard);
814 spin_unlock_irqrestore(&dev->power.lock, flags);
815 }
816 EXPORT_SYMBOL_GPL(pm_wakeup_dev_event);
817
818 void pm_print_active_wakeup_sources(void)
819 {
820 struct wakeup_source *ws;
821 int srcuidx, active = 0;
822 struct wakeup_source *last_activity_ws = NULL;
823
824 srcuidx = srcu_read_lock(&wakeup_srcu);
825 list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
826 if (ws->active) {
827 pm_pr_dbg("active wakeup source: %s\n", ws->name);
828 active = 1;
829 } else if (!active &&
830 (!last_activity_ws ||
831 ktime_to_ns(ws->last_time) >
832 ktime_to_ns(last_activity_ws->last_time))) {
833 last_activity_ws = ws;
834 }
835 }
836
837 if (!active && last_activity_ws)
838 pm_pr_dbg("last active wakeup source: %s\n",
839 last_activity_ws->name);
840 srcu_read_unlock(&wakeup_srcu, srcuidx);
841 }
842 EXPORT_SYMBOL_GPL(pm_print_active_wakeup_sources);
843
844
845
846
847
848
849
850
851
852 bool pm_wakeup_pending(void)
853 {
854 unsigned long flags;
855 bool ret = false;
856
857 raw_spin_lock_irqsave(&events_lock, flags);
858 if (events_check_enabled) {
859 unsigned int cnt, inpr;
860
861 split_counters(&cnt, &inpr);
862 ret = (cnt != saved_count || inpr > 0);
863 events_check_enabled = !ret;
864 }
865 raw_spin_unlock_irqrestore(&events_lock, flags);
866
867 if (ret) {
868 pm_pr_dbg("Wakeup pending, aborting suspend\n");
869 pm_print_active_wakeup_sources();
870 }
871
872 return ret || atomic_read(&pm_abort_suspend) > 0;
873 }
874
875 void pm_system_wakeup(void)
876 {
877 atomic_inc(&pm_abort_suspend);
878 s2idle_wake();
879 }
880 EXPORT_SYMBOL_GPL(pm_system_wakeup);
881
882 void pm_system_cancel_wakeup(void)
883 {
884 atomic_dec_if_positive(&pm_abort_suspend);
885 }
886
887 void pm_wakeup_clear(bool reset)
888 {
889 pm_wakeup_irq = 0;
890 if (reset)
891 atomic_set(&pm_abort_suspend, 0);
892 }
893
894 void pm_system_irq_wakeup(unsigned int irq_number)
895 {
896 if (pm_wakeup_irq == 0) {
897 pm_wakeup_irq = irq_number;
898 pm_system_wakeup();
899 }
900 }
901
902
903
904
905
906
907
908
909
910
911
912
913
914 bool pm_get_wakeup_count(unsigned int *count, bool block)
915 {
916 unsigned int cnt, inpr;
917
918 if (block) {
919 DEFINE_WAIT(wait);
920
921 for (;;) {
922 prepare_to_wait(&wakeup_count_wait_queue, &wait,
923 TASK_INTERRUPTIBLE);
924 split_counters(&cnt, &inpr);
925 if (inpr == 0 || signal_pending(current))
926 break;
927 pm_print_active_wakeup_sources();
928 schedule();
929 }
930 finish_wait(&wakeup_count_wait_queue, &wait);
931 }
932
933 split_counters(&cnt, &inpr);
934 *count = cnt;
935 return !inpr;
936 }
937
938
939
940
941
942
943
944
945
946
947
948 bool pm_save_wakeup_count(unsigned int count)
949 {
950 unsigned int cnt, inpr;
951 unsigned long flags;
952
953 events_check_enabled = false;
954 raw_spin_lock_irqsave(&events_lock, flags);
955 split_counters(&cnt, &inpr);
956 if (cnt == count && inpr == 0) {
957 saved_count = count;
958 events_check_enabled = true;
959 }
960 raw_spin_unlock_irqrestore(&events_lock, flags);
961 return events_check_enabled;
962 }
963
964 #ifdef CONFIG_PM_AUTOSLEEP
965
966
967
968
969 void pm_wakep_autosleep_enabled(bool set)
970 {
971 struct wakeup_source *ws;
972 ktime_t now = ktime_get();
973 int srcuidx;
974
975 srcuidx = srcu_read_lock(&wakeup_srcu);
976 list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
977 spin_lock_irq(&ws->lock);
978 if (ws->autosleep_enabled != set) {
979 ws->autosleep_enabled = set;
980 if (ws->active) {
981 if (set)
982 ws->start_prevent_time = now;
983 else
984 update_prevent_sleep_time(ws, now);
985 }
986 }
987 spin_unlock_irq(&ws->lock);
988 }
989 srcu_read_unlock(&wakeup_srcu, srcuidx);
990 }
991 #endif
992
993
994
995
996
997
998 static int print_wakeup_source_stats(struct seq_file *m,
999 struct wakeup_source *ws)
1000 {
1001 unsigned long flags;
1002 ktime_t total_time;
1003 ktime_t max_time;
1004 unsigned long active_count;
1005 ktime_t active_time;
1006 ktime_t prevent_sleep_time;
1007
1008 spin_lock_irqsave(&ws->lock, flags);
1009
1010 total_time = ws->total_time;
1011 max_time = ws->max_time;
1012 prevent_sleep_time = ws->prevent_sleep_time;
1013 active_count = ws->active_count;
1014 if (ws->active) {
1015 ktime_t now = ktime_get();
1016
1017 active_time = ktime_sub(now, ws->last_time);
1018 total_time = ktime_add(total_time, active_time);
1019 if (active_time > max_time)
1020 max_time = active_time;
1021
1022 if (ws->autosleep_enabled)
1023 prevent_sleep_time = ktime_add(prevent_sleep_time,
1024 ktime_sub(now, ws->start_prevent_time));
1025 } else {
1026 active_time = 0;
1027 }
1028
1029 seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%lld\t\t%lld\t\t%lld\t\t%lld\t\t%lld\n",
1030 ws->name, active_count, ws->event_count,
1031 ws->wakeup_count, ws->expire_count,
1032 ktime_to_ms(active_time), ktime_to_ms(total_time),
1033 ktime_to_ms(max_time), ktime_to_ms(ws->last_time),
1034 ktime_to_ms(prevent_sleep_time));
1035
1036 spin_unlock_irqrestore(&ws->lock, flags);
1037
1038 return 0;
1039 }
1040
1041 static void *wakeup_sources_stats_seq_start(struct seq_file *m,
1042 loff_t *pos)
1043 {
1044 struct wakeup_source *ws;
1045 loff_t n = *pos;
1046 int *srcuidx = m->private;
1047
1048 if (n == 0) {
1049 seq_puts(m, "name\t\tactive_count\tevent_count\twakeup_count\t"
1050 "expire_count\tactive_since\ttotal_time\tmax_time\t"
1051 "last_change\tprevent_suspend_time\n");
1052 }
1053
1054 *srcuidx = srcu_read_lock(&wakeup_srcu);
1055 list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
1056 if (n-- <= 0)
1057 return ws;
1058 }
1059
1060 return NULL;
1061 }
1062
1063 static void *wakeup_sources_stats_seq_next(struct seq_file *m,
1064 void *v, loff_t *pos)
1065 {
1066 struct wakeup_source *ws = v;
1067 struct wakeup_source *next_ws = NULL;
1068
1069 ++(*pos);
1070
1071 list_for_each_entry_continue_rcu(ws, &wakeup_sources, entry) {
1072 next_ws = ws;
1073 break;
1074 }
1075
1076 return next_ws;
1077 }
1078
1079 static void wakeup_sources_stats_seq_stop(struct seq_file *m, void *v)
1080 {
1081 int *srcuidx = m->private;
1082
1083 srcu_read_unlock(&wakeup_srcu, *srcuidx);
1084 }
1085
1086
1087
1088
1089
1090
1091 static int wakeup_sources_stats_seq_show(struct seq_file *m, void *v)
1092 {
1093 struct wakeup_source *ws = v;
1094
1095 print_wakeup_source_stats(m, ws);
1096
1097 return 0;
1098 }
1099
1100 static const struct seq_operations wakeup_sources_stats_seq_ops = {
1101 .start = wakeup_sources_stats_seq_start,
1102 .next = wakeup_sources_stats_seq_next,
1103 .stop = wakeup_sources_stats_seq_stop,
1104 .show = wakeup_sources_stats_seq_show,
1105 };
1106
1107 static int wakeup_sources_stats_open(struct inode *inode, struct file *file)
1108 {
1109 return seq_open_private(file, &wakeup_sources_stats_seq_ops, sizeof(int));
1110 }
1111
1112 static const struct file_operations wakeup_sources_stats_fops = {
1113 .owner = THIS_MODULE,
1114 .open = wakeup_sources_stats_open,
1115 .read = seq_read,
1116 .llseek = seq_lseek,
1117 .release = seq_release_private,
1118 };
1119
1120 static int __init wakeup_sources_debugfs_init(void)
1121 {
1122 debugfs_create_file("wakeup_sources", S_IRUGO, NULL, NULL,
1123 &wakeup_sources_stats_fops);
1124 return 0;
1125 }
1126
1127 postcore_initcall(wakeup_sources_debugfs_init);