Merge ../linux-2.6-watchdog-mm
[pandora-kernel.git] / arch / x86_64 / kernel / time.c
index 557e92a..5cc76d0 100644 (file)
@@ -302,20 +302,20 @@ unsigned long long monotonic_clock(void)
 }
 EXPORT_SYMBOL(monotonic_clock);
 
-static noinline void handle_lost_ticks(int lost, struct pt_regs *regs)
+static noinline void handle_lost_ticks(int lost)
 {
        static long lost_count;
        static int warned;
        if (report_lost_ticks) {
                printk(KERN_WARNING "time.c: Lost %d timer tick(s)! ", lost);
-               print_symbol("rip %s)\n", regs->rip);
+               print_symbol("rip %s)\n", get_irq_regs()->rip);
        }
 
        if (lost_count == 1000 && !warned) {
                printk(KERN_WARNING "warning: many lost ticks.\n"
                       KERN_WARNING "Your time source seems to be instable or "
                                "some driver is hogging interupts\n");
-               print_symbol("rip %s\n", regs->rip);
+               print_symbol("rip %s\n", get_irq_regs()->rip);
                if (vxtime.mode == VXTIME_TSC && vxtime.hpet_address) {
                        printk(KERN_WARNING "Falling back to HPET\n");
                        if (hpet_use_timer)
@@ -339,7 +339,7 @@ static noinline void handle_lost_ticks(int lost, struct pt_regs *regs)
 #endif
 }
 
-void main_timer_handler(struct pt_regs *regs)
+void main_timer_handler(void)
 {
        static unsigned long rtc_update = 0;
        unsigned long tsc;
@@ -411,7 +411,7 @@ void main_timer_handler(struct pt_regs *regs)
        }
 
        if (lost > 0)
-               handle_lost_ticks(lost, regs);
+               handle_lost_ticks(lost);
        else
                lost = 0;
 
@@ -421,7 +421,7 @@ void main_timer_handler(struct pt_regs *regs)
 
        do_timer(lost + 1);
 #ifndef CONFIG_SMP
-       update_process_times(user_mode(regs));
+       update_process_times(user_mode(get_irq_regs()));
 #endif
 
 /*
@@ -431,7 +431,7 @@ void main_timer_handler(struct pt_regs *regs)
  */
 
        if (!using_apic_timer)
-               smp_local_timer_interrupt(regs);
+               smp_local_timer_interrupt();
 
 /*
  * If we have an externally synchronized Linux clock, then update CMOS clock
@@ -450,11 +450,11 @@ void main_timer_handler(struct pt_regs *regs)
        write_sequnlock(&xtime_lock);
 }
 
-static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
        if (apic_runs_main_timer > 1)
                return IRQ_HANDLED;
-       main_timer_handler(regs);
+       main_timer_handler();
        if (using_apic_timer)
                smp_send_timer_broadcast_ipi();
        return IRQ_HANDLED;
@@ -563,7 +563,7 @@ static unsigned int cpufreq_delayed_issched = 0;
 static unsigned int cpufreq_init = 0;
 static struct work_struct cpufreq_delayed_get_work;
 
-static void handle_cpufreq_delayed_get(void *v)
+static void handle_cpufreq_delayed_get(struct work_struct *v)
 {
        unsigned int cpu;
        for_each_online_cpu(cpu) {
@@ -639,7 +639,7 @@ static struct notifier_block time_cpufreq_notifier_block = {
 
 static int __init cpufreq_tsc(void)
 {
-       INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL);
+       INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get);
        if (!cpufreq_register_notifier(&time_cpufreq_notifier_block,
                                       CPUFREQ_TRANSITION_NOTIFIER))
                cpufreq_init = 1;
@@ -656,6 +656,25 @@ core_initcall(cpufreq_tsc);
  */
 
 #define TICK_COUNT 100000000
+#define TICK_MIN   5000
+
+/*
+ * Some platforms take periodic SMI interrupts with 5ms duration. Make sure none
+ * occurs between the reads of the hpet & TSC.
+ */
+static void __init read_hpet_tsc(int *hpet, int *tsc)
+{
+       int tsc1, tsc2, hpet1;
+
+       do {
+               tsc1 = get_cycles_sync();
+               hpet1 = hpet_readl(HPET_COUNTER);
+               tsc2 = get_cycles_sync();
+       } while (tsc2 - tsc1 > TICK_MIN);
+       *hpet = hpet1;
+       *tsc = tsc2;
+}
+
 
 static unsigned int __init hpet_calibrate_tsc(void)
 {
@@ -666,13 +685,11 @@ static unsigned int __init hpet_calibrate_tsc(void)
        local_irq_save(flags);
        local_irq_disable();
 
-       hpet_start = hpet_readl(HPET_COUNTER);
-       rdtscl(tsc_start);
+       read_hpet_tsc(&hpet_start, &tsc_start);
 
        do {
                local_irq_disable();
-               hpet_now = hpet_readl(HPET_COUNTER);
-               tsc_now = get_cycles_sync();
+               read_hpet_tsc(&hpet_now, &tsc_now);
                local_irq_restore(flags);
        } while ((tsc_now - tsc_start) < TICK_COUNT &&
                 (hpet_now - hpet_start) < TICK_COUNT);
@@ -876,15 +893,6 @@ static struct irqaction irq0 = {
        timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL
 };
 
-static int __cpuinit
-time_cpu_notifier(struct notifier_block *nb, unsigned long action, void *hcpu)
-{
-       unsigned cpu = (unsigned long) hcpu;
-       if (action == CPU_ONLINE)
-               vsyscall_set_cpu(cpu);
-       return NOTIFY_DONE;
-}
-
 void __init time_init(void)
 {
        if (nohpet)
@@ -925,8 +933,6 @@ void __init time_init(void)
        vxtime.last_tsc = get_cycles_sync();
        set_cyc2ns_scale(cpu_khz);
        setup_irq(0, &irq0);
-       hotcpu_notifier(time_cpu_notifier, 0);
-       time_cpu_notifier(NULL, CPU_ONLINE, (void *)(long)smp_processor_id());
 
 #ifndef CONFIG_SMP
        time_init_gtod();
@@ -948,7 +954,7 @@ __cpuinit int unsynchronized_tsc(void)
        if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
 #ifdef CONFIG_ACPI
                /* But TSC doesn't tick in C3 so don't use it there */
-               if (acpi_fadt.length > 0 && acpi_fadt.plvl3_lat < 100)
+               if (acpi_fadt.length > 0 && acpi_fadt.plvl3_lat < 1000)
                        return 1;
 #endif
                return 0;
@@ -1337,7 +1343,7 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        }
        if (call_rtc_interrupt) {
                rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8));
-               rtc_interrupt(rtc_int_flag, dev_id, regs);
+               rtc_interrupt(rtc_int_flag, dev_id);
        }
        return IRQ_HANDLED;
 }