[Skiboot] [PATCH v2] IPMI: Fix eSEL logging issue

Vasant Hegde hegdevasant at linux.vnet.ibm.com
Thu Aug 6 19:56:46 AEST 2015


Presently we are passing PEL log without adding eSEL structure
information. Hence logging eSEL information is failing.

This patch send Extended SEL structure information before sending
actual PEL log... so that BMC understands its eSEL log and logs
it apropriately.

Signed-off-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
Cc: Alistair Popple <alistair at popple.id.au>
Cc: Jeremy Kerr <jk at ozlabs.org>
---
Note that presently sensor type is hardcoded to 0x01. We need to add actual
OPAL sensor type.

-Vasant

 hw/ipmi/ipmi-sel.c | 64 ++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 52 insertions(+), 12 deletions(-)

diff --git a/hw/ipmi/ipmi-sel.c b/hw/ipmi/ipmi-sel.c
index e672ecf..c155d32 100644
--- a/hw/ipmi/ipmi-sel.c
+++ b/hw/ipmi/ipmi-sel.c
@@ -56,6 +56,30 @@ struct oem_sel {
 	uint8_t data[4];
 };
 
+/* Extended SEL OEM Record Entry */
+struct oem_esel {
+	le16		record_id;
+	uint8_t		record_type;
+	le32		timestamp;
+	le16		generator_id;
+	uint8_t		evm_ver;
+	uint8_t		sensor_type;
+	uint8_t		sensor_number;
+	uint8_t		event_dir_type;
+	uint8_t		signature;
+	le16		offset;
+} __packed;
+
+static struct oem_esel oem_esel = {
+	.record_type	= 0xDF,
+	.generator_id	= 0x2000,
+	.evm_ver	= 0x04,
+	.sensor_type	= 0x01,
+	.sensor_number	= 0x01,
+	.event_dir_type	= 0x01,
+	.signature	= 0xAA,
+};
+
 /* As far as I can tell the size of PEL record is unbounded (due to
  * the possible presence of the user defined section). We chose this
  * size because it's what hostboot also uses and most of the OPAL logs
@@ -79,7 +103,8 @@ static void ipmi_elog_error(struct ipmi_msg *msg)
 /* Goes through the required steps to add a complete eSEL:
  *
  *  1. Get a reservation
- *  2. Partially add data to the SEL
+ *  2. Add eSEL header
+ *  3. Partially add data to the SEL
  *
  * Because a reservation is needed we need to ensure eSEL's are added
  * as a single transaction as concurrent/interleaved adds would cancel
@@ -96,15 +121,19 @@ static void ipmi_elog_error(struct ipmi_msg *msg)
  */
 static void ipmi_elog_poll(struct ipmi_msg *msg)
 {
+	static bool first = false;
 	static char pel_buf[MAX_PEL_SIZE];
 	static size_t pel_size;
-	static int index = 0;
+	static size_t esel_size;
+	static int esel_index = 0;
+	int pel_index;
 	static unsigned int reservation_id = 0;
 	static unsigned int record_id = 0;
 	struct errorlog *elog_buf = (struct errorlog *) msg->user_data;
 	size_t req_size;
 
 	if (msg->cmd == IPMI_CMD(IPMI_RESERVE_SEL)) {
+		first = true;
 		reservation_id = msg->data[0];
 		reservation_id |= msg->data[1] << 8;
 		if (!reservation_id) {
@@ -118,7 +147,8 @@ static void ipmi_elog_poll(struct ipmi_msg *msg)
 		}
 
 		pel_size = create_pel_log(elog_buf, pel_buf, MAX_PEL_SIZE);
-		index = 0;
+		esel_size = pel_size + sizeof(struct oem_esel);
+		esel_index = 0;
 		record_id = 0;
 	} else {
 		record_id = msg->data[0];
@@ -126,21 +156,21 @@ static void ipmi_elog_poll(struct ipmi_msg *msg)
 	}
 
 	/* Start or continue the IPMI_PARTIAL_ADD_SEL */
-	if (index >= pel_size) {
+	if (esel_index >= esel_size) {
 		/* We're all done. Invalidate the resevation id to
 		 * ensure we get an error if we cut in on another eSEL
 		 * message. */
 		reservation_id = 0;
-		index = 0;
+		esel_index = 0;
 		opal_elog_complete(elog_buf, true);
 		ipmi_free_msg(msg);
 		return;
 	}
 
-	if ((pel_size - index) < (IPMI_MAX_REQ_SIZE - ESEL_HDR_SIZE)) {
+	if ((esel_size - esel_index) < (IPMI_MAX_REQ_SIZE - ESEL_HDR_SIZE)) {
 		/* Last data to send */
 		msg->data[6] = 1;
-		req_size = pel_size - index + ESEL_HDR_SIZE;
+		req_size = esel_size - esel_index + ESEL_HDR_SIZE;
 	} else {
 		msg->data[6] = 0;
 		req_size = IPMI_MAX_REQ_SIZE;
@@ -153,11 +183,21 @@ static void ipmi_elog_poll(struct ipmi_msg *msg)
 	msg->data[1] = (reservation_id >> 8) & 0xff;
 	msg->data[2] = record_id & 0xff;
 	msg->data[3] = (record_id >> 8) & 0xff;
-	msg->data[4] = index & 0xff;
-	msg->data[5] = (index >> 8) & 0xff;
-
-	memcpy(&msg->data[ESEL_HDR_SIZE], &pel_buf[index], msg->req_size - ESEL_HDR_SIZE);
-	index += msg->req_size - ESEL_HDR_SIZE;
+	msg->data[4] = esel_index & 0xff;
+	msg->data[5] = (esel_index >> 8) & 0xff;
+
+	if (first) {
+		first = false;
+		memcpy(&msg->data[ESEL_HDR_SIZE],
+		       &oem_esel, sizeof(struct oem_esel));
+		esel_index = sizeof(struct oem_esel);
+		msg->req_size = esel_index + ESEL_HDR_SIZE;
+	} else {
+		pel_index = esel_index - sizeof(struct oem_esel);
+		memcpy(&msg->data[ESEL_HDR_SIZE],
+		       &pel_buf[pel_index], msg->req_size - ESEL_HDR_SIZE);
+		esel_index += msg->req_size - ESEL_HDR_SIZE;
+	}
 
 	ipmi_queue_msg_head(msg);
 	return;
-- 
2.1.0



More information about the Skiboot mailing list