Author: andrew
Date: Wed Jun 17 19:56:17 2020
New Revision: 362285
URL: https://svnweb.freebsd.org/changeset/base/362285
Log:
Clean up the pci host generic driver
- Support Prefetchable Memory.
- Use the correct rman when allocating memory and ioports.
- Translate PCI addresses in bus_alloc_resource to allow physical
addresses that are different than pci addresses.
Reviewed by: Robert Crowston
Sponsored by: Innovate UK
Differential Revision:https://reviews.freebsd.org/D25121
Modified:
head/sys/dev/pci/pci_host_generic.c
head/sys/dev/pci/pci_host_generic.h
head/sys/dev/pci/pci_host_generic_acpi.c
head/sys/dev/pci/pci_host_generic_fdt.c
Modified: head/sys/dev/pci/pci_host_generic.c
==
--- head/sys/dev/pci/pci_host_generic.c Wed Jun 17 19:45:05 2020
(r362284)
+++ head/sys/dev/pci/pci_host_generic.c Wed Jun 17 19:56:17 2020
(r362285)
@@ -70,8 +70,11 @@ int
pci_host_generic_core_attach(device_t dev)
{
struct generic_pcie_core_softc *sc;
+ uint64_t phys_base;
+ uint64_t pci_base;
+ uint64_t size;
int error;
- int rid;
+ int rid, tuple;
sc = device_get_softc(dev);
sc->dev = dev;
@@ -101,12 +104,23 @@ pci_host_generic_core_attach(device_t dev)
sc->bst = rman_get_bustag(sc->res);
sc->bsh = rman_get_bushandle(sc->res);
+ sc->has_pmem = false;
+ sc->pmem_rman.rm_type = RMAN_ARRAY;
+ sc->pmem_rman.rm_descr = "PCIe Prefetch Memory";
+
sc->mem_rman.rm_type = RMAN_ARRAY;
sc->mem_rman.rm_descr = "PCIe Memory";
+
sc->io_rman.rm_type = RMAN_ARRAY;
sc->io_rman.rm_descr = "PCIe IO window";
/* Initialize rman and allocate memory regions */
+ error = rman_init(>pmem_rman);
+ if (error) {
+ device_printf(dev, "rman_init() failed. error = %d\n", error);
+ return (error);
+ }
+
error = rman_init(>mem_rman);
if (error) {
device_printf(dev, "rman_init() failed. error = %d\n", error);
@@ -119,6 +133,39 @@ pci_host_generic_core_attach(device_t dev)
return (error);
}
+ for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
+ phys_base = sc->ranges[tuple].phys_base;
+ pci_base = sc->ranges[tuple].pci_base;
+ size = sc->ranges[tuple].size;
+ if (phys_base == 0 || size == 0)
+ continue; /* empty range element */
+ switch (FLAG_TYPE(sc->ranges[tuple].flags)) {
+ case FLAG_TYPE_PMEM:
+ sc->has_pmem = true;
+ error = rman_manage_region(>pmem_rman,
+ phys_base, phys_base + size - 1);
+ break;
+ case FLAG_TYPE_MEM:
+ error = rman_manage_region(>mem_rman,
+ phys_base, phys_base + size - 1);
+ break;
+ case FLAG_TYPE_IO:
+ error = rman_manage_region(>io_rman,
+ phys_base, phys_base + size - 1);
+ break;
+ default:
+ continue;
+ }
+ if (error) {
+ device_printf(dev, "rman_manage_region() failed."
+ "error = %d\n", error);
+ rman_fini(>pmem_rman);
+ rman_fini(>mem_rman);
+ rman_fini(>io_rman);
+ return (error);
+ }
+ }
+
return (0);
}
@@ -236,13 +283,15 @@ generic_pcie_write_ivar(device_t dev, device_t child,
}
static struct rman *
-generic_pcie_rman(struct generic_pcie_core_softc *sc, int type)
+generic_pcie_rman(struct generic_pcie_core_softc *sc, int type, int flags)
{
switch (type) {
case SYS_RES_IOPORT:
return (>io_rman);
case SYS_RES_MEMORY:
+ if (sc->has_pmem && (flags & RF_PREFETCHABLE) != 0)
+ return (>pmem_rman);
return (>mem_rman);
default:
break;
@@ -266,7 +315,7 @@ pci_host_generic_core_release_resource(device_t dev, d
}
#endif
- rm = generic_pcie_rman(sc, type);
+ rm = generic_pcie_rman(sc, type, rman_get_flags(res));
if (rm != NULL) {
KASSERT(rman_is_region_manager(res, rm), ("rman mismatch"));
rman_release_resource(res);
@@ -282,6 +331,11 @@ pci_host_generic_core_alloc_resource(device_t dev, dev
struct generic_pcie_core_softc *sc;
struct resource *res;
struct rman *rm;
+ uint64_t phys_base;
+ uint64_t pci_base;
+ uint64_t size;
+ int i, space;
+ bool found;
sc = device_get_softc(dev);
@@