All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] Moorestown changes in arch/x86 for 35 merge window
@ 2010-05-07 17:41 Jacob Pan
  2010-05-07 17:41 ` [PATCH 1/8] x86: avoid check hlt if no timer interrupts Jacob Pan
                   ` (7 more replies)
  0 siblings, 8 replies; 49+ messages in thread
From: Jacob Pan @ 2010-05-07 17:41 UTC (permalink / raw)
  To: Thomas Gleixner, H. Peter Anvin, Ingo Molnar, Alek Du,
	Arjan van de Ven, Feng Tang, LKML
  Cc: Jacob Pan

Hi hpa, ingo, and tglx,

The following changes are based on commit:
d94e93d495514c69d4a7a553c0938cd777267e5d

Changes include addition of vitual RTC driver and many clockevent tweaks in
order to support Medfield (next generation) in the same binary kernel image.

We consolidated tsc and lapic calibration into platform specific routine
under x86_init for MRST. There will be a follow-up RFC patch does the similar
consolidation for standard PC with HPET.

*** BLURB HERE ***

Feng Tang (2):
  x86/platform: add a wallclock_init func to x86_platforms ops
  x86/mrst: add vrtc driver which serves as a wall clock device

Jacob Pan (6):
  x86: avoid check hlt if no timer interrupts
  x86/mrst/pci: return 0 for non-present pci bars
  x86/apic: allow use of lapic timer early calibration result
  x86/mrst: change clock selection logic to support medfield
  x86/apbt: support more timer configurations on mrst
  x86/mrst: Add nop functions to x86_init mpparse functions

 arch/x86/include/asm/apb_timer.h |    2 +-
 arch/x86/include/asm/bugs.h      |    1 +
 arch/x86/include/asm/fixmap.h    |    4 +
 arch/x86/include/asm/mrst.h      |   30 ++++++++
 arch/x86/include/asm/vrtc.h      |   27 +++++++
 arch/x86/include/asm/x86_init.h  |    2 +
 arch/x86/kernel/Makefile         |    2 +-
 arch/x86/kernel/apb_timer.c      |   18 +++--
 arch/x86/kernel/apic/apic.c      |   21 +++++-
 arch/x86/kernel/cpu/bugs.c       |    4 +
 arch/x86/kernel/mrst.c           |  143 ++++++++++++++++++++++++++++++++++---
 arch/x86/kernel/setup.c          |    2 +
 arch/x86/kernel/vrtc.c           |  100 ++++++++++++++++++++++++++
 arch/x86/kernel/x86_init.c       |    2 +
 arch/x86/pci/mrst.c              |    2 +-
 15 files changed, 336 insertions(+), 24 deletions(-)
 create mode 100644 arch/x86/include/asm/vrtc.h
 create mode 100644 arch/x86/kernel/vrtc.c


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH 1/8] x86: avoid check hlt if no timer interrupts
  2010-05-07 17:41 [PATCH 0/8] Moorestown changes in arch/x86 for 35 merge window Jacob Pan
@ 2010-05-07 17:41 ` Jacob Pan
  2010-05-07 20:32   ` RFD: Should we remove the HLT check? (was Re: [PATCH 1/8] x86: avoid check hlt if no timer interrupts) H. Peter Anvin
  2010-05-07 17:41 ` [PATCH 2/8] x86/mrst/pci: return 0 for non-present pci bars Jacob Pan
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 49+ messages in thread
From: Jacob Pan @ 2010-05-07 17:41 UTC (permalink / raw)
  To: Thomas Gleixner, H. Peter Anvin, Ingo Molnar, Alek Du,
	Arjan van de Ven, Feng Tang, LKML
  Cc: Jacob Pan, Jacob Pan

From: Jacob Pan <jacob.jun.pan@intel.com>

check hlt requires external timer interrupt to wake up the
cpu. for platforms equipped with only per cpu timers, we don't
have external interrupts during check hlt.
this patch checks such condition to avoid kernel hang at hlt.
it also saves boot time in that hlt four times in the current code
requires four ticks to break out of them.

Signed-off-by: Jacob Pan <jacob.jun.pan@intel.com>
Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
---
 arch/x86/include/asm/bugs.h |    1 +
 arch/x86/kernel/cpu/bugs.c  |    4 ++++
 2 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/bugs.h b/arch/x86/include/asm/bugs.h
index 08abf63..1e0cef8 100644
--- a/arch/x86/include/asm/bugs.h
+++ b/arch/x86/include/asm/bugs.h
@@ -2,6 +2,7 @@
 #define _ASM_X86_BUGS_H
 
 extern void check_bugs(void);
+extern struct clock_event_device *global_clock_event;
 
 #if defined(CONFIG_CPU_SUP_INTEL) && defined(CONFIG_X86_32)
 int ppro_with_ram_bug(void);
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 01a2652..c0d9688 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -90,6 +90,10 @@ static void __init check_hlt(void)
 		return;
 
 	printk(KERN_INFO "Checking 'hlt' instruction... ");
+	if (!global_clock_event) {
+		printk(KERN_CONT "no clockevent to wake up, skipped.\n");
+		return;
+	}
 	if (!boot_cpu_data.hlt_works_ok) {
 		printk("disabled\n");
 		return;
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 2/8] x86/mrst/pci: return 0 for non-present pci bars
  2010-05-07 17:41 [PATCH 0/8] Moorestown changes in arch/x86 for 35 merge window Jacob Pan
  2010-05-07 17:41 ` [PATCH 1/8] x86: avoid check hlt if no timer interrupts Jacob Pan
@ 2010-05-07 17:41 ` Jacob Pan
  2010-05-07 17:41 ` [PATCH 3/8] x86/apic: allow use of lapic timer early calibration result Jacob Pan
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 49+ messages in thread
From: Jacob Pan @ 2010-05-07 17:41 UTC (permalink / raw)
  To: Thomas Gleixner, H. Peter Anvin, Ingo Molnar, Alek Du,
	Arjan van de Ven, Feng Tang, LKML
  Cc: Jacob Pan

Moorestown PCI code has special handling of devices with fixed BARs. In
case of BAR sizing writes, we need to update the fake PCI MMCFG space with real
size decode value.

When a BAR is not present, we need to return 0 instead of ~0. ~0 will be
treated as device error per bugzilla 12006.

Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 arch/x86/pci/mrst.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/x86/pci/mrst.c b/arch/x86/pci/mrst.c
index 8bf2fcb..d5c7aef 100644
--- a/arch/x86/pci/mrst.c
+++ b/arch/x86/pci/mrst.c
@@ -109,7 +109,7 @@ static int pci_device_update_fixed(struct pci_bus *bus, unsigned int devfn,
 			decode++;
 			decode = ~(decode - 1);
 		} else {
-			decode = ~0;
+			decode = 0;
 		}
 
 		/*
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 3/8] x86/apic: allow use of lapic timer early calibration result
  2010-05-07 17:41 [PATCH 0/8] Moorestown changes in arch/x86 for 35 merge window Jacob Pan
  2010-05-07 17:41 ` [PATCH 1/8] x86: avoid check hlt if no timer interrupts Jacob Pan
  2010-05-07 17:41 ` [PATCH 2/8] x86/mrst/pci: return 0 for non-present pci bars Jacob Pan
@ 2010-05-07 17:41 ` Jacob Pan
  2010-05-11 13:46   ` Thomas Gleixner
  2010-05-07 17:41 ` [PATCH 4/8] x86/mrst: change clock selection logic to support medfield Jacob Pan
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 49+ messages in thread
From: Jacob Pan @ 2010-05-07 17:41 UTC (permalink / raw)
  To: Thomas Gleixner, H. Peter Anvin, Ingo Molnar, Alek Du,
	Arjan van de Ven, Feng Tang, LKML
  Cc: Jacob Pan, Jacob Pan

From: Jacob Pan <jacob.jun.pan@intel.com>

lapic timer calibration can be combined with tsc in platform specific
calibration functions. if such calibration result is obtained early,
we can skip the redundent calibration loops.

Signed-off-by: Jacob Pan <jacob.jun.pan@intel.com>
Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
---
 arch/x86/kernel/apic/apic.c |   21 ++++++++++++++++++++-
 1 files changed, 20 insertions(+), 1 deletions(-)

diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index e5a4a1e..8ef56ac 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -175,7 +175,7 @@ static struct resource lapic_resource = {
 	.flags = IORESOURCE_MEM | IORESOURCE_BUSY,
 };
 
-static unsigned int calibration_result;
+unsigned int calibration_result;
 
 static int lapic_next_event(unsigned long delta,
 			    struct clock_event_device *evt);
@@ -597,6 +597,25 @@ static int __init calibrate_APIC_clock(void)
 	long delta, deltatsc;
 	int pm_referenced = 0;
 
+	/**
+	 * check if lapic timer has already been calibrated by platform
+	 * specific routine, such as tsc calibration code. if so, we just fill
+	 * in the clockevent structure and return.
+	 */
+
+	if (calibration_result) {
+		apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n",
+				calibration_result);
+		lapic_clockevent.mult = div_sc(calibration_result/APIC_DIVISOR,
+					TICK_NSEC, lapic_clockevent.shift);
+		lapic_clockevent.max_delta_ns =
+			clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
+		lapic_clockevent.min_delta_ns =
+			clockevent_delta2ns(0xF, &lapic_clockevent);
+		lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
+		return 0;
+	}
+
 	local_irq_disable();
 
 	/* Replace the global interrupt handler */
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 4/8] x86/mrst: change clock selection logic to support medfield
  2010-05-07 17:41 [PATCH 0/8] Moorestown changes in arch/x86 for 35 merge window Jacob Pan
                   ` (2 preceding siblings ...)
  2010-05-07 17:41 ` [PATCH 3/8] x86/apic: allow use of lapic timer early calibration result Jacob Pan
@ 2010-05-07 17:41 ` Jacob Pan
  2010-05-11 14:36   ` Thomas Gleixner
  2010-05-07 17:41 ` [PATCH 5/8] x86/apbt: support more timer configurations on mrst Jacob Pan
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 49+ messages in thread
From: Jacob Pan @ 2010-05-07 17:41 UTC (permalink / raw)
  To: Thomas Gleixner, H. Peter Anvin, Ingo Molnar, Alek Du,
	Arjan van de Ven, Feng Tang, LKML
  Cc: Jacob Pan, Alek Du, Jacob Pan

From: Jacob Pan <jacob.jun.pan@intel.com>

Penwell has added always on lapic timers and tsc, we want to treat
it as a variant of moorestown so that one binary kernel can boot on both.
this patch added clock selction logic so that platform code can set up the
optimal configuration for both moorestown and medfield.

This patch will also mark Penwell TSC reliable, thus no need for
watchdog clocksource to monitor it.

Signed-off-by: Alek Du <alek.du@intel.com>
Signed-off-by: Jacob Pan <jacob.jun.pan@intel.com>
Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
---
 arch/x86/include/asm/mrst.h |   30 +++++++++++
 arch/x86/kernel/mrst.c      |  119 ++++++++++++++++++++++++++++++++++++++----
 2 files changed, 137 insertions(+), 12 deletions(-)

diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h
index 451d30e..3054407 100644
--- a/arch/x86/include/asm/mrst.h
+++ b/arch/x86/include/asm/mrst.h
@@ -11,7 +11,37 @@
 #ifndef _ASM_X86_MRST_H
 #define _ASM_X86_MRST_H
 extern int pci_mrst_init(void);
+extern unsigned int calibration_result;
+
 int __init sfi_parse_mrtc(struct sfi_table_header *table);
+extern int mrst_timer_options __cpuinitdata;
+extern int mrst_identify_cpu(void);
+
+/**
+ * Medfield is the follow-up of Moorestown, it combines two chip solution into
+ * one. Other than that it also added always-on and constant tsc and lapic
+ * timers. Medfield is the platform name, and the chip name is called Penwell
+ * we treat Medfield/Penwell as a variant of Moorestown. Penwell can be
+ * identified via MSRs.
+ */
+
+
+#define MRST_CPU_CHIP_LINCROFT	1
+#define MRST_CPU_CHIP_PENWELL	2
+
+#define PENWELL_FAMILY		0x20670
+
+/**
+ * Penwell uses spread spectrum clock, so the freq number is not exactly
+ * as reported by MSR.
+ */
+#define PENWELL_FSB_FREQ_83SKU         83200
+#define PENWELL_FSB_FREQ_100SKU        99840
+
+#define MRST_TIMER_DEFAULT	0
+#define MRST_TIMER_APBT_ONLY	1
+#define MRST_TIMER_LAPIC_APBT	2
+
 
 #define SFI_MTMR_MAX_NUM 8
 #define SFI_MRTC_MAX	8
diff --git a/arch/x86/kernel/mrst.c b/arch/x86/kernel/mrst.c
index 0aad867..9e14e7f 100644
--- a/arch/x86/kernel/mrst.c
+++ b/arch/x86/kernel/mrst.c
@@ -25,8 +25,32 @@
 #include <asm/i8259.h>
 #include <asm/apb_timer.h>
 
+/**
+ * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock,
+ * cmdline option x86_mrst_timer can be used to override the configuration
+ * to prefer one or the other.
+ * at runtime, there are basically three timer configurations:
+ * 1. per cpu apbt clock only
+ * 2. per cpu always-on lapic clocks only, this is Penwell/Medfield only
+ * 3. per cpu lapic clock (C3STOP) and one apbt clock, with broadcast.
+ *
+ * by default (without cmdline option), platform code first detects cpu type
+ * to see if we are on lincroft or penwell, then set up both lapic or apbt
+ * clocks accordingly.
+ * i.e. by default, medfield uses configuration #2, moorestown uses #1.
+ * config #3 is supported but not recommended on medfield.
+ *
+ * rating and feature summary:
+ * lapic (with C3STOP) --------- 100
+ * apbt (always-on) ------------ 110
+ * lapic (always-on,ARAT) ------ 150
+ */
+
+int mrst_timer_options __cpuinitdata;
+
 static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM];
 static struct sfi_timer_table_entry sfi_mtimer_array[SFI_MTMR_MAX_NUM];
+static u32 mrst_cpu_chip;
 int sfi_mtimer_num;
 
 struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX];
@@ -167,15 +191,16 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table)
 	return 0;
 }
 
-/*
- * the secondary clock in Moorestown can be APBT or LAPIC clock, default to
- * APBT but cmdline option can also override it.
- */
 static void __cpuinit mrst_setup_secondary_clock(void)
 {
-	/* restore default lapic clock if disabled by cmdline */
-	if (disable_apbt_percpu)
-		return setup_secondary_APIC_clock();
+	if ((mrst_timer_options == MRST_TIMER_APBT_ONLY))
+		return apbt_setup_secondary_clock();
+	if (cpu_has(&current_cpu_data, X86_FEATURE_ARAT)
+		||  (mrst_timer_options == MRST_TIMER_LAPIC_APBT)) {
+		pr_info("using lapic timers for secondary clock\n");
+		setup_secondary_APIC_clock();
+		return;
+	}
 	apbt_setup_secondary_clock();
 }
 
@@ -183,9 +208,45 @@ static unsigned long __init mrst_calibrate_tsc(void)
 {
 	unsigned long flags, fast_calibrate;
 
-	local_irq_save(flags);
-	fast_calibrate = apbt_quick_calibrate();
-	local_irq_restore(flags);
+	if (mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) {
+		u32 lo, hi, ratio, fsb;
+
+		rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+		pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
+		ratio = (hi >> 8) & 0x1f;
+		pr_debug("ratio is %d\n", ratio);
+		if (!ratio) {
+			pr_err("read a zero ratio, should be incorrect!\n");
+			pr_err("force tsc ratio to 16 ...\n");
+			ratio = 16;
+		}
+		rdmsr(MSR_FSB_FREQ, lo, hi);
+		if ((lo & 0x7) == 0x7)
+			fsb = PENWELL_FSB_FREQ_83SKU;
+		else
+			fsb = PENWELL_FSB_FREQ_100SKU;
+		fast_calibrate = ratio * fsb;
+		pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
+		calibration_result = fsb * 1000 / HZ;
+		/* mark tsc clocksource as reliable */
+		set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
+	} else {
+		/**
+		 * TODO: calibrate lapic timer with apbt, if we use apbt only,
+		 * there is no need to calibrate lapic timer, since they are
+		 * not used.
+		 * if we use lapic timers and apbt, the default calibration
+		 * should work, since we have the global clockevent setup.
+		 * but it would be more efficient if we combine the lapic timer
+		 * with tsc calibration.
+		 */
+		local_irq_save(flags);
+		fast_calibrate = apbt_quick_calibrate();
+		local_irq_restore(flags);
+	}
+
+	pr_info("tsc lapic calibration results %lu %d\n",
+			fast_calibrate, calibration_result);
 
 	if (fast_calibrate)
 		return fast_calibrate;
@@ -195,6 +256,11 @@ static unsigned long __init mrst_calibrate_tsc(void)
 
 void __init mrst_time_init(void)
 {
+	/* if cpu is penwell, lapic timer will be used by default */
+	if ((mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) &&
+		(mrst_timer_options == MRST_TIMER_DEFAULT))
+		return;
+
 	sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr);
 	pre_init_apic_IRQ0();
 	apbt_time_init();
@@ -211,11 +277,38 @@ void __init mrst_rtc_init(void)
  */
 static void __init mrst_setup_boot_clock(void)
 {
-	pr_info("%s: per cpu apbt flag %d \n", __func__, disable_apbt_percpu);
-	if (disable_apbt_percpu)
+	if (mrst_timer_options == MRST_TIMER_APBT_ONLY)
+		return;
+	if ((mrst_timer_options == MRST_TIMER_LAPIC_APBT)
+		|| (mrst_cpu_chip == MRST_CPU_CHIP_PENWELL))
 		setup_boot_APIC_clock();
 };
 
+enum cpuid_regs {
+	CR_EAX = 0,
+	CR_ECX,
+	CR_EDX,
+	CR_EBX
+};
+
+int mrst_identify_cpu(void)
+{
+	u32 regs[4];
+
+	cpuid(1, &regs[CR_EAX], &regs[CR_EBX], &regs[CR_ECX], &regs[CR_EDX]);
+	if ((regs[CR_EAX] & PENWELL_FAMILY) == PENWELL_FAMILY)
+		mrst_cpu_chip = MRST_CPU_CHIP_PENWELL;
+	else
+		mrst_cpu_chip = MRST_CPU_CHIP_LINCROFT;
+
+	pr_debug("cpuid result %x\n", regs[CR_EAX]);
+	pr_info("Moorestown CPU %s identified\n",
+		(mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) ?
+		"Lincroft" : "Penwell");
+
+	return mrst_cpu_chip;
+}
+
 /*
  * Moorestown specific x86_init function overrides and early setup
  * calls.
@@ -237,4 +330,6 @@ void __init x86_mrst_early_setup(void)
 	x86_init.pci.fixup_irqs = x86_init_noop;
 
 	legacy_pic = &null_legacy_pic;
+
+	mrst_identify_cpu();
 }
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 5/8] x86/apbt: support more timer configurations on mrst
  2010-05-07 17:41 [PATCH 0/8] Moorestown changes in arch/x86 for 35 merge window Jacob Pan
                   ` (3 preceding siblings ...)
  2010-05-07 17:41 ` [PATCH 4/8] x86/mrst: change clock selection logic to support medfield Jacob Pan
@ 2010-05-07 17:41 ` Jacob Pan
  2010-05-07 17:41 ` [PATCH 6/8] x86/platform: add a wallclock_init func to x86_platforms ops Jacob Pan
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 49+ messages in thread
From: Jacob Pan @ 2010-05-07 17:41 UTC (permalink / raw)
  To: Thomas Gleixner, H. Peter Anvin, Ingo Molnar, Alek Du,
	Arjan van de Ven, Feng Tang, LKML
  Cc: Jacob Pan, Jacob Pan

From: Jacob Pan <jacob.jun.pan@intel.com>

With the addition of Medfield as a follow-up of Moorestown, more timer
configurations are available to the kernel. This patch allows the
optimal default configuration to be chosen and overwritten by cmdline
as well.
i.e. For Moorestown, percpu APB timers are default. For Medfield local
always-on local APIC timers are default (w/o any platform timers).

Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
---
 arch/x86/include/asm/apb_timer.h |    2 +-
 arch/x86/kernel/apb_timer.c      |   18 ++++++++++--------
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/arch/x86/include/asm/apb_timer.h b/arch/x86/include/asm/apb_timer.h
index c74a2ee..4127fd1 100644
--- a/arch/x86/include/asm/apb_timer.h
+++ b/arch/x86/include/asm/apb_timer.h
@@ -55,7 +55,7 @@ extern unsigned long apbt_quick_calibrate(void);
 extern int arch_setup_apbt_irqs(int irq, int trigger, int mask, int cpu);
 extern void apbt_setup_secondary_clock(void);
 extern unsigned int boot_cpu_id;
-extern int disable_apbt_percpu;
+extern int mrst_timer_options;
 
 extern struct sfi_timer_table_entry *sfi_get_mtmr(int hint);
 extern void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr);
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c
index a353475..08dfbf8 100644
--- a/arch/x86/kernel/apb_timer.c
+++ b/arch/x86/kernel/apb_timer.c
@@ -43,10 +43,11 @@
 
 #include <asm/fixmap.h>
 #include <asm/apb_timer.h>
+#include <asm/mrst.h>
 
 #define APBT_MASK			CLOCKSOURCE_MASK(32)
 #define APBT_SHIFT			22
-#define APBT_CLOCKEVENT_RATING		150
+#define APBT_CLOCKEVENT_RATING		110
 #define APBT_CLOCKSOURCE_RATING		250
 #define APBT_MIN_DELTA_USEC		200
 
@@ -83,8 +84,6 @@ struct apbt_dev {
 	char name[10];
 };
 
-int disable_apbt_percpu __cpuinitdata;
-
 static DEFINE_PER_CPU(struct apbt_dev, cpu_apbt_dev);
 
 #ifdef CONFIG_SMP
@@ -204,9 +203,9 @@ static inline int __init setup_x86_mrst_timer(char *arg)
 		return -EINVAL;
 
 	if (strcmp("apbt_only", arg) == 0)
-		disable_apbt_percpu = 0;
+		mrst_timer_options = MRST_TIMER_APBT_ONLY;
 	else if (strcmp("lapic_and_apbt", arg) == 0)
-		disable_apbt_percpu = 1;
+		mrst_timer_options = MRST_TIMER_LAPIC_APBT;
 	else {
 		pr_warning("X86 MRST timer option %s not recognised"
 			   " use x86_mrst_timer=apbt_only or lapic_and_apbt\n",
@@ -335,7 +334,7 @@ static int __init apbt_clockevent_register(void)
 	adev->num = smp_processor_id();
 	memcpy(&adev->evt, &apbt_clockevent, sizeof(struct clock_event_device));
 
-	if (disable_apbt_percpu) {
+	if (mrst_timer_options == MRST_TIMER_LAPIC_APBT) {
 		apbt_clockevent.rating = APBT_CLOCKEVENT_RATING - 100;
 		global_clock_event = &adev->evt;
 		printk(KERN_DEBUG "%s clockevent registered as global\n",
@@ -429,7 +428,8 @@ static int apbt_cpuhp_notify(struct notifier_block *n,
 
 static __init int apbt_late_init(void)
 {
-	if (disable_apbt_percpu || !apb_timer_block_enabled)
+	if (mrst_timer_options == MRST_TIMER_LAPIC_APBT ||
+		!apb_timer_block_enabled)
 		return 0;
 	/* This notifier should be called after workqueue is ready */
 	hotcpu_notifier(apbt_cpuhp_notify, -20);
@@ -450,6 +450,8 @@ static void apbt_set_mode(enum clock_event_mode mode,
 	int timer_num;
 	struct apbt_dev *adev = EVT_TO_APBT_DEV(evt);
 
+	BUG_ON(!apbt_virt_address);
+
 	timer_num = adev->num;
 	pr_debug("%s CPU %d timer %d mode=%d\n",
 		 __func__, first_cpu(*evt->cpumask), timer_num, mode);
@@ -676,7 +678,7 @@ void __init apbt_time_init(void)
 	}
 #ifdef CONFIG_SMP
 	/* kernel cmdline disable apb timer, so we will use lapic timers */
-	if (disable_apbt_percpu) {
+	if (mrst_timer_options == MRST_TIMER_LAPIC_APBT) {
 		printk(KERN_INFO "apbt: disabled per cpu timer\n");
 		return;
 	}
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 6/8] x86/platform: add a wallclock_init func to x86_platforms ops
  2010-05-07 17:41 [PATCH 0/8] Moorestown changes in arch/x86 for 35 merge window Jacob Pan
                   ` (4 preceding siblings ...)
  2010-05-07 17:41 ` [PATCH 5/8] x86/apbt: support more timer configurations on mrst Jacob Pan
@ 2010-05-07 17:41 ` Jacob Pan
  2010-05-11 14:42   ` Thomas Gleixner
  2010-05-07 17:41 ` [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device Jacob Pan
  2010-05-07 17:41 ` [PATCH 8/8] x86/mrst: Add nop functions to x86_init mpparse functions Jacob Pan
  7 siblings, 1 reply; 49+ messages in thread
From: Jacob Pan @ 2010-05-07 17:41 UTC (permalink / raw)
  To: Thomas Gleixner, H. Peter Anvin, Ingo Molnar, Alek Du,
	Arjan van de Ven, Feng Tang, LKML
  Cc: Feng Tang, Jacob Pan

From: Feng Tang <feng.tang@intel.com>

Some wall clock devices use MMIO based HW register, this new function will
give them a chance to do some initialization work before their get/set_time
service get called.

Signed-off-by: Feng Tang <feng.tang@intel.com>
Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
---
 arch/x86/include/asm/x86_init.h |    2 ++
 arch/x86/kernel/setup.c         |    2 ++
 arch/x86/kernel/x86_init.c      |    2 ++
 3 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index 519b543..be027a8 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -138,6 +138,7 @@ struct x86_cpuinit_ops {
 /**
  * struct x86_platform_ops - platform specific runtime functions
  * @calibrate_tsc:		calibrate TSC
+ * @wallclock_init:		init the wallclock device
  * @get_wallclock:		get time from HW clock like RTC etc.
  * @set_wallclock:		set time back to HW clock
  * @is_untracked_pat_range	exclude from PAT logic
@@ -145,6 +146,7 @@ struct x86_cpuinit_ops {
  */
 struct x86_platform_ops {
 	unsigned long (*calibrate_tsc)(void);
+	void (*wallclock_init)(void);
 	unsigned long (*get_wallclock)(void);
 	int (*set_wallclock)(unsigned long nowtime);
 	void (*iommu_shutdown)(void);
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index c4851ef..d001d8c 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1050,6 +1050,8 @@ void __init setup_arch(char **cmdline_p)
 #endif
 	x86_init.oem.banner();
 
+	x86_platform.wallclock_init();
+
 	mcheck_init();
 }
 
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index 61a1e8c..ee00d76 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -24,6 +24,7 @@ void __init x86_init_uint_noop(unsigned int unused) { }
 void __init x86_init_pgd_noop(pgd_t *unused) { }
 int __init iommu_init_noop(void) { return 0; }
 void iommu_shutdown_noop(void) { }
+void wallclock_init_noop(void) { }
 
 /*
  * The platform setup functions are preset with the default functions
@@ -88,6 +89,7 @@ static void default_nmi_init(void) { };
 
 struct x86_platform_ops x86_platform = {
 	.calibrate_tsc			= native_calibrate_tsc,
+	.wallclock_init			= wallclock_init_noop,
 	.get_wallclock			= mach_get_cmos_time,
 	.set_wallclock			= mach_set_rtc_mmss,
 	.iommu_shutdown			= iommu_shutdown_noop,
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device
  2010-05-07 17:41 [PATCH 0/8] Moorestown changes in arch/x86 for 35 merge window Jacob Pan
                   ` (5 preceding siblings ...)
  2010-05-07 17:41 ` [PATCH 6/8] x86/platform: add a wallclock_init func to x86_platforms ops Jacob Pan
@ 2010-05-07 17:41 ` Jacob Pan
  2010-05-07 18:51   ` Joe Perches
  2010-05-11 14:57   ` Thomas Gleixner
  2010-05-07 17:41 ` [PATCH 8/8] x86/mrst: Add nop functions to x86_init mpparse functions Jacob Pan
  7 siblings, 2 replies; 49+ messages in thread
From: Jacob Pan @ 2010-05-07 17:41 UTC (permalink / raw)
  To: Thomas Gleixner, H. Peter Anvin, Ingo Molnar, Alek Du,
	Arjan van de Ven, Feng Tang, LKML
  Cc: Feng Tang, Jacob Pan

From: Feng Tang <feng.tang@intel.com>

Moorestown platform doesn't have a m146818 RTC device like traditional
x86 PC, but a firmware emulated virtual RTC device(vrtc), which provides
some basic RTC functions like get/set time. vrtc serves as the only
wall clock device on Moorestown platform.

Signed-off-by: Feng Tang <feng.tang@intel.com>
Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
---
 arch/x86/include/asm/fixmap.h |    4 ++
 arch/x86/include/asm/vrtc.h   |   27 +++++++++++
 arch/x86/kernel/Makefile      |    2 +-
 arch/x86/kernel/mrst.c        |   20 ++++++++
 arch/x86/kernel/vrtc.c        |  100 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 152 insertions(+), 1 deletions(-)
 create mode 100644 arch/x86/include/asm/vrtc.h
 create mode 100644 arch/x86/kernel/vrtc.c

diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index d07b44f..c4ba8d9 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -117,6 +117,10 @@ enum fixed_addresses {
 	FIX_TEXT_POKE1,	/* reserve 2 pages for text_poke() */
 	FIX_TEXT_POKE0, /* first page is last, because allocation is backward */
 	__end_of_permanent_fixed_addresses,
+
+#ifdef	CONFIG_X86_MRST
+	FIX_LNW_VRTC,
+#endif
 	/*
 	 * 256 temporary boot-time mappings, used by early_ioremap(),
 	 * before ioremap() is functional.
diff --git a/arch/x86/include/asm/vrtc.h b/arch/x86/include/asm/vrtc.h
new file mode 100644
index 0000000..4e40129
--- /dev/null
+++ b/arch/x86/include/asm/vrtc.h
@@ -0,0 +1,27 @@
+#ifndef _MRST_VRTC_H
+#define _MRST_VRTC_H
+
+#ifdef CONFIG_X86_MRST
+extern unsigned char vrtc_cmos_read(unsigned char reg);
+extern void vrtc_cmos_write(unsigned char val, unsigned char reg);
+extern unsigned long vrtc_get_time(void);
+extern int vrtc_set_mmss(unsigned long nowtime);
+extern void vrtc_set_base(void __iomem *base);
+
+#define MRST_VRTC_PGOFFSET  (0xc00)
+
+#else
+static inline unsigned char vrtc_cmos_read(unsigned char reg)
+{
+	return 0xff;
+}
+
+static inline void vrtc_cmos_write(unsigned char val, unsigned char reg)
+{
+	return;
+}
+#endif
+
+#define MRST_VRTC_MAP_SZ	(1024)
+
+#endif
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index e77b220..f3fdcbe 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -104,7 +104,7 @@ obj-$(CONFIG_SCx200)		+= scx200.o
 scx200-y			+= scx200_32.o
 
 obj-$(CONFIG_OLPC)		+= olpc.o
-obj-$(CONFIG_X86_MRST)		+= mrst.o
+obj-$(CONFIG_X86_MRST)		+= mrst.o vrtc.o
 
 microcode-y				:= microcode_core.o
 microcode-$(CONFIG_MICROCODE_INTEL)	+= microcode_intel.o
diff --git a/arch/x86/kernel/mrst.c b/arch/x86/kernel/mrst.c
index 9e14e7f..0b3ef9f 100644
--- a/arch/x86/kernel/mrst.c
+++ b/arch/x86/kernel/mrst.c
@@ -24,6 +24,7 @@
 #include <asm/io.h>
 #include <asm/i8259.h>
 #include <asm/apb_timer.h>
+#include <asm/vrtc.h>
 
 /**
  * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock,
@@ -268,7 +269,24 @@ void __init mrst_time_init(void)
 
 void __init mrst_rtc_init(void)
 {
+	unsigned long rtc_paddr;
+	void __iomem *virt_base;
+
 	sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
+	if (!sfi_mrtc_num)
+		return;
+
+	rtc_paddr = sfi_mrtc_array[0].phys_addr;
+
+	/* vRTC's register address may not be page aligned */
+	set_fixmap_nocache(FIX_LNW_VRTC, rtc_paddr);
+
+	virt_base = (void __iomem *)__fix_to_virt(FIX_LNW_VRTC);
+	virt_base += rtc_paddr & ~PAGE_MASK;
+	vrtc_set_base(virt_base);
+
+	x86_platform.get_wallclock = vrtc_get_time;
+	x86_platform.set_wallclock = vrtc_set_mmss;
 }
 
 /*
@@ -326,6 +344,8 @@ void __init x86_mrst_early_setup(void)
 	x86_cpuinit.setup_percpu_clockev = mrst_setup_secondary_clock;
 
 	x86_platform.calibrate_tsc = mrst_calibrate_tsc;
+	x86_platform.wallclock_init = mrst_rtc_init;
+
 	x86_init.pci.init = pci_mrst_init;
 	x86_init.pci.fixup_irqs = x86_init_noop;
 
diff --git a/arch/x86/kernel/vrtc.c b/arch/x86/kernel/vrtc.c
new file mode 100644
index 0000000..fa1eb63
--- /dev/null
+++ b/arch/x86/kernel/vrtc.c
@@ -0,0 +1,100 @@
+/*
+ * vrtc.c: Driver for virtual RTC device on Intel MID platform
+ *
+ * (C) Copyright 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * Note:
+ * VRTC is emulated by system controller firmware, the real HW
+ * RTC is located in the PMIC device. SCU FW shadows PMIC RTC
+ * in a memory mapped IO space that is visible to the host IA
+ * processor.
+ *
+ * This driver is based on RTC CMOS driver.
+ */
+
+#include <linux/kernel.h>
+
+#include <asm/vrtc.h>
+#include <asm/time.h>
+#include <asm/fixmap.h>
+
+static unsigned char __iomem *vrtc_virt_base;
+
+void vrtc_set_base(void __iomem *base)
+{
+	vrtc_virt_base = base;
+}
+
+unsigned char vrtc_cmos_read(unsigned char reg)
+{
+	unsigned char retval;
+
+	/* vRTC's registers range from 0x0 to 0xD */
+	if (reg > 0xd || !vrtc_virt_base)
+		return 0xff;
+
+	lock_cmos_prefix(reg);
+	retval = __raw_readb(vrtc_virt_base + (reg << 2));
+	lock_cmos_suffix(reg);
+	return retval;
+}
+EXPORT_SYMBOL(vrtc_cmos_read);
+
+void vrtc_cmos_write(unsigned char val, unsigned char reg)
+{
+	if (reg > 0xd || !vrtc_virt_base)
+		return;
+
+	lock_cmos_prefix(reg);
+	__raw_writeb(val, vrtc_virt_base + (reg << 2));
+	lock_cmos_suffix(reg);
+}
+EXPORT_SYMBOL(vrtc_cmos_write);
+
+unsigned long vrtc_get_time(void)
+{
+	u8 sec, min, hour, mday, mon;
+	u32 year;
+
+	while ((vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP))
+		cpu_relax();
+
+	sec = vrtc_cmos_read(RTC_SECONDS);
+	min = vrtc_cmos_read(RTC_MINUTES);
+	hour = vrtc_cmos_read(RTC_HOURS);
+	mday = vrtc_cmos_read(RTC_DAY_OF_MONTH);
+	mon = vrtc_cmos_read(RTC_MONTH);
+	year = vrtc_cmos_read(RTC_YEAR);
+
+	/* vRTC YEAR reg contains the offset to 1960 */
+	year += 1960;
+
+	printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d "
+		"mon: %d year: %d\n", sec, min, hour, mday, mon, year);
+
+	return mktime(year, mon, mday, hour, min, sec);
+}
+
+/* Only care about the minutes and seconds */
+int vrtc_set_mmss(unsigned long nowtime)
+{
+	int real_sec, real_min;
+	int vrtc_min;
+
+	vrtc_min = vrtc_cmos_read(RTC_MINUTES);
+
+	real_sec = nowtime % 60;
+	real_min = nowtime / 60;
+	if (((abs(real_min - vrtc_min) + 15)/30) & 1)
+		real_min += 30;
+	real_min %= 60;
+
+	vrtc_cmos_write(real_sec, RTC_SECONDS);
+	vrtc_cmos_write(real_min, RTC_MINUTES);
+	return 0;
+}
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 8/8] x86/mrst: Add nop functions to x86_init mpparse functions
  2010-05-07 17:41 [PATCH 0/8] Moorestown changes in arch/x86 for 35 merge window Jacob Pan
                   ` (6 preceding siblings ...)
  2010-05-07 17:41 ` [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device Jacob Pan
@ 2010-05-07 17:41 ` Jacob Pan
  7 siblings, 0 replies; 49+ messages in thread
From: Jacob Pan @ 2010-05-07 17:41 UTC (permalink / raw)
  To: Thomas Gleixner, H. Peter Anvin, Ingo Molnar, Alek Du,
	Arjan van de Ven, Feng Tang, LKML
  Cc: Jacob Pan

Moorestown does not have BIOS provided MP tables, we can save some time
by avoiding scaning of these tables. e.g.
[    0.000000] Scan SMP from c0000000 for 1024 bytes.
[    0.000000] Scan SMP from c009fc00 for 1024 bytes.
[    0.000000] Scan SMP from c00f0000 for 65536 bytes.
[    0.000000] Scan SMP from c00bfff0 for 1024 bytes.

Searching EBDA with the base at 0x40E will also result in random pointer
deferencing within 1MB. This can be a problem in Lincroft if the pointer
hits VGA area and VGA mode is not enabled.

Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
---
 arch/x86/kernel/mrst.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/mrst.c b/arch/x86/kernel/mrst.c
index 0b3ef9f..73c1692 100644
--- a/arch/x86/kernel/mrst.c
+++ b/arch/x86/kernel/mrst.c
@@ -351,5 +351,9 @@ void __init x86_mrst_early_setup(void)
 
 	legacy_pic = &null_legacy_pic;
 
+	/* Avoid searching for BIOS MP tables */
+	x86_init.mpparse.find_smp_config = x86_init_noop;
+	x86_init.mpparse.get_smp_config = x86_init_uint_noop;
+
 	mrst_identify_cpu();
 }
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* Re: [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device
  2010-05-07 17:41 ` [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device Jacob Pan
@ 2010-05-07 18:51   ` Joe Perches
  2010-05-07 19:02     ` Alan Cox
  2010-05-11 14:57   ` Thomas Gleixner
  1 sibling, 1 reply; 49+ messages in thread
From: Joe Perches @ 2010-05-07 18:51 UTC (permalink / raw)
  To: Jacob Pan
  Cc: Thomas Gleixner, H. Peter Anvin, Ingo Molnar, Alek Du,
	Arjan van de Ven, Feng Tang, LKML

On Fri, 2010-05-07 at 10:41 -0700, Jacob Pan wrote: 
> +	printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d "
> +	"mon: %d year: %d\n", sec, min, hour, mday, mon, year);
> +

Even though many of the rtc drivers print this way, it seems
a very backwards way of presenting time to me.

I think "yyyy-mm-dd hh:mm:ss" is a better representation, more
compact and readable.

Also KERN_INFO may not be good, maybe KERN_DEBUG or pr_debug?


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device
  2010-05-07 18:51   ` Joe Perches
@ 2010-05-07 19:02     ` Alan Cox
  2010-05-07 19:06       ` Joe Perches
  0 siblings, 1 reply; 49+ messages in thread
From: Alan Cox @ 2010-05-07 19:02 UTC (permalink / raw)
  To: Joe Perches
  Cc: Jacob Pan, Thomas Gleixner, H. Peter Anvin, Ingo Molnar, Alek Du,
	Arjan van de Ven, Feng Tang, LKML

On Fri, 07 May 2010 11:51:06 -0700
Joe Perches <joe@perches.com> wrote:

> On Fri, 2010-05-07 at 10:41 -0700, Jacob Pan wrote: 
> > +	printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d "
> > +	"mon: %d year: %d\n", sec, min, hour, mday, mon, year);
> > +
> 
> Even though many of the rtc drivers print this way, it seems
> a very backwards way of presenting time to me.

Consistency is really more important here IMHO - lots of drivers have set
an existing policy.


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device
  2010-05-07 19:02     ` Alan Cox
@ 2010-05-07 19:06       ` Joe Perches
  2010-05-07 19:56         ` H. Peter Anvin
  0 siblings, 1 reply; 49+ messages in thread
From: Joe Perches @ 2010-05-07 19:06 UTC (permalink / raw)
  To: Alan Cox, Alessandro Zummo
  Cc: Jacob Pan, Thomas Gleixner, H. Peter Anvin, Ingo Molnar, Alek Du,
	Arjan van de Ven, Feng Tang, LKML

On Fri, 2010-05-07 at 20:02 +0100, Alan Cox wrote:
> On Fri, 07 May 2010 11:51:06 -0700
> Joe Perches <joe@perches.com> wrote:
> > On Fri, 2010-05-07 at 10:41 -0700, Jacob Pan wrote: 
> > > +	printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d "
> > > +	"mon: %d year: %d\n", sec, min, hour, mday, mon, year);
> > Even though many of the rtc drivers print this way, it seems
> > a very backwards way of presenting time to me.
> Consistency is really more important here IMHO - lots of drivers have set
> an existing policy.

(added Alessandro Zummo to cc's)

look at drivers/rtc.

All of them seem to use a templated copy/paste dev_dbg,
which seems to point to a use for a possible common rtc_util.c
or some such where this could be standardized.
 
Is there somewhere else this style is used?


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device
  2010-05-07 19:06       ` Joe Perches
@ 2010-05-07 19:56         ` H. Peter Anvin
  2010-05-10  9:17           ` Feng Tang
  0 siblings, 1 reply; 49+ messages in thread
From: H. Peter Anvin @ 2010-05-07 19:56 UTC (permalink / raw)
  To: Joe Perches
  Cc: Alan Cox, Alessandro Zummo, Jacob Pan, Thomas Gleixner,
	Ingo Molnar, Alek Du, Arjan van de Ven, Feng Tang, LKML

On 05/07/2010 12:06 PM, Joe Perches wrote:
> On Fri, 2010-05-07 at 20:02 +0100, Alan Cox wrote:
>> On Fri, 07 May 2010 11:51:06 -0700
>> Joe Perches <joe@perches.com> wrote:
>>> On Fri, 2010-05-07 at 10:41 -0700, Jacob Pan wrote: 
>>>> +	printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d "
>>>> +	"mon: %d year: %d\n", sec, min, hour, mday, mon, year);
>>> Even though many of the rtc drivers print this way, it seems
>>> a very backwards way of presenting time to me.
>> Consistency is really more important here IMHO - lots of drivers have set
>> an existing policy.
> 
> (added Alessandro Zummo to cc's)
> 
> look at drivers/rtc.
> 
> All of them seem to use a templated copy/paste dev_dbg,
> which seems to point to a use for a possible common rtc_util.c
> or some such where this could be standardized.
>  
> Is there somewhere else this style is used?
> 

Probably the right thing to do is to (a) move all this printing to
common code; (b) change to ISO 8601 format.

	-hpa


^ permalink raw reply	[flat|nested] 49+ messages in thread

* RFD: Should we remove the HLT check?  (was Re: [PATCH 1/8] x86: avoid check hlt if no timer interrupts)
  2010-05-07 17:41 ` [PATCH 1/8] x86: avoid check hlt if no timer interrupts Jacob Pan
@ 2010-05-07 20:32   ` H. Peter Anvin
  2010-05-07 20:33     ` Arjan van de Ven
  0 siblings, 1 reply; 49+ messages in thread
From: H. Peter Anvin @ 2010-05-07 20:32 UTC (permalink / raw)
  To: Jacob Pan
  Cc: Thomas Gleixner, Ingo Molnar, Alek Du, Arjan van de Ven,
	Feng Tang, LKML, Jacob Pan, Linus Torvalds, Arjan van de Ven

On 05/07/2010 10:41 AM, Jacob Pan wrote:
> From: Jacob Pan <jacob.jun.pan@intel.com>
> 
> check hlt requires external timer interrupt to wake up the
> cpu. for platforms equipped with only per cpu timers, we don't
> have external interrupts during check hlt.
> this patch checks such condition to avoid kernel hang at hlt.
> it also saves boot time in that hlt four times in the current code
> requires four ticks to break out of them.
> 
> Signed-off-by: Jacob Pan <jacob.jun.pan@intel.com>
> Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
> ---
>  arch/x86/include/asm/bugs.h |    1 +
>  arch/x86/kernel/cpu/bugs.c  |    4 ++++
>  2 files changed, 5 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/x86/include/asm/bugs.h b/arch/x86/include/asm/bugs.h
> index 08abf63..1e0cef8 100644
> --- a/arch/x86/include/asm/bugs.h
> +++ b/arch/x86/include/asm/bugs.h
> @@ -2,6 +2,7 @@
>  #define _ASM_X86_BUGS_H
>  
>  extern void check_bugs(void);
> +extern struct clock_event_device *global_clock_event;
>  
>  #if defined(CONFIG_CPU_SUP_INTEL) && defined(CONFIG_X86_32)
>  int ppro_with_ram_bug(void);
> diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
> index 01a2652..c0d9688 100644
> --- a/arch/x86/kernel/cpu/bugs.c
> +++ b/arch/x86/kernel/cpu/bugs.c
> @@ -90,6 +90,10 @@ static void __init check_hlt(void)
>  		return;
>  
>  	printk(KERN_INFO "Checking 'hlt' instruction... ");
> +	if (!global_clock_event) {
> +		printk(KERN_CONT "no clockevent to wake up, skipped.\n");
> +		return;
> +	}
>  	if (!boot_cpu_data.hlt_works_ok) {
>  		printk("disabled\n");
>  		return;

I really wish I knew the exact systems affected by the HLT bug.  If I
remember correctly, it was some 386 systems -- or possibly 486 systems
as well -- a very long time ago.  This test just provides a diagnosis if
the system really is bad (it hangs with an obvious message) at the cost
of some 40 ms to the system boot time.  I suspect C1 (HLT) being broken
is not anywhere close to the predominant power management problem in the
current day, and as such I'm wondering if this particular test hasn't
outlived its usefulness.

Thoughts?

	-hpa


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: RFD: Should we remove the HLT check?  (was Re: [PATCH 1/8] x86: avoid check hlt if no timer interrupts)
  2010-05-07 20:32   ` RFD: Should we remove the HLT check? (was Re: [PATCH 1/8] x86: avoid check hlt if no timer interrupts) H. Peter Anvin
@ 2010-05-07 20:33     ` Arjan van de Ven
  2010-05-07 20:36       ` H. Peter Anvin
  2010-05-07 20:54       ` Linus Torvalds
  0 siblings, 2 replies; 49+ messages in thread
From: Arjan van de Ven @ 2010-05-07 20:33 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Jacob Pan, Thomas Gleixner, Ingo Molnar, Alek Du, Feng Tang,
	LKML, Jacob Pan, Linus Torvalds, Arjan van de Ven

On 5/7/2010 13:32, H. Peter Anvin wrote:
>
> I really wish I knew the exact systems affected by the HLT bug.  If I
> remember correctly, it was some 386 systems -- or possibly 486 systems
> as well -- a very long time ago.  This test just provides a diagnosis if
> the system really is bad (it hangs with an obvious message) at the cost
> of some 40 ms to the system boot time.  I suspect C1 (HLT) being broken
> is not anywhere close to the predominant power management problem in the
> current day, and as such I'm wondering if this particular test hasn't
> outlived its usefulness.
>
> Thoughts?

we could at least hide it behind the "don't run on pentium or newer" config options..

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: RFD: Should we remove the HLT check?  (was Re: [PATCH 1/8] x86: avoid check hlt if no timer interrupts)
  2010-05-07 20:33     ` Arjan van de Ven
@ 2010-05-07 20:36       ` H. Peter Anvin
  2010-05-07 22:24         ` Alan Cox
  2010-05-07 20:54       ` Linus Torvalds
  1 sibling, 1 reply; 49+ messages in thread
From: H. Peter Anvin @ 2010-05-07 20:36 UTC (permalink / raw)
  To: Arjan van de Ven
  Cc: Jacob Pan, Thomas Gleixner, Ingo Molnar, Alek Du, Feng Tang,
	LKML, Jacob Pan, Linus Torvalds, Arjan van de Ven

On 05/07/2010 01:33 PM, Arjan van de Ven wrote:
> On 5/7/2010 13:32, H. Peter Anvin wrote:
>>
>> I really wish I knew the exact systems affected by the HLT bug.  If I
>> remember correctly, it was some 386 systems -- or possibly 486 systems
>> as well -- a very long time ago.  This test just provides a diagnosis if
>> the system really is bad (it hangs with an obvious message) at the cost
>> of some 40 ms to the system boot time.  I suspect C1 (HLT) being broken
>> is not anywhere close to the predominant power management problem in the
>> current day, and as such I'm wondering if this particular test hasn't
>> outlived its usefulness.
>>
>> Thoughts?
> 
> we could at least hide it behind the "don't run on pentium or newer" config options..

I'd be cool skipping it for family 5 or newer.  I'm just wondering if we
should kill it completely -- IIRC it was only a handful of 386/486
systems which had problems, usually due to marginal power supplies which
couldn't handle the noise of a variable load (DOS not having any power
management would run at a reliable 100% load) -- that's not exactly the
type of systems which would have survived to modern day.

	-hpa


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: RFD: Should we remove the HLT check?  (was Re: [PATCH 1/8] x86: avoid check hlt if no timer interrupts)
  2010-05-07 20:33     ` Arjan van de Ven
  2010-05-07 20:36       ` H. Peter Anvin
@ 2010-05-07 20:54       ` Linus Torvalds
  2010-05-07 21:04         ` H. Peter Anvin
  1 sibling, 1 reply; 49+ messages in thread
From: Linus Torvalds @ 2010-05-07 20:54 UTC (permalink / raw)
  To: Arjan van de Ven
  Cc: H. Peter Anvin, Jacob Pan, Thomas Gleixner, Ingo Molnar, Alek Du,
	Feng Tang, LKML, Jacob Pan, Arjan van de Ven



On Fri, 7 May 2010, Arjan van de Ven wrote:

> On 5/7/2010 13:32, H. Peter Anvin wrote:
> > 
> > I really wish I knew the exact systems affected by the HLT bug.  If I
> > remember correctly, it was some 386 systems -- or possibly 486 systems
> > as well -- a very long time ago.  This test just provides a diagnosis if
> > the system really is bad (it hangs with an obvious message) at the cost
> > of some 40 ms to the system boot time.  I suspect C1 (HLT) being broken
> > is not anywhere close to the predominant power management problem in the
> > current day, and as such I'm wondering if this particular test hasn't
> > outlived its usefulness.
> > 
> > Thoughts?
> 
> we could at least hide it behind the "don't run on pentium or newer" config
> options..

Ack. That would take care of all relevant machines.

		Linus

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: RFD: Should we remove the HLT check?  (was Re: [PATCH 1/8] x86: avoid check hlt if no timer interrupts)
  2010-05-07 20:54       ` Linus Torvalds
@ 2010-05-07 21:04         ` H. Peter Anvin
  2010-05-07 22:07           ` jacob pan
  0 siblings, 1 reply; 49+ messages in thread
From: H. Peter Anvin @ 2010-05-07 21:04 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Arjan van de Ven, Jacob Pan, Thomas Gleixner, Ingo Molnar,
	Alek Du, Feng Tang, LKML, Jacob Pan, Arjan van de Ven

On 05/07/2010 01:54 PM, Linus Torvalds wrote:
> 
> 
> On Fri, 7 May 2010, Arjan van de Ven wrote:
> 
>> On 5/7/2010 13:32, H. Peter Anvin wrote:
>>>
>>> I really wish I knew the exact systems affected by the HLT bug.  If I
>>> remember correctly, it was some 386 systems -- or possibly 486 systems
>>> as well -- a very long time ago.  This test just provides a diagnosis if
>>> the system really is bad (it hangs with an obvious message) at the cost
>>> of some 40 ms to the system boot time.  I suspect C1 (HLT) being broken
>>> is not anywhere close to the predominant power management problem in the
>>> current day, and as such I'm wondering if this particular test hasn't
>>> outlived its usefulness.
>>>
>>> Thoughts?
>>
>> we could at least hide it behind the "don't run on pentium or newer" config
>> options..
> 
> Ack. That would take care of all relevant machines.
> 

Sounds like a plan.  Jacob, do you want to submit a new patch (bypassing
this check if boot_cpu_info.x86 >= 5)?

	-hpa


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: RFD: Should we remove the HLT check?  (was Re: [PATCH 1/8] x86: avoid check hlt if no timer interrupts)
  2010-05-07 21:04         ` H. Peter Anvin
@ 2010-05-07 22:07           ` jacob pan
  0 siblings, 0 replies; 49+ messages in thread
From: jacob pan @ 2010-05-07 22:07 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Linus Torvalds, Arjan van de Ven, Thomas Gleixner, Ingo Molnar,
	Alek Du, Feng Tang, LKML, Jacob Pan, Arjan van de Ven


>Sounds like a plan.  Jacob, do you want to submit a new patch (bypassing
>this check if boot_cpu_info.x86 >= 5)?
>
>	-hpa
>
Just sent out the updated patch. I guess you meant boot_cpu_data instead of boot_cpu_info.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: RFD: Should we remove the HLT check?  (was Re: [PATCH 1/8] x86: avoid check hlt if no timer interrupts)
  2010-05-07 20:36       ` H. Peter Anvin
@ 2010-05-07 22:24         ` Alan Cox
  2010-05-07 22:27           ` H. Peter Anvin
  2010-05-07 22:35           ` Arjan van de Ven
  0 siblings, 2 replies; 49+ messages in thread
From: Alan Cox @ 2010-05-07 22:24 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Arjan van de Ven, Jacob Pan, Thomas Gleixner, Ingo Molnar,
	Alek Du, Feng Tang, LKML, Jacob Pan, Linus Torvalds,
	Arjan van de Ven

> I'd be cool skipping it for family 5 or newer.  I'm just wondering if we
> should kill it completely -- IIRC it was only a handful of 386/486
> systems which had problems, usually due to marginal power supplies which
> couldn't handle the noise of a variable load (DOS not having any power
> management would run at a reliable 100% load) -- that's not exactly the
> type of systems which would have survived to modern day.

Also SMM and hardware bugs on some platforms - Cyrix MediaGX 5510 for
example where a hlt at the wrong moment during ATA transfers hung the box
until power cycle. But all old old stuff.

Alan

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: RFD: Should we remove the HLT check?  (was Re: [PATCH 1/8] x86: avoid check hlt if no timer interrupts)
  2010-05-07 22:24         ` Alan Cox
@ 2010-05-07 22:27           ` H. Peter Anvin
  2010-05-07 22:46             ` Alan Cox
  2010-05-07 22:35           ` Arjan van de Ven
  1 sibling, 1 reply; 49+ messages in thread
From: H. Peter Anvin @ 2010-05-07 22:27 UTC (permalink / raw)
  To: Alan Cox
  Cc: Arjan van de Ven, Jacob Pan, Thomas Gleixner, Ingo Molnar,
	Alek Du, Feng Tang, LKML, Jacob Pan, Linus Torvalds,
	Arjan van de Ven

On 05/07/2010 03:24 PM, Alan Cox wrote:
>> I'd be cool skipping it for family 5 or newer.  I'm just wondering if we
>> should kill it completely -- IIRC it was only a handful of 386/486
>> systems which had problems, usually due to marginal power supplies which
>> couldn't handle the noise of a variable load (DOS not having any power
>> management would run at a reliable 100% load) -- that's not exactly the
>> type of systems which would have survived to modern day.
> 
> Also SMM and hardware bugs on some platforms - Cyrix MediaGX 5510 for
> example where a hlt at the wrong moment during ATA transfers hung the box
> until power cycle. But all old old stuff.

I think family < 5 seems a reasonable cutoff.

Note that the ATA transfer bug you describe above would not be caught by
the existing check.

	-hpa


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: RFD: Should we remove the HLT check?  (was Re: [PATCH 1/8] x86: avoid check hlt if no timer interrupts)
  2010-05-07 22:24         ` Alan Cox
  2010-05-07 22:27           ` H. Peter Anvin
@ 2010-05-07 22:35           ` Arjan van de Ven
  1 sibling, 0 replies; 49+ messages in thread
From: Arjan van de Ven @ 2010-05-07 22:35 UTC (permalink / raw)
  To: Alan Cox
  Cc: H. Peter Anvin, Jacob Pan, Thomas Gleixner, Ingo Molnar, Alek Du,
	Feng Tang, LKML, Jacob Pan, Linus Torvalds

On 5/7/2010 15:24, Alan Cox wrote:
>> I'd be cool skipping it for family 5 or newer.  I'm just wondering if we
>> should kill it completely -- IIRC it was only a handful of 386/486
>> systems which had problems, usually due to marginal power supplies which
>> couldn't handle the noise of a variable load (DOS not having any power
>> management would run at a reliable 100% load) -- that's not exactly the
>> type of systems which would have survived to modern day.
>
> Also SMM and hardware bugs on some platforms - Cyrix MediaGX 5510 for
> example where a hlt at the wrong moment during ATA transfers hung the box
> until power cycle. But all old old stuff.

but a boot time "does hlt work at all" check won't catch that.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: RFD: Should we remove the HLT check?  (was Re: [PATCH 1/8] x86: avoid check hlt if no timer interrupts)
  2010-05-07 22:27           ` H. Peter Anvin
@ 2010-05-07 22:46             ` Alan Cox
  0 siblings, 0 replies; 49+ messages in thread
From: Alan Cox @ 2010-05-07 22:46 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Arjan van de Ven, Jacob Pan, Thomas Gleixner, Ingo Molnar,
	Alek Du, Feng Tang, LKML, Jacob Pan, Linus Torvalds,
	Arjan van de Ven

On Fri, 07 May 2010 15:27:34 -0700
"H. Peter Anvin" <hpa@zytor.com> wrote:

> On 05/07/2010 03:24 PM, Alan Cox wrote:
> >> I'd be cool skipping it for family 5 or newer.  I'm just wondering if we
> >> should kill it completely -- IIRC it was only a handful of 386/486
> >> systems which had problems, usually due to marginal power supplies which
> >> couldn't handle the noise of a variable load (DOS not having any power
> >> management would run at a reliable 100% load) -- that's not exactly the
> >> type of systems which would have survived to modern day.
> > 
> > Also SMM and hardware bugs on some platforms - Cyrix MediaGX 5510 for
> > example where a hlt at the wrong moment during ATA transfers hung the box
> > until power cycle. But all old old stuff.
> 
> I think family < 5 seems a reasonable cutoff.
> 
> Note that the ATA transfer bug you describe above would not be caught by
> the existing check.

MediaGX5510 would I'm pretty certain be 486 reporting anyway

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device
  2010-05-07 19:56         ` H. Peter Anvin
@ 2010-05-10  9:17           ` Feng Tang
  2010-05-10 18:22             ` H. Peter Anvin
  0 siblings, 1 reply; 49+ messages in thread
From: Feng Tang @ 2010-05-10  9:17 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Joe Perches, Alan Cox, Alessandro Zummo, Jacob Pan,
	Thomas Gleixner, Ingo Molnar, Du, Alek, Arjan van de Ven, LKML

On Sat, 8 May 2010 03:56:09 +0800
"H. Peter Anvin" <hpa@zytor.com> wrote:


> > 
> 
> Probably the right thing to do is to (a) move all this printing to
> common code; (b) change to ISO 8601 format.
> 
> 	-hpa
> 

Thank you all for the comments. please review this follow-on patch.

- Feng
--
diff --git a/arch/x86/kernel/vrtc.c b/arch/x86/kernel/vrtc.c
index fa1eb63..0fbd74d 100644
--- a/arch/x86/kernel/vrtc.c
+++ b/arch/x86/kernel/vrtc.c
@@ -74,8 +74,8 @@ unsigned long vrtc_get_time(void)
 	/* vRTC YEAR reg contains the offset to 1960 */
 	year += 1960;
 
-	printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d "
-		"mon: %d year: %d\n", sec, min, hour, mday, mon, year);
+	pr_debug("vrtc time: %4d-%02d-%02d %02d:%02d:%02d\n",
+		year, mon, mday, hour, min, sec);
 
 	return mktime(year, mon, mday, hour, min, sec);
 }

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* Re: [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device
  2010-05-10  9:17           ` Feng Tang
@ 2010-05-10 18:22             ` H. Peter Anvin
  2010-05-11  2:30               ` Feng Tang
  0 siblings, 1 reply; 49+ messages in thread
From: H. Peter Anvin @ 2010-05-10 18:22 UTC (permalink / raw)
  To: Feng Tang
  Cc: Joe Perches, Alan Cox, Alessandro Zummo, Jacob Pan,
	Thomas Gleixner, Ingo Molnar, Du, Alek, Arjan van de Ven, LKML

On 05/10/2010 02:17 AM, Feng Tang wrote:
> 
> Thank you all for the comments. please review this follow-on patch.
> 
> - Feng

That doesn't move it to common code, though.  I'd rather see existing
common style used, then merged (centralized) and *then* the style corrected.

	-hpa

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device
  2010-05-10 18:22             ` H. Peter Anvin
@ 2010-05-11  2:30               ` Feng Tang
  0 siblings, 0 replies; 49+ messages in thread
From: Feng Tang @ 2010-05-11  2:30 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Joe Perches, Alan Cox, Alessandro Zummo, Jacob Pan,
	Thomas Gleixner, Ingo Molnar, Du, Alek, Arjan van de Ven, LKML

On Tue, 11 May 2010 02:22:15 +0800
"H. Peter Anvin" <hpa@zytor.com> wrote:

> On 05/10/2010 02:17 AM, Feng Tang wrote:
> > 
> > Thank you all for the comments. please review this follow-on patch.
> > 
> > - Feng
> 
> That doesn't move it to common code, though.  I'd rather see existing
> common style used, then merged (centralized) and *then* the style
> corrected.
> 
> 	-hpa

Hi Peter,

The reason I didn't move it to rtc common code is, this vrtc.c sits in
arch/x86/kernel/ and better not to depend on drivers/rtc, as drivers/rtc
may not be always enabled in kernel configuration.

I also have another general driver for vrtc which will be in drivers/rtc/,
just like general x86 kernel which has a rtc.c in arch/ and a rtc-cmos.c
in drivers/rtc, I will clean my code up and try to move these funcs to a
common code. 

Thanks,
Feng

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 3/8] x86/apic: allow use of lapic timer early calibration result
  2010-05-07 17:41 ` [PATCH 3/8] x86/apic: allow use of lapic timer early calibration result Jacob Pan
@ 2010-05-11 13:46   ` Thomas Gleixner
  2010-05-11 19:42     ` Pan, Jacob jun
  0 siblings, 1 reply; 49+ messages in thread
From: Thomas Gleixner @ 2010-05-11 13:46 UTC (permalink / raw)
  To: Jacob Pan
  Cc: H. Peter Anvin, Ingo Molnar, Alek Du, Arjan van de Ven,
	Feng Tang, LKML, Jacob Pan

On Fri, 7 May 2010, Jacob Pan wrote:

> From: Jacob Pan <jacob.jun.pan@intel.com>
> 
> lapic timer calibration can be combined with tsc in platform specific
> calibration functions. if such calibration result is obtained early,
> we can skip the redundent calibration loops.

I'd rather move lapic calibration into TSC calibration in general as
we do the same thing twice for no good reason.

That needs some code restructuring, but that's worth it.

> Signed-off-by: Jacob Pan <jacob.jun.pan@intel.com>
> Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>

Hehe. So you handed the patch to yourself :)

> ---
>  arch/x86/kernel/apic/apic.c |   21 ++++++++++++++++++++-
>  1 files changed, 20 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
> index e5a4a1e..8ef56ac 100644
> --- a/arch/x86/kernel/apic/apic.c
> +++ b/arch/x86/kernel/apic/apic.c
> @@ -175,7 +175,7 @@ static struct resource lapic_resource = {
>  	.flags = IORESOURCE_MEM | IORESOURCE_BUSY,
>  };
>  
> -static unsigned int calibration_result;
> +unsigned int calibration_result;

Aside of my general objection it'd be not a good idea to make this
global w/o renaming it to something sensible like
lapic_timer_frequency.
  
>  static int lapic_next_event(unsigned long delta,
>  			    struct clock_event_device *evt);
> @@ -597,6 +597,25 @@ static int __init calibrate_APIC_clock(void)
>  	long delta, deltatsc;
>  	int pm_referenced = 0;
>  
> +	/**
> +	 * check if lapic timer has already been calibrated by platform
> +	 * specific routine, such as tsc calibration code. if so, we just fill
> +	 * in the clockevent structure and return.
> +	 */
> +	if (calibration_result) {
> +		apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n",
> +				calibration_result);
> +		lapic_clockevent.mult = div_sc(calibration_result/APIC_DIVISOR,
> +					TICK_NSEC, lapic_clockevent.shift);
> +		lapic_clockevent.max_delta_ns =
> +			clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
> +		lapic_clockevent.min_delta_ns =
> +			clockevent_delta2ns(0xF, &lapic_clockevent);
> +		lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
> +		return 0;

  Grr. I hate duplicated code.

> +	}
> +
>  	local_irq_disable();
>  
>  	/* Replace the global interrupt handler */
> -- 
> 1.6.3.3
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 4/8] x86/mrst: change clock selection logic to support medfield
  2010-05-07 17:41 ` [PATCH 4/8] x86/mrst: change clock selection logic to support medfield Jacob Pan
@ 2010-05-11 14:36   ` Thomas Gleixner
  2010-05-11 15:30     ` Alan Cox
                       ` (3 more replies)
  0 siblings, 4 replies; 49+ messages in thread
From: Thomas Gleixner @ 2010-05-11 14:36 UTC (permalink / raw)
  To: Jacob Pan
  Cc: H. Peter Anvin, Ingo Molnar, Alek Du, Arjan van de Ven,
	Feng Tang, LKML, Jacob Pan

On Fri, 7 May 2010, Jacob Pan wrote:

> From: Jacob Pan <jacob.jun.pan@intel.com>
> 
> Penwell has added always on lapic timers and tsc, we want to treat
> it as a variant of moorestown so that one binary kernel can boot on both.
> this patch added clock selction logic so that platform code can set up the
> optimal configuration for both moorestown and medfield.
> 
> This patch will also mark Penwell TSC reliable, thus no need for
> watchdog clocksource to monitor it.
> 
> Signed-off-by: Alek Du <alek.du@intel.com>
> Signed-off-by: Jacob Pan <jacob.jun.pan@intel.com>
> Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
> ---
>  arch/x86/include/asm/mrst.h |   30 +++++++++++
>  arch/x86/kernel/mrst.c      |  119 ++++++++++++++++++++++++++++++++++++++----
>  2 files changed, 137 insertions(+), 12 deletions(-)
> 
> diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h
> index 451d30e..3054407 100644
> --- a/arch/x86/include/asm/mrst.h
> +++ b/arch/x86/include/asm/mrst.h
> @@ -11,7 +11,37 @@
>  #ifndef _ASM_X86_MRST_H
>  #define _ASM_X86_MRST_H
>  extern int pci_mrst_init(void);
> +extern unsigned int calibration_result;

Yuck, why is this in a mrst specific header ?

> +
> +#define MRST_TIMER_DEFAULT	0
> +#define MRST_TIMER_APBT_ONLY	1
> +#define MRST_TIMER_LAPIC_APBT	2

enum please, also 

> +/**
> + * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock,
> + * cmdline option x86_mrst_timer can be used to override the configuration
> + * to prefer one or the other.
> + * at runtime, there are basically three timer configurations:
> + * 1. per cpu apbt clock only
> + * 2. per cpu always-on lapic clocks only, this is Penwell/Medfield only
> + * 3. per cpu lapic clock (C3STOP) and one apbt clock, with broadcast.
> + *
> + * by default (without cmdline option), platform code first detects cpu type
> + * to see if we are on lincroft or penwell, then set up both lapic or apbt
> + * clocks accordingly.
> + * i.e. by default, medfield uses configuration #2, moorestown uses #1.
> + * config #3 is supported but not recommended on medfield.
> + *
> + * rating and feature summary:
> + * lapic (with C3STOP) --------- 100
> + * apbt (always-on) ------------ 110

 apbt sucks performance wise, so why do you consider it a better
 choice than lapic + broadcast ?

> + * lapic (always-on,ARAT) ------ 150
> + */
> +
> +int mrst_timer_options __cpuinitdata;
> +
>  static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM];
>  static struct sfi_timer_table_entry sfi_mtimer_array[SFI_MTMR_MAX_NUM];
> +static u32 mrst_cpu_chip;
>  int sfi_mtimer_num;
>  
>  struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX];
> @@ -167,15 +191,16 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table)
>  	return 0;
>  }
>  
> -/*
> - * the secondary clock in Moorestown can be APBT or LAPIC clock, default to
> - * APBT but cmdline option can also override it.
> - */
>  static void __cpuinit mrst_setup_secondary_clock(void)
>  {
> -	/* restore default lapic clock if disabled by cmdline */
> -	if (disable_apbt_percpu)
> -		return setup_secondary_APIC_clock();
> +	if ((mrst_timer_options == MRST_TIMER_APBT_ONLY))
> +		return apbt_setup_secondary_clock();
> +	if (cpu_has(&current_cpu_data, X86_FEATURE_ARAT)
> +		||  (mrst_timer_options == MRST_TIMER_LAPIC_APBT)) {
> +		pr_info("using lapic timers for secondary clock\n");
> +		setup_secondary_APIC_clock();
> +		return;

  The logic is confusing. 

> +	}
>  	apbt_setup_secondary_clock();
>  }
>  
> @@ -183,9 +208,45 @@ static unsigned long __init mrst_calibrate_tsc(void)
>  {
>  	unsigned long flags, fast_calibrate;
>  
> -	local_irq_save(flags);
> -	fast_calibrate = apbt_quick_calibrate();
> -	local_irq_restore(flags);
> +	if (mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) {
> +		u32 lo, hi, ratio, fsb;
> +
> +		rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
> +		pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
> +		ratio = (hi >> 8) & 0x1f;
> +		pr_debug("ratio is %d\n", ratio);
> +		if (!ratio) {
> +			pr_err("read a zero ratio, should be incorrect!\n");
> +			pr_err("force tsc ratio to 16 ...\n");
> +			ratio = 16;
> +		}

 This is not Penwell specific at all. The ratio can be read out on all
 Core based CPUs either from MSR_PLATFORM_ID[12:8] or
 MSR_PERF_STAT[44:40] depending on XE operation enabled
 (MSR_PERF_STAT[31] == 1)

 This should be made general available and not burried into the mrst
 code.

> +		rdmsr(MSR_FSB_FREQ, lo, hi);
> +		if ((lo & 0x7) == 0x7)
> +			fsb = PENWELL_FSB_FREQ_83SKU;
> +		else
> +			fsb = PENWELL_FSB_FREQ_100SKU;

 I guess the 111 is Penwell/MRST specific, right ?

 According to SDM we have anyway different results for the various CPU
 families, but we should utilize this in a generic way and have the
 translation tables for the various CPUs in one place.

> +		fast_calibrate = ratio * fsb;
> +		pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
> +		calibration_result = fsb * 1000 / HZ;
> +		/* mark tsc clocksource as reliable */
> +		set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
> +	} else {
> +		/**
> +		 * TODO: calibrate lapic timer with apbt, if we use apbt only,
> +		 * there is no need to calibrate lapic timer, since they are
> +		 * not used.
> +		 * if we use lapic timers and apbt, the default calibration
> +		 * should work, since we have the global clockevent setup.
> +		 * but it would be more efficient if we combine the lapic timer
> +		 * with tsc calibration.
> +		 */
> +		local_irq_save(flags);
> +		fast_calibrate = apbt_quick_calibrate();
> +		local_irq_restore(flags);
> +	}
> +
> +	pr_info("tsc lapic calibration results %lu %d\n",
> +			fast_calibrate, calibration_result);
>  
>  	if (fast_calibrate)
>  		return fast_calibrate;
> @@ -195,6 +256,11 @@ static unsigned long __init mrst_calibrate_tsc(void)
>  
>  void __init mrst_time_init(void)
>  {
> +	/* if cpu is penwell, lapic timer will be used by default */
> +	if ((mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) &&
> +		(mrst_timer_options == MRST_TIMER_DEFAULT))
> +		return;
> +
>  	sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr);
>  	pre_init_apic_IRQ0();
>  	apbt_time_init();
> @@ -211,11 +277,38 @@ void __init mrst_rtc_init(void)
>   */
>  static void __init mrst_setup_boot_clock(void)
>  {
> -	pr_info("%s: per cpu apbt flag %d \n", __func__, disable_apbt_percpu);
> -	if (disable_apbt_percpu)
> +	if (mrst_timer_options == MRST_TIMER_APBT_ONLY)
> +		return;
> +	if ((mrst_timer_options == MRST_TIMER_LAPIC_APBT)
> +		|| (mrst_cpu_chip == MRST_CPU_CHIP_PENWELL))
>  		setup_boot_APIC_clock();
>  };
>  
> +enum cpuid_regs {
> +	CR_EAX = 0,
> +	CR_ECX,
> +	CR_EDX,
> +	CR_EBX
> +};
> +
> +int mrst_identify_cpu(void)
> +{
> +	u32 regs[4];
> +
> +	cpuid(1, &regs[CR_EAX], &regs[CR_EBX], &regs[CR_ECX], &regs[CR_EDX]);

  Yikes. From which Intel cookbook is this ?

  Aside of that we have that info in boot_cpu_info already, don't we ?
  So there is neither a requirement for the extra cpuid call nor for
  the extra mrst_cpu_chip id magic.

> +	if ((regs[CR_EAX] & PENWELL_FAMILY) == PENWELL_FAMILY)
> +		mrst_cpu_chip = MRST_CPU_CHIP_PENWELL;
> +	else
> +		mrst_cpu_chip = MRST_CPU_CHIP_LINCROFT;


> +	pr_debug("cpuid result %x\n", regs[CR_EAX]);
> +	pr_info("Moorestown CPU %s identified\n",
> +		(mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) ?
> +		"Lincroft" : "Penwell");

  Are we going to add one of those for each new family ? This is
  really redundant bloat with no value.

> +	return mrst_cpu_chip;
> +}
> +
>  /*
>   * Moorestown specific x86_init function overrides and early setup
>   * calls.
> @@ -237,4 +330,6 @@ void __init x86_mrst_early_setup(void)
>  	x86_init.pci.fixup_irqs = x86_init_noop;
>  
>  	legacy_pic = &null_legacy_pic;
> +
> +	mrst_identify_cpu();
>  }
> -- 
> 1.6.3.3
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 6/8] x86/platform: add a wallclock_init func to x86_platforms ops
  2010-05-07 17:41 ` [PATCH 6/8] x86/platform: add a wallclock_init func to x86_platforms ops Jacob Pan
@ 2010-05-11 14:42   ` Thomas Gleixner
  0 siblings, 0 replies; 49+ messages in thread
From: Thomas Gleixner @ 2010-05-11 14:42 UTC (permalink / raw)
  To: Jacob Pan
  Cc: H. Peter Anvin, Ingo Molnar, Alek Du, Arjan van de Ven, Feng Tang, LKML

On Fri, 7 May 2010, Jacob Pan wrote:

> From: Feng Tang <feng.tang@intel.com>
> 
> Some wall clock devices use MMIO based HW register, this new function will
> give them a chance to do some initialization work before their get/set_time
> service get called.
> 
> Signed-off-by: Feng Tang <feng.tang@intel.com>
> Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
> ---
>  arch/x86/include/asm/x86_init.h |    2 ++
>  arch/x86/kernel/setup.c         |    2 ++
>  arch/x86/kernel/x86_init.c      |    2 ++
>  3 files changed, 6 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
> index 519b543..be027a8 100644
> --- a/arch/x86/include/asm/x86_init.h
> +++ b/arch/x86/include/asm/x86_init.h
> @@ -138,6 +138,7 @@ struct x86_cpuinit_ops {
>  /**
>   * struct x86_platform_ops - platform specific runtime functions
>   * @calibrate_tsc:		calibrate TSC
> + * @wallclock_init:		init the wallclock device


  wallclock_init is an init function and should be in x86_init.timers

>   * @get_wallclock:		get time from HW clock like RTC etc.
>   * @set_wallclock:		set time back to HW clock
>   * @is_untracked_pat_range	exclude from PAT logic
> @@ -145,6 +146,7 @@ struct x86_cpuinit_ops {
>   */
>  struct x86_platform_ops {
>  	unsigned long (*calibrate_tsc)(void);
> +	void (*wallclock_init)(void);
>  	unsigned long (*get_wallclock)(void);
>  	int (*set_wallclock)(unsigned long nowtime);
>  	void (*iommu_shutdown)(void);
> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
> index c4851ef..d001d8c 100644
> --- a/arch/x86/kernel/setup.c
> +++ b/arch/x86/kernel/setup.c
> @@ -1050,6 +1050,8 @@ void __init setup_arch(char **cmdline_p)
>  #endif
>  	x86_init.oem.banner();
>  
> +	x86_platform.wallclock_init();
> +
>  	mcheck_init();
>  }
>  
> diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
> index 61a1e8c..ee00d76 100644
> --- a/arch/x86/kernel/x86_init.c
> +++ b/arch/x86/kernel/x86_init.c
> @@ -24,6 +24,7 @@ void __init x86_init_uint_noop(unsigned int unused) { }
>  void __init x86_init_pgd_noop(pgd_t *unused) { }
>  int __init iommu_init_noop(void) { return 0; }
>  void iommu_shutdown_noop(void) { }
> +void wallclock_init_noop(void) { }

No need for that.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device
  2010-05-07 17:41 ` [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device Jacob Pan
  2010-05-07 18:51   ` Joe Perches
@ 2010-05-11 14:57   ` Thomas Gleixner
  2010-05-12  2:34     ` Feng Tang
  1 sibling, 1 reply; 49+ messages in thread
From: Thomas Gleixner @ 2010-05-11 14:57 UTC (permalink / raw)
  To: Jacob Pan
  Cc: H. Peter Anvin, Ingo Molnar, Alek Du, Arjan van de Ven, Feng Tang, LKML

On Fri, 7 May 2010, Jacob Pan wrote:
> --- /dev/null
> +++ b/arch/x86/include/asm/vrtc.h
> @@ -0,0 +1,27 @@
> +#ifndef _MRST_VRTC_H
> +#define _MRST_VRTC_H
> +
> +#ifdef CONFIG_X86_MRST
> +extern unsigned char vrtc_cmos_read(unsigned char reg);
> +extern void vrtc_cmos_write(unsigned char val, unsigned char reg);
> +extern unsigned long vrtc_get_time(void);
> +extern int vrtc_set_mmss(unsigned long nowtime);
> +extern void vrtc_set_base(void __iomem *base);
> +
> +#define MRST_VRTC_PGOFFSET  (0xc00)
> +
> +#else

  Errm. That's a MRST specific header and nothing outside of MRST is
  using it. So why the #ifdef CONFIG_X86_MRST and the inline functions
  in the #else path ?

> +static inline unsigned char vrtc_cmos_read(unsigned char reg)
> +{
> +	return 0xff;
> +}
> +
 
>  /**
>   * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock,
> @@ -268,7 +269,24 @@ void __init mrst_time_init(void)
>  
>  void __init mrst_rtc_init(void)
>  {
> +	unsigned long rtc_paddr;
> +	void __iomem *virt_base;
> +
>  	sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
> +	if (!sfi_mrtc_num)
> +		return;
> +
> +	rtc_paddr = sfi_mrtc_array[0].phys_addr;
> +
> +	/* vRTC's register address may not be page aligned */
> +	set_fixmap_nocache(FIX_LNW_VRTC, rtc_paddr);

Why do we need a fixmap for that ? There is no need to setup RTC that
early. The first call is from timekeeping_init() 

Also this RTC init code should be in vrtc.c

> +
> +static unsigned char __iomem *vrtc_virt_base;
> +
> +void vrtc_set_base(void __iomem *base)
> +{
> +	vrtc_virt_base = base;
> +}
> +
> +unsigned char vrtc_cmos_read(unsigned char reg)
> +{
> +	unsigned char retval;
> +
> +	/* vRTC's registers range from 0x0 to 0xD */
> +	if (reg > 0xd || !vrtc_virt_base)
> +		return 0xff;
> +
> +	lock_cmos_prefix(reg);

  This lock_cmos magic should just die. I have no idea why something
  wants or wanted to access the RTC from an NMI.

> +	retval = __raw_readb(vrtc_virt_base + (reg << 2));
> +	lock_cmos_suffix(reg);
> +	return retval;
> +}
> +EXPORT_SYMBOL(vrtc_cmos_read);
> +
> +void vrtc_cmos_write(unsigned char val, unsigned char reg)
> +{
> +	if (reg > 0xd || !vrtc_virt_base)
> +		return;
> +
> +	lock_cmos_prefix(reg);
> +	__raw_writeb(val, vrtc_virt_base + (reg << 2));
> +	lock_cmos_suffix(reg);
> +}
> +EXPORT_SYMBOL(vrtc_cmos_write);
> +
> +unsigned long vrtc_get_time(void)
> +{
> +	u8 sec, min, hour, mday, mon;
> +	u32 year;
> +
> +	while ((vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP))
> +		cpu_relax();
> +
> +	sec = vrtc_cmos_read(RTC_SECONDS);
> +	min = vrtc_cmos_read(RTC_MINUTES);
> +	hour = vrtc_cmos_read(RTC_HOURS);
> +	mday = vrtc_cmos_read(RTC_DAY_OF_MONTH);
> +	mon = vrtc_cmos_read(RTC_MONTH);
> +	year = vrtc_cmos_read(RTC_YEAR);
> +
> +	/* vRTC YEAR reg contains the offset to 1960 */
> +	year += 1960;
> +
> +	printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d "
> +		"mon: %d year: %d\n", sec, min, hour, mday, mon, year);

  Please remove the debug noise

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 4/8] x86/mrst: change clock selection logic to support medfield
  2010-05-11 14:36   ` Thomas Gleixner
@ 2010-05-11 15:30     ` Alan Cox
  2010-05-11 15:50       ` Thomas Gleixner
  2010-05-13 22:16     ` Pan, Jacob jun
                       ` (2 subsequent siblings)
  3 siblings, 1 reply; 49+ messages in thread
From: Alan Cox @ 2010-05-11 15:30 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Jacob Pan, H. Peter Anvin, Ingo Molnar, Alek Du,
	Arjan van de Ven, Feng Tang, LKML, Jacob Pan

> > +	pr_debug("cpuid result %x\n", regs[CR_EAX]);
> > +	pr_info("Moorestown CPU %s identified\n",
> > +		(mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) ?
> > +		"Lincroft" : "Penwell");
> 
>   Are we going to add one of those for each new family ? This is
>   really redundant bloat with no value.
> 
> > +	return mrst_cpu_chip;

>From the driver side we need this value determined and visible to the
drivers because some things like the IPC interface need to know rather
than getting the cpuid magic replicated around.


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 4/8] x86/mrst: change clock selection logic to support medfield
  2010-05-11 15:30     ` Alan Cox
@ 2010-05-11 15:50       ` Thomas Gleixner
  2010-05-11 16:03         ` Alan Cox
  0 siblings, 1 reply; 49+ messages in thread
From: Thomas Gleixner @ 2010-05-11 15:50 UTC (permalink / raw)
  To: Alan Cox
  Cc: Jacob Pan, H. Peter Anvin, Ingo Molnar, Alek Du,
	Arjan van de Ven, Feng Tang, LKML, Jacob Pan

On Tue, 11 May 2010, Alan Cox wrote:

> > > +	pr_debug("cpuid result %x\n", regs[CR_EAX]);
> > > +	pr_info("Moorestown CPU %s identified\n",
> > > +		(mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) ?
> > > +		"Lincroft" : "Penwell");
> > 
> >   Are we going to add one of those for each new family ? This is
> >   really redundant bloat with no value.
> > 
> > > +	return mrst_cpu_chip;
> 
> From the driver side we need this value determined and visible to the
> drivers because some things like the IPC interface need to know rather
> than getting the cpuid magic replicated around.

Ok. That makes sense. Is there more what MRST drivers need to know ?

Thanks,

	tglx


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 4/8] x86/mrst: change clock selection logic to support medfield
  2010-05-11 15:50       ` Thomas Gleixner
@ 2010-05-11 16:03         ` Alan Cox
  0 siblings, 0 replies; 49+ messages in thread
From: Alan Cox @ 2010-05-11 16:03 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Jacob Pan, H. Peter Anvin, Ingo Molnar, Alek Du,
	Arjan van de Ven, Feng Tang, LKML, Jacob Pan

On Tue, 11 May 2010 17:50:28 +0200 (CEST)
Thomas Gleixner <tglx@linutronix.de> wrote:

> On Tue, 11 May 2010, Alan Cox wrote:
> 
> > > > +	pr_debug("cpuid result %x\n", regs[CR_EAX]);
> > > > +	pr_info("Moorestown CPU %s identified\n",
> > > > +		(mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) ?
> > > > +		"Lincroft" : "Penwell");
> > > 
> > >   Are we going to add one of those for each new family ? This is
> > >   really redundant bloat with no value.
> > > 
> > > > +	return mrst_cpu_chip;
> > 
> > From the driver side we need this value determined and visible to the
> > drivers because some things like the IPC interface need to know rather
> > than getting the cpuid magic replicated around.
> 
> Ok. That makes sense. Is there more what MRST drivers need to know ?

At some point they will need to know what platform they are booting on, I
have a possible patch for that which just exposes the boot loader value
but I'm not sure what the final direction on that will be.

For CPU they need to know which CPU type as it affects some bits like the
message formats in use. Probably that means the mrst_cpu_type enum or
function should have an enum value of 0 which means "Not a moorestown
device".


^ permalink raw reply	[flat|nested] 49+ messages in thread

* RE: [PATCH 3/8] x86/apic: allow use of lapic timer early calibration result
  2010-05-11 13:46   ` Thomas Gleixner
@ 2010-05-11 19:42     ` Pan, Jacob jun
  2010-05-11 19:50       ` Thomas Gleixner
  0 siblings, 1 reply; 49+ messages in thread
From: Pan, Jacob jun @ 2010-05-11 19:42 UTC (permalink / raw)
  To: Thomas Gleixner, Jacob Pan
  Cc: H. Peter Anvin, Ingo Molnar, Du, Alek, Arjan van de Ven, Tang,
	Feng, LKML

Thanks for the review.

> >
> > lapic timer calibration can be combined with tsc in platform specific
> > calibration functions. if such calibration result is obtained early,
> > we can skip the redundent calibration loops.
> 
> I'd rather move lapic calibration into TSC calibration in general as
> we do the same thing twice for no good reason.
> 
> That needs some code restructuring, but that's worth it.
> 
I am trying to avoid the risks of completely remove the current lapic 
calibration code since there are so many platforms with different timer
options. And I don't understand things like why pm timer is preferred.
Why not use the rating in clocksource?

> > Signed-off-by: Jacob Pan <jacob.jun.pan@intel.com>
> > Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
> 
> Hehe. So you handed the patch to yourself :)
> 
> > ---
> >  arch/x86/kernel/apic/apic.c |   21 ++++++++++++++++++++-
> >  1 files changed, 20 insertions(+), 1 deletions(-)
> >
> > diff --git a/arch/x86/kernel/apic/apic.c
> b/arch/x86/kernel/apic/apic.c
> > index e5a4a1e..8ef56ac 100644
> > --- a/arch/x86/kernel/apic/apic.c
> > +++ b/arch/x86/kernel/apic/apic.c
> > @@ -175,7 +175,7 @@ static struct resource lapic_resource = {
> >  	.flags = IORESOURCE_MEM | IORESOURCE_BUSY,
> >  };
> >
> > -static unsigned int calibration_result;
> > +unsigned int calibration_result;
> 
> Aside of my general objection it'd be not a good idea to make this
> global w/o renaming it to something sensible like
> lapic_timer_frequency.
> 
perhaps, the calibration data can directly be assigned to lapic timer
clock_event_device.mult? There is no need for the device specific result
scale (e.g. bus clocks per tick)

> >  static int lapic_next_event(unsigned long delta,
> >  			    struct clock_event_device *evt);
> > @@ -597,6 +597,25 @@ static int __init calibrate_APIC_clock(void)
> >  	long delta, deltatsc;
> >  	int pm_referenced = 0;
> >
> > +	/**
> > +	 * check if lapic timer has already been calibrated by platform
> > +	 * specific routine, such as tsc calibration code. if so, we just
> fill
> > +	 * in the clockevent structure and return.
> > +	 */
> > +	if (calibration_result) {
> > +		apic_printk(APIC_VERBOSE, "lapic timer already calibrated
> %d\n",
> > +				calibration_result);
> > +		lapic_clockevent.mult =
> div_sc(calibration_result/APIC_DIVISOR,
> > +					TICK_NSEC, lapic_clockevent.shift);
> > +		lapic_clockevent.max_delta_ns =
> > +			clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
> > +		lapic_clockevent.min_delta_ns =
> > +			clockevent_delta2ns(0xF, &lapic_clockevent);
> > +		lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
> > +		return 0;
> 
>   Grr. I hate duplicated code.
> 
> > +	}
> > +
> >  	local_irq_disable();
> >
> >  	/* Replace the global interrupt handler */
> > --
> > 1.6.3.3
> >

^ permalink raw reply	[flat|nested] 49+ messages in thread

* RE: [PATCH 3/8] x86/apic: allow use of lapic timer early calibration result
  2010-05-11 19:42     ` Pan, Jacob jun
@ 2010-05-11 19:50       ` Thomas Gleixner
  2010-05-11 20:46         ` Pan, Jacob jun
  0 siblings, 1 reply; 49+ messages in thread
From: Thomas Gleixner @ 2010-05-11 19:50 UTC (permalink / raw)
  To: Pan, Jacob jun
  Cc: Jacob Pan, H. Peter Anvin, Ingo Molnar, Du, Alek,
	Arjan van de Ven, Tang, Feng, LKML

Jacob,

On Tue, 11 May 2010, Pan, Jacob jun wrote:

> Thanks for the review.
> 
> > >
> > > lapic timer calibration can be combined with tsc in platform specific
> > > calibration functions. if such calibration result is obtained early,
> > > we can skip the redundent calibration loops.
> > 
> > I'd rather move lapic calibration into TSC calibration in general as
> > we do the same thing twice for no good reason.
> > 
> > That needs some code restructuring, but that's worth it.
> > 
> I am trying to avoid the risks of completely remove the current lapic 
> calibration code since there are so many platforms with different timer
> options. And I don't understand things like why pm timer is preferred.
> Why not use the rating in clocksource?

We do not have access to the clocksource at that point. But we do a
calibration loop for TSC and for lapic timer. There is no reason why
we can't do that in one go.
 
> > Aside of my general objection it'd be not a good idea to make this
> > global w/o renaming it to something sensible like
> > lapic_timer_frequency.
> > 
> perhaps, the calibration data can directly be assigned to lapic timer
> clock_event_device.mult? There is no need for the device specific result
> scale (e.g. bus clocks per tick)

No. That needs an accessor function.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 49+ messages in thread

* RE: [PATCH 3/8] x86/apic: allow use of lapic timer early calibration result
  2010-05-11 19:50       ` Thomas Gleixner
@ 2010-05-11 20:46         ` Pan, Jacob jun
  2010-05-11 20:51           ` H. Peter Anvin
  0 siblings, 1 reply; 49+ messages in thread
From: Pan, Jacob jun @ 2010-05-11 20:46 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Jacob Pan, H. Peter Anvin, Ingo Molnar, Du, Alek,
	Arjan van de Ven, Tang, Feng, LKML

> 
> We do not have access to the clocksource at that point. But we do a
> calibration loop for TSC and for lapic timer. There is no reason why
> we can't do that in one go.
> 
I have a simple patch that uses HPET to calibrate both tsc and lapic timers in one
loop in native_calibrate_tsc(). Will send out for RFC.

The question I have is the reference clock used for calibrating those local timers,
PIT, HPET, PM timer how should they be ranked. Can we make those known freq
clocksource devices available at this point so that we can use the clocksource
abstraction and its ranking automatically?


> > > Aside of my general objection it'd be not a good idea to make this
> > > global w/o renaming it to something sensible like
> > > lapic_timer_frequency.
> > >
> > perhaps, the calibration data can directly be assigned to lapic timer
> > clock_event_device.mult? There is no need for the device specific
> result
> > scale (e.g. bus clocks per tick)
> 
> No. That needs an accessor function.
> 
Agreed, so you are ok with bypassing the existing calibration_result variable and use .mult
to carry the result?


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 3/8] x86/apic: allow use of lapic timer early calibration result
  2010-05-11 20:46         ` Pan, Jacob jun
@ 2010-05-11 20:51           ` H. Peter Anvin
  0 siblings, 0 replies; 49+ messages in thread
From: H. Peter Anvin @ 2010-05-11 20:51 UTC (permalink / raw)
  To: Pan, Jacob jun
  Cc: Thomas Gleixner, Jacob Pan, Ingo Molnar, Du, Alek,
	Arjan van de Ven, Tang, Feng, LKML

On 05/11/2010 01:46 PM, Pan, Jacob jun wrote:
> 
> The question I have is the reference clock used for calibrating those local timers,
> PIT, HPET, PM timer how should they be ranked. Can we make those known freq
> clocksource devices available at this point so that we can use the clocksource
> abstraction and its ranking automatically?
> 

Personally I'd rank the PMTMR first, then HPET, then PIT, just based on
the relative complexity and relative known bugginess of the various
implementations.

The PMTMRs main defect is that it can't generate an interrupt; it's just
a dumb counter.

	-hpa

-- 
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device
  2010-05-11 14:57   ` Thomas Gleixner
@ 2010-05-12  2:34     ` Feng Tang
  2010-05-17  9:15       ` Thomas Gleixner
  0 siblings, 1 reply; 49+ messages in thread
From: Feng Tang @ 2010-05-12  2:34 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Jacob Pan, H. Peter Anvin, Ingo Molnar, Du, Alek, Arjan van de Ven, LKML

Hi Thomas,

Thanks for the great comments!


On Tue, 11 May 2010 22:57:44 +0800
Thomas Gleixner <tglx@linutronix.de> wrote:

> > +extern int vrtc_set_mmss(unsigned long nowtime);
> > +extern void vrtc_set_base(void __iomem *base);
> > +
> > +#define MRST_VRTC_PGOFFSET  (0xc00)
> > +
> > +#else
> 
>   Errm. That's a MRST specific header and nothing outside of MRST is
>   using it. So why the #ifdef CONFIG_X86_MRST and the inline functions
>   in the #else path ?

My bad not mentioning there is another rtc-mrst.c which will sit in drivers/rtc,
it will use some of the functions listed here. It will be posted later.

vrtc.c/rtc-mrst.c is similar with the rtc.c/rtc-cmos.c in general x86 PCs, as
drivers/rtc may not always be enabled in kernel, vrtc.c need sit in arch/x86
to provide the get/set_time service, while rtc-mrst.c will serve general rtc
subsystem

> >  void __init mrst_rtc_init(void)
> >  {
> > +	unsigned long rtc_paddr;
> > +	void __iomem *virt_base;
> > +
> >  	sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
> > +	if (!sfi_mrtc_num)
> > +		return;
> > +
> > +	rtc_paddr = sfi_mrtc_array[0].phys_addr;
> > +
> > +	/* vRTC's register address may not be page aligned */
> > +	set_fixmap_nocache(FIX_LNW_VRTC, rtc_paddr);
> 
> Why do we need a fixmap for that ? There is no need to setup RTC that
> early. The first call is from timekeeping_init() 

Actually when to init the vrtc register is a big problem for me, vrtc
need be inited before timekeeping_init(), and I thought better to put it
somewhere in setup_arch(), as it is architecture specific, and ioremap
is not working at that time. Also that's the reason I created a new
wallclock_init func for x86_platforms, I could not find a better way
to do the vrtc init.

> 
> Also this RTC init code should be in vrtc.c
I agree I should move this init code to vrtc.c, but still think it should
be called in the setup_arch() than in start_kernel()

> 
> > +
> > +static unsigned char __iomem *vrtc_virt_base;
> > +
> > +void vrtc_set_base(void __iomem *base)
> > +{
> > +	vrtc_virt_base = base;
> > +}
> > +
> > +unsigned char vrtc_cmos_read(unsigned char reg)
> > +{
> > +	unsigned char retval;
> > +
> > +	/* vRTC's registers range from 0x0 to 0xD */
> > +	if (reg > 0xd || !vrtc_virt_base)
> > +		return 0xff;
> > +
> > +	lock_cmos_prefix(reg);
> 
>   This lock_cmos magic should just die. I have no idea why something
>   wants or wanted to access the RTC from an NMI.

I will try to reuse the rtc_lock defined in rtc.c whose get/set_time
service won't be called with vrtc's at the same time.

> > +	/* vRTC YEAR reg contains the offset to 1960 */
> > +	year += 1960;
> > +
> > +	printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d "
> > +		"mon: %d year: %d\n", sec, min, hour, mday, mon,
> > year);
> 
>   Please remove the debug noise

Will make it a pr_debug.

Thanks,
Feng

^ permalink raw reply	[flat|nested] 49+ messages in thread

* RE: [PATCH 4/8] x86/mrst: change clock selection logic to support medfield
  2010-05-11 14:36   ` Thomas Gleixner
  2010-05-11 15:30     ` Alan Cox
@ 2010-05-13 22:16     ` Pan, Jacob jun
  2010-05-17  2:14     ` Du, Alek
  2010-05-17  2:27     ` Du, Alek
  3 siblings, 0 replies; 49+ messages in thread
From: Pan, Jacob jun @ 2010-05-13 22:16 UTC (permalink / raw)
  To: Thomas Gleixner, Jacob Pan
  Cc: H. Peter Anvin, Ingo Molnar, Du, Alek, Arjan van de Ven, Tang,
	Feng, LKML

sorry for the late reply, we are working on the fixes. just to give some answers to your comments.

> 
>  apbt sucks performance wise, so why do you consider it a better
>  choice than lapic + broadcast ?
> 
apbt is always-on, I guess depends on the load, it can be better than
having broadcast timers. e.g. if there are frequency transitions
between C0 to deep C states. if we are always in c0, I can easily see
native performance impact with per cpu apbt. I don't have power number
to backup either cases. ftrace shows programming lapic timer is quite
expensive, I don't understand.


 1)               |          clockevents_program_event() {
 1)               |            lapic_next_event() {
 1)   2.947 us    |              native_apic_mem_write();
 1)   8.682 us    |            }
 1) + 14.676 us   |          }

 0)               |                  clockevents_program_event() {
 0)   4.146 us    |                    apbt_next_event();
 0)   9.910 us    |                  }


> > + * lapic (always-on,ARAT) ------ 150
> > + */
> > +
> > +int mrst_timer_options __cpuinitdata;
> > +
> >  static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM];
> >  static struct sfi_timer_table_entry
> sfi_mtimer_array[SFI_MTMR_MAX_NUM];
> > +static u32 mrst_cpu_chip;
> >  int sfi_mtimer_num;
> >
> >  struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX];
> > @@ -167,15 +191,16 @@ int __init sfi_parse_mrtc(struct
> sfi_table_header *table)
> >  	return 0;
> >  }
> >
> > -/*
> > - * the secondary clock in Moorestown can be APBT or LAPIC clock,
> default to
> > - * APBT but cmdline option can also override it.
> > - */
> >  static void __cpuinit mrst_setup_secondary_clock(void)
> >  {
> > -	/* restore default lapic clock if disabled by cmdline */
> > -	if (disable_apbt_percpu)
> > -		return setup_secondary_APIC_clock();
> > +	if ((mrst_timer_options == MRST_TIMER_APBT_ONLY))
> > +		return apbt_setup_secondary_clock();
> > +	if (cpu_has(&current_cpu_data, X86_FEATURE_ARAT)
> > +		||  (mrst_timer_options == MRST_TIMER_LAPIC_APBT)) {
> > +		pr_info("using lapic timers for secondary clock\n");
> > +		setup_secondary_APIC_clock();
> > +		return;
> 
>   The logic is confusing.
> 
it can be more straightforward if we don't allow user cmdline
overwrite.

>  I guess the 111 is Penwell/MRST specific, right ?
> 
>  According to SDM we have anyway different results for the various CPU
>  families, but we should utilize this in a generic way and have the
>  translation tables for the various CPUs in one place.
agreed. 111b is Penwell specific 83MHz spread spectrum


> 
>   Yikes. From which Intel cookbook is this ?
> 
>   Aside of that we have that info in boot_cpu_info already, don't we ?
>   So there is neither a requirement for the extra cpuid call nor for
>   the extra mrst_cpu_chip id magic.
> 
initially, I thought we need this before boot_cpu_data is initialized.
But we actually don't need it early. I will fix that.


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 4/8] x86/mrst: change clock selection logic to support medfield
  2010-05-11 14:36   ` Thomas Gleixner
  2010-05-11 15:30     ` Alan Cox
  2010-05-13 22:16     ` Pan, Jacob jun
@ 2010-05-17  2:14     ` Du, Alek
  2010-05-17  2:27     ` Du, Alek
  3 siblings, 0 replies; 49+ messages in thread
From: Du, Alek @ 2010-05-17  2:14 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Jacob Pan, H. Peter Anvin, Ingo Molnar, Arjan van de Ven, Tang,
	Feng, LKML, Pan, Jacob jun

Hi tglx,

Please help to review this patch, it is against the latest patches Jacob sent out:
Basically the idea is to put bus_ratio and fsb in cpuinfo_x86 structure, and the
CPU early_init_intel function will fill the info.

>From 5ae648b2f18778df4eb3f1916a98971332482544 Mon Sep 17 00:00:00 2001
From: Jacob Pan <jacob.jun.pan@linux.intel.com>
Date: Fri, 14 May 2010 13:45:46 -0700
Subject: [PATCH 1/2] x86/mrst: Auto detect freq for local timers

Some Intel CPUs can directly get fsb frequency and bus ratio from
various MSRs. This patch enables this feature and benefit Medfield
platform.

Signed-off-by: Alek Du <alek.du@intel.com>
Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
---
 arch/x86/include/asm/processor.h |    3 +++
 arch/x86/kernel/cpu/intel.c      |   34 ++++++++++++++++++++++++++++++++++
 arch/x86/kernel/mrst.c           |   32 ++++++++++++++++++++++++--------
 3 files changed, 61 insertions(+), 8 deletions(-)

diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 32428b4..f72107f 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -94,6 +94,9 @@ struct cpuinfo_x86 {
 	int			x86_cache_alignment;	/* In bytes */
 	int			x86_power;
 	unsigned long		loops_per_jiffy;
+	/* support TSC and LAPIC non-calibartion way */
+	__u32			bus_ratio;
+	__u32			fsb;	/* In khz */
 #ifdef CONFIG_SMP
 	/* cpus sharing the last level cache: */
 	cpumask_var_t		llc_shared_map;
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 85f69cd..f620abc 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -27,6 +27,38 @@
 #include <asm/apic.h>
 #endif
 
+/* MSR_FSB_FREQ in Khz */
+const u32 fsb[] = {266667, 133333, 200000, 166667, 333333, 100000, 400000, 0};
+/* detect Intel cpus that can do TSC/LAPIC non-calibration way */
+static void __cpuinit intel_tsc_fsb(struct cpuinfo_x86 *c)
+{
+	u32 lo, hi;
+
+	if (c->x86 != 6)
+		return;
+	if (c->x86_model != 0xf &&  /* core 2 duo */
+	    c->x86_model != 0x17 && /* core 2 extreme */
+	    c->x86_model != 0x1c && /* atom */
+	    c->x86_model != 0x26 && /* lincroft */
+	    c->x86_model != 0x27) /* penwell */
+		return;
+	rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+	if (lo >> 31)
+		c->bus_ratio = (hi >> 8) & 0x1f;
+	else {
+		rdmsr(MSR_IA32_PLATFORM_ID, lo, hi);
+		c->bus_ratio = (lo >> 8) & 0x1f;
+	}
+	c->fsb = fsb[lo & 0x7];
+	if (c->x86_model == 0x27) { /* penwell special */
+		rdmsr(MSR_FSB_FREQ, lo, hi);
+		if ((lo & 0x7) == 0x7)
+			c->fsb = 83200;
+		else c->fsb = 99840;
+	}
+	printk(KERN_INFO "Detect CPU bus ratio %d, fsb %d khz\n", c->bus_ratio, c->fsb);
+}
+
 static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
 {
 	/* Unmask CPUID levels if masked: */
@@ -46,6 +78,8 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
 		(c->x86 == 0x6 && c->x86_model >= 0x0e))
 		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
 
+	intel_tsc_fsb(c);
+
 	/*
 	 * Atom erratum AAE44/AAF40/AAG38/AAH41:
 	 *
diff --git a/arch/x86/kernel/mrst.c b/arch/x86/kernel/mrst.c
index 9b62d32..c553d10 100644
--- a/arch/x86/kernel/mrst.c
+++ b/arch/x86/kernel/mrst.c
@@ -209,14 +209,31 @@ static unsigned long __init mrst_calibrate_tsc(void)
 {
 	unsigned long flags, fast_calibrate;
 
-	local_irq_save(flags);
-	fast_calibrate = apbt_quick_calibrate();
-	local_irq_restore(flags);
+	if (mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) {
+		fast_calibrate = boot_cpu_data.bus_ratio * boot_cpu_data.fsb;
+		pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
+		lapic_timer_frequency = boot_cpu_data.fsb * 1000 / HZ;
+		/* mark tsc clocksource as reliable */
+		set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
+	} else {
+		/**
+		 * TODO: calibrate lapic timer with apbt, if we use apbt only,
+		 * there is no need to calibrate lapic timer, since they are
+		 * not used.
+		 * if we use lapic timers and apbt, the default calibration
+		 * should work, since we have the global clockevent setup.
+		 * but it would be more efficient if we combine the lapic timer
+		 * with tsc calibration.
+		 */
+		local_irq_save(flags);
+		fast_calibrate = apbt_quick_calibrate();
+		local_irq_restore(flags);
+	}
 
-	if (fast_calibrate)
-		return fast_calibrate;
+	pr_info("tsc lapic calibration results %lu %d\n",
+			fast_calibrate, lapic_timer_frequency);
 
-	return 0;
+	return fast_calibrate;
 }
 
 void __init mrst_time_init(void)
@@ -271,8 +288,7 @@ static void __init mrst_setup_boot_clock(void)
 int mrst_identify_cpu(void)
 {
 	if (boot_cpu_data.x86 == 6 &&
-		boot_cpu_data.x86_model == 0x27 &&
-		boot_cpu_data.x86_mask == 1)
+		boot_cpu_data.x86_model == 0x27)
 		mrst_cpu_chip = MRST_CPU_CHIP_PENWELL;
 	else if (boot_cpu_data.x86 == 6 &&
 		boot_cpu_data.x86_model == 0x26)
-- 
1.7.0.4


On Tue, 11 May 2010 22:36:39 +0800
Thomas Gleixner <tglx@linutronix.de> wrote:

> On Fri, 7 May 2010, Jacob Pan wrote:
> 
> > From: Jacob Pan <jacob.jun.pan@intel.com>
> > 
> > Penwell has added always on lapic timers and tsc, we want to treat
> > it as a variant of moorestown so that one binary kernel can boot on both.
> > this patch added clock selction logic so that platform code can set up the
> > optimal configuration for both moorestown and medfield.
> > 
> > This patch will also mark Penwell TSC reliable, thus no need for
> > watchdog clocksource to monitor it.
> > 
> > Signed-off-by: Alek Du <alek.du@intel.com>
> > Signed-off-by: Jacob Pan <jacob.jun.pan@intel.com>
> > Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
> > ---
> >  arch/x86/include/asm/mrst.h |   30 +++++++++++
> >  arch/x86/kernel/mrst.c      |  119 ++++++++++++++++++++++++++++++++++++++----
> >  2 files changed, 137 insertions(+), 12 deletions(-)
> > 
> > diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h
> > index 451d30e..3054407 100644
> > --- a/arch/x86/include/asm/mrst.h
> > +++ b/arch/x86/include/asm/mrst.h
> > @@ -11,7 +11,37 @@
> >  #ifndef _ASM_X86_MRST_H
> >  #define _ASM_X86_MRST_H
> >  extern int pci_mrst_init(void);
> > +extern unsigned int calibration_result;
> 
> Yuck, why is this in a mrst specific header ?
> 
> > +
> > +#define MRST_TIMER_DEFAULT	0
> > +#define MRST_TIMER_APBT_ONLY	1
> > +#define MRST_TIMER_LAPIC_APBT	2
> 
> enum please, also 
> 
> > +/**
> > + * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock,
> > + * cmdline option x86_mrst_timer can be used to override the configuration
> > + * to prefer one or the other.
> > + * at runtime, there are basically three timer configurations:
> > + * 1. per cpu apbt clock only
> > + * 2. per cpu always-on lapic clocks only, this is Penwell/Medfield only
> > + * 3. per cpu lapic clock (C3STOP) and one apbt clock, with broadcast.
> > + *
> > + * by default (without cmdline option), platform code first detects cpu type
> > + * to see if we are on lincroft or penwell, then set up both lapic or apbt
> > + * clocks accordingly.
> > + * i.e. by default, medfield uses configuration #2, moorestown uses #1.
> > + * config #3 is supported but not recommended on medfield.
> > + *
> > + * rating and feature summary:
> > + * lapic (with C3STOP) --------- 100
> > + * apbt (always-on) ------------ 110
> 
>  apbt sucks performance wise, so why do you consider it a better
>  choice than lapic + broadcast ?
> 
> > + * lapic (always-on,ARAT) ------ 150
> > + */
> > +
> > +int mrst_timer_options __cpuinitdata;
> > +
> >  static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM];
> >  static struct sfi_timer_table_entry sfi_mtimer_array[SFI_MTMR_MAX_NUM];
> > +static u32 mrst_cpu_chip;
> >  int sfi_mtimer_num;
> >  
> >  struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX];
> > @@ -167,15 +191,16 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table)
> >  	return 0;
> >  }
> >  
> > -/*
> > - * the secondary clock in Moorestown can be APBT or LAPIC clock, default to
> > - * APBT but cmdline option can also override it.
> > - */
> >  static void __cpuinit mrst_setup_secondary_clock(void)
> >  {
> > -	/* restore default lapic clock if disabled by cmdline */
> > -	if (disable_apbt_percpu)
> > -		return setup_secondary_APIC_clock();
> > +	if ((mrst_timer_options == MRST_TIMER_APBT_ONLY))
> > +		return apbt_setup_secondary_clock();
> > +	if (cpu_has(&current_cpu_data, X86_FEATURE_ARAT)
> > +		||  (mrst_timer_options == MRST_TIMER_LAPIC_APBT)) {
> > +		pr_info("using lapic timers for secondary clock\n");
> > +		setup_secondary_APIC_clock();
> > +		return;
> 
>   The logic is confusing. 
> 
> > +	}
> >  	apbt_setup_secondary_clock();
> >  }
> >  
> > @@ -183,9 +208,45 @@ static unsigned long __init mrst_calibrate_tsc(void)
> >  {
> >  	unsigned long flags, fast_calibrate;
> >  
> > -	local_irq_save(flags);
> > -	fast_calibrate = apbt_quick_calibrate();
> > -	local_irq_restore(flags);
> > +	if (mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) {
> > +		u32 lo, hi, ratio, fsb;
> > +
> > +		rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
> > +		pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
> > +		ratio = (hi >> 8) & 0x1f;
> > +		pr_debug("ratio is %d\n", ratio);
> > +		if (!ratio) {
> > +			pr_err("read a zero ratio, should be incorrect!\n");
> > +			pr_err("force tsc ratio to 16 ...\n");
> > +			ratio = 16;
> > +		}
> 
>  This is not Penwell specific at all. The ratio can be read out on all
>  Core based CPUs either from MSR_PLATFORM_ID[12:8] or
>  MSR_PERF_STAT[44:40] depending on XE operation enabled
>  (MSR_PERF_STAT[31] == 1)
> 
>  This should be made general available and not burried into the mrst
>  code.
> 
> > +		rdmsr(MSR_FSB_FREQ, lo, hi);
> > +		if ((lo & 0x7) == 0x7)
> > +			fsb = PENWELL_FSB_FREQ_83SKU;
> > +		else
> > +			fsb = PENWELL_FSB_FREQ_100SKU;
> 
>  I guess the 111 is Penwell/MRST specific, right ?
> 
>  According to SDM we have anyway different results for the various CPU
>  families, but we should utilize this in a generic way and have the
>  translation tables for the various CPUs in one place.
> 
> > +		fast_calibrate = ratio * fsb;
> > +		pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
> > +		calibration_result = fsb * 1000 / HZ;
> > +		/* mark tsc clocksource as reliable */
> > +		set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
> > +	} else {
> > +		/**
> > +		 * TODO: calibrate lapic timer with apbt, if we use apbt only,
> > +		 * there is no need to calibrate lapic timer, since they are
> > +		 * not used.
> > +		 * if we use lapic timers and apbt, the default calibration
> > +		 * should work, since we have the global clockevent setup.
> > +		 * but it would be more efficient if we combine the lapic timer
> > +		 * with tsc calibration.
> > +		 */
> > +		local_irq_save(flags);
> > +		fast_calibrate = apbt_quick_calibrate();
> > +		local_irq_restore(flags);
> > +	}
> > +
> > +	pr_info("tsc lapic calibration results %lu %d\n",
> > +			fast_calibrate, calibration_result);
> >  
> >  	if (fast_calibrate)
> >  		return fast_calibrate;
> > @@ -195,6 +256,11 @@ static unsigned long __init mrst_calibrate_tsc(void)
> >  
> >  void __init mrst_time_init(void)
> >  {
> > +	/* if cpu is penwell, lapic timer will be used by default */
> > +	if ((mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) &&
> > +		(mrst_timer_options == MRST_TIMER_DEFAULT))
> > +		return;
> > +
> >  	sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr);
> >  	pre_init_apic_IRQ0();
> >  	apbt_time_init();
> > @@ -211,11 +277,38 @@ void __init mrst_rtc_init(void)
> >   */
> >  static void __init mrst_setup_boot_clock(void)
> >  {
> > -	pr_info("%s: per cpu apbt flag %d \n", __func__, disable_apbt_percpu);
> > -	if (disable_apbt_percpu)
> > +	if (mrst_timer_options == MRST_TIMER_APBT_ONLY)
> > +		return;
> > +	if ((mrst_timer_options == MRST_TIMER_LAPIC_APBT)
> > +		|| (mrst_cpu_chip == MRST_CPU_CHIP_PENWELL))
> >  		setup_boot_APIC_clock();
> >  };
> >  
> > +enum cpuid_regs {
> > +	CR_EAX = 0,
> > +	CR_ECX,
> > +	CR_EDX,
> > +	CR_EBX
> > +};
> > +
> > +int mrst_identify_cpu(void)
> > +{
> > +	u32 regs[4];
> > +
> > +	cpuid(1, &regs[CR_EAX], &regs[CR_EBX], &regs[CR_ECX], &regs[CR_EDX]);
> 
>   Yikes. From which Intel cookbook is this ?
> 
>   Aside of that we have that info in boot_cpu_info already, don't we ?
>   So there is neither a requirement for the extra cpuid call nor for
>   the extra mrst_cpu_chip id magic.
> 
> > +	if ((regs[CR_EAX] & PENWELL_FAMILY) == PENWELL_FAMILY)
> > +		mrst_cpu_chip = MRST_CPU_CHIP_PENWELL;
> > +	else
> > +		mrst_cpu_chip = MRST_CPU_CHIP_LINCROFT;
> 
> 
> > +	pr_debug("cpuid result %x\n", regs[CR_EAX]);
> > +	pr_info("Moorestown CPU %s identified\n",
> > +		(mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) ?
> > +		"Lincroft" : "Penwell");
> 
>   Are we going to add one of those for each new family ? This is
>   really redundant bloat with no value.
> 
> > +	return mrst_cpu_chip;
> > +}
> > +
> >  /*
> >   * Moorestown specific x86_init function overrides and early setup
> >   * calls.
> > @@ -237,4 +330,6 @@ void __init x86_mrst_early_setup(void)
> >  	x86_init.pci.fixup_irqs = x86_init_noop;
> >  
> >  	legacy_pic = &null_legacy_pic;
> > +
> > +	mrst_identify_cpu();
> >  }
> > -- 
> > 1.6.3.3
> > 


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* Re: [PATCH 4/8] x86/mrst: change clock selection logic to support medfield
  2010-05-11 14:36   ` Thomas Gleixner
                       ` (2 preceding siblings ...)
  2010-05-17  2:14     ` Du, Alek
@ 2010-05-17  2:27     ` Du, Alek
  3 siblings, 0 replies; 49+ messages in thread
From: Du, Alek @ 2010-05-17  2:27 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Jacob Pan, H. Peter Anvin, Ingo Molnar, Arjan van de Ven, Tang,
	Feng, LKML, Pan, Jacob jun

Sorry, send again, the previous patch should be merged with the patch that
export lapic_timer_frequency and allow lapic use early calibration result.
Otherwise, it will break the build...


>From 4103dc6165530a490c12a6177d916f2c2e012436 Mon Sep 17 00:00:00 2001
From: Jacob Pan <jacob.jun.pan@linux.intel.com>
Date: Fri, 14 May 2010 13:45:46 -0700
Subject: [PATCH] x86/mrst: Auto detect freq for local timers

Some Intel CPUs can directly get fsb frequency and bus ratio from
various MSRs. This patch enables this feature and benefit Medfield
platform.

lapic timer calibration can be combined with tsc in platform specific
calibration functions. if such calibration result is obtained early,
we can skip the redundent calibration loops.

Signed-off-by: Alek Du <alek.du@intel.com>
Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
---
 arch/x86/include/asm/apic.h      |    1 +
 arch/x86/include/asm/processor.h |    3 +++
 arch/x86/kernel/apic/apic.c      |   33 ++++++++++++++++++++++++++-------
 arch/x86/kernel/cpu/intel.c      |   34 ++++++++++++++++++++++++++++++++++
 arch/x86/kernel/mrst.c           |   32 ++++++++++++++++++++++++--------
 5 files changed, 88 insertions(+), 15 deletions(-)

diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 1fa03e0..448c763 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -50,6 +50,7 @@ extern unsigned int apic_verbosity;
 extern int local_apic_timer_c2_ok;
 
 extern int disable_apic;
+extern unsigned int lapic_timer_frequency;
 
 #ifdef CONFIG_SMP
 extern void __inquire_remote_apic(int apicid);
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 32428b4..f72107f 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -94,6 +94,9 @@ struct cpuinfo_x86 {
 	int			x86_cache_alignment;	/* In bytes */
 	int			x86_power;
 	unsigned long		loops_per_jiffy;
+	/* support TSC and LAPIC non-calibartion way */
+	__u32			bus_ratio;
+	__u32			fsb;	/* In khz */
 #ifdef CONFIG_SMP
 	/* cpus sharing the last level cache: */
 	cpumask_var_t		llc_shared_map;
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index e5a4a1e..2141ff5 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -175,7 +175,7 @@ static struct resource lapic_resource = {
 	.flags = IORESOURCE_MEM | IORESOURCE_BUSY,
 };
 
-static unsigned int calibration_result;
+unsigned int lapic_timer_frequency;
 
 static int lapic_next_event(unsigned long delta,
 			    struct clock_event_device *evt);
@@ -430,7 +430,7 @@ static void lapic_timer_setup(enum clock_event_mode mode,
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 	case CLOCK_EVT_MODE_ONESHOT:
-		__setup_APIC_LVTT(calibration_result,
+		__setup_APIC_LVTT(lapic_timer_frequency,
 				  mode != CLOCK_EVT_MODE_PERIODIC, 1);
 		break;
 	case CLOCK_EVT_MODE_UNUSED:
@@ -597,6 +597,25 @@ static int __init calibrate_APIC_clock(void)
 	long delta, deltatsc;
 	int pm_referenced = 0;
 
+	/**
+	 * check if lapic timer has already been calibrated by platform
+	 * specific routine, such as tsc calibration code. if so, we just fill
+	 * in the clockevent structure and return.
+	 */
+
+	if (lapic_timer_frequency) {
+		apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n",
+				lapic_timer_frequency);
+		lapic_clockevent.mult = div_sc(lapic_timer_frequency/APIC_DIVISOR,
+					TICK_NSEC, lapic_clockevent.shift);
+		lapic_clockevent.max_delta_ns =
+			clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
+		lapic_clockevent.min_delta_ns =
+			clockevent_delta2ns(0xF, &lapic_clockevent);
+		lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
+		return 0;
+	}
+
 	local_irq_disable();
 
 	/* Replace the global interrupt handler */
@@ -638,12 +657,12 @@ static int __init calibrate_APIC_clock(void)
 	lapic_clockevent.min_delta_ns =
 		clockevent_delta2ns(0xF, &lapic_clockevent);
 
-	calibration_result = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
+	lapic_timer_frequency = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
 
 	apic_printk(APIC_VERBOSE, "..... delta %ld\n", delta);
 	apic_printk(APIC_VERBOSE, "..... mult: %u\n", lapic_clockevent.mult);
 	apic_printk(APIC_VERBOSE, "..... calibration result: %u\n",
-		    calibration_result);
+		    lapic_timer_frequency);
 
 	if (cpu_has_tsc) {
 		apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
@@ -654,13 +673,13 @@ static int __init calibrate_APIC_clock(void)
 
 	apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
 		    "%u.%04u MHz.\n",
-		    calibration_result / (1000000 / HZ),
-		    calibration_result % (1000000 / HZ));
+		    lapic_timer_frequency / (1000000 / HZ),
+		    lapic_timer_frequency % (1000000 / HZ));
 
 	/*
 	 * Do a sanity check on the APIC calibration result
 	 */
-	if (calibration_result < (1000000 / HZ)) {
+	if (lapic_timer_frequency < (1000000 / HZ)) {
 		local_irq_enable();
 		pr_warning("APIC frequency too slow, disabling apic timer\n");
 		return -1;
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 85f69cd..f620abc 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -27,6 +27,38 @@
 #include <asm/apic.h>
 #endif
 
+/* MSR_FSB_FREQ in Khz */
+const u32 fsb[] = {266667, 133333, 200000, 166667, 333333, 100000, 400000, 0};
+/* detect Intel cpus that can do TSC/LAPIC non-calibration way */
+static void __cpuinit intel_tsc_fsb(struct cpuinfo_x86 *c)
+{
+	u32 lo, hi;
+
+	if (c->x86 != 6)
+		return;
+	if (c->x86_model != 0xf &&  /* core 2 duo */
+	    c->x86_model != 0x17 && /* core 2 extreme */
+	    c->x86_model != 0x1c && /* atom */
+	    c->x86_model != 0x26 && /* lincroft */
+	    c->x86_model != 0x27) /* penwell */
+		return;
+	rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+	if (lo >> 31)
+		c->bus_ratio = (hi >> 8) & 0x1f;
+	else {
+		rdmsr(MSR_IA32_PLATFORM_ID, lo, hi);
+		c->bus_ratio = (lo >> 8) & 0x1f;
+	}
+	c->fsb = fsb[lo & 0x7];
+	if (c->x86_model == 0x27) { /* penwell special */
+		rdmsr(MSR_FSB_FREQ, lo, hi);
+		if ((lo & 0x7) == 0x7)
+			c->fsb = 83200;
+		else c->fsb = 99840;
+	}
+	printk(KERN_INFO "Detect CPU bus ratio %d, fsb %d khz\n", c->bus_ratio, c->fsb);
+}
+
 static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
 {
 	/* Unmask CPUID levels if masked: */
@@ -46,6 +78,8 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
 		(c->x86 == 0x6 && c->x86_model >= 0x0e))
 		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
 
+	intel_tsc_fsb(c);
+
 	/*
 	 * Atom erratum AAE44/AAF40/AAG38/AAH41:
 	 *
diff --git a/arch/x86/kernel/mrst.c b/arch/x86/kernel/mrst.c
index 9b62d32..c553d10 100644
--- a/arch/x86/kernel/mrst.c
+++ b/arch/x86/kernel/mrst.c
@@ -209,14 +209,31 @@ static unsigned long __init mrst_calibrate_tsc(void)
 {
 	unsigned long flags, fast_calibrate;
 
-	local_irq_save(flags);
-	fast_calibrate = apbt_quick_calibrate();
-	local_irq_restore(flags);
+	if (mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) {
+		fast_calibrate = boot_cpu_data.bus_ratio * boot_cpu_data.fsb;
+		pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
+		lapic_timer_frequency = boot_cpu_data.fsb * 1000 / HZ;
+		/* mark tsc clocksource as reliable */
+		set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
+	} else {
+		/**
+		 * TODO: calibrate lapic timer with apbt, if we use apbt only,
+		 * there is no need to calibrate lapic timer, since they are
+		 * not used.
+		 * if we use lapic timers and apbt, the default calibration
+		 * should work, since we have the global clockevent setup.
+		 * but it would be more efficient if we combine the lapic timer
+		 * with tsc calibration.
+		 */
+		local_irq_save(flags);
+		fast_calibrate = apbt_quick_calibrate();
+		local_irq_restore(flags);
+	}
 
-	if (fast_calibrate)
-		return fast_calibrate;
+	pr_info("tsc lapic calibration results %lu %d\n",
+			fast_calibrate, lapic_timer_frequency);
 
-	return 0;
+	return fast_calibrate;
 }
 
 void __init mrst_time_init(void)
@@ -271,8 +288,7 @@ static void __init mrst_setup_boot_clock(void)
 int mrst_identify_cpu(void)
 {
 	if (boot_cpu_data.x86 == 6 &&
-		boot_cpu_data.x86_model == 0x27 &&
-		boot_cpu_data.x86_mask == 1)
+		boot_cpu_data.x86_model == 0x27)
 		mrst_cpu_chip = MRST_CPU_CHIP_PENWELL;
 	else if (boot_cpu_data.x86 == 6 &&
 		boot_cpu_data.x86_model == 0x26)
-- 
1.7.0.4





On Tue, 11 May 2010 22:36:39 +0800
Thomas Gleixner <tglx@linutronix.de> wrote:

> On Fri, 7 May 2010, Jacob Pan wrote:
> 
> > From: Jacob Pan <jacob.jun.pan@intel.com>
> > 
> > Penwell has added always on lapic timers and tsc, we want to treat
> > it as a variant of moorestown so that one binary kernel can boot on both.
> > this patch added clock selction logic so that platform code can set up the
> > optimal configuration for both moorestown and medfield.
> > 
> > This patch will also mark Penwell TSC reliable, thus no need for
> > watchdog clocksource to monitor it.
> > 
> > Signed-off-by: Alek Du <alek.du@intel.com>
> > Signed-off-by: Jacob Pan <jacob.jun.pan@intel.com>
> > Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
> > ---
> >  arch/x86/include/asm/mrst.h |   30 +++++++++++
> >  arch/x86/kernel/mrst.c      |  119 ++++++++++++++++++++++++++++++++++++++----
> >  2 files changed, 137 insertions(+), 12 deletions(-)
> > 
> > diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h
> > index 451d30e..3054407 100644
> > --- a/arch/x86/include/asm/mrst.h
> > +++ b/arch/x86/include/asm/mrst.h
> > @@ -11,7 +11,37 @@
> >  #ifndef _ASM_X86_MRST_H
> >  #define _ASM_X86_MRST_H
> >  extern int pci_mrst_init(void);
> > +extern unsigned int calibration_result;
> 
> Yuck, why is this in a mrst specific header ?
> 
> > +
> > +#define MRST_TIMER_DEFAULT	0
> > +#define MRST_TIMER_APBT_ONLY	1
> > +#define MRST_TIMER_LAPIC_APBT	2
> 
> enum please, also 
> 
> > +/**
> > + * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock,
> > + * cmdline option x86_mrst_timer can be used to override the configuration
> > + * to prefer one or the other.
> > + * at runtime, there are basically three timer configurations:
> > + * 1. per cpu apbt clock only
> > + * 2. per cpu always-on lapic clocks only, this is Penwell/Medfield only
> > + * 3. per cpu lapic clock (C3STOP) and one apbt clock, with broadcast.
> > + *
> > + * by default (without cmdline option), platform code first detects cpu type
> > + * to see if we are on lincroft or penwell, then set up both lapic or apbt
> > + * clocks accordingly.
> > + * i.e. by default, medfield uses configuration #2, moorestown uses #1.
> > + * config #3 is supported but not recommended on medfield.
> > + *
> > + * rating and feature summary:
> > + * lapic (with C3STOP) --------- 100
> > + * apbt (always-on) ------------ 110
> 
>  apbt sucks performance wise, so why do you consider it a better
>  choice than lapic + broadcast ?
> 
> > + * lapic (always-on,ARAT) ------ 150
> > + */
> > +
> > +int mrst_timer_options __cpuinitdata;
> > +
> >  static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM];
> >  static struct sfi_timer_table_entry sfi_mtimer_array[SFI_MTMR_MAX_NUM];
> > +static u32 mrst_cpu_chip;
> >  int sfi_mtimer_num;
> >  
> >  struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX];
> > @@ -167,15 +191,16 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table)
> >  	return 0;
> >  }
> >  
> > -/*
> > - * the secondary clock in Moorestown can be APBT or LAPIC clock, default to
> > - * APBT but cmdline option can also override it.
> > - */
> >  static void __cpuinit mrst_setup_secondary_clock(void)
> >  {
> > -	/* restore default lapic clock if disabled by cmdline */
> > -	if (disable_apbt_percpu)
> > -		return setup_secondary_APIC_clock();
> > +	if ((mrst_timer_options == MRST_TIMER_APBT_ONLY))
> > +		return apbt_setup_secondary_clock();
> > +	if (cpu_has(&current_cpu_data, X86_FEATURE_ARAT)
> > +		||  (mrst_timer_options == MRST_TIMER_LAPIC_APBT)) {
> > +		pr_info("using lapic timers for secondary clock\n");
> > +		setup_secondary_APIC_clock();
> > +		return;
> 
>   The logic is confusing. 
> 
> > +	}
> >  	apbt_setup_secondary_clock();
> >  }
> >  
> > @@ -183,9 +208,45 @@ static unsigned long __init mrst_calibrate_tsc(void)
> >  {
> >  	unsigned long flags, fast_calibrate;
> >  
> > -	local_irq_save(flags);
> > -	fast_calibrate = apbt_quick_calibrate();
> > -	local_irq_restore(flags);
> > +	if (mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) {
> > +		u32 lo, hi, ratio, fsb;
> > +
> > +		rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
> > +		pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
> > +		ratio = (hi >> 8) & 0x1f;
> > +		pr_debug("ratio is %d\n", ratio);
> > +		if (!ratio) {
> > +			pr_err("read a zero ratio, should be incorrect!\n");
> > +			pr_err("force tsc ratio to 16 ...\n");
> > +			ratio = 16;
> > +		}
> 
>  This is not Penwell specific at all. The ratio can be read out on all
>  Core based CPUs either from MSR_PLATFORM_ID[12:8] or
>  MSR_PERF_STAT[44:40] depending on XE operation enabled
>  (MSR_PERF_STAT[31] == 1)
> 
>  This should be made general available and not burried into the mrst
>  code.
> 
> > +		rdmsr(MSR_FSB_FREQ, lo, hi);
> > +		if ((lo & 0x7) == 0x7)
> > +			fsb = PENWELL_FSB_FREQ_83SKU;
> > +		else
> > +			fsb = PENWELL_FSB_FREQ_100SKU;
> 
>  I guess the 111 is Penwell/MRST specific, right ?
> 
>  According to SDM we have anyway different results for the various CPU
>  families, but we should utilize this in a generic way and have the
>  translation tables for the various CPUs in one place.
> 
> > +		fast_calibrate = ratio * fsb;
> > +		pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
> > +		calibration_result = fsb * 1000 / HZ;
> > +		/* mark tsc clocksource as reliable */
> > +		set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
> > +	} else {
> > +		/**
> > +		 * TODO: calibrate lapic timer with apbt, if we use apbt only,
> > +		 * there is no need to calibrate lapic timer, since they are
> > +		 * not used.
> > +		 * if we use lapic timers and apbt, the default calibration
> > +		 * should work, since we have the global clockevent setup.
> > +		 * but it would be more efficient if we combine the lapic timer
> > +		 * with tsc calibration.
> > +		 */
> > +		local_irq_save(flags);
> > +		fast_calibrate = apbt_quick_calibrate();
> > +		local_irq_restore(flags);
> > +	}
> > +
> > +	pr_info("tsc lapic calibration results %lu %d\n",
> > +			fast_calibrate, calibration_result);
> >  
> >  	if (fast_calibrate)
> >  		return fast_calibrate;
> > @@ -195,6 +256,11 @@ static unsigned long __init mrst_calibrate_tsc(void)
> >  
> >  void __init mrst_time_init(void)
> >  {
> > +	/* if cpu is penwell, lapic timer will be used by default */
> > +	if ((mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) &&
> > +		(mrst_timer_options == MRST_TIMER_DEFAULT))
> > +		return;
> > +
> >  	sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr);
> >  	pre_init_apic_IRQ0();
> >  	apbt_time_init();
> > @@ -211,11 +277,38 @@ void __init mrst_rtc_init(void)
> >   */
> >  static void __init mrst_setup_boot_clock(void)
> >  {
> > -	pr_info("%s: per cpu apbt flag %d \n", __func__, disable_apbt_percpu);
> > -	if (disable_apbt_percpu)
> > +	if (mrst_timer_options == MRST_TIMER_APBT_ONLY)
> > +		return;
> > +	if ((mrst_timer_options == MRST_TIMER_LAPIC_APBT)
> > +		|| (mrst_cpu_chip == MRST_CPU_CHIP_PENWELL))
> >  		setup_boot_APIC_clock();
> >  };
> >  
> > +enum cpuid_regs {
> > +	CR_EAX = 0,
> > +	CR_ECX,
> > +	CR_EDX,
> > +	CR_EBX
> > +};
> > +
> > +int mrst_identify_cpu(void)
> > +{
> > +	u32 regs[4];
> > +
> > +	cpuid(1, &regs[CR_EAX], &regs[CR_EBX], &regs[CR_ECX], &regs[CR_EDX]);
> 
>   Yikes. From which Intel cookbook is this ?
> 
>   Aside of that we have that info in boot_cpu_info already, don't we ?
>   So there is neither a requirement for the extra cpuid call nor for
>   the extra mrst_cpu_chip id magic.
> 
> > +	if ((regs[CR_EAX] & PENWELL_FAMILY) == PENWELL_FAMILY)
> > +		mrst_cpu_chip = MRST_CPU_CHIP_PENWELL;
> > +	else
> > +		mrst_cpu_chip = MRST_CPU_CHIP_LINCROFT;
> 
> 
> > +	pr_debug("cpuid result %x\n", regs[CR_EAX]);
> > +	pr_info("Moorestown CPU %s identified\n",
> > +		(mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) ?
> > +		"Lincroft" : "Penwell");
> 
>   Are we going to add one of those for each new family ? This is
>   really redundant bloat with no value.
> 
> > +	return mrst_cpu_chip;
> > +}
> > +
> >  /*
> >   * Moorestown specific x86_init function overrides and early setup
> >   * calls.
> > @@ -237,4 +330,6 @@ void __init x86_mrst_early_setup(void)
> >  	x86_init.pci.fixup_irqs = x86_init_noop;
> >  
> >  	legacy_pic = &null_legacy_pic;
> > +
> > +	mrst_identify_cpu();
> >  }
> > -- 
> > 1.6.3.3
> > 


^ permalink raw reply related	[flat|nested] 49+ messages in thread

* Re: [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device
  2010-05-12  2:34     ` Feng Tang
@ 2010-05-17  9:15       ` Thomas Gleixner
  2010-05-18  6:27         ` Feng Tang
                           ` (4 more replies)
  0 siblings, 5 replies; 49+ messages in thread
From: Thomas Gleixner @ 2010-05-17  9:15 UTC (permalink / raw)
  To: Feng Tang
  Cc: Jacob Pan, H. Peter Anvin, Ingo Molnar, Du, Alek,
	Arjan van de Ven, LKML, John Stultz

Feng,

[ Cc'ed John ]

On Wed, 12 May 2010, Feng Tang wrote:
> > >  void __init mrst_rtc_init(void)
> > >  {
> > > +	unsigned long rtc_paddr;
> > > +	void __iomem *virt_base;
> > > +
> > >  	sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
> > > +	if (!sfi_mrtc_num)
> > > +		return;
> > > +
> > > +	rtc_paddr = sfi_mrtc_array[0].phys_addr;
> > > +
> > > +	/* vRTC's register address may not be page aligned */
> > > +	set_fixmap_nocache(FIX_LNW_VRTC, rtc_paddr);
> > 
> > Why do we need a fixmap for that ? There is no need to setup RTC that
> > early. The first call is from timekeeping_init() 
> 
> Actually when to init the vrtc register is a big problem for me, vrtc
> need be inited before timekeeping_init(), and I thought better to put it
> somewhere in setup_arch(), as it is architecture specific, and ioremap
> is not working at that time. Also that's the reason I created a new
> wallclock_init func for x86_platforms, I could not find a better way
> to do the vrtc init.

There is no particular reason why we need to read it in
timekeeping_init(). Nothing in the kernel needs the correct wall time
at that point. So we can safely move the setting of xtime to rtc wall
clock time to a separate timekeeping_late_init() function.

John ???
 
> > Also this RTC init code should be in vrtc.c
> I agree I should move this init code to vrtc.c, but still think it should
> be called in the setup_arch() than in start_kernel()

I do not :)

> > > +	lock_cmos_prefix(reg);
> > 
> >   This lock_cmos magic should just die. I have no idea why something
> >   wants or wanted to access the RTC from an NMI.
> 
> I will try to reuse the rtc_lock defined in rtc.c whose get/set_time
> service won't be called with vrtc's at the same time.

Please don't create artifical dependencies. Use a separate vrtc_lock
to serialize the access to vrtc.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device
  2010-05-17  9:15       ` Thomas Gleixner
@ 2010-05-18  6:27         ` Feng Tang
  2010-05-18  7:38           ` Thomas Gleixner
  2010-05-18 20:43         ` john stultz
                           ` (3 subsequent siblings)
  4 siblings, 1 reply; 49+ messages in thread
From: Feng Tang @ 2010-05-18  6:27 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Jacob Pan, H. Peter Anvin, Ingo Molnar, Du, Alek,
	Arjan van de Ven, LKML, John Stultz

Hi Thomas,


On Mon, 17 May 2010 17:15:55 +0800
Thomas Gleixner <tglx@linutronix.de> wrote:


> > 
> > Actually when to init the vrtc register is a big problem for me,
> > vrtc need be inited before timekeeping_init(), and I thought better
> > to put it somewhere in setup_arch(), as it is architecture
> > specific, and ioremap is not working at that time. Also that's the
> > reason I created a new wallclock_init func for x86_platforms, I
> > could not find a better way to do the vrtc init.
> 
> There is no particular reason why we need to read it in
> timekeeping_init(). Nothing in the kernel needs the correct wall time
> at that point. So we can safely move the setting of xtime to rtc wall
> clock time to a separate timekeeping_late_init() function.
> 
> John ???
>  
Yeah, good suggestion, if xtime init is moved to a later time in kernel
init flow, then vrtc's init function can be set a arch_initcall()


> > > > +	lock_cmos_prefix(reg);
> > > 
> > >   This lock_cmos magic should just die. I have no idea why
> > > something wants or wanted to access the RTC from an NMI.
> > 
> > I will try to reuse the rtc_lock defined in rtc.c whose get/set_time
> > service won't be called with vrtc's at the same time.
> 
> Please don't create artifical dependencies. Use a separate vrtc_lock
> to serialize the access to vrtc.
I just checked the code, when wall clock's get/set_time service is called,
it is always protected by rtc_lock(code in arch/x86/kernel/rtc.c), then
no need to add the lock for each individual register read/write operation.

I will submit a v2 vrtc patch.

Thanks,
Feng


> 
> Thanks,
> 
> 	tglx

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device
  2010-05-18  6:27         ` Feng Tang
@ 2010-05-18  7:38           ` Thomas Gleixner
  0 siblings, 0 replies; 49+ messages in thread
From: Thomas Gleixner @ 2010-05-18  7:38 UTC (permalink / raw)
  To: Feng Tang
  Cc: Jacob Pan, H. Peter Anvin, Ingo Molnar, Du, Alek,
	Arjan van de Ven, LKML, John Stultz

On Tue, 18 May 2010, Feng Tang wrote:
> Hi Thomas,
> 
> 
> On Mon, 17 May 2010 17:15:55 +0800
> Thomas Gleixner <tglx@linutronix.de> wrote:
> 
> 
> > > 
> > > Actually when to init the vrtc register is a big problem for me,
> > > vrtc need be inited before timekeeping_init(), and I thought better
> > > to put it somewhere in setup_arch(), as it is architecture
> > > specific, and ioremap is not working at that time. Also that's the
> > > reason I created a new wallclock_init func for x86_platforms, I
> > > could not find a better way to do the vrtc init.
> > 
> > There is no particular reason why we need to read it in
> > timekeeping_init(). Nothing in the kernel needs the correct wall time
> > at that point. So we can safely move the setting of xtime to rtc wall
> > clock time to a separate timekeeping_late_init() function.
> > 
> > John ???
> >  
> Yeah, good suggestion, if xtime init is moved to a later time in kernel
> init flow, then vrtc's init function can be set a arch_initcall()

John was away yesterday, so we have to wait for his answer, but I don't
expect a nono from him.
 
> > > > > +	lock_cmos_prefix(reg);
> > > > 
> > > >   This lock_cmos magic should just die. I have no idea why
> > > > something wants or wanted to access the RTC from an NMI.
> > > 
> > > I will try to reuse the rtc_lock defined in rtc.c whose get/set_time
> > > service won't be called with vrtc's at the same time.
> > 
> > Please don't create artifical dependencies. Use a separate vrtc_lock
> > to serialize the access to vrtc.
> I just checked the code, when wall clock's get/set_time service is called,
> it is always protected by rtc_lock(code in arch/x86/kernel/rtc.c), then
> no need to add the lock for each individual register read/write operation.

Grr. Yes, missed that the code is called under rtc_lock already. So
you can drop the locking in your code completely.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device
  2010-05-17  9:15       ` Thomas Gleixner
  2010-05-18  6:27         ` Feng Tang
@ 2010-05-18 20:43         ` john stultz
  2010-05-18 21:02           ` Thomas Gleixner
  2010-05-21  2:15         ` [PATCH 1/3] timekeeping: moving xtime's init to a later time Feng Tang
                           ` (2 subsequent siblings)
  4 siblings, 1 reply; 49+ messages in thread
From: john stultz @ 2010-05-18 20:43 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Feng Tang, Jacob Pan, H. Peter Anvin, Ingo Molnar, Du, Alek,
	Arjan van de Ven, LKML

On Mon, 2010-05-17 at 11:15 +0200, Thomas Gleixner wrote:
> 
> 
> There is no particular reason why we need to read it in
> timekeeping_init(). Nothing in the kernel needs the correct wall time
> at that point. So we can safely move the setting of xtime to rtc wall
> clock time to a separate timekeeping_late_init() function.
> 
> John ???

No big objections here. Still would like to keep the amount of time that
the kernel is up without xtime being initialized to a minimum. However
the generic RTC code already have this issue since some of them require
interrupts to be enabled to do a read, so pushing it off into a
_late_init() function is probably just a short term fix until we figure
out how to get the generic RTC code working better with the timekeeping
code.

Does the delayed init required by vrtc cause any trouble with
suspend/resume?

thanks
-john 


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device
  2010-05-18 20:43         ` john stultz
@ 2010-05-18 21:02           ` Thomas Gleixner
  0 siblings, 0 replies; 49+ messages in thread
From: Thomas Gleixner @ 2010-05-18 21:02 UTC (permalink / raw)
  To: john stultz
  Cc: Feng Tang, Jacob Pan, H. Peter Anvin, Ingo Molnar, Du, Alek,
	Arjan van de Ven, LKML

On Tue, 18 May 2010, john stultz wrote:

> On Mon, 2010-05-17 at 11:15 +0200, Thomas Gleixner wrote:
> > 
> > 
> > There is no particular reason why we need to read it in
> > timekeeping_init(). Nothing in the kernel needs the correct wall time
> > at that point. So we can safely move the setting of xtime to rtc wall
> > clock time to a separate timekeeping_late_init() function.
> > 
> > John ???
> 
> No big objections here. Still would like to keep the amount of time that
> the kernel is up without xtime being initialized to a minimum. However

Why? Nothing _IS_ depending on xtime at this point. We just should
have it ready when we mount the first file system, but even that is
not a big issue aside of some stupid warnings.

> the generic RTC code already have this issue since some of them require
> interrupts to be enabled to do a read, so pushing it off into a
> _late_init() function is probably just a short term fix until we figure
> out how to get the generic RTC code working better with the timekeeping
> code.

Well, you need to wait until the driver is loaded and the hardware
accessible which might take some time when I2C, SPI or similar stuff
is involved. No way to get this stuff accesible early.

So really the question is, why do we want wall time initialized early?
All we care about until we hit user space is clock monotonic and
working timekeeping in general. NTP is not an issue either before we
hit user space. So what's your concern ?

> Does the delayed init required by vrtc cause any trouble with
> suspend/resume?

No, suspend/resume does not go through that early code. It has
everything setup (mappings, etc)

Thanks,

	tglx



^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH 1/3] timekeeping: moving xtime's init to a later time
  2010-05-17  9:15       ` Thomas Gleixner
  2010-05-18  6:27         ` Feng Tang
  2010-05-18 20:43         ` john stultz
@ 2010-05-21  2:15         ` Feng Tang
  2010-05-21  2:16         ` [PATCH 2/3] x86: unify current 3 similar ways of saving IRQ info Feng Tang
  2010-05-21  2:19         ` [PATCH 3/3] x86/mrst: add vrtc driver which serves as a wall clock device Feng Tang
  4 siblings, 0 replies; 49+ messages in thread
From: Feng Tang @ 2010-05-21  2:15 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Jacob Pan, H. Peter Anvin, Ingo Molnar, Du, Alek,
	Arjan van de Ven, LKML, John Stultz

>From 2451f205e29be57b30f0c50759c1b05a67bb97d1 Mon Sep 17 00:00:00 2001
From: Feng Tang <feng.tang@intel.com>
Date: Wed, 19 May 2010 16:57:20 +0800
Subject: [PATCH 1/3] timekeeping: moving xtime's init to a later time

xtime doesn't need to be inited early, move it to a subsys_initcall,
as most of its consumers come from userspace. It will also give enough
time for some MMIO based wallclock devices to init

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <johnstul@us.ibm.com>
Signed-off-by: Feng Tang <feng.tang@intel.com>
---
 kernel/time/timekeeping.c |   28 +++++++++++++++++++++-------
 1 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 39f6177..7bc32de 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -529,26 +529,37 @@ void __attribute__((weak)) read_boot_clock(struct timespec *ts)
 }
 
 /*
- * timekeeping_init - Initializes the clocksource and common timekeeping values
+ * timekeeping_init - Initializes the clocksource
  */
 void __init timekeeping_init(void)
 {
 	struct clocksource *clock;
 	unsigned long flags;
-	struct timespec now, boot;
-
-	read_persistent_clock(&now);
-	read_boot_clock(&boot);
 
 	write_seqlock_irqsave(&xtime_lock, flags);
 
-	ntp_init();
-
 	clock = clocksource_default_clock();
 	if (clock->enable)
 		clock->enable(clock);
 	timekeeper_setup_internals(clock);
 
+	ntp_init();
+	write_sequnlock_irqrestore(&xtime_lock, flags);
+}
+
+/*
+ *  timekeeping_late_init - Initaizes the common timekeeping values
+ */
+static int __init timekeeping_late_init(void)
+{
+	unsigned long flags;
+	struct timespec now, boot;
+
+	read_persistent_clock(&now);
+	read_boot_clock(&boot);
+
+	write_seqlock_irqsave(&xtime_lock, flags);
+
 	xtime.tv_sec = now.tv_sec;
 	xtime.tv_nsec = now.tv_nsec;
 	raw_time.tv_sec = 0;
@@ -563,7 +574,10 @@ void __init timekeeping_init(void)
 	total_sleep_time.tv_sec = 0;
 	total_sleep_time.tv_nsec = 0;
 	write_sequnlock_irqrestore(&xtime_lock, flags);
+
+	return 0;
 }
+subsys_initcall(timekeeping_late_init);
 
 /* time in seconds when suspend began */
 static struct timespec timekeeping_suspend_time;
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 2/3] x86: unify current 3 similar ways of saving IRQ info
  2010-05-17  9:15       ` Thomas Gleixner
                           ` (2 preceding siblings ...)
  2010-05-21  2:15         ` [PATCH 1/3] timekeeping: moving xtime's init to a later time Feng Tang
@ 2010-05-21  2:16         ` Feng Tang
  2010-05-21  2:19         ` [PATCH 3/3] x86/mrst: add vrtc driver which serves as a wall clock device Feng Tang
  4 siblings, 0 replies; 49+ messages in thread
From: Feng Tang @ 2010-05-21  2:16 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Jacob Pan, H. Peter Anvin, Ingo Molnar, Du, Alek,
	Arjan van de Ven, LKML, John Stultz, Brown, Len

>From 9ba7685bfdcaa2a5c40eade388902c478bc46071 Mon Sep 17 00:00:00 2001
From: Feng Tang <feng.tang@intel.com>
Date: Thu, 20 May 2010 17:40:05 +0800
Subject: [PATCH 2/3] x86: unify current 3 similar ways of saving IRQ info

There are 3 places defining the similar function of saving IRQ
vector info into mp_irqs[] array: mmparse/acpi/sfi. This patch
will reduce the redundant code, and make it only one API:
	void mp_save_irq(struct mpc_intsrc *m);

Cc: Len Brown <len.brown@intel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Feng Tang <feng.tang@intel.com>
---
 arch/x86/include/asm/mpspec.h |    6 ++++++
 arch/x86/kernel/acpi/boot.c   |   32 +++-----------------------------
 arch/x86/kernel/mpparse.c     |   14 +++++++-------
 arch/x86/kernel/mrst.c        |   30 ++----------------------------
 4 files changed, 18 insertions(+), 64 deletions(-)

diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h
index c82868e..17f4314 100644
--- a/arch/x86/include/asm/mpspec.h
+++ b/arch/x86/include/asm/mpspec.h
@@ -42,6 +42,12 @@ extern int quad_local_to_mp_bus_id [NR_CPUS/4][4];
 
 #endif /* CONFIG_X86_64 */
 
+#ifdef CONFIG_X86_IO_APIC
+void mp_save_irq(struct mpc_intsrc *m);
+#else
+static inline void mp_save_irq(struct mpc_intsrc *m) {}
+#endif
+
 #if defined(CONFIG_MCA) || defined(CONFIG_EISA)
 extern int mp_bus_id_to_type[MAX_MP_BUSSES];
 #endif
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 9a5ed58..8f32fe2 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -923,32 +923,6 @@ static int __init acpi_parse_madt_lapic_entries(void)
 extern int es7000_plat;
 #endif
 
-static void assign_to_mp_irq(struct mpc_intsrc *m,
-				    struct mpc_intsrc *mp_irq)
-{
-	memcpy(mp_irq, m, sizeof(struct mpc_intsrc));
-}
-
-static int mp_irq_cmp(struct mpc_intsrc *mp_irq,
-				struct mpc_intsrc *m)
-{
-	return memcmp(mp_irq, m, sizeof(struct mpc_intsrc));
-}
-
-static void save_mp_irq(struct mpc_intsrc *m)
-{
-	int i;
-
-	for (i = 0; i < mp_irq_entries; i++) {
-		if (!mp_irq_cmp(&mp_irqs[i], m))
-			return;
-	}
-
-	assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
-	if (++mp_irq_entries == MAX_IRQ_SOURCES)
-		panic("Max # of irq sources exceeded!!\n");
-}
-
 void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
 {
 	int ioapic;
@@ -979,7 +953,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
 	mp_irq.dstapic = mp_ioapics[ioapic].apicid; /* APIC ID */
 	mp_irq.dstirq = pin;	/* INTIN# */
 
-	save_mp_irq(&mp_irq);
+	mp_save_irq(&mp_irq);
 
 	isa_irq_to_gsi[bus_irq] = gsi;
 }
@@ -1054,7 +1028,7 @@ void __init mp_config_acpi_legacy_irqs(void)
 		mp_irq.srcbusirq = i; /* Identity mapped */
 		mp_irq.dstirq = pin;
 
-		save_mp_irq(&mp_irq);
+		mp_save_irq(&mp_irq);
 	}
 }
 
@@ -1091,7 +1065,7 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
 	mp_irq.dstapic = mp_ioapics[ioapic].apicid;
 	mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
 
-	save_mp_irq(&mp_irq);
+	mp_save_irq(&mp_irq);
 #endif
 	return 0;
 }
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index 5ae5d24..f5491f7 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -143,7 +143,7 @@ static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)
 		mp_irq->srcbusirq, mp_irq->dstapic, mp_irq->dstirq);
 }
 
-static void __init assign_to_mp_irq(struct mpc_intsrc *m,
+static void assign_to_mp_irq(struct mpc_intsrc *m,
 				    struct mpc_intsrc *mp_irq)
 {
 	mp_irq->dstapic = m->dstapic;
@@ -167,7 +167,7 @@ static void __init assign_to_mpc_intsrc(struct mpc_intsrc *mp_irq,
 	m->dstirq = mp_irq->dstirq;
 }
 
-static int __init mp_irq_mpc_intsrc_cmp(struct mpc_intsrc *mp_irq,
+static int mp_irq_mpc_intsrc_cmp(struct mpc_intsrc *mp_irq,
 					struct mpc_intsrc *m)
 {
 	if (mp_irq->dstapic != m->dstapic)
@@ -188,7 +188,8 @@ static int __init mp_irq_mpc_intsrc_cmp(struct mpc_intsrc *mp_irq,
 	return 0;
 }
 
-static void __init MP_intsrc_info(struct mpc_intsrc *m)
+/* Will also be called in acpi/sfi related code */
+void mp_save_irq(struct mpc_intsrc *m)
 {
 	int i;
 
@@ -206,7 +207,6 @@ static void __init MP_intsrc_info(struct mpc_intsrc *m)
 #else /* CONFIG_X86_IO_APIC */
 static inline void __init MP_bus_info(struct mpc_bus *m) {}
 static inline void __init MP_ioapic_info(struct mpc_ioapic *m) {}
-static inline void __init MP_intsrc_info(struct mpc_intsrc *m) {}
 #endif /* CONFIG_X86_IO_APIC */
 
 
@@ -320,7 +320,7 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
 			skip_entry(&mpt, &count, sizeof(struct mpc_ioapic));
 			break;
 		case MP_INTSRC:
-			MP_intsrc_info((struct mpc_intsrc *)mpt);
+			mp_save_irq((struct mpc_intsrc *)mpt);
 			skip_entry(&mpt, &count, sizeof(struct mpc_intsrc));
 			break;
 		case MP_LINTSRC:
@@ -412,13 +412,13 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type)
 
 		intsrc.srcbusirq = i;
 		intsrc.dstirq = i ? i : 2;	/* IRQ0 to INTIN2 */
-		MP_intsrc_info(&intsrc);
+		mp_save_irq(&intsrc);
 	}
 
 	intsrc.irqtype = mp_ExtINT;
 	intsrc.srcbusirq = 0;
 	intsrc.dstirq = 0;	/* 8259A to INTIN0 */
-	MP_intsrc_info(&intsrc);
+	mp_save_irq(&intsrc);
 }
 
 
diff --git a/arch/x86/kernel/mrst.c b/arch/x86/kernel/mrst.c
index e796448..def416c 100644
--- a/arch/x86/kernel/mrst.c
+++ b/arch/x86/kernel/mrst.c
@@ -33,32 +33,6 @@ struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX];
 EXPORT_SYMBOL_GPL(sfi_mrtc_array);
 int sfi_mrtc_num;
 
-static inline void assign_to_mp_irq(struct mpc_intsrc *m,
-				    struct mpc_intsrc *mp_irq)
-{
-	memcpy(mp_irq, m, sizeof(struct mpc_intsrc));
-}
-
-static inline int mp_irq_cmp(struct mpc_intsrc *mp_irq,
-				struct mpc_intsrc *m)
-{
-	return memcmp(mp_irq, m, sizeof(struct mpc_intsrc));
-}
-
-static void save_mp_irq(struct mpc_intsrc *m)
-{
-	int i;
-
-	for (i = 0; i < mp_irq_entries; i++) {
-		if (!mp_irq_cmp(&mp_irqs[i], m))
-			return;
-	}
-
-	assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
-	if (++mp_irq_entries == MAX_IRQ_SOURCES)
-		panic("Max # of irq sources exceeded!!\n");
-}
-
 /* parse all the mtimer info to a static mtimer array */
 static int __init sfi_parse_mtmr(struct sfi_table_header *table)
 {
@@ -92,7 +66,7 @@ static int __init sfi_parse_mtmr(struct sfi_table_header *table)
 			mp_irq.srcbusirq = pentry->irq;	/* IRQ */
 			mp_irq.dstapic = MP_APIC_ALL;
 			mp_irq.dstirq = pentry->irq;
-			save_mp_irq(&mp_irq);
+			mp_save_irq(&mp_irq);
 	}
 
 	return 0;
@@ -162,7 +136,7 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table)
 		mp_irq.srcbusirq = pentry->irq;	/* IRQ */
 		mp_irq.dstapic = MP_APIC_ALL;
 		mp_irq.dstirq = pentry->irq;
-		save_mp_irq(&mp_irq);
+		mp_save_irq(&mp_irq);
 	}
 	return 0;
 }
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [PATCH 3/3] x86/mrst: add vrtc driver which serves as a wall clock device
  2010-05-17  9:15       ` Thomas Gleixner
                           ` (3 preceding siblings ...)
  2010-05-21  2:16         ` [PATCH 2/3] x86: unify current 3 similar ways of saving IRQ info Feng Tang
@ 2010-05-21  2:19         ` Feng Tang
  4 siblings, 0 replies; 49+ messages in thread
From: Feng Tang @ 2010-05-21  2:19 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Jacob Pan, H. Peter Anvin, Ingo Molnar, Du, Alek, LKML, Alessandro Zummo

>From 14760d3bf6f77a17400c30258e365c06cbc36661 Mon Sep 17 00:00:00 2001
From: Feng Tang <feng.tang@intel.com>
Date: Wed, 24 Mar 2010 10:31:35 +0800
Subject: [PATCH 3/3] x86/mrst: add vrtc driver which serves as a wall clock device

Moorestown platform doesn't have a m146818 RTC device like traditional
x86 PC, but a firmware emulated virtual RTC device(vrtc), which provides
some basic RTC functions like get/set time. vrtc serves as the only
wall clock device on Moorestown platform.

Currently, vrtc init func will be called as arch_initcall() before
xtime's init. Also move the sfi vrtc table parsing from mrst.c to
vrtc.c

There will be another general vrtc driver for rtc subsystem

Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Feng Tang <feng.tang@intel.com>
---
 arch/x86/include/asm/mrst.h |    2 -
 arch/x86/include/asm/vrtc.h |   24 +++++++
 arch/x86/kernel/Makefile    |    2 +-
 arch/x86/kernel/mrst.c      |   45 +-------------
 arch/x86/kernel/vrtc.c      |  147 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 173 insertions(+), 47 deletions(-)
 create mode 100644 arch/x86/include/asm/vrtc.h
 create mode 100644 arch/x86/kernel/vrtc.c

diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h
index 451d30e..fa144f2 100644
--- a/arch/x86/include/asm/mrst.h
+++ b/arch/x86/include/asm/mrst.h
@@ -11,9 +11,7 @@
 #ifndef _ASM_X86_MRST_H
 #define _ASM_X86_MRST_H
 extern int pci_mrst_init(void);
-int __init sfi_parse_mrtc(struct sfi_table_header *table);
 
 #define SFI_MTMR_MAX_NUM 8
-#define SFI_MRTC_MAX	8
 
 #endif /* _ASM_X86_MRST_H */
diff --git a/arch/x86/include/asm/vrtc.h b/arch/x86/include/asm/vrtc.h
new file mode 100644
index 0000000..fcdfcde
--- /dev/null
+++ b/arch/x86/include/asm/vrtc.h
@@ -0,0 +1,24 @@
+#ifndef _MRST_VRTC_H
+#define _MRST_VRTC_H
+
+#define SFI_MRTC_MAX	8
+#define VRTC_IOLEN	1024
+
+#ifdef CONFIG_X86_MRST
+extern unsigned char vrtc_reg_read(unsigned char reg);
+extern void vrtc_reg_write(unsigned char val, unsigned char reg);
+
+extern struct sfi_rtc_table_entry sfi_mrtc_array[];
+#else
+static inline unsigned char vrtc_reg_read(unsigned char reg)
+{
+	return 0xff;
+}
+
+static inline void vrtc_reg_write(unsigned char val, unsigned char reg)
+{
+	return;
+}
+#endif
+
+#endif
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index e77b220..f3fdcbe 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -104,7 +104,7 @@ obj-$(CONFIG_SCx200)		+= scx200.o
 scx200-y			+= scx200_32.o
 
 obj-$(CONFIG_OLPC)		+= olpc.o
-obj-$(CONFIG_X86_MRST)		+= mrst.o
+obj-$(CONFIG_X86_MRST)		+= mrst.o vrtc.o
 
 microcode-y				:= microcode_core.o
 microcode-$(CONFIG_MICROCODE_INTEL)	+= microcode_intel.o
diff --git a/arch/x86/kernel/mrst.c b/arch/x86/kernel/mrst.c
index def416c..fc9268e 100644
--- a/arch/x86/kernel/mrst.c
+++ b/arch/x86/kernel/mrst.c
@@ -29,10 +29,6 @@ static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM];
 static struct sfi_timer_table_entry sfi_mtimer_array[SFI_MTMR_MAX_NUM];
 int sfi_mtimer_num;
 
-struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX];
-EXPORT_SYMBOL_GPL(sfi_mrtc_array);
-int sfi_mrtc_num;
-
 /* parse all the mtimer info to a static mtimer array */
 static int __init sfi_parse_mtmr(struct sfi_table_header *table)
 {
@@ -106,41 +102,6 @@ void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr)
 	}
 }
 
-/* parse all the mrtc info to a global mrtc array */
-int __init sfi_parse_mrtc(struct sfi_table_header *table)
-{
-	struct sfi_table_simple *sb;
-	struct sfi_rtc_table_entry *pentry;
-	struct mpc_intsrc mp_irq;
-
-	int totallen;
-
-	sb = (struct sfi_table_simple *)table;
-	if (!sfi_mrtc_num) {
-		sfi_mrtc_num = SFI_GET_NUM_ENTRIES(sb,
-						struct sfi_rtc_table_entry);
-		pentry = (struct sfi_rtc_table_entry *)sb->pentry;
-		totallen = sfi_mrtc_num * sizeof(*pentry);
-		memcpy(sfi_mrtc_array, pentry, totallen);
-	}
-
-	printk(KERN_INFO "SFI: RTC info (num = %d):\n", sfi_mrtc_num);
-	pentry = sfi_mrtc_array;
-	for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) {
-		printk(KERN_INFO "RTC[%d]: paddr = 0x%08x, irq = %d\n",
-			totallen, (u32)pentry->phys_addr, pentry->irq);
-		mp_irq.type = MP_IOAPIC;
-		mp_irq.irqtype = mp_INT;
-		mp_irq.irqflag = 0;
-		mp_irq.srcbus = 0;
-		mp_irq.srcbusirq = pentry->irq;	/* IRQ */
-		mp_irq.dstapic = MP_APIC_ALL;
-		mp_irq.dstirq = pentry->irq;
-		mp_save_irq(&mp_irq);
-	}
-	return 0;
-}
-
 /*
  * the secondary clock in Moorestown can be APBT or LAPIC clock, default to
  * APBT but cmdline option can also override it.
@@ -174,11 +135,6 @@ void __init mrst_time_init(void)
 	apbt_time_init();
 }
 
-void __init mrst_rtc_init(void)
-{
-	sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
-}
-
 /*
  * if we use per cpu apb timer, the bootclock already setup. if we use lapic
  * timer and one apbt timer for broadcast, we need to set up lapic boot clock.
@@ -207,6 +163,7 @@ void __init x86_mrst_early_setup(void)
 	x86_cpuinit.setup_percpu_clockev = mrst_setup_secondary_clock;
 
 	x86_platform.calibrate_tsc = mrst_calibrate_tsc;
+
 	x86_init.pci.init = pci_mrst_init;
 	x86_init.pci.fixup_irqs = x86_init_noop;
 
diff --git a/arch/x86/kernel/vrtc.c b/arch/x86/kernel/vrtc.c
new file mode 100644
index 0000000..b113c67
--- /dev/null
+++ b/arch/x86/kernel/vrtc.c
@@ -0,0 +1,147 @@
+/*
+ * vrtc.c: Driver for virtual RTC device on Intel MID platform
+ *
+ * (C) Copyright 2010 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * Note:
+ * VRTC is emulated by system controller firmware, the real HW
+ * RTC is located in the PMIC device. SCU FW shadows PMIC RTC
+ * in a memory mapped IO space that is visible to the host IA
+ * processor.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sfi.h>
+
+#include <asm/time.h>
+#include <asm/vrtc.h>
+
+static unsigned char __iomem *vrtc_virt_base;
+struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX];
+EXPORT_SYMBOL_GPL(sfi_mrtc_array);
+static int sfi_mrtc_num;
+
+/* vRTC's registers range from 0x0 to 0xD */
+unsigned char vrtc_reg_read(unsigned char reg)
+{
+	if (unlikely(reg > 0xd || !vrtc_virt_base))
+		return 0xff;
+
+	return __raw_readb(vrtc_virt_base + (reg << 2));
+}
+EXPORT_SYMBOL(vrtc_reg_read);
+
+void vrtc_reg_write(unsigned char val, unsigned char reg)
+{
+	if (unlikely(reg > 0xd || !vrtc_virt_base))
+		return;
+
+	__raw_writeb(val, vrtc_virt_base + (reg << 2));
+}
+EXPORT_SYMBOL(vrtc_reg_write);
+
+static unsigned long vrtc_get_time(void)
+{
+	u8 sec, min, hour, mday, mon;
+	u32 year;
+
+	while ((vrtc_reg_read(RTC_FREQ_SELECT) & RTC_UIP))
+		cpu_relax();
+
+	sec = vrtc_reg_read(RTC_SECONDS);
+	min = vrtc_reg_read(RTC_MINUTES);
+	hour = vrtc_reg_read(RTC_HOURS);
+	mday = vrtc_reg_read(RTC_DAY_OF_MONTH);
+	mon = vrtc_reg_read(RTC_MONTH);
+	year = vrtc_reg_read(RTC_YEAR);
+
+	/* vRTC YEAR reg contains the offset to 1960 */
+	year += 1960;
+
+	pr_debug("vrtc time: %4d-%02d-%02d %02d:%02d:%02d\n",
+		year, mon, mday, hour, min, sec);
+
+	return mktime(year, mon, mday, hour, min, sec);
+}
+
+/* Only care about the minutes and seconds */
+static int vrtc_set_mmss(unsigned long nowtime)
+{
+	int real_sec, real_min;
+	int vrtc_min;
+
+	vrtc_min = vrtc_reg_read(RTC_MINUTES);
+
+	real_sec = nowtime % 60;
+	real_min = nowtime / 60;
+	if (((abs(real_min - vrtc_min) + 15)/30) & 1)
+		real_min += 30;
+	real_min %= 60;
+
+	vrtc_reg_write(real_sec, RTC_SECONDS);
+	vrtc_reg_write(real_min, RTC_MINUTES);
+	return 0;
+}
+
+/* parse all the mrtc info to a global mrtc array */
+static int __init sfi_parse_mrtc(struct sfi_table_header *table)
+{
+	struct sfi_table_simple *sb;
+	struct sfi_rtc_table_entry *pentry;
+	struct mpc_intsrc mp_irq;
+
+	int totallen;
+
+	sb = (struct sfi_table_simple *)table;
+	if (!sfi_mrtc_num) {
+		sfi_mrtc_num = SFI_GET_NUM_ENTRIES(sb,
+						struct sfi_rtc_table_entry);
+		pentry = (struct sfi_rtc_table_entry *)sb->pentry;
+		totallen = sfi_mrtc_num * sizeof(*pentry);
+		memcpy(sfi_mrtc_array, pentry, totallen);
+	}
+
+	pr_info("SFI: RTC info (num = %d):\n", sfi_mrtc_num);
+	pentry = sfi_mrtc_array;
+	for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) {
+		pr_info("RTC[%d]: paddr = 0x%08x, irq = %d\n",
+			totallen, (u32)pentry->phys_addr, pentry->irq);
+		mp_irq.type = MP_IOAPIC;
+		mp_irq.irqtype = mp_INT;
+		mp_irq.irqflag = 0;
+		mp_irq.srcbus = 0;
+		mp_irq.srcbusirq = pentry->irq;
+		mp_irq.dstapic = MP_APIC_ALL;
+		mp_irq.dstirq = pentry->irq;
+		mp_save_irq(&mp_irq);
+	}
+	return 0;
+}
+
+static int __init vrtc_init(void)
+{
+	unsigned long rtc_paddr;
+
+	sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
+	if (!sfi_mrtc_num)
+		return -1;
+
+	rtc_paddr = sfi_mrtc_array[0].phys_addr;
+	vrtc_virt_base = ioremap(rtc_paddr, VRTC_IOLEN);
+	if (!vrtc_virt_base)
+		return -1;
+
+	x86_platform.get_wallclock = vrtc_get_time;
+	x86_platform.set_wallclock = vrtc_set_mmss;
+
+	pr_info("vrtc: successfully inited as a wall clock device.\n");
+	return 0;
+}
+arch_initcall(vrtc_init);
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

end of thread, other threads:[~2010-05-21  2:07 UTC | newest]

Thread overview: 49+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-05-07 17:41 [PATCH 0/8] Moorestown changes in arch/x86 for 35 merge window Jacob Pan
2010-05-07 17:41 ` [PATCH 1/8] x86: avoid check hlt if no timer interrupts Jacob Pan
2010-05-07 20:32   ` RFD: Should we remove the HLT check? (was Re: [PATCH 1/8] x86: avoid check hlt if no timer interrupts) H. Peter Anvin
2010-05-07 20:33     ` Arjan van de Ven
2010-05-07 20:36       ` H. Peter Anvin
2010-05-07 22:24         ` Alan Cox
2010-05-07 22:27           ` H. Peter Anvin
2010-05-07 22:46             ` Alan Cox
2010-05-07 22:35           ` Arjan van de Ven
2010-05-07 20:54       ` Linus Torvalds
2010-05-07 21:04         ` H. Peter Anvin
2010-05-07 22:07           ` jacob pan
2010-05-07 17:41 ` [PATCH 2/8] x86/mrst/pci: return 0 for non-present pci bars Jacob Pan
2010-05-07 17:41 ` [PATCH 3/8] x86/apic: allow use of lapic timer early calibration result Jacob Pan
2010-05-11 13:46   ` Thomas Gleixner
2010-05-11 19:42     ` Pan, Jacob jun
2010-05-11 19:50       ` Thomas Gleixner
2010-05-11 20:46         ` Pan, Jacob jun
2010-05-11 20:51           ` H. Peter Anvin
2010-05-07 17:41 ` [PATCH 4/8] x86/mrst: change clock selection logic to support medfield Jacob Pan
2010-05-11 14:36   ` Thomas Gleixner
2010-05-11 15:30     ` Alan Cox
2010-05-11 15:50       ` Thomas Gleixner
2010-05-11 16:03         ` Alan Cox
2010-05-13 22:16     ` Pan, Jacob jun
2010-05-17  2:14     ` Du, Alek
2010-05-17  2:27     ` Du, Alek
2010-05-07 17:41 ` [PATCH 5/8] x86/apbt: support more timer configurations on mrst Jacob Pan
2010-05-07 17:41 ` [PATCH 6/8] x86/platform: add a wallclock_init func to x86_platforms ops Jacob Pan
2010-05-11 14:42   ` Thomas Gleixner
2010-05-07 17:41 ` [PATCH 7/8] x86/mrst: add vrtc driver which serves as a wall clock device Jacob Pan
2010-05-07 18:51   ` Joe Perches
2010-05-07 19:02     ` Alan Cox
2010-05-07 19:06       ` Joe Perches
2010-05-07 19:56         ` H. Peter Anvin
2010-05-10  9:17           ` Feng Tang
2010-05-10 18:22             ` H. Peter Anvin
2010-05-11  2:30               ` Feng Tang
2010-05-11 14:57   ` Thomas Gleixner
2010-05-12  2:34     ` Feng Tang
2010-05-17  9:15       ` Thomas Gleixner
2010-05-18  6:27         ` Feng Tang
2010-05-18  7:38           ` Thomas Gleixner
2010-05-18 20:43         ` john stultz
2010-05-18 21:02           ` Thomas Gleixner
2010-05-21  2:15         ` [PATCH 1/3] timekeeping: moving xtime's init to a later time Feng Tang
2010-05-21  2:16         ` [PATCH 2/3] x86: unify current 3 similar ways of saving IRQ info Feng Tang
2010-05-21  2:19         ` [PATCH 3/3] x86/mrst: add vrtc driver which serves as a wall clock device Feng Tang
2010-05-07 17:41 ` [PATCH 8/8] x86/mrst: Add nop functions to x86_init mpparse functions Jacob Pan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.