On Fri, Jun 17, 2022 at 10:38:08AM +0200, Mark Kettenis wrote:
> > Date: Fri, 17 Jun 2022 17:22:58 +1000
> > From: Jonathan Gray <[email protected]>
> > 
> > On Fri, Jun 17, 2022 at 12:33:47AM +0200, Mark Kettenis wrote:
> > > 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?
> > > 
> > 
> > ok jsg@
> > 
> > Linux and NetBSD also handle additional types as downstream.
> > Referred to in the pcie base spec as:
> > 
> > 0100b Root Port of PCI Express Root Complex*
> > 1000b PCI/PCI-X to PCI Express Bridge*
> > 
> > *This value is only valid for Functions that implement a Type
> > 01h PCI Configuration Space header.
> > 
> > FreeBSD also checks for Root Port but not the bridge.
> 
> Ah, I missed that Linux also checks for the root port.  That's
> probably a good idea.  The PCI-PCIe bridge is probably rare enough not
> to matter, but lets align with Linux and NetBSD here.
> 
> How about this?

sure, still ok with this version

> 
> 
> 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     17 Jun 2022 08:34:30 -0000
> @@ -807,11 +807,31 @@ 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 and root 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)) {
> +             switch (PCI_PCIE_XCAP_TYPE(cap)) {
> +             case PCI_PCIE_XCAP_TYPE_RP:
> +             case PCI_PCIE_XCAP_TYPE_DOWN:
> +             case PCI_PCIE_XCAP_TYPE_PCI2PCIE:
> +                     maxndevs = 1;
> +                     break;
> +             }
> +     }
> +
> +     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  17 Jun 2022 08:34:30 -0000
> @@ -563,6 +563,10 @@ 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_RP               0x4
> +#define  PCI_PCIE_XCAP_TYPE_DOWN     0x6
> +#define  PCI_PCIE_XCAP_TYPE_PCI2PCIE 0x8
>  #define PCI_PCIE_DCAP                0x04
>  #define PCI_PCIE_DCSR                0x08
>  #define PCI_PCIE_DCSR_ERO    0x00000010
> 

Reply via email to