mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
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:d79b6b8ec2pci_host_generic: Don't rewrite resource start address for translation Differential Revision: https://reviews.freebsd.org/D44698 (cherry picked from commit03713f805a)
This commit is contained in:
parent
d172f42e4b
commit
92e5936686
1 changed files with 16 additions and 39 deletions
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Reference in a new issue