Skip to content

Commit 4d3c4a4

Browse files
committed
Merge branch 'smp-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull smp/hotplug fix from Thomas Gleixner: "A single fix for a brown paperbag bug: The unparking of the initial percpu threads of an upcoming CPU happens right now on the idle task, but that's wrong as the unpark function might sleep. Move it to the control CPU." * 'smp-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: smp/hotplug: Move unparking of percpu threads to the control CPU
2 parents 4fde846 + 9cd4f1a commit 4d3c4a4

File tree

1 file changed

+19
-18
lines changed

1 file changed

+19
-18
lines changed

kernel/cpu.c

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -271,11 +271,25 @@ void cpu_hotplug_enable(void)
271271
EXPORT_SYMBOL_GPL(cpu_hotplug_enable);
272272
#endif /* CONFIG_HOTPLUG_CPU */
273273

274+
static void __cpuhp_kick_ap_work(struct cpuhp_cpu_state *st);
275+
274276
static int bringup_wait_for_ap(unsigned int cpu)
275277
{
276278
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
277279

280+
/* Wait for the CPU to reach CPUHP_AP_ONLINE_IDLE */
278281
wait_for_completion(&st->done);
282+
BUG_ON(!cpu_online(cpu));
283+
284+
/* Unpark the stopper thread and the hotplug thread of the target cpu */
285+
stop_machine_unpark(cpu);
286+
kthread_unpark(st->thread);
287+
288+
/* Should we go further up ? */
289+
if (st->target > CPUHP_AP_ONLINE_IDLE) {
290+
__cpuhp_kick_ap_work(st);
291+
wait_for_completion(&st->done);
292+
}
279293
return st->result;
280294
}
281295

@@ -296,9 +310,7 @@ static int bringup_cpu(unsigned int cpu)
296310
irq_unlock_sparse();
297311
if (ret)
298312
return ret;
299-
ret = bringup_wait_for_ap(cpu);
300-
BUG_ON(!cpu_online(cpu));
301-
return ret;
313+
return bringup_wait_for_ap(cpu);
302314
}
303315

304316
/*
@@ -767,31 +779,20 @@ void notify_cpu_starting(unsigned int cpu)
767779
}
768780

769781
/*
770-
* Called from the idle task. We need to set active here, so we can kick off
771-
* the stopper thread and unpark the smpboot threads. If the target state is
772-
* beyond CPUHP_AP_ONLINE_IDLE we kick cpuhp thread and let it bring up the
773-
* cpu further.
782+
* Called from the idle task. Wake up the controlling task which brings the
783+
* stopper and the hotplug thread of the upcoming CPU up and then delegates
784+
* the rest of the online bringup to the hotplug thread.
774785
*/
775786
void cpuhp_online_idle(enum cpuhp_state state)
776787
{
777788
struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
778-
unsigned int cpu = smp_processor_id();
779789

780790
/* Happens for the boot cpu */
781791
if (state != CPUHP_AP_ONLINE_IDLE)
782792
return;
783793

784794
st->state = CPUHP_AP_ONLINE_IDLE;
785-
786-
/* Unpark the stopper thread and the hotplug thread of this cpu */
787-
stop_machine_unpark(cpu);
788-
kthread_unpark(st->thread);
789-
790-
/* Should we go further up ? */
791-
if (st->target > CPUHP_AP_ONLINE_IDLE)
792-
__cpuhp_kick_ap_work(st);
793-
else
794-
complete(&st->done);
795+
complete(&st->done);
795796
}
796797

797798
/* Requires cpu_add_remove_lock to be held */

0 commit comments

Comments
 (0)