Index: sys/arm64/cavium/thunder_pcie_common.h =================================================================== --- sys/arm64/cavium/thunder_pcie_common.h +++ sys/arm64/cavium/thunder_pcie_common.h @@ -39,5 +39,9 @@ uint64_t range_addr_pci_to_phys(struct pcie_range *, uint64_t); int thunder_pcie_identify_ecam(device_t, int *); +#ifdef THUNDERX_PASS_1_1_ERRATA +struct resource *thunder_pcie_alloc_resource(device_t, + device_t, int, int *, rman_res_t, rman_res_t, rman_res_t, u_int); +#endif #endif /* _CAVIUM_THUNDER_PCIE_COMMON_H_ */ Index: sys/arm64/cavium/thunder_pcie_common.c =================================================================== --- sys/arm64/cavium/thunder_pcie_common.c +++ sys/arm64/cavium/thunder_pcie_common.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include "opt_platform.h" +#include "opt_bus.h" #include #include @@ -52,10 +53,16 @@ #include #endif -#include +#include #include +#include +#include #include #include +#ifdef PCI_IOV +#include +#include +#endif #include "thunder_pcie_common.h" @@ -142,3 +149,67 @@ return (0); } + +#ifdef THUNDERX_PASS_1_1_ERRATA +struct resource * +thunder_pcie_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) +{ + pci_addr_t map, testval; +#ifdef PCI_IOV + struct pci_devinfo *dinfo; + struct pcicfg_iov *iov; +#endif + int iov_cnt; + + iov_cnt = 1; +#ifdef PCI_IOV + dinfo = device_get_ivars(child); + iov = dinfo->cfg.iov; + if (iov != NULL) + iov_cnt = iov->iov_num_vfs; +#endif + + /* + * If Enhanced Allocation is not used, we can't allocate any random + * range. All internal devices have hardcoded place where they can + * be located within PCI address space. Fortunately, we can read + * this value from BAR. + */ + if (((type == SYS_RES_IOPORT) || (type == SYS_RES_MEMORY)) && + RMAN_IS_DEFAULT_RANGE(start, end)) { +#ifdef FDT + if ((int)ofw_bus_get_node(child) > 0) + return (pci_host_generic_alloc_resource(dev, child, + type, rid, start, end, count, flags)); +#endif + + /* Read BAR manually to get resource address and size */ + pci_read_bar(child, *rid, &map, &testval, NULL); + + /* Mask the information bits */ + if (PCI_BAR_MEM(map)) + map &= PCIM_BAR_MEM_BASE; + else + map &= PCIM_BAR_IO_BASE; + + if (PCI_BAR_MEM(testval)) + testval &= PCIM_BAR_MEM_BASE; + else + testval &= PCIM_BAR_IO_BASE; + + /* + * If the upper layer wants us to allocate VF-BAR, reserve + * a bigger slice to make a room for other VFs adjacent + * to this one. + */ + start = map; + count = (~testval) + 1; + count = count * iov_cnt; + end = start + count - 1; + } + + return (pci_host_generic_alloc_resource(dev, child, type, rid, start, + end, count, flags)); +} +#endif Index: sys/arm64/cavium/thunder_pcie_fdt.c =================================================================== --- sys/arm64/cavium/thunder_pcie_fdt.c +++ sys/arm64/cavium/thunder_pcie_fdt.c @@ -25,11 +25,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include "opt_platform.h" #include __FBSDID("$FreeBSD$"); +#include "opt_platform.h" +#include "opt_bus.h" + #include #include #include @@ -41,10 +43,15 @@ #include #include #include +#include #include #include #include + +#include +#include +#include #include #include "thunder_pcie_common.h" @@ -56,6 +63,9 @@ /* Device interface */ DEVMETHOD(device_probe, thunder_pcie_fdt_probe), DEVMETHOD(device_attach, thunder_pcie_fdt_attach), +#ifdef THUNDERX_PASS_1_1_ERRATA + DEVMETHOD(bus_alloc_resource, thunder_pcie_alloc_resource), +#endif /* End */ DEVMETHOD_END Index: sys/dev/pci/pci_host_generic.h =================================================================== --- sys/dev/pci/pci_host_generic.h +++ sys/dev/pci/pci_host_generic.h @@ -66,6 +66,8 @@ extern devclass_t generic_pcie_devclass; DECLARE_CLASS(generic_pcie_driver); +struct resource *pci_host_generic_alloc_resource(device_t, + device_t, int, int *, rman_res_t, rman_res_t, rman_res_t, u_int); int pci_host_generic_attach(device_t); #endif /* __PCI_HOST_GENERIC_H_ */ Index: sys/dev/pci/pci_host_generic.c =================================================================== --- sys/dev/pci/pci_host_generic.c +++ sys/dev/pci/pci_host_generic.c @@ -104,9 +104,6 @@ uintptr_t *result); static int generic_pcie_write_ivar(device_t dev, device_t child, int index, uintptr_t value); -static struct resource *generic_pcie_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 struct resource *generic_pcie_alloc_resource_ofw(device_t, device_t, int, int *, rman_res_t, rman_res_t, rman_res_t, u_int); static struct resource *generic_pcie_alloc_resource_pcie(device_t dev, @@ -508,8 +505,8 @@ child, type, rid, res)); } -static struct resource * -generic_pcie_alloc_resource(device_t dev, device_t child, int type, int *rid, +struct resource * +pci_host_generic_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) { @@ -661,7 +658,7 @@ DEVMETHOD(device_attach, pci_host_generic_attach), DEVMETHOD(bus_read_ivar, generic_pcie_read_ivar), DEVMETHOD(bus_write_ivar, generic_pcie_write_ivar), - DEVMETHOD(bus_alloc_resource, generic_pcie_alloc_resource), + DEVMETHOD(bus_alloc_resource, pci_host_generic_alloc_resource), DEVMETHOD(bus_adjust_resource, generic_pcie_adjust_resource), DEVMETHOD(bus_release_resource, generic_pcie_release_resource), DEVMETHOD(bus_activate_resource, generic_pcie_activate_resource),