aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/hmi.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/core/hmi.c b/core/hmi.c
index 4d1c3a7..57f3fdb 100644
--- a/core/hmi.c
+++ b/core/hmi.c
@@ -32,6 +32,7 @@
#include <npu.h>
#include <capp.h>
#include <nvram.h>
+#include <cpu.h>
/*
* HMER register layout:
@@ -966,14 +967,54 @@ static int handle_thread_tfac_error(uint64_t tfmr, uint64_t *out_flags)
return recover;
}
+static int64_t opal_handle_hmi(void);
+
+static void opal_handle_hmi_job(void *data __unused)
+{
+ opal_handle_hmi();
+}
+
+/*
+ * Queue hmi handling job If secondaries are still in OPAL
+ * This function is called by thread 0.
+ */
+static struct cpu_job **hmi_kick_secondaries(void)
+{
+ struct cpu_thread *ts = this_cpu();
+ struct cpu_job **hmi_jobs = NULL;
+ int job_sz = sizeof(struct cpu_job *) * cpu_thread_count;
+ int i;
+
+ for (i = 1; i < cpu_thread_count; i++) {
+ ts = next_cpu(ts);
+
+ /* Is this thread still in OPAL ? */
+ if (ts->state == cpu_state_active) {
+ if (!hmi_jobs) {
+ hmi_jobs = zalloc(job_sz);
+ assert(hmi_jobs);
+ }
+
+ prlog(PR_DEBUG, "Sending hmi job to thread %d\n", i);
+ hmi_jobs[i] = cpu_queue_job(ts, "handle_hmi_job",
+ opal_handle_hmi_job, NULL);
+ }
+ }
+ return hmi_jobs;
+}
+
static int handle_all_core_tfac_error(uint64_t tfmr, uint64_t *out_flags)
{
struct cpu_thread *t, *t0;
int recover = -1;
+ struct cpu_job **hmi_jobs = NULL;
t = this_cpu();
t0 = find_cpu_by_pir(cpu_get_thread0(t));
+ if (t == t0 && t0->state == cpu_state_os)
+ hmi_jobs = hmi_kick_secondaries();
+
/* Rendez vous all threads */
hmi_rendez_vous(1);
@@ -1055,6 +1096,14 @@ error_out:
if (t0->tb_resynced)
*out_flags |= OPAL_HMI_FLAGS_TB_RESYNC;
+ if (t == t0 && hmi_jobs) {
+ int i;
+ for (i = 1; i < cpu_thread_count; i++)
+ if (hmi_jobs[i])
+ cpu_wait_job(hmi_jobs[i], true);
+ free(hmi_jobs);
+ }
+
return recover;
}