Changeset View
Standalone View
sys/arm64/cavium/thunder_pcie.c
Show All 29 Lines | |||||
/* PCIe root complex driver for Cavium Thunder SOC */ | /* PCIe root complex driver for Cavium Thunder SOC */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/types.h> | |||||
#include <sys/sysctl.h> | |||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/rman.h> | #include <sys/rman.h> | ||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#include <sys/endian.h> | #include <sys/endian.h> | ||||
#include <sys/cpuset.h> | #include <sys/cpuset.h> | ||||
#include <dev/ofw/openfirm.h> | #include <dev/ofw/openfirm.h> | ||||
#include <dev/ofw/ofw_bus.h> | #include <dev/ofw/ofw_bus.h> | ||||
#include <dev/ofw/ofw_bus_subr.h> | #include <dev/ofw/ofw_bus_subr.h> | ||||
#include <dev/pci/pcivar.h> | #include <dev/pci/pcivar.h> | ||||
#include <dev/pci/pcireg.h> | #include <dev/pci/pcireg.h> | ||||
#include <dev/pci/pcib_private.h> | #include <dev/pci/pcib_private.h> | ||||
#include <dev/pci/pci_private.h> | |||||
#include <machine/cpu.h> | #include <machine/cpu.h> | ||||
#include <machine/bus.h> | #include <machine/bus.h> | ||||
#include <machine/intr.h> | #include <machine/intr.h> | ||||
#include "thunder_pcie_common.h" | #include "thunder_pcie_common.h" | ||||
#include "pcib_if.h" | #include "pcib_if.h" | ||||
Show All 33 Lines | |||||
struct thunder_pcie_softc { | struct thunder_pcie_softc { | ||||
struct pcie_range ranges[MAX_RANGES_TUPLES]; | struct pcie_range ranges[MAX_RANGES_TUPLES]; | ||||
struct rman mem_rman; | struct rman mem_rman; | ||||
struct resource *res; | struct resource *res; | ||||
int ecam; | int ecam; | ||||
device_t dev; | device_t dev; | ||||
}; | }; | ||||
static int thunder_pcie_max_vfs = 4; | |||||
andrew: Why 4? | |||||
SYSCTL_INT(_hw, OID_AUTO, thunder_pcie_max_vfs, CTLFLAG_RWTUN, | |||||
&thunder_pcie_max_vfs, 0, "Max VFs supported by ThunderX internal PCIe"); | |||||
/* Forward prototypes */ | /* Forward prototypes */ | ||||
static struct resource *thunder_pcie_alloc_resource(device_t, | static struct resource *thunder_pcie_alloc_resource(device_t, | ||||
device_t, int, int *, u_long, u_long, u_long, u_int); | device_t, int, int *, u_long, u_long, u_long, u_int); | ||||
static int thunder_pcie_attach(device_t); | static int thunder_pcie_attach(device_t); | ||||
static int thunder_pcie_identify_pcib(device_t); | static int thunder_pcie_identify_pcib(device_t); | ||||
static int thunder_pcie_maxslots(device_t); | static int thunder_pcie_maxslots(device_t); | ||||
static int parse_pci_mem_ranges(struct thunder_pcie_softc *); | static int parse_pci_mem_ranges(struct thunder_pcie_softc *); | ||||
static int thunder_pcie_probe(device_t); | static int thunder_pcie_probe(device_t); | ||||
▲ Show 20 Lines • Show All 312 Lines • ▼ Show 20 Lines | |||||
static struct resource * | static struct resource * | ||||
thunder_pcie_alloc_resource(device_t dev, device_t child, int type, int *rid, | thunder_pcie_alloc_resource(device_t dev, device_t child, int type, int *rid, | ||||
u_long start, u_long end, u_long count, u_int flags) | u_long start, u_long end, u_long count, u_int flags) | ||||
{ | { | ||||
struct thunder_pcie_softc *sc = device_get_softc(dev); | struct thunder_pcie_softc *sc = device_get_softc(dev); | ||||
struct rman *rm = NULL; | struct rman *rm = NULL; | ||||
struct resource *res; | struct resource *res; | ||||
pci_addr_t map, testval; | |||||
switch (type) { | switch (type) { | ||||
case SYS_RES_IOPORT: | case SYS_RES_IOPORT: | ||||
goto fail; | goto fail; | ||||
break; | break; | ||||
case SYS_RES_MEMORY: | case SYS_RES_MEMORY: | ||||
rm = &sc->mem_rman; | rm = &sc->mem_rman; | ||||
break; | break; | ||||
default: | default: | ||||
return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, | return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, | ||||
type, rid, start, end, count, flags)); | type, rid, start, end, count, flags)); | ||||
}; | }; | ||||
if ((start == 0UL) && (end == ~0UL)) { | if ((start == 0UL) && (end == ~0UL)) { | ||||
device_printf(dev, | |||||
"Cannot allocate resource with unspecified range\n"); | /* Read BAR manually to get resource address and size */ | ||||
goto fail; | 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; | |||||
start = map; | |||||
count = (~testval) + 1; | |||||
andrewUnsubmitted Not Done Inline ActionsWhat is happening here? I don't understand how this works, a comment would be useful to help explain it. andrew: What is happening here? I don't understand how this works, a comment would be useful to help… | |||||
impUnsubmitted Not Done Inline ActionsYou're supposed to write all f's to the BAR to size it. The bits for the decode lines will be 0's, the address range it occupies are 1's. So this flips the upper bits that are set and adds 1 to get the size. The masking above masks out the low-order bits that contain attributes for the mapping. imp: You're supposed to write all f's to the BAR to size it. The bits for the decode lines will be… | |||||
/* | |||||
* Internal ThunderX devices supports up to 3 64-bit BARs. | |||||
* If we're allocating anything above, that means upper layer | |||||
* wants us to allocate VF-BAR. In that case reserve bigger | |||||
* slice to make a room for other VFs adjacent to this one. | |||||
*/ | |||||
if (*rid > PCIR_BAR(5)) | |||||
andrewUnsubmitted Not Done Inline ActionsYou talk about 3 64-bit bars, then use 5 here. Why? andrew: You talk about 3 64-bit bars, then use 5 here. Why? | |||||
impUnsubmitted Not Done Inline Actions0, 2 and 4 are valid valid values for 3 64-bit BARs. 5 is the first invalid one. imp: 0, 2 and 4 are valid valid values for 3 64-bit BARs. 5 is the first invalid one.
| |||||
emasteUnsubmitted Not Done Inline ActionsAlternatively, 6 is the 4th 64-bit BAR? emaste: Alternatively, 6 is the 4th 64-bit BAR? | |||||
wma_semihalf.comAuthorUnsubmitted Not Done Inline ActionsPCI supports up to 6 BAR registers. They can be used either as 6x 32-bit regs, or 3x 64-bit. Anyway, PCIR_BAR(5) is the last valid entry inside configuration header, so anything above means we're accessing VFs. wma_semihalf.com: PCI supports up to 6 BAR registers. They can be used either as 6x 32-bit regs, or 3x 64-bit. | |||||
count = count * thunder_pcie_max_vfs; | |||||
end = start + count - 1; | |||||
} | } | ||||
/* Convert input BUS address to required PHYS */ | /* Convert input BUS address to required PHYS */ | ||||
if (range_addr_is_pci(sc->ranges, start, count) == 0) | if (range_addr_is_pci(sc->ranges, start, count) == 0) | ||||
goto fail; | goto fail; | ||||
start = range_addr_pci_to_phys(sc->ranges, start); | start = range_addr_pci_to_phys(sc->ranges, start); | ||||
end = start + count - 1; | end = start + count - 1; | ||||
▲ Show 20 Lines • Show All 107 Lines • Show Last 20 Lines |
Why 4?