aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/platform/efi/efi.c
diff options
context:
space:
mode:
authorPrarit Bhargava <prarit@redhat.com>2013-02-14 12:02:54 -0500
committerJohn Stultz <john.stultz@linaro.org>2013-03-15 19:50:26 -0400
commit3195ef59cb42cda3aeeb24a7fd2ba1b900c4a3cc (patch)
treee439d7cd1a3242ccff03521657699f9e9497bf13 /arch/x86/platform/efi/efi.c
parent7859e404ae73fe4f38b8cfc1af19ea82f153084e (diff)
x86: Do full rtc synchronization with ntp
Every 11 minutes ntp attempts to update the x86 rtc with the current system time. Currently, the x86 code only updates the rtc if the system time is within +/-15 minutes of the current value of the rtc. This was done originally to avoid setting the RTC if the RTC was in localtime mode (common with Windows dualbooting). Other architectures do a full synchronization and now that we have better infrastructure to detect when the RTC is in localtime, there is no reason that x86 should be software limited to a 30 minute window. This patch changes the behavior of the kernel to do a full synchronization (year, month, day, hour, minute, and second) of the rtc when ntp requests a synchronization between the system time and the rtc. I've used the RTC library functions in this patchset as they do all the required bounds checking. Cc: Thomas Gleixner <tglx@linutronix.de> Cc: John Stultz <john.stultz@linaro.org> Cc: x86@kernel.org Cc: Matt Fleming <matt.fleming@intel.com> Cc: David Vrabel <david.vrabel@citrix.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andi Kleen <ak@linux.intel.com> Cc: linux-efi@vger.kernel.org Signed-off-by: Prarit Bhargava <prarit@redhat.com> [jstultz: Tweak commit message, fold in build fix found by fengguang Also add select RTC_LIB to X86, per new dependency, as found by prarit] Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'arch/x86/platform/efi/efi.c')
-rw-r--r--arch/x86/platform/efi/efi.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 5f2ecaf3f9d8..28d9efacc9b6 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -48,6 +48,7 @@
48#include <asm/cacheflush.h> 48#include <asm/cacheflush.h>
49#include <asm/tlbflush.h> 49#include <asm/tlbflush.h>
50#include <asm/x86_init.h> 50#include <asm/x86_init.h>
51#include <asm/rtc.h>
51 52
52#define EFI_DEBUG 1 53#define EFI_DEBUG 1
53 54
@@ -258,10 +259,10 @@ static efi_status_t __init phys_efi_get_time(efi_time_t *tm,
258 259
259int efi_set_rtc_mmss(unsigned long nowtime) 260int efi_set_rtc_mmss(unsigned long nowtime)
260{ 261{
261 int real_seconds, real_minutes;
262 efi_status_t status; 262 efi_status_t status;
263 efi_time_t eft; 263 efi_time_t eft;
264 efi_time_cap_t cap; 264 efi_time_cap_t cap;
265 struct rtc_time tm;
265 266
266 status = efi.get_time(&eft, &cap); 267 status = efi.get_time(&eft, &cap);
267 if (status != EFI_SUCCESS) { 268 if (status != EFI_SUCCESS) {
@@ -269,13 +270,20 @@ int efi_set_rtc_mmss(unsigned long nowtime)
269 return -1; 270 return -1;
270 } 271 }
271 272
272 real_seconds = nowtime % 60; 273 rtc_time_to_tm(nowtime, &tm);
273 real_minutes = nowtime / 60; 274 if (!rtc_valid_tm(&tm)) {
274 if (((abs(real_minutes - eft.minute) + 15)/30) & 1) 275 eft.year = tm.tm_year + 1900;
275 real_minutes += 30; 276 eft.month = tm.tm_mon + 1;
276 real_minutes %= 60; 277 eft.day = tm.tm_mday;
277 eft.minute = real_minutes; 278 eft.minute = tm.tm_min;
278 eft.second = real_seconds; 279 eft.second = tm.tm_sec;
280 eft.nanosecond = 0;
281 } else {
282 printk(KERN_ERR
283 "%s: Invalid EFI RTC value: write of %lx to EFI RTC failed\n",
284 __FUNCTION__, nowtime);
285 return -1;
286 }
279 287
280 status = efi.set_time(&eft); 288 status = efi.set_time(&eft);
281 if (status != EFI_SUCCESS) { 289 if (status != EFI_SUCCESS) {