x86: provide delay loop for x86_64.
authorGlauber Costa <gcosta@redhat.com>
Tue, 24 Jun 2008 12:34:08 +0000 (09:34 -0300)
committerIngo Molnar <mingo@elte.hu>
Wed, 9 Jul 2008 06:51:41 +0000 (08:51 +0200)
This is for consistency with i386. We call use_tsc_delay()
at tsc initialization for x86_64, so we'll be always using it.

Signed-off-by: Glauber Costa <gcosta@redhat.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/kernel/tsc.c
arch/x86/lib/delay_64.c

index 3c36f92160c99c1d157e27a341c3541d9a57bfcb..4a775d00195791bc455d35a0f507f0372bade084 100644 (file)
@@ -513,6 +513,7 @@ void __init tsc_init(void)
         */
        for_each_possible_cpu(cpu)
                set_cyc2ns_scale(cpu_khz, cpu);
+       use_tsc_delay();
 
        if (tsc_disabled > 0)
                return;
index 4c441be92641a3ae295c8dea3db10b86323e7de2..d0326d07c845bb9cfe806ae5b74a4ed14058e427 100644 (file)
 #include <asm/smp.h>
 #endif
 
-int __devinit read_current_timer(unsigned long *timer_value)
+/* simple loop based delay: */
+static void delay_loop(unsigned long loops)
 {
-       rdtscll(*timer_value);
-       return 0;
+       asm volatile(
+               "       test %0,%0      \n"
+               "       jz 3f           \n"
+               "       jmp 1f          \n"
+
+               ".align 16              \n"
+               "1:     jmp 2f          \n"
+
+               ".align 16              \n"
+               "2:     dec %0          \n"
+               "       jnz 2b          \n"
+               "3:     dec %0          \n"
+
+               : /* we don't need output */
+               :"a" (loops)
+       );
 }
 
-void __delay(unsigned long loops)
+static void delay_tsc(unsigned long loops)
 {
        unsigned bclock, now;
        int cpu;
@@ -63,6 +78,27 @@ void __delay(unsigned long loops)
        }
        preempt_enable();
 }
+
+static void (*delay_fn)(unsigned long) = delay_loop;
+
+void use_tsc_delay(void)
+{
+       delay_fn = delay_tsc;
+}
+
+int __devinit read_current_timer(unsigned long *timer_value)
+{
+       if (delay_fn == delay_tsc) {
+               rdtscll(*timer_value);
+               return 0;
+       }
+       return -1;
+}
+
+void __delay(unsigned long loops)
+{
+       delay_fn(loops);
+}
 EXPORT_SYMBOL(__delay);
 
 inline void __const_udelay(unsigned long xloops)