Commit 45fe4502 authored by David S. Miller's avatar David S. Miller

SPARC64: Make __cpu_up and friends work as specified by Rusty.

parent f83a6783
...@@ -45,7 +45,6 @@ cpuinfo_sparc cpu_data[NR_CPUS]; ...@@ -45,7 +45,6 @@ cpuinfo_sparc cpu_data[NR_CPUS];
/* Please don't make this stuff initdata!!! --DaveM */ /* Please don't make this stuff initdata!!! --DaveM */
static unsigned char boot_cpu_id; static unsigned char boot_cpu_id;
static int smp_activated;
/* Kernel spinlock */ /* Kernel spinlock */
spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
...@@ -223,85 +222,46 @@ extern unsigned long sparc64_cpu_startup; ...@@ -223,85 +222,46 @@ extern unsigned long sparc64_cpu_startup;
*/ */
static struct thread_info *cpu_new_thread = NULL; static struct thread_info *cpu_new_thread = NULL;
static void __init smp_boot_cpus(unsigned int max_cpus) static int __devinit smp_boot_one_cpu(unsigned int cpu)
{ {
int cpucount = 0, i;
printk("Entering UltraSMPenguin Mode...\n");
local_irq_enable();
smp_store_cpu_info(boot_cpu_id);
if (linux_num_cpus == 1)
return;
for (i = 0; i < NR_CPUS; i++) {
if (i == boot_cpu_id)
continue;
if ((cpucount + 1) == max_cpus)
goto ignorecpu;
if (test_bit(i, &phys_cpu_present_map)) {
unsigned long entry = unsigned long entry =
(unsigned long)(&sparc64_cpu_startup); (unsigned long)(&sparc64_cpu_startup);
unsigned long cookie = unsigned long cookie =
(unsigned long)(&cpu_new_thread); (unsigned long)(&cpu_new_thread);
struct task_struct *p; struct task_struct *p;
int timeout; int timeout, no, ret;
int no;
prom_printf("Starting CPU %d... ", i);
kernel_thread(NULL, NULL, CLONE_IDLETASK); kernel_thread(NULL, NULL, CLONE_IDLETASK);
cpucount++;
p = prev_task(&init_task); p = prev_task(&init_task);
init_idle(p, i); init_idle(p, cpu);
unhash_process(p); unhash_process(p);
callin_flag = 0; callin_flag = 0;
for (no = 0; no < linux_num_cpus; no++) for (no = 0; no < linux_num_cpus; no++)
if (linux_cpus[no].mid == i) if (linux_cpus[no].mid == cpu)
break; break;
cpu_new_thread = p->thread_info; cpu_new_thread = p->thread_info;
set_bit(i, &cpu_callout_map); set_bit(cpu, &cpu_callout_map);
prom_startcpu(linux_cpus[no].prom_node, prom_startcpu(linux_cpus[no].prom_node, entry, cookie);
entry, cookie);
for (timeout = 0; timeout < 5000000; timeout++) { for (timeout = 0; timeout < 5000000; timeout++) {
if (callin_flag) if (callin_flag)
break; break;
udelay(100); udelay(100);
} }
if (callin_flag) { if (callin_flag) {
prom_cpu_nodes[i] = linux_cpus[no].prom_node; prom_cpu_nodes[cpu] = linux_cpus[no].prom_node;
prom_printf("OK\n"); ret = 0;
} else { } else {
cpucount--; printk("Processor %d is stuck.\n", cpu);
printk("Processor %d is stuck.\n", i); clear_bit(cpu, &cpu_callout_map);
prom_printf("FAILED\n"); ret = -ENODEV;
clear_bit(i, &cpu_callout_map);
}
ignorecpu:
}
} }
cpu_new_thread = NULL; cpu_new_thread = NULL;
if (cpucount == 0) {
if (max_cpus != 1)
printk("Error: only one processor found.\n");
} else {
unsigned long bogosum = 0;
for (i = 0; i < NR_CPUS; i++) { return ret;
if (cpu_online(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;
}
} }
static void spitfire_xcall_helper(u64 data0, u64 data1, u64 data2, u64 pstate, unsigned long cpu) static void spitfire_xcall_helper(u64 data0, u64 data1, u64 data2, u64 pstate, unsigned long cpu)
...@@ -1119,8 +1079,6 @@ static void __init smp_setup_percpu_timer(void) ...@@ -1119,8 +1079,6 @@ static void __init smp_setup_percpu_timer(void)
void __init smp_tick_init(void) void __init smp_tick_init(void)
{ {
int i;
boot_cpu_id = hard_smp_processor_id(); boot_cpu_id = hard_smp_processor_id();
current_tick_offset = timer_tick_offset; current_tick_offset = timer_tick_offset;
...@@ -1129,19 +1087,10 @@ void __init smp_tick_init(void) ...@@ -1129,19 +1087,10 @@ void __init smp_tick_init(void)
prom_halt(); prom_halt();
} }
atomic_set(&sparc64_num_cpus_online, 1); atomic_inc(&sparc64_num_cpus_online);
memset(&cpu_online_map, 0, sizeof(cpu_online_map));
set_bit(boot_cpu_id, &cpu_online_map); set_bit(boot_cpu_id, &cpu_online_map);
prom_cpu_nodes[boot_cpu_id] = linux_cpus[0].prom_node; prom_cpu_nodes[boot_cpu_id] = linux_cpus[0].prom_node;
prof_counter(boot_cpu_id) = prof_multiplier(boot_cpu_id) = 1; prof_counter(boot_cpu_id) = prof_multiplier(boot_cpu_id) = 1;
for (i = 0; i < linux_num_cpus; i++) {
if (linux_cpus[i].mid < NR_CPUS) {
set_bit(linux_cpus[i].mid,
&phys_cpu_present_map);
atomic_inc(&sparc64_num_cpus_possible);
}
}
} }
cycles_t cacheflush_time; cycles_t cacheflush_time;
...@@ -1272,19 +1221,59 @@ int setup_profiling_timer(unsigned int multiplier) ...@@ -1272,19 +1221,59 @@ int setup_profiling_timer(unsigned int multiplier)
void __init smp_prepare_cpus(unsigned int max_cpus) void __init smp_prepare_cpus(unsigned int max_cpus)
{ {
smp_boot_cpus(max_cpus); int i;
for (i = 0; i < linux_num_cpus; i++) {
if (linux_cpus[i].mid < max_cpus) {
set_bit(linux_cpus[i].mid,
&phys_cpu_present_map);
atomic_inc(&sparc64_num_cpus_possible);
}
}
if (atomic_read(&sparc64_num_cpus_possible) > max_cpus) {
for (i = linux_num_cpus - 1; i >= 0; i--) {
if (linux_cpus[i].mid != boot_cpu_id) {
clear_bit(linux_cpus[i].mid,
&phys_cpu_present_map);
atomic_dec(&sparc64_num_cpus_possible);
if (atomic_read(&sparc64_num_cpus_possible) <= max_cpus)
break;
}
}
}
smp_store_cpu_info(boot_cpu_id);
} }
int __devinit __cpu_up(unsigned int cpu) int __devinit __cpu_up(unsigned int cpu)
{ {
int ret = smp_boot_one_cpu(cpu);
if (!ret) {
set_bit(cpu, &smp_commenced_mask); set_bit(cpu, &smp_commenced_mask);
while (!test_bit(cpu, &cpu_online_map)) while (!test_bit(cpu, &cpu_online_map))
mb(); mb();
return 0; if (!test_bit(cpu, &cpu_online_map))
ret = -ENODEV;
}
return ret;
} }
void __init smp_cpus_done(unsigned int max_cpus) void __init smp_cpus_done(unsigned int max_cpus)
{ {
unsigned long bogosum = 0;
int i;
for (i = 0; i < NR_CPUS; i++) {
if (cpu_online(i))
bogosum += cpu_data[i].udelay_val;
}
printk("Total of %d processors activated "
"(%lu.%02lu BogoMIPS).\n",
num_online_cpus(),
bogosum/(500000/HZ),
(bogosum/(5000/HZ))%100);
/* We want to run this with all the other cpus spinning /* We want to run this with all the other cpus spinning
* in the kernel. * in the kernel.
*/ */
......
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