summaryrefslogtreecommitdiffstats
path: root/sys/dev/pci/pci.c
diff options
context:
space:
mode:
authorrstone <rstone@FreeBSD.org>2015-03-01 00:40:26 +0000
committerrstone <rstone@FreeBSD.org>2015-03-01 00:40:26 +0000
commit7a996d41b68bfc27452a84924998470fbfc2acbd (patch)
tree27cdf99df1fa9cb67ab09386bc428478c76c8ff1 /sys/dev/pci/pci.c
parent89058c6ddf90ce9df75bd000e86824b6d85b8a20 (diff)
downloadFreeBSD-src-7a996d41b68bfc27452a84924998470fbfc2acbd.zip
FreeBSD-src-7a996d41b68bfc27452a84924998470fbfc2acbd.tar.gz
Allocate PCI I/O memory spaces for VFs
When creating VFs, we must size each SR-IOV BAR on the PF and allocate a configuous I/O memory window large enough for every VF. However, the window only needs to be aligned to a boundary equal to the size of the window for a single VF. When a VF attempts to allocate an I/O memory resource, we must intercept the request in the pci driver and pass it off to the SR-IOV code, which will allocate the correct window from the pre-allocated memory space for the PF. Inform the pci driver about the size and address of the BARs on the VF when the VF is created. This is required by pciconf -b and bhyve. Differential Revision: https://reviews.freebsd.org/D78 Reviewed by: jhb MFC after: 1 month Sponsored by: Sandvine Inc.
Diffstat (limited to 'sys/dev/pci/pci.c')
-rw-r--r--sys/dev/pci/pci.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index e103f04..b106c67 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -4695,11 +4695,30 @@ struct resource *
pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
+#ifdef PCI_IOV
+ struct pci_devinfo *dinfo;
+#endif
if (device_get_parent(child) != dev)
return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
type, rid, start, end, count, flags));
+#ifdef PCI_IOV
+ dinfo = device_get_ivars(child);
+ if (dinfo->cfg.flags & PCICFG_VF) {
+ switch (type) {
+ /* VFs can't have I/O BARs. */
+ case SYS_RES_IOPORT:
+ return (NULL);
+ case SYS_RES_MEMORY:
+ return (pci_vf_alloc_mem_resource(dev, child, rid,
+ start, end, count, flags));
+ }
+
+ /* Fall through for other types of resource allocations. */
+ }
+#endif
+
return (pci_alloc_multi_resource(dev, child, type, rid, start, end,
count, 1, flags));
}
@@ -4718,6 +4737,22 @@ pci_release_resource(device_t dev, device_t child, int type, int rid,
dinfo = device_get_ivars(child);
cfg = &dinfo->cfg;
+
+#ifdef PCI_IOV
+ if (dinfo->cfg.flags & PCICFG_VF) {
+ switch (type) {
+ /* VFs can't have I/O BARs. */
+ case SYS_RES_IOPORT:
+ return (EDOOFUS);
+ case SYS_RES_MEMORY:
+ return (pci_vf_release_mem_resource(dev, child, rid,
+ r));
+ }
+
+ /* Fall through for other types of resource allocations. */
+ }
+#endif
+
#ifdef NEW_PCIB
/*
* PCI-PCI bridge I/O window resources are not BARs. For
OpenPOWER on IntegriCloud