Translaate the PCI address when activating a resource

When the PCI address != physical address we need to translate from the
former to the latter before passing to the parent to map into the kernels
virtual address space.

Sponsored by:	Innovate UK
This commit is contained in:
Andrew Turner 2020-06-22 10:49:50 +00:00
parent f31030ba61
commit 372c142b4f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=362493

View File

@ -324,13 +324,11 @@ pci_host_generic_core_release_resource(device_t dev, device_t child, int type,
return (bus_generic_release_resource(dev, child, type, rid, res));
}
struct resource *
pci_host_generic_core_alloc_resource(device_t dev, device_t child, int type,
int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
static bool
generic_pcie_translate_resource(device_t dev, int type, rman_res_t start,
rman_res_t end, rman_res_t *new_start, rman_res_t *new_end)
{
struct generic_pcie_core_softc *sc;
struct resource *res;
struct rman *rm;
uint64_t phys_base;
uint64_t pci_base;
uint64_t size;
@ -338,19 +336,6 @@ pci_host_generic_core_alloc_resource(device_t dev, device_t child, int type,
bool found;
sc = device_get_softc(dev);
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
if (type == PCI_RES_BUS) {
return (pci_domain_alloc_bus(sc->ecam, child, rid, start, end,
count, flags));
}
#endif
rm = generic_pcie_rman(sc, type, flags);
if (rm == NULL)
return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
type, rid, start, end, count, flags));
/* Translate the address from a PCI address to a physical address */
switch (type) {
case SYS_RES_IOPORT:
@ -378,25 +363,57 @@ pci_host_generic_core_alloc_resource(device_t dev, device_t child, int type,
}
if (type == space) {
start = start - pci_base + phys_base;
end = end - pci_base + phys_base;
*new_start = start - pci_base + phys_base;
*new_end = end - pci_base + phys_base;
found = true;
break;
}
}
if (!found) {
device_printf(dev,
"Failed to allocate %s resource %jx-%jx for %s\n",
type == SYS_RES_IOPORT ? "IOPORT" : "MEMORY",
(uintmax_t)start, (uintmax_t)end,
device_get_nameunit(child));
return (NULL);
}
break;
default:
/* No translation for non-memory types */
*new_start = start;
*new_end = end;
found = true;
break;
}
return (found);
}
struct resource *
pci_host_generic_core_alloc_resource(device_t dev, device_t child, int type,
int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
struct generic_pcie_core_softc *sc;
struct resource *res;
struct rman *rm;
rman_res_t phys_start, phys_end;
sc = device_get_softc(dev);
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
if (type == PCI_RES_BUS) {
return (pci_domain_alloc_bus(sc->ecam, child, rid, start, end,
count, flags));
}
#endif
rm = generic_pcie_rman(sc, type, flags);
if (rm == NULL)
return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
type, rid, start, end, count, flags));
/* Translate the address from a PCI address to a physical address */
if (!generic_pcie_translate_resource(dev, type, start, end, &phys_start,
&phys_end)) {
device_printf(dev,
"Failed to translate resource %jx-%jx type %x for %s\n",
(uintmax_t)start, (uintmax_t)end, type,
device_get_nameunit(child));
return (NULL);
}
if (bootverbose) {
device_printf(dev,
"rman_reserve_resource: start=%#jx, end=%#jx, count=%#jx\n",
@ -430,6 +447,7 @@ generic_pcie_activate_resource(device_t dev, device_t child, int type,
int rid, struct resource *r)
{
struct generic_pcie_core_softc *sc;
rman_res_t start, end;
int res;
sc = device_get_softc(dev);
@ -437,6 +455,14 @@ generic_pcie_activate_resource(device_t dev, device_t child, int type,
if ((res = rman_activate_resource(r)) != 0)
return (res);
start = rman_get_start(r);
end = rman_get_end(r);
if (!generic_pcie_translate_resource(dev, type, start, end, &start,
&end))
return (EINVAL);
rman_set_start(r, start);
rman_set_end(r, end);
return (BUS_ACTIVATE_RESOURCE(device_get_parent(dev), child, type,
rid, r));
}