diff --git a/sys/dev/pci/pci_host_generic.h b/sys/dev/pci/pci_host_generic.h --- a/sys/dev/pci/pci_host_generic.h +++ b/sys/dev/pci/pci_host_generic.h @@ -64,6 +64,7 @@ #define FLAG_TYPE_MEM 0x2 #define FLAG_TYPE_PMEM 0x3 struct resource *res; + int rid; }; struct generic_pcie_core_softc { diff --git a/sys/dev/pci/pci_host_generic.c b/sys/dev/pci/pci_host_generic.c --- a/sys/dev/pci/pci_host_generic.c +++ b/sys/dev/pci/pci_host_generic.c @@ -59,6 +59,12 @@ #define PCI_RF_FLAGS 0 #endif +/* + * We allocate "ranges" specified mappings higher up in the rid space to avoid + * conflicts with various definitions in the wild that may have other registers + * attributed to the controller besides just the config space. + */ +#define RANGE_RID(idx) ((idx) + 100) /* Forward prototypes */ @@ -174,7 +180,7 @@ phys_base = sc->ranges[tuple].phys_base; pci_base = sc->ranges[tuple].pci_base; size = sc->ranges[tuple].size; - rid = tuple + 1; + rid = RANGE_RID(tuple); if (size == 0) continue; /* empty range element */ switch (FLAG_TYPE(sc->ranges[tuple].flags)) { @@ -215,6 +221,7 @@ error); goto err_rman_manage; } + sc->ranges[tuple].rid = rid; sc->ranges[tuple].res = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE | RF_UNMAPPED | flags); if (sc->ranges[tuple].res == NULL) { @@ -233,8 +240,13 @@ err_rman_manage: for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) { - if (sc->ranges[tuple].size == 0) + rid = sc->ranges[tuple].rid; + if (sc->ranges[tuple].size == 0) { + MPASS(sc->ranges[tuple].res == NULL); continue; /* empty range element */ + } + + MPASS(rid != -1); switch (FLAG_TYPE(sc->ranges[tuple].flags)) { case FLAG_TYPE_PMEM: case FLAG_TYPE_MEM: @@ -247,9 +259,9 @@ continue; } if (sc->ranges[tuple].res != NULL) - bus_release_resource(dev, type, tuple + 1, + bus_release_resource(dev, type, rid, sc->ranges[tuple].res); - bus_delete_resource(dev, type, tuple + 1); + bus_delete_resource(dev, type, rid); } rman_fini(&sc->io_rman); err_io_rman: @@ -271,7 +283,7 @@ pci_host_generic_core_detach(device_t dev) { struct generic_pcie_core_softc *sc; - int error, tuple, type; + int error, rid, tuple, type; sc = device_get_softc(dev); @@ -280,8 +292,13 @@ return (error); for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) { - if (sc->ranges[tuple].size == 0) + rid = sc->ranges[tuple].rid; + if (sc->ranges[tuple].size == 0) { + MPASS(sc->ranges[tuple].res == NULL); continue; /* empty range element */ + } + + MPASS(rid != -1); switch (FLAG_TYPE(sc->ranges[tuple].flags)) { case FLAG_TYPE_PMEM: case FLAG_TYPE_MEM: @@ -294,9 +311,9 @@ continue; } if (sc->ranges[tuple].res != NULL) - bus_release_resource(dev, type, tuple + 1, + bus_release_resource(dev, type, rid, sc->ranges[tuple].res); - bus_delete_resource(dev, type, tuple + 1); + bus_delete_resource(dev, type, rid); } rman_fini(&sc->io_rman); rman_fini(&sc->mem_rman); diff --git a/sys/dev/pci/pci_host_generic_acpi.c b/sys/dev/pci/pci_host_generic_acpi.c --- a/sys/dev/pci/pci_host_generic_acpi.c +++ b/sys/dev/pci/pci_host_generic_acpi.c @@ -183,6 +183,7 @@ /* Save detected ranges */ if (res->Data.Address.ResourceType == ACPI_MEMORY_RANGE || res->Data.Address.ResourceType == ACPI_IO_RANGE) { + sc->base.ranges[r].rid = -1; sc->base.ranges[r].pci_base = min; sc->base.ranges[r].phys_base = min + off; sc->base.ranges[r].size = max - min + 1; diff --git a/sys/dev/pci/pci_host_generic_fdt.c b/sys/dev/pci/pci_host_generic_fdt.c --- a/sys/dev/pci/pci_host_generic_fdt.c +++ b/sys/dev/pci/pci_host_generic_fdt.c @@ -214,6 +214,7 @@ sc->ranges[i].flags |= FLAG_TYPE_MEM; } + sc->ranges[i].rid = -1; sc->ranges[i].pci_base = 0; for (k = 0; k < (pci_addr_cells - 1); k++) { sc->ranges[i].pci_base <<= 32;