[Skiboot] [PATCH 09/16] [PATCH 09/16] opencapi5: enable interrupt on error

Frederic Barrat fbarrat at linux.ibm.com
Wed Sep 8 22:56:47 AEST 2021



On 20/08/2021 11:45, Christophe Lombard wrote:
> The default action for the errors (unexpected errors on the opencapi
> link) reported in the PAU FIR2 registe is mostly set to system
> checkstop.
> 
> This patch changes the default action of those errors so that the PAU
> will raise an interrupt instead. Interrupt information are logged so
> that the error can be debugged and linux can catch the event.
> 
> Signed-off-by: Christophe Lombard <clombard at linux.vnet.ibm.com>
> ---


Reviewed-by: Frederic Barrat <fbarrat at linux.ibm.com>



>   hw/pau.c           | 157 +++++++++++++++++++++++++++++++++++++++++++++
>   include/pau-regs.h |  12 ++++
>   include/pau.h      |   2 +
>   3 files changed, 171 insertions(+)
> 
> diff --git a/hw/pau.c b/hw/pau.c
> index d45b5023..98abe704 100644
> --- a/hw/pau.c
> +++ b/hw/pau.c
> @@ -6,6 +6,7 @@
>   #include <interrupts.h>
>   #include <pci-slot.h>
>   #include <phys-map.h>
> +#include <xive.h>
>   #include <pau.h>
>   #include <pau-regs.h>
> 
> @@ -236,6 +237,15 @@ static int pau_opencapi_set_fence_control(struct pau_dev *dev,
>   	return OPAL_HARDWARE;
>   }
> 
> +#define PAU_DEV_STATUS_BROKEN	0x1
> +
> +static void pau_opencapi_set_broken(struct pau_dev *dev)
> +{
> +	PAUDEVDBG(dev, "Update status to broken\n");
> +
> +	dev->status = PAU_DEV_STATUS_BROKEN;
> +}
> +
>   static void pau_opencapi_mask_firs(struct pau *pau)
>   {
>   	uint64_t reg, val;
> @@ -309,6 +319,113 @@ static void pau_opencapi_assign_bars(struct pau *pau)
>   	}
>   }
> 
> +static uint64_t pau_opencapi_ipi_attributes(struct irq_source *is,
> +					    uint32_t isn)
> +{
> +	struct pau *pau = is->data;
> +	uint32_t level = isn - pau->irq_base;
> +
> +	if (level >= 37 && level <= 40) {
> +		/* level 37-40: OTL/XSL interrupt */
> +		return IRQ_ATTR_TARGET_OPAL |
> +		       IRQ_ATTR_TARGET_RARE |
> +		       IRQ_ATTR_TYPE_MSI;
> +	}
> +
> +	return IRQ_ATTR_TARGET_LINUX;
> +}
> +
> +static void pau_opencapi_ipi_interrupt(struct irq_source *is,
> +				       uint32_t isn)
> +{
> +	struct pau *pau = is->data;
> +	uint32_t level = isn - pau->irq_base;
> +	struct pau_dev *dev;
> +
> +	switch (level) {
> +	case 37 ... 40:
> +		pau_for_each_opencapi_dev(dev, pau)
> +			pau_opencapi_set_broken(dev);
> +
> +		opal_update_pending_evt(OPAL_EVENT_PCI_ERROR,
> +					OPAL_EVENT_PCI_ERROR);
> +		break;
> +	default:
> +		PAUERR(pau, "Received unknown interrupt %d\n", level);
> +		return;
> +	}
> +}
> +
> +#define PAU_IRQ_LEVELS 60
> +
> +static char *pau_opencapi_ipi_name(struct irq_source *is, uint32_t isn)
> +{
> +	struct pau *pau = is->data;
> +	uint32_t level = isn - pau->irq_base;
> +
> +	switch (level) {
> +	case 0 ... 19:
> +		return strdup("Reserved");
> +	case 20:
> +		return strdup("An error event related to PAU CQ functions");
> +	case 21:
> +		return strdup("An error event related to PAU MISC functions");
> +	case 22 ... 34:
> +		return strdup("Reserved");
> +	case 35:
> +		return strdup("Translation failure for OCAPI link 0");
> +	case 36:
> +		return strdup("Translation failure for OCAPI link 1");
> +	case 37:
> +		return strdup("An error event related to OTL for link 0");
> +	case 38:
> +		return strdup("An error event related to OTL for link 1");
> +	case 39:
> +		return strdup("An error event related to XSL for link 0");
> +	case 40:
> +		return strdup("An error event related to XSL for link 1");
> +	case 41 ... 59:
> +		return strdup("Reserved");
> +	}
> +
> +	return strdup("Unknown");
> +}
> +
> +static const struct irq_source_ops pau_opencapi_ipi_ops = {
> +	.attributes	= pau_opencapi_ipi_attributes,
> +	.interrupt	= pau_opencapi_ipi_interrupt,
> +	.name		= pau_opencapi_ipi_name,
> +};
> +
> +static void pau_opencapi_setup_irqs(struct pau *pau)
> +{
> +	uint64_t reg, val;
> +	uint32_t base;
> +
> +	base = xive2_alloc_ipi_irqs(pau->chip_id, PAU_IRQ_LEVELS, 64);
> +	if (base == XIVE_IRQ_ERROR) {
> +		PAUERR(pau, "Failed to allocate interrupt sources\n");
> +		return;
> +	}
> +
> +	xive2_register_ipi_source(base, PAU_IRQ_LEVELS, pau, &pau_opencapi_ipi_ops);
> +
> +	/* Set IPI configuration */
> +	reg = PAU_MISC_CONFIG;
> +	val = pau_read(pau, reg);
> +	val = SETFIELD(PAU_MISC_CONFIG_IPI_PS, val, PAU_MISC_CONFIG_IPI_PS_64K);
> +	val = SETFIELD(PAU_MISC_CONFIG_IPI_OS, val, PAU_MISC_CONFIG_IPI_OS_AIX);
> +	pau_write(pau, reg, val);
> +
> +	/* Set IRQ base */
> +	reg = PAU_MISC_INT_BAR;
> +	val = SETFIELD(PAU_MISC_INT_BAR_ADDR, 0ull,
> +		       (uint64_t)xive2_get_trigger_port(base) >> 12);
> +	pau_write(pau, reg, val);
> +
> +	pau->irq_base = base;
> +}
> +
>   static void pau_opencapi_enable_bars(struct pau_dev *dev, bool enable)
>   {
>   	struct pau *pau = dev->pau;
> @@ -768,12 +885,48 @@ static void pau_opencapi_address_translation_config(struct pau_dev *dev)
>   	/* XSL_GP  - use defaults */
>   }
> 
> +static void pau_opencapi_enable_interrupt_on_error(struct pau_dev *dev)
> +{
> +	struct pau *pau = dev->pau;
> +	uint64_t reg, val;
> +
> +	PAUDEVDBG(dev, "Enable Interrupt-on-error\n");
> +
> +	/* translation fault */
> +	reg = PAU_MISC_INT_2_CONFIG;
> +	val = pau_read(pau, reg);
> +	val |= PAU_MISC_INT_2_CONFIG_XFAULT_2_5(dev->index);
> +	pau_write(pau, reg, val);
> +
> +	/* freeze disable */
> +	reg = PAU_MISC_FREEZE_1_CONFIG;
> +	val = pau_read(pau, reg);
> +	val &= ~PAU_FIR1_NDL_BRICKS_0_5;
> +	val &= ~PAU_FIR1_NDL_BRICKS_6_11;
> +	pau_write(pau, reg, val);
> +
> +	/* fence disable */
> +	reg = PAU_MISC_FENCE_1_CONFIG;
> +	val = pau_read(pau, reg);
> +	val &= ~PAU_FIR1_NDL_BRICKS_0_5;
> +	val &= ~PAU_FIR1_NDL_BRICKS_6_11;
> +	pau_write(pau, reg, val);
> +
> +	/* irq disable */
> +	reg = PAU_MISC_INT_1_CONFIG;
> +	val = pau_read(pau, reg);
> +	val &= ~PAU_FIR1_NDL_BRICKS_0_5;
> +	val &= ~PAU_FIR1_NDL_BRICKS_6_11;
> +	pau_write(pau, reg, val);
> +}
> +
>   static void pau_opencapi_init_hw(struct pau *pau)
>   {
>   	struct pau_dev *dev = NULL;
> 
>   	pau_opencapi_mask_firs(pau);
>   	pau_opencapi_assign_bars(pau);
> +	pau_opencapi_setup_irqs(pau);
> 
>   	/* Create phb */
>   	pau_for_each_opencapi_dev(dev, pau) {
> @@ -850,6 +1003,10 @@ static void pau_opencapi_init_hw(struct pau *pau)
>   		 * AFU's memory
>   		 */
> 
> +		/* Procedure 17.1.3.11 - Interrupt Configuration */
> +		/* done in pau_opencapi_setup_irqs() */
> +		pau_opencapi_enable_interrupt_on_error(dev);
> +
>   		/* Reset disabled. Place OTLs into Run State */
>   		pau_opencapi_set_fence_control(dev, 0b00);
>   	}
> diff --git a/include/pau-regs.h b/include/pau-regs.h
> index e4ff7cc0..d98f435b 100644
> --- a/include/pau-regs.h
> +++ b/include/pau-regs.h
> @@ -139,6 +139,18 @@
>   #define PAU_MISC_HOLD				(PAU_BLOCK_PAU_MISC + 0x020)
>   #define   PAU_MISC_HOLD_NDL_STALL		PPC_BITMASK(0, 3)
>   #define PAU_MISC_CONFIG				(PAU_BLOCK_PAU_MISC + 0x030)
> +#define   PAU_MISC_CONFIG_IPI_PS		PPC_BIT(11)
> +#define   PAU_MISC_CONFIG_IPI_PS_64K		1
> +#define   PAU_MISC_CONFIG_IPI_OS		PPC_BIT(12)
> +#define   PAU_MISC_CONFIG_IPI_OS_AIX		0
>   #define   PAU_MISC_CONFIG_OC_MODE		PPC_BIT(16)
> +#define PAU_MISC_FREEZE_1_CONFIG		(PAU_BLOCK_PAU_MISC + 0x048)
> +#define PAU_MISC_FENCE_1_CONFIG			(PAU_BLOCK_PAU_MISC + 0x058)
> +#define PAU_MISC_INT_1_CONFIG			(PAU_BLOCK_PAU_MISC + 0x068)
> +#define PAU_MISC_INT_BAR			(PAU_BLOCK_PAU_MISC + 0x098)
> +#define   PAU_MISC_INT_BAR_ADDR			PPC_BITMASK(0, 39)
> +#define PAU_MISC_INT_2_CONFIG			(PAU_BLOCK_PAU_MISC + 0x408)
> +#define   PAU_MISC_INT_2_CONFIG_XFAULT_2_5(n)	PPC_BIT(0 + (n))
> +#define   PAU_MISC_INT_2_CONFIG_XFAULT_0_1(n)	PPC_BIT(54 + (n))
> 
>   #endif /* __PAU_REGS_H */
> diff --git a/include/pau.h b/include/pau.h
> index 4d78cbb6..d6a08809 100644
> --- a/include/pau.h
> +++ b/include/pau.h
> @@ -33,6 +33,7 @@ struct pau_dev {
>   	uint32_t		index;
>   	struct dt_node		*dn;
>   	struct phb		phb;
> +	uint32_t		status;
> 
>   	struct pau_bar		ntl_bar;
>   	struct pau_bar		genid_bar;
> @@ -59,6 +60,7 @@ struct pau {
>   	uint64_t		regs[2];
>   	bool			mmio_access;
> 
> +	uint32_t		irq_base;
>   	struct lock		lock;
> 
>   	uint32_t		links;
> 


More information about the Skiboot mailing list