[Skiboot] [PATCH V4 4/6] opal/errorlog : Generalizes the error log read path

Mukesh Ojha mukesh02 at linux.vnet.ibm.com
Tue Jul 26 15:45:36 AEST 2016


Introduces platform hooks for error log 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 host.

Moving the opal call registration from fsp-elog-read.c to core/errorlog.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 V4:
 - Changes are rebased on master.
 - Changes done for core/elog-host moved to core/errorlog.c .

Changes in V3:
 - No changes.

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

 core/errorlog.c             | 61 ++++++++++++++++++++++++++++++++-------------
 hw/fsp/fsp-elog-read.c      | 29 +++------------------
 include/errorlog.h          |  6 -----
 include/fsp-elog.h          |  7 ++++++
 include/platform.h          | 23 +++++++++++++++++
 platforms/ibm-fsp/apollo.c  |  7 +++++-
 platforms/ibm-fsp/firenze.c |  7 +++++-
 7 files changed, 90 insertions(+), 50 deletions(-)

diff --git a/core/errorlog.c b/core/errorlog.c
index 12dc7a4..5648433 100644
--- a/core/errorlog.c
+++ b/core/errorlog.c
@@ -230,10 +230,11 @@ static inline void opal_elog_write_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) {
@@ -249,16 +250,23 @@ bool opal_elog_info(uint64_t *opal_elog_id, uint64_t *opal_elog_size)
 			prlog(PR_ERR, "%s:Inconsistent internal list state !\n",
 					__func__);
 			opal_elog_write_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_write_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;
 }
 
 static void opal_commit_elog_in_host(void)
@@ -279,11 +287,11 @@ static 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,
+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) {
@@ -292,13 +300,13 @@ bool opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
 		if (!log_data) {
 			opal_elog_write_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)) {
 			unlock(&elog_write_to_host_lock);
-			return rc;
+			return OPAL_PARAMETER;
 		}
 
 		memcpy((void *)buffer, elog_write_to_host_buffer,
@@ -306,17 +314,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_write_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;
 
@@ -329,7 +341,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;
 		}
 	}
 
@@ -346,7 +359,6 @@ 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);
 			opal_commit_elog_in_host();
 			return rc;
@@ -354,14 +366,20 @@ bool opal_elog_ack(uint64_t ack_id)
 	}
 
 	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);
+	elog_enabled = true;
+	unlock(&elog_write_to_host_lock);
+	lock(&elog_write_to_host_lock);
 	while (!list_empty(&elog_write_to_host_processed)) {
 		record = list_pop(&elog_write_to_host_processed,
 				struct errorlog, link);
@@ -371,6 +389,10 @@ void opal_resend_pending_logs(void)
 	opal_elog_write_set_head_state(ELOG_STATE_NONE);
 	unlock(&elog_write_to_host_lock);
 	opal_commit_elog_in_host();
+	if (platform.resend_pending_elogs)
+		platform.resend_pending_elogs();
+
+	return;
 }
 
 void elog_append_write_to_host(struct errorlog *buf)
@@ -415,5 +437,10 @@ void opal_elog_init(void)
 	elog_write_to_host_buffer = memalign(TCE_PSIZE,
 					ELOG_WRITE_TO_HOST_BUFFER_SIZE);
 	assert(elog_write_to_host_buffer);
+	/* 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);
 	elog_init();
 }
diff --git a/hw/fsp/fsp-elog-read.c b/hw/fsp/fsp-elog-read.c
index 12405c8..60d581c 100644
--- a/hw/fsp/fsp-elog-read.c
+++ b/hw/fsp/fsp-elog-read.c
@@ -278,17 +278,13 @@ 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;
 
 	/* 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);
@@ -318,16 +314,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 PowerNV */
-	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
@@ -388,14 +380,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) {
@@ -439,16 +428,11 @@ 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;
 
 	lock(&elog_read_lock);
-	elog_enabled = true;
-	unlock(&elog_read_lock);
-	/* 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
 	 * processed list to pending list at head of the list
@@ -583,9 +567,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/errorlog.h b/include/errorlog.h
index 3251cfe..8bddce2 100644
--- a/include/errorlog.h
+++ b/include/errorlog.h
@@ -374,12 +374,6 @@ void opal_elog_complete(struct errorlog *elog, bool success);
 void elog_append_write_to_host(struct errorlog *buf);
 int elog_init(void);
 void opal_elog_init(void);
-bool opal_elog_info(uint64_t *opal_elog_id,
-		uint64_t *opal_elog_size) __warn_unused_result;
-bool opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
-		uint64_t opal_elog_id) __warn_unused_result;
-bool opal_elog_ack(uint64_t ack_id) __warn_unused_result;
-void opal_resend_pending_logs(void);
 void elog_set_head_state(bool opal_logs, enum elog_head_state state);
 
 #endif /* __ERRORLOG_H */
diff --git a/include/fsp-elog.h b/include/fsp-elog.h
index 217cdbe..4c6827b 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>
@@ -29,5 +30,11 @@
 extern bool elog_enabled;
 
 int elog_fsp_commit(struct errorlog *buf) __warn_unused_result;
+int fsp_opal_elog_info(uint64_t *opal_elog_id,
+		uint64_t *opal_elog_size, uint64_t *elog_type);
+int fsp_opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
+		uint64_t opal_elog_id);
+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 062a941..8d68454 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -168,6 +168,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 d98699d..63c7a0e 100644
--- a/platforms/ibm-fsp/apollo.c
+++ b/platforms/ibm-fsp/apollo.c
@@ -1,4 +1,4 @@
-/* Copyright 2013-2014 IBM Corp.
+/* Copyright 2013-2016 IBM Corp.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
 #include <skiboot.h>
 #include <device.h>
 #include <fsp.h>
+#include <fsp-elog.h>
 #include <pci.h>
 #include <pci-slot.h>
 
@@ -47,4 +48,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 00aba8d..a2c0783 100644
--- a/platforms/ibm-fsp/firenze.c
+++ b/platforms/ibm-fsp/firenze.c
@@ -1,4 +1,4 @@
-/* Copyright 2013-2014 IBM Corp.
+/* Copyright 2013-2016 IBM Corp.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -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>
@@ -229,4 +230,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.7.4



More information about the Skiboot mailing list