3030#include <linux/irq.h>
3131#include <linux/of.h>
3232#include <linux/sched/task_stack.h>
33+ #include <linux/sched/hotplug.h>
3334#include <asm/irq.h>
3435#include <asm/mmu_context.h>
3536#include <asm/tlbflush.h>
@@ -82,20 +83,84 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
8283 __cpu_up_stack_pointer [cpu ] = task_stack_page (tidle ) + THREAD_SIZE ;
8384 __cpu_up_task_pointer [cpu ] = tidle ;
8485
86+ arch_send_call_function_single_ipi (cpu );
8587 while (!cpu_online (cpu ))
8688 cpu_relax ();
8789
90+ pr_notice ("CPU%u: online\n" , cpu );
8891 return 0 ;
8992}
9093
9194void __init smp_cpus_done (unsigned int max_cpus )
9295{
9396}
9497
98+ #ifdef CONFIG_HOTPLUG_CPU
99+ /*
100+ * __cpu_disable runs on the processor to be shutdown.
101+ */
102+ int __cpu_disable (void )
103+ {
104+ unsigned int cpu = smp_processor_id ();
105+ int ret ;
106+
107+ set_cpu_online (cpu , false);
108+ irq_migrate_all_off_this_cpu ();
109+
110+ return 0 ;
111+ }
112+ /*
113+ * called on the thread which is asking for a CPU to be shutdown -
114+ * waits until shutdown has completed, or it is timed out.
115+ */
116+ void __cpu_die (unsigned int cpu )
117+ {
118+ int err = 0 ;
119+
120+ if (!cpu_wait_death (cpu , 5 )) {
121+ pr_err ("CPU %u: didn't die\n" , cpu );
122+ return ;
123+ }
124+ pr_notice ("CPU%u: shutdown\n" , cpu );
125+ }
126+ /*
127+ * Called from the idle thread for the CPU which has been shutdown.
128+ */
129+ void cpu_play_dead (void )
130+ {
131+ int sipval , sieval , scauseval ;
132+ int cpu = smp_processor_id ();
133+
134+ idle_task_exit ();
135+
136+ (void )cpu_report_death ();
137+
138+ /* Do not disable software interrupt to restart cpu after WFI */
139+ csr_clear (sie , SIE_STIE | SIE_SEIE );
140+
141+ /* clear all pending flags */
142+ csr_write (sip , 0 );
143+ /* clear any previous scause data */
144+ csr_write (scause , 0 );
145+
146+ do {
147+ wait_for_interrupt ();
148+ sipval = csr_read (sip );
149+ sieval = csr_read (sie );
150+ scauseval = csr_read (scause );
151+ /* only break if wfi returns for an enabled interrupt */
152+ } while ((sipval & sieval ) == 0 &&
153+ scauseval != INTERRUPT_CAUSE_SOFTWARE );
154+
155+ boot_sec_cpu ();
156+ }
157+
158+
159+ #endif
95160/*
96161 * C entry point for a secondary processor.
97162 */
98- asmlinkage void __init smp_callin (void )
163+ asmlinkage void smp_callin (void )
99164{
100165 struct mm_struct * mm = & init_mm ;
101166
@@ -104,9 +169,8 @@ asmlinkage void __init smp_callin(void)
104169 current -> active_mm = mm ;
105170
106171 trap_init ();
107- init_clockevent ();
108172 notify_cpu_starting (smp_processor_id ());
109- set_cpu_online (smp_processor_id (), 1 );
173+ set_cpu_online (smp_processor_id (), true );
110174 local_flush_tlb_all ();
111175 local_irq_enable ();
112176 preempt_disable ();
0 commit comments