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.
Unified · Split
| @@ -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 | ||
| 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 | |||
| 591 | static struct pci_driver virtio_pci_driver = { | 620 | static 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_SLEEP | 625 | #ifdef CONFIG_PM_SLEEP |
| 597 | .driver.pm = &virtio_pci_pm_ops, | 626 | .driver.pm = &virtio_pci_pm_ops, |
| 598 | #endif | 627 | #endif |
| 628 | .sriov_configure = virtio_pci_sriov_configure, | ||
| 599 | }; | 629 | }; |
| 600 | 630 | ||
| 601 | module_pci_driver(virtio_pci_driver); | 631 | module_pci_driver(virtio_pci_driver); |
| @@ -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 | ||
| 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 | |||
| 156 | /* virtio config->finalize_features() implementation */ | 166 | /* virtio config->finalize_features() implementation */ |
| 157 | static int vp_finalize_features(struct virtio_device *vdev) | 167 | static 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"); |
| @@ -49,7 +49,7 @@ · 48 unmodified lines | |||
| 49 | * transport being used (eg. virtio_ring), the rest are per-device feature | 49 | * transport being used (eg. virtio_ring), the rest are per-device feature |
| 50 | * bits. */ | 50 | * bits. */ |
| 51 | #define VIRTIO_TRANSPORT_F_START 28 | 51 | #define VIRTIO_TRANSPORT_F_START 28 |
| 52 | #define VIRTIO_TRANSPORT_F_END 34 | 52 | #define VIRTIO_TRANSPORT_F_END 38 |
| 53 | 53 | ||
| 54 | #ifndef VIRTIO_CONFIG_NO_LEGACY | 54 | #ifndef VIRTIO_CONFIG_NO_LEGACY |
| 55 | /* Do we get callbacks when the ring is completely used, even if we've | 55 | /* 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 33 | 73 | #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 */ |