LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
From: John Stultz <john.stultz@linaro.org>
To: lkml <linux-kernel@vger.kernel.org>
Cc: Xunlei Pang <pang.xunlei@linaro.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@kernel.org>,
	John Stultz <john.stultz@linaro.org>
Subject: [PATCH 17/21] time: Fix a bug in timekeeping_suspend() with no persistent clock
Date: Wed,  1 Apr 2015 20:34:37 -0700	[thread overview]
Message-ID: <1427945681-29972-18-git-send-email-john.stultz@linaro.org> (raw)
In-Reply-To: <1427945681-29972-1-git-send-email-john.stultz@linaro.org>

From: Xunlei Pang <pang.xunlei@linaro.org>

When there's no persistent clock, normally timekeeping_suspend_time
should always be zero, but this can break in timekeeping_suspend().

At T1, there was a system suspend, so old_delta was assigned T1.
After some time, one time adjustment happened, and xtime got the
value of T1-dt(0s<dt<2s). Then, there comes another system suspend
soon after this adjustment, obviously we will get a small negative
delta_delta, resulting in a negative timekeeping_suspend_time.

This is problematic, when doing timekeeping_resume() if there is
no nonstop clocksource for example, it will hit the else leg and
inject the improper sleeptime which is the wrong logic.

So, we can solve this problem by only doing delta related code when
the persistent clock is existent. Actually the code only makes sense
for persistent clock cases.

Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Xunlei Pang <pang.xunlei@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
 kernel/time/timekeeping.c | 36 +++++++++++++++++++-----------------
 1 file changed, 19 insertions(+), 17 deletions(-)

diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 7d799d3..6dafcea 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1255,7 +1255,7 @@ void __init timekeeping_init(void)
 	raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
 }
 
-/* time in seconds when suspend began */
+/* time in seconds when suspend began for persistent clock */
 static struct timespec64 timekeeping_suspend_time;
 
 /**
@@ -1430,24 +1430,26 @@ int timekeeping_suspend(void)
 	timekeeping_forward_now(tk);
 	timekeeping_suspended = 1;
 
-	/*
-	 * To avoid drift caused by repeated suspend/resumes,
-	 * which each can add ~1 second drift error,
-	 * try to compensate so the difference in system time
-	 * and persistent_clock time stays close to constant.
-	 */
-	delta = timespec64_sub(tk_xtime(tk), timekeeping_suspend_time);
-	delta_delta = timespec64_sub(delta, old_delta);
-	if (abs(delta_delta.tv_sec)  >= 2) {
+	if (has_persistent_clock()) {
 		/*
-		 * if delta_delta is too large, assume time correction
-		 * has occured and set old_delta to the current delta.
+		 * To avoid drift caused by repeated suspend/resumes,
+		 * which each can add ~1 second drift error,
+		 * try to compensate so the difference in system time
+		 * and persistent_clock time stays close to constant.
 		 */
-		old_delta = delta;
-	} else {
-		/* Otherwise try to adjust old_system to compensate */
-		timekeeping_suspend_time =
-			timespec64_add(timekeeping_suspend_time, delta_delta);
+		delta = timespec64_sub(tk_xtime(tk), timekeeping_suspend_time);
+		delta_delta = timespec64_sub(delta, old_delta);
+		if (abs(delta_delta.tv_sec) >= 2) {
+			/*
+			 * if delta_delta is too large, assume time correction
+			 * has occurred and set old_delta to the current delta.
+			 */
+			old_delta = delta;
+		} else {
+			/* Otherwise try to adjust old_system to compensate */
+			timekeeping_suspend_time =
+				timespec64_add(timekeeping_suspend_time, delta_delta);
+		}
 	}
 
 	timekeeping_update(tk, TK_MIRROR);
-- 
1.9.1


  parent reply	other threads:[~2015-04-02  3:37 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-02  3:34 [PATCH 00/21] 4.1 time and rtc changes for tip/timers/core John Stultz
2015-04-02  3:34 ` [PATCH 01/21] time: Add y2038 safe read_boot_clock64() John Stultz
2015-04-03  8:15   ` [tip:timers/core] " tip-bot for Xunlei Pang
2015-04-02  3:34 ` [PATCH 02/21] time: Add y2038 safe read_persistent_clock64() John Stultz
2015-04-03  8:15   ` [tip:timers/core] " tip-bot for Xunlei Pang
2015-04-02  3:34 ` [PATCH 03/21] time: Add y2038 safe update_persistent_clock64() John Stultz
2015-04-03  8:16   ` [tip:timers/core] time: Add y2038 safe update_persistent_clock64( ) tip-bot for Xunlei Pang
2015-04-02  3:34 ` [PATCH 04/21] ARM: OMAP: 32k counter: Provide y2038-safe omap_read_persistent_clock() replacement John Stultz
2015-04-03  8:16   ` [tip:timers/core] " tip-bot for Xunlei Pang
2015-04-02  3:34 ` [PATCH 05/21] ARM: tegra: clock: Provide y2038-safe tegra_read_persistent_clock() replacement John Stultz
2015-04-03  8:16   ` [tip:timers/core] clocksource/drivers/tegra: " tip-bot for Xunlei Pang
2015-04-02  3:34 ` [PATCH 06/21] ARM: time: Provide read_boot_clock64() and read_persistent_clock64() John Stultz
2015-04-03  8:17   ` [tip:timers/core] ARM, clocksource/drivers: Provide read_boot_clock64() and read_persistent_clock64() and use them tip-bot for Xunlei Pang
2015-04-02  3:34 ` [PATCH 07/21] rtc: Provide y2038 safe rtc_class_ops.set_mmss() replacement John Stultz
2015-04-03  8:17   ` [tip:timers/core] drivers/rtc: " tip-bot for Xunlei Pang
2015-04-02  3:34 ` [PATCH 08/21] rtc/test: Update driver to address y2038/y2106 issues John Stultz
2015-04-03  8:17   ` [tip:timers/core] drivers/rtc/test: " tip-bot for Xunlei Pang
2015-04-02  3:34 ` [PATCH 09/21] rtc/ab3100: " John Stultz
2015-04-03  8:17   ` [tip:timers/core] drivers/rtc/ab3100: " tip-bot for Xunlei Pang
2015-04-02  3:34 ` [PATCH 10/21] rtc/mc13xxx: " John Stultz
2015-04-03  8:18   ` [tip:timers/core] drivers/rtc/mc13xxx: " tip-bot for Xunlei Pang
2015-04-02  3:34 ` [PATCH 11/21] rtc/mxc: Modify rtc_update_alarm() not to touch the alarm time John Stultz
2015-04-03  8:18   ` [tip:timers/core] drivers/rtc/mxc: " tip-bot for Xunlei Pang
2015-04-02  3:34 ` [PATCH 12/21] rtc/mxc: Convert get_alarm_or_time()/set_alarm_or_time() to use time64_t John Stultz
2015-04-03  8:18   ` [tip:timers/core] drivers/rtc/mxc: Convert get_alarm_or_time()/ set_alarm_or_time() " tip-bot for Xunlei Pang
2015-04-02  3:34 ` [PATCH 13/21] rtc/mxc: Update driver to address y2038/y2106 issues John Stultz
2015-04-03  8:19   ` [tip:timers/core] drivers/rtc/mxc: Update driver to address y2038 /y2106 issues tip-bot for Xunlei Pang
2015-04-02  3:34 ` [PATCH 14/21] alpha: rtc: Change to use rtc_class_ops's set_mmss64() John Stultz
2015-04-03  8:19   ` [tip:timers/core] alpha, rtc: Change to use rtc_class_ops' s set_mmss64() tip-bot for Xunlei Pang
2015-04-02  3:34 ` [PATCH 15/21] time: Don't build timekeeping_inject_sleeptime64() if no one uses it John Stultz
2015-04-03  8:19   ` [tip:timers/core] time: Don' t " tip-bot for Xunlei Pang
2015-04-02  3:34 ` [PATCH 16/21] rtc: Remove redundant rtc_valid_tm() from rtc_resume() John Stultz
2015-04-03  8:19   ` [tip:timers/core] drivers/rtc: " tip-bot for Xunlei Pang
2015-04-02  3:34 ` John Stultz [this message]
2015-04-03  6:16   ` [PATCH 17/21] time: Fix a bug in timekeeping_suspend() with no persistent clock Ingo Molnar
2015-04-03  8:20   ` [tip:timers/core] " tip-bot for Xunlei Pang
2015-04-02  3:34 ` [PATCH 18/21] time: rtc: Don't bother into rtc_resume() for the nonstop clocksource John Stultz
2015-04-03  8:20   ` [tip:timers/core] time, drivers/rtc: Don't bother with rtc_resume () " tip-bot for Xunlei Pang
2015-04-02  3:34 ` [PATCH 19/21] clocksource: Improve comment explaining clocks_calc_max_nsecs()'s 50% safety margin John Stultz
2015-04-02  8:50   ` Peter Zijlstra
2015-04-02 17:30     ` John Stultz
2015-04-02 18:34       ` Peter Zijlstra
2015-04-02 18:41         ` John Stultz
2015-04-02 18:43           ` Peter Zijlstra
2015-04-02 18:50             ` John Stultz
2015-04-02 19:04               ` Peter Zijlstra
2015-04-03  8:20   ` [tip:timers/core] " tip-bot for John Stultz
2015-04-02  3:34 ` [PATCH 20/21] timekeeping: Change timekeeping_check_update() to take a tk_read_base John Stultz
2015-04-02  3:34 ` [PATCH 21/21] time: Rework debugging variables so they aren't global John Stultz
2015-04-02  7:47   ` Peter Zijlstra
2015-04-02  7:51     ` Ingo Molnar
2015-04-02  8:36       ` Peter Zijlstra
2015-04-02  8:41         ` Peter Zijlstra
2015-04-02 17:32       ` John Stultz
2015-04-03  6:21         ` Ingo Molnar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1427945681-29972-18-git-send-email-john.stultz@linaro.org \
    --to=john.stultz@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=pang.xunlei@linaro.org \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --subject='Re: [PATCH 17/21] time: Fix a bug in timekeeping_suspend() with no persistent clock' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).