[Skiboot] [PATCH] console: Completely flush output buffer before power down and reboot

Russell Currey ruscur at russell.cc
Fri Oct 23 16:15:26 AEDT 2015


Completely flush the output buffer of the console driver before
power down and reboot.  Implements the flushing function for uart
consoles, which includes the astbmc and rhesus platforms.

Adds a new function, flush(), to the con_ops struct that allows
each console driver to specify how their output buffers are flushed.

In the cec_power_down and cec_reboot functions, the flush function
of the driver is called if it exists.

This fixes an issue where some console output is sometimes lost before
power down or reboot in uart consoles. If this issue is also prevalent
in other console types then it can be fixed later by adding a .flush
to that driver's con_ops.

Signed-off-by: Russell Currey <ruscur at russell.cc>
---
 core/console.c    |  6 +++++
 core/platform.c   |  6 +++++
 hw/lpc-uart.c     | 71 ++++++++++++++++++++++++++++++++-----------------------
 include/console.h |  3 +++
 4 files changed, 56 insertions(+), 30 deletions(-)

diff --git a/core/console.c b/core/console.c
index df3ce3b..f2ae069 100644
--- a/core/console.c
+++ b/core/console.c
@@ -290,6 +290,12 @@ ssize_t read(int fd __unused, void *buf, size_t req_count)
 	return count;
 }
 
+void flush_driver_output_buffer(void)
+{
+	if (con_driver->flush != NULL)
+		con_driver->flush();
+}
+
 void set_console(struct con_ops *driver)
 {
 	con_driver = driver;
diff --git a/core/platform.c b/core/platform.c
index 12c4ec2..91b6222 100644
--- a/core/platform.c
+++ b/core/platform.c
@@ -37,6 +37,9 @@ static int64_t opal_cec_power_down(uint64_t request)
 {
 	printf("OPAL: Shutdown request type 0x%llx...\n", request);
 
+	/* Ensure output buffers are fully flushed */
+	flush_driver_output_buffer();
+
 	if (platform.cec_power_down)
 		return platform.cec_power_down(request);
 
@@ -48,6 +51,9 @@ static int64_t opal_cec_reboot(void)
 {
 	printf("OPAL: Reboot request...\n");
 
+	/* Ensure output buffers are fully flushed */
+	flush_driver_output_buffer();
+
 #ifdef ENABLE_FAST_RESET
 	/* Try a fast reset first */
 	fast_reset();
diff --git a/hw/lpc-uart.c b/hw/lpc-uart.c
index 5c5d942..5ae914c 100644
--- a/hw/lpc-uart.c
+++ b/hw/lpc-uart.c
@@ -129,36 +129,6 @@ static void uart_update_ier(void)
 	}
 }
 
-/*
- * Internal console driver (output only)
- */
-static size_t uart_con_write(const char *buf, size_t len)
-{
-	size_t written = 0;
-
-	/* If LPC bus is bad, we just swallow data */
-	if (!lpc_ok())
-		return written;
-
-	lock(&uart_lock);
-	while(written < len) {
-		if (tx_room == 0) {
-			uart_wait_tx_room();
-			if (tx_room == 0)
-				goto bail;
-		} else {
-			uart_write(REG_THR, buf[written++]);
-			tx_room--;
-		}
-	}
- bail:
-	unlock(&uart_lock);
-	return written;
-}
-
-static struct con_ops uart_con_driver = {
-	.write = uart_con_write
-};
 
 /*
  * OPAL console driver
@@ -376,6 +346,47 @@ static void uart_irq(uint32_t chip_id __unused, uint32_t irq_mask __unused)
 }
 
 /*
+ * Internal console driver (output only)
+ */
+static size_t uart_con_write(const char *buf, size_t len)
+{
+	size_t written = 0;
+
+	/* If LPC bus is bad, we just swallow data */
+	if (!lpc_ok())
+		return written;
+
+	lock(&uart_lock);
+	while(written < len) {
+		if (tx_room == 0) {
+			uart_wait_tx_room();
+			if (tx_room == 0)
+				goto bail;
+		} else {
+			uart_write(REG_THR, buf[written++]);
+			tx_room--;
+		}
+	}
+ bail:
+	unlock(&uart_lock);
+	return written;
+}
+
+/*
+ * Flush the entire buffer all at once
+ */
+static void uart_con_flush_all(void)
+{
+	while(out_buf_prod != out_buf_cons)
+		uart_flush_out();
+}
+
+static struct con_ops uart_con_driver = {
+	.write = uart_con_write,
+	.flush = uart_con_flush_all
+};
+
+/*
  * Common setup/inits
  */
 
diff --git a/include/console.h b/include/console.h
index e426adb..0dbbf39 100644
--- a/include/console.h
+++ b/include/console.h
@@ -51,6 +51,7 @@ struct con_ops {
 	size_t (*write)(const char *buf, size_t len);
 	size_t (*read)(char *buf, size_t len);
 	bool (*poll_read)(void);
+	void (*flush)(void);
 };
 
 extern struct lock con_lock;
@@ -61,6 +62,8 @@ extern bool flush_console(void);
 extern bool __flush_console(bool flush_to_drivers);
 extern void set_console(struct con_ops *driver);
 
+extern void flush_driver_output_buffer(void);
+
 extern int mambo_read(void);
 extern void mambo_write(const char *buf, size_t count);
 extern void enable_mambo_console(void);
-- 
2.6.2



More information about the Skiboot mailing list