Commit 6eb10fe9 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[PATCH] x86_64: Auto enable HPET on Summit

From: James Cleverdon

Switch to HPET timer automatically mode on Summit 2
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 2c059083
...@@ -905,6 +905,54 @@ void smp_apic_timer_interrupt(struct pt_regs *regs) ...@@ -905,6 +905,54 @@ void smp_apic_timer_interrupt(struct pt_regs *regs)
irq_exit(); irq_exit();
} }
/*
* oem_force_hpet_timer -- force HPET mode for some boxes.
*
* Thus far, the major user of this is IBM's Summit2 series:
*
* Clustered boxes may have unsynced TSC problems if they are
* multi-chassis. Use available data to take a good guess.
* If in doubt, go HPET.
*/
__init int oem_force_hpet_timer(void)
{
int i, clusters, zeros;
unsigned id;
DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
bitmap_empty(clustermap, NUM_APIC_CLUSTERS);
for (i = 0; i < NR_CPUS; i++) {
id = bios_cpu_apicid[i];
if (id != BAD_APICID)
__set_bit(APIC_CLUSTERID(id), clustermap);
}
/* Problem: Partially populated chassis may not have CPUs in some of
* the APIC clusters they have been allocated. Only present CPUs have
* bios_cpu_apicid entries, thus causing zeroes in the bitmap. Since
* clusters are allocated sequentially, count zeros only if they are
* bounded by ones.
*/
clusters = 0;
zeros = 0;
for (i = 0; i < NUM_APIC_CLUSTERS; i++) {
if (test_bit(i, clustermap)) {
clusters += 1 + zeros;
zeros = 0;
} else
++zeros;
}
/*
* If clusters > 2, then should be multi-chassis. Return 1 for HPET.
* Else return 0 to use TSC.
* May have to revisit this when multi-core + hyperthreaded CPUs come
* out, but AFAIK this will work even for them.
*/
return (clusters > 2);
}
/* /*
* This interrupt should _never_ happen with our APIC/SMP architecture * This interrupt should _never_ happen with our APIC/SMP architecture
*/ */
......
...@@ -928,7 +928,7 @@ void __init time_init_smp(void) ...@@ -928,7 +928,7 @@ void __init time_init_smp(void)
* the TSC. * the TSC.
* *
* Exceptions: * Exceptions:
* IBM Summit. Will need to be special cased later. * IBM Summit2 checked by oem_force_hpet_timer().
* AMD dual core may also not need HPET. Check me. * AMD dual core may also not need HPET. Check me.
* *
* Can be turned off with "notsc". * Can be turned off with "notsc".
...@@ -936,6 +936,9 @@ void __init time_init_smp(void) ...@@ -936,6 +936,9 @@ void __init time_init_smp(void)
if (num_online_cpus() > 1 && if (num_online_cpus() > 1 &&
boot_cpu_data.x86_vendor == X86_VENDOR_AMD) boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
notsc = 1; notsc = 1;
/* Some systems will want to disable TSC and use HPET. */
if (oem_force_hpet_timer())
notsc = 1;
if (vxtime.hpet_address && notsc) { if (vxtime.hpet_address && notsc) {
timetype = "HPET"; timetype = "HPET";
vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick; vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
......
...@@ -54,6 +54,7 @@ extern int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned ch ...@@ -54,6 +54,7 @@ extern int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned ch
extern int hpet_set_periodic_freq(unsigned long freq); extern int hpet_set_periodic_freq(unsigned long freq);
extern int hpet_rtc_dropped_irq(void); extern int hpet_rtc_dropped_irq(void);
extern int hpet_rtc_timer_init(void); extern int hpet_rtc_timer_init(void);
extern int oem_force_hpet_timer(void);
#endif /* CONFIG_HPET_EMULATE_RTC */ #endif /* CONFIG_HPET_EMULATE_RTC */
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment