git: 34f9dca1917b - stable/14 - pci: avoid accidental clobbering of regs on some fdt platforms

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Tue, 29 Apr 2025 18:30:31 UTC
The branch stable/14 has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=34f9dca1917b7837f7d1f5475b2e0d7be2ced717

commit 34f9dca1917b7837f7d1f5475b2e0d7be2ced717
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2024-12-29 03:57:03 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2025-04-29 14:17:50 +0000

    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)
---
 sys/dev/pci/pci_host_generic.c      | 22 +++++++++++++++++-----
 sys/dev/pci/pci_host_generic.h      |  1 +
 sys/dev/pci/pci_host_generic_acpi.c |  1 +
 sys/dev/pci/pci_host_generic_fdt.c  |  1 +
 4 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/sys/dev/pci/pci_host_generic.c b/sys/dev/pci/pci_host_generic.c
index ff8d222e3fd3..2552dc6cc599 100644
--- 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 @@ 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);
diff --git a/sys/dev/pci/pci_host_generic.h b/sys/dev/pci/pci_host_generic.h
index 65f69fc05314..2d15f06890db 100644
--- a/sys/dev/pci/pci_host_generic.h
+++ b/sys/dev/pci/pci_host_generic.h
@@ -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 {
diff --git a/sys/dev/pci/pci_host_generic_acpi.c b/sys/dev/pci/pci_host_generic_acpi.c
index 992e8b5c8b8d..e309684a3603 100644
--- a/sys/dev/pci/pci_host_generic_acpi.c
+++ b/sys/dev/pci/pci_host_generic_acpi.c
@@ -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;
diff --git a/sys/dev/pci/pci_host_generic_fdt.c b/sys/dev/pci/pci_host_generic_fdt.c
index 854ec0be8dfa..05e77f46032f 100644
--- a/sys/dev/pci/pci_host_generic_fdt.c
+++ b/sys/dev/pci/pci_host_generic_fdt.c
@@ -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;