| From 03da3ff1cfcd7774c8780d2547ba0d995f7dc03d Mon Sep 17 00:00:00 2001 |
| From: David Woodhouse <dwmw2@infradead.org> |
| Date: Wed, 16 Sep 2015 14:10:03 +0100 |
| Subject: x86/platform: Fix Geode LX timekeeping in the generic x86 build |
| |
| From: David Woodhouse <dwmw2@infradead.org> |
| |
| commit 03da3ff1cfcd7774c8780d2547ba0d995f7dc03d upstream. |
| |
| In 2007, commit 07190a08eef36 ("Mark TSC on GeodeLX reliable") |
| bypassed verification of the TSC on Geode LX. However, this code |
| (now in the check_system_tsc_reliable() function in |
| arch/x86/kernel/tsc.c) was only present if CONFIG_MGEODE_LX was |
| set. |
| |
| OpenWRT has recently started building its generic Geode target |
| for Geode GX, not LX, to include support for additional |
| platforms. This broke the timekeeping on LX-based devices, |
| because the TSC wasn't marked as reliable: |
| https://dev.openwrt.org/ticket/20531 |
| |
| By adding a runtime check on is_geode_lx(), we can also include |
| the fix if CONFIG_MGEODEGX1 or CONFIG_X86_GENERIC are set, thus |
| fixing the problem. |
| |
| Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> |
| Cc: Andres Salomon <dilinger@queued.net> |
| Cc: Linus Torvalds <torvalds@linux-foundation.org> |
| Cc: Marcelo Tosatti <marcelo@kvack.org> |
| Cc: Peter Zijlstra <peterz@infradead.org> |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Link: http://lkml.kernel.org/r/1442409003.131189.87.camel@infradead.org |
| Signed-off-by: Ingo Molnar <mingo@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/x86/kernel/tsc.c | 17 ++++++++++------- |
| 1 file changed, 10 insertions(+), 7 deletions(-) |
| |
| --- a/arch/x86/kernel/tsc.c |
| +++ b/arch/x86/kernel/tsc.c |
| @@ -21,6 +21,7 @@ |
| #include <asm/hypervisor.h> |
| #include <asm/nmi.h> |
| #include <asm/x86_init.h> |
| +#include <asm/geode.h> |
| |
| unsigned int __read_mostly cpu_khz; /* TSC clocks / usec, not used here */ |
| EXPORT_SYMBOL(cpu_khz); |
| @@ -1011,15 +1012,17 @@ EXPORT_SYMBOL_GPL(mark_tsc_unstable); |
| |
| static void __init check_system_tsc_reliable(void) |
| { |
| -#ifdef CONFIG_MGEODE_LX |
| - /* RTSC counts during suspend */ |
| +#if defined(CONFIG_MGEODEGX1) || defined(CONFIG_MGEODE_LX) || defined(CONFIG_X86_GENERIC) |
| + if (is_geode_lx()) { |
| + /* RTSC counts during suspend */ |
| #define RTSC_SUSP 0x100 |
| - unsigned long res_low, res_high; |
| + unsigned long res_low, res_high; |
| |
| - rdmsr_safe(MSR_GEODE_BUSCONT_CONF0, &res_low, &res_high); |
| - /* Geode_LX - the OLPC CPU has a very reliable TSC */ |
| - if (res_low & RTSC_SUSP) |
| - tsc_clocksource_reliable = 1; |
| + rdmsr_safe(MSR_GEODE_BUSCONT_CONF0, &res_low, &res_high); |
| + /* Geode_LX - the OLPC CPU has a very reliable TSC */ |
| + if (res_low & RTSC_SUSP) |
| + tsc_clocksource_reliable = 1; |
| + } |
| #endif |
| if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) |
| tsc_clocksource_reliable = 1; |