aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/fsp/fsp-op-panel.c8
-rw-r--r--hw/fsp/fsp.c31
-rw-r--r--include/fsp.h7
3 files changed, 45 insertions, 1 deletions
diff --git a/hw/fsp/fsp-op-panel.c b/hw/fsp/fsp-op-panel.c
index eb61e8d..7063cbb 100644
--- a/hw/fsp/fsp-op-panel.c
+++ b/hw/fsp/fsp-op-panel.c
@@ -40,7 +40,13 @@ static void fsp_op_display_fatal(uint32_t w0, uint32_t w1)
fsp_fillmsg(&op_msg, FSP_CMD_DISP_SRC_DIRECT, 3, 1, w0, w1);
- fsp_sync_msg(&op_msg, false);
+ /*
+ * A special way to send a message: it doesn't run pollers.
+ * This means we can call it while in a poller, which we may
+ * well be in when we're terminating (and thus displaying a *fatal*
+ * message on the op-panel).
+ */
+ fsp_fatal_msg(&op_msg);
}
void op_display(enum op_severity sev, enum op_module mod, uint16_t code)
diff --git a/hw/fsp/fsp.c b/hw/fsp/fsp.c
index 58219a0..c25e42c 100644
--- a/hw/fsp/fsp.c
+++ b/hw/fsp/fsp.c
@@ -1689,6 +1689,7 @@ void fsp_interrupt(void)
unlock(&fsp_lock);
}
+
int fsp_sync_msg(struct fsp_msg *msg, bool autofree)
{
int rc;
@@ -1977,6 +1978,36 @@ static void fsp_opal_poll(void *data __unused)
}
}
+int fsp_fatal_msg(struct fsp_msg *msg)
+{
+ int rc = 0;
+
+ rc = fsp_queue_msg(msg, NULL);
+ if (rc)
+ return rc;
+
+ while(fsp_msg_busy(msg)) {
+ cpu_relax();
+ fsp_opal_poll(NULL);
+ }
+
+ switch(msg->state) {
+ case fsp_msg_done:
+ rc = 0;
+ break;
+ case fsp_msg_timeout:
+ rc = -1; /* XXX to improve */
+ break;
+ default:
+ rc = -1; /* Should not happen... (assert ?) */
+ }
+
+ if (msg->resp)
+ rc = (msg->resp->word1 >> 8) & 0xff;
+
+ return rc;
+}
+
static bool fsp_init_one(const char *compat)
{
struct dt_node *fsp_node;
diff --git a/include/fsp.h b/include/fsp.h
index 7ea162d..6142ca3 100644
--- a/include/fsp.h
+++ b/include/fsp.h
@@ -697,6 +697,13 @@ extern void fsp_cancelmsg(struct fsp_msg *msg);
extern int fsp_queue_msg(struct fsp_msg *msg,
void (*comp)(struct fsp_msg *msg)) __warn_unused_result;
+/* Send a fatal message to FSP
+ *
+ * This will *not* run pollers.
+ * Use only when attempting to get the word out about how we died.
+ */
+extern int fsp_fatal_msg(struct fsp_msg *msg);
+
/* Synchronously send a command. If there's a response, the status is
* returned as a positive number. A negative result means an error
* sending the message.