Pull bsp-removal into release branch
[linux-2.6.git] / arch / ia64 / kernel / time.c
index 1ca130a..ac16743 100644 (file)
@@ -255,31 +255,53 @@ time_init (void)
        set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec);
 }
 
-#define SMALLUSECS 100
+/*
+ * Generic udelay assumes that if preemption is allowed and the thread
+ * migrates to another CPU, that the ITC values are synchronized across
+ * all CPUs.
+ */
+static void
+ia64_itc_udelay (unsigned long usecs)
+{
+       unsigned long start = ia64_get_itc();
+       unsigned long end = start + usecs*local_cpu_data->cyc_per_usec;
+
+       while (time_before(ia64_get_itc(), end))
+               cpu_relax();
+}
+
+void (*ia64_udelay)(unsigned long usecs) = &ia64_itc_udelay;
 
 void
 udelay (unsigned long usecs)
 {
-       unsigned long start;
-       unsigned long cycles;
-       unsigned long smallusecs;
+       (*ia64_udelay)(usecs);
+}
+EXPORT_SYMBOL(udelay);
 
-       /*
-        * Execute the non-preemptible delay loop (because the ITC might
-        * not be synchronized between CPUS) in relatively short time
-        * chunks, allowing preemption between the chunks.
-        */
-       while (usecs > 0) {
-               smallusecs = (usecs > SMALLUSECS) ? SMALLUSECS : usecs;
-               preempt_disable();
-               cycles = smallusecs*local_cpu_data->cyc_per_usec;
-               start = ia64_get_itc();
+static unsigned long long ia64_itc_printk_clock(void)
+{
+       if (ia64_get_kr(IA64_KR_PER_CPU_DATA))
+               return sched_clock();
+       return 0;
+}
+
+static unsigned long long ia64_default_printk_clock(void)
+{
+       return (unsigned long long)(jiffies_64 - INITIAL_JIFFIES) *
+               (1000000000/HZ);
+}
 
-               while (ia64_get_itc() - start < cycles)
-                       cpu_relax();
+unsigned long long (*ia64_printk_clock)(void) = &ia64_default_printk_clock;
 
-               preempt_enable();
-               usecs -= smallusecs;
-       }
+unsigned long long printk_clock(void)
+{
+       return ia64_printk_clock();
+}
+
+void __init
+ia64_setup_printk_clock(void)
+{
+       if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT))
+               ia64_printk_clock = ia64_itc_printk_clock;
 }
-EXPORT_SYMBOL(udelay);