git: 03713f805a91 - main - pci_host_generic: Tolerate range resource allocation failures
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 09 Apr 2024 21:56:05 UTC
The branch main has been updated by jhb:
URL: https://cgit.FreeBSD.org/src/commit/?id=03713f805a91749eabcfb2e23e86489b2d4034df
commit 03713f805a91749eabcfb2e23e86489b2d4034df
Author: John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2024-04-09 21:55:40 +0000
Commit: John Baldwin <jhb@FreeBSD.org>
CommitDate: 2024-04-09 21:55:40 +0000
pci_host_generic: Tolerate range resource allocation failures
QEMU for armv7 includes a PCI memory range whose CPU address is
greater than 4GB. This falls outside the range of armv7's global
mem_rman used by the nexus driver. As a result, pcib0 fails to
attach blocking all PCI devices.
Instead, change the driver to be a bit more tolerant. If allocating a
resource for a range fails, don't fail attaching the entire driver,
but do skip adding the associated PCI range to the relevant rman in
the pcib driver. This will prevent child devices from using BARs that
allocate from this range. In the case of QEMU on armv7 devices can
still allocate from an earlier PCI memory range that is within the
32-bit address space (and in fact none of the firmware-assigned memory
BARs use addresses from the upper range).
While here, reorder the operations on I/O ranges a bit: 1) print the
range under bootverbose first (rather than last) so that the range is
printed before any relevant errors for the range, 2) move
rman_manage_region last after the parent resource has been set and
allocated.
Reported by: markj, Jenkins
Reviewed by: markj
Fixes: d79b6b8ec267 pci_host_generic: Don't rewrite resource start address for translation
Differential Revision: https://reviews.freebsd.org/D44698
---
sys/dev/pci/pci_host_generic.c | 55 ++++++++++++------------------------------
1 file changed, 16 insertions(+), 39 deletions(-)
diff --git a/sys/dev/pci/pci_host_generic.c b/sys/dev/pci/pci_host_generic.c
index 0bdc121f9727..82ed51460621 100644
--- a/sys/dev/pci/pci_host_generic.c
+++ b/sys/dev/pci/pci_host_generic.c
@@ -80,6 +80,7 @@ pci_host_generic_core_attach(device_t dev)
struct resource_map map;
#endif
struct generic_pcie_core_softc *sc;
+ struct rman *rm;
uint64_t phys_base;
uint64_t pci_base;
uint64_t size;
@@ -183,75 +184,51 @@ pci_host_generic_core_attach(device_t dev)
range_descr = "prefetch";
flags = RF_PREFETCHABLE;
type = SYS_RES_MEMORY;
- error = rman_manage_region(&sc->pmem_rman,
- pci_base, pci_base + size - 1);
+ rm = &sc->pmem_rman;
break;
case FLAG_TYPE_MEM:
range_descr = "memory";
flags = 0;
type = SYS_RES_MEMORY;
- error = rman_manage_region(&sc->mem_rman,
- pci_base, pci_base + size - 1);
+ rm = &sc->mem_rman;
break;
case FLAG_TYPE_IO:
range_descr = "I/O port";
flags = 0;
type = SYS_RES_IOPORT;
- error = rman_manage_region(&sc->io_rman,
- pci_base, pci_base + size - 1);
+ rm = &sc->io_rman;
break;
default:
continue;
}
- if (error) {
- device_printf(dev, "rman_manage_region() failed."
- "error = %d\n", error);
- goto err_rman_manage;
- }
+ if (bootverbose)
+ device_printf(dev,
+ "PCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx, Type: %s\n",
+ pci_base, phys_base, size, range_descr);
error = bus_set_resource(dev, type, rid, phys_base, size);
if (error != 0) {
device_printf(dev,
"failed to set resource for range %d: %d\n", tuple,
error);
- goto err_rman_manage;
+ continue;
}
sc->ranges[tuple].res = bus_alloc_resource_any(dev, type, &rid,
RF_ACTIVE | RF_UNMAPPED | flags);
if (sc->ranges[tuple].res == NULL) {
device_printf(dev,
"failed to allocate resource for range %d\n", tuple);
- error = ENXIO;
- goto err_rman_manage;
+ continue;
+ }
+ error = rman_manage_region(rm, pci_base, pci_base + size - 1);
+ if (error) {
+ device_printf(dev, "rman_manage_region() failed."
+ "error = %d\n", error);
+ continue;
}
- if (bootverbose)
- device_printf(dev,
- "PCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx, Type: %s\n",
- pci_base, phys_base, size, range_descr);
}
return (0);
-err_rman_manage:
- for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
- if (sc->ranges[tuple].size == 0)
- continue; /* empty range element */
- switch (FLAG_TYPE(sc->ranges[tuple].flags)) {
- case FLAG_TYPE_PMEM:
- case FLAG_TYPE_MEM:
- type = SYS_RES_MEMORY;
- break;
- case FLAG_TYPE_IO:
- type = SYS_RES_IOPORT;
- break;
- default:
- continue;
- }
- if (sc->ranges[tuple].res != NULL)
- bus_release_resource(dev, type, tuple + 1,
- sc->ranges[tuple].res);
- bus_delete_resource(dev, type, tuple + 1);
- }
- rman_fini(&sc->io_rman);
err_io_rman:
rman_fini(&sc->mem_rman);
err_mem_rman: