|
11 | 11 | #include <linux/sched.h>
|
12 | 12 | #include <linux/capability.h>
|
13 | 13 | #include <linux/suspend.h>
|
| 14 | +#include <linux/seq_file.h> |
| 15 | +#include <linux/debugfs.h> |
14 | 16 |
|
15 | 17 | #include "power.h"
|
16 | 18 |
|
@@ -617,3 +619,86 @@ bool pm_save_wakeup_count(unsigned int count)
|
617 | 619 | pm_wakeup_update_hit_counts();
|
618 | 620 | return ret;
|
619 | 621 | }
|
| 622 | + |
| 623 | +static struct dentry *wakeup_sources_stats_dentry; |
| 624 | + |
| 625 | +/** |
| 626 | + * print_wakeup_source_stats - Print wakeup source statistics information. |
| 627 | + * @m: seq_file to print the statistics into. |
| 628 | + * @ws: Wakeup source object to print the statistics for. |
| 629 | + */ |
| 630 | +static int print_wakeup_source_stats(struct seq_file *m, |
| 631 | + struct wakeup_source *ws) |
| 632 | +{ |
| 633 | + unsigned long flags; |
| 634 | + ktime_t total_time; |
| 635 | + ktime_t max_time; |
| 636 | + unsigned long active_count; |
| 637 | + ktime_t active_time; |
| 638 | + int ret; |
| 639 | + |
| 640 | + spin_lock_irqsave(&ws->lock, flags); |
| 641 | + |
| 642 | + total_time = ws->total_time; |
| 643 | + max_time = ws->max_time; |
| 644 | + active_count = ws->active_count; |
| 645 | + if (ws->active) { |
| 646 | + active_time = ktime_sub(ktime_get(), ws->last_time); |
| 647 | + total_time = ktime_add(total_time, active_time); |
| 648 | + if (active_time.tv64 > max_time.tv64) |
| 649 | + max_time = active_time; |
| 650 | + } else { |
| 651 | + active_time = ktime_set(0, 0); |
| 652 | + } |
| 653 | + |
| 654 | + ret = seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t" |
| 655 | + "%lld\t\t%lld\t\t%lld\t\t%lld\n", |
| 656 | + ws->name, active_count, ws->event_count, ws->hit_count, |
| 657 | + ktime_to_ms(active_time), ktime_to_ms(total_time), |
| 658 | + ktime_to_ms(max_time), ktime_to_ms(ws->last_time)); |
| 659 | + |
| 660 | + spin_unlock_irqrestore(&ws->lock, flags); |
| 661 | + |
| 662 | + return ret; |
| 663 | +} |
| 664 | + |
| 665 | +/** |
| 666 | + * wakeup_sources_stats_show - Print wakeup sources statistics information. |
| 667 | + * @m: seq_file to print the statistics into. |
| 668 | + */ |
| 669 | +static int wakeup_sources_stats_show(struct seq_file *m, void *unused) |
| 670 | +{ |
| 671 | + struct wakeup_source *ws; |
| 672 | + |
| 673 | + seq_puts(m, "name\t\tactive_count\tevent_count\thit_count\t" |
| 674 | + "active_since\ttotal_time\tmax_time\tlast_change\n"); |
| 675 | + |
| 676 | + rcu_read_lock(); |
| 677 | + list_for_each_entry_rcu(ws, &wakeup_sources, entry) |
| 678 | + print_wakeup_source_stats(m, ws); |
| 679 | + rcu_read_unlock(); |
| 680 | + |
| 681 | + return 0; |
| 682 | +} |
| 683 | + |
| 684 | +static int wakeup_sources_stats_open(struct inode *inode, struct file *file) |
| 685 | +{ |
| 686 | + return single_open(file, wakeup_sources_stats_show, NULL); |
| 687 | +} |
| 688 | + |
| 689 | +static const struct file_operations wakeup_sources_stats_fops = { |
| 690 | + .owner = THIS_MODULE, |
| 691 | + .open = wakeup_sources_stats_open, |
| 692 | + .read = seq_read, |
| 693 | + .llseek = seq_lseek, |
| 694 | + .release = single_release, |
| 695 | +}; |
| 696 | + |
| 697 | +static int __init wakeup_sources_debugfs_init(void) |
| 698 | +{ |
| 699 | + wakeup_sources_stats_dentry = debugfs_create_file("wakeup_sources", |
| 700 | + S_IRUGO, NULL, NULL, &wakeup_sources_stats_fops); |
| 701 | + return 0; |
| 702 | +} |
| 703 | + |
| 704 | +postcore_initcall(wakeup_sources_debugfs_init); |
0 commit comments