Commit d71eecf3 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6:
  [SPARC]: Try to start getting SMP back into shape.
parents b55813a2 a54123e2
...@@ -23,7 +23,6 @@ menu "General machine setup" ...@@ -23,7 +23,6 @@ menu "General machine setup"
config SMP config SMP
bool "Symmetric multi-processing support (does not work on sun4/sun4c)" bool "Symmetric multi-processing support (does not work on sun4/sun4c)"
depends on BROKEN
---help--- ---help---
This enables support for systems with more than one CPU. If you have 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 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 *)) = ...@@ -154,9 +154,11 @@ void (*sparc_init_timers)(irqreturn_t (*)(int, void *,struct pt_regs *)) =
struct irqaction static_irqaction[MAX_STATIC_ALLOC]; struct irqaction static_irqaction[MAX_STATIC_ALLOC];
int static_irq_count; int static_irq_count;
struct irqaction *irq_action[NR_IRQS] = { struct {
[0 ... (NR_IRQS-1)] = NULL struct irqaction *action;
}; int flags;
} sparc_irq[NR_IRQS];
#define SPARC_IRQ_INPROGRESS 1
/* Used to protect the IRQ action lists */ /* Used to protect the IRQ action lists */
DEFINE_SPINLOCK(irq_action_lock); DEFINE_SPINLOCK(irq_action_lock);
...@@ -177,7 +179,7 @@ int show_interrupts(struct seq_file *p, void *v) ...@@ -177,7 +179,7 @@ int show_interrupts(struct seq_file *p, void *v)
} }
spin_lock_irqsave(&irq_action_lock, flags); spin_lock_irqsave(&irq_action_lock, flags);
if (i < NR_IRQS) { if (i < NR_IRQS) {
action = *(i + irq_action); action = sparc_irq[i].action;
if (!action) if (!action)
goto out_unlock; goto out_unlock;
seq_printf(p, "%3d: ", i); seq_printf(p, "%3d: ", i);
...@@ -186,7 +188,7 @@ int show_interrupts(struct seq_file *p, void *v) ...@@ -186,7 +188,7 @@ int show_interrupts(struct seq_file *p, void *v)
#else #else
for_each_online_cpu(j) { for_each_online_cpu(j) {
seq_printf(p, "%10u ", seq_printf(p, "%10u ",
kstat_cpu(cpu_logical_map(j)).irqs[i]); kstat_cpu(j).irqs[i]);
} }
#endif #endif
seq_printf(p, " %c %s", seq_printf(p, " %c %s",
...@@ -207,7 +209,7 @@ int show_interrupts(struct seq_file *p, void *v) ...@@ -207,7 +209,7 @@ int show_interrupts(struct seq_file *p, void *v)
void free_irq(unsigned int irq, void *dev_id) void free_irq(unsigned int irq, void *dev_id)
{ {
struct irqaction * action; struct irqaction * action;
struct irqaction * tmp = NULL; struct irqaction **actionp;
unsigned long flags; unsigned long flags;
unsigned int cpu_irq; unsigned int cpu_irq;
...@@ -225,7 +227,8 @@ void free_irq(unsigned int irq, void *dev_id) ...@@ -225,7 +227,8 @@ void free_irq(unsigned int irq, void *dev_id)
spin_lock_irqsave(&irq_action_lock, flags); spin_lock_irqsave(&irq_action_lock, flags);
action = *(cpu_irq + irq_action); actionp = &sparc_irq[cpu_irq].action;
action = *actionp;
if (!action->handler) { if (!action->handler) {
printk("Trying to free free IRQ%d\n",irq); printk("Trying to free free IRQ%d\n",irq);
...@@ -235,7 +238,7 @@ void free_irq(unsigned int irq, void *dev_id) ...@@ -235,7 +238,7 @@ void free_irq(unsigned int irq, void *dev_id)
for (; action; action = action->next) { for (; action; action = action->next) {
if (action->dev_id == dev_id) if (action->dev_id == dev_id)
break; break;
tmp = action; actionp = &action->next;
} }
if (!action) { if (!action) {
printk("Trying to free free shared IRQ%d\n",irq); printk("Trying to free free shared IRQ%d\n",irq);
...@@ -254,11 +257,8 @@ void free_irq(unsigned int irq, void *dev_id) ...@@ -254,11 +257,8 @@ void free_irq(unsigned int irq, void *dev_id)
irq, action->name); irq, action->name);
goto out_unlock; goto out_unlock;
} }
if (action && tmp) *actionp = action->next;
tmp->next = action->next;
else
*(cpu_irq + irq_action) = action->next;
spin_unlock_irqrestore(&irq_action_lock, flags); spin_unlock_irqrestore(&irq_action_lock, flags);
...@@ -268,7 +268,7 @@ void free_irq(unsigned int irq, void *dev_id) ...@@ -268,7 +268,7 @@ void free_irq(unsigned int irq, void *dev_id)
kfree(action); kfree(action);
if (!(*(cpu_irq + irq_action))) if (!sparc_irq[cpu_irq].action)
disable_irq(irq); disable_irq(irq);
out_unlock: out_unlock:
...@@ -287,8 +287,11 @@ EXPORT_SYMBOL(free_irq); ...@@ -287,8 +287,11 @@ EXPORT_SYMBOL(free_irq);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
void synchronize_irq(unsigned int irq) void synchronize_irq(unsigned int irq)
{ {
printk("synchronize_irq says: implement me!\n"); unsigned int cpu_irq;
BUG();
cpu_irq = irq & (NR_IRQS - 1);
while (sparc_irq[cpu_irq].flags & SPARC_IRQ_INPROGRESS)
cpu_relax();
} }
#endif /* SMP */ #endif /* SMP */
...@@ -299,7 +302,7 @@ void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs) ...@@ -299,7 +302,7 @@ void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs)
unsigned int cpu_irq; unsigned int cpu_irq;
cpu_irq = irq & (NR_IRQS - 1); 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("IO device interrupt, irq = %d\n", irq);
printk("PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc, printk("PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc,
...@@ -330,7 +333,8 @@ void handler_irq(int irq, struct pt_regs * regs) ...@@ -330,7 +333,8 @@ void handler_irq(int irq, struct pt_regs * regs)
if(irq < 10) if(irq < 10)
smp4m_irq_rotate(cpu); smp4m_irq_rotate(cpu);
#endif #endif
action = *(irq + irq_action); action = sparc_irq[irq].action;
sparc_irq[irq].flags |= SPARC_IRQ_INPROGRESS;
kstat_cpu(cpu).irqs[irq]++; kstat_cpu(cpu).irqs[irq]++;
do { do {
if (!action || !action->handler) if (!action || !action->handler)
...@@ -338,6 +342,7 @@ void handler_irq(int irq, struct pt_regs * regs) ...@@ -338,6 +342,7 @@ void handler_irq(int irq, struct pt_regs * regs)
action->handler(irq, action->dev_id, regs); action->handler(irq, action->dev_id, regs);
action = action->next; action = action->next;
} while (action); } while (action);
sparc_irq[irq].flags &= ~SPARC_IRQ_INPROGRESS;
enable_pil_irq(irq); enable_pil_irq(irq);
irq_exit(); irq_exit();
} }
...@@ -389,7 +394,7 @@ int request_fast_irq(unsigned int irq, ...@@ -389,7 +394,7 @@ int request_fast_irq(unsigned int irq,
spin_lock_irqsave(&irq_action_lock, flags); spin_lock_irqsave(&irq_action_lock, flags);
action = *(cpu_irq + irq_action); action = sparc_irq[cpu_irq].action;
if(action) { if(action) {
if(action->flags & SA_SHIRQ) if(action->flags & SA_SHIRQ)
panic("Trying to register fast irq when already shared.\n"); panic("Trying to register fast irq when already shared.\n");
...@@ -452,7 +457,7 @@ int request_fast_irq(unsigned int irq, ...@@ -452,7 +457,7 @@ int request_fast_irq(unsigned int irq,
action->dev_id = NULL; action->dev_id = NULL;
action->next = NULL; action->next = NULL;
*(cpu_irq + irq_action) = action; sparc_irq[cpu_irq].action = action;
enable_irq(irq); enable_irq(irq);
...@@ -467,7 +472,7 @@ int request_irq(unsigned int irq, ...@@ -467,7 +472,7 @@ int request_irq(unsigned int irq,
irqreturn_t (*handler)(int, void *, struct pt_regs *), irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags, const char * devname, void *dev_id) unsigned long irqflags, const char * devname, void *dev_id)
{ {
struct irqaction * action, *tmp = NULL; struct irqaction * action, **actionp;
unsigned long flags; unsigned long flags;
unsigned int cpu_irq; unsigned int cpu_irq;
int ret; int ret;
...@@ -490,20 +495,20 @@ int request_irq(unsigned int irq, ...@@ -490,20 +495,20 @@ int request_irq(unsigned int irq,
spin_lock_irqsave(&irq_action_lock, flags); spin_lock_irqsave(&irq_action_lock, flags);
action = *(cpu_irq + irq_action); actionp = &sparc_irq[cpu_irq].action;
action = *actionp;
if (action) { if (action) {
if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) { if (!(action->flags & SA_SHIRQ) || !(irqflags & SA_SHIRQ)) {
for (tmp = action; tmp->next; tmp = tmp->next);
} else {
ret = -EBUSY; ret = -EBUSY;
goto out_unlock; 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); printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
ret = -EBUSY; ret = -EBUSY;
goto out_unlock; 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 /* If this is flagged as statically allocated then we use our
...@@ -532,10 +537,7 @@ int request_irq(unsigned int irq, ...@@ -532,10 +537,7 @@ int request_irq(unsigned int irq,
action->next = NULL; action->next = NULL;
action->dev_id = dev_id; action->dev_id = dev_id;
if (tmp) *actionp = action;
tmp->next = action;
else
*(cpu_irq + irq_action) = action;
enable_irq(irq); enable_irq(irq);
......
...@@ -45,6 +45,7 @@ volatile int __cpu_logical_map[NR_CPUS]; ...@@ -45,6 +45,7 @@ volatile int __cpu_logical_map[NR_CPUS];
cpumask_t cpu_online_map = CPU_MASK_NONE; cpumask_t cpu_online_map = CPU_MASK_NONE;
cpumask_t phys_cpu_present_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 /* The only guaranteed locking primitive available on all Sparc
* processors is 'ldstub [%reg + immediate], %dest_reg' which atomically * processors is 'ldstub [%reg + immediate], %dest_reg' which atomically
...@@ -57,11 +58,6 @@ cpumask_t phys_cpu_present_map = CPU_MASK_NONE; ...@@ -57,11 +58,6 @@ cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
/* Used to make bitops atomic */ /* Used to make bitops atomic */
unsigned char bitops_spinlock = 0; 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) void __init smp_store_cpu_info(int id)
{ {
int cpu_node; int cpu_node;
...@@ -79,6 +75,22 @@ void __init smp_store_cpu_info(int id) ...@@ -79,6 +75,22 @@ void __init smp_store_cpu_info(int id)
void __init smp_cpus_done(unsigned int max_cpus) 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) void cpu_panic(void)
...@@ -89,17 +101,6 @@ void cpu_panic(void) ...@@ -89,17 +101,6 @@ void cpu_panic(void)
struct linux_prom_registers smp_penguin_ctable __initdata = { 0 }; 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) void smp_send_reschedule(int cpu)
{ {
/* See sparc64 */ /* See sparc64 */
...@@ -252,20 +253,61 @@ int setup_profiling_timer(unsigned int multiplier) ...@@ -252,20 +253,61 @@ int setup_profiling_timer(unsigned int multiplier)
return 0; 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) void __devinit smp_prepare_boot_cpu(void)
{ {
current_thread_info()->cpu = hard_smp_processor_id(); int cpuid = hard_smp_processor_id();
cpu_set(smp_processor_id(), cpu_online_map);
cpu_set(smp_processor_id(), phys_cpu_present_map); 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) 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) void smp_bogo(struct seq_file *m)
......
...@@ -136,10 +136,6 @@ EXPORT_PER_CPU_SYMBOL(__cpu_data); ...@@ -136,10 +136,6 @@ EXPORT_PER_CPU_SYMBOL(__cpu_data);
/* IRQ implementation. */ /* IRQ implementation. */
EXPORT_SYMBOL(synchronize_irq); EXPORT_SYMBOL(synchronize_irq);
/* Misc SMP information */
EXPORT_SYMBOL(__cpu_number_map);
EXPORT_SYMBOL(__cpu_logical_map);
/* CPU online map and active count. */ /* CPU online map and active count. */
EXPORT_SYMBOL(cpu_online_map); EXPORT_SYMBOL(cpu_online_map);
EXPORT_SYMBOL(phys_cpu_present_map); EXPORT_SYMBOL(phys_cpu_present_map);
......
...@@ -54,7 +54,7 @@ unsigned char cpu_leds[32]; ...@@ -54,7 +54,7 @@ unsigned char cpu_leds[32];
unsigned char sbus_tid[32]; unsigned char sbus_tid[32];
#endif #endif
extern struct irqaction *irq_action[]; static struct irqaction *irq_action[NR_IRQS];
extern spinlock_t irq_action_lock; extern spinlock_t irq_action_lock;
struct sbus_action { struct sbus_action {
......
...@@ -46,14 +46,16 @@ extern volatile int smp_processors_ready; ...@@ -46,14 +46,16 @@ extern volatile int smp_processors_ready;
extern int smp_num_cpus; extern int smp_num_cpus;
static int smp_highest_cpu; static int smp_highest_cpu;
extern volatile unsigned long cpu_callin_map[NR_CPUS]; 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 unsigned char boot_cpu_id;
extern int smp_activated; extern int smp_activated;
extern volatile int __cpu_number_map[NR_CPUS]; extern volatile int __cpu_number_map[NR_CPUS];
extern volatile int __cpu_logical_map[NR_CPUS]; extern volatile int __cpu_logical_map[NR_CPUS];
extern volatile unsigned long ipi_count; extern volatile unsigned long ipi_count;
extern volatile int smp_process_available; extern volatile int smp_process_available;
extern volatile int smp_commenced;
extern cpumask_t smp_commenced_mask;
extern int __smp4d_processor_id(void); extern int __smp4d_processor_id(void);
/* #define SMP_DEBUG */ /* #define SMP_DEBUG */
...@@ -136,7 +138,7 @@ void __init smp4d_callin(void) ...@@ -136,7 +138,7 @@ void __init smp4d_callin(void)
local_irq_enable(); /* We don't allow PIL 14 yet */ local_irq_enable(); /* We don't allow PIL 14 yet */
while(!smp_commenced) while (!cpu_isset(cpuid, smp_commenced_mask))
barrier(); barrier();
spin_lock_irqsave(&sun4d_imsk_lock, flags); spin_lock_irqsave(&sun4d_imsk_lock, flags);
......
...@@ -40,15 +40,11 @@ extern ctxd_t *srmmu_ctx_table_phys; ...@@ -40,15 +40,11 @@ extern ctxd_t *srmmu_ctx_table_phys;
extern void calibrate_delay(void); extern void calibrate_delay(void);
extern volatile int smp_processors_ready; extern volatile int smp_processors_ready;
extern int smp_num_cpus;
extern volatile unsigned long cpu_callin_map[NR_CPUS]; extern volatile unsigned long cpu_callin_map[NR_CPUS];
extern unsigned char boot_cpu_id; extern unsigned char boot_cpu_id;
extern int smp_activated;
extern volatile int __cpu_number_map[NR_CPUS]; extern cpumask_t smp_commenced_mask;
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 int __smp4m_processor_id(void); extern int __smp4m_processor_id(void);
/*#define SMP_DEBUG*/ /*#define SMP_DEBUG*/
...@@ -77,8 +73,6 @@ void __init smp4m_callin(void) ...@@ -77,8 +73,6 @@ void __init smp4m_callin(void)
local_flush_cache_all(); local_flush_cache_all();
local_flush_tlb_all(); local_flush_tlb_all();
set_irq_udt(boot_cpu_id);
/* Get our local ticker going. */ /* Get our local ticker going. */
smp_setup_percpu_timer(); smp_setup_percpu_timer();
...@@ -95,8 +89,9 @@ void __init smp4m_callin(void) ...@@ -95,8 +89,9 @@ void __init smp4m_callin(void)
* to call the scheduler code. * to call the scheduler code.
*/ */
/* Allow master to continue. */ /* 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_cache_all();
local_flush_tlb_all(); local_flush_tlb_all();
...@@ -111,13 +106,14 @@ void __init smp4m_callin(void) ...@@ -111,13 +106,14 @@ void __init smp4m_callin(void)
atomic_inc(&init_mm.mm_count); atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm; current->active_mm = &init_mm;
while(!smp_commenced) while (!cpu_isset(cpuid, smp_commenced_mask))
barrier(); mb();
local_flush_cache_all();
local_flush_tlb_all();
local_irq_enable(); 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); extern void init_IRQ(void);
...@@ -134,102 +130,76 @@ extern unsigned long trapbase_cpu3[]; ...@@ -134,102 +130,76 @@ extern unsigned long trapbase_cpu3[];
void __init smp4m_boot_cpus(void) void __init smp4m_boot_cpus(void)
{ {
int cpucount = 0; smp_setup_percpu_timer();
int i, mid; local_flush_cache_all();
}
printk("Entering SMP Mode...\n"); 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;
local_irq_enable(); cpu_find_by_mid(i, &cpu_node);
cpus_clear(cpu_present_map);
/* 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);
for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) /*
cpu_set(mid, cpu_present_map); * 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;
for(i=0; i < NR_CPUS; i++) { /* whirrr, whirrr, whirrrrrrrrr... */
__cpu_number_map[i] = -1; printk("Starting CPU %d at %p\n", i, entry);
__cpu_logical_map[i] = -1; local_flush_cache_all();
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);
} }
__cpu_number_map[boot_cpu_id] = 0; if (!(cpu_callin_map[i])) {
__cpu_logical_map[0] = boot_cpu_id; printk("Processor %d is stuck.\n", i);
current_thread_info()->cpu = boot_cpu_id; return -ENODEV;
}
smp_store_cpu_info(boot_cpu_id);
set_irq_udt(boot_cpu_id);
smp_setup_percpu_timer();
local_flush_cache_all(); local_flush_cache_all();
if(cpu_find_by_instance(1, NULL, NULL)) return 0;
return; /* Not an MP box. */ }
for(i = 0; i < NR_CPUS; i++) {
if(i == boot_cpu_id) void __init smp4m_smp_done(void)
continue; {
int i, first;
if (cpu_isset(i, cpu_present_map)) { int *prev;
extern unsigned long sun4m_cpu_startup;
unsigned long *entry = &sun4m_cpu_startup; /* setup cpu list for irq rotation */
struct task_struct *p; first = 0;
int timeout; prev = &first;
for (i = 0; i < NR_CPUS; i++) {
/* Cook up an idler for this guy. */ if (cpu_online(i)) {
p = fork_idle(i); *prev = i;
cpucount++; prev = &cpu_data(i).next;
current_set[i] = task_thread_info(p);
/* See trampoline.S for details... */
entry += ((i-1) * 3);
/*
* 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;
/* 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);
/* 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;
} }
} }
*prev = first;
local_flush_cache_all(); 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;
}
/* Free unneeded trap tables */ /* Free unneeded trap tables */
if (!cpu_isset(i, cpu_present_map)) { if (!cpu_isset(1, cpu_present_map)) {
ClearPageReserved(virt_to_page(trapbase_cpu1)); ClearPageReserved(virt_to_page(trapbase_cpu1));
init_page_count(virt_to_page(trapbase_cpu1)); init_page_count(virt_to_page(trapbase_cpu1));
free_page((unsigned long)trapbase_cpu1); free_page((unsigned long)trapbase_cpu1);
...@@ -263,6 +233,9 @@ void __init smp4m_boot_cpus(void) ...@@ -263,6 +233,9 @@ void __init smp4m_boot_cpus(void)
*/ */
void smp4m_irq_rotate(int cpu) 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 /* 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) ...@@ -289,7 +262,7 @@ void smp4m_message_pass(int target, int msg, unsigned long data, int wait)
smp_cpu_in_msg[me]++; smp_cpu_in_msg[me]++;
if(target == MSG_ALL_BUT_SELF || target == MSG_ALL) { if(target == MSG_ALL_BUT_SELF || target == MSG_ALL) {
mask = cpu_present_map; mask = cpu_online_map;
if(target == MSG_ALL_BUT_SELF) if(target == MSG_ALL_BUT_SELF)
cpu_clear(me, mask); cpu_clear(me, mask);
for(i = 0; i < 4; i++) { for(i = 0; i < 4; i++) {
...@@ -314,8 +287,8 @@ static struct smp_funcall { ...@@ -314,8 +287,8 @@ static struct smp_funcall {
unsigned long arg3; unsigned long arg3;
unsigned long arg4; unsigned long arg4;
unsigned long arg5; unsigned long arg5;
unsigned long processors_in[NR_CPUS]; /* Set when ipi entered. */ unsigned long processors_in[SUN4M_NCPUS]; /* Set when ipi entered. */
unsigned long processors_out[NR_CPUS]; /* Set when ipi exited. */ unsigned long processors_out[SUN4M_NCPUS]; /* Set when ipi exited. */
} ccall_info; } ccall_info;
static DEFINE_SPINLOCK(cross_call_lock); static DEFINE_SPINLOCK(cross_call_lock);
...@@ -324,8 +297,7 @@ 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, void smp4m_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
unsigned long arg3, unsigned long arg4, unsigned long arg5) unsigned long arg3, unsigned long arg4, unsigned long arg5)
{ {
if(smp_processors_ready) { register int ncpus = SUN4M_NCPUS;
register int ncpus = smp_num_cpus;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&cross_call_lock, 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, ...@@ -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. */ /* 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; register int i;
cpu_clear(smp_processor_id(), mask); cpu_clear(smp_processor_id(), mask);
...@@ -373,7 +345,6 @@ void smp4m_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2, ...@@ -373,7 +345,6 @@ void smp4m_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
} }
spin_unlock_irqrestore(&cross_call_lock, flags); spin_unlock_irqrestore(&cross_call_lock, flags);
}
} }
/* Running cross calls. */ /* Running cross calls. */
......
...@@ -1302,7 +1302,12 @@ void __init srmmu_paging_init(void) ...@@ -1302,7 +1302,12 @@ void __init srmmu_paging_init(void)
flush_cache_all(); flush_cache_all();
srmmu_set_ctable_ptr((unsigned long)srmmu_ctx_table_phys); 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(); flush_tlb_all();
#endif
poke_srmmu(); poke_srmmu();
#ifdef CONFIG_SUN_IO #ifdef CONFIG_SUN_IO
...@@ -1419,6 +1424,7 @@ static void __init init_vac_layout(void) ...@@ -1419,6 +1424,7 @@ static void __init init_vac_layout(void)
max_size = vac_cache_size; max_size = vac_cache_size;
if(vac_line_size < min_line_size) if(vac_line_size < min_line_size)
min_line_size = vac_line_size; min_line_size = vac_line_size;
//FIXME: cpus not contiguous!!
cpu++; cpu++;
if (cpu >= NR_CPUS || !cpu_online(cpu)) if (cpu >= NR_CPUS || !cpu_online(cpu))
break; break;
......
...@@ -18,6 +18,7 @@ typedef struct { ...@@ -18,6 +18,7 @@ typedef struct {
unsigned int counter; unsigned int counter;
int prom_node; int prom_node;
int mid; int mid;
int next;
} cpuinfo_sparc; } cpuinfo_sparc;
DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data); 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 ...@@ -81,16 +81,9 @@ static inline int smp_call_function(void (*func)(void *info), void *info, int no
return 0; 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) static inline int cpu_logical_map(int cpu)
{ {
return __cpu_logical_map[cpu]; return cpu;
}
static inline int cpu_number_map(int cpu)
{
return __cpu_number_map[cpu];
} }
static inline int hard_smp4m_processor_id(void) static inline int hard_smp4m_processor_id(void)
......
...@@ -94,7 +94,7 @@ static inline void __read_lock(raw_rwlock_t *rw) ...@@ -94,7 +94,7 @@ static inline void __read_lock(raw_rwlock_t *rw)
#define __raw_read_lock(lock) \ #define __raw_read_lock(lock) \
do { unsigned long flags; \ do { unsigned long flags; \
local_irq_save(flags); \ local_irq_save(flags); \
__raw_read_lock(lock); \ __read_lock(lock); \
local_irq_restore(flags); \ local_irq_restore(flags); \
} while(0) } while(0)
...@@ -114,11 +114,11 @@ static inline void __read_unlock(raw_rwlock_t *rw) ...@@ -114,11 +114,11 @@ static inline void __read_unlock(raw_rwlock_t *rw)
#define __raw_read_unlock(lock) \ #define __raw_read_unlock(lock) \
do { unsigned long flags; \ do { unsigned long flags; \
local_irq_save(flags); \ local_irq_save(flags); \
__raw_read_unlock(lock); \ __read_unlock(lock); \
local_irq_restore(flags); \ local_irq_restore(flags); \
} while(0) } 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"); register raw_rwlock_t *lp asm("g1");
lp = rw; lp = rw;
...@@ -131,9 +131,28 @@ extern __inline__ void __raw_write_lock(raw_rwlock_t *rw) ...@@ -131,9 +131,28 @@ extern __inline__ void __raw_write_lock(raw_rwlock_t *rw)
: "g2", "g4", "memory", "cc"); : "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_write_unlock(rw) do { (rw)->lock = 0; } while(0)
#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
#endif /* !(__ASSEMBLY__) */ #endif /* !(__ASSEMBLY__) */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment