aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStewart Smith <stewart@linux.vnet.ibm.com>2016-11-18 14:58:28 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2016-11-24 17:02:51 +1100
commit1a0cd0a969baec3730d277cd00609ce455a67e36 (patch)
tree8cf8db2c45ce382c933bc01119e74b96ddc8e358
parent7a6298eaf7ce282890bfa9e630d82a1edb3daf12 (diff)
downloadskiboot-1a0cd0a969baec3730d277cd00609ce455a67e36.zip
skiboot-1a0cd0a969baec3730d277cd00609ce455a67e36.tar.gz
skiboot-1a0cd0a969baec3730d277cd00609ce455a67e36.tar.bz2
fsp: Don't recurse pollers in ibm_fsp_terminate
If we were to terminate in a poller, we'd call op_display() which called pollers which hit the recursive poller warning, which ended in not much fun at all. This patch will skip the running of pollers and instead run the FSP poller to set the op-panel display before attn. Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com> (cherry picked from commit 9fcb109218b1374a8caa3cac62e83fbedb1f7f2f) Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-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.