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
536int device_set_wakeup_enable(struct device *dev, bool enable)
537{
538 return enable ? device_wakeup_enable(dev) : device_wakeup_disable(dev);
539}
540EXPORT_SYMBOL_GPL(device_set_wakeup_enable);
541
542
543
544
545
546static bool wakeup_source_not_registered(struct wakeup_source *ws)
547{
548
549
550
551
552 return ws->timer.function != pm_wakeup_timer_fn;
553}
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
591static void wakeup_source_activate(struct wakeup_source *ws)
592{
593 unsigned int cec;
594
595 if (WARN_ONCE(wakeup_source_not_registered(ws),
596 "unregistered wakeup source\n"))
597 return;
598
599 ws->active = true;
600 ws->active_count++;
601 ws->last_time = ktime_get();
602 if (ws->autosleep_enabled)
603 ws->start_prevent_time = ws->last_time;
604
605
606 cec = atomic_inc_return(&combined_event_count);
607
608 trace_wakeup_source_activate(ws->name, cec);
609}
610
611
612
613
614
615
616static void wakeup_source_report_event(struct wakeup_source *ws, bool hard)
617{
618 ws->event_count++;
619
620 if (events_check_enabled)
621 ws->wakeup_count++;
622
623 if (!ws->active)
624 wakeup_source_activate(ws);
625
626 if (hard)
627 pm_system_wakeup();
628}
629
630
631
632
633
634
635
636void __pm_stay_awake(struct wakeup_source *ws)
637{
638 unsigned long flags;
639
640 if (!ws)
641 return;
642
643 spin_lock_irqsave(&ws->lock, flags);
644
645 wakeup_source_report_event(ws, false);
646 del_timer(&ws->timer);
647 ws->timer_expires = 0;
648
649 spin_unlock_irqrestore(&ws->lock, flags);
650}
651EXPORT_SYMBOL_GPL(__pm_stay_awake);
652
653
654
655
656
657
658
659
660
661
662
663
664void pm_stay_awake(struct device *dev)
665{
666 unsigned long flags;
667
668 if (!dev)
669 return;
670
671 spin_lock_irqsave(&dev->power.lock, flags);
672 __pm_stay_awake(dev->power.wakeup);
673 spin_unlock_irqrestore(&dev->power.lock, flags);
674}
675EXPORT_SYMBOL_GPL(pm_stay_awake);
676
677#ifdef CONFIG_PM_AUTOSLEEP
678static void update_prevent_sleep_time(struct wakeup_source *ws, ktime_t now)
679{
680 ktime_t delta = ktime_sub(now, ws->start_prevent_time);
681 ws->prevent_sleep_time = ktime_add(ws->prevent_sleep_time, delta);
682}
683#else
684static inline void update_prevent_sleep_time(struct wakeup_source *ws,
685 ktime_t now) {}
686#endif
687
688
689
690
691
692
693
694
695
696static void wakeup_source_deactivate(struct wakeup_source *ws)
697{
698 unsigned int cnt, inpr, cec;
699 ktime_t duration;
700 ktime_t now;
701
702 ws->relax_count++;
703
704
705
706
707
708
709
710
711
712 if (ws->relax_count != ws->active_count) {
713 ws->relax_count--;
714 return;
715 }
716
717 ws->active = false;
718
719 now = ktime_get();
720 duration = ktime_sub(now, ws->last_time);
721 ws->total_time = ktime_add(ws->total_time, duration);
722 if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time))
723 ws->max_time = duration;
724
725 ws->last_time = now;
726 del_timer(&ws->timer);
727 ws->timer_expires = 0;
728
729 if (ws->autosleep_enabled)
730 update_prevent_sleep_time(ws, now);
731
732
733
734
735
736 cec = atomic_add_return(MAX_IN_PROGRESS, &combined_event_count);
737 trace_wakeup_source_deactivate(ws->name, cec);
738
739 split_counters(&cnt, &inpr);
740 if (!inpr && waitqueue_active(&wakeup_count_wait_queue))
741 wake_up(&wakeup_count_wait_queue);
742}
743
744
745
746
747
748
749
750
751
752
753void __pm_relax(struct wakeup_source *ws)
754{
755 unsigned long flags;
756
757 if (!ws)
758 return;
759
760 spin_lock_irqsave(&ws->lock, flags);
761 if (ws->active)
762 wakeup_source_deactivate(ws);
763 spin_unlock_irqrestore(&ws->lock, flags);
764}
765EXPORT_SYMBOL_GPL(__pm_relax);
766
767
768
769
770
771
772
773void pm_relax(struct device *dev)
774{
775 unsigned long flags;
776
777 if (!dev)
778 return;
779
780 spin_lock_irqsave(&dev->power.lock, flags);
781 __pm_relax(dev->power.wakeup);
782 spin_unlock_irqrestore(&dev->power.lock, flags);
783}
784EXPORT_SYMBOL_GPL(pm_relax);
785
786
787
788
789
790
791
792
793
794static void pm_wakeup_timer_fn(struct timer_list *t)
795{
796 struct wakeup_source *ws = from_timer(ws, t, timer);
797 unsigned long flags;
798
799 spin_lock_irqsave(&ws->lock, flags);
800
801 if (ws->active && ws->timer_expires
802 && time_after_eq(jiffies, ws->timer_expires)) {
803 wakeup_source_deactivate(ws);
804 ws->expire_count++;
805 }
806
807 spin_unlock_irqrestore(&ws->lock, flags);
808}
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823void pm_wakeup_ws_event(struct wakeup_source *ws, unsigned int msec, bool hard)
824{
825 unsigned long flags;
826 unsigned long expires;
827
828 if (!ws)
829 return;
830
831 spin_lock_irqsave(&ws->lock, flags);
832
833 wakeup_source_report_event(ws, hard);
834
835 if (!msec) {
836 wakeup_source_deactivate(ws);
837 goto unlock;
838 }
839
840 expires = jiffies + msecs_to_jiffies(msec);
841 if (!expires)
842 expires = 1;
843
844 if (!ws->timer_expires || time_after(expires, ws->timer_expires)) {
845 mod_timer(&ws->timer, expires);
846 ws->timer_expires = expires;
847 }
848
849 unlock:
850 spin_unlock_irqrestore(&ws->lock, flags);
851}
852EXPORT_SYMBOL_GPL(pm_wakeup_ws_event);
853
854
855
856
857
858
859
860
861
862void pm_wakeup_dev_event(struct device *dev, unsigned int msec, bool hard)
863{
864 unsigned long flags;
865
866 if (!dev)
867 return;
868
869 spin_lock_irqsave(&dev->power.lock, flags);
870 pm_wakeup_ws_event(dev->power.wakeup, msec, hard);
871 spin_unlock_irqrestore(&dev->power.lock, flags);
872}
873EXPORT_SYMBOL_GPL(pm_wakeup_dev_event);
874
875void pm_print_active_wakeup_sources(void)
876{
877 struct wakeup_source *ws;
878 int srcuidx, active = 0;
879 struct wakeup_source *last_activity_ws = NULL;
880
881 srcuidx = srcu_read_lock(&wakeup_srcu);
882 list_for_each_entry_rcu_locked(ws, &wakeup_sources, entry) {
883 if (ws->active) {
884 pm_pr_dbg("active wakeup source: %s\n", ws->name);
885 active = 1;
886 } else if (!active &&
887 (!last_activity_ws ||
888 ktime_to_ns(ws->last_time) >
889 ktime_to_ns(last_activity_ws->last_time))) {
890 last_activity_ws = ws;
891 }
892 }
893
894 if (!active && last_activity_ws)
895 pm_pr_dbg("last active wakeup source: %s\n",
896 last_activity_ws->name);
897 srcu_read_unlock(&wakeup_srcu, srcuidx);
898}
899EXPORT_SYMBOL_GPL(pm_print_active_wakeup_sources);
900
901
902
903
904
905
906
907
908
909bool pm_wakeup_pending(void)
910{
911 unsigned long flags;
912 bool ret = false;
913
914 raw_spin_lock_irqsave(&events_lock, flags);
915 if (events_check_enabled) {
916 unsigned int cnt, inpr;
917
918 split_counters(&cnt, &inpr);
919 ret = (cnt != saved_count || inpr > 0);
920 events_check_enabled = !ret;
921 }
922 raw_spin_unlock_irqrestore(&events_lock, flags);
923
924 if (ret) {
925 pm_pr_dbg("Wakeup pending, aborting suspend\n");
926 pm_print_active_wakeup_sources();
927 }
928
929 return ret || atomic_read(&pm_abort_suspend) > 0;
930}
931
932void pm_system_wakeup(void)
933{
934 atomic_inc(&pm_abort_suspend);
935 s2idle_wake();
936}
937EXPORT_SYMBOL_GPL(pm_system_wakeup);
938
939void pm_system_cancel_wakeup(void)
940{
941 atomic_dec_if_positive(&pm_abort_suspend);
942}
943
944void pm_wakeup_clear(bool reset)
945{
946 pm_wakeup_irq = 0;
947 if (reset)
948 atomic_set(&pm_abort_suspend, 0);
949}
950
951void pm_system_irq_wakeup(unsigned int irq_number)
952{
953 if (pm_wakeup_irq == 0) {
954 pm_wakeup_irq = irq_number;
955 pm_system_wakeup();
956 }
957}
958
959
960
961
962
963
964
965
966
967
968
969
970
971bool pm_get_wakeup_count(unsigned int *count, bool block)
972{
973 unsigned int cnt, inpr;
974
975 if (block) {
976 DEFINE_WAIT(wait);
977
978 for (;;) {
979 prepare_to_wait(&wakeup_count_wait_queue, &wait,
980 TASK_INTERRUPTIBLE);
981 split_counters(&cnt, &inpr);
982 if (inpr == 0 || signal_pending(current))
983 break;
984 pm_print_active_wakeup_sources();
985 schedule();
986 }
987 finish_wait(&wakeup_count_wait_queue, &wait);
988 }
989
990 split_counters(&cnt, &inpr);
991 *count = cnt;
992 return !inpr;
993}
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005bool pm_save_wakeup_count(unsigned int count)
1006{
1007 unsigned int cnt, inpr;
1008 unsigned long flags;
1009
1010 events_check_enabled = false;
1011 raw_spin_lock_irqsave(&events_lock, flags);
1012 split_counters(&cnt, &inpr);
1013 if (cnt == count && inpr == 0) {
1014 saved_count = count;
1015 events_check_enabled = true;
1016 }
1017 raw_spin_unlock_irqrestore(&events_lock, flags);
1018 return events_check_enabled;
1019}
1020
1021#ifdef CONFIG_PM_AUTOSLEEP
1022
1023
1024
1025
1026void pm_wakep_autosleep_enabled(bool set)
1027{
1028 struct wakeup_source *ws;
1029 ktime_t now = ktime_get();
1030 int srcuidx;
1031
1032 srcuidx = srcu_read_lock(&wakeup_srcu);
1033 list_for_each_entry_rcu_locked(ws, &wakeup_sources, entry) {
1034 spin_lock_irq(&ws->lock);
1035 if (ws->autosleep_enabled != set) {
1036 ws->autosleep_enabled = set;
1037 if (ws->active) {
1038 if (set)
1039 ws->start_prevent_time = now;
1040 else
1041 update_prevent_sleep_time(ws, now);
1042 }
1043 }
1044 spin_unlock_irq(&ws->lock);
1045 }
1046 srcu_read_unlock(&wakeup_srcu, srcuidx);
1047}
1048#endif
1049
1050
1051
1052
1053
1054
1055static int print_wakeup_source_stats(struct seq_file *m,
1056 struct wakeup_source *ws)
1057{
1058 unsigned long flags;
1059 ktime_t total_time;
1060 ktime_t max_time;
1061 unsigned long active_count;
1062 ktime_t active_time;
1063 ktime_t prevent_sleep_time;
1064
1065 spin_lock_irqsave(&ws->lock, flags);
1066
1067 total_time = ws->total_time;
1068 max_time = ws->max_time;
1069 prevent_sleep_time = ws->prevent_sleep_time;
1070 active_count = ws->active_count;
1071 if (ws->active) {
1072 ktime_t now = ktime_get();
1073
1074 active_time = ktime_sub(now, ws->last_time);
1075 total_time = ktime_add(total_time, active_time);
1076 if (active_time > max_time)
1077 max_time = active_time;
1078
1079 if (ws->autosleep_enabled)
1080 prevent_sleep_time = ktime_add(prevent_sleep_time,
1081 ktime_sub(now, ws->start_prevent_time));
1082 } else {
1083 active_time = 0;
1084 }
1085
1086 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",
1087 ws->name, active_count, ws->event_count,
1088 ws->wakeup_count, ws->expire_count,
1089 ktime_to_ms(active_time), ktime_to_ms(total_time),
1090 ktime_to_ms(max_time), ktime_to_ms(ws->last_time),
1091 ktime_to_ms(prevent_sleep_time));
1092
1093 spin_unlock_irqrestore(&ws->lock, flags);
1094
1095 return 0;
1096}
1097
1098static void *wakeup_sources_stats_seq_start(struct seq_file *m,
1099 loff_t *pos)
1100{
1101 struct wakeup_source *ws;
1102 loff_t n = *pos;
1103 int *srcuidx = m->private;
1104
1105 if (n == 0) {
1106 seq_puts(m, "name\t\tactive_count\tevent_count\twakeup_count\t"
1107 "expire_count\tactive_since\ttotal_time\tmax_time\t"
1108 "last_change\tprevent_suspend_time\n");
1109 }
1110
1111 *srcuidx = srcu_read_lock(&wakeup_srcu);
1112 list_for_each_entry_rcu_locked(ws, &wakeup_sources, entry) {
1113 if (n-- <= 0)
1114 return ws;
1115 }
1116
1117 return NULL;
1118}
1119
1120static void *wakeup_sources_stats_seq_next(struct seq_file *m,
1121 void *v, loff_t *pos)
1122{
1123 struct wakeup_source *ws = v;
1124 struct wakeup_source *next_ws = NULL;
1125
1126 ++(*pos);
1127
1128 list_for_each_entry_continue_rcu(ws, &wakeup_sources, entry) {
1129 next_ws = ws;
1130 break;
1131 }
1132
1133 if (!next_ws)
1134 print_wakeup_source_stats(m, &deleted_ws);
1135
1136 return next_ws;
1137}
1138
1139static void wakeup_sources_stats_seq_stop(struct seq_file *m, void *v)
1140{
1141 int *srcuidx = m->private;
1142
1143 srcu_read_unlock(&wakeup_srcu, *srcuidx);
1144}
1145
1146
1147
1148
1149
1150
1151static int wakeup_sources_stats_seq_show(struct seq_file *m, void *v)
1152{
1153 struct wakeup_source *ws = v;
1154
1155 print_wakeup_source_stats(m, ws);
1156
1157 return 0;
1158}
1159
1160static const struct seq_operations wakeup_sources_stats_seq_ops = {
1161 .start = wakeup_sources_stats_seq_start,
1162 .next = wakeup_sources_stats_seq_next,
1163 .stop = wakeup_sources_stats_seq_stop,
1164 .show = wakeup_sources_stats_seq_show,
1165};
1166
1167static int wakeup_sources_stats_open(struct inode *inode, struct file *file)
1168{
1169 return seq_open_private(file, &wakeup_sources_stats_seq_ops, sizeof(int));
1170}
1171
1172static const struct file_operations wakeup_sources_stats_fops = {
1173 .owner = THIS_MODULE,
1174 .open = wakeup_sources_stats_open,
1175 .read = seq_read,
1176 .llseek = seq_lseek,
1177 .release = seq_release_private,
1178};
1179
1180static int __init wakeup_sources_debugfs_init(void)
1181{
1182 debugfs_create_file("wakeup_sources", S_IRUGO, NULL, NULL,
1183 &wakeup_sources_stats_fops);
1184 return 0;
1185}
1186
1187postcore_initcall(wakeup_sources_debugfs_init);
1188