aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/power/main.c77
-rw-r--r--include/trace/events/power.h37
-rw-r--r--kernel/power/suspend.c4
3 files changed, 82 insertions, 36 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 5a9b6569dd74..9f098a82cf04 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -28,6 +28,7 @@
28#include <linux/sched.h> 28#include <linux/sched.h>
29#include <linux/async.h> 29#include <linux/async.h>
30#include <linux/suspend.h> 30#include <linux/suspend.h>
31#include <trace/events/power.h>
31#include <linux/cpuidle.h> 32#include <linux/cpuidle.h>
32#include "../base.h" 33#include "../base.h"
33#include "power.h" 34#include "power.h"
@@ -56,6 +57,30 @@ static pm_message_t pm_transition;
56 57
57static int async_error; 58static int async_error;
58 59
60static char *pm_verb(int event)
61{
62 switch (event) {
63 case PM_EVENT_SUSPEND:
64 return "suspend";
65 case PM_EVENT_RESUME:
66 return "resume";
67 case PM_EVENT_FREEZE:
68 return "freeze";
69 case PM_EVENT_QUIESCE:
70 return "quiesce";
71 case PM_EVENT_HIBERNATE:
72 return "hibernate";
73 case PM_EVENT_THAW:
74 return "thaw";
75 case PM_EVENT_RESTORE:
76 return "restore";
77 case PM_EVENT_RECOVER:
78 return "recover";
79 default:
80 return "(unknown PM event)";
81 }
82}
83
59/** 84/**
60 * device_pm_sleep_init - Initialize system suspend-related device fields. 85 * device_pm_sleep_init - Initialize system suspend-related device fields.
61 * @dev: Device object being initialized. 86 * @dev: Device object being initialized.
@@ -172,16 +197,21 @@ static ktime_t initcall_debug_start(struct device *dev)
172} 197}
173 198
174static void initcall_debug_report(struct device *dev, ktime_t calltime, 199static void initcall_debug_report(struct device *dev, ktime_t calltime,
175 int error) 200 int error, pm_message_t state, char *info)
176{ 201{
177 ktime_t delta, rettime; 202 ktime_t rettime;
203 s64 nsecs;
204
205 rettime = ktime_get();
206 nsecs = (s64) ktime_to_ns(ktime_sub(rettime, calltime));
178 207
179 if (pm_print_times_enabled) { 208 if (pm_print_times_enabled) {
180 rettime = ktime_get();
181 delta = ktime_sub(rettime, calltime);
182 pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev), 209 pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev),
183 error, (unsigned long long)ktime_to_ns(delta) >> 10); 210 error, (unsigned long long)nsecs >> 10);
184 } 211 }
212
213 trace_device_pm_report_time(dev, info, nsecs, pm_verb(state.event),
214 error);
185} 215}
186 216
187/** 217/**
@@ -309,30 +339,6 @@ static pm_callback_t pm_noirq_op(const struct dev_pm_ops *ops, pm_message_t stat
309 return NULL; 339 return NULL;
310} 340}
311 341
312static char *pm_verb(int event)
313{
314 switch (event) {
315 case PM_EVENT_SUSPEND:
316 return "suspend";
317 case PM_EVENT_RESUME:
318 return "resume";
319 case PM_EVENT_FREEZE:
320 return "freeze";
321 case PM_EVENT_QUIESCE:
322 return "quiesce";
323 case PM_EVENT_HIBERNATE:
324 return "hibernate";
325 case PM_EVENT_THAW:
326 return "thaw";
327 case PM_EVENT_RESTORE:
328 return "restore";
329 case PM_EVENT_RECOVER:
330 return "recover";
331 default:
332 return "(unknown PM event)";
333 }
334}
335
336static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info) 342static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info)
337{ 343{
338 dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event), 344 dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event),
@@ -379,7 +385,7 @@ static int dpm_run_callback(pm_callback_t cb, struct device *dev,
379 error = cb(dev); 385 error = cb(dev);
380 suspend_report_result(cb, error); 386 suspend_report_result(cb, error);
381 387
382 initcall_debug_report(dev, calltime, error); 388 initcall_debug_report(dev, calltime, error, state, info);
383 389
384 return error; 390 return error;
385} 391}
@@ -1027,7 +1033,8 @@ EXPORT_SYMBOL_GPL(dpm_suspend_end);
1027 * @cb: Suspend callback to execute. 1033 * @cb: Suspend callback to execute.
1028 */ 1034 */
1029static int legacy_suspend(struct device *dev, pm_message_t state, 1035static int legacy_suspend(struct device *dev, pm_message_t state,
1030 int (*cb)(struct device *dev, pm_message_t state)) 1036 int (*cb)(struct device *dev, pm_message_t state),
1037 char *info)
1031{ 1038{
1032 int error; 1039 int error;
1033 ktime_t calltime; 1040 ktime_t calltime;
@@ -1037,7 +1044,7 @@ static int legacy_suspend(struct device *dev, pm_message_t state,
1037 error = cb(dev, state); 1044 error = cb(dev, state);
1038 suspend_report_result(cb, error); 1045 suspend_report_result(cb, error);
1039 1046
1040 initcall_debug_report(dev, calltime, error); 1047 initcall_debug_report(dev, calltime, error, state, info);
1041 1048
1042 return error; 1049 return error;
1043} 1050}
@@ -1097,7 +1104,8 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
1097 goto Run; 1104 goto Run;
1098 } else if (dev->class->suspend) { 1105 } else if (dev->class->suspend) {
1099 pm_dev_dbg(dev, state, "legacy class "); 1106 pm_dev_dbg(dev, state, "legacy class ");
1100 error = legacy_suspend(dev, state, dev->class->suspend); 1107 error = legacy_suspend(dev, state, dev->class->suspend,
1108 "legacy class ");
1101 goto End; 1109 goto End;
1102 } 1110 }
1103 } 1111 }
@@ -1108,7 +1116,8 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
1108 callback = pm_op(dev->bus->pm, state); 1116 callback = pm_op(dev->bus->pm, state);
1109 } else if (dev->bus->suspend) { 1117 } else if (dev->bus->suspend) {
1110 pm_dev_dbg(dev, state, "legacy bus "); 1118 pm_dev_dbg(dev, state, "legacy bus ");
1111 error = legacy_suspend(dev, state, dev->bus->suspend); 1119 error = legacy_suspend(dev, state, dev->bus->suspend,
1120 "legacy bus ");
1112 goto End; 1121 goto End;
1113 } 1122 }
1114 } 1123 }
diff --git a/include/trace/events/power.h b/include/trace/events/power.h
index 8e42410bd159..cda100d6762d 100644
--- a/include/trace/events/power.h
+++ b/include/trace/events/power.h
@@ -66,6 +66,43 @@ TRACE_EVENT(machine_suspend,
66 TP_printk("state=%lu", (unsigned long)__entry->state) 66 TP_printk("state=%lu", (unsigned long)__entry->state)
67); 67);
68 68
69TRACE_EVENT(device_pm_report_time,
70
71 TP_PROTO(struct device *dev, const char *pm_ops, s64 ops_time,
72 char *pm_event_str, int error),
73
74 TP_ARGS(dev, pm_ops, ops_time, pm_event_str, error),
75
76 TP_STRUCT__entry(
77 __string(device, dev_name(dev))
78 __string(driver, dev_driver_string(dev))
79 __string(parent, dev->parent ? dev_name(dev->parent) : "none")
80 __string(pm_ops, pm_ops ? pm_ops : "none ")
81 __string(pm_event_str, pm_event_str)
82 __field(s64, ops_time)
83 __field(int, error)
84 ),
85
86 TP_fast_assign(
87 const char *tmp = dev->parent ? dev_name(dev->parent) : "none";
88 const char *tmp_i = pm_ops ? pm_ops : "none ";
89
90 __assign_str(device, dev_name(dev));
91 __assign_str(driver, dev_driver_string(dev));
92 __assign_str(parent, tmp);
93 __assign_str(pm_ops, tmp_i);
94 __assign_str(pm_event_str, pm_event_str);
95 __entry->ops_time = ops_time;
96 __entry->error = error;
97 ),
98
99 /* ops_str has an extra space at the end */
100 TP_printk("%s %s parent=%s state=%s ops=%snsecs=%lld err=%d",
101 __get_str(driver), __get_str(device), __get_str(parent),
102 __get_str(pm_event_str), __get_str(pm_ops),
103 __entry->ops_time, __entry->error)
104);
105
69DECLARE_EVENT_CLASS(wakeup_source, 106DECLARE_EVENT_CLASS(wakeup_source,
70 107
71 TP_PROTO(const char *name, unsigned int state), 108 TP_PROTO(const char *name, unsigned int state),
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index ece04223bb1e..62ee437b5c7e 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -210,6 +210,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
210 goto Platform_wake; 210 goto Platform_wake;
211 } 211 }
212 212
213 ftrace_stop();
213 error = disable_nonboot_cpus(); 214 error = disable_nonboot_cpus();
214 if (error || suspend_test(TEST_CPUS)) 215 if (error || suspend_test(TEST_CPUS))
215 goto Enable_cpus; 216 goto Enable_cpus;
@@ -232,6 +233,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
232 233
233 Enable_cpus: 234 Enable_cpus:
234 enable_nonboot_cpus(); 235 enable_nonboot_cpus();
236 ftrace_start();
235 237
236 Platform_wake: 238 Platform_wake:
237 if (need_suspend_ops(state) && suspend_ops->wake) 239 if (need_suspend_ops(state) && suspend_ops->wake)
@@ -265,7 +267,6 @@ int suspend_devices_and_enter(suspend_state_t state)
265 goto Close; 267 goto Close;
266 } 268 }
267 suspend_console(); 269 suspend_console();
268 ftrace_stop();
269 suspend_test_start(); 270 suspend_test_start();
270 error = dpm_suspend_start(PMSG_SUSPEND); 271 error = dpm_suspend_start(PMSG_SUSPEND);
271 if (error) { 272 if (error) {
@@ -285,7 +286,6 @@ int suspend_devices_and_enter(suspend_state_t state)
285 suspend_test_start(); 286 suspend_test_start();
286 dpm_resume_end(PMSG_RESUME); 287 dpm_resume_end(PMSG_RESUME);
287 suspend_test_finish("resume devices"); 288 suspend_test_finish("resume devices");
288 ftrace_start();
289 resume_console(); 289 resume_console();
290 Close: 290 Close:
291 if (need_suspend_ops(state) && suspend_ops->end) 291 if (need_suspend_ops(state) && suspend_ops->end)