Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756052Ab3EQSYk (ORCPT ); Fri, 17 May 2013 14:24:40 -0400 Received: from mail-pa0-f49.google.com ([209.85.220.49]:45073 "EHLO mail-pa0-f49.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755889Ab3EQSYh (ORCPT ); Fri, 17 May 2013 14:24:37 -0400 From: Zoran Markovic To: linux-kernel@vger.kernel.org Cc: zoran.markovic@linaro.org, John Stultz , Thomas Gleixner , Feng Tang , stable@vger.kernel.org Subject: [RFC PATCH] timekeeping: Correct run-time detection of real-time clock. Date: Fri, 17 May 2013 11:24:05 -0700 Message-Id: <1368815045-21209-1-git-send-email-zoran.markovic@linaro.org> X-Mailer: git-send-email 1.7.9.5 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2342 Lines: 56 Since commit <31ade30692dc9680bfc95700d794818fa3f754ac>, timekeeping_init() checks for presence of persistent clock by attempting to read a non-zero time value from real-time clock. This is an issue on platforms where persistent_clock (instead of a RTC) is implemented as a free-running counter starting from zero on each boot and running during suspend. Examples are some ARM platforms (e.g. PandaBoard). An attempt to read such a clock during timekeeping_init() may return zero value and falsely declare persistent clock as missing. Additionally, in the above case suspend times may be accounted twice (once from timekeeping_resume() and once from rtc_resume()), resulting in a gradual drift of system time. This patch does a run-time correction of the issue by doing the same check during timekeeping_suspend(). A better long-term solution would have to return error when trying to read non-existing clock and zero when trying to read an uninitialized clock, but that would require changing all persistent_clock implementations. This patch addresses the immediate breakage, for now. Cc: John Stultz Cc: Thomas Gleixner Cc: Feng Tang Cc: stable@vger.kernel.org Signed-off-by: Zoran Markovic --- kernel/time/timekeeping.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 98cd470..baeeb5c 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -975,6 +975,14 @@ static int timekeeping_suspend(void) read_persistent_clock(&timekeeping_suspend_time); + /* + * On some systems the persistent_clock can not be detected at + * timekeeping_init by its return value, so if we see a valid + * value returned, update the persistent_clock_exists flag. + */ + if (timekeeping_suspend_time.tv_sec || timekeeping_suspend_time.tv_nsec) + persistent_clock_exist = true; + raw_spin_lock_irqsave(&timekeeper_lock, flags); write_seqcount_begin(&timekeeper_seq); timekeeping_forward_now(tk); -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/