ANDROID: power: wakeup_reason: Report suspend times from last_suspend_time

This node epxorts two values separated by space.
From left to right:
1. time spent in suspend/resume process
2. time spent sleep in suspend state

Change-Id: I2cb9a9408a5fd12166aaec11b935a0fd6a408c63
This commit is contained in:
jinqian 2015-03-25 16:18:44 -07:00 committed by Amit Pundir
parent ba32dd1412
commit acccb4cc66
2 changed files with 52 additions and 0 deletions

View file

@ -0,0 +1,16 @@
What: /sys/kernel/wakeup_reasons/last_resume_reason
Date: February 2014
Contact: Ruchi Kandoi <kandoiruchi@google.com>
Description:
The /sys/kernel/wakeup_reasons/last_resume_reason is
used to report wakeup reasons after system exited suspend.
What: /sys/kernel/wakeup_reasons/last_suspend_time
Date: March 2015
Contact: jinqian <jinqian@google.com>
Description:
The /sys/kernel/wakeup_reasons/last_suspend_time is
used to report time spent in last suspend cycle. It contains
two numbers (in seconds) separated by space. First number is
the time spent in suspend and resume processes. Second number
is the time spent in sleep state.

View file

@ -36,6 +36,11 @@ static char abort_reason[MAX_SUSPEND_ABORT_LEN];
static struct kobject *wakeup_reason; static struct kobject *wakeup_reason;
static spinlock_t resume_reason_lock; static spinlock_t resume_reason_lock;
static struct timespec last_xtime; /* wall time before last suspend */
static struct timespec curr_xtime; /* wall time after last suspend */
static struct timespec last_stime; /* total_sleep_time before last suspend */
static struct timespec curr_stime; /* total_sleep_time after last suspend */
static ssize_t last_resume_reason_show(struct kobject *kobj, struct kobj_attribute *attr, static ssize_t last_resume_reason_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf) char *buf)
{ {
@ -59,10 +64,32 @@ static ssize_t last_resume_reason_show(struct kobject *kobj, struct kobj_attribu
return buf_offset; return buf_offset;
} }
static ssize_t last_suspend_time_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
struct timespec sleep_time;
struct timespec total_time;
struct timespec suspend_resume_time;
sleep_time = timespec_sub(curr_stime, last_stime);
total_time = timespec_sub(curr_xtime, last_xtime);
suspend_resume_time = timespec_sub(total_time, sleep_time);
/*
* suspend_resume_time is calculated from sleep_time. Userspace would
* always need both. Export them in pair here.
*/
return sprintf(buf, "%lu.%09lu %lu.%09lu\n",
suspend_resume_time.tv_sec, suspend_resume_time.tv_nsec,
sleep_time.tv_sec, sleep_time.tv_nsec);
}
static struct kobj_attribute resume_reason = __ATTR_RO(last_resume_reason); static struct kobj_attribute resume_reason = __ATTR_RO(last_resume_reason);
static struct kobj_attribute suspend_time = __ATTR_RO(last_suspend_time);
static struct attribute *attrs[] = { static struct attribute *attrs[] = {
&resume_reason.attr, &resume_reason.attr,
&suspend_time.attr,
NULL, NULL,
}; };
static struct attribute_group attr_group = { static struct attribute_group attr_group = {
@ -118,12 +145,21 @@ void log_suspend_abort_reason(const char *fmt, ...)
static int wakeup_reason_pm_event(struct notifier_block *notifier, static int wakeup_reason_pm_event(struct notifier_block *notifier,
unsigned long pm_event, void *unused) unsigned long pm_event, void *unused)
{ {
struct timespec xtom; /* wall_to_monotonic, ignored */
switch (pm_event) { switch (pm_event) {
case PM_SUSPEND_PREPARE: case PM_SUSPEND_PREPARE:
spin_lock(&resume_reason_lock); spin_lock(&resume_reason_lock);
irqcount = 0; irqcount = 0;
suspend_abort = false; suspend_abort = false;
spin_unlock(&resume_reason_lock); spin_unlock(&resume_reason_lock);
get_xtime_and_monotonic_and_sleep_offset(&last_xtime, &xtom,
&last_stime);
break;
case PM_POST_SUSPEND:
get_xtime_and_monotonic_and_sleep_offset(&curr_xtime, &xtom,
&curr_stime);
break; break;
default: default:
break; break;