[Skiboot] [PATCH 3/3] opal/errorlog : Enables errorlog write to host on BMC systems
Mukesh Ojha
mukesh02 at linux.vnet.ibm.com
Wed Apr 6 21:47:46 AEST 2016
Adds the support of errorlog write to host by using the generic interface
of errorlog read/write framework. OPAL sents the errorlog messages to both
BMC and host kernel by passing the errorlog buffers.
Properly returning of buffers to the pool by introducing ref_count variable
in the errorlog structure, which is manipulated in 'get_elog' and
'put_elog' function. Makes put_elog a wrapper of opal_elog_complete
(static) and exported function. Call to 'opal_elog_complete' made on
ref_count of zero.
'opal_elog_init' initialises the memory and the callbacks require for
errorlog write to host framework.
Signed-off-by: Mukesh Ojha <mukesh02 at linux.vnet.ibm.com>
---
core/elog-host.c | 4 ++--
core/errorlog.c | 46 +++++++++++++++++++++++++++++++++++-----------
hw/fsp/fsp-elog-write.c | 9 +++++----
hw/ipmi/ipmi-sel.c | 25 ++++++++++++++++++-------
include/errorlog.h | 7 +++----
platforms/astbmc/common.c | 4 ++--
6 files changed, 65 insertions(+), 30 deletions(-)
diff --git a/core/elog-host.c b/core/elog-host.c
index c6ec51a..b104447 100644
--- a/core/elog-host.c
+++ b/core/elog-host.c
@@ -180,7 +180,7 @@ static int opal_elog_ack(uint64_t ack_id)
if (record->plid != ack_id)
continue;
list_del(&record->link);
- opal_elog_complete(record, true);
+ put_elog(record);
unlock(&elog_write_to_host_lock);
return rc;
}
@@ -197,7 +197,7 @@ static int opal_elog_ack(uint64_t ack_id)
if (record->plid != ack_id)
continue;
list_del(&record->link);
- opal_elog_complete(record, true);
+ put_elog(record);
unlock(&elog_write_to_host_lock);
return rc;
}
diff --git a/core/errorlog.c b/core/errorlog.c
index 7afd16c..af2853b 100644
--- a/core/errorlog.c
+++ b/core/errorlog.c
@@ -42,6 +42,40 @@ static struct pool elog_pool;
static struct lock elog_lock = LOCK_UNLOCKED;
static bool elog_available = false;
+static struct lock elog_buf_ref_lock = LOCK_UNLOCKED;
+
+static void opal_elog_complete(struct errorlog *buf)
+{
+ lock(&elog_lock);
+ pool_free_object(&elog_pool, buf);
+ unlock(&elog_lock);
+}
+
+void get_elog(struct errorlog *elog_buf)
+{
+ lock(&elog_buf_ref_lock);
+ elog_buf->ref_count++;
+ unlock(&elog_buf_ref_lock);
+}
+
+void put_elog(struct errorlog *elog_buf)
+{
+ lock(&elog_buf_ref_lock);
+ if (!elog_buf->ref_count) {
+ prerror(
+ "put_elog has been called multiple times on reference"
+ " count zero\n"
+ );
+ unlock(&elog_buf_ref_lock);
+ return;
+ }
+
+ elog_buf->ref_count--;
+ if (!elog_buf->ref_count)
+ opal_elog_complete(elog_buf);
+
+ unlock(&elog_buf_ref_lock);
+}
static struct errorlog *get_write_buffer(int opal_event_severity)
{
@@ -112,16 +146,6 @@ void log_add_section(struct errorlog *buf, uint32_t tag)
buf->user_section_count++;
}
-void opal_elog_complete(struct errorlog *buf, bool success)
-{
- if (!success)
- printf("Unable to log error\n");
-
- lock(&elog_lock);
- pool_free_object(&elog_pool, buf);
- unlock(&elog_lock);
-}
-
void log_commit(struct errorlog *elog)
{
int rc;
@@ -135,7 +159,7 @@ void log_commit(struct errorlog *elog)
prerror("ELOG: Platform commit error %d\n", rc);
return;
}
- opal_elog_complete(elog, false);
+ opal_elog_complete(elog);
}
void log_append_data(struct errorlog *buf, unsigned char *data, uint16_t size)
diff --git a/hw/fsp/fsp-elog-write.c b/hw/fsp/fsp-elog-write.c
index ee293f1..dced70d 100644
--- a/hw/fsp/fsp-elog-write.c
+++ b/hw/fsp/fsp-elog-write.c
@@ -66,7 +66,7 @@ static void remove_elog_head_entry(void)
if (head->plid == elog_plid_fsp_commit) {
entry = list_pop(&elog_write_to_fsp_pending,
struct errorlog, link);
- opal_elog_complete(entry, elog_write_retries < MAX_RETRIES);
+ put_elog(entry);
/* Reset the counter */
elog_plid_fsp_commit = -1;
}
@@ -161,7 +161,7 @@ static int opal_push_logs_sync_to_fsp(struct errorlog *buf)
prerror("ELOG: PLID: 0x%x Failed to create message for WRITE "
"to FSP\n", buf->plid);
unlock(&elog_panic_write_lock);
- opal_elog_complete(buf, false);
+ put_elog(buf);
return OPAL_INTERNAL_ERROR;
}
@@ -175,9 +175,9 @@ static int opal_push_logs_sync_to_fsp(struct errorlog *buf)
unlock(&elog_panic_write_lock);
if (rc != OPAL_SUCCESS)
- opal_elog_complete(buf, false);
+ put_elog(buf);
else
- opal_elog_complete(buf, true);
+ put_elog(buf);
return rc;
}
@@ -193,6 +193,7 @@ int elog_fsp_commit(struct errorlog *buf)
/* Error needs to be committed, update the time out value */
buf->elog_timeout = get_elog_timeout();
+ get_elog(buf);
if (buf->event_severity == OPAL_ERROR_PANIC) {
rc = opal_push_logs_sync_to_fsp(buf);
return rc;
diff --git a/hw/ipmi/ipmi-sel.c b/hw/ipmi/ipmi-sel.c
index 6bc386a..0950218 100644
--- a/hw/ipmi/ipmi-sel.c
+++ b/hw/ipmi/ipmi-sel.c
@@ -262,7 +262,7 @@ static void ipmi_elog_error(struct ipmi_msg *msg)
/* Retry due to SEL erase */
ipmi_queue_msg(msg);
else {
- opal_elog_complete(msg->user_data, false);
+ put_elog(msg->user_data);
ipmi_sel_free_msg(msg);
}
}
@@ -345,7 +345,7 @@ static void ipmi_elog_poll(struct ipmi_msg *msg)
* get here, but just in case we do we cancel
* sending the message. */
prerror("Invalid reservation id");
- opal_elog_complete(elog_buf, false);
+ put_elog(elog_buf);
ipmi_sel_free_msg(msg);
return;
}
@@ -371,7 +371,7 @@ static void ipmi_elog_poll(struct ipmi_msg *msg)
/* Log SEL event and free ipmi message */
ipmi_log_sel_event(msg, elog_buf->event_severity, record_id);
- opal_elog_complete(elog_buf, true);
+ put_elog(elog_buf);
return;
}
@@ -415,24 +415,34 @@ int ipmi_elog_commit(struct errorlog *elog_buf)
{
struct ipmi_msg *msg;
+ get_elog(elog_buf);
/* Only log events that needs attention */
if (elog_buf->event_severity < OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_REBOOT ||
elog_buf->elog_origin != ORG_SAPPHIRE) {
prlog(PR_INFO, "dropping non severe PEL event\n");
- opal_elog_complete(elog_buf, true);
+ put_elog(elog_buf);
return 0;
}
+ /* We take get_elog two times to make sure errorlog will be sent to
+ * both BMC and the host irrespective of either of them is complete
+ * or not, buffer will be return to the pool during the call of
+ * put_elog().
+ */
+ get_elog(elog_buf);
+
/* We pass a large request size in to mkmsg so that we have a
* large enough allocation to reuse the message to pass the
- * PEL data via a series of partial add commands. */
+ * PEL data via a series of partial add commands.
+ */
msg = ipmi_sel_alloc_msg(elog_buf);
if (!msg) {
- opal_elog_complete(elog_buf, false);
+ put_elog(elog_buf);
+ elog_append_write_to_host(elog_buf);
return OPAL_RESOURCE;
}
- msg->error = ipmi_elog_error;
+ msg->error = ipmi_elog_error;
msg->req_size = 0;
if (elog_buf->event_severity == OPAL_ERROR_PANIC)
@@ -440,6 +450,7 @@ int ipmi_elog_commit(struct errorlog *elog_buf)
else
ipmi_queue_msg(msg);
+ elog_append_write_to_host(elog_buf);
return 0;
}
diff --git a/include/errorlog.h b/include/errorlog.h
index d58eb5e..d7c25c2 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;
@@ -349,10 +350,8 @@ void log_append_msg(struct errorlog *buf,
const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
void log_commit(struct errorlog *elog);
-/* Called by the backend after an error has been logged by the
- * backend. If the error could not be logged successfully success is
- * set to false. */
-void opal_elog_complete(struct errorlog *elog, bool success);
+void get_elog(struct errorlog *elog_buf);
+void put_elog(struct errorlog *elog_buf);
void opal_elog_init(void);
void opal_commit_elog_in_host(void);
diff --git a/platforms/astbmc/common.c b/platforms/astbmc/common.c
index 1ed7d42..4dd5401 100644
--- a/platforms/astbmc/common.c
+++ b/platforms/astbmc/common.c
@@ -115,8 +115,8 @@ void astbmc_init(void)
/* Register the BT interface with the IPMI layer */
bt_init();
- /* Initialize elog */
- elog_init();
+ /*Initialize the errorlog framework*/
+ opal_elog_init();
ipmi_sel_init();
ipmi_wdt_init();
ipmi_rtc_init();
--
2.1.4
More information about the Skiboot
mailing list