[Skiboot] [PATCH 1/4] ELOG: Disable event notification during kexec
Vasant Hegde
hegdevasant at linux.vnet.ibm.com
Fri Jun 24 20:39:10 AEST 2016
ELOG enables event notification once new log is available. And this
will be disabled after host completes reading logs (it has to complete
both fsp_opal_elog_info and fsp_opal_elog_read).
In some corner cases like kexec, host may endup reading same ELOG id twice
(calling fsp_opal_elog_info twice because of resend request). Host finds it
as duplicate and it will not read actual log (fsp_opal_elog_read()). In such
situations we fails to disable event notification :-(
Scenario :
OPAL Host
-------------------------------------
OPAL_EVENT_ELOG_AVAIL --> kexec
OPAL_EVENT_ELOG_AVAIL --> elog client registered
<-- read ELOG (id=x)
<-- resend elog (opal_resend_pending_logs())
resend all ELOG --> read ELOG (id=x) -- Duplicate ELOG !
bhoom!!
kernel call trace:
------------------
[ 28.055923] CPU: 10 PID: 20 Comm: irq/29-opal-elo Not tainted 4.4.0-24-generic #43-Ubuntu
[ 28.056012] task: c0000000ef982a20 ti: c0000000efa38000 task.ti: c0000000efa38000
[ 28.056100] NIP: c000000008010a24 LR: c000000008010a24 CTR: 0000000030033758
[ 28.056188] REGS: c0000000efa3b9c0 TRAP: 0901 Not tainted (4.4.0-24-generic)
[ 28.056274] MSR: 9000000100009033 <SF,HV,EE,ME,IR,DR,RI,LE> CR: 22000844 XER: 20000000
[ 28.056499] CFAR: c000000008009958 SOFTE: 1
GPR00: c000000008131e8c c0000000efa3bc40 c0000000095b4200 0000000000000900
GPR04: c0000000094a63c8 0000000000000001 9000000100009033 0000000000000062
GPR08: 0000000000000000 0000000000000000 c0000000ef960400 9000000100001003
GPR12: c00000000806de48 c00000000fb45f00
[ 28.057042] NIP [c000000008010a24] arch_local_irq_restore+0x74/0x90
[ 28.057117] LR [c000000008010a24] arch_local_irq_restore+0x74/0x90
[ 28.057189] Call Trace:
[ 28.057221] [c0000000efa3bc40] [c0000000f108a980] 0xc0000000f108a980 (unreliable)
[ 28.057326] [c0000000efa3bc60] [c000000008131e8c] irq_finalize_oneshot.part.2+0xbc/0x250
[ 28.057429] [c0000000efa3bcb0] [c000000008132170] irq_thread_fn+0x80/0xa0
[ 28.057519] [c0000000efa3bcf0] [c00000000813263c] irq_thread+0x1ac/0x280
[ 28.057609] [c0000000efa3bd80] [c0000000080e61e0] kthread+0x110/0x130
[ 28.057698] [c0000000efa3be30] [c000000008009538] ret_from_kernel_thread+0x5c/0xa4
[ 28.057799] Instruction dump:
[ 28.057844] 994d02ca 2fa30000 409e0024 e92d0020 61298000 7d210164 38210020 e8010010
[ 28.057995] 7c0803a6 4e800020 60420000 4bff17ad <60000000> 4bffffe4 60420000 e92d0020
This patch adds kexec notifier client. It will disable event notification
during kexec. We will enable ELOG once host is ready to receive events
(fsp_opal_resend_pending_logs()).
It will fix above issue. I will add follow up patch to improve event state.
Signed-off-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
---
hw/fsp/fsp-elog-read.c | 39 +++++++++++++++++++++++++++------------
1 file changed, 27 insertions(+), 12 deletions(-)
diff --git a/hw/fsp/fsp-elog-read.c b/hw/fsp/fsp-elog-read.c
index 16667ae..c63198f 100644
--- a/hw/fsp/fsp-elog-read.c
+++ b/hw/fsp/fsp-elog-read.c
@@ -88,6 +88,8 @@ static uint32_t elog_read_retries; /* bad response status count */
/* Initialize the state of the log */
static enum elog_head_state elog_read_from_fsp_head_state = ELOG_STATE_NONE;
+static bool elog_enabled;
+
/* Need forward declaration because of Circular dependency */
static void fsp_elog_queue_fetch(void);
@@ -130,6 +132,9 @@ static int64_t fsp_send_elog_ack(uint32_t log_id)
/* retrive error log from FSP with TCE for the data transfer */
static void fsp_elog_check_and_fetch_head(void)
{
+ if (!elog_enabled)
+ return;
+
lock(&elog_read_lock);
if (elog_read_from_fsp_head_state != ELOG_STATE_NONE ||
@@ -152,6 +157,9 @@ static void fsp_elog_set_head_state(enum elog_head_state state)
elog_read_from_fsp_head_state = state;
+ if (!elog_enabled)
+ return;
+
if (state == ELOG_STATE_FETCHED_DATA &&
old_state != ELOG_STATE_FETCHED_DATA)
opal_update_pending_evt(OPAL_EVENT_ERROR_LOG_AVAIL,
@@ -354,7 +362,7 @@ static void elog_reject_head(void)
{
if (elog_read_from_fsp_head_state == ELOG_STATE_FETCHING)
fsp_elog_set_head_state(ELOG_STATE_REJECTED);
- if (elog_read_from_fsp_head_state == ELOG_STATE_FETCHED_DATA)
+ else
fsp_elog_set_head_state(ELOG_STATE_NONE);
}
@@ -403,6 +411,8 @@ static void fsp_opal_resend_pending_logs(void)
opal_resend_pending_logs();
lock(&elog_read_lock);
+ elog_enabled = true;
+
/*
* If processed list is not empty add all record from
* processed list to pending list at head of the list
@@ -414,23 +424,23 @@ static void fsp_opal_resend_pending_logs(void)
list_add(&elog_read_pending, &entry->link);
}
- /*
- * If the current fetched or fetching log doesn't match our
- * new pending list head, then reject it
- */
- if (!list_empty(&elog_read_pending)) {
- entry = list_top(&elog_read_pending,
- struct fsp_log_entry, link);
- if (entry->log_id != elog_head_id)
- elog_reject_head();
- }
-
unlock(&elog_read_lock);
/* Read error log from FSP if needed */
fsp_elog_check_and_fetch_head();
}
+/* Disable ELOG event flag until host is ready to receive event */
+static bool opal_kexec_elog_notify(void *data __unused)
+{
+ lock(&elog_read_lock);
+ elog_reject_head();
+ elog_enabled = false;
+ unlock(&elog_read_lock);
+
+ return true;
+}
+
/* fsp elog notify function */
static bool fsp_elog_msg(uint32_t cmd_sub_mod, struct fsp_msg *msg)
{
@@ -552,9 +562,14 @@ void fsp_elog_read_init(void)
if (val != 0)
return;
+ elog_enabled = true;
+
/* register Eror log Class D2 */
fsp_register_client(&fsp_get_elog_notify, FSP_MCLASS_ERR_LOG);
+ /* Register for sync on host reboot call */
+ opal_add_host_sync_notifier(opal_kexec_elog_notify, NULL);
+
/* register opal Interface */
opal_register(OPAL_ELOG_READ, fsp_opal_elog_read, 3);
opal_register(OPAL_ELOG_ACK, fsp_opal_elog_ack, 1);
More information about the Skiboot
mailing list