aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVasant Hegde <hegdevasant@linux.vnet.ibm.com>2016-07-02 21:03:39 +0530
committerStewart Smith <stewart@linux.vnet.ibm.com>2016-07-21 16:52:08 +1000
commit1c7d8755cf921eb392368bb32df4f952c9a6f139 (patch)
treef8e9969f8756e1d3c8815c778366e6eeb1142abd
parentdfb88e6d437fb6fbf6e688285be4963218cae8c6 (diff)
downloadskiboot-1c7d8755cf921eb392368bb32df4f952c9a6f139.zip
skiboot-1c7d8755cf921eb392368bb32df4f952c9a6f139.tar.gz
skiboot-1c7d8755cf921eb392368bb32df4f952c9a6f139.tar.bz2
FSP/ELOG: Fix OPAL generated elog event notification
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@linux.vnet.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com> (cherry picked from commit ec366ad4e2e871096fa4c614ad7e89f5bb6f884f) Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r--hw/fsp/fsp-elog-read.c27
-rw-r--r--hw/fsp/fsp-elog-write.c23
-rw-r--r--include/fsp-elog.h2
3 files changed, 34 insertions, 18 deletions
diff --git a/hw/fsp/fsp-elog-read.c b/hw/fsp/fsp-elog-read.c
index 8978a32..72f43f7 100644
--- a/hw/fsp/fsp-elog-read.c
+++ b/hw/fsp/fsp-elog-read.c
@@ -150,26 +150,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 cf915a2..5e07bcc 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;
@@ -139,11 +146,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;
}
}
@@ -164,9 +171,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);
}
@@ -183,7 +188,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;
}
@@ -198,7 +203,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);
@@ -228,7 +233,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) {
@@ -258,7 +263,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 */