aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorShuoX Liu <shuox.liu@intel.com>2011-08-10 17:01:26 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2011-10-16 17:27:45 -0400
commit2a77c46de1e3dace73745015635ebbc648eca69c (patch)
treea801ed6ba5623c7d963377906776ade6f02eea0a /drivers/base
parent9bd717c0dc8224cadfd66df7eeff98c987711d98 (diff)
PM / Suspend: Add statistics debugfs file for suspend to RAM
Record S3 failure time about each reason and the latest two failed devices' names in S3 progress. We can check it through 'suspend_stats' entry in debugfs. The motivation of the patch: We are enabling power features on Medfield. Comparing with PC/notebook, a mobile enters/exits suspend-2-ram (we call it s3 on Medfield) far more frequently. If it can't enter suspend-2-ram in time, the power might be used up soon. We often find sometimes, a device suspend fails. Then, system retries s3 over and over again. As display is off, testers and developers don't know what happens. Some testers and developers complain they don't know if system tries suspend-2-ram, and what device fails to suspend. They need such info for a quick check. The patch adds suspend_stats under debugfs for users to check suspend to RAM statistics quickly. If not using this patch, we have other methods to get info about what device fails. One is to turn on CONFIG_PM_DEBUG, but users would get too much info and testers need recompile the system. In addition, dynamic debug is another good tool to dump debug info. But it still doesn't match our utilization scenario closely. 1) user need write a user space parser to process the syslog output; 2) Our testing scenario is we leave the mobile for at least hours. Then, check its status. No serial console available during the testing. One is because console would be suspended, and the other is serial console connecting with spi or HSU devices would consume power. These devices are powered off at suspend-2-ram. Signed-off-by: ShuoX Liu <shuox.liu@intel.com> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/main.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index c6291ab725a3..b1b58260b4ff 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -46,6 +46,7 @@ LIST_HEAD(dpm_prepared_list);
46LIST_HEAD(dpm_suspended_list); 46LIST_HEAD(dpm_suspended_list);
47LIST_HEAD(dpm_noirq_list); 47LIST_HEAD(dpm_noirq_list);
48 48
49struct suspend_stats suspend_stats;
49static DEFINE_MUTEX(dpm_list_mtx); 50static DEFINE_MUTEX(dpm_list_mtx);
50static pm_message_t pm_transition; 51static pm_message_t pm_transition;
51 52
@@ -467,8 +468,12 @@ void dpm_resume_noirq(pm_message_t state)
467 mutex_unlock(&dpm_list_mtx); 468 mutex_unlock(&dpm_list_mtx);
468 469
469 error = device_resume_noirq(dev, state); 470 error = device_resume_noirq(dev, state);
470 if (error) 471 if (error) {
472 suspend_stats.failed_resume_noirq++;
473 dpm_save_failed_step(SUSPEND_RESUME_NOIRQ);
474 dpm_save_failed_dev(dev_name(dev));
471 pm_dev_err(dev, state, " early", error); 475 pm_dev_err(dev, state, " early", error);
476 }
472 477
473 mutex_lock(&dpm_list_mtx); 478 mutex_lock(&dpm_list_mtx);
474 put_device(dev); 479 put_device(dev);
@@ -629,8 +634,12 @@ void dpm_resume(pm_message_t state)
629 mutex_unlock(&dpm_list_mtx); 634 mutex_unlock(&dpm_list_mtx);
630 635
631 error = device_resume(dev, state, false); 636 error = device_resume(dev, state, false);
632 if (error) 637 if (error) {
638 suspend_stats.failed_resume++;
639 dpm_save_failed_step(SUSPEND_RESUME);
640 dpm_save_failed_dev(dev_name(dev));
633 pm_dev_err(dev, state, "", error); 641 pm_dev_err(dev, state, "", error);
642 }
634 643
635 mutex_lock(&dpm_list_mtx); 644 mutex_lock(&dpm_list_mtx);
636 } 645 }
@@ -805,6 +814,9 @@ int dpm_suspend_noirq(pm_message_t state)
805 mutex_lock(&dpm_list_mtx); 814 mutex_lock(&dpm_list_mtx);
806 if (error) { 815 if (error) {
807 pm_dev_err(dev, state, " late", error); 816 pm_dev_err(dev, state, " late", error);
817 suspend_stats.failed_suspend_noirq++;
818 dpm_save_failed_step(SUSPEND_SUSPEND_NOIRQ);
819 dpm_save_failed_dev(dev_name(dev));
808 put_device(dev); 820 put_device(dev);
809 break; 821 break;
810 } 822 }
@@ -926,8 +938,10 @@ static void async_suspend(void *data, async_cookie_t cookie)
926 int error; 938 int error;
927 939
928 error = __device_suspend(dev, pm_transition, true); 940 error = __device_suspend(dev, pm_transition, true);
929 if (error) 941 if (error) {
942 dpm_save_failed_dev(dev_name(dev));
930 pm_dev_err(dev, pm_transition, " async", error); 943 pm_dev_err(dev, pm_transition, " async", error);
944 }
931 945
932 put_device(dev); 946 put_device(dev);
933} 947}
@@ -970,6 +984,7 @@ int dpm_suspend(pm_message_t state)
970 mutex_lock(&dpm_list_mtx); 984 mutex_lock(&dpm_list_mtx);
971 if (error) { 985 if (error) {
972 pm_dev_err(dev, state, "", error); 986 pm_dev_err(dev, state, "", error);
987 dpm_save_failed_dev(dev_name(dev));
973 put_device(dev); 988 put_device(dev);
974 break; 989 break;
975 } 990 }
@@ -983,7 +998,10 @@ int dpm_suspend(pm_message_t state)
983 async_synchronize_full(); 998 async_synchronize_full();
984 if (!error) 999 if (!error)
985 error = async_error; 1000 error = async_error;
986 if (!error) 1001 if (error) {
1002 suspend_stats.failed_suspend++;
1003 dpm_save_failed_step(SUSPEND_SUSPEND);
1004 } else
987 dpm_show_time(starttime, state, NULL); 1005 dpm_show_time(starttime, state, NULL);
988 return error; 1006 return error;
989} 1007}
@@ -1091,7 +1109,10 @@ int dpm_suspend_start(pm_message_t state)
1091 int error; 1109 int error;
1092 1110
1093 error = dpm_prepare(state); 1111 error = dpm_prepare(state);
1094 if (!error) 1112 if (error) {
1113 suspend_stats.failed_prepare++;
1114 dpm_save_failed_step(SUSPEND_PREPARE);
1115 } else
1095 error = dpm_suspend(state); 1116 error = dpm_suspend(state);
1096 return error; 1117 return error;
1097} 1118}