History

virtio_pci: support enabling VFs

There is a new feature bit allocated in virtio spec to support SR-IOV (Single Root I/O Virtualization): https://github.com/oasis-tcs/virtio-spec/issues/11 This patch enables the support for this feature bit in virtio driver.

Tiwei Bie committed 8 years ago

Commit cfecc291 parent 670ae9c3 files · +50 −1Browse files

Unified · Split

3 files
  1. drivers/virtio/virtio_pci_common.c +30 −0
  2. drivers/virtio/virtio_pci_modern.c +14 −0
  3. include/uapi/linux/virtio_config.h +6 −1
drivers/virtio/virtio_pci_common.c+30−0
@@ -577,6 +577,8 @@ static void virtio_pci_remove(struct pci_dev *pci_dev) · 576 unmodified lines
577577 struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
578578 struct device *dev = get_device(&vp_dev->vdev.dev);
579579
580+ pci_disable_sriov(pci_dev);
581+
580582 unregister_virtio_device(&vp_dev->vdev);
581583
582584 if (vp_dev->ioaddr)
@@ -588,6 +590,33 @@ static void virtio_pci_remove(struct pci_dev *pci_dev) · 5 unmodified lines
588590 put_device(dev);
589591 }
590592
593+static int virtio_pci_sriov_configure(struct pci_dev *pci_dev, int num_vfs)
594+{
595+ struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
596+ struct virtio_device *vdev = &vp_dev->vdev;
597+ int ret;
598+
599+ if (!(vdev->config->get_status(vdev) & VIRTIO_CONFIG_S_DRIVER_OK))
600+ return -EBUSY;
601+
602+ if (!__virtio_test_bit(vdev, VIRTIO_F_SR_IOV))
603+ return -EINVAL;
604+
605+ if (pci_vfs_assigned(pci_dev))
606+ return -EPERM;
607+
608+ if (num_vfs == 0) {
609+ pci_disable_sriov(pci_dev);
610+ return 0;
611+ }
612+
613+ ret = pci_enable_sriov(pci_dev, num_vfs);
614+ if (ret < 0)
615+ return ret;
616+
617+ return num_vfs;
618+}
619+
591620 static struct pci_driver virtio_pci_driver = {
592621 .name = "virtio-pci",
593622 .id_table = virtio_pci_id_table,
@@ -596,6 +625,7 @@ static struct pci_driver virtio_pci_driver = { · 2 unmodified lines
596625 #ifdef CONFIG_PM_SLEEP
597626 .driver.pm = &virtio_pci_pm_ops,
598627 #endif
628+ .sriov_configure = virtio_pci_sriov_configure,
599629 };
600630
601631 module_pci_driver(virtio_pci_driver);
drivers/virtio/virtio_pci_modern.c+14−0
@@ -153,14 +153,28 @@ static u64 vp_get_features(struct virtio_device *vdev) · 152 unmodified lines
153153 return features;
154154 }
155155
156+static void vp_transport_features(struct virtio_device *vdev, u64 features)
157+{
158+ struct virtio_pci_device *vp_dev = to_vp_device(vdev);
159+ struct pci_dev *pci_dev = vp_dev->pci_dev;
160+
161+ if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
162+ pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
163+ __virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
164+}
165+
156166 /* virtio config->finalize_features() implementation */
157167 static int vp_finalize_features(struct virtio_device *vdev)
158168 {
159169 struct virtio_pci_device *vp_dev = to_vp_device(vdev);
170+ u64 features = vdev->features;
160171
161172 /* Give virtio_ring a chance to accept features. */
162173 vring_transport_features(vdev);
163174
175+ /* Give virtio_pci a chance to accept features. */
176+ vp_transport_features(vdev, features);
177+
164178 if (!__virtio_test_bit(vdev, VIRTIO_F_VERSION_1)) {
165179 dev_err(&vdev->dev, "virtio: device uses modern interface "
166180 "but does not have VIRTIO_F_VERSION_1\n");
include/uapi/linux/virtio_config.h+6−1
@@ -49,7 +49,7 @@ · 48 unmodified lines
4949 * transport being used (eg. virtio_ring), the rest are per-device feature
5050 * bits. */
5151 #define VIRTIO_TRANSPORT_F_START 28
52−#define VIRTIO_TRANSPORT_F_END 34
52+#define VIRTIO_TRANSPORT_F_END 38
5353
5454 #ifndef VIRTIO_CONFIG_NO_LEGACY
5555 /* Do we get callbacks when the ring is completely used, even if we've
@@ -71,4 +71,9 @@ · 15 unmodified lines
7171 * this is for compatibility with legacy systems.
7272 */
7373 #define VIRTIO_F_IOMMU_PLATFORM 33
74+
75+/*
76+ * Does the device support Single Root I/O Virtualization?
77+ */
78+#define VIRTIO_F_SR_IOV 37
7479 #endif /* _UAPI_LINUX_VIRTIO_CONFIG_H */