Message ID | d0deca52e80558429e1a4436abaa58e87adcd683.1544597914.git-series.andrew.donnellan@au1.ibm.com |
---|---|
State | Superseded |
Headers | show |
Series | Support OpenCAPI and NVLink devices on same NPU on Witherspoon | expand |
Context | Check | Description |
---|---|---|
snowpatch_ozlabs/apply_patch | success | master/apply_patch Successfully applied |
snowpatch_ozlabs/snowpatch_job_snowpatch-skiboot | success | Test snowpatch/job/snowpatch-skiboot on branch master |
Le 12/12/2018 à 07:58, Andrew Donnellan a écrit : > From: Frederic Barrat <fbarrat@linux.ibm.com> > > The NPU IRQ setup code is currently duplicated between NVLink and > OpenCAPI. > > Apart from the NPU2_MISC_IRQ_ENABLE2 register, the setup of IRQs is > basically identical between NVLink and OpenCAPI. One difference worth mentioning in the commit message is that we now allocate a few extra interrupts per NPU, as opencapi is more greedy than nvlink (35 vs 23 previously). Fred > Move the NVLink IRQ setup code into the common path and get rid of all the > OpenCAPI IRQ setup apart from the enable mask. > > Signed-off-by: Frederic Barrat <fbarrat@linux.ibm.com> > Signed-off-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com> > > --- > > Might need some testing > --- > hw/npu2-common.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++- > hw/npu2-opencapi.c | 50 +-------------------- > hw/npu2.c | 100 +----------------------------------------- > include/npu2.h | 1 +- > 4 files changed, 116 insertions(+), 147 deletions(-) > > diff --git a/hw/npu2-common.c b/hw/npu2-common.c > index 6cbae9bffaf9..8edf761cf56b 100644 > --- a/hw/npu2-common.c > +++ b/hw/npu2-common.c > @@ -24,6 +24,12 @@ > #include <nvram.h> > #include <i2c.h> > #include <phys-map.h> > +#include <interrupts.h> > +#include <xive.h> > + > +#define NPU2_IRQ_BASE_SHIFT 13 > +#define NPU2_N_DL_IRQS 35 > +#define NPU2_N_DL_IRQS_ALIGN 64 > > /* > * We use the indirect method because it uses the same addresses as > @@ -244,6 +250,111 @@ static void assign_bars(struct npu2 *npu) > npu->mm_size = last_bar.base + last_bar.size - npu->mm_base; > } > > +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; > + case 23: name = "Translate Fail (brick 2)"; break; > + case 24: name = "Translate Fail (brick 3)"; break; > + case 25: name = "Translate Fail (brick 4)"; break; > + case 26: name = "Translate Fail (brick 5)"; break; > + case 27: name = "OTL Event (brick 2)"; break; > + case 28: name = "OTL Event (brick 3)"; break; > + case 29: name = "OTL Event (brick 4)"; break; > + case 30: name = "OTL Event (brick 5)"; break; > + case 31: name = "XSL Event (brick 2)"; break; > + case 32: name = "XSL Event (brick 3)"; break; > + case 33: name = "XSL Event (brick 4)"; break; > + case 34: name = "XSL Event (brick 5)"; 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\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; > @@ -421,6 +532,7 @@ static void setup_devices(struct npu2 *npu) > } > > assign_bars(npu); > + setup_irqs(npu); > > if (nvlink_detected) > npu2_nvlink_init_npu(npu); > diff --git a/hw/npu2-opencapi.c b/hw/npu2-opencapi.c > index cc7c403351ce..dd40b24009f3 100644 > --- a/hw/npu2-opencapi.c > +++ b/hw/npu2-opencapi.c > @@ -48,11 +48,9 @@ > #include <npu2.h> > #include <npu2-regs.h> > #include <phys-map.h> > -#include <xive.h> > #include <i2c.h> > #include <nvram.h> > > -#define NPU_IRQ_LEVELS 35 > #define NPU_IRQ_LEVELS_XSL 23 > #define MAX_PE_HANDLE ((1 << 15) - 1) > #define TL_MAX_TEMPLATE 63 > @@ -1383,7 +1381,7 @@ static int npu2_add_mmio_regs(struct phb *phb, struct pci_device *pd, > * Pass the hw irq number for the translation fault irq > * irq levels 23 -> 26 are for translation faults, 1 per brick > */ > - irq = dev->npu->irq_base + NPU_IRQ_LEVELS_XSL; > + irq = dev->npu->base_lsi + NPU_IRQ_LEVELS_XSL; > if (stacku == NPU2_STACK_STCK_2U) > irq += 2; > if (block == NPU2_BLOCK_OTL1) > @@ -1456,43 +1454,9 @@ static void mask_nvlink_fir(struct npu2 *p) > NPU2_MISC_IRQ_ENABLE1, NPU2_MISC_DA_LEN_8B, reg); > } > > -static int setup_irq(struct npu2 *p) > +static int enable_xsl_irq(struct npu2 *p) > { > - uint64_t reg, mmio_addr; > - uint32_t base; > - > - base = xive_alloc_ipi_irqs(p->chip_id, NPU_IRQ_LEVELS, 64); > - if (base == XIVE_IRQ_ERROR) { > - /** > - * @fwts-label OCAPIIRQAllocationFailed > - * @fwts-advice OpenCAPI IRQ setup failed. This is probably > - * a firmware bug. OpenCAPI functionality will be broken. > - */ > - prlog(PR_ERR, "OCAPI: Couldn't allocate interrupts for NPU\n"); > - return -1; > - } > - p->irq_base = base; > - > - xive_register_ipi_source(base, NPU_IRQ_LEVELS, NULL, NULL); > - mmio_addr = (uint64_t ) xive_get_trigger_port(base); > - prlog(PR_DEBUG, "OCAPI: NPU base irq %d @%llx\n", base, mmio_addr); > - reg = (mmio_addr & NPU2_MISC_IRQ_BASE_MASK) << 13; > - npu2_scom_write(p->chip_id, p->xscom_base, NPU2_MISC_IRQ_BASE, > - NPU2_MISC_DA_LEN_8B, reg); > - /* > - * setup page size = 64k > - * > - * OS type is set to AIX: opal also runs with 2 pages per interrupt, > - * so to cover the max offset for 35 levels of interrupt, we need > - * bits 41 to 46, which is what the AIX setting does. There's no > - * other meaning for that AIX setting. > - */ > - reg = npu2_scom_read(p->chip_id, p->xscom_base, NPU2_MISC_CFG, > - NPU2_MISC_DA_LEN_8B); > - reg |= NPU2_MISC_CFG_IPI_PS; > - reg &= ~NPU2_MISC_CFG_IPI_OS; > - npu2_scom_write(p->chip_id, p->xscom_base, NPU2_MISC_CFG, > - NPU2_MISC_DA_LEN_8B, reg); > + uint64_t reg; > > /* enable translation interrupts for all bricks */ > reg = npu2_scom_read(p->chip_id, p->xscom_base, NPU2_MISC_IRQ_ENABLE2, > @@ -1619,7 +1583,6 @@ static void read_nvram_training_state(void) > int npu2_opencapi_init_npu(struct npu2 *npu) > { > struct npu2_dev *dev; > - int rc; > > assert(platform.ocapi); > read_nvram_training_state(); > @@ -1645,10 +1608,7 @@ int npu2_opencapi_init_npu(struct npu2 *npu) > address_translation_config(npu->chip_id, npu->xscom_base, dev->brick_index); > } > > - /* Procedure 13.1.3.10 - Interrupt Configuration */ > - rc = setup_irq(npu); > - if (rc) > - goto failed; > + enable_xsl_irq(npu); > > for (int i = 0; i < npu->total_devices; i++) { > dev = &npu->devices[i]; > @@ -1658,8 +1618,6 @@ int npu2_opencapi_init_npu(struct npu2 *npu) > } > > return 0; > -failed: > - return -1; > } > > static const struct phb_ops npu2_opencapi_ops = { > diff --git a/hw/npu2.c b/hw/npu2.c > index 9e2c7d5fdda4..8a4611424609 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> > @@ -36,14 +35,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 > @@ -1780,99 +1774,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; > @@ -1887,7 +1788,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_configure_devices(npu); > npu2_add_interrupt_map(npu); > npu2_add_phb_properties(npu); > diff --git a/include/npu2.h b/include/npu2.h > index 64be9f4eb9dd..9eb436db524a 100644 > --- a/include/npu2.h > +++ b/include/npu2.h > @@ -155,7 +155,6 @@ struct npu2 { > uint64_t mm_base; > uint64_t mm_size; > uint32_t base_lsi; > - uint32_t irq_base; > uint32_t total_devices; > struct npu2_dev *devices; > enum phys_map_type gpu_map_type; >
diff --git a/hw/npu2-common.c b/hw/npu2-common.c index 6cbae9bffaf9..8edf761cf56b 100644 --- a/hw/npu2-common.c +++ b/hw/npu2-common.c @@ -24,6 +24,12 @@ #include <nvram.h> #include <i2c.h> #include <phys-map.h> +#include <interrupts.h> +#include <xive.h> + +#define NPU2_IRQ_BASE_SHIFT 13 +#define NPU2_N_DL_IRQS 35 +#define NPU2_N_DL_IRQS_ALIGN 64 /* * We use the indirect method because it uses the same addresses as @@ -244,6 +250,111 @@ static void assign_bars(struct npu2 *npu) npu->mm_size = last_bar.base + last_bar.size - npu->mm_base; } +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; + case 23: name = "Translate Fail (brick 2)"; break; + case 24: name = "Translate Fail (brick 3)"; break; + case 25: name = "Translate Fail (brick 4)"; break; + case 26: name = "Translate Fail (brick 5)"; break; + case 27: name = "OTL Event (brick 2)"; break; + case 28: name = "OTL Event (brick 3)"; break; + case 29: name = "OTL Event (brick 4)"; break; + case 30: name = "OTL Event (brick 5)"; break; + case 31: name = "XSL Event (brick 2)"; break; + case 32: name = "XSL Event (brick 3)"; break; + case 33: name = "XSL Event (brick 4)"; break; + case 34: name = "XSL Event (brick 5)"; 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\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; @@ -421,6 +532,7 @@ static void setup_devices(struct npu2 *npu) } assign_bars(npu); + setup_irqs(npu); if (nvlink_detected) npu2_nvlink_init_npu(npu); diff --git a/hw/npu2-opencapi.c b/hw/npu2-opencapi.c index cc7c403351ce..dd40b24009f3 100644 --- a/hw/npu2-opencapi.c +++ b/hw/npu2-opencapi.c @@ -48,11 +48,9 @@ #include <npu2.h> #include <npu2-regs.h> #include <phys-map.h> -#include <xive.h> #include <i2c.h> #include <nvram.h> -#define NPU_IRQ_LEVELS 35 #define NPU_IRQ_LEVELS_XSL 23 #define MAX_PE_HANDLE ((1 << 15) - 1) #define TL_MAX_TEMPLATE 63 @@ -1383,7 +1381,7 @@ static int npu2_add_mmio_regs(struct phb *phb, struct pci_device *pd, * Pass the hw irq number for the translation fault irq * irq levels 23 -> 26 are for translation faults, 1 per brick */ - irq = dev->npu->irq_base + NPU_IRQ_LEVELS_XSL; + irq = dev->npu->base_lsi + NPU_IRQ_LEVELS_XSL; if (stacku == NPU2_STACK_STCK_2U) irq += 2; if (block == NPU2_BLOCK_OTL1) @@ -1456,43 +1454,9 @@ static void mask_nvlink_fir(struct npu2 *p) NPU2_MISC_IRQ_ENABLE1, NPU2_MISC_DA_LEN_8B, reg); } -static int setup_irq(struct npu2 *p) +static int enable_xsl_irq(struct npu2 *p) { - uint64_t reg, mmio_addr; - uint32_t base; - - base = xive_alloc_ipi_irqs(p->chip_id, NPU_IRQ_LEVELS, 64); - if (base == XIVE_IRQ_ERROR) { - /** - * @fwts-label OCAPIIRQAllocationFailed - * @fwts-advice OpenCAPI IRQ setup failed. This is probably - * a firmware bug. OpenCAPI functionality will be broken. - */ - prlog(PR_ERR, "OCAPI: Couldn't allocate interrupts for NPU\n"); - return -1; - } - p->irq_base = base; - - xive_register_ipi_source(base, NPU_IRQ_LEVELS, NULL, NULL); - mmio_addr = (uint64_t ) xive_get_trigger_port(base); - prlog(PR_DEBUG, "OCAPI: NPU base irq %d @%llx\n", base, mmio_addr); - reg = (mmio_addr & NPU2_MISC_IRQ_BASE_MASK) << 13; - npu2_scom_write(p->chip_id, p->xscom_base, NPU2_MISC_IRQ_BASE, - NPU2_MISC_DA_LEN_8B, reg); - /* - * setup page size = 64k - * - * OS type is set to AIX: opal also runs with 2 pages per interrupt, - * so to cover the max offset for 35 levels of interrupt, we need - * bits 41 to 46, which is what the AIX setting does. There's no - * other meaning for that AIX setting. - */ - reg = npu2_scom_read(p->chip_id, p->xscom_base, NPU2_MISC_CFG, - NPU2_MISC_DA_LEN_8B); - reg |= NPU2_MISC_CFG_IPI_PS; - reg &= ~NPU2_MISC_CFG_IPI_OS; - npu2_scom_write(p->chip_id, p->xscom_base, NPU2_MISC_CFG, - NPU2_MISC_DA_LEN_8B, reg); + uint64_t reg; /* enable translation interrupts for all bricks */ reg = npu2_scom_read(p->chip_id, p->xscom_base, NPU2_MISC_IRQ_ENABLE2, @@ -1619,7 +1583,6 @@ static void read_nvram_training_state(void) int npu2_opencapi_init_npu(struct npu2 *npu) { struct npu2_dev *dev; - int rc; assert(platform.ocapi); read_nvram_training_state(); @@ -1645,10 +1608,7 @@ int npu2_opencapi_init_npu(struct npu2 *npu) address_translation_config(npu->chip_id, npu->xscom_base, dev->brick_index); } - /* Procedure 13.1.3.10 - Interrupt Configuration */ - rc = setup_irq(npu); - if (rc) - goto failed; + enable_xsl_irq(npu); for (int i = 0; i < npu->total_devices; i++) { dev = &npu->devices[i]; @@ -1658,8 +1618,6 @@ int npu2_opencapi_init_npu(struct npu2 *npu) } return 0; -failed: - return -1; } static const struct phb_ops npu2_opencapi_ops = { diff --git a/hw/npu2.c b/hw/npu2.c index 9e2c7d5fdda4..8a4611424609 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> @@ -36,14 +35,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 @@ -1780,99 +1774,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; @@ -1887,7 +1788,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_configure_devices(npu); npu2_add_interrupt_map(npu); npu2_add_phb_properties(npu); diff --git a/include/npu2.h b/include/npu2.h index 64be9f4eb9dd..9eb436db524a 100644 --- a/include/npu2.h +++ b/include/npu2.h @@ -155,7 +155,6 @@ struct npu2 { uint64_t mm_base; uint64_t mm_size; uint32_t base_lsi; - uint32_t irq_base; uint32_t total_devices; struct npu2_dev *devices; enum phys_map_type gpu_map_type;