diff options
author | Vasant Hegde <hegdevasant@linux.vnet.ibm.com> | 2015-09-04 16:55:09 +0530 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-09-09 15:17:56 +1000 |
commit | 425a89ba2f4264a9215b176fe7b2ebf38a29cf09 (patch) | |
tree | dcf9ac180596c3bcd217302576e36dfd0ad00c0d /hw/ipmi | |
parent | 87edc3d8c87f113ec2a6d92c71fa25473cb8cec6 (diff) | |
download | skiboot-425a89ba2f4264a9215b176fe7b2ebf38a29cf09.zip skiboot-425a89ba2f4264a9215b176fe7b2ebf38a29cf09.tar.gz skiboot-425a89ba2f4264a9215b176fe7b2ebf38a29cf09.tar.bz2 |
IPMI: Pre-allocate memory for PANIC event
Currently we allocate ipmi_msg for every eSEL event.. But in PANIC
its not advised to allocate memory. Hence pre-allocate ipmi_msg for
PANIC event.
Note that we continue to allocate memory for normal event. Also with
current implementation we can log only one eSEL event in PANIC path.
Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/ipmi')
-rw-r--r-- | hw/ipmi/ipmi-sel.c | 75 |
1 files changed, 69 insertions, 6 deletions
diff --git a/hw/ipmi/ipmi-sel.c b/hw/ipmi/ipmi-sel.c index 42de2a5..5556b65 100644 --- a/hw/ipmi/ipmi-sel.c +++ b/hw/ipmi/ipmi-sel.c @@ -134,6 +134,62 @@ struct oem_sel { #define ESEL_HDR_SIZE 7 +/* Used for sending PANIC events like abort() path */ +struct ipmi_sel_panic_msg { + bool busy; + struct ipmi_msg *msg; + struct lock lock; +}; +static struct ipmi_sel_panic_msg ipmi_sel_panic_msg; + +/* Forward declaration */ +static void ipmi_elog_poll(struct ipmi_msg *msg); + +/* + * Allocate IPMI message + * For normal event, allocate memory using ipmi_mkmsg and for PANIC + * event, use pre-allocated buffer. + */ +static struct ipmi_msg *ipmi_sel_alloc_msg(struct errorlog *elog_buf) +{ + struct ipmi_msg *msg = NULL; + + if (elog_buf->event_severity == OPAL_ERROR_PANIC) { + /* Called before initialization completes */ + if (ipmi_sel_panic_msg.msg == NULL) + return NULL; + + if (ipmi_sel_panic_msg.busy == true) + return NULL; + + lock(&ipmi_sel_panic_msg.lock); + msg = ipmi_sel_panic_msg.msg; + ipmi_sel_panic_msg.busy = true; + unlock(&ipmi_sel_panic_msg.lock); + + ipmi_init_msg(msg, IPMI_DEFAULT_INTERFACE, + IPMI_RESERVE_SEL, ipmi_elog_poll, + elog_buf, IPMI_MAX_REQ_SIZE, 2); + } else { + msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_RESERVE_SEL, + ipmi_elog_poll, elog_buf, + NULL, IPMI_MAX_REQ_SIZE, 2); + } + + return msg; +} + +static void ipmi_sel_free_msg(struct ipmi_msg *msg) +{ + if (msg == ipmi_sel_panic_msg.msg) { + lock(&ipmi_sel_panic_msg.lock); + ipmi_sel_panic_msg.busy = false; + unlock(&ipmi_sel_panic_msg.lock); + } else { + ipmi_free_msg(msg); + } + msg = NULL; +} /* Initialize eSEL record */ static void ipmi_init_esel_record(void) @@ -199,7 +255,7 @@ static void ipmi_elog_error(struct ipmi_msg *msg) ipmi_queue_msg(msg); else { opal_elog_complete(msg->user_data, false); - ipmi_free_msg(msg); + ipmi_sel_free_msg(msg); } } @@ -208,7 +264,7 @@ static void ipmi_log_sel_event_error(struct ipmi_msg *msg) if (msg->cc != IPMI_CC_NO_ERROR) prlog(PR_INFO, "SEL: Failed to log SEL event\n"); - ipmi_free_msg(msg); + ipmi_sel_free_msg(msg); } static void ipmi_log_sel_event_complete(struct ipmi_msg *msg) @@ -216,7 +272,7 @@ static void ipmi_log_sel_event_complete(struct ipmi_msg *msg) prlog(PR_INFO, "SEL: New event logged [ID : %x%x]\n", msg->data[1], msg->data[0]); - ipmi_free_msg(msg); + ipmi_sel_free_msg(msg); } /* Log SEL event with eSEL record ID */ @@ -282,7 +338,7 @@ static void ipmi_elog_poll(struct ipmi_msg *msg) * sending the message. */ prerror("Invalid reservation id"); opal_elog_complete(elog_buf, false); - ipmi_free_msg(msg); + ipmi_sel_free_msg(msg); return; } @@ -360,8 +416,7 @@ int ipmi_elog_commit(struct errorlog *elog_buf) /* We pass a large request size in to mkmsg so that we have a * large enough allocation to reuse the message to pass the * PEL data via a series of partial add commands. */ - msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_RESERVE_SEL, ipmi_elog_poll, - elog_buf, NULL, IPMI_MAX_REQ_SIZE, 2); + msg = ipmi_sel_alloc_msg(elog_buf); if (!msg) { opal_elog_complete(elog_buf, false); return OPAL_RESOURCE; @@ -486,3 +541,11 @@ void ipmi_parse_sel(struct ipmi_msg *msg) sel.cmd); } } + +void ipmi_sel_init(void) +{ + memset(&ipmi_sel_panic_msg, 0, sizeof(struct ipmi_sel_panic_msg)); + ipmi_sel_panic_msg.msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, + IPMI_RESERVE_SEL, ipmi_elog_poll, + NULL, NULL, IPMI_MAX_REQ_SIZE, 2); +} |