diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /kernel/power/suspend_time.c | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'kernel/power/suspend_time.c')
-rw-r--r-- | kernel/power/suspend_time.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/kernel/power/suspend_time.c b/kernel/power/suspend_time.c new file mode 100644 index 00000000000..d2a65da9f22 --- /dev/null +++ b/kernel/power/suspend_time.c | |||
@@ -0,0 +1,111 @@ | |||
1 | /* | ||
2 | * debugfs file to track time spent in suspend | ||
3 | * | ||
4 | * Copyright (c) 2011, Google, Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/debugfs.h> | ||
18 | #include <linux/err.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/seq_file.h> | ||
22 | #include <linux/syscore_ops.h> | ||
23 | #include <linux/time.h> | ||
24 | |||
25 | static struct timespec suspend_time_before; | ||
26 | static unsigned int time_in_suspend_bins[32]; | ||
27 | |||
28 | #ifdef CONFIG_DEBUG_FS | ||
29 | static int suspend_time_debug_show(struct seq_file *s, void *data) | ||
30 | { | ||
31 | int bin; | ||
32 | seq_printf(s, "time (secs) count\n"); | ||
33 | seq_printf(s, "------------------\n"); | ||
34 | for (bin = 0; bin < 32; bin++) { | ||
35 | if (time_in_suspend_bins[bin] == 0) | ||
36 | continue; | ||
37 | seq_printf(s, "%4d - %4d %4u\n", | ||
38 | bin ? 1 << (bin - 1) : 0, 1 << bin, | ||
39 | time_in_suspend_bins[bin]); | ||
40 | } | ||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | static int suspend_time_debug_open(struct inode *inode, struct file *file) | ||
45 | { | ||
46 | return single_open(file, suspend_time_debug_show, NULL); | ||
47 | } | ||
48 | |||
49 | static const struct file_operations suspend_time_debug_fops = { | ||
50 | .open = suspend_time_debug_open, | ||
51 | .read = seq_read, | ||
52 | .llseek = seq_lseek, | ||
53 | .release = single_release, | ||
54 | }; | ||
55 | |||
56 | static int __init suspend_time_debug_init(void) | ||
57 | { | ||
58 | struct dentry *d; | ||
59 | |||
60 | d = debugfs_create_file("suspend_time", 0755, NULL, NULL, | ||
61 | &suspend_time_debug_fops); | ||
62 | if (!d) { | ||
63 | pr_err("Failed to create suspend_time debug file\n"); | ||
64 | return -ENOMEM; | ||
65 | } | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | late_initcall(suspend_time_debug_init); | ||
71 | #endif | ||
72 | |||
73 | static int suspend_time_syscore_suspend(void) | ||
74 | { | ||
75 | read_persistent_clock(&suspend_time_before); | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static void suspend_time_syscore_resume(void) | ||
81 | { | ||
82 | struct timespec after; | ||
83 | |||
84 | read_persistent_clock(&after); | ||
85 | |||
86 | after = timespec_sub(after, suspend_time_before); | ||
87 | |||
88 | time_in_suspend_bins[fls(after.tv_sec)]++; | ||
89 | |||
90 | pr_info("Suspended for %lu.%03lu seconds\n", after.tv_sec, | ||
91 | after.tv_nsec / NSEC_PER_MSEC); | ||
92 | } | ||
93 | |||
94 | static struct syscore_ops suspend_time_syscore_ops = { | ||
95 | .suspend = suspend_time_syscore_suspend, | ||
96 | .resume = suspend_time_syscore_resume, | ||
97 | }; | ||
98 | |||
99 | static int suspend_time_syscore_init(void) | ||
100 | { | ||
101 | register_syscore_ops(&suspend_time_syscore_ops); | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static void suspend_time_syscore_exit(void) | ||
107 | { | ||
108 | unregister_syscore_ops(&suspend_time_syscore_ops); | ||
109 | } | ||
110 | module_init(suspend_time_syscore_init); | ||
111 | module_exit(suspend_time_syscore_exit); | ||