Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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.

Signed-off-by: Tiwei Bie <tiwei.bie@intel.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

authored by

Tiwei Bie and committed by
Michael S. Tsirkin
cfecc291 670ae9ca

+50 -1
+30
drivers/virtio/virtio_pci_common.c
··· 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) ··· 590 588 put_device(dev); 591 589 } 592 590 591 + static int virtio_pci_sriov_configure(struct pci_dev *pci_dev, int num_vfs) 592 + { 593 + struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); 594 + struct virtio_device *vdev = &vp_dev->vdev; 595 + int ret; 596 + 597 + if (!(vdev->config->get_status(vdev) & VIRTIO_CONFIG_S_DRIVER_OK)) 598 + return -EBUSY; 599 + 600 + if (!__virtio_test_bit(vdev, VIRTIO_F_SR_IOV)) 601 + return -EINVAL; 602 + 603 + if (pci_vfs_assigned(pci_dev)) 604 + return -EPERM; 605 + 606 + if (num_vfs == 0) { 607 + pci_disable_sriov(pci_dev); 608 + return 0; 609 + } 610 + 611 + ret = pci_enable_sriov(pci_dev, num_vfs); 612 + if (ret < 0) 613 + return ret; 614 + 615 + return num_vfs; 616 + } 617 + 593 618 static struct pci_driver virtio_pci_driver = { 594 619 .name = "virtio-pci", 595 620 .id_table = virtio_pci_id_table, ··· 625 596 #ifdef CONFIG_PM_SLEEP 626 597 .driver.pm = &virtio_pci_pm_ops, 627 598 #endif 599 + .sriov_configure = virtio_pci_sriov_configure, 628 600 }; 629 601 630 602 module_pci_driver(virtio_pci_driver);
+14
drivers/virtio/virtio_pci_modern.c
··· 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); 174 + 175 + /* Give virtio_pci a chance to accept features. */ 176 + vp_transport_features(vdev, features); 163 177 164 178 if (!__virtio_test_bit(vdev, VIRTIO_F_VERSION_1)) { 165 179 dev_err(&vdev->dev, "virtio: device uses modern interface "
+6 -1
include/uapi/linux/virtio_config.h
··· 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 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 */