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