[Skiboot] [PATCH V5 08/10] Introduces get and put elog routine and reference count field in elog structure

Mukesh Ojha mukesh02 at linux.vnet.ibm.com
Sun Aug 21 18:47:26 AEST 2016


Our aim is to send the error log to both BMC and PowerNV host. To meet this
purpose we can have a way where we can keep a separate buffer for BMC and
PowerNV host. But with this way we have a overhead of again memory creation,
copy and freeing it buffer separately.

So, better to use existing allocation and deallocation from the pool of
error log object technique with the introduction of reference count
variable in the error log structure. Reference count variable is to
track the number of users using the error log buffer.

The reason of introducing reference count variable is while we send
error log buffer to both BMC and PowerNV host, one of them does not
free the buffer once they are done sending, while the other is using
it.

'get_elog' and 'put_elog' routine to increment/decrement the reference count
variable. Error log buffer object is returned to the pool on zero value of
reference count.

Signed-off-by: Mukesh Ojha <mukesh02 at linux.vnet.ibm.com>
---
Changes in V5:
 - Added more description

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 |  3 +++
 include/errorlog.h      |  3 +++
 3 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/core/errorlog.c b/core/errorlog.c
index da01b58..30cfaa7 100644
--- a/core/errorlog.c
+++ b/core/errorlog.c
@@ -40,6 +40,7 @@ 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 bool elog_enabled = false;
@@ -55,6 +56,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 with ref_count 0\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;
@@ -127,12 +148,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 71969a7..d146fe0 100644
--- a/hw/fsp/fsp-elog-write.c
+++ b/hw/fsp/fsp-elog-write.c
@@ -195,6 +195,9 @@ int elog_fsp_commit(struct errorlog *buf)
 {
 	int rc = OPAL_SUCCESS;
 
+	/* Increments the number of users using error log buffer */
+	get_elog(buf);
+
 	/* Error needs to be committed, update the time out value */
 	buf->elog_timeout = get_elog_timeout();
 
diff --git a/include/errorlog.h b/include/errorlog.h
index 2d5c3b0..9b882ac 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;
@@ -376,4 +377,6 @@ void opal_elog_init(void);
 int elog_init(void);
 void elog_append_write_to_host(struct errorlog *buf);
 void elog_set_head_state(bool opal_logs, enum elog_head_state state);
+
+void get_elog(struct errorlog *elog_buf);
 #endif /* __ERRORLOG_H */
-- 
2.7.4



More information about the Skiboot mailing list