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