summaryrefslogtreecommitdiff
path: root/arch/powerpc/kernel/rtas.c
diff options
context:
space:
mode:
authorGreg Kurz <gkurz@linux.vnet.ibm.com>2014-04-04 09:35:13 +0200
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-04-07 10:33:12 +1000
commita08a53ea4c97940fe83fea3eab27618ac0fb5ed1 (patch)
treea6d61d06dbf2929477e066d14eceff2ea7a5ac31 /arch/powerpc/kernel/rtas.c
parentc59c015b6aa5bc18d01c8e482149086cafd7332a (diff)
powerpc/le: Enable RTAS events support
The current kernel code assumes big endian and parses RTAS events all wrong. The most visible effect is that we cannot honor EPOW events, meaning, for example, we cannot shut down a guest properly from the hypervisor. This new patch is largely inspired by Nathan's work: we get rid of all the bit fields in the RTAS event structures (even the unused ones, for consistency). We also introduce endian safe accessors for the fields used by the kernel (trivial rtas_error_type() accessor added for consistency). Cc: Nathan Fontenot <nfont@linux.vnet.ibm.com> Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/rtas.c')
-rw-r--r--arch/powerpc/kernel/rtas.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index f386296ff378..8cd5ed049b5d 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -993,21 +993,24 @@ struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log,
(struct rtas_ext_event_log_v6 *)log->buffer;
struct pseries_errorlog *sect;
unsigned char *p, *log_end;
+ uint32_t ext_log_length = rtas_error_extended_log_length(log);
+ uint8_t log_format = rtas_ext_event_log_format(ext_log);
+ uint32_t company_id = rtas_ext_event_company_id(ext_log);
/* Check that we understand the format */
- if (log->extended_log_length < sizeof(struct rtas_ext_event_log_v6) ||
- ext_log->log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG ||
- ext_log->company_id != RTAS_V6EXT_COMPANY_ID_IBM)
+ if (ext_log_length < sizeof(struct rtas_ext_event_log_v6) ||
+ log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG ||
+ company_id != RTAS_V6EXT_COMPANY_ID_IBM)
return NULL;
- log_end = log->buffer + log->extended_log_length;
+ log_end = log->buffer + ext_log_length;
p = ext_log->vendor_log;
while (p < log_end) {
sect = (struct pseries_errorlog *)p;
- if (sect->id == section_id)
+ if (pseries_errorlog_id(sect) == section_id)
return sect;
- p += sect->length;
+ p += pseries_errorlog_length(sect);
}
return NULL;