[Skiboot] [PATCH V4 5/6] Introduces get and put elog routine and reference count field in elog structure

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


Introduces a reference count variable in the error log structure, which is
to track the number of user of error log buffer.

get_elog and put_elog routine to increment/decrement the reference count variable.
error log buffer return to the pool on zero count of reference count.

The reason of introducing this patch, as in BMC systems, we use the same
error log buffer to send the log to both BMC, and to the host kernel. This
patch ensures that one does not free the buffer, while the other is using it.

Signed-off-by: Mukesh Ojha <mukesh02 at linux.vnet.ibm.com>
---
Changes in V4:
 - Changes are rebased on master.

Changes in V3:
 - Change in the description.
 - Improves the error message as per review comment.

Changes in V2:
 - Separates it from patch 3/3 from V1.

 core/errorlog.c         | 30 +++++++++++++++++++++++++++---
 hw/fsp/fsp-elog-write.c |  1 +
 include/errorlog.h      |  2 ++
 3 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/core/errorlog.c b/core/errorlog.c
index 5648433..432e3c7 100644
--- a/core/errorlog.c
+++ b/core/errorlog.c
@@ -41,6 +41,7 @@ static uint32_t sapphire_elog_id = 0xB0000000;
 static struct pool elog_pool;
 bool elog_enabled;
 static struct lock elog_lock = LOCK_UNLOCKED;
+static struct lock elog_buf_ref_lock = LOCK_UNLOCKED;
 static bool elog_available = false;
 
 static LIST_HEAD(elog_write_to_host_pending);
@@ -54,6 +55,26 @@ static struct lock elog_write_to_host_lock = LOCK_UNLOCKED;
 /* Manipulate this only with write_lock held */
 static enum elog_head_state elog_write_to_host_head_state = ELOG_STATE_NONE;
 
+static void put_elog(struct errorlog *elog_buf)
+{
+	lock(&elog_buf_ref_lock);
+	if (!elog_buf->ref_count) {
+		prerror("put_elog has been called\n");
+		unlock(&elog_buf_ref_lock);
+		return;
+	}
+
+	elog_buf->ref_count--;
+	unlock(&elog_buf_ref_lock);
+}
+
+void get_elog(struct errorlog *elog_buf)
+{
+	lock(&elog_buf_ref_lock);
+	elog_buf->ref_count++;
+	unlock(&elog_buf_ref_lock);
+}
+
 static struct errorlog *get_write_buffer(int opal_event_severity)
 {
 	struct errorlog *buf;
@@ -123,12 +144,15 @@ void log_add_section(struct errorlog *buf, uint32_t tag)
 
 void opal_elog_complete(struct errorlog *buf, bool success)
 {
+	put_elog(buf);
 	if (!success)
 		printf("Unable to log error\n");
 
-	lock(&elog_lock);
-	pool_free_object(&elog_pool, buf);
-	unlock(&elog_lock);
+	if (!buf->ref_count) {
+		lock(&elog_lock);
+		pool_free_object(&elog_pool, buf);
+		unlock(&elog_lock);
+	}
 }
 
 void log_commit(struct errorlog *elog)
diff --git a/hw/fsp/fsp-elog-write.c b/hw/fsp/fsp-elog-write.c
index 199aed3..4bc8dd0 100644
--- a/hw/fsp/fsp-elog-write.c
+++ b/hw/fsp/fsp-elog-write.c
@@ -193,6 +193,7 @@ int elog_fsp_commit(struct errorlog *buf)
 {
 	int rc = OPAL_SUCCESS;
 
+	get_elog(buf);
 	/* Error needs to be committed, update the time out value */
 	buf->elog_timeout = get_elog_timeout();
 	if (buf->event_severity == OPAL_ERROR_PANIC) {
diff --git a/include/errorlog.h b/include/errorlog.h
index 8bddce2..fd95afa 100644
--- a/include/errorlog.h
+++ b/include/errorlog.h
@@ -137,6 +137,7 @@ struct __attribute__((__packed__)) errorlog {
 	uint32_t plid;
 	uint32_t log_size;
 	uint64_t elog_timeout;
+	uint32_t ref_count;
 
 	char user_data_dump[OPAL_LOG_MAX_DUMP];
 	struct list_node link;
@@ -372,6 +373,7 @@ void log_commit(struct errorlog *elog);
  * set to false. */
 void opal_elog_complete(struct errorlog *elog, bool success);
 void elog_append_write_to_host(struct errorlog *buf);
+void get_elog(struct errorlog *elog_buf);
 int elog_init(void);
 void opal_elog_init(void);
 void elog_set_head_state(bool opal_logs, enum elog_head_state state);
-- 
2.7.4



More information about the Skiboot mailing list