1affddff6SRussell Currey /* 2affddff6SRussell Currey * kmsg dumper that ensures the OPAL console fully flushes panic messages 3affddff6SRussell Currey * 4affddff6SRussell Currey * Author: Russell Currey <ruscur@russell.cc> 5affddff6SRussell Currey * 6affddff6SRussell Currey * Copyright 2015 IBM Corporation. 7affddff6SRussell Currey * 8affddff6SRussell Currey * This program is free software; you can redistribute it and/or modify it 9affddff6SRussell Currey * under the terms of the GNU General Public License as published by the 10affddff6SRussell Currey * Free Software Foundation; either version 2 of the License, or (at your 11affddff6SRussell Currey * option) any later version. 12affddff6SRussell Currey */ 13affddff6SRussell Currey 14affddff6SRussell Currey #include <linux/kmsg_dump.h> 15affddff6SRussell Currey 16affddff6SRussell Currey #include <asm/opal.h> 17affddff6SRussell Currey #include <asm/opal-api.h> 18affddff6SRussell Currey 19affddff6SRussell Currey /* 20affddff6SRussell Currey * Console output is controlled by OPAL firmware. The kernel regularly calls 21affddff6SRussell Currey * OPAL_POLL_EVENTS, which flushes some console output. In a panic state, 22affddff6SRussell Currey * however, the kernel no longer calls OPAL_POLL_EVENTS and the panic message 23affddff6SRussell Currey * may not be completely printed. This function does not actually dump the 24affddff6SRussell Currey * message, it just ensures that OPAL completely flushes the console buffer. 25affddff6SRussell Currey */ 26affddff6SRussell Currey static void force_opal_console_flush(struct kmsg_dumper *dumper, 27affddff6SRussell Currey enum kmsg_dump_reason reason) 28affddff6SRussell Currey { 29affddff6SRussell Currey int i; 30affddff6SRussell Currey 31affddff6SRussell Currey /* 32affddff6SRussell Currey * Outside of a panic context the pollers will continue to run, 33affddff6SRussell Currey * so we don't need to do any special flushing. 34affddff6SRussell Currey */ 35affddff6SRussell Currey if (reason != KMSG_DUMP_PANIC) 36affddff6SRussell Currey return; 37affddff6SRussell Currey 38affddff6SRussell Currey if (opal_check_token(OPAL_CONSOLE_FLUSH)) { 39affddff6SRussell Currey opal_console_flush(); 40affddff6SRussell Currey } else { 41affddff6SRussell Currey /* 42affddff6SRussell Currey * If OPAL_CONSOLE_FLUSH is not implemented in the firmware, 43affddff6SRussell Currey * the console can still be flushed by calling the polling 44affddff6SRussell Currey * function enough times to flush the buffer. We don't know 45affddff6SRussell Currey * how much output still needs to be flushed, but we can be 46affddff6SRussell Currey * generous since the kernel is in panic and doesn't need 47affddff6SRussell Currey * to do much else. 48affddff6SRussell Currey */ 49affddff6SRussell Currey printk(KERN_NOTICE "opal: OPAL_CONSOLE_FLUSH missing.\n"); 50affddff6SRussell Currey for (i = 0; i < 1024; i++) { 51affddff6SRussell Currey opal_poll_events(NULL); 52affddff6SRussell Currey } 53affddff6SRussell Currey } 54affddff6SRussell Currey } 55affddff6SRussell Currey 56affddff6SRussell Currey static struct kmsg_dumper opal_kmsg_dumper = { 57affddff6SRussell Currey .dump = force_opal_console_flush 58affddff6SRussell Currey }; 59affddff6SRussell Currey 60affddff6SRussell Currey void __init opal_kmsg_init(void) 61affddff6SRussell Currey { 62affddff6SRussell Currey int rc; 63affddff6SRussell Currey 64affddff6SRussell Currey /* Add our dumper to the list */ 65affddff6SRussell Currey rc = kmsg_dump_register(&opal_kmsg_dumper); 66affddff6SRussell Currey if (rc != 0) 67affddff6SRussell Currey pr_err("opal: kmsg_dump_register failed; returned %d\n", rc); 68affddff6SRussell Currey } 69