linux/arch/powerpc/platforms/powernv/opal-kmsg.c
Russell Currey c88c5d4373 powerpc/powernv: Fix OPAL_CONSOLE_FLUSH prototype and usages
The recently added OPAL API call, OPAL_CONSOLE_FLUSH, originally took no
parameters and returned nothing.  The call was updated to accept the
terminal number to flush, and returned various values depending on the
state of the output buffer.

The prototype has been updated and its usage in the OPAL kmsg dumper has
been modified to support its new behaviour as an incremental flush.

Signed-off-by: Russell Currey <ruscur@russell.cc>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
2016-01-13 12:35:17 +11:00

76 lines
2.2 KiB
C

/*
* kmsg dumper that ensures the OPAL console fully flushes panic messages
*
* Author: Russell Currey <ruscur@russell.cc>
*
* Copyright 2015 IBM Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/kmsg_dump.h>
#include <asm/opal.h>
#include <asm/opal-api.h>
/*
* Console output is controlled by OPAL firmware. The kernel regularly calls
* OPAL_POLL_EVENTS, which flushes some console output. In a panic state,
* however, the kernel no longer calls OPAL_POLL_EVENTS and the panic message
* may not be completely printed. This function does not actually dump the
* message, it just ensures that OPAL completely flushes the console buffer.
*/
static void force_opal_console_flush(struct kmsg_dumper *dumper,
enum kmsg_dump_reason reason)
{
int i;
int64_t ret;
/*
* Outside of a panic context the pollers will continue to run,
* so we don't need to do any special flushing.
*/
if (reason != KMSG_DUMP_PANIC)
return;
if (opal_check_token(OPAL_CONSOLE_FLUSH)) {
ret = opal_console_flush(0);
if (ret == OPAL_UNSUPPORTED || ret == OPAL_PARAMETER)
return;
/* Incrementally flush until there's nothing left */
while (opal_console_flush(0) != OPAL_SUCCESS);
} else {
/*
* If OPAL_CONSOLE_FLUSH is not implemented in the firmware,
* the console can still be flushed by calling the polling
* function enough times to flush the buffer. We don't know
* how much output still needs to be flushed, but we can be
* generous since the kernel is in panic and doesn't need
* to do much else.
*/
printk(KERN_NOTICE "opal: OPAL_CONSOLE_FLUSH missing.\n");
for (i = 0; i < 1024; i++) {
opal_poll_events(NULL);
}
}
}
static struct kmsg_dumper opal_kmsg_dumper = {
.dump = force_opal_console_flush
};
void __init opal_kmsg_init(void)
{
int rc;
/* Add our dumper to the list */
rc = kmsg_dump_register(&opal_kmsg_dumper);
if (rc != 0)
pr_err("opal: kmsg_dump_register failed; returned %d\n", rc);
}