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 */ @@ -173,7 +179,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)) { @@ -211,6 +217,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) { @@ -224,8 +231,13 @@ err_rman_manage: for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) { - if (sc->ranges[tuple].size == 0) - continue; /* empty range element */ + rid = sc->ranges[tuple].rid; + if (rid == -1) { + /* not an allocated range element */ + MPASS(sc->ranges[tuple].res == NULL); + continue; + } + switch (FLAG_TYPE(sc->ranges[tuple].flags)) { case FLAG_TYPE_PMEM: case FLAG_TYPE_MEM: @@ -237,10 +249,11 @@ default: 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: @@ -262,7 +275,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); @@ -271,8 +284,12 @@ return (error); for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) { - if (sc->ranges[tuple].size == 0) - continue; /* empty range element */ + rid = sc->ranges[tuple].rid; + if (rid == -1) { + /* not an allocated range element */ + MPASS(sc->ranges[tuple].res == NULL); + continue; + } switch (FLAG_TYPE(sc->ranges[tuple].flags)) { case FLAG_TYPE_PMEM: case FLAG_TYPE_MEM: @@ -284,10 +301,11 @@ default: 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 @@ -215,6 +215,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;