diff options
author | Russell Currey <ruscur@russell.cc> | 2015-12-18 17:15:36 +1100 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2016-01-12 12:13:32 +1100 |
commit | f2efc652cbad6b32e1f0295aac819f6062777e31 (patch) | |
tree | ded31817c9ce70d1fb454134a45ffdbb13cb97b2 /hw/lpc-uart.c | |
parent | d4b142823e28deed097cf79b25d8d1e60b6f4e67 (diff) | |
download | skiboot-f2efc652cbad6b32e1f0295aac819f6062777e31.zip skiboot-f2efc652cbad6b32e1f0295aac819f6062777e31.tar.gz skiboot-f2efc652cbad6b32e1f0295aac819f6062777e31.tar.bz2 |
Add OPAL_CONSOLE_FLUSH to the OPAL API
uart consoles only flush output when polled. The Linux kernel calls
these pollers frequently, except when in a panic state. As such, panic
messages are not fully printed unless the system is configured to reboot
after panic.
This patch adds a new call to the OPAL API to flush the buffer. If the
system has a uart console (i.e. BMC machines), it will incrementally
flush the buffer, returning if there is more to be flushed or not. If
the system has a different console, the function will have no effect.
This will allow the Linux kernel to ensure that panic message have been
fully printed out.
The existing synchronous flushing mechanism used in OPAL's shutdown and
reboot routines has been refactored into a helper that repeatedly calls
the new partial flush function.
Signed-off-by: Russell Currey <ruscur@russell.cc>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/lpc-uart.c')
-rw-r--r-- | hw/lpc-uart.c | 30 |
1 files changed, 16 insertions, 14 deletions
diff --git a/hw/lpc-uart.c b/hw/lpc-uart.c index e856563..2a95da5 100644 --- a/hw/lpc-uart.c +++ b/hw/lpc-uart.c @@ -156,11 +156,11 @@ static size_t uart_con_write(const char *buf, size_t len) return written; } -static void uart_con_flush_all(void); +static int64_t uart_con_flush(void); static struct con_ops uart_con_driver = { .write = uart_con_write, - .flush = uart_con_flush_all + .flush = uart_con_flush }; /* @@ -193,9 +193,11 @@ static uint8_t *out_buf; static uint32_t out_buf_prod; static uint32_t out_buf_cons; -static void uart_flush_out(void) +/* Asynchronous flush */ +static int64_t uart_con_flush(void) { bool tx_was_full = tx_full; + uint32_t out_buf_cons_initial = out_buf_cons; while(out_buf_prod != out_buf_cons) { if (tx_room == 0) { @@ -220,6 +222,15 @@ static void uart_flush_out(void) } if (tx_full != tx_was_full) uart_update_ier(); + if (out_buf_prod != out_buf_cons) { + /* Return busy if nothing was flushed this call */ + if (out_buf_cons == out_buf_cons_initial) + return OPAL_BUSY; + /* Return partial if there's more to flush */ + return OPAL_PARTIAL; + } + + return OPAL_SUCCESS; } static uint32_t uart_tx_buf_space(void) @@ -246,7 +257,7 @@ static int64_t uart_opal_write(int64_t term_number, int64_t *length, } /* Flush out buffer again */ - uart_flush_out(); + uart_con_flush(); unlock(&uart_lock); @@ -357,7 +368,7 @@ static void __uart_do_poll(u8 trace_ctx) lock(&uart_lock); uart_read_to_buffer(); - uart_flush_out(); + uart_con_flush(); uart_trace(trace_ctx, 0, tx_full, in_count); unlock(&uart_lock); @@ -379,15 +390,6 @@ static void uart_irq(uint32_t chip_id __unused, uint32_t irq_mask __unused) } /* - * Flush the entire buffer all at once - */ -static void uart_con_flush_all(void) -{ - while(out_buf_prod != out_buf_cons) - uart_flush_out(); -} - -/* * Common setup/inits */ |