[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>
This commit is contained in:
parent
e5d8d54db2
commit
dc559f7cd5
1 changed files with 14 additions and 10 deletions
|
@ -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 = {
|
||||
|
|
Loading…
Reference in a new issue