Commit ac55528c authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: Move EPOW log buffer to BSS

From: Olof Johansson <olof@austin.ibm.com>

RTAS on IBM pSeries runs in real mode, so all pointers being passed in to
it need to be in low memory.  There's two places in the RAS code that
passes in pointers to items on the stack, which might end up being above
the limit.

Below patch resolves this by creating a buffer in BSS + a lock for
serialization.  There's no reason to worry about contention on the lock,
since rtas_call() also serializes on a single spinlock and this is an
infrequent code path in the first place.
parent 81c31b89
...@@ -110,6 +110,9 @@ static int __init init_ras_IRQ(void) ...@@ -110,6 +110,9 @@ static int __init init_ras_IRQ(void)
} }
__initcall(init_ras_IRQ); __initcall(init_ras_IRQ);
static struct rtas_error_log log_buf;
static spinlock_t log_lock = SPIN_LOCK_UNLOCKED;
/* /*
* Handle power subsystem events (EPOW). * Handle power subsystem events (EPOW).
* *
...@@ -124,11 +127,17 @@ ras_epow_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -124,11 +127,17 @@ ras_epow_interrupt(int irq, void *dev_id, struct pt_regs * regs)
unsigned int size = sizeof(log_entry); unsigned int size = sizeof(log_entry);
long status = 0xdeadbeef; long status = 0xdeadbeef;
spin_lock(&log_lock);
status = rtas_call(rtas_token("check-exception"), 6, 1, NULL, status = rtas_call(rtas_token("check-exception"), 6, 1, NULL,
0x500, irq, 0x500, irq,
RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS, RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS,
1, /* Time Critical */ 1, /* Time Critical */
__pa(&log_entry), size); __pa(&log_buf), size);
log_entry = log_buf;
spin_unlock(&log_lock);
udbg_printf("EPOW <0x%lx 0x%lx>\n", udbg_printf("EPOW <0x%lx 0x%lx>\n",
*((unsigned long *)&log_entry), status); *((unsigned long *)&log_entry), status);
...@@ -157,11 +166,17 @@ ras_error_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -157,11 +166,17 @@ ras_error_interrupt(int irq, void *dev_id, struct pt_regs * regs)
long status = 0xdeadbeef; long status = 0xdeadbeef;
int fatal; int fatal;
spin_lock(&log_lock);
status = rtas_call(rtas_token("check-exception"), 6, 1, NULL, status = rtas_call(rtas_token("check-exception"), 6, 1, NULL,
0x500, irq, 0x500, irq,
RTAS_INTERNAL_ERROR, RTAS_INTERNAL_ERROR,
1, /* Time Critical */ 1, /* Time Critical */
__pa(&log_entry), size); __pa(&log_buf), size);
log_entry = log_buf;
spin_unlock(&log_lock);
if ((status == 0) && (log_entry.severity >= SEVERITY_ERROR_SYNC)) if ((status == 0) && (log_entry.severity >= SEVERITY_ERROR_SYNC))
fatal = 1; fatal = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment