sparc32: refactor smp boot
Introduce a common smp_callin() function to call from trampoline_32.S. Add platform specific functions to handle the platform details. This is in preparation for a patch that will unify the smp boot stuff for all architectures. sparc32 was significantly different to warrant this patch in preparation. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: David S. Miller <davem@davemloft.net> Cc: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com> Acked-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
76968ad2ea
commit
f9fd3488f6
@@ -48,6 +48,10 @@ extern void sun4m_init_IRQ(void);
|
|||||||
extern void sun4m_unmask_profile_irq(void);
|
extern void sun4m_unmask_profile_irq(void);
|
||||||
extern void sun4m_clear_profile_irq(int cpu);
|
extern void sun4m_clear_profile_irq(int cpu);
|
||||||
|
|
||||||
|
/* sun4m_smp.c */
|
||||||
|
void sun4m_cpu_pre_starting(void *arg);
|
||||||
|
void sun4m_cpu_pre_online(void *arg);
|
||||||
|
|
||||||
/* sun4d_irq.c */
|
/* sun4d_irq.c */
|
||||||
extern spinlock_t sun4d_imsk_lock;
|
extern spinlock_t sun4d_imsk_lock;
|
||||||
|
|
||||||
@@ -60,6 +64,14 @@ extern int show_sun4d_interrupts(struct seq_file *, void *);
|
|||||||
extern void sun4d_distribute_irqs(void);
|
extern void sun4d_distribute_irqs(void);
|
||||||
extern void sun4d_free_irq(unsigned int irq, void *dev_id);
|
extern void sun4d_free_irq(unsigned int irq, void *dev_id);
|
||||||
|
|
||||||
|
/* sun4d_smp.c */
|
||||||
|
void sun4d_cpu_pre_starting(void *arg);
|
||||||
|
void sun4d_cpu_pre_online(void *arg);
|
||||||
|
|
||||||
|
/* leon_smp.c */
|
||||||
|
void leon_cpu_pre_starting(void *arg);
|
||||||
|
void leon_cpu_pre_online(void *arg);
|
||||||
|
|
||||||
/* head_32.S */
|
/* head_32.S */
|
||||||
extern unsigned int t_nmi[];
|
extern unsigned int t_nmi[];
|
||||||
extern unsigned int linux_trap_ipi15_sun4d[];
|
extern unsigned int linux_trap_ipi15_sun4d[];
|
||||||
|
@@ -69,31 +69,19 @@ static inline unsigned long do_swap(volatile unsigned long *ptr,
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __cpuinit leon_callin(void)
|
void __cpuinit leon_cpu_pre_starting(void *arg)
|
||||||
|
{
|
||||||
|
leon_configure_cache_smp();
|
||||||
|
}
|
||||||
|
|
||||||
|
void __cpuinit leon_cpu_pre_online(void *arg)
|
||||||
{
|
{
|
||||||
int cpuid = hard_smp_processor_id();
|
int cpuid = hard_smp_processor_id();
|
||||||
|
|
||||||
local_ops->cache_all();
|
/* Allow master to continue. The master will then give us the
|
||||||
local_ops->tlb_all();
|
* go-ahead by setting the smp_commenced_mask and will wait without
|
||||||
leon_configure_cache_smp();
|
* timeouts until our setup is completed fully (signified by
|
||||||
|
* our bit being set in the cpu_online_mask).
|
||||||
notify_cpu_starting(cpuid);
|
|
||||||
|
|
||||||
/* Get our local ticker going. */
|
|
||||||
register_percpu_ce(cpuid);
|
|
||||||
|
|
||||||
calibrate_delay();
|
|
||||||
smp_store_cpu_info(cpuid);
|
|
||||||
|
|
||||||
local_ops->cache_all();
|
|
||||||
local_ops->tlb_all();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Unblock the master CPU _only_ when the scheduler state
|
|
||||||
* of all secondary CPUs will be up-to-date, so after
|
|
||||||
* the SMP initialization the master will be just allowed
|
|
||||||
* to call the scheduler code.
|
|
||||||
* Allow master to continue.
|
|
||||||
*/
|
*/
|
||||||
do_swap(&cpu_callin_map[cpuid], 1);
|
do_swap(&cpu_callin_map[cpuid], 1);
|
||||||
|
|
||||||
@@ -110,9 +98,6 @@ void __cpuinit leon_callin(void)
|
|||||||
|
|
||||||
while (!cpumask_test_cpu(cpuid, &smp_commenced_mask))
|
while (!cpumask_test_cpu(cpuid, &smp_commenced_mask))
|
||||||
mb();
|
mb();
|
||||||
|
|
||||||
local_irq_enable();
|
|
||||||
set_cpu_online(cpuid, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/cache.h>
|
#include <linux/cache.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
#include <linux/cpu.h>
|
||||||
|
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
#include <linux/atomic.h>
|
#include <linux/atomic.h>
|
||||||
@@ -32,8 +33,10 @@
|
|||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/tlbflush.h>
|
#include <asm/tlbflush.h>
|
||||||
#include <asm/cpudata.h>
|
#include <asm/cpudata.h>
|
||||||
|
#include <asm/timer.h>
|
||||||
#include <asm/leon.h>
|
#include <asm/leon.h>
|
||||||
|
|
||||||
|
#include "kernel.h"
|
||||||
#include "irq.h"
|
#include "irq.h"
|
||||||
|
|
||||||
volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,};
|
volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,};
|
||||||
@@ -294,6 +297,89 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __cpuinit arch_cpu_pre_starting(void *arg)
|
||||||
|
{
|
||||||
|
local_ops->cache_all();
|
||||||
|
local_ops->tlb_all();
|
||||||
|
|
||||||
|
switch(sparc_cpu_model) {
|
||||||
|
case sun4m:
|
||||||
|
sun4m_cpu_pre_starting(arg);
|
||||||
|
break;
|
||||||
|
case sun4d:
|
||||||
|
sun4d_cpu_pre_starting(arg);
|
||||||
|
break;
|
||||||
|
case sparc_leon:
|
||||||
|
leon_cpu_pre_starting(arg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __cpuinit arch_cpu_pre_online(void *arg)
|
||||||
|
{
|
||||||
|
unsigned int cpuid = hard_smp_processor_id();
|
||||||
|
|
||||||
|
register_percpu_ce(cpuid);
|
||||||
|
|
||||||
|
calibrate_delay();
|
||||||
|
smp_store_cpu_info(cpuid);
|
||||||
|
|
||||||
|
local_ops->cache_all();
|
||||||
|
local_ops->tlb_all();
|
||||||
|
|
||||||
|
switch(sparc_cpu_model) {
|
||||||
|
case sun4m:
|
||||||
|
sun4m_cpu_pre_online(arg);
|
||||||
|
break;
|
||||||
|
case sun4d:
|
||||||
|
sun4d_cpu_pre_online(arg);
|
||||||
|
break;
|
||||||
|
case sparc_leon:
|
||||||
|
leon_cpu_pre_online(arg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __cpuinit sparc_start_secondary(void *arg)
|
||||||
|
{
|
||||||
|
unsigned int cpu;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SMP booting is extremely fragile in some architectures. So run
|
||||||
|
* the cpu initialization code first before anything else.
|
||||||
|
*/
|
||||||
|
arch_cpu_pre_starting(arg);
|
||||||
|
|
||||||
|
preempt_disable();
|
||||||
|
cpu = smp_processor_id();
|
||||||
|
|
||||||
|
/* Invoke the CPU_STARTING notifier callbacks */
|
||||||
|
notify_cpu_starting(cpu);
|
||||||
|
|
||||||
|
arch_cpu_pre_online(arg);
|
||||||
|
|
||||||
|
/* Set the CPU in the cpu_online_mask */
|
||||||
|
set_cpu_online(cpu, true);
|
||||||
|
|
||||||
|
/* Enable local interrupts now */
|
||||||
|
local_irq_enable();
|
||||||
|
|
||||||
|
wmb();
|
||||||
|
cpu_idle();
|
||||||
|
|
||||||
|
/* We should never reach here! */
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
void __cpuinit smp_callin(void)
|
||||||
|
{
|
||||||
|
sparc_start_secondary(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void smp_bogo(struct seq_file *m)
|
void smp_bogo(struct seq_file *m)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@@ -50,10 +50,9 @@ static inline void show_leds(int cpuid)
|
|||||||
"i" (ASI_M_CTL));
|
"i" (ASI_M_CTL));
|
||||||
}
|
}
|
||||||
|
|
||||||
void __cpuinit smp4d_callin(void)
|
void __cpuinit sun4d_cpu_pre_starting(void *arg)
|
||||||
{
|
{
|
||||||
int cpuid = hard_smp_processor_id();
|
int cpuid = hard_smp_processor_id();
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
/* Show we are alive */
|
/* Show we are alive */
|
||||||
cpu_leds[cpuid] = 0x6;
|
cpu_leds[cpuid] = 0x6;
|
||||||
@@ -61,26 +60,20 @@ void __cpuinit smp4d_callin(void)
|
|||||||
|
|
||||||
/* Enable level15 interrupt, disable level14 interrupt for now */
|
/* Enable level15 interrupt, disable level14 interrupt for now */
|
||||||
cc_set_imsk((cc_get_imsk() & ~0x8000) | 0x4000);
|
cc_set_imsk((cc_get_imsk() & ~0x8000) | 0x4000);
|
||||||
|
}
|
||||||
|
|
||||||
local_ops->cache_all();
|
void __cpuinit sun4d_cpu_pre_online(void *arg)
|
||||||
local_ops->tlb_all();
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
int cpuid;
|
||||||
|
|
||||||
notify_cpu_starting(cpuid);
|
cpuid = hard_smp_processor_id();
|
||||||
/*
|
|
||||||
* Unblock the master CPU _only_ when the scheduler state
|
/* Unblock the master CPU _only_ when the scheduler state
|
||||||
* of all secondary CPUs will be up-to-date, so after
|
* of all secondary CPUs will be up-to-date, so after
|
||||||
* the SMP initialization the master will be just allowed
|
* the SMP initialization the master will be just allowed
|
||||||
* to call the scheduler code.
|
* to call the scheduler code.
|
||||||
*/
|
*/
|
||||||
/* Get our local ticker going. */
|
|
||||||
register_percpu_ce(cpuid);
|
|
||||||
|
|
||||||
calibrate_delay();
|
|
||||||
smp_store_cpu_info(cpuid);
|
|
||||||
local_ops->cache_all();
|
|
||||||
local_ops->tlb_all();
|
|
||||||
|
|
||||||
/* Allow master to continue. */
|
|
||||||
sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1);
|
sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1);
|
||||||
local_ops->cache_all();
|
local_ops->cache_all();
|
||||||
local_ops->tlb_all();
|
local_ops->tlb_all();
|
||||||
@@ -106,16 +99,12 @@ void __cpuinit smp4d_callin(void)
|
|||||||
local_ops->cache_all();
|
local_ops->cache_all();
|
||||||
local_ops->tlb_all();
|
local_ops->tlb_all();
|
||||||
|
|
||||||
local_irq_enable(); /* We don't allow PIL 14 yet */
|
|
||||||
|
|
||||||
while (!cpumask_test_cpu(cpuid, &smp_commenced_mask))
|
while (!cpumask_test_cpu(cpuid, &smp_commenced_mask))
|
||||||
barrier();
|
barrier();
|
||||||
|
|
||||||
spin_lock_irqsave(&sun4d_imsk_lock, flags);
|
spin_lock_irqsave(&sun4d_imsk_lock, flags);
|
||||||
cc_set_imsk(cc_get_imsk() & ~0x4000); /* Allow PIL 14 as well */
|
cc_set_imsk(cc_get_imsk() & ~0x4000); /* Allow PIL 14 as well */
|
||||||
spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
|
spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
|
||||||
set_cpu_online(cpuid, true);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -34,30 +34,19 @@ swap_ulong(volatile unsigned long *ptr, unsigned long val)
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __cpuinit smp4m_callin(void)
|
void __cpuinit sun4m_cpu_pre_starting(void *arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void __cpuinit sun4m_cpu_pre_online(void *arg)
|
||||||
{
|
{
|
||||||
int cpuid = hard_smp_processor_id();
|
int cpuid = hard_smp_processor_id();
|
||||||
|
|
||||||
local_ops->cache_all();
|
/* Allow master to continue. The master will then give us the
|
||||||
local_ops->tlb_all();
|
* go-ahead by setting the smp_commenced_mask and will wait without
|
||||||
|
* timeouts until our setup is completed fully (signified by
|
||||||
notify_cpu_starting(cpuid);
|
* our bit being set in the cpu_online_mask).
|
||||||
|
|
||||||
register_percpu_ce(cpuid);
|
|
||||||
|
|
||||||
calibrate_delay();
|
|
||||||
smp_store_cpu_info(cpuid);
|
|
||||||
|
|
||||||
local_ops->cache_all();
|
|
||||||
local_ops->tlb_all();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Unblock the master CPU _only_ when the scheduler state
|
|
||||||
* of all secondary CPUs will be up-to-date, so after
|
|
||||||
* the SMP initialization the master will be just allowed
|
|
||||||
* to call the scheduler code.
|
|
||||||
*/
|
*/
|
||||||
/* Allow master to continue. */
|
|
||||||
swap_ulong(&cpu_callin_map[cpuid], 1);
|
swap_ulong(&cpu_callin_map[cpuid], 1);
|
||||||
|
|
||||||
/* XXX: What's up with all the flushes? */
|
/* XXX: What's up with all the flushes? */
|
||||||
@@ -75,10 +64,6 @@ void __cpuinit smp4m_callin(void)
|
|||||||
|
|
||||||
while (!cpumask_test_cpu(cpuid, &smp_commenced_mask))
|
while (!cpumask_test_cpu(cpuid, &smp_commenced_mask))
|
||||||
mb();
|
mb();
|
||||||
|
|
||||||
local_irq_enable();
|
|
||||||
|
|
||||||
set_cpu_online(cpuid, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -79,18 +79,15 @@ cpu3_startup:
|
|||||||
nop
|
nop
|
||||||
|
|
||||||
/* Start this processor. */
|
/* Start this processor. */
|
||||||
call smp4m_callin
|
call smp_callin
|
||||||
nop
|
nop
|
||||||
|
|
||||||
b,a smp_do_cpu_idle
|
b,a smp_panic
|
||||||
|
|
||||||
.text
|
.text
|
||||||
.align 4
|
.align 4
|
||||||
|
|
||||||
smp_do_cpu_idle:
|
smp_panic:
|
||||||
call cpu_idle
|
|
||||||
mov 0, %o0
|
|
||||||
|
|
||||||
call cpu_panic
|
call cpu_panic
|
||||||
nop
|
nop
|
||||||
|
|
||||||
@@ -144,10 +141,10 @@ sun4d_cpu_startup:
|
|||||||
nop
|
nop
|
||||||
|
|
||||||
/* Start this processor. */
|
/* Start this processor. */
|
||||||
call smp4d_callin
|
call smp_callin
|
||||||
nop
|
nop
|
||||||
|
|
||||||
b,a smp_do_cpu_idle
|
b,a smp_panic
|
||||||
|
|
||||||
__CPUINIT
|
__CPUINIT
|
||||||
.align 4
|
.align 4
|
||||||
@@ -201,7 +198,7 @@ leon_smp_cpu_startup:
|
|||||||
nop
|
nop
|
||||||
|
|
||||||
/* Start this processor. */
|
/* Start this processor. */
|
||||||
call leon_callin
|
call smp_callin
|
||||||
nop
|
nop
|
||||||
|
|
||||||
b,a smp_do_cpu_idle
|
b,a smp_panic
|
||||||
|
Reference in New Issue
Block a user