On the Ampere Altra machines, some PCIe devices show up 32 times; once for each possible PCI device number. This is a hardware bug, since a downstream switch port (or root port) is supposed to terminate configuration request targeted at device numbers 1-31. But it is a somewhat common bug since I have seen this before on other hardware. Linux and FreeBSD both have code that only scans device 0 on downstream switch ports. So let's do that in OpenBSD as well.
ok? Index: dev/pci/pci.c =================================================================== RCS file: /cvs/src/sys/dev/pci/pci.c,v retrieving revision 1.124 diff -u -p -r1.124 pci.c --- dev/pci/pci.c 11 Mar 2022 18:00:51 -0000 1.124 +++ dev/pci/pci.c 16 Jun 2022 22:27:35 -0000 @@ -807,11 +807,25 @@ pci_enumerate_bus(struct pci_softc *sc, { pci_chipset_tag_t pc = sc->sc_pc; int device, function, nfunctions, ret; + int maxndevs = sc->sc_maxndevs; const struct pci_quirkdata *qd; - pcireg_t id, bhlcr; + pcireg_t id, bhlcr, cap; pcitag_t tag; - for (device = 0; device < sc->sc_maxndevs; device++) { + /* + * PCIe downstream ports should only forward configuration + * requests for device number 0. However, not all hardware + * implements this correctly, and some devices will respond to + * other device numbers making the device show up 32 times. + * Prevent this by only scanning a single device. + */ + if (sc->sc_bridgetag && pci_get_capability(pc, *sc->sc_bridgetag, + PCI_CAP_PCIEXPRESS, NULL, &cap)) { + if (PCI_PCIE_XCAP_TYPE(cap) == PCI_PCIE_XCAP_TYPE_DOWN) + maxndevs = 1; + } + + for (device = 0; device < maxndevs; device++) { tag = pci_make_tag(pc, sc->sc_bus, device, 0); bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); Index: dev/pci/pcireg.h =================================================================== RCS file: /cvs/src/sys/dev/pci/pcireg.h,v retrieving revision 1.60 diff -u -p -r1.60 pcireg.h --- dev/pci/pcireg.h 31 Dec 2021 11:24:24 -0000 1.60 +++ dev/pci/pcireg.h 16 Jun 2022 22:27:35 -0000 @@ -563,6 +563,8 @@ typedef u_int8_t pci_revision_t; #define PCI_PCIE_XCAP 0x00 #define PCI_PCIE_XCAP_SI 0x01000000 #define PCI_PCIE_XCAP_VER(x) (((x) >> 16) & 0x0f) +#define PCI_PCIE_XCAP_TYPE(x) (((x) >> 20) & 0x0f) +#define PCI_PCIE_XCAP_TYPE_DOWN 0x6 #define PCI_PCIE_DCAP 0x04 #define PCI_PCIE_DCSR 0x08 #define PCI_PCIE_DCSR_ERO 0x00000010