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 22:17:49 -0000 @@ -395,10 +436,15 @@ 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); + } + + KASSERT(PCI_INTR_TYPE(*ihp) == PCI_INTR_INTX); + + return (0); } int @@ -416,6 +462,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 & ~PCI_INTR_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_MASK)); + KASSERT(!ISSET(pa->pa_tag, PCI_INTR_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); @@ -427,15 +497,23 @@ pci_intr_string(pc, ih) pci_intr_handle_t ih; { static char str[16]; + const char *rv = str; DPRINTF(SPDB_INTR, ("pci_intr_string: ih %u", ih)); - if (ih & PCI_INTR_MSI) - snprintf(str, sizeof str, "msi"); - else + switch (PCI_INTR_TYPE(ih)) { + case PCI_INTR_MSIX: + rv = "msix"; + break; + case PCI_INTR_MSI: + rv = "msi"; + break; + case PCI_INTR_INTX: snprintf(str, sizeof str, "ivec 0x%llx", INTVEC(ih)); - DPRINTF(SPDB_INTR, ("; returning %s\n", str)); + break; + } + DPRINTF(SPDB_INTR, ("; returning %s\n", rv)); - return (str); + return (rv); } void * @@ -495,3 +573,43 @@ 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) || + 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 22:17:49 -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 (PCI_INTR_TYPE(ihandle) != PCI_INTR_INTX) { pci_chipset_tag_t pc = pbm->pp_pc; - pcitag_t tag = ihandle & ~PCI_INTR_MSI; + pcitag_t tag = PCI_INTR_TAG(ihandle); 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 (PCI_INTR_TYPE(ihandle)) { + 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, + PCI_INTR_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 22:17:49 -0000 @@ -525,9 +525,9 @@ vpci_intr_establish(bus_space_tag_t t, b if (flags & BUS_INTR_ESTABLISH_MPSAFE) ih->ih_mpsafe = 1; - if (ihandle & PCI_INTR_MSI) { + if (PCI_INTR_TYPE(ihandle) != PCI_INTR_INTX) { pci_chipset_tag_t pc = pbm->vp_pc; - pcitag_t tag = ihandle & ~PCI_INTR_MSI; + pcitag_t tag = PCI_INTR_TAG(ihandle); int msinum = pbm->vp_msinum++; evcount_attach(&ih->ih_count, ih->ih_name, NULL); @@ -537,7 +537,15 @@ vpci_intr_establish(bus_space_tag_t t, b pbm->vp_msi[msinum] = ih; ih->ih_number = msinum; - pci_msi_enable(pc, tag, pbm->vp_msiaddr, msinum); + switch (PCI_INTR_TYPE(ihandle)) { + case PCI_INTR_MSI: + pci_msi_enable(pc, tag, pbm->vp_msiaddr, msinum); + break; + case PCI_INTR_MSIX: + pci_msix_enable(pc, tag, pbm->vp_memt, + PCI_INTR_VEC(ihandle), pbm->vp_msiaddr, msinum); + break; + } err = hv_pci_msi_setmsiq(pbm->vp_devhandle, msinum, 0, 0); if (err != H_EOK) { 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 22:17:49 -0000 @@ -43,7 +43,17 @@ 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_MASK 0xc0000000 +#define PCI_INTR_TYPE(_ih) ((_ih) & PCI_INTR_TYPE_MASK) + +#define PCI_INTR_TAG_MASK 0x00ffff00 +#define PCI_INTR_TAG(_ih) ((_ih) & PCI_INTR_TAG_MASK) + +#define PCI_INTR_VEC_MASK 0x000000ff +#define PCI_INTR_VEC(_ih) ((_ih) & PCI_INTR_VEC_MASK) typedef u_int pci_intr_handle_t; /* @@ -74,10 +84,13 @@ struct sparc_pci_chipset { pcireg_t (*conf_read)(pci_chipset_tag_t, pcitag_t, int); void (*conf_write)(pci_chipset_tag_t, pcitag_t, int, pcireg_t); int (*intr_map)(struct pci_attach_args *, pci_intr_handle_t *); + int (*probe_device_hook)(void *, struct pci_attach_args *); }; void pci_attach_hook(struct device *, struct device *, struct pcibus_attach_args *); +int pci_probe_device_hook(pci_chipset_tag_t, + struct pci_attach_args *); int pci_bus_maxdevs(pci_chipset_tag_t, int); pcitag_t pci_make_tag(pci_chipset_tag_t, int, int, int); void pci_decompose_tag(pci_chipset_tag_t, pcitag_t, int *, int *, @@ -88,7 +101,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 +110,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 *),