Re: [PATCH] [1/5] Only do century BCD conversion when we know the RTC is BCD

Previous thread: acer aspire 5720ZG APIC error on CPU0: 40(40) ACPI/USB by Mr Souissi on Saturday, February 9, 2008 - 7:59 am. (1 message)

Next thread: [PATCH 0/8][for -mm] mem_notify v6 by KOSAKI Motohiro on Saturday, February 9, 2008 - 8:19 am. (35 messages)
From: Andi Kleen
Date: Saturday, February 9, 2008 - 8:16 am

Minor logic fix. The century change was previously always BCD,
even when the CMOS data would report itself not being BCD.

Signed-off-by: Andi Kleen <ak@suse.de>

---
 arch/x86/kernel/rtc.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Index: linux/arch/x86/kernel/rtc.c
===================================================================
--- linux.orig/arch/x86/kernel/rtc.c
+++ linux/arch/x86/kernel/rtc.c
@@ -130,10 +130,10 @@ unsigned long mach_get_cmos_time(void)
 		BCD_TO_BIN(day);
 		BCD_TO_BIN(mon);
 		BCD_TO_BIN(year);
+		BCD_TO_BIN(century);
 	}
 
 	if (century) {
-		BCD_TO_BIN(century);
 		year += century * 100;
 		printk(KERN_INFO "Extended CMOS year: %d\n", century * 100);
 	} else {
--

From: Andi Kleen
Date: Saturday, February 9, 2008 - 8:16 am

We know it is already after 2000.

This extends the effective lifetime of 32bit systems by 8 years:
from 2030 to 2038.

The only drawback is that users cannot set the cmos date to before 2000
now on 32bit with systems that don't support extended century in 
the RTC clock. 64bit systems had this limitation for some time
and nobody complained.

And they can always set it to such a date in Linux only using date -s 
if they really want.

Signed-off-by: Andi Kleen <ak@suse.de>

---
 arch/x86/kernel/rtc.c |   10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

Index: linux/arch/x86/kernel/rtc.c
===================================================================
--- linux.orig/arch/x86/kernel/rtc.c
+++ linux/arch/x86/kernel/rtc.c
@@ -9,7 +9,6 @@
 #include <asm/vsyscall.h>
 
 #ifdef CONFIG_X86_32
-# define CMOS_YEARS_OFFS 1900
 /*
  * This is a special lock that is owned by the CPU and holds the index
  * register we are working with.  It is required for NMI access to the
@@ -17,14 +16,11 @@
  */
 volatile unsigned long cmos_lock = 0;
 EXPORT_SYMBOL(cmos_lock);
-#else
-/*
- * x86-64 systems only exists since 2002.
- * This will work up to Dec 31, 2100
- */
-# define CMOS_YEARS_OFFS 2000
 #endif
 
+/* For two digit years assume time is always after that */
+#define CMOS_YEARS_OFFS 2000
+
 DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL(rtc_lock);
 
--

From: Thomas Gleixner
Date: Saturday, February 16, 2008 - 12:24 pm

Applied. Thanks,

	 tglx
--

From: Thomas Gleixner
Date: Wednesday, February 20, 2008 - 3:07 am

Could you please explain what magic math does the 2030 -> 2038
extension ?

According to the code the 1970 comparison works until 2069:

	year += 1900;
	if (year < 1970)
		year += 100;

I keep the patch nevertheless as it removes ifdeffery, but I change
the commit log to something sensible and remove the year < 1970 check
as well as it is not longer necessary.

Thanks,

	tglx
--

From: Andi Kleen
Date: Wednesday, February 20, 2008 - 3:23 am

Hmm, yes on rechecking I also don't know how I got the original
conclusion.

-Andi

--

From: Andi Kleen
Date: Saturday, February 9, 2008 - 8:16 am

We tend to assume the RTC clock is BCD, so print a warning
if it claims to be binary.

Signed-off-by: Andi Kleen <ak@suse.de>

Index: linux/arch/x86/kernel/rtc.c
===================================================================
--- linux.orig/arch/x86/kernel/rtc.c
+++ linux/arch/x86/kernel/rtc.c
@@ -94,6 +94,8 @@ int mach_set_rtc_mmss(unsigned long nowt
 
 unsigned long mach_get_cmos_time(void)
 {
+	unsigned status;
+	static int warned;
 	unsigned int year, mon, day, hour, min, sec, century = 0;
 
 	/*
@@ -119,7 +121,13 @@ unsigned long mach_get_cmos_time(void)
 		century = CMOS_READ(acpi_gbl_FADT.century);
 #endif
 
-	if (RTC_ALWAYS_BCD || !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)) {
+	status = CMOS_READ(RTC_CONTROL);
+	if (RTC_ALWAYS_BCD && (status & RTC_DM_BINARY) && !warned) {
+		printk(KERN_INFO "RTC clock reports binary. Ignored\n");
+		warned = 1;
+	}
+
+	if (RTC_ALWAYS_BCD || !(status & RTC_DM_BINARY)) {
 		BCD_TO_BIN(sec);
 		BCD_TO_BIN(min);
 		BCD_TO_BIN(hour);
--

From: Thomas Gleixner
Date: Saturday, February 16, 2008 - 12:38 pm

Applied. FYI, I changed it to a WARN_ON_ONCE. That will make reports
more likely.

Thanks,

	tglx
--

From: Andi Kleen
Date: Saturday, February 9, 2008 - 8:17 am

It should operate in BCD mode.
Signed-off-by: Andi Kleen <ak@suse.de>

Index: linux/include/asm-x86/mc146818rtc.h
===================================================================
--- linux.orig/include/asm-x86/mc146818rtc.h
+++ linux/include/asm-x86/mc146818rtc.h
@@ -11,7 +11,7 @@
 
 #ifndef RTC_PORT
 #define RTC_PORT(x)	(0x70 + (x))
-#define RTC_ALWAYS_BCD	1	/* RTC operates in binary mode */
+#define RTC_ALWAYS_BCD	1	/* RTC operates in BCD mode */
 #endif
 
 #if defined(CONFIG_X86_32) && defined(__HAVE_ARCH_CMPXCHG)
--

From: Andi Kleen
Date: Saturday, February 9, 2008 - 8:17 am

Not that it matters much, see comment in the code.

v2: Fix compilation on !ACPI, pointed out by tglx

Signed-off-by: Andi Kleen <ak@suse.de>

---
 arch/x86/kernel/rtc.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

Index: linux/arch/x86/kernel/rtc.c
===================================================================
--- linux.orig/arch/x86/kernel/rtc.c
+++ linux/arch/x86/kernel/rtc.c
@@ -112,8 +112,11 @@ unsigned long mach_get_cmos_time(void)
 	mon = CMOS_READ(RTC_MONTH);
 	year = CMOS_READ(RTC_YEAR);
 
-#if defined(CONFIG_ACPI) && defined(CONFIG_X86_64)
-	/* CHECKME: Is this really 64bit only ??? */
+#ifdef CONFIG_ACPI
+	/*
+	 * On 32bit not strictly needed because the world ends in 2038
+	 * and the code can handle that with the 2 digit heuristics.
+	 */
 	if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
 	    acpi_gbl_FADT.century)
 		century = CMOS_READ(acpi_gbl_FADT.century);
--

From: Thomas Gleixner
Date: Saturday, February 16, 2008 - 12:38 pm

Applied. Thanks,

	 tglx
--

From: Thomas Gleixner
Date: Monday, February 11, 2008 - 1:30 am

I checked that whole rtc / BCD logic again. We always set RTC_ALWAYS_BCD:

#ifndef RTC_PORT
#define RTC_PORT(x)    (0x70 + (x))
#define RTC_ALWAYS_BCD 1       /* RTC operates in BCD mode */
#endif

Nothing ever defines RTC_PORT and RTC_ALWAYS_BCD


This should probably go here:

        if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
            acpi_gbl_FADT.century) {
--->
 	}

It does not matter much, because BCD_TO_BIN(0) is 0, but it makes a
lot of sense.

Thanks,

	tglx
--

From: Andi Kleen
Date: Monday, February 11, 2008 - 1:56 am

Please see the second version of the patch series. This means I didn't drop it 
completely, but added a warning about it not agreeing with the status 
register. If this warning never triggers it can be dropped eventually,
if it triggers RTC_ALWAYS_BCD should be unset.

-Andi
--

From: Thomas Gleixner
Date: Monday, February 11, 2008 - 3:08 pm

#define RTC_ALWAYS_BCD 1 is there since Linux 1.0 and got never
changed for x86.

So the warning comes a bit late :)

Later on the #ifdef RTC_PORT was introduced to share the header in
include/linux across architectures. When the header got copied to
include/i386 and elsewhere this just was never removed.

Thanks,

	tglx
--

From: Andi Kleen
Date: Monday, February 11, 2008 - 3:15 pm

> So the warning comes a bit late :)

I suspect if this was wrong before it would not have been noticed
because user space hwclock would work around it. The warning
certainly won't hurt.

Anyways if you feel strongly about this (I don't) then drop
this patch, but apply the other ones in the series. The main
one I consider important is the change to the 2000 offset for 32bit
to extend the 32bit lifetime.

-Andi
--

From: Thomas Gleixner
Date: Tuesday, February 12, 2008 - 1:36 pm

And how exaclty does it work around ? By setting the binary cmos clock


I'm not opposing the patch, I merily asked for a removal of the never

Picked the whole lot up.

Thanks,

	tglx
--

From: Andi Kleen
Date: Wednesday, February 13, 2008 - 6:49 am

By reading the value directly from CMOS I suppose and checking
the BCD bit and then setting the clock to the correct value [all
theoretical; i have not checked the hwclock code if
it does that or not. It might be wrong. Just a hypothesis.]

-Andi

--

Previous thread: acer aspire 5720ZG APIC error on CPU0: 40(40) ACPI/USB by Mr Souissi on Saturday, February 9, 2008 - 7:59 am. (1 message)

Next thread: [PATCH 0/8][for -mm] mem_notify v6 by KOSAKI Motohiro on Saturday, February 9, 2008 - 8:19 am. (35 messages)