Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq
[safe/jmp/linux-2.6] / arch / x86 / kernel / time_64.c
index 12b4a71..5ba343e 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/time.h>
+#include <linux/mca.h>
+#include <linux/nmi.h>
 
 #include <asm/i8253.h>
 #include <asm/hpet.h>
-#include <asm/nmi.h>
 #include <asm/vgtod.h>
 #include <asm/time.h>
 #include <asm/timer.h>
@@ -33,30 +34,41 @@ unsigned long profile_pc(struct pt_regs *regs)
        /* Assume the lock function has either no stack frame or a copy
           of flags from PUSHF
           Eflags always has bits 22 and up cleared unlike kernel addresses. */
-       if (!user_mode(regs) && in_lock_functions(pc)) {
+       if (!user_mode_vm(regs) && in_lock_functions(pc)) {
+#ifdef CONFIG_FRAME_POINTER
+               return *(unsigned long *)(regs->bp + sizeof(long));
+#else
                unsigned long *sp = (unsigned long *)regs->sp;
                if (sp[0] >> 22)
                        return sp[0];
                if (sp[1] >> 22)
                        return sp[1];
+#endif
        }
        return pc;
 }
 EXPORT_SYMBOL(profile_pc);
 
-static irqreturn_t timer_event_interrupt(int irq, void *dev_id)
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
-       add_pda(irq0_irqs, 1);
+       inc_irq_stat(irq0_irqs);
 
        global_clock_event->event_handler(global_clock_event);
 
+#ifdef CONFIG_MCA
+       if (MCA_bus) {
+               u8 irq_v = inb_p(0x61);       /* read the current state */
+               outb_p(irq_v|0x80, 0x61);     /* reset the IRQ */
+       }
+#endif
+
        return IRQ_HANDLED;
 }
 
 /* calibrate_cpu is used on systems with fixed rate TSCs to determine
  * processor frequency */
 #define TICK_COUNT 100000000
-unsigned long __init native_calculate_cpu_khz(void)
+unsigned long __init calibrate_cpu(void)
 {
        int tsc_start, tsc_now;
        int i, no_ctr_free;
@@ -68,6 +80,8 @@ unsigned long __init native_calculate_cpu_khz(void)
                        break;
        no_ctr_free = (i == 4);
        if (no_ctr_free) {
+               WARN(1, KERN_WARNING "Warning: AMD perfctrs busy ... "
+                    "cpu_khz value may be incorrect.\n");
                i = 3;
                rdmsrl(MSR_K7_EVNTSEL3, evntsel3);
                wrmsrl(MSR_K7_EVNTSEL3, 0);
@@ -100,9 +114,8 @@ unsigned long __init native_calculate_cpu_khz(void)
 }
 
 static struct irqaction irq0 = {
-       .handler        = timer_event_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING,
-       .mask           = CPU_MASK_NONE,
+       .handler        = timer_interrupt,
+       .flags          = IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING | IRQF_TIMER,
        .name           = "timer"
 };
 
@@ -116,25 +129,7 @@ void __init hpet_time_init(void)
 
 void __init time_init(void)
 {
-       tsc_calibrate();
-
-       cpu_khz = tsc_khz;
-       if (cpu_has(&boot_cpu_data, X86_FEATURE_CONSTANT_TSC) &&
-               (boot_cpu_data.x86_vendor == X86_VENDOR_AMD))
-               cpu_khz = calculate_cpu_khz();
-
-       lpj_tsc = ((unsigned long)tsc_khz * 1000)/HZ;
-
-       if (unsynchronized_tsc())
-               mark_tsc_unstable("TSCs unsynchronized");
-
-       if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP))
-               vgetcpu_mode = VGETCPU_RDTSCP;
-       else
-               vgetcpu_mode = VGETCPU_LSL;
+       tsc_init();
 
-       printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
-               cpu_khz / 1000, cpu_khz % 1000);
-       init_tsc_clocksource();
        late_time_init = choose_time_init();
 }