aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorjinqian <jinqian@google.com>2015-03-25 16:18:44 -0700
committerjinqian <jinqian@google.com>2015-04-09 11:42:30 -0700
commite7d473583da732196bb9119f0ab32dfb59025c09 (patch)
treec4a5474d60671f8f70a1aaa5a9d33b891803826f /kernel
parent33ba72c7c74c98206ce3ec74b14f0354d8505ae8 (diff)
Power: 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
Diffstat (limited to 'kernel')
-rw-r--r--kernel/power/wakeup_reason.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/kernel/power/wakeup_reason.c b/kernel/power/wakeup_reason.c
index 085c99edca06..76b53400cb16 100644
--- a/kernel/power/wakeup_reason.c
+++ b/kernel/power/wakeup_reason.c
@@ -36,6 +36,11 @@ static char abort_reason[MAX_SUSPEND_ABORT_LEN];
static struct kobject *wakeup_reason;
static DEFINE_SPINLOCK(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,
char *buf)
{
@@ -59,10 +64,32 @@ static ssize_t last_resume_reason_show(struct kobject *kobj, struct kobj_attribu
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 suspend_time = __ATTR_RO(last_suspend_time);
static struct attribute *attrs[] = {
&resume_reason.attr,
+ &suspend_time.attr,
NULL,
};
static struct attribute_group attr_group = {
@@ -133,12 +160,21 @@ void log_suspend_abort_reason(const char *fmt, ...)
static int wakeup_reason_pm_event(struct notifier_block *notifier,
unsigned long pm_event, void *unused)
{
+ struct timespec xtom; /* wall_to_monotonic, ignored */
+
switch (pm_event) {
case PM_SUSPEND_PREPARE:
spin_lock(&resume_reason_lock);
irqcount = 0;
suspend_abort = false;
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;
default:
break;