[Skiboot] [PATCH v2 4/8] IPMI: Pre-allocate memory for PANIC event

Vasant Hegde hegdevasant at linux.vnet.ibm.com
Fri Sep 4 21:25:09 AEST 2015


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 at linux.vnet.ibm.com>
---
 hw/ipmi/ipmi-sel.c        | 75 +++++++++++++++++++++++++++++++++++++++++++----
 include/ipmi.h            |  3 ++
 platforms/astbmc/common.c |  1 +
 3 files changed, 73 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);
+}
diff --git a/include/ipmi.h b/include/ipmi.h
index 54c415b..a1a236d 100644
--- a/include/ipmi.h
+++ b/include/ipmi.h
@@ -230,6 +230,9 @@ int ipmi_set_fw_progress_sensor(uint8_t state);
 /* Register a backend with the ipmi core. Currently we only support one. */
 void ipmi_register_backend(struct ipmi_backend *backend);
 
+/* Allocate IPMI SEL panic message */
+void ipmi_sel_init(void);
+
 /* Register rtc ipmi commands with as opal callbacks. */
 void ipmi_rtc_init(void);
 
diff --git a/platforms/astbmc/common.c b/platforms/astbmc/common.c
index 2af0309..8d37785 100644
--- a/platforms/astbmc/common.c
+++ b/platforms/astbmc/common.c
@@ -115,6 +115,7 @@ void astbmc_init(void)
 
 	/* Register the BT interface with the IPMI layer */
 	bt_init();
+	ipmi_sel_init();
 	ipmi_wdt_init();
 	ipmi_rtc_init();
 	ipmi_opal_init();
-- 
2.1.0



More information about the Skiboot mailing list