summaryrefslogtreecommitdiffstats
path: root/sys/dev/pci/pci.c
diff options
context:
space:
mode:
authorrstone <rstone@FreeBSD.org>2015-03-01 04:22:06 +0000
committerrstone <rstone@FreeBSD.org>2015-03-01 04:22:06 +0000
commit0b55a8c80a8931d02374a071f01ad9db0ef81d38 (patch)
tree446f913517294e1706cb75904e32f64162cd9d7d /sys/dev/pci/pci.c
parent058f9df18735c3a34032de747c66a1b31569903d (diff)
downloadFreeBSD-src-0b55a8c80a8931d02374a071f01ad9db0ef81d38.zip
FreeBSD-src-0b55a8c80a8931d02374a071f01ad9db0ef81d38.tar.gz
MFC r264007,r264008,r264009,r264011,r264012,r264013
MFC support for PCI Alternate RID Interpretation. ARI is an optional PCIe feature that allows PCI devices to present up to 256 functions on a bus. This is effectively a prerequisite for PCI SR-IOV support. r264007: Add a method to get the PCI RID for a device. Reviewed by: kib MFC after: 2 months Sponsored by: Sandvine Inc. r264008: Re-implement the DMAR I/O MMU code in terms of PCI RIDs Under the hood the VT-d spec is really implemented in terms of PCI RIDs instead of bus/slot/function, even though the spec makes pains to convert back to bus/slot/function in examples. However working with bus/slot/function is not correct when PCI ARI is in use, so convert to using RIDs in most cases. bus/slot/function will only be used when reporting errors to a user. Reviewed by: kib MFC after: 2 months Sponsored by: Sandvine Inc. r264009: Re-write bhyve's I/O MMU handling in terms of PCI RID. Reviewed by: neel MFC after: 2 months Sponsored by: Sandvine Inc. r264011: Add support for PCIe ARI PCIe Alternate RID Interpretation (ARI) is an optional feature that allows devices to have up to 256 different functions. It is implemented by always setting the PCI slot number to 0 and re-purposing the 5 bits used to encode the slot number to instead contain the function number. Combined with the original 3 bits allocated for the function number, this allows for 256 functions. This is enabled by default, but it's expected to be a no-op on currently supported hardware. It's a prerequisite for supporting PCI SR-IOV, and I want the ARI support to go in early to help shake out any bugs in it. ARI can be disabled by setting the tunable hw.pci.enable_ari=0. Reviewed by: kib MFC after: 2 months Sponsored by: Sandvine Inc. r264012: Print status of ARI capability in pciconf -c Teach pciconf how to print out the status (enabled/disabled) of the ARI capability on PCI Root Complexes and Downstream Ports. MFC after: 2 months Sponsored by: Sandvine Inc. r264013: Add missing copyright date. MFC after: 2 months
Diffstat (limited to 'sys/dev/pci/pci.c')
-rw-r--r--sys/dev/pci/pci.c59
1 files changed, 52 insertions, 7 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index fc18f70..db2a6cc 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -121,6 +121,8 @@ static void pci_resume_msix(device_t dev);
static int pci_remap_intr_method(device_t bus, device_t dev,
u_int irq);
+static uint16_t pci_get_rid_method(device_t dev, device_t child);
+
static device_method_t pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, pci_probe),
@@ -175,6 +177,7 @@ static device_method_t pci_methods[] = {
DEVMETHOD(pci_release_msi, pci_release_msi_method),
DEVMETHOD(pci_msi_count, pci_msi_count_method),
DEVMETHOD(pci_msix_count, pci_msix_count_method),
+ DEVMETHOD(pci_get_rid, pci_get_rid_method),
DEVMETHOD_END
};
@@ -358,6 +361,11 @@ TUNABLE_INT("hw.pci.clear_bars", &pci_clear_bars);
SYSCTL_INT(_hw_pci, OID_AUTO, clear_bars, CTLFLAG_RDTUN, &pci_clear_bars, 0,
"Ignore firmware-assigned resources for BARs.");
+static int pci_enable_ari = 1;
+TUNABLE_INT("hw.pci.enable_ari", &pci_enable_ari);
+SYSCTL_INT(_hw_pci, OID_AUTO, enable_ari, CTLFLAG_RDTUN, &pci_enable_ari,
+ 0, "Enable support for PCIe Alternative RID Interpretation");
+
static int
pci_has_quirk(uint32_t devid, int quirk)
{
@@ -3292,6 +3300,19 @@ pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask)
}
}
+static struct pci_devinfo *
+pci_identify_function(device_t pcib, device_t dev, int domain, int busno,
+ int slot, int func, size_t dinfo_size)
+{
+ struct pci_devinfo *dinfo;
+
+ dinfo = pci_read_device(pcib, domain, busno, slot, func, dinfo_size);
+ if (dinfo != NULL)
+ pci_add_child(dev, dinfo);
+
+ return (dinfo);
+}
+
void
pci_add_children(device_t dev, int domain, int busno, size_t dinfo_size)
{
@@ -3301,6 +3322,24 @@ pci_add_children(device_t dev, int domain, int busno, size_t dinfo_size)
int maxslots;
int s, f, pcifunchigh;
uint8_t hdrtype;
+ int first_func;
+
+ /*
+ * Try to detect a device at slot 0, function 0. If it exists, try to
+ * enable ARI. We must enable ARI before detecting the rest of the
+ * functions on this bus as ARI changes the set of slots and functions
+ * that are legal on this bus.
+ */
+ dinfo = pci_identify_function(pcib, dev, domain, busno, 0, 0,
+ dinfo_size);
+ if (dinfo != NULL && pci_enable_ari)
+ PCIB_TRY_ENABLE_ARI(pcib, dinfo->cfg.dev);
+
+ /*
+ * Start looking for new devices on slot 0 at function 1 because we
+ * just identified the device at slot 0, function 0.
+ */
+ first_func = 1;
KASSERT(dinfo_size >= sizeof(struct pci_devinfo),
("dinfo_size too small"));
@@ -3313,14 +3352,13 @@ pci_add_children(device_t dev, int domain, int busno, size_t dinfo_size)
if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
continue;
if (hdrtype & PCIM_MFDEV)
- pcifunchigh = PCI_FUNCMAX;
- for (f = 0; f <= pcifunchigh; f++) {
- dinfo = pci_read_device(pcib, domain, busno, s, f,
+ pcifunchigh = PCIB_MAXFUNCS(pcib);
+ for (f = first_func; f <= pcifunchigh; f++)
+ pci_identify_function(pcib, dev, domain, busno, s, f,
dinfo_size);
- if (dinfo != NULL) {
- pci_add_child(dev, dinfo);
- }
- }
+
+ /* For slots after slot 0 we need to check for function 0. */
+ first_func = 0;
}
#undef REG
}
@@ -4877,3 +4915,10 @@ pci_restore_state(device_t dev)
dinfo = device_get_ivars(dev);
pci_cfg_restore(dev, dinfo);
}
+
+static uint16_t
+pci_get_rid_method(device_t dev, device_t child)
+{
+
+ return (PCIB_GET_RID(device_get_parent(dev), child));
+}
OpenPOWER on IntegriCloud