summaryrefslogtreecommitdiff
path: root/drivers/base
diff options
context:
space:
mode:
authorZhang Jiejing <jiejing.zhang@freescale.com>2010-11-22 17:14:32 +0800
committerJason Liu <r64343@freescale.com>2012-07-20 13:10:17 +0800
commit43681cabc16498709e63809380c736e801f08677 (patch)
tree45c8275377e8d5cec7e0d49b53d2bbb0068a232e /drivers/base
parent61fa59f5c82e1b4ccd4e53b712d4c17a35e813f5 (diff)
ENGR00133978 PM: add time sensitive debug function to suspend & resume
There was some driver is slow on suspend/resume, but some embeded system like eReader,Cellphone are time sensitive,this commit will report the slow driver on suspend/resume, the default value is 500us(0.5ms) Also, the threshold can be change by modify '/sys/power/device_suspend_time_threshold' to change the threshold, it is in microsecond. The output is like: PM: device platform:soc-audio.2 suspend too slow, takes 606.696 msecs PM: device platform:mxc_sdc_fb.1 suspend too slow, takes 7.708 msecs the default state of suspend driver is default off, if you want to debug the suspend time, echo time in microsecond(u Second) to /sys/powe/device_suspend_time_threshold eg: I want to know which driver suspend & resume takes more that 0.5 ms (500 us), you can just : ehco 500 > /sys/power/device_suspend_time_threshold Signed-off-by: Zhang Jiejing <jiejing.zhang@freescale.com>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/main.c39
-rw-r--r--drivers/base/power/power.h4
2 files changed, 42 insertions, 1 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 06f09bf89cb2..f1e1a5b8fb04 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -179,6 +179,39 @@ static void initcall_debug_report(struct device *dev, ktime_t calltime,
error, (unsigned long long)ktime_to_ns(delta) >> 10);
}
}
+#ifdef CONFIG_SUSPEND_DEVICE_TIME_DEBUG
+static void suspend_time_debug_start(ktime_t *start)
+{
+ *start = ktime_get();
+}
+
+static void suspend_time_debug_report(const char *name, struct device *dev,
+ ktime_t starttime)
+{
+ ktime_t rettime;
+ s64 usecs64;
+ int usecs;
+
+ if (!dev->driver)
+ return;
+
+ rettime = ktime_get();
+ usecs64 = ktime_to_us(ktime_sub(rettime, starttime));
+ usecs = usecs64;
+ if (usecs == 0)
+ usecs = 1;
+
+ if (device_suspend_time_threshold
+ && usecs > device_suspend_time_threshold)
+ pr_info("PM: device %s:%s %s too slow, it takes \t %ld.%03ld msecs\n",
+ dev->bus->name, dev_name(dev), name,
+ usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC);
+}
+#else
+static void suspend_time_debug_start(ktime_t *start) {}
+static void suspend_time_debug_report(const char *name, struct device *dev,
+ ktime_t starttime) {}
+#endif /* CONFIG_SUSPEND_DEVICE_TIME_DEBUG */
/**
* dpm_wait - Wait for a PM operation to complete.
@@ -216,7 +249,7 @@ static int pm_op(struct device *dev,
pm_message_t state)
{
int error = 0;
- ktime_t calltime;
+ ktime_t calltime, starttime;
calltime = initcall_debug_start(dev);
@@ -224,13 +257,17 @@ static int pm_op(struct device *dev,
#ifdef CONFIG_SUSPEND
case PM_EVENT_SUSPEND:
if (ops->suspend) {
+ suspend_time_debug_start(&starttime);
error = ops->suspend(dev);
+ suspend_time_debug_report("suspend", dev, starttime);
suspend_report_result(ops->suspend, error);
}
break;
case PM_EVENT_RESUME:
if (ops->resume) {
+ suspend_time_debug_start(&starttime);
error = ops->resume(dev);
+ suspend_time_debug_report("resume", dev, starttime);
suspend_report_result(ops->resume, error);
}
break;
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index f2a25f18fde7..51b585a4e9d9 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -10,6 +10,10 @@ static inline void pm_runtime_remove(struct device *dev) {}
#endif /* !CONFIG_PM_RUNTIME */
+#ifdef CONFIG_SUSPEND_DEVICE_TIME_DEBUG
+extern int device_suspend_time_threshold;
+#endif
+
#ifdef CONFIG_PM_SLEEP
/* kernel/power/main.c */