lkml.org 
[lkml]   [2018]   [Apr]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 02/15] powerpc/powernv: Fix OPAL console driver OPAL_BUSY loops
    Date
    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>
    ---
    arch/powerpc/platforms/powernv/opal.c | 38 ++++++++++++++++-----------
    1 file changed, 23 insertions(+), 15 deletions(-)

    diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
    index e695b836fd49..6b621d47ac29 100644
    --- a/arch/powerpc/platforms/powernv/opal.c
    +++ b/arch/powerpc/platforms/powernv/opal.c
    @@ -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_console_write(vtermno, &olen, data);
    +
    + 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;
    - }
    +
    + 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;
    --
    2.17.0
    \
     
     \ /
      Last update: 2018-04-30 17:00    [W:4.515 / U:0.348 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site