[Intel-wired-lan] [PATCH] virtio_pci: Add SR-IOV support
Mark D Rustad
mark.d.rustad at intel.com
Sat Feb 10 00:10:02 UTC 2018
From: Mark Rustad <mark.d.rustad at intel.com>
Hardware-realized virtio devices can implement SR-IOV, so enable
its use.
Signed-off-by: Mark Rustad <mark.d.rustad at intel.com>
---
drivers/virtio/virtio_pci_common.c | 64 ++++++++++++++++++++++++++++++++++++
drivers/virtio/virtio_pci_common.h | 3 ++
2 files changed, 67 insertions(+)
diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index 1c4797e53f68..c46bbad57e67 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -584,6 +584,67 @@ static void virtio_pci_remove(struct pci_dev *pci_dev)
put_device(dev);
}
+#ifdef CONFIG_PCI_IOV
+static int _virtio_pci_sriov_disable(struct virtio_pci_device *vp_dev,
+ struct pci_dev *pci_dev)
+{
+ vp_dev->num_vfs = 0;
+ /* If vfs are assigned we cannot shut down SR-IOV without causing
+ * issues, so just leave the hardware available.
+ */
+ if (pci_vfs_assigned(pci_dev)) {
+ dev_warn(&pci_dev->dev,
+ "Unloading driver while VFs are assigned - VFs will not be deallocated\n");
+ return -EPERM;
+ }
+ pci_disable_sriov(pci_dev);
+ return 0;
+}
+
+static int virtio_pci_sriov_disable(struct pci_dev *pci_dev)
+{
+ struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
+
+ if (!vp_dev->num_vfs && !pci_num_vf(pci_dev))
+ return -EINVAL;
+
+ return _virtio_pci_sriov_disable(vp_dev, pci_dev);
+}
+
+static int virtio_pci_sriov_enable(struct pci_dev *pci_dev, int num_vfs)
+{
+ struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
+ int pre_existing_vfs = pci_num_vf(pci_dev);
+ int rc = 0;
+
+ if (vp_dev->num_vfs == num_vfs)
+ return -EINVAL;
+
+ if (pre_existing_vfs && pre_existing_vfs != num_vfs)
+ rc = _virtio_pci_sriov_disable(vp_dev, pci_dev);
+ else if (pre_existing_vfs && pre_existing_vfs == num_vfs)
+ return num_vfs;
+ if (rc)
+ return rc;
+
+ rc = pci_enable_sriov(pci_dev, num_vfs);
+ if (rc) {
+ dev_warn(&pci_dev->dev, "Failed to enable PCI sriov: %d\n", rc);
+ return rc;
+ }
+ vp_dev->num_vfs = num_vfs;
+ dev_info(&pci_dev->dev, "SR-IOV enabled with %d VFs\n", num_vfs);
+ return num_vfs;
+}
+
+static int virtio_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
+{
+ if (!num_vfs)
+ return virtio_pci_sriov_disable(dev);
+ return virtio_pci_sriov_enable(dev, num_vfs);
+}
+#endif /* CONFIG_PCI_IOV */
+
static struct pci_driver virtio_pci_driver = {
.name = "virtio-pci",
.id_table = virtio_pci_id_table,
@@ -592,6 +653,9 @@ static void virtio_pci_remove(struct pci_dev *pci_dev)
#ifdef CONFIG_PM_SLEEP
.driver.pm = &virtio_pci_pm_ops,
#endif
+#ifdef CONFIG_PCI_IOV
+ .sriov_configure = virtio_pci_sriov_configure,
+#endif
};
module_pci_driver(virtio_pci_driver);
diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
index 135ee3cf7175..7d3910c15e99 100644
--- a/drivers/virtio/virtio_pci_common.h
+++ b/drivers/virtio/virtio_pci_common.h
@@ -94,6 +94,9 @@ struct virtio_pci_device {
/* Vectors allocated, excluding per-vq vectors if any */
unsigned msix_used_vectors;
+ /* Number of VFs allocated */
+ int num_vfs;
+
/* Whether we have vector per vq */
bool per_vq_vectors;
More information about the Intel-wired-lan
mailing list