pci: avoid accidental clobbering of regs on some fdt platforms

Most pci controllers will just have a single reg for the config space,
but others (e.g., on Apple Silicon) may have more following that to
describe, e.g., controller port space.  Bump the "ranges" rid space up
to avoid overriding these other memory resources.

Reviewed by:	jhb
Differential Revision:	https://reviews.freebsd.org/D43921

(cherry picked from commit b313229969cc56a057dfea28506784fd5468c6f3)
This commit is contained in:
Kyle Evans 2024-12-28 21:57:03 -06:00 committed by John Baldwin
parent 7bc852d94d
commit 34f9dca191
4 changed files with 20 additions and 5 deletions

View file

@ -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 @@ pci_host_generic_core_attach(device_t dev)
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)) {
@ -210,6 +216,7 @@ pci_host_generic_core_attach(device_t dev)
error);
continue;
}
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) {
@ -246,7 +253,7 @@ int
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);
@ -255,8 +262,13 @@ pci_host_generic_core_detach(device_t dev)
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:
@ -269,9 +281,9 @@ pci_host_generic_core_detach(device_t dev)
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);

View file

@ -64,6 +64,7 @@ struct pcie_range {
#define FLAG_TYPE_MEM 0x2
#define FLAG_TYPE_PMEM 0x3
struct resource *res;
int rid;
};
struct generic_pcie_core_softc {

View file

@ -182,6 +182,7 @@ pci_host_generic_acpi_parse_resource(ACPI_RESOURCE *res, void *arg)
/* 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;

View file

@ -214,6 +214,7 @@ parse_pci_mem_ranges(device_t dev, struct generic_pcie_core_softc *sc)
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;