diff options
author | Zhang Jiejing <jiejing.zhang@freescale.com> | 2010-11-22 17:14:32 +0800 |
---|---|---|
committer | Justin Waters <justin.waters@timesys.com> | 2012-07-03 16:51:47 -0400 |
commit | 127eed297d9486173141f99b689b4b4a4f15f3a9 (patch) | |
tree | 12af690561edba3a04ed0ad91b2052bce8a4e495 /drivers/base | |
parent | 3427dcbd22c543f26cbfb6d866f21be7288d71b9 (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.c | 39 | ||||
-rw-r--r-- | drivers/base/power/power.h | 4 |
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 */ |