[Skiboot] [PATCH RFC 1/1] npu2: Enable recoverable data link (no-stall) interrupts
Sam Bobroff
sam.bobroff at au1.ibm.com
Fri Aug 18 10:46:10 AEST 2017
On Thu, Aug 17, 2017 at 05:03:08PM +1000, Alistair Popple wrote:
> Hi Sam,
>
> This looks pretty good except for one minor simplification below. I also can't
> help but think it would be better if we split the patch up into three - one to
> enable the IRQs, one to add the vendor space misc_irq_request stuff and another
> with NPU->NPU2 name changes to keep the history clean.
OK, will do. I'll repost ASAP.
> Thanks!
>
> Regards,
>
> Alistair
>
> On Wed, 16 Aug 2017 12:37:40 PM Sam Bobroff wrote:
> > Allow the NPU2 to trigger "recoverable data link" interrupts
> > and provide a way to test them via a new vendor capability.
> >
> > Signed-off-by: Sam Bobroff <sam.bobroff at au1.ibm.com>
> > ---
>
> >
> > +static void npu2_add_interrupt_map(struct npu2 *p,
> > + struct dt_node *dn)
> > +{
> > + struct dt_node *npu2_dn, *link, *phb_dn;
> > + uint32_t npu2_phandle, index = 0, i;
> > + uint32_t icsp = get_ics_phandle();
> > + uint32_t *map;
> > + size_t map_size;
> > + uint32_t mask[] = {0xff00, 0x0, 0x0, 0x7};
> > + int nlinks = 0;
> > +
> > + npu2_phandle = dt_prop_get_u32(dn, "ibm,npcq");
> > + assert((npu2_dn = dt_find_by_phandle(dt_root, npu2_phandle)));
> > + assert((phb_dn = p->phb.dt_node));
> > + dt_for_each_compatible(npu2_dn, link, "ibm,npu-link") {
> > + nlinks++;
> > + }
>
> You could just use p->total_devices here.
Ah thanks :-)
> > + map_size = 7 * sizeof(*map) * nlinks;
> > + map = malloc(map_size);
> > + index = 0;
> > + dt_for_each_compatible(npu2_dn, link, "ibm,npu-link") {
> > + i = index * 7;
> > + map[i + 0] = (p->devices[index].bdfn << 8);
> > + map[i + 1] = 0;
> > + map[i + 2] = 0;
> > +
> > + map[i + 3] = 1; /* INT A */
> > + map[i + 4] = icsp; /* interrupt-parent */
> > + map[i + 5] = p->base_lsi + (index * 2) + 1; /* NDL No-Stall Event */
> > + map[i + 6] = 0; /* 0 = EDGE, 1 = LEVEL. */
> > + index++;
> > + }
> > + dt_add_property(phb_dn, "interrupt-map", map, map_size);
> > + free(map);
> > + dt_add_property(phb_dn, "interrupt-map-mask", mask, sizeof(mask));
> > +}
> > +
> > static void npu2_add_phb_properties(struct npu2 *p)
> > {
> > struct dt_node *np = p->phb.dt_node;
> > @@ -1617,7 +1682,7 @@ static void npu2_add_phb_properties(struct npu2 *p)
> > dt_add_property_cells(np, "clock-frequency", 0x200, 0);
> > dt_add_property_cells(np, "interrupt-parent", icsp);
> >
> > - /* NPU PHB properties */
> > + /* NPU2 PHB properties */
> > dt_add_property_cells(np, "ibm,opal-num-pes",
> > NPU2_MAX_PE_NUM);
> > dt_add_property_cells(np, "ibm,opal-reserved-pe",
> > @@ -1641,6 +1706,77 @@ 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)
> > +{
> > + 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 const struct irq_source_ops npu2_ipi_ops = {
> > + .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, "NPU2: 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 void npu2_create_phb(struct dt_node *dn)
> > {
> > const struct dt_property *prop;
> > @@ -1678,7 +1814,9 @@ static void npu2_create_phb(struct dt_node *dn)
> > list_head_init(&p->phb.devices);
> > list_head_init(&p->phb.virt_devices);
> >
> > + npu2_setup_irqs(p);
> > npu2_populate_devices(p, dn);
> > + npu2_add_interrupt_map(p, dn);
> > npu2_add_phb_properties(p);
> >
> > slot = npu2_slot_create(&p->phb);
> > @@ -1687,9 +1825,9 @@ static void npu2_create_phb(struct dt_node *dn)
> > /**
> > * @fwts-label NPUCannotCreatePHBSlot
> > * @fwts-advice Firmware probably ran out of memory creating
> > - * NPU slot. NVLink functionality could be broken.
> > + * NPU2 slot. NVLink functionality could be broken.
> > */
> > - prlog(PR_ERR, "NPU: Cannot create PHB slot\n");
> > + prlog(PR_ERR, "NPU2: Cannot create PHB slot\n");
> > }
> >
> > pci_register_phb(&p->phb, OPAL_DYNAMIC_PHB_ID);
> > @@ -1710,7 +1848,7 @@ void probe_npu2(void)
> > prlog(PR_WARNING, "NPU2: Using ZCAL impedance override = %d\n", nv_zcal_nominal);
> > }
> >
> > - /* Scan NPU XSCOM nodes */
> > + /* Scan NPU2 XSCOM nodes */
> > dt_for_each_compatible(dt_root, np, "ibm,power9-npu")
> > npu2_probe_phb(np);
> >
> > diff --git a/include/npu2-regs.h b/include/npu2-regs.h
> > index 86e2658a..759404cc 100644
> > --- a/include/npu2-regs.h
> > +++ b/include/npu2-regs.h
> > @@ -286,6 +286,16 @@ void npu2_write_mask(struct npu2 *p, uint64_t reg, uint64_t val, uint64_t mask);
> > #define NPU2_MISC_ERR_RPT_HOLD NPU2_REG_OFFSET(NPU2_STACK_MISC, NPU2_BLOCK_MISC, 0x020)
> > #define NPU2_MISC_ERR_RPT_MASK NPU2_REG_OFFSET(NPU2_STACK_MISC, NPU2_BLOCK_MISC, 0x028)
> > #define NPU2_MISC_CFG NPU2_REG_OFFSET(NPU2_STACK_MISC, NPU2_BLOCK_MISC, 0x030)
> > +#define NPU2_MISC_CFG_CONFIG_SYNC_WAIT PPC_BITMASK(0,4)
> > +#define NPU2_MISC_CFG_PERF_CONFIG_ENABLE PPC_BIT(5)
> > +#define NPU2_MISC_CFG_PERF_CONFIG_PE_MASK PPC_BIT(6)
> > +#define NPU2_MISC_CFG_PERF_CONFIG_PE_MATCH PPC_BITMASK(7,10)
> > +#define NPU2_MISC_CFG_IPI_PS PPC_BIT(11)
> > +#define NPU2_MISC_CFG_IPI_PS_4K 0
> > +#define NPU2_MISC_CFG_IPI_PS_64K 1
> > +#define NPU2_MISC_CFG_IPI_OS PPC_BIT(12)
> > +#define NPU2_MISC_CFG_IPI_OS_AIX 0
> > +#define NPU2_MISC_CFG_IPI_OS_LINUX 1
> > #define NPU2_MISC_INHIBIT_CFG NPU2_REG_OFFSET(NPU2_STACK_MISC, NPU2_BLOCK_MISC, 0x038)
> > #define NPU2_MISC_FREEZE_ENABLE0 NPU2_REG_OFFSET(NPU2_STACK_MISC, NPU2_BLOCK_MISC, 0x040)
> > #define NPU2_MISC_FREEZE_ENABLE1 NPU2_REG_OFFSET(NPU2_STACK_MISC, NPU2_BLOCK_MISC, 0x048)
> >
More information about the Skiboot
mailing list