diff options
Diffstat (limited to 'arch/powerpc/platforms/pasemi/setup.c')
-rw-r--r-- | arch/powerpc/platforms/pasemi/setup.c | 24 |
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 |
52 | static DEFINE_SPINLOCK(timebase_lock); | 52 | static DEFINE_SPINLOCK(timebase_lock); |
53 | static unsigned long timebase; | ||
53 | 54 | ||
54 | static void __devinit pas_give_timebase(void) | 55 | static 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 | ||
69 | static void __devinit pas_take_timebase(void) | 68 | static 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 | ||
75 | struct smp_ops_t pas_smp_ops = { | 79 | struct smp_ops_t pas_smp_ops = { |