diff options
author | rstone <rstone@FreeBSD.org> | 2015-03-01 00:40:26 +0000 |
---|---|---|
committer | rstone <rstone@FreeBSD.org> | 2015-03-01 00:40:26 +0000 |
commit | 7a996d41b68bfc27452a84924998470fbfc2acbd (patch) | |
tree | 27cdf99df1fa9cb67ab09386bc428478c76c8ff1 /sys/dev/pci/pci.c | |
parent | 89058c6ddf90ce9df75bd000e86824b6d85b8a20 (diff) | |
download | FreeBSD-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.c | 35 |
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 |