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