diff options
author | Sam Mendoza-Jonas <sam@mendozajonas.com> | 2016-06-28 13:07:06 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2016-07-15 14:48:38 +1000 |
commit | 7116c948ee63019ceda7dc3b7334e6c25e291eeb (patch) | |
tree | 918b3f92142841056c595a215063484f7c99d9d7 | |
parent | 65e436ad726aac81fe8acca55868afdf9d5f3161 (diff) | |
download | skiboot-7116c948ee63019ceda7dc3b7334e6c25e291eeb.zip skiboot-7116c948ee63019ceda7dc3b7334e6c25e291eeb.tar.gz skiboot-7116c948ee63019ceda7dc3b7334e6c25e291eeb.tar.bz2 |
fsp/console: Ignore data on unresponsive consoles
Linux kernels from v4.1 onwards will try to request an irq for each hvc
console using OPAL_EVENT_CONSOLE_INPUT, however because the IRQF_SHARED
flag is not set any console after the first will fail. If there is data
on one of these failed consoles OPAL will set OPAL_EVENT_CONSOLE_INPUT
every time fsp_console_read is called, leading to RCU stalls in the
kernel.
As a workaround for unpatched kernels, cease setting
OPAL_EVENT_CONSOLE_INPUT for consoles that we have noticed are not being
read.
Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
(cherry picked from commit fd6b71fcc6912611ce81f455b4805f0531699d5e)
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r-- | hw/fsp/fsp-console.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/hw/fsp/fsp-console.c b/hw/fsp/fsp-console.c index 2a25e1c..87e509d 100644 --- a/hw/fsp/fsp-console.c +++ b/hw/fsp/fsp-console.c @@ -54,6 +54,7 @@ struct fsp_serial { struct fsp_serbuf_hdr *in_buf; struct fsp_serbuf_hdr *out_buf; struct fsp_msg *poke_msg; + u8 waiting; }; #define SER_BUFFER_SIZE 0x00040000UL @@ -653,6 +654,8 @@ static int64_t fsp_console_read(int64_t term_number, int64_t *length, unlock(&fsp_con_lock); return OPAL_CLOSED; } + if (fs->waiting) + fs->waiting = 0; sb = fs->in_buf; old_nin = sb->next_in; lwsync(); @@ -687,8 +690,19 @@ static int64_t fsp_console_read(int64_t term_number, int64_t *length, if (fs->log_port || !fs->open) continue; - if (sb->next_out != sb->next_in) - pending = true; + if (sb->next_out != sb->next_in) { + /* + * HACK: Some kernels (4.1+) may fail to properly + * register hvc1 and will never read it. This can lead + * to RCU stalls, so if we notice this console is not + * being read, do not set OPAL_EVENT_CONSOLE_INPUT even + * if it has data + */ + if (fs->waiting < 5) { + pending = true; + fs->waiting++; + } + } } if (!pending) opal_update_pending_evt(OPAL_EVENT_CONSOLE_INPUT, 0); |