aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2009-12-17 19:57:31 -0500
committerRafael J. Wysocki <rjw@sisk.pl>2009-12-17 19:57:31 -0500
commit875ab0b74e85d6801a49392447d26e0b28688d86 (patch)
tree03762971d57d0657a12a99f1a73473878c2c7ada
parentb8a7f3cd7e8212e5c572178ff3b5a514861036a5 (diff)
PM: Make the initcall_debug style timing for suspend/resume complete
Commit f2511774863487e61b56a97da07ebf8dd61d7836 (PM: Add initcall_debug style timing for suspend/resume) introduced basic timing instrumentation, needed for a scritps/bootgraph.pl equivalent or humans, but it missed the fact that bus types and device classes which haven't been switched to using struct dev_pm_ops objects yet need special handling. As a result, the suspend/resume timing information is only available for devices whose bus types or device classes use struct dev_pm_ops objects, so the majority of devices is not covered. Fix this by adding basic suspend/resume timing instrumentation for devices whose bus types and device classes still don't use struct dev_pm_ops objects for power management. To reduce code duplication move the timing code to helper functions. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-rw-r--r--drivers/base/power/main.c97
1 files changed, 77 insertions, 20 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 1a216c114a0f..c448d5972a0b 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -161,6 +161,32 @@ void device_pm_move_last(struct device *dev)
161 list_move_tail(&dev->power.entry, &dpm_list); 161 list_move_tail(&dev->power.entry, &dpm_list);
162} 162}
163 163
164static ktime_t initcall_debug_start(struct device *dev)
165{
166 ktime_t calltime = ktime_set(0, 0);
167
168 if (initcall_debug) {
169 pr_info("calling %s+ @ %i\n",
170 dev_name(dev), task_pid_nr(current));
171 calltime = ktime_get();
172 }
173
174 return calltime;
175}
176
177static void initcall_debug_report(struct device *dev, ktime_t calltime,
178 int error)
179{
180 ktime_t delta, rettime;
181
182 if (initcall_debug) {
183 rettime = ktime_get();
184 delta = ktime_sub(rettime, calltime);
185 pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev),
186 error, (unsigned long long)ktime_to_ns(delta) >> 10);
187 }
188}
189
164/** 190/**
165 * pm_op - Execute the PM operation appropriate for given PM event. 191 * pm_op - Execute the PM operation appropriate for given PM event.
166 * @dev: Device to handle. 192 * @dev: Device to handle.
@@ -172,13 +198,9 @@ static int pm_op(struct device *dev,
172 pm_message_t state) 198 pm_message_t state)
173{ 199{
174 int error = 0; 200 int error = 0;
175 ktime_t calltime, delta, rettime; 201 ktime_t calltime;
176 202
177 if (initcall_debug) { 203 calltime = initcall_debug_start(dev);
178 pr_info("calling %s+ @ %i\n",
179 dev_name(dev), task_pid_nr(current));
180 calltime = ktime_get();
181 }
182 204
183 switch (state.event) { 205 switch (state.event) {
184#ifdef CONFIG_SUSPEND 206#ifdef CONFIG_SUSPEND
@@ -227,12 +249,7 @@ static int pm_op(struct device *dev,
227 error = -EINVAL; 249 error = -EINVAL;
228 } 250 }
229 251
230 if (initcall_debug) { 252 initcall_debug_report(dev, calltime, error);
231 rettime = ktime_get();
232 delta = ktime_sub(rettime, calltime);
233 pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev),
234 error, (unsigned long long)ktime_to_ns(delta) >> 10);
235 }
236 253
237 return error; 254 return error;
238} 255}
@@ -309,8 +326,9 @@ static int pm_noirq_op(struct device *dev,
309 if (initcall_debug) { 326 if (initcall_debug) {
310 rettime = ktime_get(); 327 rettime = ktime_get();
311 delta = ktime_sub(rettime, calltime); 328 delta = ktime_sub(rettime, calltime);
312 printk("initcall %s_i+ returned %d after %Ld usecs\n", dev_name(dev), 329 printk("initcall %s_i+ returned %d after %Ld usecs\n",
313 error, (unsigned long long)ktime_to_ns(delta) >> 10); 330 dev_name(dev), error,
331 (unsigned long long)ktime_to_ns(delta) >> 10);
314 } 332 }
315 333
316 return error; 334 return error;
@@ -408,6 +426,26 @@ void dpm_resume_noirq(pm_message_t state)
408EXPORT_SYMBOL_GPL(dpm_resume_noirq); 426EXPORT_SYMBOL_GPL(dpm_resume_noirq);
409 427
410/** 428/**
429 * legacy_resume - Execute a legacy (bus or class) resume callback for device.
430 * dev: Device to resume.
431 * cb: Resume callback to execute.
432 */
433static int legacy_resume(struct device *dev, int (*cb)(struct device *dev))
434{
435 int error;
436 ktime_t calltime;
437
438 calltime = initcall_debug_start(dev);
439
440 error = cb(dev);
441 suspend_report_result(cb, error);
442
443 initcall_debug_report(dev, calltime, error);
444
445 return error;
446}
447
448/**
411 * device_resume - Execute "resume" callbacks for given device. 449 * device_resume - Execute "resume" callbacks for given device.
412 * @dev: Device to handle. 450 * @dev: Device to handle.
413 * @state: PM transition of the system being carried out. 451 * @state: PM transition of the system being carried out.
@@ -427,7 +465,7 @@ static int device_resume(struct device *dev, pm_message_t state)
427 error = pm_op(dev, dev->bus->pm, state); 465 error = pm_op(dev, dev->bus->pm, state);
428 } else if (dev->bus->resume) { 466 } else if (dev->bus->resume) {
429 pm_dev_dbg(dev, state, "legacy "); 467 pm_dev_dbg(dev, state, "legacy ");
430 error = dev->bus->resume(dev); 468 error = legacy_resume(dev, dev->bus->resume);
431 } 469 }
432 if (error) 470 if (error)
433 goto End; 471 goto End;
@@ -448,7 +486,7 @@ static int device_resume(struct device *dev, pm_message_t state)
448 error = pm_op(dev, dev->class->pm, state); 486 error = pm_op(dev, dev->class->pm, state);
449 } else if (dev->class->resume) { 487 } else if (dev->class->resume) {
450 pm_dev_dbg(dev, state, "legacy class "); 488 pm_dev_dbg(dev, state, "legacy class ");
451 error = dev->class->resume(dev); 489 error = legacy_resume(dev, dev->class->resume);
452 } 490 }
453 } 491 }
454 End: 492 End:
@@ -648,6 +686,27 @@ int dpm_suspend_noirq(pm_message_t state)
648EXPORT_SYMBOL_GPL(dpm_suspend_noirq); 686EXPORT_SYMBOL_GPL(dpm_suspend_noirq);
649 687
650/** 688/**
689 * legacy_suspend - Execute a legacy (bus or class) suspend callback for device.
690 * dev: Device to suspend.
691 * cb: Suspend callback to execute.
692 */
693static int legacy_suspend(struct device *dev, pm_message_t state,
694 int (*cb)(struct device *dev, pm_message_t state))
695{
696 int error;
697 ktime_t calltime;
698
699 calltime = initcall_debug_start(dev);
700
701 error = cb(dev, state);
702 suspend_report_result(cb, error);
703
704 initcall_debug_report(dev, calltime, error);
705
706 return error;
707}
708
709/**
651 * device_suspend - Execute "suspend" callbacks for given device. 710 * device_suspend - Execute "suspend" callbacks for given device.
652 * @dev: Device to handle. 711 * @dev: Device to handle.
653 * @state: PM transition of the system being carried out. 712 * @state: PM transition of the system being carried out.
@@ -664,8 +723,7 @@ static int device_suspend(struct device *dev, pm_message_t state)
664 error = pm_op(dev, dev->class->pm, state); 723 error = pm_op(dev, dev->class->pm, state);
665 } else if (dev->class->suspend) { 724 } else if (dev->class->suspend) {
666 pm_dev_dbg(dev, state, "legacy class "); 725 pm_dev_dbg(dev, state, "legacy class ");
667 error = dev->class->suspend(dev, state); 726 error = legacy_suspend(dev, state, dev->class->suspend);
668 suspend_report_result(dev->class->suspend, error);
669 } 727 }
670 if (error) 728 if (error)
671 goto End; 729 goto End;
@@ -686,8 +744,7 @@ static int device_suspend(struct device *dev, pm_message_t state)
686 error = pm_op(dev, dev->bus->pm, state); 744 error = pm_op(dev, dev->bus->pm, state);
687 } else if (dev->bus->suspend) { 745 } else if (dev->bus->suspend) {
688 pm_dev_dbg(dev, state, "legacy "); 746 pm_dev_dbg(dev, state, "legacy ");
689 error = dev->bus->suspend(dev, state); 747 error = legacy_suspend(dev, state, dev->bus->suspend);
690 suspend_report_result(dev->bus->suspend, error);
691 } 748 }
692 } 749 }
693 End: 750 End: