From patchwork Thu Jun 6 10:51:49 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Holler X-Patchwork-Id: 249384 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail-bk0-x23a.google.com (mail-bk0-x23a.google.com [IPv6:2a00:1450:4008:c01::23a]) (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 1DEB62C0099 for ; Thu, 6 Jun 2013 20:53:03 +1000 (EST) Received: by mail-bk0-f58.google.com with SMTP id it19sf527312bkc.3 for ; Thu, 06 Jun 2013 03:53:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20120806; h=mime-version:x-beenthere:x-spam-checker-version:x-spam-level :x-spam-status:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references: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; bh=FQw5lpj3b35bsTUZ83nYN6GfdlZXIS6+1TqovYHPc/Q=; b=I0m/y2+SRKG1PK20bJr0uyj3SXnt7n6xVdo5iQCjuDttoCgDki/z0w84l+nxtNCBfg luMJ2WlAw7QYxfC6Crotw2GjeSFfhPWInpo/FfkxukxEYs+Vg/fPu0u20rNl7FZ7hKOl kNJ397AoDnfMCoVwO+hsDbxlprMyuIPrap1N5+LoILuC4ilQ1l8/PCYUejhIbVoxUjgS VIVjcDcronK/q3mLVuC+YZgSkbkL1tQRKzgPty6SLXSmwLcN3KqFl2SeUVgWfJBTzkQP cMNI9E4Nck8tn3taKZD2xpwMnZ7sMcLE9hghCHt0uSma+CweKZiUf04JferMjY+9kDly g1yQ== X-Received: by 10.180.189.6 with SMTP id ge6mr1155667wic.6.1370515980492; Thu, 06 Jun 2013 03:53:00 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: rtc-linux@googlegroups.com Received: by 10.180.13.52 with SMTP id e20ls871996wic.4.gmail; Thu, 06 Jun 2013 03:52:59 -0700 (PDT) X-Received: by 10.204.228.132 with SMTP id je4mr3125603bkb.6.1370515979443; Thu, 06 Jun 2013 03:52:59 -0700 (PDT) Received: from mail.ahsoftware.de (h1446028.stratoserver.net. [85.214.92.142]) by gmr-mx.google.com with ESMTP id rl1si3217487bkb.3.2013.06.06.03.52.59 for ; Thu, 06 Jun 2013 03:52:59 -0700 (PDT) Received-SPF: neutral (google.com: 85.214.92.142 is neither permitted nor denied by best guess record for domain of holler@ahsoftware.de) client-ip=85.214.92.142; Received: by mail.ahsoftware.de (Postfix, from userid 65534) id 39485888C21; Thu, 6 Jun 2013 12:52:59 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.ahsoftware.de X-Spam-Level: X-Spam-Status: No, score=-101.0 required=5.0 tests=ALL_TRUSTED, USER_IN_WHITELIST autolearn=disabled version=3.3.1 Received: from eiche.ahsoftware (p57B205D7.dip0.t-ipconnect.de [87.178.5.215]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.ahsoftware.de (Postfix) with ESMTPSA id 284ED888BFD for ; Thu, 6 Jun 2013 12:52:58 +0200 (CEST) Received: by eiche.ahsoftware (Postfix, from userid 65534) id 781C17F810; Thu, 6 Jun 2013 12:52:57 +0200 (CEST) Received: from laptopahbt.ahsoftware (unknown [192.168.211.6]) by eiche.ahsoftware (Postfix) with ESMTP id 34C597F977; Thu, 6 Jun 2013 10:52:30 +0000 (UTC) From: Alexander Holler To: linux-kernel@vger.kernel.org Cc: Andrew Morton , John Stultz , Thomas Gleixner , Alessandro Zummo , rtc-linux@googlegroups.com, Alexander Holler Subject: [rtc-linux] [PATCH 2/3 v2] RFC: timekeeping: rtc: Introduce new kernel parameter hctosys Date: Thu, 6 Jun 2013 12:51:49 +0200 Message-Id: <1370515910-2883-3-git-send-email-holler@ahsoftware.de> X-Mailer: git-send-email 1.8.1.5 In-Reply-To: <1370515910-2883-1-git-send-email-holler@ahsoftware.de> References: <1370452540-3319-1-git-send-email-holler@ahsoftware.de> <1370515910-2883-1-git-send-email-holler@ahsoftware.de> X-Original-Sender: holler@ahsoftware.de X-Original-Authentication-Results: gmr-mx.google.com; spf=neutral (google.com: 85.214.92.142 is neither permitted nor denied by best guess record for domain of holler@ahsoftware.de) smtp.mail=holler@ahsoftware.de 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: , hctosys= specifies the driver (RTC) name which sets the system clock at boot, if and only if userspace hasn't set the time before the driver will be loaded. If hctosys will not be specified, the first available hardware clock with a valid time will be used (again, if and only if ...). If you don't want that the system clock will be set by any hardware clock, just specify a non-existent RTC driver name, e.g. with hctosys=none. Currently there exist a special name "persistent" for the persistent clock found on some systems (e.g. the CMOS clock on x86 platforms which might be handled by the driver named rtc_cmos too). This will replace the existent driver/mechanism hctosys and the kernel config options CONFIG_RTC_HCTOSYS and CONFIG_RTC_HCTOSYS_DEVICE (done with one of the following patches) Signed-off-by: Alexander Holler --- Documentation/kernel-parameters.txt | 12 +++++++++ drivers/rtc/class.c | 39 +++++++++++++++++++++++++++++ include/linux/time.h | 6 +++++ kernel/time/timekeeping.c | 49 +++++++++++++++++++++++++++++-------- 4 files changed, 96 insertions(+), 10 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 6e3b18a..a8b7a9c 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -983,6 +983,18 @@ bytes respectively. Such letter suffixes can also be entirely omitted. hcl= [IA-64] SGI's Hardware Graph compatibility layer + hctosys= [KNL] Specifies the driver (RTC) name which sets the + time at boot, if and only if userspace hasn't set the + time before the driver will be loaded. If hctosys will + not be specified, the first available hardware clock + with a valid time will be used. + Use a non-existent name (e.g. hctosys=none) if you want + to avoid that a hardware clock will set the time. + Currently there exist a special name "persistent" for + the persistent clock found on some systems (e.g. the + CMOS clock on x86 platforms which might be handled + by the driver named rtc_cmos too). + hd= [EIDE] (E)IDE hard drive subsystem geometry Format: ,, diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 6638540..a159d1f 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -141,6 +141,40 @@ static int rtc_resume(struct device *dev) #endif +static void hctosys(struct rtc_device *rtc) +{ + struct rtc_time now; + struct timespec tv = { + .tv_nsec = NSEC_PER_SEC >> 1, + }; + int rc; + + rc = rtc_read_time(rtc, &now); + if (rc) { + dev_err(rtc->dev.parent, "rtc core: error reading time from RTC: %d\n", rc); + return; + } + rc = rtc_valid_tm(&now); + if (rc) { + dev_err(rtc->dev.parent, "rtc core: date/time from RTC is invalid\n"); + return; + } + rtc_tm_to_time(&now, &tv.tv_sec); + if (systime_was_set) + return; + rc = do_settimeofday(&tv); + if (rc) { + dev_err(rtc->dev.parent, "rtc core: error setting system clock: %d\n", rc); + return; + } else if (systime_was_set) + dev_info(rtc->dev.parent, + "setting system clock to " + "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n", + now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, + now.tm_hour, now.tm_min, now.tm_sec, + (unsigned int) tv.tv_sec); +} + /** * rtc_device_register - register w/ RTC class * @dev: the device to register @@ -157,6 +191,7 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, struct rtc_device *rtc; struct rtc_wkalrm alrm; int id, err; + const char *hctosys_name = get_hctosys_name(); id = ida_simple_get(&rtc_ida, 0, 0, GFP_KERNEL); if (id < 0) { @@ -196,6 +231,10 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, rtc->pie_timer.function = rtc_pie_update_irq; rtc->pie_enabled = 0; + if (!systime_was_set && + (!hctosys_name[0] || !strcasecmp(name, hctosys_name))) + hctosys(rtc); + /* Check to see if there is an ALARM already set in hw */ err = __rtc_read_alarm(rtc, &alrm); diff --git a/include/linux/time.h b/include/linux/time.h index 888280f..e5f644c 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -135,6 +135,12 @@ extern int timekeeping_suspended; */ extern bool systime_was_set; +/* + * Returns a pointer to the string specified with + * hctosys= at the kernel command line. + */ +const char *get_hctosys_name(void); + unsigned long get_seconds(void); struct timespec current_kernel_time(void); struct timespec __current_kernel_time(void); /* does not take xtime_lock */ diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 07f151f..fdbe3ab 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "tick-internal.h" #include "ntp_internal.h" @@ -40,6 +41,22 @@ bool __read_mostly persistent_clock_exist = false; /* Flag for if the system time was set at least once */ bool __read_mostly systime_was_set; +static char hctosys_name[RTC_DEVICE_NAME_SIZE]; + +static int __init hctosys_setup(char *line) +{ + strlcpy(hctosys_name, line, sizeof(hctosys_name)); + return 1; +} + +__setup("hctosys=", hctosys_setup); + +const char *get_hctosys_name(void) +{ + return hctosys_name; +} +EXPORT_SYMBOL_GPL(get_hctosys_name); + static inline void tk_normalize_xtime(struct timekeeper *tk) { while (tk->xtime_nsec >= ((u64)NSEC_PER_SEC << tk->shift)) { @@ -780,16 +797,17 @@ void __init timekeeping_init(void) unsigned long flags; struct timespec now, boot, tmp; - read_persistent_clock(&now); - - if (!timespec_valid_strict(&now)) { - pr_warn("WARNING: Persistent clock returned invalid value!\n" - " Check your CMOS/BIOS settings.\n"); - now.tv_sec = 0; - now.tv_nsec = 0; - } else if (now.tv_sec || now.tv_nsec) { - persistent_clock_exist = true; - systime_was_set = true; + if (!hctosys_name[0] || !strcasecmp(hctosys_name, "persistent")) { + read_persistent_clock(&now); + if (!timespec_valid_strict(&now)) { + pr_warn("WARNING: Persistent clock returned invalid value!\n" + " Check your CMOS/BIOS settings.\n"); + now.tv_sec = 0; + now.tv_nsec = 0; + } else if (now.tv_sec || now.tv_nsec) { + persistent_clock_exist = true; + systime_was_set = true; + } } read_boot_clock(&boot); @@ -826,6 +844,17 @@ void __init timekeeping_init(void) write_seqcount_end(&timekeeper_seq); raw_spin_unlock_irqrestore(&timekeeper_lock, flags); + + if (systime_was_set) { + /* print a msg like if the time was set by a RTC */ + struct tm now_tm; + time_to_tm(now.tv_sec, 0, &now_tm); + pr_info("persistent clock: setting system clock to " + "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n", + (int)now_tm.tm_year + 1900, now_tm.tm_mon + 1, + now_tm.tm_mday, now_tm.tm_hour, now_tm.tm_min, + now_tm.tm_sec, (unsigned int) now.tv_sec); + } } /* time in seconds when suspend began */