diff options
Diffstat (limited to 'arch/mips/kernel/smp.c')
| -rw-r--r-- | arch/mips/kernel/smp.c | 51 | 
1 files changed, 27 insertions, 24 deletions
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index af5cd3b8a39..fcacf1aae98 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -50,7 +50,6 @@ static void smp_tune_scheduling (void)  {  	struct cache_desc *cd = ¤t_cpu_data.scache;  	unsigned long cachesize;       /* kB   */ -	unsigned long bandwidth = 350; /* MB/s */  	unsigned long cpu_khz;  	/* @@ -121,7 +120,19 @@ struct call_data_struct *call_data;   * or are or have executed.   *   * You must not call this function with disabled interrupts or from a - * hardware interrupt handler or from a bottom half handler. + * hardware interrupt handler or from a bottom half handler: + * + * CPU A                               CPU B + * Disable interrupts + *                                     smp_call_function() + *                                     Take call_lock + *                                     Send IPIs + *                                     Wait for all cpus to acknowledge IPI + *                                     CPU A has not responded, spin waiting + *                                     for cpu A to respond, holding call_lock + * smp_call_function() + * Spin waiting for call_lock + * Deadlock                            Deadlock   */  int smp_call_function (void (*func) (void *info), void *info, int retry,  								int wait) @@ -130,6 +141,11 @@ int smp_call_function (void (*func) (void *info), void *info, int retry,  	int i, cpus = num_online_cpus() - 1;  	int cpu = smp_processor_id(); +	/* +	 * Can die spectacularly if this CPU isn't yet marked online +	 */ +	BUG_ON(!cpu_online(cpu)); +  	if (!cpus)  		return 0; @@ -214,7 +230,6 @@ void __init smp_cpus_done(unsigned int max_cpus)  /* called from main before smp_init() */  void __init smp_prepare_cpus(unsigned int max_cpus)  { -	cpu_data[0].udelay_val = loops_per_jiffy;  	init_new_context(current, &init_mm);  	current_thread_info()->cpu = 0;  	smp_tune_scheduling(); @@ -236,23 +251,28 @@ void __devinit smp_prepare_boot_cpu(void)  }  /* - * Startup the CPU with this logical number + * Called once for each "cpu_possible(cpu)".  Needs to spin up the cpu + * and keep control until "cpu_online(cpu)" is set.  Note: cpu is + * physical, not logical.   */ -static int __init do_boot_cpu(int cpu) +int __devinit __cpu_up(unsigned int cpu)  {  	struct task_struct *idle;  	/* +	 * Processor goes to start_secondary(), sets online flag  	 * The following code is purely to make sure  	 * Linux can schedule processes on this slave.  	 */  	idle = fork_idle(cpu);  	if (IS_ERR(idle)) -		panic("failed fork for CPU %d\n", cpu); +		panic(KERN_ERR "Fork failed for CPU %d", cpu);  	prom_boot_secondary(cpu, idle); -	/* XXXKW timeout */ +	/* +	 * Trust is futile.  We should really have timeouts ... +	 */  	while (!cpu_isset(cpu, cpu_callin_map))  		udelay(100); @@ -261,23 +281,6 @@ static int __init do_boot_cpu(int cpu)  	return 0;  } -/* - * Called once for each "cpu_possible(cpu)".  Needs to spin up the cpu - * and keep control until "cpu_online(cpu)" is set.  Note: cpu is - * physical, not logical. - */ -int __devinit __cpu_up(unsigned int cpu) -{ -	int ret; - -	/* Processor goes to start_secondary(), sets online flag */ -	ret = do_boot_cpu(cpu); -	if (ret < 0) -		return ret; - -	return 0; -} -  /* Not really SMP stuff ... */  int setup_profiling_timer(unsigned int multiplier)  {  | 
