aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power')
-rw-r--r--kernel/power/main.c102
-rw-r--r--kernel/power/suspend.c17
2 files changed, 116 insertions, 3 deletions
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 6c601f871964..2757acba8e8a 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -12,6 +12,8 @@
12#include <linux/string.h> 12#include <linux/string.h>
13#include <linux/resume-trace.h> 13#include <linux/resume-trace.h>
14#include <linux/workqueue.h> 14#include <linux/workqueue.h>
15#include <linux/debugfs.h>
16#include <linux/seq_file.h>
15 17
16#include "power.h" 18#include "power.h"
17 19
@@ -133,6 +135,101 @@ power_attr(pm_test);
133 135
134#endif /* CONFIG_PM_SLEEP */ 136#endif /* CONFIG_PM_SLEEP */
135 137
138#ifdef CONFIG_DEBUG_FS
139static char *suspend_step_name(enum suspend_stat_step step)
140{
141 switch (step) {
142 case SUSPEND_FREEZE:
143 return "freeze";
144 case SUSPEND_PREPARE:
145 return "prepare";
146 case SUSPEND_SUSPEND:
147 return "suspend";
148 case SUSPEND_SUSPEND_NOIRQ:
149 return "suspend_noirq";
150 case SUSPEND_RESUME_NOIRQ:
151 return "resume_noirq";
152 case SUSPEND_RESUME:
153 return "resume";
154 default:
155 return "";
156 }
157}
158
159static int suspend_stats_show(struct seq_file *s, void *unused)
160{
161 int i, index, last_dev, last_errno, last_step;
162
163 last_dev = suspend_stats.last_failed_dev + REC_FAILED_NUM - 1;
164 last_dev %= REC_FAILED_NUM;
165 last_errno = suspend_stats.last_failed_errno + REC_FAILED_NUM - 1;
166 last_errno %= REC_FAILED_NUM;
167 last_step = suspend_stats.last_failed_step + REC_FAILED_NUM - 1;
168 last_step %= REC_FAILED_NUM;
169 seq_printf(s, "%s: %d\n%s: %d\n%s: %d\n%s: %d\n"
170 "%s: %d\n%s: %d\n%s: %d\n%s: %d\n",
171 "success", suspend_stats.success,
172 "fail", suspend_stats.fail,
173 "failed_freeze", suspend_stats.failed_freeze,
174 "failed_prepare", suspend_stats.failed_prepare,
175 "failed_suspend", suspend_stats.failed_suspend,
176 "failed_suspend_noirq",
177 suspend_stats.failed_suspend_noirq,
178 "failed_resume", suspend_stats.failed_resume,
179 "failed_resume_noirq",
180 suspend_stats.failed_resume_noirq);
181 seq_printf(s, "failures:\n last_failed_dev:\t%-s\n",
182 suspend_stats.failed_devs[last_dev]);
183 for (i = 1; i < REC_FAILED_NUM; i++) {
184 index = last_dev + REC_FAILED_NUM - i;
185 index %= REC_FAILED_NUM;
186 seq_printf(s, "\t\t\t%-s\n",
187 suspend_stats.failed_devs[index]);
188 }
189 seq_printf(s, " last_failed_errno:\t%-d\n",
190 suspend_stats.errno[last_errno]);
191 for (i = 1; i < REC_FAILED_NUM; i++) {
192 index = last_errno + REC_FAILED_NUM - i;
193 index %= REC_FAILED_NUM;
194 seq_printf(s, "\t\t\t%-d\n",
195 suspend_stats.errno[index]);
196 }
197 seq_printf(s, " last_failed_step:\t%-s\n",
198 suspend_step_name(
199 suspend_stats.failed_steps[last_step]));
200 for (i = 1; i < REC_FAILED_NUM; i++) {
201 index = last_step + REC_FAILED_NUM - i;
202 index %= REC_FAILED_NUM;
203 seq_printf(s, "\t\t\t%-s\n",
204 suspend_step_name(
205 suspend_stats.failed_steps[index]));
206 }
207
208 return 0;
209}
210
211static int suspend_stats_open(struct inode *inode, struct file *file)
212{
213 return single_open(file, suspend_stats_show, NULL);
214}
215
216static const struct file_operations suspend_stats_operations = {
217 .open = suspend_stats_open,
218 .read = seq_read,
219 .llseek = seq_lseek,
220 .release = single_release,
221};
222
223static int __init pm_debugfs_init(void)
224{
225 debugfs_create_file("suspend_stats", S_IFREG | S_IRUGO,
226 NULL, NULL, &suspend_stats_operations);
227 return 0;
228}
229
230late_initcall(pm_debugfs_init);
231#endif /* CONFIG_DEBUG_FS */
232
136struct kobject *power_kobj; 233struct kobject *power_kobj;
137 234
138/** 235/**
@@ -194,6 +291,11 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
194 } 291 }
195 if (state < PM_SUSPEND_MAX && *s) 292 if (state < PM_SUSPEND_MAX && *s)
196 error = enter_state(state); 293 error = enter_state(state);
294 if (error) {
295 suspend_stats.fail++;
296 dpm_save_failed_errno(error);
297 } else
298 suspend_stats.success++;
197#endif 299#endif
198 300
199 Exit: 301 Exit:
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index b6b71ad2208f..595a3dd56a8a 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -104,7 +104,10 @@ static int suspend_prepare(void)
104 goto Finish; 104 goto Finish;
105 105
106 error = suspend_freeze_processes(); 106 error = suspend_freeze_processes();
107 if (!error) 107 if (error) {
108 suspend_stats.failed_freeze++;
109 dpm_save_failed_step(SUSPEND_FREEZE);
110 } else
108 return 0; 111 return 0;
109 112
110 suspend_thaw_processes(); 113 suspend_thaw_processes();
@@ -315,8 +318,16 @@ int enter_state(suspend_state_t state)
315 */ 318 */
316int pm_suspend(suspend_state_t state) 319int pm_suspend(suspend_state_t state)
317{ 320{
318 if (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX) 321 int ret;
319 return enter_state(state); 322 if (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX) {
323 ret = enter_state(state);
324 if (ret) {
325 suspend_stats.fail++;
326 dpm_save_failed_errno(ret);
327 } else
328 suspend_stats.success++;
329 return ret;
330 }
320 return -EINVAL; 331 return -EINVAL;
321} 332}
322EXPORT_SYMBOL(pm_suspend); 333EXPORT_SYMBOL(pm_suspend);