diff options
author | Vasant Hegde <hegdevasant@linux.vnet.ibm.com> | 2017-10-10 15:07:47 +0530 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-10-11 19:30:03 +1100 |
commit | 6557a728385c3fbcef297d2c61c7d93bc539f8bb (patch) | |
tree | 1403639d9e0384d9433f7b52ce88b671ace16011 /hw/fsp | |
parent | 9d1755179112071652bb4a317f9006da630ce25d (diff) | |
download | skiboot-6557a728385c3fbcef297d2c61c7d93bc539f8bb.zip skiboot-6557a728385c3fbcef297d2c61c7d93bc539f8bb.tar.gz skiboot-6557a728385c3fbcef297d2c61c7d93bc539f8bb.tar.bz2 |
FSP/CONSOLE: Fix fsp_console_write_buffer_space() call
Kernel calls fsp_console_write_buffer_space() to check console buffer space
availability. If there is enough buffer space to write data, then kernel will
call fsp_console_write() to write actual data.
In some extreme corner cases (like one explained in commit c8a7535f)
console becomes full and this function returns 0 to kernel (or space available
in console buffer < next incoming data size). Kernel will continue retrying
until it gets enough space. So we will start seeing RCU stalls.
This patch keeps track of previous available space. If previous space is same
as current means not enough space in console buffer to write incoming data.
It may be due to very high console write operation and slow response from FSP
-OR- FSP has stopped processing data (ex: because of ipmi daemon died). At this
point we will start timer with timeout of SER_BUFFER_OUT_TIMEOUT (10 secs).
If situation is not improved within 10 seconds means something went bad. Lets
return OPAL_RESOURCE so that kernel can drop console write and continue.
CC: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
CC: Stewart Smith <stewart@linux.vnet.ibm.com>
Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
[stewart: reset timeout in fsp_console_write() path]
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/fsp')
-rw-r--r-- | hw/fsp/fsp-console.c | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/hw/fsp/fsp-console.c b/hw/fsp/fsp-console.c index d1996cc..38d4474 100644 --- a/hw/fsp/fsp-console.c +++ b/hw/fsp/fsp-console.c @@ -61,11 +61,15 @@ struct fsp_serial { struct fsp_msg *poke_msg; u8 waiting; u64 irq; + u16 out_buf_prev_len; + u64 out_buf_timeout; }; #define SER_BUFFER_SIZE 0x00040000UL #define MAX_SERIAL 4 +#define SER_BUFFER_OUT_TIMEOUT 10 + static struct fsp_serial fsp_serials[MAX_SERIAL]; static bool got_intf_query; static struct lock fsp_con_lock = LOCK_UNLOCKED; @@ -315,6 +319,8 @@ static void fsp_open_vserial(struct fsp_msg *msg) fs->in_buf->flags = fs->out_buf->flags = 0; fs->in_buf->reserved = fs->out_buf->reserved = 0; fs->in_buf->next_out = fs->out_buf->next_out = 0; + fs->out_buf_prev_len = 0; + fs->out_buf_timeout = 0; unlock(&fsp_con_lock); already_open: @@ -606,6 +612,12 @@ static int64_t fsp_console_write(int64_t term_number, int64_t *length, requested = 0x1000; written = fsp_write_vserial(fs, buffer, requested); + if (written) { + /* If we wrote anything, reset timeout */ + fs->out_buf_prev_len = 0; + fs->out_buf_timeout = 0; + } + #ifdef OPAL_DEBUG_CONSOLE_IO prlog(PR_TRACE, "OPAL: console write req=%ld written=%ld" " ni=%d no=%d\n", @@ -655,7 +667,29 @@ static int64_t fsp_console_write_buffer_space(int64_t term_number, % SER_BUF_DATA_SIZE; unlock(&fsp_con_lock); - return OPAL_SUCCESS; + /* Console buffer has enough space to write incoming data */ + if (*length != fs->out_buf_prev_len) { + fs->out_buf_prev_len = *length; + fs->out_buf_timeout = 0; + + return OPAL_SUCCESS; + } + + /* + * Buffer is full, start internal timer. We will continue returning + * SUCCESS until timeout happens, hoping FSP will consume data within + * timeout period. + */ + if (fs->out_buf_timeout == 0) { + fs->out_buf_timeout = mftb() + + secs_to_tb(SER_BUFFER_OUT_TIMEOUT); + } + + if (tb_compare(mftb(), fs->out_buf_timeout) != TB_AAFTERB) + return OPAL_SUCCESS; + + /* Timeout happened. Lets drop incoming data */ + return OPAL_RESOURCE; } static int64_t fsp_console_read(int64_t term_number, int64_t *length, |