From 8ad200d7b7c8fac77cf705831e90e889360d7030 Mon Sep 17 00:00:00 2001
From: Paul Mackerras <paulus@samba.org>
Date: Fri, 4 Nov 2005 13:28:58 +1100
Subject: [PATCH] powerpc: Merge smp-tbsync.c (the generic timebase sync
 routine)

Signed-off-by: Paul Mackerras <paulus@samba.org>
---
 arch/powerpc/Kconfig                        |   7 ++
 arch/powerpc/kernel/Makefile                |   1 +
 arch/{ppc64 => powerpc}/kernel/smp-tbsync.c | 110 +++++++++-----------
 arch/ppc64/Kconfig                          |   5 +
 arch/ppc64/kernel/Makefile                  |   5 -
 5 files changed, 64 insertions(+), 64 deletions(-)
 rename arch/{ppc64 => powerpc}/kernel/smp-tbsync.c (52%)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 3cf03ab46113..f4e25c648fbb 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -300,6 +300,7 @@ config PPC_PMAC64
 	bool
 	depends on PPC_PMAC && POWER4
 	select U3_DART
+	select GENERIC_TBSYNC
 	default y
 
 config PPC_PREP
@@ -314,6 +315,7 @@ config PPC_MAPLE
 	bool "  Maple 970FX Evaluation Board"
 	select U3_DART
 	select MPIC_BROKEN_U3
+	select GENERIC_TBSYNC
 	default n
 	help
           This option enables support for the Maple 970FX Evaluation Board.
@@ -386,6 +388,11 @@ config PPC_MPC106
 	bool
 	default n
 
+config GENERIC_TBSYNC
+	bool
+	default y if CONFIG_PPC32 && CONFIG_SMP
+	default n
+
 source "drivers/cpufreq/Kconfig"
 
 config CPU_FREQ_PMAC
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 7a3e1155ac9a..631149ea93db 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_PPC_RTAS)		+= rtas.o
 obj-$(CONFIG_RTAS_FLASH)	+= rtas_flash.o
 obj-$(CONFIG_RTAS_PROC)		+= rtas-proc.o
 obj-$(CONFIG_IBMVIO)		+= vio.o
+obj-$(CONFIG_GENERIC_TBSYNC)	+= smp-tbsync.o
 
 ifeq ($(CONFIG_PPC_MERGE),y)
 
diff --git a/arch/ppc64/kernel/smp-tbsync.c b/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 7d8ec9996b3e..9adef3bddad4 100644
--- a/arch/ppc64/kernel/smp-tbsync.c
+++ b/arch/powerpc/kernel/smp-tbsync.c
@@ -22,11 +22,11 @@ enum {
 };
 
 static struct {
-	volatile long		tb;
-	volatile long		mark;
+	volatile u64		tb;
+	volatile u64		mark;
 	volatile int		cmd;
 	volatile int		handshake;
-	int			filler[3];
+	int			filler[2];
 
 	volatile int		ack;
 	int			filler2[7];
@@ -36,89 +36,80 @@ static struct {
 
 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;
 }
 
-void __devinit
-smp_generic_take_timebase( void )
+void __devinit smp_generic_take_timebase(void)
 {
 	int cmd;
-	long tb;
+	u64 tb;
 
 	local_irq_disable();
-	while( !running )
-		;
+	while (!running)
+		barrier();
 	rmb();
 
-	for( ;; ) {
+	for (;;) {
 		tbsync->ack = 1;
-		while( !tbsync->handshake )
-			;
+		while (!tbsync->handshake)
+			barrier();
 		rmb();
 
 		cmd = tbsync->cmd;
 		tb = tbsync->tb;
+		mb();
 		tbsync->ack = 0;
-		if( cmd == kExit )
-			return;
+		if (cmd == kExit)
+			break;
 
-		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 );
+		while (tbsync->handshake)
+			barrier();
+		if (cmd == kSetAndTest)
+			set_tb(tb >> 32, tb & 0xfffffffful);
+		enter_contest(tbsync->mark, -1);
 	}
 	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;
-	long tb, mark;
+	u64 tb;
+	long mark;
 
 	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;
-		while( tbsync->ack )
-			;
+		while (tbsync->ack)
+			barrier();
 
-		while( (long)(mftb() - tb) <= 0 )
-			;
+		while (get_tb() <= tb)
+			barrier();
 		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;
 }
 
-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;
 
@@ -130,14 +121,14 @@ smp_generic_give_timebase( void )
 	mb();
 	running = 1;
 
-	while( !tbsync->ack )
-		;
+	while (!tbsync->ack)
+		barrier();
 
 	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 );
 
@@ -147,21 +138,22 @@ smp_generic_give_timebase( void )
 			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 */
-	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;
-		if( score2 <= score || score2 < 20 )
+		if (score2 <= score || score2 < 20)
 			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;
-	while( tbsync->ack )
-		;
+	while (tbsync->ack)
+		barrier();
 	tbsync->handshake = 0;
-	kfree( tbsync );
+	kfree(tbsync);
 	tbsync = NULL;
 	running = 0;
 }
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index 42677cc96508..b987164fca4c 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -89,12 +89,14 @@ config PPC_PMAC
 	bool "  Apple G5 based machines"
 	default y
 	select U3_DART
+	select GENERIC_TBSYNC
 
 config PPC_MAPLE
 	depends on PPC_MULTIPLATFORM
 	bool "  Maple 970FX Evaluation Board"
 	select U3_DART
 	select MPIC_BROKEN_U3
+	select GENERIC_TBSYNC
 	default n
 	help
           This option enables support for the Maple 970FX Evaluation Board.
@@ -182,6 +184,9 @@ config MPIC_BROKEN_U3
 	depends on PPC_MAPLE
 	default y
 
+config GENERIC_TBSYNC
+	def_bool n
+
 config PPC_PMAC64
 	bool
 	depends on PPC_PMAC
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index 430cb3900a07..f597c2954b71 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -51,11 +51,6 @@ obj-$(CONFIG_PPC_PMAC)		+= udbg_scc.o
 
 obj-$(CONFIG_PPC_MAPLE)		+= udbg_16550.o
 
-ifdef CONFIG_SMP
-obj-$(CONFIG_PPC_PMAC)		+= smp-tbsync.o
-obj-$(CONFIG_PPC_MAPLE)		+= smp-tbsync.o
-endif
-
 obj-$(CONFIG_KPROBES)		+= kprobes.o
 
 CFLAGS_ioctl32.o += -Ifs/