@@ -80,19 +80,23 @@ static DEFINE_SPINLOCK(smp_call_function_lock);
8080
8181int __cpuinit __cpu_up (unsigned int cpu )
8282{
83- struct task_struct * idle ;
83+ struct cpuinfo_arm * ci = & per_cpu (cpu_data , cpu );
84+ struct task_struct * idle = ci -> idle ;
8485 pgd_t * pgd ;
8586 pmd_t * pmd ;
8687 int ret ;
8788
8889 /*
89- * Spawn a new process manually. Grab a pointer to
90- * its task struct so we can mess with it
90+ * Spawn a new process manually, if not already done.
91+ * Grab a pointer to its task struct so we can mess with it
9192 */
92- idle = fork_idle (cpu );
93- if (IS_ERR (idle )) {
94- printk (KERN_ERR "CPU%u: fork() failed\n" , cpu );
95- return PTR_ERR (idle );
93+ if (!idle ) {
94+ idle = fork_idle (cpu );
95+ if (IS_ERR (idle )) {
96+ printk (KERN_ERR "CPU%u: fork() failed\n" , cpu );
97+ return PTR_ERR (idle );
98+ }
99+ ci -> idle = idle ;
96100 }
97101
98102 /*
@@ -155,6 +159,91 @@ int __cpuinit __cpu_up(unsigned int cpu)
155159 return ret ;
156160}
157161
162+ #ifdef CONFIG_HOTPLUG_CPU
163+ /*
164+ * __cpu_disable runs on the processor to be shutdown.
165+ */
166+ int __cpuexit __cpu_disable (void )
167+ {
168+ unsigned int cpu = smp_processor_id ();
169+ struct task_struct * p ;
170+ int ret ;
171+
172+ ret = mach_cpu_disable (cpu );
173+ if (ret )
174+ return ret ;
175+
176+ /*
177+ * Take this CPU offline. Once we clear this, we can't return,
178+ * and we must not schedule until we're ready to give up the cpu.
179+ */
180+ cpu_clear (cpu , cpu_online_map );
181+
182+ /*
183+ * OK - migrate IRQs away from this CPU
184+ */
185+ migrate_irqs ();
186+
187+ /*
188+ * Flush user cache and TLB mappings, and then remove this CPU
189+ * from the vm mask set of all processes.
190+ */
191+ flush_cache_all ();
192+ local_flush_tlb_all ();
193+
194+ read_lock (& tasklist_lock );
195+ for_each_process (p ) {
196+ if (p -> mm )
197+ cpu_clear (cpu , p -> mm -> cpu_vm_mask );
198+ }
199+ read_unlock (& tasklist_lock );
200+
201+ return 0 ;
202+ }
203+
204+ /*
205+ * called on the thread which is asking for a CPU to be shutdown -
206+ * waits until shutdown has completed, or it is timed out.
207+ */
208+ void __cpuexit __cpu_die (unsigned int cpu )
209+ {
210+ if (!platform_cpu_kill (cpu ))
211+ printk ("CPU%u: unable to kill\n" , cpu );
212+ }
213+
214+ /*
215+ * Called from the idle thread for the CPU which has been shutdown.
216+ *
217+ * Note that we disable IRQs here, but do not re-enable them
218+ * before returning to the caller. This is also the behaviour
219+ * of the other hotplug-cpu capable cores, so presumably coming
220+ * out of idle fixes this.
221+ */
222+ void __cpuexit cpu_die (void )
223+ {
224+ unsigned int cpu = smp_processor_id ();
225+
226+ local_irq_disable ();
227+ idle_task_exit ();
228+
229+ /*
230+ * actual CPU shutdown procedure is at least platform (if not
231+ * CPU) specific
232+ */
233+ platform_cpu_die (cpu );
234+
235+ /*
236+ * Do not return to the idle loop - jump back to the secondary
237+ * cpu initialisation. There's some initialisation which needs
238+ * to be repeated to undo the effects of taking the CPU offline.
239+ */
240+ __asm__("mov sp, %0\n"
241+ " b secondary_start_kernel"
242+ :
243+ : "r" ((void * )current -> thread_info + THREAD_SIZE - 8 ));
244+ }
245+ #endif /* CONFIG_HOTPLUG_CPU */
246+
158247/*
159248 * This is the secondary CPU boot entry. We're using this CPUs
160249 * idle thread stack, but a set of temporary page tables.
@@ -236,6 +325,8 @@ void __init smp_prepare_boot_cpu(void)
236325{
237326 unsigned int cpu = smp_processor_id ();
238327
328+ per_cpu (cpu_data , cpu ).idle = current ;
329+
239330 cpu_set (cpu , cpu_possible_map );
240331 cpu_set (cpu , cpu_present_map );
241332 cpu_set (cpu , cpu_online_map );
@@ -309,8 +400,8 @@ int smp_call_function_on_cpu(void (*func)(void *info), void *info, int retry,
309400 printk (KERN_CRIT
310401 "CPU%u: smp_call_function timeout for %p(%p)\n"
311402 " callmap %lx pending %lx, %swait\n" ,
312- smp_processor_id (), func , info , callmap , data . pending ,
313- wait ? "" : "no " );
403+ smp_processor_id (), func , info , * cpus_addr ( callmap ) ,
404+ * cpus_addr ( data . pending ), wait ? "" : "no " );
314405
315406 /*
316407 * TRACE
0 commit comments