summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/ras.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 02:33:12 +0200
commita08a53ea4c97940fe83fea3eab27618ac0fb5ed1 (patch)
treea6d61d06dbf2929477e066d14eceff2ea7a5ac31 /arch/powerpc/platforms/pseries/ras.c
parentpowerpc: Correct emulated mtfsf instruction (diff)
downloadlinux-a08a53ea4c97940fe83fea3eab27618ac0fb5ed1.tar.xz
linux-a08a53ea4c97940fe83fea3eab27618ac0fb5ed1.zip
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/platforms/pseries/ras.c')
-rw-r--r--arch/powerpc/platforms/pseries/ras.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index 721c0586b284..9c5778e6ed4b 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -236,7 +236,8 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
rtas_elog = (struct rtas_error_log *)ras_log_buf;
- if ((status == 0) && (rtas_elog->severity >= RTAS_SEVERITY_ERROR_SYNC))
+ if (status == 0 &&
+ rtas_error_severity(rtas_elog) >= RTAS_SEVERITY_ERROR_SYNC)
fatal = 1;
else
fatal = 0;
@@ -300,13 +301,14 @@ static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs)
/* If it isn't an extended log we can use the per cpu 64bit buffer */
h = (struct rtas_error_log *)&savep[1];
- if (!h->extended) {
+ if (!rtas_error_extended(h)) {
memcpy(&__get_cpu_var(mce_data_buf), h, sizeof(__u64));
errhdr = (struct rtas_error_log *)&__get_cpu_var(mce_data_buf);
} else {
- int len;
+ int len, error_log_length;
- len = max_t(int, 8+h->extended_log_length, RTAS_ERROR_LOG_MAX);
+ error_log_length = 8 + rtas_error_extended_log_length(h);
+ len = max_t(int, error_log_length, RTAS_ERROR_LOG_MAX);
memset(global_mce_data_buf, 0, RTAS_ERROR_LOG_MAX);
memcpy(global_mce_data_buf, h, len);
errhdr = (struct rtas_error_log *)global_mce_data_buf;
@@ -350,23 +352,24 @@ int pSeries_system_reset_exception(struct pt_regs *regs)
static int recover_mce(struct pt_regs *regs, struct rtas_error_log *err)
{
int recovered = 0;
+ int disposition = rtas_error_disposition(err);
if (!(regs->msr & MSR_RI)) {
/* If MSR_RI isn't set, we cannot recover */
recovered = 0;
- } else if (err->disposition == RTAS_DISP_FULLY_RECOVERED) {
+ } else if (disposition == RTAS_DISP_FULLY_RECOVERED) {
/* Platform corrected itself */
recovered = 1;
- } else if (err->disposition == RTAS_DISP_LIMITED_RECOVERY) {
+ } else if (disposition == RTAS_DISP_LIMITED_RECOVERY) {
/* Platform corrected itself but could be degraded */
printk(KERN_ERR "MCE: limited recovery, system may "
"be degraded\n");
recovered = 1;
} else if (user_mode(regs) && !is_global_init(current) &&
- err->severity == RTAS_SEVERITY_ERROR_SYNC) {
+ rtas_error_severity(err) == RTAS_SEVERITY_ERROR_SYNC) {
/*
* If we received a synchronous error when in userspace