Skip to content

Commit

Permalink
[POWERPC] Rework SMP timebase handoff for pasemi
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Olof Johansson authored and Paul Mackerras committed Aug 22, 2007
1 parent e5d8d54 commit dc559f7
Showing 1 changed file with 14 additions and 10 deletions.
24 changes: 14 additions & 10 deletions arch/powerpc/platforms/pasemi/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,26 +50,30 @@ static void pas_restart(char *cmd)

#ifdef CONFIG_SMP
static DEFINE_SPINLOCK(timebase_lock);
static unsigned long timebase;

static void __devinit pas_give_timebase(void)
{
unsigned long tb;

spin_lock(&timebase_lock);
mtspr(SPRN_TBCTL, TBCTL_FREEZE);
tb = mftb();
mtspr(SPRN_TBCTL, TBCTL_UPDATE_LOWER | (tb & 0xffffffff));
mtspr(SPRN_TBCTL, TBCTL_UPDATE_UPPER | (tb >> 32));
mtspr(SPRN_TBCTL, TBCTL_RESTART);
isync();
timebase = get_tb();
spin_unlock(&timebase_lock);
pr_debug("pas_give_timebase: cpu %d gave tb %lx\n",
smp_processor_id(), tb);

while (timebase)
barrier();
mtspr(SPRN_TBCTL, TBCTL_RESTART);
}

static void __devinit pas_take_timebase(void)
{
pr_debug("pas_take_timebase: cpu %d has tb %lx\n",
smp_processor_id(), mftb());
while (!timebase)
smp_rmb();

spin_lock(&timebase_lock);
set_tb(timebase >> 32, timebase & 0xffffffff);
timebase = 0;
spin_unlock(&timebase_lock);
}

struct smp_ops_t pas_smp_ops = {
Expand Down

0 comments on commit dc559f7

Please sign in to comment.