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:31:14 +1000
commitec366ad4e2e871096fa4c614ad7e89f5bb6f884f (patch)
tree8d554f725194b09e6a887d23dcb7e1f57a3f0308
parentd2ae07fd97bb9408456279cec799f72cb78680a6 (diff)
downloadskiboot-ec366ad4e2e871096fa4c614ad7e89f5bb6f884f.zip
skiboot-ec366ad4e2e871096fa4c614ad7e89f5bb6f884f.tar.gz
skiboot-ec366ad4e2e871096fa4c614ad7e89f5bb6f884f.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>
-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 a7897a8..d55c858 100644
--- a/hw/fsp/fsp-elog-read.c
+++ b/hw/fsp/fsp-elog-read.c
@@ -148,26 +148,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 5358823..80a0a39 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;
@@ -145,11 +152,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;
}
}
@@ -170,9 +177,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);
}
@@ -189,7 +194,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;
}
@@ -204,7 +209,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);
@@ -234,7 +239,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) {
@@ -264,7 +269,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 */