[Skiboot] [PATCH v2 2/6] FSP/ELOG: Fix OPAL generated elog event notification

Vasant Hegde hegdevasant at linux.vnet.ibm.com
Sun Jul 3 01:33:39 AEST 2016


We use elog notifier to notify logs from multiple sources (FSP generated
logs - fsp-elog-read.c and OPAL generated logs - fsp-elog-write.c).

OPAL generated logs sets elog event bit whenever it has new logs to send
to host. But it relies on fsp-elog-read.c to disable the event bit..which
is wrong!

This patch creates common function to enable/disable event notification.
It will enable event notification if any of the source is ready to send
error log to host and disables notification once it completes sending
all errors to host.

Signed-off-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
---
Changes in v2:
  Fixed OPAL generated log code (fsp-elog-write.c).

Vasant

 hw/fsp/fsp-elog-read.c  | 27 ++++++++++++++++++---------
 hw/fsp/fsp-elog-write.c | 23 ++++++++++++++---------
 include/fsp-elog.h      |  2 ++
 3 files changed, 34 insertions(+), 18 deletions(-)

diff --git a/hw/fsp/fsp-elog-read.c b/hw/fsp/fsp-elog-read.c
index a7897a8..d55c858 100644
--- a/hw/fsp/fsp-elog-read.c
+++ b/hw/fsp/fsp-elog-read.c
@@ -148,26 +148,35 @@ static void fsp_elog_check_and_fetch_head(void)
 	unlock(&elog_read_lock);
 }
 
-/* this function should be called with the lock held */
-static void fsp_elog_set_head_state(enum elog_head_state state)
+void elog_set_head_state(bool opal_logs, enum elog_head_state state)
 {
-	enum elog_head_state old_state = elog_read_from_fsp_head_state;
-
-	elog_read_from_fsp_head_state = state;
+	static enum elog_head_state opal_logs_state = ELOG_STATE_NONE;
+	static enum elog_head_state fsp_logs_state = ELOG_STATE_NONE;
 
 	/* ELOG disabled */
 	if (!elog_enabled)
 		return;
 
-	if (state == ELOG_STATE_FETCHED_DATA &&
-			old_state != ELOG_STATE_FETCHED_DATA)
+	if (opal_logs)
+		opal_logs_state = state;
+	else
+		fsp_logs_state = state;
+
+	if (fsp_logs_state == ELOG_STATE_FETCHED_DATA ||
+	    opal_logs_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)
+	else
 		opal_update_pending_evt(OPAL_EVENT_ERROR_LOG_AVAIL, 0);
 }
 
+/* this function should be called with the lock held */
+static inline void fsp_elog_set_head_state(enum elog_head_state state)
+{
+	elog_set_head_state(false, state);
+	elog_read_from_fsp_head_state = state;
+}
+
 /*
  * when we try maximum time of fetching log from fsp
  * we call following function to delete log from the
diff --git a/hw/fsp/fsp-elog-write.c b/hw/fsp/fsp-elog-write.c
index 5358823..80a0a39 100644
--- a/hw/fsp/fsp-elog-write.c
+++ b/hw/fsp/fsp-elog-write.c
@@ -126,6 +126,13 @@ static int64_t fsp_opal_elog_write(size_t opal_elog_size)
 	return OPAL_SUCCESS;
 }
 
+/* This should be called with elog_write_to_host_lock lock */
+static inline void fsp_elog_write_set_head_state(enum elog_head_state state)
+{
+	elog_set_head_state(true, state);
+	elog_write_to_host_head_state = state;
+}
+
 bool opal_elog_info(uint64_t *opal_elog_id, uint64_t *opal_elog_size)
 {
 	struct errorlog *head;
@@ -145,11 +152,11 @@ bool opal_elog_info(uint64_t *opal_elog_id, uint64_t *opal_elog_size)
 			prlog(PR_ERR,
 			      "%s: Inconsistent internal list state !\n",
 			      __func__);
-			elog_write_to_host_head_state = ELOG_STATE_NONE;
+			fsp_elog_write_set_head_state(ELOG_STATE_NONE);
 		} else {
 			*opal_elog_id = head->plid;
 			*opal_elog_size = head->log_size;
-			elog_write_to_host_head_state = ELOG_STATE_FETCHED_INFO;
+			fsp_elog_write_set_head_state(ELOG_STATE_FETCHED_INFO);
 			rc = true;
 		}
 	}
@@ -170,9 +177,7 @@ static 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);
+		fsp_elog_write_set_head_state(ELOG_STATE_FETCHED_DATA);
 	}
 	unlock(&elog_write_to_host_lock);
 }
@@ -189,7 +194,7 @@ bool opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
 		log_data = list_top(&elog_write_to_host_pending,
 					struct errorlog, link);
 		if (!log_data) {
-			elog_write_to_host_head_state = ELOG_STATE_NONE;
+			fsp_elog_write_set_head_state(ELOG_STATE_NONE);
 			unlock(&elog_write_to_host_lock);
 			return rc;
 		}
@@ -204,7 +209,7 @@ 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);
-		elog_write_to_host_head_state = ELOG_STATE_NONE;
+		fsp_elog_write_set_head_state(ELOG_STATE_NONE);
 		rc = true;
 	}
 	unlock(&elog_write_to_host_lock);
@@ -234,7 +239,7 @@ bool opal_elog_ack(uint64_t ack_id)
 		log_data = list_top(&elog_write_to_host_pending,
 					struct errorlog, link);
 		if (ack_id == log_data->plid)
-			elog_write_to_host_head_state = ELOG_STATE_NONE;
+			fsp_elog_write_set_head_state(ELOG_STATE_NONE);
 
 		list_for_each_safe(&elog_write_to_host_pending, record,
 							next_record, link) {
@@ -264,7 +269,7 @@ void opal_resend_pending_logs(void)
 					struct errorlog, link);
 		list_add_tail(&elog_write_to_host_pending, &record->link);
 	}
-	elog_write_to_host_head_state = ELOG_STATE_NONE;
+	fsp_elog_write_set_head_state(ELOG_STATE_NONE);
 	unlock(&elog_write_to_host_lock);
 	opal_commit_elog_in_host();
 }
diff --git a/include/fsp-elog.h b/include/fsp-elog.h
index 1522b18..37a1953 100644
--- a/include/fsp-elog.h
+++ b/include/fsp-elog.h
@@ -50,4 +50,6 @@ 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 /* __ELOG_H */
-- 
2.5.5



More information about the Skiboot mailing list