All of lore.kernel.org
 help / color / mirror / Atom feed
From: Nicholas Piggin <npiggin@gmail.com>
To: linuxppc-dev@lists.ozlabs.org
Cc: Nicholas Piggin <npiggin@gmail.com>,
	Benjamin Herrenschmidt <benh@kernel.crashing.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Jiri Slaby <jslaby@suse.com>,
	linux-kernel@vger.kernel.org
Subject: [PATCH 15/15] powerpc/powernv: provide a console flush operation for opal hvc driver
Date: Tue,  1 May 2018 00:55:58 +1000	[thread overview]
Message-ID: <20180430145558.4308-16-npiggin@gmail.com> (raw)
In-Reply-To: <20180430145558.4308-1-npiggin@gmail.com>

Provide the flush hv_op for the opal hvc driver. This will flush the
firmware console buffers without spinning with interrupts disabled.

Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: linuxppc-dev@lists.ozlabs.org
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/include/asm/opal.h       |  1 +
 arch/powerpc/platforms/powernv/opal.c | 83 +++++++++++++++++----------
 drivers/tty/hvc/hvc_opal.c            |  2 +
 3 files changed, 55 insertions(+), 31 deletions(-)

diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 5d7072411561..a426d2caaf9f 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -304,6 +304,7 @@ extern void opal_configure_cores(void);
 extern int opal_get_chars(uint32_t vtermno, char *buf, int count);
 extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
 extern int opal_put_chars_atomic(uint32_t vtermno, const char *buf, int total_len);
+extern int opal_flush_chars(uint32_t vtermno, bool wait);
 extern int opal_flush_console(uint32_t vtermno);
 
 extern void hvc_opal_init_early(void);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index bcdb90ada938..048bc09afc83 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -370,12 +370,8 @@ static int __opal_put_chars(uint32_t vtermno, const char *data, int total_len, b
 	olen = cpu_to_be64(total_len);
 	rc = opal_console_write(vtermno, &olen, data);
 	if (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
-		if (rc == OPAL_BUSY_EVENT) {
-			mdelay(OPAL_BUSY_DELAY_MS);
+		if (rc == OPAL_BUSY_EVENT)
 			opal_poll_events(NULL);
-		} else if (rc == OPAL_BUSY_EVENT) {
-			mdelay(OPAL_BUSY_DELAY_MS);
-		}
 		written = -EAGAIN;
 		goto out;
 	}
@@ -401,15 +397,6 @@ static int __opal_put_chars(uint32_t vtermno, const char *data, int total_len, b
 	if (atomic)
 		spin_unlock_irqrestore(&opal_write_lock, flags);
 
-	/* In the -EAGAIN case, callers loop, so we have to flush the console
-	 * here in case they have interrupts off (and we don't want to wait
-	 * for async flushing if we can make immediate progress here). If
-	 * necessary the API could be made entirely non-flushing if the
-	 * callers had a ->flush API to use.
-	 */
-	if (written == -EAGAIN)
-		opal_flush_console(vtermno);
-
 	return written;
 }
 
@@ -429,40 +416,74 @@ int opal_put_chars_atomic(uint32_t vtermno, const char *data, int total_len)
 	return __opal_put_chars(vtermno, data, total_len, true);
 }
 
-int opal_flush_console(uint32_t vtermno)
+static s64 __opal_flush_console(uint32_t vtermno)
 {
 	s64 rc;
 
 	if (!opal_check_token(OPAL_CONSOLE_FLUSH)) {
 		__be64 evt;
 
-		WARN_ONCE(1, "opal: OPAL_CONSOLE_FLUSH missing.\n");
 		/*
 		 * If OPAL_CONSOLE_FLUSH is not implemented in the firmware,
 		 * the console can still be flushed by calling the polling
 		 * function while it has OPAL_EVENT_CONSOLE_OUTPUT events.
 		 */
-		do {
-			opal_poll_events(&evt);
-		} while (be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_OUTPUT);
+		WARN_ONCE(1, "opal: OPAL_CONSOLE_FLUSH missing.\n");
+
+		opal_poll_events(&evt);
+		if (!(be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_OUTPUT))
+			return OPAL_SUCCESS;
+		return OPAL_BUSY;
 
-		return OPAL_SUCCESS;
+	} else {
+		rc = opal_console_flush(vtermno);
+		if (rc == OPAL_BUSY_EVENT) {
+			opal_poll_events(NULL);
+			rc = OPAL_BUSY;
+		}
+		return rc;
 	}
 
-	do  {
-		rc = OPAL_BUSY;
-		while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
-			rc = opal_console_flush(vtermno);
-			if (rc == OPAL_BUSY_EVENT) {
-				mdelay(OPAL_BUSY_DELAY_MS);
-				opal_poll_events(NULL);
-			} else if (rc == OPAL_BUSY) {
-				mdelay(OPAL_BUSY_DELAY_MS);
+}
+
+/*
+ * opal_flush_console spins until the console is flushed
+ */
+int opal_flush_console(uint32_t vtermno)
+{
+	for (;;) {
+		s64 rc = __opal_flush_console(vtermno);
+
+		if (rc == OPAL_BUSY || rc == OPAL_PARTIAL) {
+			mdelay(1);
+			continue;
+		}
+
+		return opal_error_code(rc);
+	}
+}
+
+/*
+ * opal_flush_chars is an hvc interface that sleeps until the console is
+ * flushed if wait, otherwise it will return -EBUSY if the console has data,
+ * -EAGAIN if it has data and some of it was flushed.
+ */
+int opal_flush_chars(uint32_t vtermno, bool wait)
+{
+	for (;;) {
+		s64 rc = __opal_flush_console(vtermno);
+
+		if (rc == OPAL_BUSY || rc == OPAL_PARTIAL) {
+			if (wait) {
+				msleep(OPAL_BUSY_DELAY_MS);
+				continue;
 			}
+			if (rc == OPAL_PARTIAL)
+				return -EAGAIN;
 		}
-	} while (rc == OPAL_PARTIAL); /* More to flush */
 
-	return opal_error_code(rc);
+		return opal_error_code(rc);
+	}
 }
 
 static int opal_recover_mce(struct pt_regs *regs,
diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c
index 786e76a1e06d..fd306033f8d4 100644
--- a/drivers/tty/hvc/hvc_opal.c
+++ b/drivers/tty/hvc/hvc_opal.c
@@ -52,6 +52,7 @@ static u32 hvc_opal_boot_termno;
 static const struct hv_ops hvc_opal_raw_ops = {
 	.get_chars = opal_get_chars,
 	.put_chars = opal_put_chars,
+	.flush = opal_flush_chars,
 	.notifier_add = notifier_add_irq,
 	.notifier_del = notifier_del_irq,
 	.notifier_hangup = notifier_hangup_irq,
@@ -141,6 +142,7 @@ static int hvc_opal_hvsi_tiocmset(struct hvc_struct *hp, unsigned int set,
 static const struct hv_ops hvc_opal_hvsi_ops = {
 	.get_chars = hvc_opal_hvsi_get_chars,
 	.put_chars = hvc_opal_hvsi_put_chars,
+	.flush = opal_flush_chars,
 	.notifier_add = hvc_opal_hvsi_open,
 	.notifier_del = hvc_opal_hvsi_close,
 	.notifier_hangup = hvc_opal_hvsi_hangup,
-- 
2.17.0

  parent reply	other threads:[~2018-04-30 14:57 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-04-30 14:55 [PATCH 00/15] hvc and powerpc opal console latency reduction Nicholas Piggin
2018-04-30 14:55 ` [PATCH 01/15] powerpc/powernv: opal_put_chars partial write fix Nicholas Piggin
2018-07-24 13:59   ` [01/15] " Michael Ellerman
2018-04-30 14:55 ` [PATCH 02/15] powerpc/powernv: Fix OPAL console driver OPAL_BUSY loops Nicholas Piggin
2018-04-30 14:55 ` [PATCH 03/15] powerpc/powernv: opal-kmsg standardise OPAL_BUSY handling Nicholas Piggin
2018-04-30 14:55 ` [PATCH 04/15] powerpc/powernv: opal-kmsg use flush fallback from console code Nicholas Piggin
2018-05-04  5:16   ` Michael Ellerman
2018-05-04  5:37     ` Nicholas Piggin
2018-05-07 10:36       ` Michael Ellerman
2018-05-08  3:40         ` Nicholas Piggin
2018-04-30 14:55 ` [PATCH 05/15] powerpc/powernv: Implement and use opal_flush_console Nicholas Piggin
2018-04-30 14:55 ` [PATCH 06/15] powerpc/powernv: Remove OPALv1 support from opal console driver Nicholas Piggin
2018-04-30 14:55 ` [PATCH 07/15] powerpc/powernv: move opal console flushing to udbg Nicholas Piggin
2018-04-30 14:55 ` [PATCH 08/15] powerpc/powernv: implement opal_put_chars_atomic Nicholas Piggin
2018-05-01  9:48   ` Benjamin Herrenschmidt
2018-05-01 10:37     ` Nicholas Piggin
2018-05-07 10:35       ` Michael Ellerman
2018-05-08  3:36         ` Nicholas Piggin
2018-04-30 14:55 ` [PATCH 09/15] tty: hvc: remove unexplained "just in case" spin delay Nicholas Piggin
2018-04-30 14:55 ` [PATCH 10/15] tty: hvc: use mutex instead of spinlock for hvc_structs lock Nicholas Piggin
2018-08-13 11:22   ` [10/15] " Michael Ellerman
2018-04-30 14:55 ` [PATCH 11/15] tty: hvc: hvc_poll break hv read loop Nicholas Piggin
2018-08-13 11:23   ` [11/15] " Michael Ellerman
2018-04-30 14:55 ` [PATCH 12/15] tty: hvc: hvc_poll may sleep Nicholas Piggin
2018-08-13 11:23   ` [12/15] " Michael Ellerman
2018-04-30 14:55 ` [PATCH 13/15] tty: hvc: hvc_write " Nicholas Piggin
2018-08-13 11:23   ` [13/15] " Michael Ellerman
2018-04-30 14:55 ` [PATCH 14/15] tty: hvc: introduce the hv_ops.flush operation for hvc drivers Nicholas Piggin
2018-08-13 11:23   ` [14/15] " Michael Ellerman
2018-04-30 14:55 ` Nicholas Piggin [this message]
2018-08-21 10:35   ` [15/15] powerpc/powernv: provide a console flush operation for opal hvc driver Michael Ellerman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180430145558.4308-16-npiggin@gmail.com \
    --to=npiggin@gmail.com \
    --cc=benh@kernel.crashing.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=jslaby@suse.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.