[Skiboot] [PATCH v2 2/7] hw/npu2: Move npu2 irq setup code to common area

Andrew Donnellan andrew.donnellan at au1.ibm.com
Thu Apr 4 15:06:52 AEDT 2019


On 26/3/19 5:29 am, Frederic Barrat wrote:
> The NPU IRQ setup code is currently duplicated between NVLink and
> OpenCAPI, yet it's almost identical. This patch moves the NVLink version of the
> code to the common file. A later patch will make use of it for OpenCAPI.
> 
> Signed-off-by: Frederic Barrat <fbarrat at linux.ibm.com>

Reviewed-by: Andrew Donnellan <andrew.donnellan at au1.ibm.com>

> ---
> Changelog
> v2: no change
> 
> hw/npu2-common.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++
>   hw/npu2.c        | 100 ----------------------------------------------
>   2 files changed, 102 insertions(+), 100 deletions(-)
> 
> diff --git a/hw/npu2-common.c b/hw/npu2-common.c
> index 3d0b6366..b0d55f5d 100644
> --- a/hw/npu2-common.c
> +++ b/hw/npu2-common.c
> @@ -22,6 +22,12 @@
>   #include <bitutils.h>
>   #include <nvram.h>
>   #include <i2c.h>
> +#include <interrupts.h>
> +#include <xive.h>
> +
> +#define NPU2_IRQ_BASE_SHIFT 13
> +#define NPU2_N_DL_IRQS 23
> +#define NPU2_N_DL_IRQS_ALIGN 64
>   
>   /*
>    * We use the indirect method because it uses the same addresses as
> @@ -97,6 +103,99 @@ void npu2_write_mask_4b(struct npu2 *p, uint64_t reg, uint32_t val, uint32_t mas
>   			(uint64_t)new_val << 32);
>   }
>   
> +static uint64_t npu2_ipi_attributes(struct irq_source *is __unused, uint32_t isn __unused)
> +{
> +	struct npu2 *p = is->data;
> +	uint32_t idx = isn - p->base_lsi;
> +
> +	if (idx == 18)
> +		/* TCE Interrupt - used to detect a frozen PE */
> +		return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_RARE | IRQ_ATTR_TYPE_MSI;
> +	else
> +		return IRQ_ATTR_TARGET_LINUX;
> +}
> +
> +static char *npu2_ipi_name(struct irq_source *is, uint32_t isn)
> +{
> +	struct npu2 *p = is->data;
> +	uint32_t idx = isn - p->base_lsi;
> +	const char *name;
> +
> +	switch (idx) {
> +	case 0: name = "NDL 0 Stall Event (brick 0)"; break;
> +	case 1: name = "NDL 0 No-Stall Event (brick 0)"; break;
> +	case 2: name = "NDL 1 Stall Event (brick 1)"; break;
> +	case 3: name = "NDL 1 No-Stall Event (brick 1)"; break;
> +	case 4: name = "NDL 2 Stall Event (brick 2)"; break;
> +	case 5: name = "NDL 2 No-Stall Event (brick 2)"; break;
> +	case 6: name = "NDL 5 Stall Event (brick 3)"; break;
> +	case 7: name = "NDL 5 No-Stall Event (brick 3)"; break;
> +	case 8: name = "NDL 4 Stall Event (brick 4)"; break;
> +	case 9: name = "NDL 4 No-Stall Event (brick 4)"; break;
> +	case 10: name = "NDL 3 Stall Event (brick 5)"; break;
> +	case 11: name = "NDL 3 No-Stall Event (brick 5)"; break;
> +	case 12: name = "NTL 0 Event"; break;
> +	case 13: name = "NTL 1 Event"; break;
> +	case 14: name = "NTL 2 Event"; break;
> +	case 15: name = "NTL 3 Event"; break;
> +	case 16: name = "NTL 4 Event"; break;
> +	case 17: name = "NTL 5 Event"; break;
> +	case 18: name = "TCE Event"; break;
> +	case 19: name = "ATS Event"; break;
> +	case 20: name = "CQ Event"; break;
> +	case 21: name = "MISC Event"; break;
> +	case 22: name = "NMMU Local Xstop"; break;
> +	default: name = "Unknown";
> +	}
> +	return strdup(name);
> +}
> +
> +static void npu2_err_interrupt(struct irq_source *is, uint32_t isn)
> +{
> +	struct npu2 *p = is->data;
> +	uint32_t idx = isn - p->base_lsi;
> +
> +	if (idx != 18) {
> +		prerror("OPAL received unknown NPU2 interrupt %d\n", idx);
> +		return;
> +	}
> +
> +	opal_update_pending_evt(OPAL_EVENT_PCI_ERROR,
> +				OPAL_EVENT_PCI_ERROR);
> +}
> +
> +static const struct irq_source_ops npu2_ipi_ops = {
> +	.interrupt	= npu2_err_interrupt,
> +	.attributes	= npu2_ipi_attributes,
> +	.name = npu2_ipi_name,
> +};
> +
> +static void setup_irqs(struct npu2 *p)
> +{
> +	uint64_t reg, val;
> +	void *tp;
> +
> +	p->base_lsi = xive_alloc_ipi_irqs(p->chip_id, NPU2_N_DL_IRQS, NPU2_N_DL_IRQS_ALIGN);
> +	if (p->base_lsi == XIVE_IRQ_ERROR) {
> +		prlog(PR_ERR, "NPU: Failed to allocate interrupt sources, IRQs for NDL No-stall events will not be available.\n");
> +		return;
> +	}
> +	xive_register_ipi_source(p->base_lsi, NPU2_N_DL_IRQS, p, &npu2_ipi_ops);
> +
> +	/* Set IPI configuration */
> +	reg = NPU2_REG_OFFSET(NPU2_STACK_MISC, NPU2_BLOCK_MISC, NPU2_MISC_CFG);
> +	val = npu2_read(p, reg);
> +	val = SETFIELD(NPU2_MISC_CFG_IPI_PS, val, NPU2_MISC_CFG_IPI_PS_64K);
> +	val = SETFIELD(NPU2_MISC_CFG_IPI_OS, val, NPU2_MISC_CFG_IPI_OS_AIX);
> +	npu2_write(p, reg, val);
> +
> +	/* Set IRQ base */
> +	reg = NPU2_REG_OFFSET(NPU2_STACK_MISC, NPU2_BLOCK_MISC, NPU2_MISC_IRQ_BASE);
> +	tp = xive_get_trigger_port(p->base_lsi);
> +	val = ((uint64_t)tp) << NPU2_IRQ_BASE_SHIFT;
> +	npu2_write(p, reg, val);
> +}
> +
>   static bool _i2c_presence_detect(struct npu2_dev *dev)
>   {
>   	uint8_t state, data;
> @@ -276,6 +375,9 @@ static void setup_devices(struct npu2 *npu)
>   		return;
>   	}
>   
> +	if (nvlink_detected)
> +		setup_irqs(npu);
> +
>   	if (nvlink_detected)
>   		npu2_nvlink_init_npu(npu);
>   	else if (ocapi_detected)
> diff --git a/hw/npu2.c b/hw/npu2.c
> index 4ecc9135..d532c4da 100644
> --- a/hw/npu2.c
> +++ b/hw/npu2.c
> @@ -20,7 +20,6 @@
>   #include <pci.h>
>   #include <pci-slot.h>
>   #include <pci-virt.h>
> -#include <interrupts.h>
>   #include <opal.h>
>   #include <opal-api.h>
>   #include <cpu.h>
> @@ -35,14 +34,9 @@
>   #include <chip.h>
>   #include <phys-map.h>
>   #include <nvram.h>
> -#include <xive.h>
>   #include <xscom-p9-regs.h>
>   #include <phb4.h>
>   
> -#define NPU2_IRQ_BASE_SHIFT 13
> -#define NPU2_N_DL_IRQS 23
> -#define NPU2_N_DL_IRQS_ALIGN 64
> -
>   #define VENDOR_CAP_START    0x80
>   #define VENDOR_CAP_END      0x90
>   #define VENDOR_CAP_LEN      0x10
> @@ -1922,99 +1916,6 @@ static void npu2_add_phb_properties(struct npu2 *p)
>   			      hi32(mm_size), lo32(mm_size));
>   }
>   
> -static uint64_t npu2_ipi_attributes(struct irq_source *is __unused, uint32_t isn __unused)
> -{
> -	struct npu2 *p = is->data;
> -	uint32_t idx = isn - p->base_lsi;
> -
> -	if (idx == 18)
> -		/* TCE Interrupt - used to detect a frozen PE */
> -		return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_RARE | IRQ_ATTR_TYPE_MSI;
> -	else
> -		return IRQ_ATTR_TARGET_LINUX;
> -}
> -
> -static char *npu2_ipi_name(struct irq_source *is, uint32_t isn)
> -{
> -	struct npu2 *p = is->data;
> -	uint32_t idx = isn - p->base_lsi;
> -	const char *name;
> -
> -	switch (idx) {
> -	case 0: name = "NDL 0 Stall Event (brick 0)"; break;
> -	case 1: name = "NDL 0 No-Stall Event (brick 0)"; break;
> -	case 2: name = "NDL 1 Stall Event (brick 1)"; break;
> -	case 3: name = "NDL 1 No-Stall Event (brick 1)"; break;
> -	case 4: name = "NDL 2 Stall Event (brick 2)"; break;
> -	case 5: name = "NDL 2 No-Stall Event (brick 2)"; break;
> -	case 6: name = "NDL 5 Stall Event (brick 3)"; break;
> -	case 7: name = "NDL 5 No-Stall Event (brick 3)"; break;
> -	case 8: name = "NDL 4 Stall Event (brick 4)"; break;
> -	case 9: name = "NDL 4 No-Stall Event (brick 4)"; break;
> -	case 10: name = "NDL 3 Stall Event (brick 5)"; break;
> -	case 11: name = "NDL 3 No-Stall Event (brick 5)"; break;
> -	case 12: name = "NTL 0 Event"; break;
> -	case 13: name = "NTL 1 Event"; break;
> -	case 14: name = "NTL 2 Event"; break;
> -	case 15: name = "NTL 3 Event"; break;
> -	case 16: name = "NTL 4 Event"; break;
> -	case 17: name = "NTL 5 Event"; break;
> -	case 18: name = "TCE Event"; break;
> -	case 19: name = "ATS Event"; break;
> -	case 20: name = "CQ Event"; break;
> -	case 21: name = "MISC Event"; break;
> -	case 22: name = "NMMU Local Xstop"; break;
> -	default: name = "Unknown";
> -	}
> -	return strdup(name);
> -}
> -
> -static void npu2_err_interrupt(struct irq_source *is, uint32_t isn)
> -{
> -	struct npu2 *p = is->data;
> -	uint32_t idx = isn - p->base_lsi;
> -
> -	if (idx != 18) {
> -		prerror("OPAL received unknown NPU2 interrupt %d\n", idx);
> -		return;
> -	}
> -
> -	opal_update_pending_evt(OPAL_EVENT_PCI_ERROR,
> -				OPAL_EVENT_PCI_ERROR);
> -}
> -
> -static const struct irq_source_ops npu2_ipi_ops = {
> -	.interrupt	= npu2_err_interrupt,
> -	.attributes	= npu2_ipi_attributes,
> -	.name = npu2_ipi_name,
> -};
> -
> -static void npu2_setup_irqs(struct npu2 *p)
> -{
> -	uint64_t reg, val;
> -	void *tp;
> -
> -	p->base_lsi = xive_alloc_ipi_irqs(p->chip_id, NPU2_N_DL_IRQS, NPU2_N_DL_IRQS_ALIGN);
> -	if (p->base_lsi == XIVE_IRQ_ERROR) {
> -		prlog(PR_ERR, "NPU: Failed to allocate interrupt sources, IRQs for NDL No-stall events will not be available.\n");
> -		return;
> -	}
> -	xive_register_ipi_source(p->base_lsi, NPU2_N_DL_IRQS, p, &npu2_ipi_ops );
> -
> -	/* Set IPI configuration */
> -	reg = NPU2_REG_OFFSET(NPU2_STACK_MISC, NPU2_BLOCK_MISC, NPU2_MISC_CFG);
> -	val = npu2_read(p, reg);
> -	val = SETFIELD(NPU2_MISC_CFG_IPI_PS, val, NPU2_MISC_CFG_IPI_PS_64K);
> -	val = SETFIELD(NPU2_MISC_CFG_IPI_OS, val, NPU2_MISC_CFG_IPI_OS_AIX);
> -	npu2_write(p, reg, val);
> -
> -	/* Set IRQ base */
> -	reg = NPU2_REG_OFFSET(NPU2_STACK_MISC, NPU2_BLOCK_MISC, NPU2_MISC_IRQ_BASE);
> -	tp = xive_get_trigger_port(p->base_lsi);
> -	val = ((uint64_t)tp) << NPU2_IRQ_BASE_SHIFT;
> -	npu2_write(p, reg, val);
> -}
> -
>   void npu2_nvlink_create_phb(struct npu2 *npu, struct dt_node *dn)
>   {
>   	struct pci_slot *slot;
> @@ -2028,7 +1929,6 @@ void npu2_nvlink_create_phb(struct npu2 *npu, struct dt_node *dn)
>   	list_head_init(&npu->phb_nvlink.devices);
>   	list_head_init(&npu->phb_nvlink.virt_devices);
>   
> -	npu2_setup_irqs(npu);
>   	npu2_populate_devices(npu, dn);
>   	npu2_add_interrupt_map(npu, dn);
>   	npu2_add_phb_properties(npu);
> 

-- 
Andrew Donnellan              OzLabs, ADL Canberra
andrew.donnellan at au1.ibm.com  IBM Australia Limited



More information about the Skiboot mailing list