aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2016-07-07 11:50:07 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2016-07-13 17:13:57 +1000
commitee8d135aa92de252d3f79034f829e3579e6a122f (patch)
treec4d644d700a21d648cc15dd4507e65fe50e2c0cb
parent6b216257d3945653352f06f713f019cd6fa88f8c (diff)
downloadskiboot-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.c24
-rw-r--r--include/cpu.h1
2 files changed, 18 insertions, 7 deletions
diff --git a/core/cpu.c b/core/cpu.c
index 8a7a43f..2084150 100644
--- a/core/cpu.c
+++ b/core/cpu.c
@@ -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;