From 8effc395c2097e258fcedfc02ed4a66d45fb4238 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sat, 21 Apr 2018 15:23:09 -0500 Subject: [PATCH] PCI/IOV: Add pci_sriov_configure_simple() SR-IOV (Single Root I/O Virtualization) is an optional PCIe capability (see PCIe r4.0, sec 9). A PCIe Function with the SR-IOV capability is referred to as a PF (Physical Function). If SR-IOV is enabled on the PF, several VFs (Virtual Functions) may be created. The VFs can be individually assigned to virtual machines, which allows them to share a single hardware device while being isolated from each other. Some SR-IOV devices have resources such as queues and interrupts that must be set up in the PF before enabling the VFs, so they require a PF driver to do that. Other SR-IOV devices don't require any PF setup before enabling VFs. Add a pci_sriov_configure_simple() interface so PF drivers for such devices can use it without repeating the VF-enabling code. Tested-by: Mark Rustad Signed-off-by: Alexander Duyck [bhelgaas: changelog, comment] Signed-off-by: Bjorn Helgaas Reviewed-by: Greg Rose Reviewed-by: Christoph Hellwig :wq --- drivers/pci/iov.c | 36 ++++++++++++++++++++++++++++++++++++ include/linux/pci.h | 2 ++ 2 files changed, 38 insertions(+) diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 8adf4a64f291..192b82898a38 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -833,3 +833,39 @@ int pci_sriov_get_totalvfs(struct pci_dev *dev) return dev->sriov->total_VFs; } EXPORT_SYMBOL_GPL(pci_sriov_get_totalvfs); + +/** + * pci_sriov_configure_simple - helper to configure SR-IOV + * @dev: the PCI device + * @nr_virtfn: number of virtual functions to enable, 0 to disable + * + * Enable or disable SR-IOV for devices that don't require any PF setup + * before enabling SR-IOV. Return value is negative on error, or number of + * VFs allocated on success. + */ +int pci_sriov_configure_simple(struct pci_dev *dev, int nr_virtfn) +{ + int rc; + + might_sleep(); + + if (!dev->is_physfn) + return -ENODEV; + + if (pci_vfs_assigned(dev)) { + pci_warn(dev, "Cannot modify SR-IOV while VFs are assigned\n"); + return -EPERM; + } + + if (nr_virtfn == 0) { + sriov_disable(dev); + return 0; + } + + rc = sriov_enable(dev, nr_virtfn); + if (rc < 0) + return rc; + + return nr_virtfn; +} +EXPORT_SYMBOL_GPL(pci_sriov_configure_simple); diff --git a/include/linux/pci.h b/include/linux/pci.h index 73178a2fcee0..911f9098a466 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1954,6 +1954,7 @@ int pci_num_vf(struct pci_dev *dev); int pci_vfs_assigned(struct pci_dev *dev); int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs); int pci_sriov_get_totalvfs(struct pci_dev *dev); +int pci_sriov_configure_simple(struct pci_dev *dev, int nr_virtfn); resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno); void pci_vf_drivers_autoprobe(struct pci_dev *dev, bool probe); @@ -1986,6 +1987,7 @@ static inline int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs) { return 0; } static inline int pci_sriov_get_totalvfs(struct pci_dev *dev) { return 0; } +#define pci_sriov_configure_simple NULL static inline resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno) { return 0; } static inline void pci_vf_drivers_autoprobe(struct pci_dev *dev, bool probe) { } -- 2.30.2