From patchwork Mon Dec 17 21:30:53 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gunthorpe X-Patchwork-Id: 206998 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail-ob0-f184.google.com (mail-ob0-f184.google.com [209.85.214.184]) (using TLSv1 with cipher ECDHE-RSA-RC4-SHA (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 1DA0C2C0092 for ; Tue, 18 Dec 2012 08:31:06 +1100 (EST) Received: by mail-ob0-f184.google.com with SMTP id 16sf3960061obc.21 for ; Mon, 17 Dec 2012 13:31:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20120806; h=x-received:x-beenthere:x-received:x-received:received-spf:date:from :to:cc:subject:message-id:references:mime-version:in-reply-to :user-agent:x-broken-reverse-dns:x-original-sender :x-original-authentication-results:reply-to:precedence:mailing-list :list-id:x-google-group-id:list-post:list-help:list-archive:sender :list-subscribe:list-unsubscribe:content-type:content-disposition; bh=4wo08klZPp3REiYGXdtOYSLet6qwlgsPFDPB+YXrY3U=; b=LTaVab1zXkkneStAWC/EvKP45EiVHFQbRujk8wNcDYCcrvtblDVzWNEVbu9FD9rY7Y 52s4Ds1yWaYSmcW/5bPAjkhcDb0QVL1Dj7lSrNL3PKE52pJYX0RD8OB/ZKiqf0V7HQAy ThvcFdw2MkI72FH9xm/MqxCEc7prWijcNovuXQDi6tkRcPeBLlJUOWRUGwDdI0KR+tkV 9FibaJ+Fd2ymskFDZN9s0sQOb0bbe/Kea2rpVWblpExusyjlx/Hk75koUu3zQ5bYGTYM hA/HXZSgvWISLCOt2j07Nl6l1dPiWbwua3QQ8u6iPL3jEDlX0xLoRUvvPLiseZOlrAxy Si3A== X-Received: by 10.50.45.226 with SMTP id q2mr37028igm.0.1355779864427; Mon, 17 Dec 2012 13:31:04 -0800 (PST) X-BeenThere: rtc-linux@googlegroups.com Received: by 10.50.41.137 with SMTP id f9ls3515933igl.44.canary; Mon, 17 Dec 2012 13:31:03 -0800 (PST) X-Received: by 10.66.82.137 with SMTP id i9mr21194pay.41.1355779863323; Mon, 17 Dec 2012 13:31:03 -0800 (PST) X-Received: by 10.66.82.137 with SMTP id i9mr21193pay.41.1355779863308; Mon, 17 Dec 2012 13:31:03 -0800 (PST) Received: from quartz.orcorp.ca (quartz.orcorp.ca. [184.70.90.242]) by gmr-mx.google.com with ESMTPS id uz6si3154344pbc.0.2012.12.17.13.31.02 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 17 Dec 2012 13:31:03 -0800 (PST) Received-SPF: pass (google.com: domain of jgunthorpe@obsidianresearch.com designates 184.70.90.242 as permitted sender) client-ip=184.70.90.242; Received: from [10.0.0.162] (helo=jggl.edm.orcorp.ca) by quartz.orcorp.ca with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.72) (envelope-from ) id 1TkiGz-0003uq-F6; Mon, 17 Dec 2012 14:30:53 -0700 Received: from jgg by jggl.edm.orcorp.ca with local (Exim 4.76) (envelope-from ) id 1TkiGz-0007HJ-8y; Mon, 17 Dec 2012 14:30:53 -0700 Date: Mon, 17 Dec 2012 14:30:53 -0700 From: Jason Gunthorpe To: John Stultz Cc: Alessandro Zummo , Thomas Gleixner , rtc-linux@googlegroups.com, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linuxppc-dev@lists.ozlabs.org Subject: [rtc-linux] [PATCH v3] NTP: Add a CONFIG_RTC_SYSTOHC configuration Message-ID: <20121217213053.GA27497@obsidianresearch.com> References: <20121214231933.GA15796@obsidianresearch.com> <50CBB917.7090502@linaro.org> MIME-Version: 1.0 In-Reply-To: <50CBB917.7090502@linaro.org> User-Agent: Mutt/1.5.21 (2010-09-15) X-Broken-Reverse-DNS: no host name found for IP address 10.0.0.162 X-Original-Sender: jgunthorpe@obsidianresearch.com X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com: domain of jgunthorpe@obsidianresearch.com designates 184.70.90.242 as permitted sender) smtp.mail=jgunthorpe@obsidianresearch.com; dkim=pass (test mode) header.i=@obsidianresearch.com Reply-To: rtc-linux@googlegroups.com Precedence: list Mailing-list: list rtc-linux@googlegroups.com; contact rtc-linux+owners@googlegroups.com List-ID: X-Google-Group-Id: 712029733259 List-Post: , List-Help: , List-Archive: Sender: rtc-linux@googlegroups.com List-Subscribe: , List-Unsubscribe: , Content-Disposition: inline The purpose of this option is to allow ARM/etc systems that rely on the class RTC subsystem to have the same kind of automatic NTP based synchronization that we have on PC platforms. Today ARM does not implement update_persistent_clock and makes extensive use of the class RTC system. When enabled CONFIG_RTC_SYSTOHC will provide a generic rtc_update_persistent_clock that stores the current time in the RTC and is intended complement the existing CONFIG_RTC_HCTOSYS option that loads the RTC at boot. Like with RTC_HCTOSYS the platform's update_persistent_clock is used first, if it works. Platforms with mixed class RTC and non-RTC drivers need to return ENODEV when class RTC should be used. Such an update for PPC is included in this patch. Long term, implementations of update_persistent_clock should migrate to proper class RTC drivers and use CONFIG_RTC_SYSTOHC instead. Tested on ARM kirkwood and PPC405 Signed-off-by: Jason Gunthorpe --- arch/powerpc/kernel/time.c | 2 +- drivers/rtc/Kconfig | 10 +++++++++- drivers/rtc/Makefile | 1 + drivers/rtc/systohc.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/rtc.h | 1 + kernel/time/ntp.c | 16 ++++++++++++---- 6 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 drivers/rtc/systohc.c v3 changes: - Test menuconfig, reorder options to look better, fix kconfig RTC_HCTOSYS_DEVICE to be 'or' not 'and' - Change the function name to rtc_set_ntp_time to avoid confusing this api with the distinct *_persistant_clock stuff - Fix typo in the ENODEV test to be || not && - Fully retest on ARM+PPC diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index ce4cb77..bc844a8 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -667,7 +667,7 @@ int update_persistent_clock(struct timespec now) struct rtc_time tm; if (!ppc_md.set_rtc_time) - return 0; + return -ENODEV; to_tm(now.tv_sec + 1 + timezone_offset, &tm); tm.tm_year -= 1900; diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 19c03ab..b377e96 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -25,9 +25,17 @@ config RTC_HCTOSYS the value read from a specified RTC device. This is useful to avoid unnecessary fsck runs at boot time, and to network better. +config RTC_SYSTOHC + bool "Set the RTC time based on NTP synchronization" + default y + help + If you say yes here, the system time (wall clock) will be stored + in the RTC specified by RTC_HCTOSYS_DEVICE approximately every 11 + minutes if userspace reports synchronized NTP status. + config RTC_HCTOSYS_DEVICE string "RTC used to set the system time" - depends on RTC_HCTOSYS = y + depends on RTC_HCTOSYS = y || RTC_SYSTOHC = y default "rtc0" help The RTC device that will be used to (re)initialize the system diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 56297f0..69d11f1 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -6,6 +6,7 @@ ccflags-$(CONFIG_RTC_DEBUG) := -DDEBUG obj-$(CONFIG_RTC_LIB) += rtc-lib.o obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o +obj-$(CONFIG_RTC_SYSTOHC) += systohc.o obj-$(CONFIG_RTC_CLASS) += rtc-core.o rtc-core-y := class.o interface.o diff --git a/drivers/rtc/systohc.c b/drivers/rtc/systohc.c new file mode 100644 index 0000000..bf3e242 --- /dev/null +++ b/drivers/rtc/systohc.c @@ -0,0 +1,44 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + */ +#include +#include + +/** + * rtc_set_ntp_time - Save NTP synchronized time to the RTC + * @now: Current time of day + * + * Replacement for the NTP platform function update_persistent_clock + * that stores time for later retrieval by rtc_hctosys. + * + * Returns 0 on successful RTC update, -ENODEV if a RTC update is not + * possible at all, and various other -errno for specific temporary failure + * cases. + * + * If temporary failure is indicated the caller should try again 'soon' + */ +int rtc_set_ntp_time(struct timespec now) +{ + struct rtc_device *rtc; + struct rtc_time tm; + int err = -ENODEV; + + if (now.tv_nsec < (NSEC_PER_SEC >> 1)) + rtc_time_to_tm(now.tv_sec, &tm); + else + rtc_time_to_tm(now.tv_sec + 1, &tm); + + rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); + if (rtc) { + /* rtc_hctosys exclusively uses UTC, so we call set_time here, + * not set_mmss. */ + if (rtc->ops && (rtc->ops->set_time || rtc->ops->set_mmss)) + err = rtc_set_time(rtc, &tm); + rtc_class_close(rtc); + } + + return err; +} diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 9531845..11d05f9 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -138,6 +138,7 @@ extern void rtc_device_unregister(struct rtc_device *rtc); extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm); extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm); extern int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs); +extern int rtc_set_ntp_time(struct timespec now); int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm); extern int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alrm); diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 24174b4..313b161 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "tick-internal.h" @@ -483,8 +484,7 @@ out: return leap; } -#ifdef CONFIG_GENERIC_CMOS_UPDATE - +#if defined(CONFIG_GENERIC_CMOS_UPDATE) || defined(CONFIG_RTC_SYSTOHC) static void sync_cmos_clock(struct work_struct *work); static DECLARE_DELAYED_WORK(sync_cmos_work, sync_cmos_clock); @@ -510,14 +510,22 @@ static void sync_cmos_clock(struct work_struct *work) } getnstimeofday(&now); - if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) + if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) { + fail = -ENODEV; +#ifdef CONFIG_GENERIC_CMOS_UPDATE fail = update_persistent_clock(now); +#endif +#ifdef CONFIG_RTC_SYSTOHC + if (fail == -ENODEV) + fail = rtc_set_ntp_time(now); +#endif + } next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec - (TICK_NSEC / 2); if (next.tv_nsec <= 0) next.tv_nsec += NSEC_PER_SEC; - if (!fail) + if (!fail || fail == -ENODEV) next.tv_sec = 659; else next.tv_sec = 0;