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

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


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

get_elog and put_elog routine to increment/decrement the reference count variable.
errorlog 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
errorlog 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 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 c34251b..ec2084b 100644
--- a/core/errorlog.c
+++ b/core/errorlog.c
@@ -39,9 +39,30 @@ static uint32_t sapphire_elog_id = 0xB0000000;
 /* Pool to allocate elog messages from */
 static struct pool elog_pool;
 static struct lock elog_lock = LOCK_UNLOCKED;
+static struct lock elog_buf_ref_lock = LOCK_UNLOCKED;
 
 static bool elog_available = false;
 
+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;
@@ -113,12 +134,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 6e307a4..309617f 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 37a0b0d..6891c6a 100644
--- a/include/errorlog.h
+++ b/include/errorlog.h
@@ -150,6 +150,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;
@@ -375,6 +376,7 @@ void elog_set_head_state(bool platform_log, enum elog_head_state old_state,
 		enum elog_head_state new_state);
 void opal_commit_elog_in_host(void);
 void elog_append_write_to_host(struct errorlog *buf);
+void get_elog(struct errorlog *elog_buf);
 int elog_init(void);
 
 #endif /* __ERRORLOG_H */
-- 
2.1.4



More information about the Skiboot mailing list