diff options
Diffstat (limited to 'kernel/power/main.c')
-rw-r--r-- | kernel/power/main.c | 99 |
1 files changed, 96 insertions, 3 deletions
diff --git a/kernel/power/main.c b/kernel/power/main.c index bdbd605c4215..e8710d179b35 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c | |||
@@ -254,7 +254,6 @@ static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr, | |||
254 | power_attr(pm_test); | 254 | power_attr(pm_test); |
255 | #endif /* CONFIG_PM_SLEEP_DEBUG */ | 255 | #endif /* CONFIG_PM_SLEEP_DEBUG */ |
256 | 256 | ||
257 | #ifdef CONFIG_DEBUG_FS | ||
258 | static char *suspend_step_name(enum suspend_stat_step step) | 257 | static char *suspend_step_name(enum suspend_stat_step step) |
259 | { | 258 | { |
260 | switch (step) { | 259 | switch (step) { |
@@ -275,6 +274,92 @@ static char *suspend_step_name(enum suspend_stat_step step) | |||
275 | } | 274 | } |
276 | } | 275 | } |
277 | 276 | ||
277 | #define suspend_attr(_name) \ | ||
278 | static ssize_t _name##_show(struct kobject *kobj, \ | ||
279 | struct kobj_attribute *attr, char *buf) \ | ||
280 | { \ | ||
281 | return sprintf(buf, "%d\n", suspend_stats._name); \ | ||
282 | } \ | ||
283 | static struct kobj_attribute _name = __ATTR_RO(_name) | ||
284 | |||
285 | suspend_attr(success); | ||
286 | suspend_attr(fail); | ||
287 | suspend_attr(failed_freeze); | ||
288 | suspend_attr(failed_prepare); | ||
289 | suspend_attr(failed_suspend); | ||
290 | suspend_attr(failed_suspend_late); | ||
291 | suspend_attr(failed_suspend_noirq); | ||
292 | suspend_attr(failed_resume); | ||
293 | suspend_attr(failed_resume_early); | ||
294 | suspend_attr(failed_resume_noirq); | ||
295 | |||
296 | static ssize_t last_failed_dev_show(struct kobject *kobj, | ||
297 | struct kobj_attribute *attr, char *buf) | ||
298 | { | ||
299 | int index; | ||
300 | char *last_failed_dev = NULL; | ||
301 | |||
302 | index = suspend_stats.last_failed_dev + REC_FAILED_NUM - 1; | ||
303 | index %= REC_FAILED_NUM; | ||
304 | last_failed_dev = suspend_stats.failed_devs[index]; | ||
305 | |||
306 | return sprintf(buf, "%s\n", last_failed_dev); | ||
307 | } | ||
308 | static struct kobj_attribute last_failed_dev = __ATTR_RO(last_failed_dev); | ||
309 | |||
310 | static ssize_t last_failed_errno_show(struct kobject *kobj, | ||
311 | struct kobj_attribute *attr, char *buf) | ||
312 | { | ||
313 | int index; | ||
314 | int last_failed_errno; | ||
315 | |||
316 | index = suspend_stats.last_failed_errno + REC_FAILED_NUM - 1; | ||
317 | index %= REC_FAILED_NUM; | ||
318 | last_failed_errno = suspend_stats.errno[index]; | ||
319 | |||
320 | return sprintf(buf, "%d\n", last_failed_errno); | ||
321 | } | ||
322 | static struct kobj_attribute last_failed_errno = __ATTR_RO(last_failed_errno); | ||
323 | |||
324 | static ssize_t last_failed_step_show(struct kobject *kobj, | ||
325 | struct kobj_attribute *attr, char *buf) | ||
326 | { | ||
327 | int index; | ||
328 | enum suspend_stat_step step; | ||
329 | char *last_failed_step = NULL; | ||
330 | |||
331 | index = suspend_stats.last_failed_step + REC_FAILED_NUM - 1; | ||
332 | index %= REC_FAILED_NUM; | ||
333 | step = suspend_stats.failed_steps[index]; | ||
334 | last_failed_step = suspend_step_name(step); | ||
335 | |||
336 | return sprintf(buf, "%s\n", last_failed_step); | ||
337 | } | ||
338 | static struct kobj_attribute last_failed_step = __ATTR_RO(last_failed_step); | ||
339 | |||
340 | static struct attribute *suspend_attrs[] = { | ||
341 | &success.attr, | ||
342 | &fail.attr, | ||
343 | &failed_freeze.attr, | ||
344 | &failed_prepare.attr, | ||
345 | &failed_suspend.attr, | ||
346 | &failed_suspend_late.attr, | ||
347 | &failed_suspend_noirq.attr, | ||
348 | &failed_resume.attr, | ||
349 | &failed_resume_early.attr, | ||
350 | &failed_resume_noirq.attr, | ||
351 | &last_failed_dev.attr, | ||
352 | &last_failed_errno.attr, | ||
353 | &last_failed_step.attr, | ||
354 | NULL, | ||
355 | }; | ||
356 | |||
357 | static struct attribute_group suspend_attr_group = { | ||
358 | .name = "suspend_stats", | ||
359 | .attrs = suspend_attrs, | ||
360 | }; | ||
361 | |||
362 | #ifdef CONFIG_DEBUG_FS | ||
278 | static int suspend_stats_show(struct seq_file *s, void *unused) | 363 | static int suspend_stats_show(struct seq_file *s, void *unused) |
279 | { | 364 | { |
280 | int i, index, last_dev, last_errno, last_step; | 365 | int i, index, last_dev, last_errno, last_step; |
@@ -495,7 +580,7 @@ static suspend_state_t decode_state(const char *buf, size_t n) | |||
495 | len = p ? p - buf : n; | 580 | len = p ? p - buf : n; |
496 | 581 | ||
497 | /* Check hibernation first. */ | 582 | /* Check hibernation first. */ |
498 | if (len == 4 && !strncmp(buf, "disk", len)) | 583 | if (len == 4 && str_has_prefix(buf, "disk")) |
499 | return PM_SUSPEND_MAX; | 584 | return PM_SUSPEND_MAX; |
500 | 585 | ||
501 | #ifdef CONFIG_SUSPEND | 586 | #ifdef CONFIG_SUSPEND |
@@ -794,6 +879,14 @@ static const struct attribute_group attr_group = { | |||
794 | .attrs = g, | 879 | .attrs = g, |
795 | }; | 880 | }; |
796 | 881 | ||
882 | static const struct attribute_group *attr_groups[] = { | ||
883 | &attr_group, | ||
884 | #ifdef CONFIG_PM_SLEEP | ||
885 | &suspend_attr_group, | ||
886 | #endif | ||
887 | NULL, | ||
888 | }; | ||
889 | |||
797 | struct workqueue_struct *pm_wq; | 890 | struct workqueue_struct *pm_wq; |
798 | EXPORT_SYMBOL_GPL(pm_wq); | 891 | EXPORT_SYMBOL_GPL(pm_wq); |
799 | 892 | ||
@@ -815,7 +908,7 @@ static int __init pm_init(void) | |||
815 | power_kobj = kobject_create_and_add("power", NULL); | 908 | power_kobj = kobject_create_and_add("power", NULL); |
816 | if (!power_kobj) | 909 | if (!power_kobj) |
817 | return -ENOMEM; | 910 | return -ENOMEM; |
818 | error = sysfs_create_group(power_kobj, &attr_group); | 911 | error = sysfs_create_groups(power_kobj, attr_groups); |
819 | if (error) | 912 | if (error) |
820 | return error; | 913 | return error; |
821 | pm_print_times_init(); | 914 | pm_print_times_init(); |