aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/power/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/power/main.c')
-rw-r--r--drivers/base/power/main.c42
1 files changed, 36 insertions, 6 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index a85459126bc..59f8ab23548 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
@@ -65,6 +66,7 @@ void device_pm_init(struct device *dev)
65 spin_lock_init(&dev->power.lock); 66 spin_lock_init(&dev->power.lock);
66 pm_runtime_init(dev); 67 pm_runtime_init(dev);
67 INIT_LIST_HEAD(&dev->power.entry); 68 INIT_LIST_HEAD(&dev->power.entry);
69 dev->power.power_state = PMSG_INVALID;
68} 70}
69 71
70/** 72/**
@@ -96,6 +98,7 @@ void device_pm_add(struct device *dev)
96 dev_warn(dev, "parent %s should not be sleeping\n", 98 dev_warn(dev, "parent %s should not be sleeping\n",
97 dev_name(dev->parent)); 99 dev_name(dev->parent));
98 list_add_tail(&dev->power.entry, &dpm_list); 100 list_add_tail(&dev->power.entry, &dpm_list);
101 dev_pm_qos_constraints_init(dev);
99 mutex_unlock(&dpm_list_mtx); 102 mutex_unlock(&dpm_list_mtx);
100} 103}
101 104
@@ -109,6 +112,7 @@ void device_pm_remove(struct device *dev)
109 dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); 112 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
110 complete_all(&dev->power.completion); 113 complete_all(&dev->power.completion);
111 mutex_lock(&dpm_list_mtx); 114 mutex_lock(&dpm_list_mtx);
115 dev_pm_qos_constraints_destroy(dev);
112 list_del_init(&dev->power.entry); 116 list_del_init(&dev->power.entry);
113 mutex_unlock(&dpm_list_mtx); 117 mutex_unlock(&dpm_list_mtx);
114 device_wakeup_disable(dev); 118 device_wakeup_disable(dev);
@@ -464,8 +468,12 @@ void dpm_resume_noirq(pm_message_t state)
464 mutex_unlock(&dpm_list_mtx); 468 mutex_unlock(&dpm_list_mtx);
465 469
466 error = device_resume_noirq(dev, state); 470 error = device_resume_noirq(dev, state);
467 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));
468 pm_dev_err(dev, state, " early", error); 475 pm_dev_err(dev, state, " early", error);
476 }
469 477
470 mutex_lock(&dpm_list_mtx); 478 mutex_lock(&dpm_list_mtx);
471 put_device(dev); 479 put_device(dev);
@@ -626,8 +634,12 @@ void dpm_resume(pm_message_t state)
626 mutex_unlock(&dpm_list_mtx); 634 mutex_unlock(&dpm_list_mtx);
627 635
628 error = device_resume(dev, state, false); 636 error = device_resume(dev, state, false);
629 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));
630 pm_dev_err(dev, state, "", error); 641 pm_dev_err(dev, state, "", error);
642 }
631 643
632 mutex_lock(&dpm_list_mtx); 644 mutex_lock(&dpm_list_mtx);
633 } 645 }
@@ -802,6 +814,9 @@ int dpm_suspend_noirq(pm_message_t state)
802 mutex_lock(&dpm_list_mtx); 814 mutex_lock(&dpm_list_mtx);
803 if (error) { 815 if (error) {
804 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));
805 put_device(dev); 820 put_device(dev);
806 break; 821 break;
807 } 822 }
@@ -902,7 +917,11 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
902 } 917 }
903 918
904 End: 919 End:
905 dev->power.is_suspended = !error; 920 if (!error) {
921 dev->power.is_suspended = true;
922 if (dev->power.wakeup_path && dev->parent)
923 dev->parent->power.wakeup_path = true;
924 }
906 925
907 device_unlock(dev); 926 device_unlock(dev);
908 complete_all(&dev->power.completion); 927 complete_all(&dev->power.completion);
@@ -923,8 +942,10 @@ static void async_suspend(void *data, async_cookie_t cookie)
923 int error; 942 int error;
924 943
925 error = __device_suspend(dev, pm_transition, true); 944 error = __device_suspend(dev, pm_transition, true);
926 if (error) 945 if (error) {
946 dpm_save_failed_dev(dev_name(dev));
927 pm_dev_err(dev, pm_transition, " async", error); 947 pm_dev_err(dev, pm_transition, " async", error);
948 }
928 949
929 put_device(dev); 950 put_device(dev);
930} 951}
@@ -967,6 +988,7 @@ int dpm_suspend(pm_message_t state)
967 mutex_lock(&dpm_list_mtx); 988 mutex_lock(&dpm_list_mtx);
968 if (error) { 989 if (error) {
969 pm_dev_err(dev, state, "", error); 990 pm_dev_err(dev, state, "", error);
991 dpm_save_failed_dev(dev_name(dev));
970 put_device(dev); 992 put_device(dev);
971 break; 993 break;
972 } 994 }
@@ -980,7 +1002,10 @@ int dpm_suspend(pm_message_t state)
980 async_synchronize_full(); 1002 async_synchronize_full();
981 if (!error) 1003 if (!error)
982 error = async_error; 1004 error = async_error;
983 if (!error) 1005 if (error) {
1006 suspend_stats.failed_suspend++;
1007 dpm_save_failed_step(SUSPEND_SUSPEND);
1008 } else
984 dpm_show_time(starttime, state, NULL); 1009 dpm_show_time(starttime, state, NULL);
985 return error; 1010 return error;
986} 1011}
@@ -999,6 +1024,8 @@ static int device_prepare(struct device *dev, pm_message_t state)
999 1024
1000 device_lock(dev); 1025 device_lock(dev);
1001 1026
1027 dev->power.wakeup_path = device_may_wakeup(dev);
1028
1002 if (dev->pm_domain) { 1029 if (dev->pm_domain) {
1003 pm_dev_dbg(dev, state, "preparing power domain "); 1030 pm_dev_dbg(dev, state, "preparing power domain ");
1004 if (dev->pm_domain->ops.prepare) 1031 if (dev->pm_domain->ops.prepare)
@@ -1088,7 +1115,10 @@ int dpm_suspend_start(pm_message_t state)
1088 int error; 1115 int error;
1089 1116
1090 error = dpm_prepare(state); 1117 error = dpm_prepare(state);
1091 if (!error) 1118 if (error) {
1119 suspend_stats.failed_prepare++;
1120 dpm_save_failed_step(SUSPEND_PREPARE);
1121 } else
1092 error = dpm_suspend(state); 1122 error = dpm_suspend(state);
1093 return error; 1123 return error;
1094} 1124}