[Skiboot] [PATCH 1/4] fsp/console: Ignore data on unresponsive consoles

Samuel Mendoza-Jonas sam at mendozajonas.com
Thu Jul 14 10:26:00 AEST 2016


On Tue, 2016-06-28 at 13:07 +1000, Samuel Mendoza-Jonas wrote:
> 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 at mendozajonas.com>

Realised I forgot to mention, patch 1 in particular should be merged into
stable as well.

> ---
>  hw/fsp/fsp-console.c | 18 ++++++++++++++++--
>  1 file 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);



More information about the Skiboot mailing list