powerpc/powernv: Fix OPAL console driver OPAL_BUSY loops

The OPAL console driver does not delay in case it gets OPAL_BUSY or
OPAL_BUSY_EVENT from firmware.

It can't yet be made to sleep because it is called under spinlock,
but it can be changed to the standard OPAL_BUSY loop form, and a
delay added to keep it from hitting the firmware too frequently.

Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
Nicholas Piggin 2018-05-01 00:55:45 +10:00 committed by Michael Ellerman
parent bd90284cc6
commit 36d2dabc87
1 changed files with 23 additions and 15 deletions

View File

@ -378,33 +378,41 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len)
/* We still try to handle partial completions, though they
* should no longer happen.
*/
rc = OPAL_BUSY;
while(total_len > 0 && (rc == OPAL_BUSY ||
rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) {
while (total_len > 0) {
olen = cpu_to_be64(total_len);
rc = OPAL_BUSY;
while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
rc = opal_console_write(vtermno, &olen, data);
if (rc == OPAL_BUSY_EVENT) {
mdelay(OPAL_BUSY_DELAY_MS);
opal_poll_events(NULL);
} else if (rc == OPAL_BUSY) {
mdelay(OPAL_BUSY_DELAY_MS);
}
}
len = be64_to_cpu(olen);
/* Closed or other error drop */
if (rc != OPAL_SUCCESS && rc != OPAL_BUSY &&
rc != OPAL_BUSY_EVENT) {
written += total_len;
if (rc != OPAL_SUCCESS) {
written += total_len; /* drop remaining chars */
break;
}
if (rc == OPAL_SUCCESS) {
total_len -= len;
data += len;
written += len;
}
/* This is a bit nasty but we need that for the console to
* flush when there aren't any interrupts. We will clean
* things a bit later to limit that to synchronous path
* such as the kernel console and xmon/udbg
*/
do
do {
opal_poll_events(&evt);
while(rc == OPAL_SUCCESS &&
(be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_OUTPUT));
} while (be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_OUTPUT);
}
spin_unlock_irqrestore(&opal_write_lock, flags);
return written;