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