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
577 struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);577 struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
578 struct device *dev = get_device(&vp_dev->vdev.dev);578 struct device *dev = get_device(&vp_dev->vdev.dev);
579 579
580 pci_disable_sriov(pci_dev);
581
580 unregister_virtio_device(&vp_dev->vdev);582 unregister_virtio_device(&vp_dev->vdev);
581 583
582 if (vp_dev->ioaddr)584 if (vp_dev->ioaddr)
@@ -588,6 +590,33 @@ static void virtio_pci_remove(struct pci_dev *pci_dev) · 5 unmodified lines
588 put_device(dev);590 put_device(dev);
589}591}
590 592
593static 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
591static struct pci_driver virtio_pci_driver = {620static struct pci_driver virtio_pci_driver = {
592 .name = "virtio-pci",621 .name = "virtio-pci",
593 .id_table = virtio_pci_id_table,622 .id_table = virtio_pci_id_table,
@@ -596,6 +625,7 @@ static struct pci_driver virtio_pci_driver = { · 2 unmodified lines
596#ifdef CONFIG_PM_SLEEP625#ifdef CONFIG_PM_SLEEP
597 .driver.pm = &virtio_pci_pm_ops,626 .driver.pm = &virtio_pci_pm_ops,
598#endif627#endif
628 .sriov_configure = virtio_pci_sriov_configure,
599};629};
600 630
601module_pci_driver(virtio_pci_driver);631module_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
153 return features;153 return features;
154}154}
155 155
156static 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
156/* virtio config->finalize_features() implementation */166/* virtio config->finalize_features() implementation */
157static int vp_finalize_features(struct virtio_device *vdev)167static int vp_finalize_features(struct virtio_device *vdev)
158{168{
159 struct virtio_pci_device *vp_dev = to_vp_device(vdev);169 struct virtio_pci_device *vp_dev = to_vp_device(vdev);
170 u64 features = vdev->features;
160 171
161 /* Give virtio_ring a chance to accept features. */172 /* Give virtio_ring a chance to accept features. */
162 vring_transport_features(vdev);173 vring_transport_features(vdev);
163 174
175 /* Give virtio_pci a chance to accept features. */
176 vp_transport_features(vdev, features);
177
164 if (!__virtio_test_bit(vdev, VIRTIO_F_VERSION_1)) {178 if (!__virtio_test_bit(vdev, VIRTIO_F_VERSION_1)) {
165 dev_err(&vdev->dev, "virtio: device uses modern interface "179 dev_err(&vdev->dev, "virtio: device uses modern interface "
166 "but does not have VIRTIO_F_VERSION_1\n");180 "but does not have VIRTIO_F_VERSION_1\n");
include/uapi/linux/virtio_config.h+6−1
@@ -49,7 +49,7 @@ · 48 unmodified lines
49 * transport being used (eg. virtio_ring), the rest are per-device feature49 * transport being used (eg. virtio_ring), the rest are per-device feature
50 * bits. */50 * bits. */
51#define VIRTIO_TRANSPORT_F_START 2851#define VIRTIO_TRANSPORT_F_START 28
52#define VIRTIO_TRANSPORT_F_END 3452#define VIRTIO_TRANSPORT_F_END 38
53 53
54#ifndef VIRTIO_CONFIG_NO_LEGACY54#ifndef VIRTIO_CONFIG_NO_LEGACY
55/* Do we get callbacks when the ring is completely used, even if we've55/* Do we get callbacks when the ring is completely used, even if we've
@@ -71,4 +71,9 @@ · 15 unmodified lines
71 * this is for compatibility with legacy systems.71 * this is for compatibility with legacy systems.
72 */72 */
73#define VIRTIO_F_IOMMU_PLATFORM 3373#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
74#endif /* _UAPI_LINUX_VIRTIO_CONFIG_H */79#endif /* _UAPI_LINUX_VIRTIO_CONFIG_H */