|
@@ -195,9 +195,11 @@ static int boot_secondary(unsigned int cpu, struct task_struct *ts)
|
|
|
int i;
|
|
int i;
|
|
|
|
|
|
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
|
- cpu_start_id = cpu;
|
|
|
|
|
- system_flush_invalidate_dcache_range(
|
|
|
|
|
- (unsigned long)&cpu_start_id, sizeof(cpu_start_id));
|
|
|
|
|
|
|
+ WRITE_ONCE(cpu_start_id, cpu);
|
|
|
|
|
+ /* Pairs with the third memw in the cpu_restart */
|
|
|
|
|
+ mb();
|
|
|
|
|
+ system_flush_invalidate_dcache_range((unsigned long)&cpu_start_id,
|
|
|
|
|
+ sizeof(cpu_start_id));
|
|
|
#endif
|
|
#endif
|
|
|
smp_call_function_single(0, mx_cpu_start, (void *)cpu, 1);
|
|
smp_call_function_single(0, mx_cpu_start, (void *)cpu, 1);
|
|
|
|
|
|
|
@@ -206,18 +208,21 @@ static int boot_secondary(unsigned int cpu, struct task_struct *ts)
|
|
|
ccount = get_ccount();
|
|
ccount = get_ccount();
|
|
|
while (!ccount);
|
|
while (!ccount);
|
|
|
|
|
|
|
|
- cpu_start_ccount = ccount;
|
|
|
|
|
|
|
+ WRITE_ONCE(cpu_start_ccount, ccount);
|
|
|
|
|
|
|
|
- while (time_before(jiffies, timeout)) {
|
|
|
|
|
|
|
+ do {
|
|
|
|
|
+ /*
|
|
|
|
|
+ * Pairs with the first two memws in the
|
|
|
|
|
+ * .Lboot_secondary.
|
|
|
|
|
+ */
|
|
|
mb();
|
|
mb();
|
|
|
- if (!cpu_start_ccount)
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ ccount = READ_ONCE(cpu_start_ccount);
|
|
|
|
|
+ } while (ccount && time_before(jiffies, timeout));
|
|
|
|
|
|
|
|
- if (cpu_start_ccount) {
|
|
|
|
|
|
|
+ if (ccount) {
|
|
|
smp_call_function_single(0, mx_cpu_stop,
|
|
smp_call_function_single(0, mx_cpu_stop,
|
|
|
- (void *)cpu, 1);
|
|
|
|
|
- cpu_start_ccount = 0;
|
|
|
|
|
|
|
+ (void *)cpu, 1);
|
|
|
|
|
+ WRITE_ONCE(cpu_start_ccount, 0);
|
|
|
return -EIO;
|
|
return -EIO;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -237,6 +242,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
|
|
|
pr_debug("%s: Calling wakeup_secondary(cpu:%d, idle:%p, sp: %08lx)\n",
|
|
pr_debug("%s: Calling wakeup_secondary(cpu:%d, idle:%p, sp: %08lx)\n",
|
|
|
__func__, cpu, idle, start_info.stack);
|
|
__func__, cpu, idle, start_info.stack);
|
|
|
|
|
|
|
|
|
|
+ init_completion(&cpu_running);
|
|
|
ret = boot_secondary(cpu, idle);
|
|
ret = boot_secondary(cpu, idle);
|
|
|
if (ret == 0) {
|
|
if (ret == 0) {
|
|
|
wait_for_completion_timeout(&cpu_running,
|
|
wait_for_completion_timeout(&cpu_running,
|
|
@@ -298,8 +304,10 @@ void __cpu_die(unsigned int cpu)
|
|
|
unsigned long timeout = jiffies + msecs_to_jiffies(1000);
|
|
unsigned long timeout = jiffies + msecs_to_jiffies(1000);
|
|
|
while (time_before(jiffies, timeout)) {
|
|
while (time_before(jiffies, timeout)) {
|
|
|
system_invalidate_dcache_range((unsigned long)&cpu_start_id,
|
|
system_invalidate_dcache_range((unsigned long)&cpu_start_id,
|
|
|
- sizeof(cpu_start_id));
|
|
|
|
|
- if (cpu_start_id == -cpu) {
|
|
|
|
|
|
|
+ sizeof(cpu_start_id));
|
|
|
|
|
+ /* Pairs with the second memw in the cpu_restart */
|
|
|
|
|
+ mb();
|
|
|
|
|
+ if (READ_ONCE(cpu_start_id) == -cpu) {
|
|
|
platform_cpu_kill(cpu);
|
|
platform_cpu_kill(cpu);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|