[SPARC]: Try to start getting SMP back into shape.
Todo items: - IRQ_INPROGRESS flag - use sparc64 irq buckets, or generic irq_desc? - sun4d - re-indent large chunks of sun4m_smp.c - some places assume sequential cpu numbering (i.e. 0,1 instead of 0,2) Last I checked (with 2.6.14), random programs segfault with dual HyperSPARC. And with SuperSPARC II's, it seems stable but will eventually die from a write lock error (wrong lock owner or something). I haven't tried the HyperSPARC + highmem combination recently, so that may still be a problem. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
674a396c6d
commit
a54123e277
|
@ -23,7 +23,6 @@ menu "General machine setup"
|
|||
|
||||
config SMP
|
||||
bool "Symmetric multi-processing support (does not work on sun4/sun4c)"
|
||||
depends on BROKEN
|
||||
---help---
|
||||
This enables support for systems with more than one CPU. If you have
|
||||
a system with only one CPU, say N. If you have a system with more
|
||||
|
|
|
@ -154,9 +154,11 @@ void (*sparc_init_timers)(irqreturn_t (*)(int, void *,struct pt_regs *)) =
|
|||
struct irqaction static_irqaction[MAX_STATIC_ALLOC];
|
||||
int static_irq_count;
|
||||
|
||||
struct irqaction *irq_action[NR_IRQS] = {
|
||||
[0 ... (NR_IRQS-1)] = NULL
|
||||
};
|
||||
struct {
|
||||
struct irqaction *action;
|
||||
int flags;
|
||||
} sparc_irq[NR_IRQS];
|
||||
#define SPARC_IRQ_INPROGRESS 1
|
||||
|
||||
/* Used to protect the IRQ action lists */
|
||||
DEFINE_SPINLOCK(irq_action_lock);
|
||||
|
@ -177,7 +179,7 @@ int show_interrupts(struct seq_file *p, void *v)
|
|||
}
|
||||
spin_lock_irqsave(&irq_action_lock, flags);
|
||||
if (i < NR_IRQS) {
|
||||
action = *(i + irq_action);
|
||||
action = sparc_irq[i].action;
|
||||
if (!action)
|
||||
goto out_unlock;
|
||||
seq_printf(p, "%3d: ", i);
|
||||
|
@ -186,7 +188,7 @@ int show_interrupts(struct seq_file *p, void *v)
|
|||
#else
|
||||
for_each_online_cpu(j) {
|
||||
seq_printf(p, "%10u ",
|
||||
kstat_cpu(cpu_logical_map(j)).irqs[i]);
|
||||
kstat_cpu(j).irqs[i]);
|
||||
}
|
||||
#endif
|
||||
seq_printf(p, " %c %s",
|
||||
|
@ -207,7 +209,7 @@ out_unlock:
|
|||
void free_irq(unsigned int irq, void *dev_id)
|
||||
{
|
||||
struct irqaction * action;
|
||||
struct irqaction * tmp = NULL;
|
||||
struct irqaction **actionp;
|
||||
unsigned long flags;
|
||||
unsigned int cpu_irq;
|
||||
|
||||
|
@ -225,7 +227,8 @@ void free_irq(unsigned int irq, void *dev_id)
|
|||
|
||||
spin_lock_irqsave(&irq_action_lock, flags);
|
||||
|
||||
action = *(cpu_irq + irq_action);
|
||||
actionp = &sparc_irq[cpu_irq].action;
|
||||
action = *actionp;
|
||||
|
||||
if (!action->handler) {
|
||||
printk("Trying to free free IRQ%d\n",irq);
|
||||
|
@ -235,7 +238,7 @@ void free_irq(unsigned int irq, void *dev_id)
|
|||
for (; action; action = action->next) {
|
||||
if (action->dev_id == dev_id)
|
||||
break;
|
||||
tmp = action;
|
||||
actionp = &action->next;
|
||||
}
|
||||
if (!action) {
|
||||
printk("Trying to free free shared IRQ%d\n",irq);
|
||||
|
@ -254,11 +257,8 @@ void free_irq(unsigned int irq, void *dev_id)
|
|||
irq, action->name);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (action && tmp)
|
||||
tmp->next = action->next;
|
||||
else
|
||||
*(cpu_irq + irq_action) = action->next;
|
||||
|
||||
*actionp = action->next;
|
||||
|
||||
spin_unlock_irqrestore(&irq_action_lock, flags);
|
||||
|
||||
|
@ -268,7 +268,7 @@ void free_irq(unsigned int irq, void *dev_id)
|
|||
|
||||
kfree(action);
|
||||
|
||||
if (!(*(cpu_irq + irq_action)))
|
||||
if (!sparc_irq[cpu_irq].action)
|
||||
disable_irq(irq);
|
||||
|
||||
out_unlock:
|
||||
|
@ -287,8 +287,11 @@ EXPORT_SYMBOL(free_irq);
|
|||
#ifdef CONFIG_SMP
|
||||
void synchronize_irq(unsigned int irq)
|
||||
{
|
||||
printk("synchronize_irq says: implement me!\n");
|
||||
BUG();
|
||||
unsigned int cpu_irq;
|
||||
|
||||
cpu_irq = irq & (NR_IRQS - 1);
|
||||
while (sparc_irq[cpu_irq].flags & SPARC_IRQ_INPROGRESS)
|
||||
cpu_relax();
|
||||
}
|
||||
#endif /* SMP */
|
||||
|
||||
|
@ -299,7 +302,7 @@ void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs)
|
|||
unsigned int cpu_irq;
|
||||
|
||||
cpu_irq = irq & (NR_IRQS - 1);
|
||||
action = *(cpu_irq + irq_action);
|
||||
action = sparc_irq[cpu_irq].action;
|
||||
|
||||
printk("IO device interrupt, irq = %d\n", irq);
|
||||
printk("PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc,
|
||||
|
@ -330,7 +333,8 @@ void handler_irq(int irq, struct pt_regs * regs)
|
|||
if(irq < 10)
|
||||
smp4m_irq_rotate(cpu);
|
||||
#endif
|
||||
action = *(irq + irq_action);
|
||||
action = sparc_irq[irq].action;
|
||||
sparc_irq[irq].flags |= SPARC_IRQ_INPROGRESS;
|
||||
kstat_cpu(cpu).irqs[irq]++;
|
||||
do {
|
||||
if (!action || !action->handler)
|
||||
|
@ -338,6 +342,7 @@ void handler_irq(int irq, struct pt_regs * regs)
|
|||
action->handler(irq, action->dev_id, regs);
|
||||
action = action->next;
|
||||
} while (action);
|
||||
sparc_irq[irq].flags &= ~SPARC_IRQ_INPROGRESS;
|
||||
enable_pil_irq(irq);
|
||||
irq_exit();
|
||||
}
|
||||
|
@ -389,7 +394,7 @@ int request_fast_irq(unsigned int irq,
|
|||
|
||||
spin_lock_irqsave(&irq_action_lock, flags);
|
||||
|
||||
action = *(cpu_irq + irq_action);
|
||||
action = sparc_irq[cpu_irq].action;
|
||||
if(action) {
|
||||
if(action->flags & SA_SHIRQ)
|
||||
panic("Trying to register fast irq when already shared.\n");
|
||||
|
@ -452,7 +457,7 @@ int request_fast_irq(unsigned int irq,
|
|||
action->dev_id = NULL;
|
||||
action->next = NULL;
|
||||
|
||||
*(cpu_irq + irq_action) = action;
|
||||
sparc_irq[cpu_irq].action = action;
|
||||
|
||||
enable_irq(irq);
|
||||
|
||||
|
@ -467,7 +472,7 @@ int request_irq(unsigned int irq,
|
|||
irqreturn_t (*handler)(int, void *, struct pt_regs *),
|
||||
unsigned long irqflags, const char * devname, void *dev_id)
|
||||
{
|
||||
struct irqaction * action, *tmp = NULL;
|
||||
struct irqaction * action, **actionp;
|
||||
unsigned long flags;
|
||||
unsigned int cpu_irq;
|
||||
int ret;
|
||||
|
@ -490,20 +495,20 @@ int request_irq(unsigned int irq,
|
|||
|
||||
spin_lock_irqsave(&irq_action_lock, flags);
|
||||
|
||||
action = *(cpu_irq + irq_action);
|
||||
actionp = &sparc_irq[cpu_irq].action;
|
||||
action = *actionp;
|
||||
if (action) {
|
||||
if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
|
||||
for (tmp = action; tmp->next; tmp = tmp->next);
|
||||
} else {
|
||||
if (!(action->flags & SA_SHIRQ) || !(irqflags & SA_SHIRQ)) {
|
||||
ret = -EBUSY;
|
||||
goto out_unlock;
|
||||
}
|
||||
if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
|
||||
if ((action->flags & SA_INTERRUPT) != (irqflags & SA_INTERRUPT)) {
|
||||
printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
|
||||
ret = -EBUSY;
|
||||
goto out_unlock;
|
||||
}
|
||||
action = NULL; /* Or else! */
|
||||
}
|
||||
for ( ; action; action = *actionp)
|
||||
actionp = &action->next;
|
||||
}
|
||||
|
||||
/* If this is flagged as statically allocated then we use our
|
||||
|
@ -532,10 +537,7 @@ int request_irq(unsigned int irq,
|
|||
action->next = NULL;
|
||||
action->dev_id = dev_id;
|
||||
|
||||
if (tmp)
|
||||
tmp->next = action;
|
||||
else
|
||||
*(cpu_irq + irq_action) = action;
|
||||
*actionp = action;
|
||||
|
||||
enable_irq(irq);
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ volatile int __cpu_logical_map[NR_CPUS];
|
|||
|
||||
cpumask_t cpu_online_map = CPU_MASK_NONE;
|
||||
cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
|
||||
cpumask_t smp_commenced_mask = CPU_MASK_NONE;
|
||||
|
||||
/* The only guaranteed locking primitive available on all Sparc
|
||||
* processors is 'ldstub [%reg + immediate], %dest_reg' which atomically
|
||||
|
@ -57,11 +58,6 @@ cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
|
|||
/* Used to make bitops atomic */
|
||||
unsigned char bitops_spinlock = 0;
|
||||
|
||||
volatile unsigned long ipi_count;
|
||||
|
||||
volatile int smp_process_available=0;
|
||||
volatile int smp_commenced = 0;
|
||||
|
||||
void __init smp_store_cpu_info(int id)
|
||||
{
|
||||
int cpu_node;
|
||||
|
@ -79,6 +75,22 @@ void __init smp_store_cpu_info(int id)
|
|||
|
||||
void __init smp_cpus_done(unsigned int max_cpus)
|
||||
{
|
||||
extern void smp4m_smp_done(void);
|
||||
unsigned long bogosum = 0;
|
||||
int cpu, num;
|
||||
|
||||
for (cpu = 0, num = 0; cpu < NR_CPUS; cpu++)
|
||||
if (cpu_online(cpu)) {
|
||||
num++;
|
||||
bogosum += cpu_data(cpu).udelay_val;
|
||||
}
|
||||
|
||||
printk("Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
|
||||
num, bogosum/(500000/HZ),
|
||||
(bogosum/(5000/HZ))%100);
|
||||
|
||||
BUG_ON(sparc_cpu_model != sun4m);
|
||||
smp4m_smp_done();
|
||||
}
|
||||
|
||||
void cpu_panic(void)
|
||||
|
@ -89,17 +101,6 @@ void cpu_panic(void)
|
|||
|
||||
struct linux_prom_registers smp_penguin_ctable __initdata = { 0 };
|
||||
|
||||
void __init smp_boot_cpus(void)
|
||||
{
|
||||
extern void smp4m_boot_cpus(void);
|
||||
extern void smp4d_boot_cpus(void);
|
||||
|
||||
if (sparc_cpu_model == sun4m)
|
||||
smp4m_boot_cpus();
|
||||
else
|
||||
smp4d_boot_cpus();
|
||||
}
|
||||
|
||||
void smp_send_reschedule(int cpu)
|
||||
{
|
||||
/* See sparc64 */
|
||||
|
@ -252,20 +253,61 @@ int setup_profiling_timer(unsigned int multiplier)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void __init smp_prepare_cpus(unsigned int maxcpus)
|
||||
void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
extern void smp4m_boot_cpus(void);
|
||||
int i, cpuid, ncpus, extra;
|
||||
|
||||
BUG_ON(sparc_cpu_model != sun4m);
|
||||
printk("Entering SMP Mode...\n");
|
||||
|
||||
ncpus = 1;
|
||||
extra = 0;
|
||||
for (i = 0; !cpu_find_by_instance(i, NULL, &cpuid); i++) {
|
||||
if (cpuid == boot_cpu_id)
|
||||
continue;
|
||||
if (cpuid < NR_CPUS && ncpus++ < max_cpus)
|
||||
cpu_set(cpuid, phys_cpu_present_map);
|
||||
else
|
||||
extra++;
|
||||
}
|
||||
if (max_cpus >= NR_CPUS && extra)
|
||||
printk("Warning: NR_CPUS is too low to start all cpus\n");
|
||||
|
||||
smp_store_cpu_info(boot_cpu_id);
|
||||
|
||||
smp4m_boot_cpus();
|
||||
}
|
||||
|
||||
void __devinit smp_prepare_boot_cpu(void)
|
||||
{
|
||||
current_thread_info()->cpu = hard_smp_processor_id();
|
||||
cpu_set(smp_processor_id(), cpu_online_map);
|
||||
cpu_set(smp_processor_id(), phys_cpu_present_map);
|
||||
int cpuid = hard_smp_processor_id();
|
||||
|
||||
if (cpuid >= NR_CPUS) {
|
||||
prom_printf("Serious problem, boot cpu id >= NR_CPUS\n");
|
||||
prom_halt();
|
||||
}
|
||||
if (cpuid != 0)
|
||||
printk("boot cpu id != 0, this could work but is untested\n");
|
||||
|
||||
current_thread_info()->cpu = cpuid;
|
||||
cpu_set(cpuid, cpu_online_map);
|
||||
cpu_set(cpuid, phys_cpu_present_map);
|
||||
}
|
||||
|
||||
int __devinit __cpu_up(unsigned int cpu)
|
||||
{
|
||||
panic("smp doesn't work\n");
|
||||
extern int smp4m_boot_one_cpu(int);
|
||||
int ret;
|
||||
|
||||
ret = smp4m_boot_one_cpu(cpu);
|
||||
|
||||
if (!ret) {
|
||||
cpu_set(cpu, smp_commenced_mask);
|
||||
while (!cpu_online(cpu))
|
||||
mb();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void smp_bogo(struct seq_file *m)
|
||||
|
|
|
@ -136,10 +136,6 @@ EXPORT_PER_CPU_SYMBOL(__cpu_data);
|
|||
/* IRQ implementation. */
|
||||
EXPORT_SYMBOL(synchronize_irq);
|
||||
|
||||
/* Misc SMP information */
|
||||
EXPORT_SYMBOL(__cpu_number_map);
|
||||
EXPORT_SYMBOL(__cpu_logical_map);
|
||||
|
||||
/* CPU online map and active count. */
|
||||
EXPORT_SYMBOL(cpu_online_map);
|
||||
EXPORT_SYMBOL(phys_cpu_present_map);
|
||||
|
|
|
@ -54,7 +54,7 @@ unsigned char cpu_leds[32];
|
|||
unsigned char sbus_tid[32];
|
||||
#endif
|
||||
|
||||
extern struct irqaction *irq_action[];
|
||||
static struct irqaction *irq_action[NR_IRQS];
|
||||
extern spinlock_t irq_action_lock;
|
||||
|
||||
struct sbus_action {
|
||||
|
|
|
@ -46,14 +46,16 @@ extern volatile int smp_processors_ready;
|
|||
extern int smp_num_cpus;
|
||||
static int smp_highest_cpu;
|
||||
extern volatile unsigned long cpu_callin_map[NR_CPUS];
|
||||
extern struct cpuinfo_sparc cpu_data[NR_CPUS];
|
||||
extern cpuinfo_sparc cpu_data[NR_CPUS];
|
||||
extern unsigned char boot_cpu_id;
|
||||
extern int smp_activated;
|
||||
extern volatile int __cpu_number_map[NR_CPUS];
|
||||
extern volatile int __cpu_logical_map[NR_CPUS];
|
||||
extern volatile unsigned long ipi_count;
|
||||
extern volatile int smp_process_available;
|
||||
extern volatile int smp_commenced;
|
||||
|
||||
extern cpumask_t smp_commenced_mask;
|
||||
|
||||
extern int __smp4d_processor_id(void);
|
||||
|
||||
/* #define SMP_DEBUG */
|
||||
|
@ -136,7 +138,7 @@ void __init smp4d_callin(void)
|
|||
|
||||
local_irq_enable(); /* We don't allow PIL 14 yet */
|
||||
|
||||
while(!smp_commenced)
|
||||
while (!cpu_isset(cpuid, smp_commenced_mask))
|
||||
barrier();
|
||||
|
||||
spin_lock_irqsave(&sun4d_imsk_lock, flags);
|
||||
|
|
|
@ -40,15 +40,11 @@ extern ctxd_t *srmmu_ctx_table_phys;
|
|||
extern void calibrate_delay(void);
|
||||
|
||||
extern volatile int smp_processors_ready;
|
||||
extern int smp_num_cpus;
|
||||
extern volatile unsigned long cpu_callin_map[NR_CPUS];
|
||||
extern unsigned char boot_cpu_id;
|
||||
extern int smp_activated;
|
||||
extern volatile int __cpu_number_map[NR_CPUS];
|
||||
extern volatile int __cpu_logical_map[NR_CPUS];
|
||||
extern volatile unsigned long ipi_count;
|
||||
extern volatile int smp_process_available;
|
||||
extern volatile int smp_commenced;
|
||||
|
||||
extern cpumask_t smp_commenced_mask;
|
||||
|
||||
extern int __smp4m_processor_id(void);
|
||||
|
||||
/*#define SMP_DEBUG*/
|
||||
|
@ -77,8 +73,6 @@ void __init smp4m_callin(void)
|
|||
local_flush_cache_all();
|
||||
local_flush_tlb_all();
|
||||
|
||||
set_irq_udt(boot_cpu_id);
|
||||
|
||||
/* Get our local ticker going. */
|
||||
smp_setup_percpu_timer();
|
||||
|
||||
|
@ -95,8 +89,9 @@ void __init smp4m_callin(void)
|
|||
* to call the scheduler code.
|
||||
*/
|
||||
/* Allow master to continue. */
|
||||
swap((unsigned long *)&cpu_callin_map[cpuid], 1);
|
||||
swap(&cpu_callin_map[cpuid], 1);
|
||||
|
||||
/* XXX: What's up with all the flushes? */
|
||||
local_flush_cache_all();
|
||||
local_flush_tlb_all();
|
||||
|
||||
|
@ -111,13 +106,14 @@ void __init smp4m_callin(void)
|
|||
atomic_inc(&init_mm.mm_count);
|
||||
current->active_mm = &init_mm;
|
||||
|
||||
while(!smp_commenced)
|
||||
barrier();
|
||||
|
||||
local_flush_cache_all();
|
||||
local_flush_tlb_all();
|
||||
while (!cpu_isset(cpuid, smp_commenced_mask))
|
||||
mb();
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
cpu_set(cpuid, cpu_online_map);
|
||||
/* last one in gets all the interrupts (for testing) */
|
||||
set_irq_udt(boot_cpu_id);
|
||||
}
|
||||
|
||||
extern void init_IRQ(void);
|
||||
|
@ -134,102 +130,76 @@ extern unsigned long trapbase_cpu3[];
|
|||
|
||||
void __init smp4m_boot_cpus(void)
|
||||
{
|
||||
int cpucount = 0;
|
||||
int i, mid;
|
||||
|
||||
printk("Entering SMP Mode...\n");
|
||||
|
||||
local_irq_enable();
|
||||
cpus_clear(cpu_present_map);
|
||||
|
||||
for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++)
|
||||
cpu_set(mid, cpu_present_map);
|
||||
|
||||
for(i=0; i < NR_CPUS; i++) {
|
||||
__cpu_number_map[i] = -1;
|
||||
__cpu_logical_map[i] = -1;
|
||||
}
|
||||
|
||||
__cpu_number_map[boot_cpu_id] = 0;
|
||||
__cpu_logical_map[0] = boot_cpu_id;
|
||||
current_thread_info()->cpu = boot_cpu_id;
|
||||
|
||||
smp_store_cpu_info(boot_cpu_id);
|
||||
set_irq_udt(boot_cpu_id);
|
||||
smp_setup_percpu_timer();
|
||||
local_flush_cache_all();
|
||||
if(cpu_find_by_instance(1, NULL, NULL))
|
||||
return; /* Not an MP box. */
|
||||
for(i = 0; i < NR_CPUS; i++) {
|
||||
if(i == boot_cpu_id)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cpu_isset(i, cpu_present_map)) {
|
||||
extern unsigned long sun4m_cpu_startup;
|
||||
unsigned long *entry = &sun4m_cpu_startup;
|
||||
struct task_struct *p;
|
||||
int timeout;
|
||||
int smp4m_boot_one_cpu(int i)
|
||||
{
|
||||
extern unsigned long sun4m_cpu_startup;
|
||||
unsigned long *entry = &sun4m_cpu_startup;
|
||||
struct task_struct *p;
|
||||
int timeout;
|
||||
int cpu_node;
|
||||
|
||||
/* Cook up an idler for this guy. */
|
||||
p = fork_idle(i);
|
||||
cpucount++;
|
||||
current_set[i] = task_thread_info(p);
|
||||
/* See trampoline.S for details... */
|
||||
entry += ((i-1) * 3);
|
||||
cpu_find_by_mid(i, &cpu_node);
|
||||
|
||||
/*
|
||||
* Initialize the contexts table
|
||||
* Since the call to prom_startcpu() trashes the structure,
|
||||
* we need to re-initialize it for each cpu
|
||||
*/
|
||||
smp_penguin_ctable.which_io = 0;
|
||||
smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys;
|
||||
smp_penguin_ctable.reg_size = 0;
|
||||
/* Cook up an idler for this guy. */
|
||||
p = fork_idle(i);
|
||||
current_set[i] = task_thread_info(p);
|
||||
/* See trampoline.S for details... */
|
||||
entry += ((i-1) * 3);
|
||||
|
||||
/* whirrr, whirrr, whirrrrrrrrr... */
|
||||
printk("Starting CPU %d at %p\n", i, entry);
|
||||
local_flush_cache_all();
|
||||
prom_startcpu(cpu_data(i).prom_node,
|
||||
&smp_penguin_ctable, 0, (char *)entry);
|
||||
/*
|
||||
* Initialize the contexts table
|
||||
* Since the call to prom_startcpu() trashes the structure,
|
||||
* we need to re-initialize it for each cpu
|
||||
*/
|
||||
smp_penguin_ctable.which_io = 0;
|
||||
smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys;
|
||||
smp_penguin_ctable.reg_size = 0;
|
||||
|
||||
/* wheee... it's going... */
|
||||
for(timeout = 0; timeout < 10000; timeout++) {
|
||||
if(cpu_callin_map[i])
|
||||
break;
|
||||
udelay(200);
|
||||
}
|
||||
if(cpu_callin_map[i]) {
|
||||
/* Another "Red Snapper". */
|
||||
__cpu_number_map[i] = i;
|
||||
__cpu_logical_map[i] = i;
|
||||
} else {
|
||||
cpucount--;
|
||||
printk("Processor %d is stuck.\n", i);
|
||||
}
|
||||
}
|
||||
if(!(cpu_callin_map[i])) {
|
||||
cpu_clear(i, cpu_present_map);
|
||||
__cpu_number_map[i] = -1;
|
||||
}
|
||||
}
|
||||
/* whirrr, whirrr, whirrrrrrrrr... */
|
||||
printk("Starting CPU %d at %p\n", i, entry);
|
||||
local_flush_cache_all();
|
||||
if(cpucount == 0) {
|
||||
printk("Error: only one Processor found.\n");
|
||||
cpu_present_map = cpumask_of_cpu(smp_processor_id());
|
||||
} else {
|
||||
unsigned long bogosum = 0;
|
||||
for_each_present_cpu(i)
|
||||
bogosum += cpu_data(i).udelay_val;
|
||||
printk("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n",
|
||||
cpucount + 1,
|
||||
bogosum/(500000/HZ),
|
||||
(bogosum/(5000/HZ))%100);
|
||||
smp_activated = 1;
|
||||
smp_num_cpus = cpucount + 1;
|
||||
prom_startcpu(cpu_node,
|
||||
&smp_penguin_ctable, 0, (char *)entry);
|
||||
|
||||
/* wheee... it's going... */
|
||||
for(timeout = 0; timeout < 10000; timeout++) {
|
||||
if(cpu_callin_map[i])
|
||||
break;
|
||||
udelay(200);
|
||||
}
|
||||
|
||||
if (!(cpu_callin_map[i])) {
|
||||
printk("Processor %d is stuck.\n", i);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
local_flush_cache_all();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init smp4m_smp_done(void)
|
||||
{
|
||||
int i, first;
|
||||
int *prev;
|
||||
|
||||
/* setup cpu list for irq rotation */
|
||||
first = 0;
|
||||
prev = &first;
|
||||
for (i = 0; i < NR_CPUS; i++) {
|
||||
if (cpu_online(i)) {
|
||||
*prev = i;
|
||||
prev = &cpu_data(i).next;
|
||||
}
|
||||
}
|
||||
*prev = first;
|
||||
local_flush_cache_all();
|
||||
|
||||
/* Free unneeded trap tables */
|
||||
if (!cpu_isset(i, cpu_present_map)) {
|
||||
if (!cpu_isset(1, cpu_present_map)) {
|
||||
ClearPageReserved(virt_to_page(trapbase_cpu1));
|
||||
init_page_count(virt_to_page(trapbase_cpu1));
|
||||
free_page((unsigned long)trapbase_cpu1);
|
||||
|
@ -263,6 +233,9 @@ void __init smp4m_boot_cpus(void)
|
|||
*/
|
||||
void smp4m_irq_rotate(int cpu)
|
||||
{
|
||||
int next = cpu_data(cpu).next;
|
||||
if (next != cpu)
|
||||
set_irq_udt(next);
|
||||
}
|
||||
|
||||
/* Cross calls, in order to work efficiently and atomically do all
|
||||
|
@ -289,7 +262,7 @@ void smp4m_message_pass(int target, int msg, unsigned long data, int wait)
|
|||
|
||||
smp_cpu_in_msg[me]++;
|
||||
if(target == MSG_ALL_BUT_SELF || target == MSG_ALL) {
|
||||
mask = cpu_present_map;
|
||||
mask = cpu_online_map;
|
||||
if(target == MSG_ALL_BUT_SELF)
|
||||
cpu_clear(me, mask);
|
||||
for(i = 0; i < 4; i++) {
|
||||
|
@ -314,8 +287,8 @@ static struct smp_funcall {
|
|||
unsigned long arg3;
|
||||
unsigned long arg4;
|
||||
unsigned long arg5;
|
||||
unsigned long processors_in[NR_CPUS]; /* Set when ipi entered. */
|
||||
unsigned long processors_out[NR_CPUS]; /* Set when ipi exited. */
|
||||
unsigned long processors_in[SUN4M_NCPUS]; /* Set when ipi entered. */
|
||||
unsigned long processors_out[SUN4M_NCPUS]; /* Set when ipi exited. */
|
||||
} ccall_info;
|
||||
|
||||
static DEFINE_SPINLOCK(cross_call_lock);
|
||||
|
@ -324,8 +297,7 @@ static DEFINE_SPINLOCK(cross_call_lock);
|
|||
void smp4m_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
|
||||
unsigned long arg3, unsigned long arg4, unsigned long arg5)
|
||||
{
|
||||
if(smp_processors_ready) {
|
||||
register int ncpus = smp_num_cpus;
|
||||
register int ncpus = SUN4M_NCPUS;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&cross_call_lock, flags);
|
||||
|
@ -340,7 +312,7 @@ void smp4m_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
|
|||
|
||||
/* Init receive/complete mapping, plus fire the IPI's off. */
|
||||
{
|
||||
cpumask_t mask = cpu_present_map;
|
||||
cpumask_t mask = cpu_online_map;
|
||||
register int i;
|
||||
|
||||
cpu_clear(smp_processor_id(), mask);
|
||||
|
@ -373,7 +345,6 @@ void smp4m_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
|
|||
}
|
||||
|
||||
spin_unlock_irqrestore(&cross_call_lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
/* Running cross calls. */
|
||||
|
|
|
@ -1302,7 +1302,12 @@ void __init srmmu_paging_init(void)
|
|||
|
||||
flush_cache_all();
|
||||
srmmu_set_ctable_ptr((unsigned long)srmmu_ctx_table_phys);
|
||||
#ifdef CONFIG_SMP
|
||||
/* Stop from hanging here... */
|
||||
local_flush_tlb_all();
|
||||
#else
|
||||
flush_tlb_all();
|
||||
#endif
|
||||
poke_srmmu();
|
||||
|
||||
#ifdef CONFIG_SUN_IO
|
||||
|
@ -1419,6 +1424,7 @@ static void __init init_vac_layout(void)
|
|||
max_size = vac_cache_size;
|
||||
if(vac_line_size < min_line_size)
|
||||
min_line_size = vac_line_size;
|
||||
//FIXME: cpus not contiguous!!
|
||||
cpu++;
|
||||
if (cpu >= NR_CPUS || !cpu_online(cpu))
|
||||
break;
|
||||
|
|
|
@ -18,6 +18,7 @@ typedef struct {
|
|||
unsigned int counter;
|
||||
int prom_node;
|
||||
int mid;
|
||||
int next;
|
||||
} cpuinfo_sparc;
|
||||
|
||||
DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
|
||||
|
|
|
@ -81,16 +81,9 @@ static inline int smp_call_function(void (*func)(void *info), void *info, int no
|
|||
return 0;
|
||||
}
|
||||
|
||||
extern __volatile__ int __cpu_number_map[NR_CPUS];
|
||||
extern __volatile__ int __cpu_logical_map[NR_CPUS];
|
||||
|
||||
static inline int cpu_logical_map(int cpu)
|
||||
{
|
||||
return __cpu_logical_map[cpu];
|
||||
}
|
||||
static inline int cpu_number_map(int cpu)
|
||||
{
|
||||
return __cpu_number_map[cpu];
|
||||
return cpu;
|
||||
}
|
||||
|
||||
static inline int hard_smp4m_processor_id(void)
|
||||
|
|
|
@ -94,7 +94,7 @@ static inline void __read_lock(raw_rwlock_t *rw)
|
|||
#define __raw_read_lock(lock) \
|
||||
do { unsigned long flags; \
|
||||
local_irq_save(flags); \
|
||||
__raw_read_lock(lock); \
|
||||
__read_lock(lock); \
|
||||
local_irq_restore(flags); \
|
||||
} while(0)
|
||||
|
||||
|
@ -114,11 +114,11 @@ static inline void __read_unlock(raw_rwlock_t *rw)
|
|||
#define __raw_read_unlock(lock) \
|
||||
do { unsigned long flags; \
|
||||
local_irq_save(flags); \
|
||||
__raw_read_unlock(lock); \
|
||||
__read_unlock(lock); \
|
||||
local_irq_restore(flags); \
|
||||
} while(0)
|
||||
|
||||
extern __inline__ void __raw_write_lock(raw_rwlock_t *rw)
|
||||
static inline void __raw_write_lock(raw_rwlock_t *rw)
|
||||
{
|
||||
register raw_rwlock_t *lp asm("g1");
|
||||
lp = rw;
|
||||
|
@ -131,9 +131,28 @@ extern __inline__ void __raw_write_lock(raw_rwlock_t *rw)
|
|||
: "g2", "g4", "memory", "cc");
|
||||
}
|
||||
|
||||
static inline int __raw_write_trylock(raw_rwlock_t *rw)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
__asm__ __volatile__("ldstub [%1 + 3], %0"
|
||||
: "=r" (val)
|
||||
: "r" (&rw->lock)
|
||||
: "memory");
|
||||
|
||||
if (val == 0) {
|
||||
val = rw->lock & ~0xff;
|
||||
if (val)
|
||||
((volatile u8*)&rw->lock)[3] = 0;
|
||||
}
|
||||
|
||||
return (val == 0);
|
||||
}
|
||||
|
||||
#define __raw_write_unlock(rw) do { (rw)->lock = 0; } while(0)
|
||||
|
||||
#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
|
||||
#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
|
||||
|
||||
#endif /* !(__ASSEMBLY__) */
|
||||
|
||||
|
|
Loading…
Reference in New Issue