Index: dev/pci_machdep.c =================================================================== RCS file: /cvs/src/sys/arch/sparc64/dev/pci_machdep.c,v retrieving revision 1.46 diff -u -p -r1.46 pci_machdep.c --- dev/pci_machdep.c 27 Dec 2018 11:04:41 -0000 1.46 +++ dev/pci_machdep.c 3 Jun 2019 03:25:52 -0000 @@ -395,10 +436,16 @@ pci_intr_map(pa, ihp) /* XXXX -- we use the ino. What if there is a valid IGN? */ *ihp = interrupts[0]; - if (pa->pa_pc->intr_map) - return ((*pa->pa_pc->intr_map)(pa, ihp)); - else - return (0); + if (pa->pa_pc->intr_map) { + int rv = (*pa->pa_pc->intr_map)(pa, ihp); + if (rv != 0) + return (rv); + } + + if ((*ihp & PCI_INTR_TYPE) != PCI_INTR_INTX) + return (EADDRNOTAVAIL); + + return (0); } int @@ -416,6 +463,30 @@ pci_intr_map_msi(struct pci_attach_args } int +pci_intr_map_msix(struct pci_attach_args *pa, int vec, pci_intr_handle_t *ihp) +{ + pci_chipset_tag_t pc = pa->pa_pc; + pcitag_t tag = pa->pa_tag; + pcireg_t reg; + + if (vec & ~PCITAG_VEC_MASK) + return (-1); + + if ((pa->pa_flags & PCI_FLAGS_MSI_ENABLED) == 0 || + pci_get_capability(pc, tag, PCI_CAP_MSIX, NULL, ®) == 0) + return (-1); + + if (vec > PCI_MSIX_MC_TBLSZ(reg)) + return (-1); + + KASSERT(!ISSET(pa->pa_tag, PCI_INTR_TYPE)); + KASSERT(!ISSET(pa->pa_tag, PCITAG_VEC_MASK)); + + *ihp = PCI_INTR_MSIX | PCITAG_OFFSET(pa->pa_tag) | vec; + return (0); +} + +int pci_intr_line(pci_chipset_tag_t pc, pci_intr_handle_t ih) { return (ih); @@ -429,7 +500,9 @@ pci_intr_string(pc, ih) static char str[16]; DPRINTF(SPDB_INTR, ("pci_intr_string: ih %u", ih)); - if (ih & PCI_INTR_MSI) + if (ih & PCI_INTR_MSIX) + snprintf(str, sizeof str, "msix"); /* %u vec? */ + else if (ih & PCI_INTR_MSI) snprintf(str, sizeof str, "msi"); else snprintf(str, sizeof str, "ivec 0x%llx", INTVEC(ih)); @@ -495,3 +568,44 @@ pci_msi_enable(pci_chipset_tag_t pc, pci } pci_conf_write(pc, tag, off, reg | PCI_MSI_MC_MSIE); } + +void +pci_msix_enable(pci_chipset_tag_t pc, pcitag_t tag, bus_space_tag_t memt, + int vec, bus_addr_t addr, uint32_t data) +{ + bus_space_handle_t memh; + bus_addr_t base; + pcireg_t reg, table, type; + uint32_t ctrl; + int bir, offset; + int off, tblsz; + + if (pci_get_capability(pc, tag, PCI_CAP_MSIX, &off, ®) == 0) + panic("%s: no msix capability", __func__); + + table = pci_conf_read(pc, tag, off + PCI_MSIX_TABLE); + bir = (table & PCI_MSIX_TABLE_BIR); + offset = (table & PCI_MSIX_TABLE_OFF); + tblsz = PCI_MSIX_MC_TBLSZ(reg) + 1; + + bir = PCI_MAPREG_START + bir * 4; + type = pci_mapreg_type(pc, tag, bir); + if (pci_mapreg_info(pc, tag, bir, type, &base, NULL, NULL)) + panic("%s: cannot get info for %u", __func__, bir); + if (bus_space_map(memt, base + offset, tblsz * 16, 0, &memh)) + panic("%s: cannot map registers", __func__); + + bus_space_write_4(memt, memh, PCI_MSIX_MA(vec), addr); + bus_space_write_4(memt, memh, PCI_MSIX_MAU32(vec), addr >> 32); + bus_space_write_4(memt, memh, PCI_MSIX_MD(vec), data); + bus_space_barrier(memt, memh, PCI_MSIX_MA(vec), 16, + BUS_SPACE_BARRIER_WRITE); + ctrl = bus_space_read_4(memt, memh, PCI_MSIX_VC(vec)); + bus_space_write_4(memt, memh, PCI_MSIX_VC(vec), + ctrl & ~PCI_MSIX_VC_MASK); + + bus_space_unmap(memt, memh, tblsz * 16); + + pci_conf_write(pc, tag, off, reg | PCI_MSIX_MC_MSIXE); +} + Index: dev/pyro.c =================================================================== RCS file: /cvs/src/sys/arch/sparc64/dev/pyro.c,v retrieving revision 1.31 diff -u -p -r1.31 pyro.c --- dev/pyro.c 25 May 2017 03:19:39 -0000 1.31 +++ dev/pyro.c 3 Jun 2019 03:25:52 -0000 @@ -611,9 +648,9 @@ pyro_intr_establish(bus_space_tag_t t, b volatile u_int64_t *intrmapptr = NULL, *intrclrptr = NULL; int ino; - if (ihandle & PCI_INTR_MSI) { + if ((ihandle & PCI_INTR_TYPE) != PCI_INTR_INTX) { pci_chipset_tag_t pc = pbm->pp_pc; - pcitag_t tag = ihandle & ~PCI_INTR_MSI; + pcitag_t tag = ihandle & ~(PCI_INTR_TYPE | PCITAG_VEC_MASK); int msinum = pbm->pp_msinum++; u_int64_t reg; @@ -632,7 +669,15 @@ pyro_intr_establish(bus_space_tag_t t, b if (flags & BUS_INTR_ESTABLISH_MPSAFE) ih->ih_mpsafe = 1; - pci_msi_enable(pc, tag, pbm->pp_msiaddr, msinum); + switch (ihandle & PCI_INTR_TYPE) { + case PCI_INTR_MSI: + pci_msi_enable(pc, tag, pbm->pp_msiaddr, msinum); + break; + case PCI_INTR_MSIX: + pci_msix_enable(pc, tag, pbm->pp_memt, + PCITAG_VEC(ihandle), pbm->pp_msiaddr, msinum); + break; + } /* Map MSI to the right EQ and mark it as valid. */ reg = bus_space_read_8(sc->sc_bust, sc->sc_csrh, Index: dev/vpci.c =================================================================== RCS file: /cvs/src/sys/arch/sparc64/dev/vpci.c,v retrieving revision 1.24 diff -u -p -r1.24 vpci.c --- dev/vpci.c 22 Dec 2017 15:52:36 -0000 1.24 +++ dev/vpci.c 3 Jun 2019 03:25:52 -0000 @@ -516,6 +532,9 @@ vpci_intr_establish(bus_space_tag_t t, b uint64_t sysino = INTVEC(ihandle); struct intrhand *ih; int err; + + if (ihandle & PCI_INTR_MSIX) + return (NULL); ih = bus_intr_allocate(t0, handler, arg, ihandle, level, NULL, NULL, what); Index: include/pci_machdep.h =================================================================== RCS file: /cvs/src/sys/arch/sparc64/include/pci_machdep.h,v retrieving revision 1.33 diff -u -p -r1.33 pci_machdep.h --- include/pci_machdep.h 4 May 2016 14:30:01 -0000 1.33 +++ include/pci_machdep.h 3 Jun 2019 03:39:54 -0000 @@ -43,7 +43,10 @@ struct pci_attach_args; typedef struct sparc_pci_chipset *pci_chipset_tag_t; +#define PCI_INTR_INTX 0x00000000 #define PCI_INTR_MSI 0x80000000 +#define PCI_INTR_MSIX 0x40000000 +#define PCI_INTR_TYPE 0xc0000000 typedef u_int pci_intr_handle_t; /* @@ -60,6 +63,8 @@ typedef u_int pci_intr_handle_t; #define PCITAG_BUS(t) ((PCITAG_OFFSET(t)>>16)&0xff) #define PCITAG_DEV(t) ((PCITAG_OFFSET(t)>>11)&0x1f) #define PCITAG_FUN(t) ((PCITAG_OFFSET(t)>>8)&0x7) +#define PCITAG_VEC_MASK 0xff +#define PCITAG_VEC(t) ((PCITAG_OFFSET(t)>>0) & PCITAG_VEC_MASK) #define PCITAG_CREATE(n,b,d,f) (((u_int64_t)(n)<<32)|((b)<<16)|((d)<<11)|((f)<<8)) #define PCITAG_SETNODE(t,n) ((t)&0xffffffff)|(((n)<<32) typedef u_int64_t pcitag_t; @@ -88,7 +96,8 @@ void pci_conf_write(pci_chipset_tag_t, pcireg_t); int pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *); int pci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *); -#define pci_intr_map_msix(pa, vec, ihp) (-1) +int pci_intr_map_msix(struct pci_attach_args *, int, + pci_intr_handle_t *); int pci_intr_line(pci_chipset_tag_t, pci_intr_handle_t); const char *pci_intr_string(pci_chipset_tag_t, pci_intr_handle_t); void *pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t, @@ -96,6 +105,8 @@ void *pci_intr_establish(pci_chipset_ta void pci_intr_disestablish(pci_chipset_tag_t, void *); void pci_msi_enable(pci_chipset_tag_t, pcitag_t, bus_addr_t, int); +void pci_msix_enable(pci_chipset_tag_t, pcitag_t, bus_space_tag_t, + int, bus_addr_t, uint32_t); int sparc64_pci_enumerate_bus(struct pci_softc *, int (*match)(struct pci_attach_args *),