aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pasemi/setup.c
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2007-08-21 22:26:43 -0400
committerPaul Mackerras <paulus@samba.org>2007-08-22 01:37:11 -0400
commitdc559f7cd5d6d11a99b6c29402b31fbb3f3a1db0 (patch)
treee7309240d628231b3c70a3319625835289604542 /arch/powerpc/platforms/pasemi/setup.c
parente5d8d54db25790524da34b0143f4e0176fb7677b (diff)
[POWERPC] Rework SMP timebase handoff for pasemi
Rework timebase handoff to play nice with configurations with more than 2 cores, as well as with CPU hotplug. Previous scheme just pushed out the current timebase from the giving core to all cores without caring if they wanted it or not, nor checking if they'd taken it. The taking side didn't make sure the giving side had provided a value yet either. In other words, it was completely broken. Signed-off-by: Olof Johansson <olof@lixom.net> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/pasemi/setup.c')
-rw-r--r--arch/powerpc/platforms/pasemi/setup.c24
1 files changed, 14 insertions, 10 deletions
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index ffe6528048b5..05def6282f83 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -50,26 +50,30 @@ static void pas_restart(char *cmd)
50 50
51#ifdef CONFIG_SMP 51#ifdef CONFIG_SMP
52static DEFINE_SPINLOCK(timebase_lock); 52static DEFINE_SPINLOCK(timebase_lock);
53static unsigned long timebase;
53 54
54static void __devinit pas_give_timebase(void) 55static void __devinit pas_give_timebase(void)
55{ 56{
56 unsigned long tb;
57
58 spin_lock(&timebase_lock); 57 spin_lock(&timebase_lock);
59 mtspr(SPRN_TBCTL, TBCTL_FREEZE); 58 mtspr(SPRN_TBCTL, TBCTL_FREEZE);
60 tb = mftb(); 59 isync();
61 mtspr(SPRN_TBCTL, TBCTL_UPDATE_LOWER | (tb & 0xffffffff)); 60 timebase = get_tb();
62 mtspr(SPRN_TBCTL, TBCTL_UPDATE_UPPER | (tb >> 32));
63 mtspr(SPRN_TBCTL, TBCTL_RESTART);
64 spin_unlock(&timebase_lock); 61 spin_unlock(&timebase_lock);
65 pr_debug("pas_give_timebase: cpu %d gave tb %lx\n", 62
66 smp_processor_id(), tb); 63 while (timebase)
64 barrier();
65 mtspr(SPRN_TBCTL, TBCTL_RESTART);
67} 66}
68 67
69static void __devinit pas_take_timebase(void) 68static void __devinit pas_take_timebase(void)
70{ 69{
71 pr_debug("pas_take_timebase: cpu %d has tb %lx\n", 70 while (!timebase)
72 smp_processor_id(), mftb()); 71 smp_rmb();
72
73 spin_lock(&timebase_lock);
74 set_tb(timebase >> 32, timebase & 0xffffffff);
75 timebase = 0;
76 spin_unlock(&timebase_lock);
73} 77}
74 78
75struct smp_ops_t pas_smp_ops = { 79struct smp_ops_t pas_smp_ops = {