diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index d3fb8521dac4..3ec75fbeca19 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -716,15 +716,22 @@ pci_enumerate_bus(struct pci_softc *sc, const int *locators, break; } + pcireg_t dcap = pci_conf_read(ppbpc, ppbtag, pciecap + + PCIE_DCAP2); reg = pci_conf_read(ppbpc, ppbtag, pciecap + PCIE_DCSR2); + if ((dcap & PCIE_DCAP2_ARI_FWD) != 0) { + reg |= PCIE_DCSR2_ARI_FWD; + pci_conf_write(ppbpc, ppbtag, + pciecap + PCIE_DCSR2, reg); + } if ((reg & PCIE_DCSR2_ARI_FWD) != 0) arien = true; } } n = pci_bus_devorder(sc->sc_pc, sc->sc_bus, devs, __arraycount(devs)); - if (downstream_port) { + if (downstream_port && !arien) { /* PCIe downstream ports only have a single child device */ n = 1; } diff --git a/sys/dev/pci/pciconf.c b/sys/dev/pci/pciconf.c index 2e57fab14e55..6295346b9a93 100644 --- a/sys/dev/pci/pciconf.c +++ b/sys/dev/pci/pciconf.c @@ -457,6 +457,7 @@ query_bus(pciconf_bus_t *parent, pciconf_dev_t *pd, int dev) printf("PCI bus bridge (parent %d) covers busses %d-%d\n", parent->busno, pb->busno, pb->last_busno); + // XXXNH Does something need to happen here for EA busses? if (pb->io_total > 0) { if (parent->niowin >= MAX_CONF_IO) { printf("pciconf: too many (%d) I/O windows\n", @@ -608,13 +609,8 @@ pci_do_device_query(pciconf_bus_t *pb, pcitag_t tag, int dev, int func, cmd = pci_conf_read(pb->pc, tag, PCI_COMMAND_STATUS_REG); bhlc = pci_conf_read(pb->pc, tag, PCI_BHLC_REG); - if (pci_get_capability(pb->pc, tag, PCI_CAP_EA, &pd->ea_cap_ptr, - NULL)) { - /* XXX Skip devices with EA for now. */ - print_tag(pb->pc, tag); - printf("skipping devices with Enhanced Allocations\n"); - return 0; - } + bool ea = pci_get_capability(pb->pc, tag, PCI_CAP_EA, &pd->ea_cap_ptr, + NULL); if (PCI_CLASS(classreg) != PCI_CLASS_BRIDGE && PCI_HDRTYPE_TYPE(bhlc) != PCI_HDRTYPE_PPB) { @@ -634,8 +630,10 @@ pci_do_device_query(pciconf_bus_t *pb, pcitag_t tag, int dev, int func, switch (PCI_HDRTYPE_TYPE(bhlc)) { case PCI_HDRTYPE_DEVICE: - reg_start = PCI_MAPREG_START; - reg_end = PCI_MAPREG_END; + if (!ea) { + reg_start = PCI_MAPREG_START; + reg_end = PCI_MAPREG_END; + } break; case PCI_HDRTYPE_PPB: pd->ppb = query_bus(pb, pd, dev); @@ -643,11 +641,13 @@ pci_do_device_query(pciconf_bus_t *pb, pcitag_t tag, int dev, int func, return -1; return 0; case PCI_HDRTYPE_PCB: - reg_start = PCI_MAPREG_START; - reg_end = PCI_MAPREG_PCB_END; + if (!ea) { + reg_start = PCI_MAPREG_START; + reg_end = PCI_MAPREG_PCB_END; + } busreg = pci_conf_read(pb->pc, tag, PCI_BUSNUM); - busreg = (busreg & 0xff000000) | + busreg = (busreg & 0xff000000) | __SHIFTIN(pb->busno, PCI_BRIDGE_BUS_PRIMARY) | __SHIFTIN(pb->next_busno, PCI_BRIDGE_BUS_SECONDARY) | __SHIFTIN(pb->next_busno, PCI_BRIDGE_BUS_SUBORDINATE); @@ -659,6 +659,12 @@ pci_do_device_query(pciconf_bus_t *pb, pcitag_t tag, int dev, int func, return -1; } + if (ea) { + /* XXX Skip devices with EA for now. */ + print_tag(pb->pc, tag); + printf("skipping devices with Enhanced Allocations\n"); + return 0; + } icr = pci_conf_read(pb->pc, tag, PCI_INTERRUPT_REG); pd->ipin = PCI_INTERRUPT_PIN(icr); pd->iline = PCI_INTERRUPT_LINE(icr);