diff --git a/kernel/power/wakeup_reason.c b/kernel/power/wakeup_reason.c index 8480e32b41cb..ddbcf15ec667 100644 --- a/kernel/power/wakeup_reason.c +++ b/kernel/power/wakeup_reason.c @@ -36,10 +36,10 @@ static char abort_reason[MAX_SUSPEND_ABORT_LEN]; static struct kobject *wakeup_reason; 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 ktime_t last_monotime; /* monotonic time before last suspend */ +static ktime_t curr_monotime; /* monotonic time after last suspend */ +static ktime_t last_stime; /* monotonic boottime offset before last suspend */ +static ktime_t curr_stime; /* monotonic boottime offset after last suspend */ static ssize_t last_resume_reason_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) @@ -71,14 +71,22 @@ static ssize_t last_suspend_time_show(struct kobject *kobj, 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); + /* + * total_time is calculated from monotonic bootoffsets because + * unlike CLOCK_MONOTONIC it include the time spent in suspend state. + */ + total_time = ktime_to_timespec(ktime_sub(curr_stime, last_stime)); /* - * suspend_resume_time is calculated from sleep_time. Userspace would - * always need both. Export them in pair here. + * suspend_resume_time is calculated as monotonic (CLOCK_MONOTONIC) + * time interval before entering suspend and post suspend. */ + suspend_resume_time = ktime_to_timespec(ktime_sub(curr_monotime, last_monotime)); + + /* sleep_time = total_time - suspend_resume_time */ + sleep_time = timespec_sub(total_time, suspend_resume_time); + + /* Export suspend_resume_time and sleep_time 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); @@ -145,21 +153,22 @@ 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); + /* monotonic time since boot */ + last_monotime = ktime_get(); + /* monotonic time since boot including the time spent in suspend */ + last_stime = ktime_get_boottime(); break; case PM_POST_SUSPEND: - get_xtime_and_monotonic_and_sleep_offset(&curr_xtime, &xtom, - &curr_stime); + /* monotonic time since boot */ + curr_monotime = ktime_get(); + /* monotonic time since boot including the time spent in suspend */ + curr_stime = ktime_get_boottime(); break; default: break;