[Skiboot] [PATCH 2/3] opal/errorlog : Generalize the errorlog read path

Mukesh Ojha mukesh02 at linux.vnet.ibm.com
Wed Apr 6 21:47:45 AEST 2016


Introduces platform hooks for errorlog info, read, ack, resend pending logs
and elog_pending by adding five new function pointers in the platform
structure.

Adds opal generic function for read, info, ack and resend pending logs as
callback, which will be called from kernel.

Moving the opal call registration from fsp-elog-read.c to core/elog-host.c
and the calling the fsp specific function via platform hooks, which will
be initialised once the platform is known, otherwise it will be NULL.
Declarations of fsp specific routine are kept in fsp-elog.h .

Adds a function 'opal_check_elog_pending_write_to_host' and
'fsp_check_elog_pending' to check the state of the availability of
errorlogs from OPAL and FSP to be 'fetched' or not.

Introduces a function 'opal_elog_set_head_state' to notify the host kernel
about the availabilty of opal errorlogs ready to get pulled. It also
removes a bug of not clearing the 'OPAL_EVENT_ERROR_LOG_AVAIL' after
reading of the opal errorlog is complete.

Signed-off-by: Mukesh Ojha <mukesh02 at linux.vnet.ibm.com>

---
 core/elog-host.c            | 157 ++++++++++++++++++++++++++++++++------------
 hw/fsp/fsp-elog-read.c      | 107 ++++++++++++++----------------
 include/errorlog.h          |   1 +
 include/fsp-elog.h          |  15 +++--
 include/platform.h          |  28 ++++++++
 platforms/ibm-fsp/apollo.c  |   7 +-
 platforms/ibm-fsp/firenze.c |   8 ++-
 7 files changed, 214 insertions(+), 109 deletions(-)

diff --git a/core/elog-host.c b/core/elog-host.c
index 893b9e3..c6ec51a 100644
--- a/core/elog-host.c
+++ b/core/elog-host.c
@@ -21,42 +21,93 @@
 #include <lock.h>
 #include <fsp-elog.h>
 
-/*Log buffer size to WRITE into Host */
+/* Log buffer size to write into Host */
 #define ELOG_WRITE_TO_HOST_BUFFER_SIZE  0x00004000
 
 static LIST_HEAD(elog_write_to_host_pending);
 static LIST_HEAD(elog_write_to_host_processed);
 
 static struct lock elog_write_to_host_lock = LOCK_UNLOCKED;
-
 void *elog_write_to_host_buffer;
 
-/*Manipulate this only with write_lock held*/
+/* Manipulate this only with write_lock held */
 static enum elog_head_state elog_write_to_host_head_state = ELOG_STATE_NONE;
 
-bool opal_elog_info(uint64_t *opal_elog_id, uint64_t *opal_elog_size)
+/* To check whether OPAL errorlogs are pending to get pulled, while FSP
+   errorlogs list got empty*/
+bool opal_check_elog_pending_write_to_host(void)
+{
+	return (elog_write_to_host_head_state == ELOG_STATE_FETCHED_DATA) ?
+		true : false;
+}
+
+/* This function should be called with the lock held */
+static void opal_elog_set_head_state(enum elog_head_state state)
+{
+	enum elog_head_state old_state = elog_write_to_host_head_state;
+
+	elog_write_to_host_head_state = state;
+
+	if (state == ELOG_STATE_FETCHED_DATA &&
+			old_state != ELOG_STATE_FETCHED_DATA)
+		opal_update_pending_evt(OPAL_EVENT_ERROR_LOG_AVAIL,
+				OPAL_EVENT_ERROR_LOG_AVAIL);
+
+	if (state != ELOG_STATE_FETCHED_DATA &&
+			old_state == ELOG_STATE_FETCHED_DATA) {
+		/*
+		 * We assume that this condition is true, only when
+		 * OPAL_EVENT_ERROR_LOG_AVAIL is already in the raised state,
+		 * and it is true.
+		 *
+		 * This checks the availability of the platform errorlog,
+		 * which is ready to get pull in via platform.elog_pending()
+		 * function which return true if it is available otherwise
+		 * false. If it is true, we will let the
+		 * OPAL_EVENT_ERROR_LOG_AVAIL raised otherwise clear the
+		 * OPAL_EVENT_ERROR_LOG_AVAIL signal.
+		 */
+
+		if (platform.elog_pending && platform.elog_pending())
+			return;
+
+		opal_update_pending_evt(OPAL_EVENT_ERROR_LOG_AVAIL, 0);
+	}
+}
+
+static int opal_elog_info(uint64_t *opal_elog_id,
+		uint64_t *opal_elog_size, uint64_t *elog_type)
 {
 	struct errorlog *head;
-	bool rc = false;
+	int rc = OPAL_SUCCESS;
 
 	lock(&elog_write_to_host_lock);
 	if (elog_write_to_host_head_state == ELOG_STATE_FETCHED_DATA) {
 		head = list_top(&elog_write_to_host_pending,
-					struct errorlog, link);
+				struct errorlog, link);
 		if (!head) {
 			prlog(PR_ERR,
-			      "%s: Inconsistent internal list state !\n",
-			      __func__);
-			elog_write_to_host_head_state = ELOG_STATE_NONE;
+					"%s: Inconsistent internal list state !\n",
+					__func__);
+			opal_elog_set_head_state(ELOG_STATE_NONE);
+			unlock(&elog_write_to_host_lock);
+			return OPAL_INTERNAL_ERROR;
+
 		} else {
 			*opal_elog_id = head->plid;
 			*opal_elog_size = head->log_size;
-			elog_write_to_host_head_state = ELOG_STATE_FETCHED_INFO;
-			rc = true;
+			opal_elog_set_head_state(ELOG_STATE_FETCHED_INFO);
+			unlock(&elog_write_to_host_lock);
+			return rc;
 		}
 	}
 	unlock(&elog_write_to_host_lock);
-	return rc;
+
+	if (platform.elog_info)
+		return platform.elog_info(opal_elog_id,
+					 opal_elog_size, elog_type);
+
+	return OPAL_PARAMETER;
 }
 
 void opal_commit_elog_in_host(void)
@@ -72,103 +123,117 @@ void opal_commit_elog_in_host(void)
 		buf->log_size = create_pel_log(buf,
 					(char *)elog_write_to_host_buffer,
 						ELOG_WRITE_TO_HOST_BUFFER_SIZE);
-		elog_write_to_host_head_state = ELOG_STATE_FETCHED_DATA;
-		opal_update_pending_evt(OPAL_EVENT_ERROR_LOG_AVAIL,
-					OPAL_EVENT_ERROR_LOG_AVAIL);
+		opal_elog_set_head_state(ELOG_STATE_FETCHED_DATA);
 	}
 	unlock(&elog_write_to_host_lock);
 }
 
-
-bool opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
-		    uint64_t opal_elog_id)
+static int opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
+		uint64_t opal_elog_id)
 {
 	struct errorlog *log_data;
-	bool rc = false;
+	int rc = OPAL_SUCCESS;
 
 	lock(&elog_write_to_host_lock);
 	if (elog_write_to_host_head_state == ELOG_STATE_FETCHED_INFO) {
 		log_data = list_top(&elog_write_to_host_pending,
-					struct errorlog, link);
+				struct errorlog, link);
 		if (!log_data) {
-			elog_write_to_host_head_state = ELOG_STATE_NONE;
+			opal_elog_set_head_state(ELOG_STATE_NONE);
 			unlock(&elog_write_to_host_lock);
-			return rc;
+			return OPAL_INTERNAL_ERROR;
 		}
 		if ((opal_elog_id != log_data->plid) &&
-		    (opal_elog_size != log_data->log_size)) {
+				(opal_elog_size != log_data->log_size)) {
 			unlock(&elog_write_to_host_lock);
-			return rc;
+			return OPAL_PARAMETER;
 		}
 
 		memcpy((void *)buffer, elog_write_to_host_buffer,
-							opal_elog_size);
+				opal_elog_size);
 
 		list_del(&log_data->link);
 		list_add(&elog_write_to_host_processed, &log_data->link);
-		elog_write_to_host_head_state = ELOG_STATE_NONE;
-		rc = true;
+		opal_elog_set_head_state(ELOG_STATE_NONE);
+		unlock(&elog_write_to_host_lock);
+		opal_commit_elog_in_host();
+		return rc;
 	}
 	unlock(&elog_write_to_host_lock);
-	opal_commit_elog_in_host();
-	return rc;
+
+	if (platform.elog_read)
+		return platform.elog_read(buffer, opal_elog_size, opal_elog_id);
+
+	return OPAL_PARAMETER;
 }
 
-bool opal_elog_ack(uint64_t ack_id)
+static int opal_elog_ack(uint64_t ack_id)
 {
-	bool rc = false;
+	int rc = OPAL_SUCCESS;
 	struct errorlog *log_data;
 	struct errorlog *record, *next_record;
 
 	lock(&elog_write_to_host_lock);
 	if (!list_empty(&elog_write_to_host_processed)) {
 		list_for_each_safe(&elog_write_to_host_processed, record,
-							next_record, link) {
+				next_record, link) {
 			if (record->plid != ack_id)
 				continue;
 			list_del(&record->link);
 			opal_elog_complete(record, true);
-			rc = true;
+			unlock(&elog_write_to_host_lock);
+			return rc;
 		}
 	}
 
 	if ((!rc) && (!list_empty(&elog_write_to_host_pending))) {
 		log_data = list_top(&elog_write_to_host_pending,
-					struct errorlog, link);
+				struct errorlog, link);
 		if (ack_id == log_data->plid)
-			elog_write_to_host_head_state = ELOG_STATE_NONE;
+			opal_elog_set_head_state(ELOG_STATE_NONE);
 
 		list_for_each_safe(&elog_write_to_host_pending, record,
-							next_record, link) {
+				next_record, link) {
 			if (record->plid != ack_id)
 				continue;
 			list_del(&record->link);
 			opal_elog_complete(record, true);
-			rc = true;
+			unlock(&elog_write_to_host_lock);
+			return rc;
 		}
 	}
 	unlock(&elog_write_to_host_lock);
-	return rc;
+
+	if (platform.elog_ack)
+		return platform.elog_ack(ack_id);
+
+	return OPAL_PARAMETER;
 }
 
-void opal_resend_pending_logs(void)
+static void opal_resend_pending_logs(void)
 {
 	struct errorlog *record;
 
 	lock(&elog_write_to_host_lock);
 	if (list_empty(&elog_write_to_host_processed)) {
 		unlock(&elog_write_to_host_lock);
-		return;
+		goto out;
 	}
 
 	while (!list_empty(&elog_write_to_host_processed)) {
 		record = list_pop(&elog_write_to_host_processed,
-					struct errorlog, link);
+				struct errorlog, link);
 		list_add_tail(&elog_write_to_host_pending, &record->link);
 	}
-	elog_write_to_host_head_state = ELOG_STATE_NONE;
+	opal_elog_set_head_state(ELOG_STATE_NONE);
 	unlock(&elog_write_to_host_lock);
 	opal_commit_elog_in_host();
+
+out:
+	if (platform.resend_pending_elogs)
+		platform.resend_pending_elogs();
+
+	return;
 }
 
 void elog_append_write_to_host(struct errorlog *buf)
@@ -187,7 +252,13 @@ void elog_append_write_to_host(struct errorlog *buf)
 void opal_elog_init(void)
 {
 	elog_write_to_host_buffer = memalign(TCE_PSIZE,
-					ELOG_WRITE_TO_HOST_BUFFER_SIZE);
+			ELOG_WRITE_TO_HOST_BUFFER_SIZE);
 	assert(elog_write_to_host_buffer);
 	elog_init();
+
+	/* Register OPAL Interface */
+	opal_register(OPAL_ELOG_READ, opal_elog_read, 3);
+	opal_register(OPAL_ELOG_ACK, opal_elog_ack, 1);
+	opal_register(OPAL_ELOG_RESEND, opal_resend_pending_logs, 0);
+	opal_register(OPAL_ELOG_SIZE, opal_elog_info, 3);
 }
diff --git a/hw/fsp/fsp-elog-read.c b/hw/fsp/fsp-elog-read.c
index 16667ae..c616067 100644
--- a/hw/fsp/fsp-elog-read.c
+++ b/hw/fsp/fsp-elog-read.c
@@ -61,7 +61,10 @@
  */
 #define ELOG_READ_MAX_RECORD		128
 
-/* structure to maintain log-id,log-size, pending and processed list */
+/* Log buffer to copy FSP log for read */
+#define ELOG_READ_BUFFER_SIZE	0x00004000
+
+/* Structure to maintain log-id,log-size, pending and processed list */
 struct fsp_log_entry {
 	uint32_t log_id;
 	size_t log_size;
@@ -73,17 +76,15 @@ static LIST_HEAD(elog_read_processed);
 static LIST_HEAD(elog_read_free);
 
 /*
- * lock is used to protect overwriting of processed and pending list
+ * Lock is used to protect overwriting of processed and pending list
  * and also used while updating state of each log
  */
 static struct lock elog_read_lock = LOCK_UNLOCKED;
 
-/* log buffer  to copy FSP log for READ */
-#define ELOG_READ_BUFFER_SIZE	0x00004000
 static void *elog_read_buffer;
 static uint32_t elog_head_id;	/* FSP entry ID */
-static size_t elog_head_size;	/* actual FSP log size */
-static uint32_t elog_read_retries;	/* bad response status count */
+static size_t elog_head_size;	/* Actual FSP log size */
+static uint32_t elog_read_retries;	/* Bad response status count */
 
 /* Initialize the state of the log */
 static enum elog_head_state elog_read_from_fsp_head_state = ELOG_STATE_NONE;
@@ -91,8 +92,15 @@ static enum elog_head_state elog_read_from_fsp_head_state = ELOG_STATE_NONE;
 /* Need forward declaration because of Circular dependency */
 static void fsp_elog_queue_fetch(void);
 
+/* To check Whether FSP errorlogs are pending to be pulled*/
+bool fsp_check_elog_pending(void)
+{
+	return (elog_read_from_fsp_head_state == ELOG_STATE_FETCHED_DATA) ?
+			true : false;
+}
+
 /*
- * check the response message for mbox acknowledgment
+ * Check the response message for mbox acknowledgment
  * command send to FSP.
  */
 static void fsp_elog_ack_complete(struct fsp_msg *msg)
@@ -107,10 +115,9 @@ static void fsp_elog_ack_complete(struct fsp_msg *msg)
 	fsp_freemsg(msg);
 }
 
-/* send Error Log PHYP Acknowledgment to FSP with entry ID */
+/* Send errorlog PHYP Acknowledgment to FSP with entry ID */
 static int64_t fsp_send_elog_ack(uint32_t log_id)
 {
-
 	struct fsp_msg *ack_msg;
 
 	ack_msg = fsp_mkmsg(FSP_CMD_ERRLOG_PHYP_ACK, 1, log_id);
@@ -127,7 +134,7 @@ static int64_t fsp_send_elog_ack(uint32_t log_id)
 	return OPAL_SUCCESS;
 }
 
-/* retrive error log from FSP with TCE for the data transfer */
+/* Retrieve errorlog from FSP with TCE for the data transfer */
 static void fsp_elog_check_and_fetch_head(void)
 {
 	lock(&elog_read_lock);
@@ -145,7 +152,7 @@ static void fsp_elog_check_and_fetch_head(void)
 	unlock(&elog_read_lock);
 }
 
-/* this function should be called with the lock held */
+/* This function should be called with the lock held */
 static void fsp_elog_set_head_state(enum elog_head_state state)
 {
 	enum elog_head_state old_state = elog_read_from_fsp_head_state;
@@ -156,17 +163,22 @@ static void fsp_elog_set_head_state(enum elog_head_state state)
 			old_state != ELOG_STATE_FETCHED_DATA)
 		opal_update_pending_evt(OPAL_EVENT_ERROR_LOG_AVAIL,
 					OPAL_EVENT_ERROR_LOG_AVAIL);
+
 	if (state != ELOG_STATE_FETCHED_DATA &&
-			old_state == ELOG_STATE_FETCHED_DATA)
+			old_state == ELOG_STATE_FETCHED_DATA) {
+		if (opal_check_elog_pending_write_to_host())
+			return;
+
 		opal_update_pending_evt(OPAL_EVENT_ERROR_LOG_AVAIL, 0);
+	}
 }
 
 /*
- * when we try maximum time of fetching log from fsp
+ * When we try maximum time of fetching log from fsp
  * we call following function to delete log from the
- * pending list and update the state to fetch next log
+ * pending list and update the state to fetch next log.
  *
- * this function should be called with the lock held
+ * This function should be called with the lock held
  */
 static void fsp_elog_fetch_failure(uint8_t fsp_status)
 {
@@ -191,7 +203,6 @@ static void fsp_elog_fetch_failure(uint8_t fsp_status)
 static void fsp_elog_read_complete(struct fsp_msg *read_msg)
 {
 	uint8_t val;
-	/*struct fsp_log_entry *log_data;*/
 
 	lock(&elog_read_lock);
 	val = (read_msg->resp->word1 >> 8) & 0xff;
@@ -210,7 +221,7 @@ static void fsp_elog_read_complete(struct fsp_msg *read_msg)
 	case FSP_STATUS_DMA_ERROR:
 		if (elog_read_retries++ < MAX_RETRIES) {
 			/*
-			 * for a error response value from FSP, we try to
+			 * For a error response value from FSP, we try to
 			 * send fetch sp data mbox command again for three
 			 * times if response from FSP is still not valid
 			 * we send generic error response to fsp.
@@ -232,7 +243,7 @@ elog_read_out:
 	fsp_elog_check_and_fetch_head();
 }
 
-/* read error log from FSP through mbox commands */
+/* Read errorlog from FSP through mbox commands */
 static void fsp_elog_queue_fetch(void)
 {
 	int rc;
@@ -259,19 +270,15 @@ static void fsp_elog_queue_fetch(void)
 	}
 }
 
-/* opal interface for powernv to read log size and log ID from sapphire */
-static int64_t fsp_opal_elog_info(uint64_t *opal_elog_id,
+/* Opal interface for powernv to read log size and log ID from sapphire */
+int fsp_opal_elog_info(uint64_t *opal_elog_id,
 				  uint64_t *opal_elog_size, uint64_t *elog_type)
 {
 	struct fsp_log_entry *log_data;
 
-	/* copy type of the error log */
+	/* Copy type of the error log */
 	*elog_type = ELOG_TYPE_PEL;
 
-	/* Check if any OPAL log needs to be reported to the host */
-	if (opal_elog_info(opal_elog_id, opal_elog_size))
-		return OPAL_SUCCESS;
-
 	lock(&elog_read_lock);
 	if (elog_read_from_fsp_head_state != ELOG_STATE_FETCHED_DATA) {
 		unlock(&elog_read_lock);
@@ -290,17 +297,13 @@ static int64_t fsp_opal_elog_info(uint64_t *opal_elog_id,
 	return OPAL_SUCCESS;
 }
 
-/* opal interface for powernv to read log from sapphire */
-static int64_t fsp_opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
+/* Opal interface for powernv to read log from sapphire */
+int fsp_opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
 				  uint64_t opal_elog_id)
 {
 	int size = opal_elog_size;
 	struct fsp_log_entry *log_data;
 
-
-	/* Check if any OPAL log needs to be reported to the host */
-	if (opal_elog_read(buffer, opal_elog_size, opal_elog_id))
-		return OPAL_SUCCESS;
 	/*
 	 * Read top entry from list.
 	 * as we know always top record of the list is fetched from FSP
@@ -333,7 +336,7 @@ static int64_t fsp_opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
 	memcpy((void *)buffer, elog_read_buffer, size);
 
 	/*
-	 * once log is read from linux move record from pending
+	 * Once log is read from linux move record from pending
 	 * to processed list and delete record from pending list
 	 * and change state of the log to fetch next record
 	 */
@@ -343,13 +346,13 @@ static int64_t fsp_opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
 	unlock(&elog_read_lock);
 
 
-	/* read error log from FSP */
+	/* Read error log from FSP */
 	fsp_elog_check_and_fetch_head();
 
 	return OPAL_SUCCESS;
 }
 
-/* set state of the log head before fetching the log */
+/* Set state of the log head before fetching the log */
 static void elog_reject_head(void)
 {
 	if (elog_read_from_fsp_head_state == ELOG_STATE_FETCHING)
@@ -358,15 +361,12 @@ static void elog_reject_head(void)
 		fsp_elog_set_head_state(ELOG_STATE_NONE);
 }
 
-/* opal Interface for powernv to send ack to fsp with log ID */
-static int64_t fsp_opal_elog_ack(uint64_t ack_id)
+/* Opal interface for powernv to send ack to fsp with log ID */
+int fsp_opal_elog_ack(uint64_t ack_id)
 {
 	int rc = 0;
 	struct fsp_log_entry  *record, *next_record;
 
-	if (opal_elog_ack(ack_id))
-		return rc;
-
 	/* Send acknowledgement to FSP */
 	rc = fsp_send_elog_ack(ack_id);
 	if (rc != OPAL_SUCCESS) {
@@ -392,16 +392,13 @@ static int64_t fsp_opal_elog_ack(uint64_t ack_id)
 }
 
 /*
- * once linux kexec's it ask to resend all logs which
+ * Once linux kexec's it ask to resend all logs which
  * are not acknowledged from  linux
  */
-static void fsp_opal_resend_pending_logs(void)
+void fsp_opal_resend_pending_logs(void)
 {
 	struct fsp_log_entry  *entry;
 
-	/* Check if any Sapphire logs are pending */
-	opal_resend_pending_logs();
-
 	lock(&elog_read_lock);
 	/*
 	 * If processed list is not empty add all record from
@@ -431,7 +428,7 @@ static void fsp_opal_resend_pending_logs(void)
 	fsp_elog_check_and_fetch_head();
 }
 
-/* fsp elog notify function  */
+/* FSP elog notify function  */
 static bool fsp_elog_msg(uint32_t cmd_sub_mod, struct fsp_msg *msg)
 {
 	int rc = 0;
@@ -456,7 +453,7 @@ static bool fsp_elog_msg(uint32_t cmd_sub_mod, struct fsp_msg *msg)
 		       log_id, log_size);
 	}
 
-	/* take a lock until we take out the node from elog_read_free */
+	/* Take a lock until we take out the node from elog_read_free */
 	lock(&elog_read_lock);
 	if (!list_empty(&elog_read_free)) {
 		/* Create a new entry in the pending list */
@@ -473,13 +470,13 @@ static bool fsp_elog_msg(uint32_t cmd_sub_mod, struct fsp_msg *msg)
 			prerror("ELOG: Failed to queue errlog notification"
 				" response: %d\n", rc);
 
-		/* read error log from FSP */
+		/* Read error log from FSP */
 		fsp_elog_check_and_fetch_head();
 
 	} else {
 		printf("ELOG: Log entry 0x%08x discarded\n", log_id);
 
-		/* unlock if elog_read_free is empty */
+		/* Unlock if elog_read_free is empty */
 		unlock(&elog_read_lock);
 
 		rc = fsp_queue_msg(fsp_mkmsg(FSP_RSP_ERRLOG_NOTIFICATION,
@@ -488,7 +485,7 @@ static bool fsp_elog_msg(uint32_t cmd_sub_mod, struct fsp_msg *msg)
 			prerror("ELOG: Failed to queue errlog notification"
 				" response: %d\n", rc);
 		/*
-		 * if list is full with max record then we
+		 * If list is full with max record then we
 		 * send discarded by phyp (condition full) ack to FSP.
 		 *
 		 * At some point in the future, we'll get notified again.
@@ -529,7 +526,7 @@ out_err:
 	return -ENOMEM;
 }
 
-/* fsp elog read init function */
+/* FSP elog read init function */
 void fsp_elog_read_init(void)
 {
 	int val = 0;
@@ -547,17 +544,11 @@ void fsp_elog_read_init(void)
 	fsp_tce_map(PSI_DMA_ERRLOG_READ_BUF, elog_read_buffer,
 					PSI_DMA_ERRLOG_READ_BUF_SZ);
 
-	/* pre allocate memory for 128 record */
+	/* Pre allocate memory for 128 record */
 	val = init_elog_read_free_list(ELOG_READ_MAX_RECORD);
 	if (val != 0)
 		return;
 
-	/* register Eror log Class D2 */
+	/* Register errorlog Class D2 */
 	fsp_register_client(&fsp_get_elog_notify, FSP_MCLASS_ERR_LOG);
-
-	/* register opal Interface */
-	opal_register(OPAL_ELOG_READ, fsp_opal_elog_read, 3);
-	opal_register(OPAL_ELOG_ACK, fsp_opal_elog_ack, 1);
-	opal_register(OPAL_ELOG_RESEND, fsp_opal_resend_pending_logs, 0);
-	opal_register(OPAL_ELOG_SIZE, fsp_opal_elog_info, 3);
 }
diff --git a/include/errorlog.h b/include/errorlog.h
index ba1c6aa..d58eb5e 100644
--- a/include/errorlog.h
+++ b/include/errorlog.h
@@ -356,6 +356,7 @@ void opal_elog_complete(struct errorlog *elog, bool success);
 
 void opal_elog_init(void);
 void opal_commit_elog_in_host(void);
+bool opal_check_elog_pending_write_to_host(void);
 void elog_append_write_to_host(struct errorlog *buf);
 int elog_init(void);
 
diff --git a/include/fsp-elog.h b/include/fsp-elog.h
index 1522b18..5fdda93 100644
--- a/include/fsp-elog.h
+++ b/include/fsp-elog.h
@@ -37,17 +37,20 @@ enum elog_head_state {
 
 /* Generate src from opal reason code (src_comp) */
 #define generate_src_from_comp(src_comp)  (OPAL_SRC_TYPE_ERROR << 24 | \
-				OPAL_FAILING_SUBSYSTEM << 16 | src_comp)
+		OPAL_FAILING_SUBSYSTEM << 16 | src_comp)
 
 int elog_fsp_commit(struct errorlog *buf) __warn_unused_result;
 
-bool opal_elog_info(uint64_t *opal_elog_id, uint64_t *opal_elog_size) __warn_unused_result;
+bool fsp_check_elog_pending(void);
 
-bool opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
-						uint64_t opal_elog_id) __warn_unused_result;
+int fsp_opal_elog_info(uint64_t *opal_elog_id,
+		uint64_t *opal_elog_size, uint64_t *elog_type);
 
-bool opal_elog_ack(uint64_t ack_id) __warn_unused_result;
+int fsp_opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
+		uint64_t opal_elog_id);
 
-void opal_resend_pending_logs(void);
+int fsp_opal_elog_ack(uint64_t ack_id);
+
+void fsp_opal_resend_pending_logs(void);
 
 #endif /* __ELOG_H */
diff --git a/include/platform.h b/include/platform.h
index f1bdc30..43a1bca 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -163,6 +163,34 @@ struct platform {
 	 * OPAL terminate
 	 */
 	void __attribute__((noreturn)) (*terminate)(const char *msg);
+
+	/*
+	 * OPAL interface for powernv to read log size and log ID from sapphire
+	 */
+	int         (*elog_info)(uint64_t *opal_elog_id,
+			uint64_t *opal_elog_size, uint64_t *elog_type);
+
+	/*
+	 * OPAL interface for powernv to read log from sapphire
+	 */
+	int         (*elog_read)(uint64_t *buffer, uint64_t opal_elog_size,
+			uint64_t opal_elog_id);
+
+	/*
+	 * OPAL Interface for powernv to send ack to fsp with log ID
+	 */
+	int         (*elog_ack)(uint64_t ack_id);
+
+	/*
+	 * once linux kexec's it ask to resend all logs which
+	 * are not acknowledged from  linux
+	 */
+	void         (*resend_pending_elogs)(void);
+
+	/*
+	 * Checking whether elogs are available from the platform
+	 */
+	bool	     (*elog_pending)(void);
 };
 
 extern struct platform __platforms_start;
diff --git a/platforms/ibm-fsp/apollo.c b/platforms/ibm-fsp/apollo.c
index e9616d5..39e128a 100644
--- a/platforms/ibm-fsp/apollo.c
+++ b/platforms/ibm-fsp/apollo.c
@@ -19,7 +19,7 @@
 #include <device.h>
 #include <fsp.h>
 #include <pci.h>
-
+#include <fsp-elog.h>
 #include "ibm-fsp.h"
 #include "lxvpd.h"
 
@@ -64,4 +64,9 @@ DECLARE_PLATFORM(apollo) = {
 	.resource_loaded	= fsp_resource_loaded,
 	.sensor_read		= ibm_fsp_sensor_read,
 	.terminate		= ibm_fsp_terminate,
+	.elog_info              = fsp_opal_elog_info,
+	.elog_read              = fsp_opal_elog_read,
+	.elog_ack               = fsp_opal_elog_ack,
+	.resend_pending_elogs   = fsp_opal_resend_pending_logs,
+	.elog_pending		= fsp_check_elog_pending,
 };
diff --git a/platforms/ibm-fsp/firenze.c b/platforms/ibm-fsp/firenze.c
index 75f566c..85195b3 100644
--- a/platforms/ibm-fsp/firenze.c
+++ b/platforms/ibm-fsp/firenze.c
@@ -24,6 +24,7 @@
 #include <i2c.h>
 #include <timebase.h>
 #include <hostservices.h>
+#include <fsp-elog.h>
 
 #include "ibm-fsp.h"
 #include "lxvpd.h"
@@ -566,4 +567,9 @@ DECLARE_PLATFORM(firenze) = {
 	.resource_loaded	= fsp_resource_loaded,
 	.sensor_read		= ibm_fsp_sensor_read,
 	.terminate		= ibm_fsp_terminate,
-} ;
+	.elog_info              = fsp_opal_elog_info,
+	.elog_read              = fsp_opal_elog_read,
+	.elog_ack               = fsp_opal_elog_ack,
+	.resend_pending_elogs   = fsp_opal_resend_pending_logs,
+	.elog_pending		= fsp_check_elog_pending,
+};
-- 
2.1.4



More information about the Skiboot mailing list