[Skiboot] [PATCH v2 3/5] hw/psi-p9: Mask OPAL-owned LSIs without handlers

Cédric Le Goater clg at kaod.org
Thu Sep 5 17:05:57 AEST 2019


On 05/09/2019 05:08, Oliver O'Halloran wrote:
> Some versions of Swift have the TPM interrupt line of the second chip
> pulled up instead of down. This causes the PSI's external (TPM) interrupt
> to constantly re-fire since it's an LSI and the interrupt signal is
> constantly active. There's nothing that can be done to clear the underlying
> interrupt condition so we to ensure that it's masked.
> 
> The problem isn't really specific to the external interrupt and will
> occur for any of the PSI interrupts that don't have an actual handler
> (FSP, global error, and sometimes the external). When one of these is
> delivered to OPAL we should log that it happened and mask it to prevent
> re-firing.
> 
> Cc: Cédric Le Goater <clg at kaod.org>
> Signed-off-by: Oliver O'Halloran <oohall at gmail.com>
> ---
> v2: Use __xive_source_mask() to mask the interrupt rather than
>     opencoding the ESB manipulation in the PSI driver.

We can get rid of xive_source_mask() and rename it to __xive_source_mask().

I would remove the test on platform.external_irq as it is not used on P9 
and it adds extra noise in the code. 

Anyhow,

Reviewed-by: Cédric Le Goater <clg at kaod.org>

Thanks,

C.

> 
>     look up the interrupt name from the name array rather than
>     using the name callback.
> ---
>  hw/psi.c | 35 +++++++++++++++++++++++++++++------
>  1 file changed, 29 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/psi.c b/hw/psi.c
> index 99ec06ac488a..6c28eb0447ad 100644
> --- a/hw/psi.c
> +++ b/hw/psi.c
> @@ -536,6 +536,29 @@ static char *psi_p9_irq_name(struct irq_source *is, uint32_t isn)
>  	return strdup(p9_psi_int_names[idx]);
>  }
>  
> +static void psi_p9_mask_unhandled_irq(struct irq_source *is, uint32_t isn)
> +{
> +	int idx = isn - psi->interrupt;
> +	struct psi *psi = is->data;
> +	const char *name;
> +
> +	if (idx < ARRAY_SIZE(p9_psi_int_names))
> +		name = p9_psi_int_names[idx];
> +	else
> +		name = "unknown irq";
> +
> +	prerror("PSI: Masking unhandled LSI %s (idx: %d)!\n", name, idx);
> +
> +	/*
> +	 * All the PSI interrupts are LSIs and will be constantly re-fired
> +	 * unless the underlying interrupt condition is cleared. If we don't
> +	 * have a handler for the interrupt then it needs to be masked to
> +	 * prevent the IRQ from locking up the thread which handles it.
> +	 */
> +	__xive_source_mask(is, isn);
> +
> +}
> +
>  static void psihb_p9_interrupt(struct irq_source *is, uint32_t isn)
>  {
>  	struct psi *psi = is->data;
> @@ -548,21 +571,17 @@ static void psihb_p9_interrupt(struct irq_source *is, uint32_t isn)
>  	case P9_PSI_IRQ_OCC:
>  		occ_p9_interrupt(psi->chip_id);
>  		break;
> -	case P9_PSI_IRQ_FSI:
> -		printf("PSI: FSI irq received\n");
> -		break;
>  	case P9_PSI_IRQ_LPCHC:
>  		lpc_interrupt(psi->chip_id);
>  		break;
>  	case P9_PSI_IRQ_LOCAL_ERR:
>  		prd_psi_interrupt(psi->chip_id);
>  		break;
> -	case P9_PSI_IRQ_GLOBAL_ERR:
> -		printf("PSI: Global error irq received\n");
> -		break;
>  	case P9_PSI_IRQ_EXTERNAL:
>  		if (platform.external_irq)
>  			platform.external_irq(psi->chip_id);
> +		else
> +			psi_p9_mask_unhandled_irq(is, isn);
>  		break;
>  	case P9_PSI_IRQ_LPC_SIRQ0:
>  	case P9_PSI_IRQ_LPC_SIRQ1:
> @@ -580,6 +599,9 @@ static void psihb_p9_interrupt(struct irq_source *is, uint32_t isn)
>  	case P9_PSI_IRQ_PSU:
>  		p9_sbe_interrupt(psi->chip_id);
>  		break;
> +
> +	default:
> +		psi_p9_mask_unhandled_irq(is, isn);
>  	}
>  }
>  
> @@ -614,6 +636,7 @@ static const struct irq_source_ops psi_p9_irq_ops = {
>  	.interrupt = psihb_p9_interrupt,
>  	.attributes = psi_p9_irq_attributes,
>  	.name = psi_p9_irq_name,
> +	.mask = psi_p9_mask_unhandled_irq,
>  };
>  
>  void psi_set_external_irq_policy(bool policy)
> 



More information about the Skiboot mailing list