aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorStewart Smith <stewart@linux.vnet.ibm.com>2015-02-18 17:39:25 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-02-18 17:41:24 +1100
commit2e70c840a30688d70a9034ca41ce110240d58539 (patch)
tree7478ca416cefc111386c6101a4247fb98e5ce647 /hw
parente5a0df37aeeb4e8a484f8305be146a4b2b000f21 (diff)
downloadskiboot-2e70c840a30688d70a9034ca41ce110240d58539.zip
skiboot-2e70c840a30688d70a9034ca41ce110240d58539.tar.gz
skiboot-2e70c840a30688d70a9034ca41ce110240d58539.tar.bz2
fsp-op-panel: don't call fsp_sync_msg with lock held
Use allocated fsp message in usual case, fall back to static one in the event of a fatal error. Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/fsp/fsp-op-panel.c78
1 files changed, 45 insertions, 33 deletions
diff --git a/hw/fsp/fsp-op-panel.c b/hw/fsp/fsp-op-panel.c
index 8c3c893..b494abd 100644
--- a/hw/fsp/fsp-op-panel.c
+++ b/hw/fsp/fsp-op-panel.c
@@ -28,73 +28,81 @@ DEFINE_LOG_ENTRY(OPAL_RC_PANEL_WRITE, OPAL_PLATFORM_ERR_EVT, OPAL_OP_PANEL,
OPAL_MISC_SUBSYSTEM, OPAL_PREDICTIVE_ERR_GENERAL,
OPAL_NA, NULL);
-static struct fsp_msg op_msg_resp;
-static struct fsp_msg op_msg = {
- .resp = &op_msg_resp,
-};
+/* For OPAL OP_PANEL API we can only have one in flight due to TCEs */
static struct fsp_msg *op_req;
static uint64_t op_async_token;
static struct lock op_lock = LOCK_UNLOCKED;
+static void fsp_op_display_fatal(uint32_t w0, uint32_t w1)
+{
+ static struct fsp_msg op_msg_resp;
+ static struct fsp_msg op_msg = {
+ .resp = &op_msg_resp,
+ };
+
+ fsp_fillmsg(&op_msg, FSP_CMD_DISP_SRC_DIRECT, 3, 1, w0, w1);
+
+ fsp_sync_msg(&op_msg, false);
+}
+
void op_display(enum op_severity sev, enum op_module mod, uint16_t code)
{
- uint32_t w0 = sev << 16 | mod;
+ struct fsp_msg *op_msg;
+ uint32_t w0;
uint32_t w1;
- bool clean_lock;
if (!fsp_present())
return;
+ w0 = sev << 16 | mod;
+
w1 = tohex((code >> 12) & 0xf) << 24;
w1 |= tohex((code >> 8) & 0xf) << 16;
w1 |= tohex((code >> 4) & 0xf) << 8;
w1 |= tohex((code ) & 0xf);
- /*
- * We use lock_recursive to detect recursion. We avoid sending
- * the message if that happens as this could be a case of a
- * locking error in the FSP driver for example
- */
- clean_lock = lock_recursive(&op_lock);
- if (!clean_lock)
- return;
+ if (sev == OP_FATAL) {
+ fsp_op_display_fatal(w0, w1);
+ } else {
+ op_msg = fsp_allocmsg(true);
+ if (!op_msg) {
+ prerror("Failed to allocate FSP message for PANEL\n");
+ return;
+ }
- /* We don't use mkmsg, we use a preallocated msg to avoid
- * going down the malloc path etc... since this can be called
- * in case of fatal errors
- */
- fsp_fillmsg(&op_msg, FSP_CMD_DISP_SRC_DIRECT, 3, 1, w0, w1);
+ fsp_fillmsg(op_msg, FSP_CMD_DISP_SRC_DIRECT, 3, 1, w0, w1);
- if (sev == OP_FATAL) {
- if(fsp_queue_msg(&op_msg, NULL))
+ if(fsp_queue_msg(op_msg, fsp_freemsg))
prerror("Failed to queue FSP message for OP PANEL\n");
- } else {
- fsp_sync_msg(&op_msg, false);
}
-
- unlock(&op_lock);
}
void op_panel_disable_src_echo(void)
{
+ struct fsp_msg op_msg_resp;
+ struct fsp_msg op_msg = {
+ .resp = &op_msg_resp,
+ };
+
if (!fsp_present())
return;
- lock(&op_lock);
fsp_fillmsg(&op_msg, FSP_CMD_DIS_SRC_ECHO, 0);
fsp_sync_msg(&op_msg, false);
- unlock(&op_lock);
}
void op_panel_clear_src(void)
{
+ struct fsp_msg op_msg_resp;
+ struct fsp_msg op_msg = {
+ .resp = &op_msg_resp,
+ };
+
if (!fsp_present())
return;
- lock(&op_lock);
fsp_fillmsg(&op_msg, FSP_CMD_CLEAR_SRC, 0);
fsp_sync_msg(&op_msg, false);
- unlock(&op_lock);
}
/* opal_write_oppanel - Write to the physical op panel.
@@ -136,8 +144,11 @@ static struct op_src op_src __align(0x1000);
static void __op_panel_write_complete(struct fsp_msg *msg)
{
fsp_tce_unmap(PSI_DMA_OP_PANEL_MISC, 0x1000);
- lwsync();
+
+ lock(&op_lock);
op_req = NULL;
+ unlock(&op_lock);
+
fsp_freemsg(msg);
}
@@ -163,19 +174,21 @@ static int64_t __opal_write_oppanel(oppanel_line_t *lines, uint64_t num_lines,
if (num_lines < 1 || num_lines > 2)
return OPAL_PARAMETER;
- lock(&op_lock);
-
/* Only one in flight */
+ lock(&op_lock);
if (op_req) {
rc = OPAL_BUSY_EVENT;
+ unlock(&op_lock);
goto bail;
}
op_req = fsp_allocmsg(true);
if (!op_req) {
rc = OPAL_NO_MEM;
+ unlock(&op_lock);
goto bail;
}
+ unlock(&op_lock);
op_async_token = async_token;
@@ -232,7 +245,6 @@ static int64_t __opal_write_oppanel(oppanel_line_t *lines, uint64_t num_lines,
rc = OPAL_INTERNAL_ERROR;
}
bail:
- unlock(&op_lock);
log_simple_error(&e_info(OPAL_RC_PANEL_WRITE),
"FSP: Error updating Op Panel: %lld\n", rc);
return rc;