[Skiboot] [PATCH V3 4/6] opal/errorlog : Generalize the errorlog read path

Mukesh Ojha mukesh02 at linux.vnet.ibm.com
Mon Jun 13 06:49:58 AEST 2016


Introduces platform hooks for errorlog info, read, ack, and resend pending logs
by adding four 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 .

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

---
Changes in V3:
 - No changes.

Changes in V2:
 - Separates the Bug solve part to patch 3/6.

 core/elog-host.c            | 77 +++++++++++++++++++++++++++++++--------------
 hw/fsp/fsp-elog-read.c      | 26 +++------------
 include/fsp-elog.h          | 12 ++++---
 include/platform.h          | 23 ++++++++++++++
 platforms/ibm-fsp/apollo.c  |  5 +++
 platforms/ibm-fsp/firenze.c |  5 +++
 6 files changed, 98 insertions(+), 50 deletions(-)

diff --git a/core/elog-host.c b/core/elog-host.c
index 0315055..ff9205a 100644
--- a/core/elog-host.c
+++ b/core/elog-host.c
@@ -68,10 +68,11 @@ static inline void opal_elog_set_head_state(enum elog_head_state state)
 	elog_write_to_host_head_state = state;
 }
 
-bool opal_elog_info(uint64_t *opal_elog_id, uint64_t *opal_elog_size)
+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) {
@@ -79,18 +80,25 @@ bool opal_elog_info(uint64_t *opal_elog_id, uint64_t *opal_elog_size)
 				link);
 		if (!head) {
 			prlog(PR_ERR, "%s: Inconsistent internal list state !\n"
-				, __func__);
+					, __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;
 			opal_elog_set_head_state(ELOG_STATE_FETCHED_INFO);
-			rc = true;
+			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)
@@ -110,11 +118,11 @@ void opal_commit_elog_in_host(void)
 	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) {
@@ -123,13 +131,13 @@ bool opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
 		if (!log_data) {
 			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,
@@ -137,16 +145,21 @@ bool opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
 		list_del(&log_data->link);
 		list_add(&elog_write_to_host_processed, &log_data->link);
 		opal_elog_set_head_state(ELOG_STATE_NONE);
-		rc = true;
+		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;
 
@@ -159,7 +172,8 @@ bool opal_elog_ack(uint64_t ack_id)
 
 			list_del(&record->link);
 			opal_elog_complete(record, true);
-			rc = true;
+			unlock(&elog_write_to_host_lock);
+			return rc;
 		}
 	}
 
@@ -176,32 +190,43 @@ bool opal_elog_ack(uint64_t ack_id)
 
 			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);
 	}
 
 	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)
@@ -220,7 +245,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 9c3f843..8fba6d3 100644
--- a/hw/fsp/fsp-elog-read.c
+++ b/hw/fsp/fsp-elog-read.c
@@ -249,7 +249,7 @@ 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,
+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;
@@ -257,10 +257,6 @@ static int64_t fsp_opal_elog_info(uint64_t *opal_elog_id,
 	/* 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);
@@ -282,16 +278,12 @@ static int64_t fsp_opal_elog_info(uint64_t *opal_elog_id,
 }
 
 /* OPAL interface for PowerNV to read log from sapphire */
-static int64_t fsp_opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
+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
@@ -348,14 +340,11 @@ static void elog_reject_head(void)
 }
 
 /* OPAL interface for PowerNV to send ack to FSP with log ID */
-static int64_t fsp_opal_elog_ack(uint64_t ack_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) {
@@ -386,12 +375,10 @@ static int64_t fsp_opal_elog_ack(uint64_t ack_id)
  * 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
@@ -536,9 +523,4 @@ void fsp_elog_read_init(void)
 
 	/* Register Error log 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/fsp-elog.h b/include/fsp-elog.h
index 812c593..b7dfc5d 100644
--- a/include/fsp-elog.h
+++ b/include/fsp-elog.h
@@ -15,6 +15,7 @@
  */
 #ifndef __ELOG_H
 #define __ELOG_H
+
 #include <opal.h>
 #include <errorlog.h>
 #include <pel.h>
@@ -28,13 +29,14 @@
 
 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;
+int fsp_opal_elog_info(uint64_t *opal_elog_id,
+		uint64_t *opal_elog_size, uint64_t *elog_type);
 
-bool opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
-						uint64_t opal_elog_id) __warn_unused_result;
+int fsp_opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
+		uint64_t opal_elog_id);
 
-bool opal_elog_ack(uint64_t ack_id) __warn_unused_result;
+int fsp_opal_elog_ack(uint64_t ack_id);
 
-void opal_resend_pending_logs(void);
+void fsp_opal_resend_pending_logs(void);
 
 #endif /* __ELOG_H */
diff --git a/include/platform.h b/include/platform.h
index f1bdc30..83cb0f8 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -163,6 +163,29 @@ 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);
 };
 
 extern struct platform __platforms_start;
diff --git a/platforms/ibm-fsp/apollo.c b/platforms/ibm-fsp/apollo.c
index e9616d5..f6a7382 100644
--- a/platforms/ibm-fsp/apollo.c
+++ b/platforms/ibm-fsp/apollo.c
@@ -18,6 +18,7 @@
 #include <skiboot.h>
 #include <device.h>
 #include <fsp.h>
+#include <fsp-elog.h>
 #include <pci.h>
 
 #include "ibm-fsp.h"
@@ -64,4 +65,8 @@ 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,
 };
diff --git a/platforms/ibm-fsp/firenze.c b/platforms/ibm-fsp/firenze.c
index 3ef62a4..d25a505 100644
--- a/platforms/ibm-fsp/firenze.c
+++ b/platforms/ibm-fsp/firenze.c
@@ -18,6 +18,7 @@
 #include <skiboot.h>
 #include <device.h>
 #include <fsp.h>
+#include <fsp-elog.h>
 #include <pci.h>
 #include <pci-cfg.h>
 #include <chip.h>
@@ -566,4 +567,8 @@ 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,
 };
-- 
2.1.4



More information about the Skiboot mailing list