diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2016-07-07 11:50:07 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2016-07-13 17:13:57 +1000 |
commit | ee8d135aa92de252d3f79034f829e3579e6a122f (patch) | |
tree | c4d644d700a21d648cc15dd4507e65fe50e2c0cb | |
parent | 6b216257d3945653352f06f713f019cd6fa88f8c (diff) | |
download | skiboot-ee8d135aa92de252d3f79034f829e3579e6a122f.zip skiboot-ee8d135aa92de252d3f79034f829e3579e6a122f.tar.gz skiboot-ee8d135aa92de252d3f79034f829e3579e6a122f.tar.bz2 |
cpu: Don't call time_wait with lock held
Also make the locking around re-init safer, properly block the
OS from restarting a thread that was caught for re-init.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r-- | core/cpu.c | 24 | ||||
-rw-r--r-- | include/cpu.h | 1 |
2 files changed, 18 insertions, 7 deletions
@@ -726,6 +726,11 @@ static int64_t opal_start_cpu_thread(uint64_t server_no, uint64_t start_address) prerror("OPAL: CPU not active in OPAL !\n"); return OPAL_WRONG_STATE; } + if (cpu->in_reinit) { + unlock(&reinit_lock); + prerror("OPAL: CPU being reinitialized !\n"); + return OPAL_WRONG_STATE; + } job = __cpu_queue_job(cpu, "start_thread", opal_start_thread_job, (void *)start_address, true); @@ -821,34 +826,37 @@ static int64_t opal_reinit_cpus(uint64_t flags) prerror("OPAL: Trying a CPU re-init with flags: 0x%llx\n", flags); + again: lock(&reinit_lock); for (cpu = first_cpu(); cpu; cpu = next_cpu(cpu)) { - if (cpu == this_cpu()) + if (cpu == this_cpu() || cpu->in_reinit) continue; if (cpu->state == cpu_state_os) { + unlock(&reinit_lock); /* * That might be a race with return CPU during kexec * where we are still, wait a bit and try again */ for (i = 0; (i < 1000) && (cpu->state == cpu_state_os); i++) { - unlock(&reinit_lock); time_wait_ms(1); - lock(&reinit_lock); } if (cpu->state == cpu_state_os) { prerror("OPAL: CPU 0x%x not in OPAL !\n", cpu->pir); - rc = OPAL_WRONG_STATE; - goto bail; + return OPAL_WRONG_STATE; } + goto again; } + cpu->in_reinit = true; } /* * Now we need to mark ourselves "active" or we'll be skipped * by the various "for_each_active_..." calls done by slw_reinit() */ this_cpu()->state = cpu_state_active; + this_cpu()->in_reinit = true; + unlock(&reinit_lock); /* * If the flags affect endianness and we are on P8 DD2 or later, then @@ -875,10 +883,12 @@ static int64_t opal_reinit_cpus(uint64_t flags) rc = slw_reinit(flags); /* And undo the above */ + lock(&reinit_lock); this_cpu()->state = cpu_state_os; - -bail: + for (cpu = first_cpu(); cpu; cpu = next_cpu(cpu)) + cpu->in_reinit = false; unlock(&reinit_lock); + return rc; } opal_call(OPAL_REINIT_CPUS, opal_reinit_cpus, 1); diff --git a/include/cpu.h b/include/cpu.h index 59923d5..62f5629 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -60,6 +60,7 @@ struct cpu_thread { bool con_need_flush; bool in_mcount; bool in_poller; + bool in_reinit; uint32_t hbrt_spec_wakeup; /* primary only */ uint64_t save_l2_fir_action1; uint64_t current_token; |