powerpc: Merge smp-tbsync.c (the generic timebase sync routine)
[linux-2.6.git] / arch / powerpc / kernel / smp-tbsync.c
similarity index 52%
rename from arch/ppc64/kernel/smp-tbsync.c
rename to arch/powerpc/kernel/smp-tbsync.c
index 7d8ec9996b3e7ea91f4f3dd3ba18a12d616f5a07..9adef3bddad41b335beb6b1188770941cd6353fd 100644 (file)
@@ -22,11 +22,11 @@ enum {
 };
 
 static struct {
 };
 
 static struct {
-       volatile long           tb;
-       volatile long           mark;
+       volatile u64            tb;
+       volatile u64            mark;
        volatile int            cmd;
        volatile int            handshake;
        volatile int            cmd;
        volatile int            handshake;
-       int                     filler[3];
+       int                     filler[2];
 
        volatile int            ack;
        int                     filler2[7];
 
        volatile int            ack;
        int                     filler2[7];
@@ -36,89 +36,80 @@ static struct {
 
 static volatile int            running;
 
 
 static volatile int            running;
 
-static void __devinit
-enter_contest( long mark, long add )
+static void __devinit enter_contest(u64 mark, long add)
 {
 {
-       while( (long)(mftb() - mark) < 0 )
+       while (get_tb() < mark)
                tbsync->race_result = add;
 }
 
                tbsync->race_result = add;
 }
 
-void __devinit
-smp_generic_take_timebase( void )
+void __devinit smp_generic_take_timebase(void)
 {
        int cmd;
 {
        int cmd;
-       long tb;
+       u64 tb;
 
        local_irq_disable();
 
        local_irq_disable();
-       while( !running )
-               ;
+       while (!running)
+               barrier();
        rmb();
 
        rmb();
 
-       for( ;; ) {
+       for (;;) {
                tbsync->ack = 1;
                tbsync->ack = 1;
-               while( !tbsync->handshake )
-                       ;
+               while (!tbsync->handshake)
+                       barrier();
                rmb();
 
                cmd = tbsync->cmd;
                tb = tbsync->tb;
                rmb();
 
                cmd = tbsync->cmd;
                tb = tbsync->tb;
+               mb();
                tbsync->ack = 0;
                tbsync->ack = 0;
-               if( cmd == kExit )
-                       return;
-
-               if( cmd == kSetAndTest ) {
-                       while( tbsync->handshake )
-                               ;
-                       asm volatile ("mttbl %0" :: "r" (tb & 0xfffffffful) );
-                       asm volatile ("mttbu %0" :: "r" (tb >> 32) );
-               } else {
-                       while( tbsync->handshake )
-                               ;
-               }
-               enter_contest( tbsync->mark, -1 );
+               if (cmd == kExit)
+                       break;
+
+               while (tbsync->handshake)
+                       barrier();
+               if (cmd == kSetAndTest)
+                       set_tb(tb >> 32, tb & 0xfffffffful);
+               enter_contest(tbsync->mark, -1);
        }
        local_irq_enable();
 }
 
        }
        local_irq_enable();
 }
 
-static int __devinit
-start_contest( int cmd, long offset, long num )
+static int __devinit start_contest(int cmd, long offset, int num)
 {
        int i, score=0;
 {
        int i, score=0;
-       long tb, mark;
+       u64 tb;
+       long mark;
 
        tbsync->cmd = cmd;
 
        local_irq_disable();
 
        tbsync->cmd = cmd;
 
        local_irq_disable();
-       for( i=-3; i<num; ) {
-               tb = (long)mftb() + 400;
+       for (i = -3; i < num; ) {
+               tb = get_tb() + 400;
                tbsync->tb = tb + offset;
                tbsync->mark = mark = tb + 400;
 
                wmb();
 
                tbsync->handshake = 1;
                tbsync->tb = tb + offset;
                tbsync->mark = mark = tb + 400;
 
                wmb();
 
                tbsync->handshake = 1;
-               while( tbsync->ack )
-                       ;
+               while (tbsync->ack)
+                       barrier();
 
 
-               while( (long)(mftb() - tb) <= 0 )
-                       ;
+               while (get_tb() <= tb)
+                       barrier();
                tbsync->handshake = 0;
                tbsync->handshake = 0;
-               enter_contest( mark, 1 );
+               enter_contest(mark, 1);
 
 
-               while( !tbsync->ack )
-                       ;
+               while (!tbsync->ack)
+                       barrier();
 
 
-               if ((tbsync->tb ^ (long)mftb()) & 0x8000000000000000ul)
-                       continue;
-               if( i++ > 0 )
+               if (i++ > 0)
                        score += tbsync->race_result;
        }
        local_irq_enable();
        return score;
 }
 
                        score += tbsync->race_result;
        }
        local_irq_enable();
        return score;
 }
 
-void __devinit
-smp_generic_give_timebase( void )
+void __devinit smp_generic_give_timebase(void)
 {
        int i, score, score2, old, min=0, max=5000, offset=1000;
 
 {
        int i, score, score2, old, min=0, max=5000, offset=1000;
 
@@ -130,14 +121,14 @@ smp_generic_give_timebase( void )
        mb();
        running = 1;
 
        mb();
        running = 1;
 
-       while( !tbsync->ack )
-               ;
+       while (!tbsync->ack)
+               barrier();
 
        printk("Got ack\n");
 
        /* binary search */
 
        printk("Got ack\n");
 
        /* binary search */
-       for( old=-1 ; old != offset ; offset=(min+max)/2 ) {
-               score = start_contest( kSetAndTest, offset, NUM_ITER );
+       for (old = -1; old != offset ; offset = (min+max) / 2) {
+               score = start_contest(kSetAndTest, offset, NUM_ITER);
 
                printk("score %d, offset %d\n", score, offset );
 
 
                printk("score %d, offset %d\n", score, offset );
 
@@ -147,21 +138,22 @@ smp_generic_give_timebase( void )
                        min = offset;
                old = offset;
        }
                        min = offset;
                old = offset;
        }
-       score = start_contest( kSetAndTest, min, NUM_ITER );
-       score2 = start_contest( kSetAndTest, max, NUM_ITER );
+       score = start_contest(kSetAndTest, min, NUM_ITER);
+       score2 = start_contest(kSetAndTest, max, NUM_ITER);
 
 
-       printk( "Min %d (score %d), Max %d (score %d)\n", min, score, max, score2 );
-       score = abs( score );
-       score2 = abs( score2 );
+       printk("Min %d (score %d), Max %d (score %d)\n",
+              min, score, max, score2);
+       score = abs(score);
+       score2 = abs(score2);
        offset = (score < score2) ? min : max;
 
        /* guard against inaccurate mttb */
        offset = (score < score2) ? min : max;
 
        /* guard against inaccurate mttb */
-       for( i=0; i<10; i++ ) {
-               start_contest( kSetAndTest, offset, NUM_ITER/10 );
+       for (i = 0; i < 10; i++) {
+               start_contest(kSetAndTest, offset, NUM_ITER/10);
 
 
-               if( (score2=start_contest(kTest, offset, NUM_ITER)) < 0 )
+               if ((score2 = start_contest(kTest, offset, NUM_ITER)) < 0)
                        score2 = -score2;
                        score2 = -score2;
-               if( score2 <= score || score2 < 20 )
+               if (score2 <= score || score2 < 20)
                        break;
        }
        printk("Final offset: %d (%d/%d)\n", offset, score2, NUM_ITER );
                        break;
        }
        printk("Final offset: %d (%d/%d)\n", offset, score2, NUM_ITER );
@@ -170,10 +162,10 @@ smp_generic_give_timebase( void )
        tbsync->cmd = kExit;
        wmb();
        tbsync->handshake = 1;
        tbsync->cmd = kExit;
        wmb();
        tbsync->handshake = 1;
-       while( tbsync->ack )
-               ;
+       while (tbsync->ack)
+               barrier();
        tbsync->handshake = 0;
        tbsync->handshake = 0;
-       kfree( tbsync );
+       kfree(tbsync);
        tbsync = NULL;
        running = 0;
 }
        tbsync = NULL;
        running = 0;
 }