> Date: Thu, 6 Sep 2012 11:24:01 +0200
> From: Christian Ehrhardt <ehrha...@genua.de>
> 
> Hi,
> 
> most modern x86 hardware includes more than one PCI root segement.
> E.g. a hardware that I have here has three PCI root segemnts with bus
> numbers 0, 0x7f, 0x80 and 0xff respectively. (0x7f and 0xff host the
> uncore devices of each processor).

Well, machines with multiple host bridges have been around for a
while.  Some of them even pre-date ACPI.

> 
> These segments are already detected by APCI but this information is not
> used when attaching PCI busses to the mainbus. Below is a patch that
> should solve the PCI bus detection problem in a robust way.

I hate ACPI!  It's full of lies; I don't trust it.  It is much better
to detect these additional PCI busses by looking at actual hardware
registers.  So before we go down this path, can you investigate that?
It seems the bus number for the additional "Uncore" devices of the
Xeon E5 1600/2600 CPUs is available in config register 0x108 of device
0:5:0.  But I haven't figured how to find the bus number for the
second socket.  Looking at the AML for this machine and determining
how it detects these additional busses might provide some clues.  Feel
free to send me the acpidump output for this box.

> There's a small problem though: Some of the secondary PCI segments
> can show up as busses behind some kind of host bridge device dowstream
> of pci bus 0, too. These PCI busses would be attached twice, now. Thus we
> keep track of attached root segemnents in the ACPI code.

Yup.  Since we have code to detect additional host bridges some of
them may already have been attached.  And it would be a good way to
defend against ACPI lying to us.  However, please keep the ACPI hooks
out of the MI PCI code.  It'd be better if you used pci_attach_hook(),
which lives in arch/pci/pci_machdep.c.


> Index: arch/i386/i386/mainbus.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/i386/i386/mainbus.c,v
> retrieving revision 1.48
> diff -u -r1.48 mainbus.c
> --- arch/i386/i386/mainbus.c  3 Nov 2010 10:15:23 -0000       1.48
> +++ arch/i386/i386/mainbus.c  6 Sep 2012 08:58:38 -0000
> @@ -244,6 +244,9 @@
>               mba.mba_pba.pba_domain = pci_ndomains++;
>               mba.mba_pba.pba_bus = 0;
>               config_found(self, &mba.mba_pba, mainbus_print);
> +#if NACPI > 0
> +             acpi_pciroots_attach(self, &mba.mba_pba, mainbus_print);
> +#endif
>       }
>  #endif
>  
> Index: dev/acpi/acpi.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/acpi/acpi.c,v
> retrieving revision 1.238
> diff -u -r1.238 acpi.c
> --- dev/acpi/acpi.c   13 Jul 2012 11:51:41 -0000      1.238
> +++ dev/acpi/acpi.c   6 Sep 2012 08:58:39 -0000
> @@ -392,6 +392,8 @@
>  
>  TAILQ_HEAD(, acpi_pci) acpi_pcidevs =
>      TAILQ_HEAD_INITIALIZER(acpi_pcidevs);
> +TAILQ_HEAD(, acpi_pci) acpi_pcirootdevs = 
> +    TAILQ_HEAD_INITIALIZER(acpi_pcirootdevs);
>  
>  int acpi_getpci(struct aml_node *node, void *arg);
>  int acpi_getminbus(union acpi_resource *crs, void *arg);
> @@ -480,6 +482,7 @@
>                       node->pci = pci;
>                       dnprintf(10, "found PCI root: %s %d\n",
>                           aml_nodename(node), pci->bus);
> +                     TAILQ_INSERT_TAIL(&acpi_pcirootdevs, pci, next);
>               }
>               aml_freevalue(&res);
>               return 0;
> @@ -548,6 +551,31 @@
>                           dev->dv_xname, aml_nodename(pdev->node));
>                       pdev->device = dev;
>               }
> +     }
> +}
> +
> +void
> +acpi_pciroot_match(struct device *dev, int bus)
> +{
> +     struct acpi_pci *pdev;
> +
> +     TAILQ_FOREACH(pdev, &acpi_pcirootdevs, next) {
> +             if (pdev->bus == bus)
> +                     pdev->device = dev;
> +     }
> +}
> +
> +void
> +acpi_pciroots_attach(struct device *dev, void *aux, cfprint_t pr)
> +{
> +     struct acpi_pci                 *pdev;
> +     struct pcibus_attach_args       *pba = aux;
> +
> +     TAILQ_FOREACH(pdev, &acpi_pcirootdevs, next) {
> +             if (pdev->device)       /* Already attached */
> +                     continue;
> +             pba->pba_bus = pdev->bus;
> +             config_found(dev, pba, pr);
>       }
>  }
>  
> Index: dev/acpi/acpivar.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/acpi/acpivar.h,v
> retrieving revision 1.71
> diff -u -r1.71 acpivar.h
> --- dev/acpi/acpivar.h        15 Apr 2011 17:34:51 -0000      1.71
> +++ dev/acpi/acpivar.h        6 Sep 2012 08:58:39 -0000
> @@ -322,6 +322,9 @@
>  void acpi_powerdown_task(void *, int);
>  void acpi_sleep_task(void *, int);
>  
> +void acpi_pciroot_match(struct device *, int);
> +void acpi_pciroots_attach(struct device *, void *, cfprint_t);
> +
>  #endif
>  
>  #endif /* !_ACPI_WAKECODE */
> Index: dev/pci/pci.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/pci.c,v
> retrieving revision 1.94
> diff -u -r1.94 pci.c
> --- dev/pci/pci.c     10 Oct 2011 19:42:37 -0000      1.94
> +++ dev/pci/pci.c     6 Sep 2012 08:58:39 -0000
> @@ -46,6 +46,12 @@
>  #include <dev/pci/pcidevs.h>
>  #include <dev/pci/ppbreg.h>
>  
> +#include "acpi.h"
> +
> +#if NACPI > 0
> +#include <dev/acpi/acpivar.h>
> +#endif
> +
>  int pcimatch(struct device *, void *, void *);
>  void pciattach(struct device *, struct device *, void *);
>  int pcidetach(struct device *, int);
> @@ -187,6 +193,9 @@
>       if (pci_enumerate_bus(sc, pci_primary_vga, NULL))
>               pci_vga_pci = sc;
>       pci_enumerate_bus(sc, NULL, NULL);
> +#if NACPI > 0
> +     acpi_pciroot_match(self, pba->pba_bus);
> +#endif
>  }
>  
>  int

Reply via email to