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

Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost

Pull virtio updates from Michael Tsirkin:
"Several new features here:

- Virtio find vqs API has been reworked (required to fix the
scalability issue we have with adminq, which I hope to merge later
in the cycle)

- vDPA driver for Marvell OCTEON

- virtio fs performance improvement

- mlx5 migration speedups

Fixes, cleanups all over the place"

* tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost: (56 commits)
virtio: rename virtio_find_vqs_info() to virtio_find_vqs()
virtio: remove unused virtio_find_vqs() and virtio_find_vqs_ctx() helpers
virtio: convert the rest virtio_find_vqs() users to virtio_find_vqs_info()
virtio_balloon: convert to use virtio_find_vqs_info()
virtiofs: convert to use virtio_find_vqs_info()
scsi: virtio_scsi: convert to use virtio_find_vqs_info()
virtio_net: convert to use virtio_find_vqs_info()
virtio_crypto: convert to use virtio_find_vqs_info()
virtio_console: convert to use virtio_find_vqs_info()
virtio_blk: convert to use virtio_find_vqs_info()
virtio: rename find_vqs_info() op to find_vqs()
virtio: remove the original find_vqs() op
virtio: call virtio_find_vqs_info() from virtio_find_single_vq() directly
virtio: convert find_vqs() op implementations to find_vqs_info()
virtio_pci: convert vp_*find_vqs() ops to find_vqs_info()
virtio: introduce virtio_queue_info struct and find_vqs_info() config op
virtio: make virtio_find_single_vq() call virtio_find_vqs()
virtio: make virtio_find_vqs() call virtio_find_vqs_ctx()
caif_virtio: use virtio_find_single_vq() for single virtqueue finding
vdpa/mlx5: Don't enable non-active VQs in .set_vq_ready()
...

+2145 -543
+6 -1
MAINTAINERS
··· 10786 10786 F: net/mac802154/ 10787 10787 10788 10788 Intel VIRTIO DATA PATH ACCELERATOR 10789 - M: Zhu Lingshan <lingshan.zhu@intel.com> 10789 + M: Zhu Lingshan <lingshan.zhu@kernel.org> 10790 10790 L: virtualization@lists.linux.dev 10791 10791 S: Supported 10792 10792 F: drivers/vdpa/ifcvf/ ··· 13610 13610 S: Supported 13611 13611 F: Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.yaml 13612 13612 F: drivers/mmc/host/sdhci-xenon* 13613 + 13614 + MARVELL OCTEON ENDPOINT VIRTIO DATA PATH ACCELERATOR 13615 + R: schalla@marvell.com 13616 + R: vattunuru@marvell.com 13617 + F: drivers/vdpa/octeon_ep/ 13613 13618 13614 13619 MATROX FRAMEBUFFER DRIVER 13615 13620 L: linux-fbdev@vger.kernel.org
+5 -3
arch/um/drivers/virt-pci.c
··· 567 567 568 568 static int um_pci_init_vqs(struct um_pci_device *dev) 569 569 { 570 + struct virtqueue_info vqs_info[] = { 571 + { "cmd", um_pci_cmd_vq_cb }, 572 + { "irq", um_pci_irq_vq_cb }, 573 + }; 570 574 struct virtqueue *vqs[2]; 571 - static const char *const names[2] = { "cmd", "irq" }; 572 - vq_callback_t *cbs[2] = { um_pci_cmd_vq_cb, um_pci_irq_vq_cb }; 573 575 int err, i; 574 576 575 - err = virtio_find_vqs(dev->vdev, 2, vqs, cbs, names, NULL); 577 + err = virtio_find_vqs(dev->vdev, 2, vqs, vqs_info, NULL); 576 578 if (err) 577 579 return err; 578 580
+7 -5
arch/um/drivers/virtio_uml.c
··· 1014 1014 } 1015 1015 1016 1016 static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs, 1017 - struct virtqueue *vqs[], vq_callback_t *callbacks[], 1018 - const char * const names[], const bool *ctx, 1017 + struct virtqueue *vqs[], 1018 + struct virtqueue_info vqs_info[], 1019 1019 struct irq_affinity *desc) 1020 1020 { 1021 1021 struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev); ··· 1031 1031 return rc; 1032 1032 1033 1033 for (i = 0; i < nvqs; ++i) { 1034 - if (!names[i]) { 1034 + struct virtqueue_info *vqi = &vqs_info[i]; 1035 + 1036 + if (!vqi->name) { 1035 1037 vqs[i] = NULL; 1036 1038 continue; 1037 1039 } 1038 1040 1039 - vqs[i] = vu_setup_vq(vdev, queue_idx++, callbacks[i], names[i], 1040 - ctx ? ctx[i] : false); 1041 + vqs[i] = vu_setup_vq(vdev, queue_idx++, vqi->callback, 1042 + vqi->name, vqi->ctx); 1041 1043 if (IS_ERR(vqs[i])) { 1042 1044 rc = PTR_ERR(vqs[i]); 1043 1045 goto error_setup;
+8 -12
drivers/block/virtio_blk.c
··· 964 964 { 965 965 int err; 966 966 unsigned short i; 967 - vq_callback_t **callbacks; 968 - const char **names; 967 + struct virtqueue_info *vqs_info; 969 968 struct virtqueue **vqs; 970 969 unsigned short num_vqs; 971 970 unsigned short num_poll_vqs; ··· 1001 1002 if (!vblk->vqs) 1002 1003 return -ENOMEM; 1003 1004 1004 - names = kmalloc_array(num_vqs, sizeof(*names), GFP_KERNEL); 1005 - callbacks = kmalloc_array(num_vqs, sizeof(*callbacks), GFP_KERNEL); 1005 + vqs_info = kcalloc(num_vqs, sizeof(*vqs_info), GFP_KERNEL); 1006 1006 vqs = kmalloc_array(num_vqs, sizeof(*vqs), GFP_KERNEL); 1007 - if (!names || !callbacks || !vqs) { 1007 + if (!vqs_info || !vqs) { 1008 1008 err = -ENOMEM; 1009 1009 goto out; 1010 1010 } 1011 1011 1012 1012 for (i = 0; i < num_vqs - num_poll_vqs; i++) { 1013 - callbacks[i] = virtblk_done; 1013 + vqs_info[i].callback = virtblk_done; 1014 1014 snprintf(vblk->vqs[i].name, VQ_NAME_LEN, "req.%u", i); 1015 - names[i] = vblk->vqs[i].name; 1015 + vqs_info[i].name = vblk->vqs[i].name; 1016 1016 } 1017 1017 1018 1018 for (; i < num_vqs; i++) { 1019 - callbacks[i] = NULL; 1020 1019 snprintf(vblk->vqs[i].name, VQ_NAME_LEN, "req_poll.%u", i); 1021 - names[i] = vblk->vqs[i].name; 1020 + vqs_info[i].name = vblk->vqs[i].name; 1022 1021 } 1023 1022 1024 1023 /* Discover virtqueues and write information to configuration. */ 1025 - err = virtio_find_vqs(vdev, num_vqs, vqs, callbacks, names, &desc); 1024 + err = virtio_find_vqs(vdev, num_vqs, vqs, vqs_info, &desc); 1026 1025 if (err) 1027 1026 goto out; 1028 1027 ··· 1032 1035 1033 1036 out: 1034 1037 kfree(vqs); 1035 - kfree(callbacks); 1036 - kfree(names); 1038 + kfree(vqs_info); 1037 1039 if (err) 1038 1040 kfree(vblk->vqs); 1039 1041 return err;
+4 -9
drivers/bluetooth/virtio_bt.c
··· 254 254 255 255 static int virtbt_probe(struct virtio_device *vdev) 256 256 { 257 - vq_callback_t *callbacks[VIRTBT_NUM_VQS] = { 258 - [VIRTBT_VQ_TX] = virtbt_tx_done, 259 - [VIRTBT_VQ_RX] = virtbt_rx_done, 260 - }; 261 - const char *names[VIRTBT_NUM_VQS] = { 262 - [VIRTBT_VQ_TX] = "tx", 263 - [VIRTBT_VQ_RX] = "rx", 257 + struct virtqueue_info vqs_info[VIRTBT_NUM_VQS] = { 258 + [VIRTBT_VQ_TX] = { "tx", virtbt_tx_done }, 259 + [VIRTBT_VQ_RX] = { "rx", virtbt_rx_done }, 264 260 }; 265 261 struct virtio_bluetooth *vbt; 266 262 struct hci_dev *hdev; ··· 284 288 285 289 INIT_WORK(&vbt->rx, virtbt_rx_work); 286 290 287 - err = virtio_find_vqs(vdev, VIRTBT_NUM_VQS, vbt->vqs, callbacks, 288 - names, NULL); 291 + err = virtio_find_vqs(vdev, VIRTBT_NUM_VQS, vbt->vqs, vqs_info, NULL); 289 292 if (err) 290 293 return err; 291 294
+17 -26
drivers/char/virtio_console.c
··· 1804 1804 1805 1805 static int init_vqs(struct ports_device *portdev) 1806 1806 { 1807 - vq_callback_t **io_callbacks; 1808 - char **io_names; 1807 + struct virtqueue_info *vqs_info; 1809 1808 struct virtqueue **vqs; 1810 1809 u32 i, j, nr_ports, nr_queues; 1811 1810 int err; ··· 1813 1814 nr_queues = use_multiport(portdev) ? (nr_ports + 1) * 2 : 2; 1814 1815 1815 1816 vqs = kmalloc_array(nr_queues, sizeof(struct virtqueue *), GFP_KERNEL); 1816 - io_callbacks = kmalloc_array(nr_queues, sizeof(vq_callback_t *), 1817 - GFP_KERNEL); 1818 - io_names = kmalloc_array(nr_queues, sizeof(char *), GFP_KERNEL); 1817 + vqs_info = kcalloc(nr_queues, sizeof(*vqs_info), GFP_KERNEL); 1819 1818 portdev->in_vqs = kmalloc_array(nr_ports, sizeof(struct virtqueue *), 1820 1819 GFP_KERNEL); 1821 1820 portdev->out_vqs = kmalloc_array(nr_ports, sizeof(struct virtqueue *), 1822 1821 GFP_KERNEL); 1823 - if (!vqs || !io_callbacks || !io_names || !portdev->in_vqs || 1824 - !portdev->out_vqs) { 1822 + if (!vqs || !vqs_info || !portdev->in_vqs || !portdev->out_vqs) { 1825 1823 err = -ENOMEM; 1826 1824 goto free; 1827 1825 } ··· 1829 1833 * 0 before others. 1830 1834 */ 1831 1835 j = 0; 1832 - io_callbacks[j] = in_intr; 1833 - io_callbacks[j + 1] = out_intr; 1834 - io_names[j] = "input"; 1835 - io_names[j + 1] = "output"; 1836 + vqs_info[j].callback = in_intr; 1837 + vqs_info[j + 1].callback = out_intr; 1838 + vqs_info[j].name = "input"; 1839 + vqs_info[j + 1].name = "output"; 1836 1840 j += 2; 1837 1841 1838 1842 if (use_multiport(portdev)) { 1839 - io_callbacks[j] = control_intr; 1840 - io_callbacks[j + 1] = NULL; 1841 - io_names[j] = "control-i"; 1842 - io_names[j + 1] = "control-o"; 1843 + vqs_info[j].callback = control_intr; 1844 + vqs_info[j].name = "control-i"; 1845 + vqs_info[j + 1].name = "control-o"; 1843 1846 1844 1847 for (i = 1; i < nr_ports; i++) { 1845 1848 j += 2; 1846 - io_callbacks[j] = in_intr; 1847 - io_callbacks[j + 1] = out_intr; 1848 - io_names[j] = "input"; 1849 - io_names[j + 1] = "output"; 1849 + vqs_info[j].callback = in_intr; 1850 + vqs_info[j + 1].callback = out_intr; 1851 + vqs_info[j].name = "input"; 1852 + vqs_info[j + 1].name = "output"; 1850 1853 } 1851 1854 } 1852 1855 /* Find the queues. */ 1853 - err = virtio_find_vqs(portdev->vdev, nr_queues, vqs, 1854 - io_callbacks, 1855 - (const char **)io_names, NULL); 1856 + err = virtio_find_vqs(portdev->vdev, nr_queues, vqs, vqs_info, NULL); 1856 1857 if (err) 1857 1858 goto free; 1858 1859 ··· 1867 1874 portdev->out_vqs[i] = vqs[j + 1]; 1868 1875 } 1869 1876 } 1870 - kfree(io_names); 1871 - kfree(io_callbacks); 1877 + kfree(vqs_info); 1872 1878 kfree(vqs); 1873 1879 1874 1880 return 0; ··· 1875 1883 free: 1876 1884 kfree(portdev->out_vqs); 1877 1885 kfree(portdev->in_vqs); 1878 - kfree(io_names); 1879 - kfree(io_callbacks); 1886 + kfree(vqs_info); 1880 1887 kfree(vqs); 1881 1888 1882 1889 return err;
+12 -19
drivers/crypto/virtio/virtio_crypto_core.c
··· 96 96 97 97 static int virtcrypto_find_vqs(struct virtio_crypto *vi) 98 98 { 99 - vq_callback_t **callbacks; 99 + struct virtqueue_info *vqs_info; 100 100 struct virtqueue **vqs; 101 101 int ret = -ENOMEM; 102 102 int i, total_vqs; 103 - const char **names; 104 103 struct device *dev = &vi->vdev->dev; 105 104 106 105 /* ··· 113 114 vqs = kcalloc(total_vqs, sizeof(*vqs), GFP_KERNEL); 114 115 if (!vqs) 115 116 goto err_vq; 116 - callbacks = kcalloc(total_vqs, sizeof(*callbacks), GFP_KERNEL); 117 - if (!callbacks) 118 - goto err_callback; 119 - names = kcalloc(total_vqs, sizeof(*names), GFP_KERNEL); 120 - if (!names) 121 - goto err_names; 117 + vqs_info = kcalloc(total_vqs, sizeof(*vqs_info), GFP_KERNEL); 118 + if (!vqs_info) 119 + goto err_vqs_info; 122 120 123 121 /* Parameters for control virtqueue */ 124 - callbacks[total_vqs - 1] = virtcrypto_ctrlq_callback; 125 - names[total_vqs - 1] = "controlq"; 122 + vqs_info[total_vqs - 1].callback = virtcrypto_ctrlq_callback; 123 + vqs_info[total_vqs - 1].name = "controlq"; 126 124 127 125 /* Allocate/initialize parameters for data virtqueues */ 128 126 for (i = 0; i < vi->max_data_queues; i++) { 129 - callbacks[i] = virtcrypto_dataq_callback; 127 + vqs_info[i].callback = virtcrypto_dataq_callback; 130 128 snprintf(vi->data_vq[i].name, sizeof(vi->data_vq[i].name), 131 129 "dataq.%d", i); 132 - names[i] = vi->data_vq[i].name; 130 + vqs_info[i].name = vi->data_vq[i].name; 133 131 } 134 132 135 - ret = virtio_find_vqs(vi->vdev, total_vqs, vqs, callbacks, names, NULL); 133 + ret = virtio_find_vqs(vi->vdev, total_vqs, vqs, vqs_info, NULL); 136 134 if (ret) 137 135 goto err_find; 138 136 ··· 149 153 (unsigned long)&vi->data_vq[i]); 150 154 } 151 155 152 - kfree(names); 153 - kfree(callbacks); 156 + kfree(vqs_info); 154 157 kfree(vqs); 155 158 156 159 return 0; 157 160 158 161 err_engine: 159 162 err_find: 160 - kfree(names); 161 - err_names: 162 - kfree(callbacks); 163 - err_callback: 163 + kfree(vqs_info); 164 + err_vqs_info: 164 165 kfree(vqs); 165 166 err_vq: 166 167 return ret;
+4 -7
drivers/firmware/arm_scmi/virtio.c
··· 354 354 scmi_vio_channel_release(vioch); 355 355 } 356 356 357 - static const char *const scmi_vio_vqueue_names[] = { "tx", "rx" }; 358 - 359 - static vq_callback_t *scmi_vio_complete_callbacks[] = { 360 - scmi_vio_complete_cb, 361 - scmi_vio_complete_cb 357 + static struct virtqueue_info scmi_vio_vqs_info[] = { 358 + { "tx", scmi_vio_complete_cb }, 359 + { "rx", scmi_vio_complete_cb }, 362 360 }; 363 361 364 362 static unsigned int virtio_get_max_msg(struct scmi_chan_info *base_cinfo) ··· 829 831 if (have_vq_rx) 830 832 channels[VIRTIO_SCMI_VQ_RX].is_rx = true; 831 833 832 - ret = virtio_find_vqs(vdev, vq_cnt, vqs, scmi_vio_complete_callbacks, 833 - scmi_vio_vqueue_names, NULL); 834 + ret = virtio_find_vqs(vdev, vq_cnt, vqs, scmi_vio_vqs_info, NULL); 834 835 if (ret) { 835 836 dev_err(dev, "Failed to get %d virtqueue(s)\n", vq_cnt); 836 837 return ret;
+5 -5
drivers/gpio/gpio-virtio.c
··· 457 457 static int virtio_gpio_alloc_vqs(struct virtio_gpio *vgpio, 458 458 struct virtio_device *vdev) 459 459 { 460 - const char * const names[] = { "requestq", "eventq" }; 461 - vq_callback_t *cbs[] = { 462 - virtio_gpio_request_vq, 463 - virtio_gpio_event_vq, 460 + struct virtqueue_info vqs_info[] = { 461 + { "requestq", virtio_gpio_request_vq }, 462 + { "eventq", virtio_gpio_event_vq }, 464 463 }; 465 464 struct virtqueue *vqs[2] = { NULL, NULL }; 466 465 int ret; 467 466 468 - ret = virtio_find_vqs(vdev, vgpio->irq_lines ? 2 : 1, vqs, cbs, names, NULL); 467 + ret = virtio_find_vqs(vdev, vgpio->irq_lines ? 2 : 1, vqs, 468 + vqs_info, NULL); 469 469 if (ret) { 470 470 dev_err(&vdev->dev, "failed to find vqs: %d\n", ret); 471 471 return ret;
+4 -5
drivers/gpu/drm/virtio/virtgpu_kms.c
··· 116 116 117 117 int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev) 118 118 { 119 - static vq_callback_t *callbacks[] = { 120 - virtio_gpu_ctrl_ack, virtio_gpu_cursor_ack 119 + struct virtqueue_info vqs_info[] = { 120 + { "control", virtio_gpu_ctrl_ack }, 121 + { "cursor", virtio_gpu_cursor_ack }, 121 122 }; 122 - static const char * const names[] = { "control", "cursor" }; 123 - 124 123 struct virtio_gpu_device *vgdev; 125 124 /* this will expand later */ 126 125 struct virtqueue *vqs[2]; ··· 206 207 DRM_INFO("features: %ccontext_init\n", 207 208 vgdev->has_context_init ? '+' : '-'); 208 209 209 - ret = virtio_find_vqs(vgdev->vdev, 2, vqs, callbacks, names, NULL); 210 + ret = virtio_find_vqs(vgdev->vdev, 2, vqs, vqs_info, NULL); 210 211 if (ret) { 211 212 DRM_ERROR("failed to find virt queues\n"); 212 213 goto err_vqs;
+5 -6
drivers/iommu/virtio-iommu.c
··· 1084 1084 static int viommu_init_vqs(struct viommu_dev *viommu) 1085 1085 { 1086 1086 struct virtio_device *vdev = dev_to_virtio(viommu->dev); 1087 - const char *names[] = { "request", "event" }; 1088 - vq_callback_t *callbacks[] = { 1089 - NULL, /* No async requests */ 1090 - viommu_event_handler, 1087 + struct virtqueue_info vqs_info[] = { 1088 + { "request" }, 1089 + { "event", viommu_event_handler }, 1091 1090 }; 1092 1091 1093 - return virtio_find_vqs(vdev, VIOMMU_NR_VQS, viommu->vqs, callbacks, 1094 - names, NULL); 1092 + return virtio_find_vqs(vdev, VIOMMU_NR_VQS, viommu->vqs, 1093 + vqs_info, NULL); 1095 1094 } 1096 1095 1097 1096 static int viommu_fill_evtq(struct viommu_dev *viommu)
+4 -4
drivers/net/caif/caif_virtio.c
··· 646 646 /* Setup CAIF for the a virtio device */ 647 647 static int cfv_probe(struct virtio_device *vdev) 648 648 { 649 - vq_callback_t *vq_cbs = cfv_release_cb; 650 649 vrh_callback_t *vrh_cbs = cfv_recv; 651 - const char *names = "output"; 652 650 const char *cfv_netdev_name = "cfvrt"; 653 651 struct net_device *netdev; 654 652 struct cfv_info *cfv; ··· 673 675 goto err; 674 676 675 677 /* Get the TX virtio ring. This is a "guest side vring". */ 676 - err = virtio_find_vqs(vdev, 1, &cfv->vq_tx, &vq_cbs, &names, NULL); 677 - if (err) 678 + cfv->vq_tx = virtio_find_single_vq(vdev, cfv_release_cb, "output"); 679 + if (IS_ERR(cfv->vq_tx)) { 680 + err = PTR_ERR(cfv->vq_tx); 678 681 goto err; 682 + } 679 683 680 684 /* Get the CAIF configuration from virtio config space, if available */ 681 685 if (vdev->config->get) {
+13 -21
drivers/net/virtio_net.c
··· 5946 5946 5947 5947 static int virtnet_find_vqs(struct virtnet_info *vi) 5948 5948 { 5949 - vq_callback_t **callbacks; 5949 + struct virtqueue_info *vqs_info; 5950 5950 struct virtqueue **vqs; 5951 - const char **names; 5952 5951 int ret = -ENOMEM; 5953 5952 int total_vqs; 5954 5953 bool *ctx; ··· 5964 5965 vqs = kcalloc(total_vqs, sizeof(*vqs), GFP_KERNEL); 5965 5966 if (!vqs) 5966 5967 goto err_vq; 5967 - callbacks = kmalloc_array(total_vqs, sizeof(*callbacks), GFP_KERNEL); 5968 - if (!callbacks) 5969 - goto err_callback; 5970 - names = kmalloc_array(total_vqs, sizeof(*names), GFP_KERNEL); 5971 - if (!names) 5972 - goto err_names; 5968 + vqs_info = kcalloc(total_vqs, sizeof(*vqs_info), GFP_KERNEL); 5969 + if (!vqs_info) 5970 + goto err_vqs_info; 5973 5971 if (!vi->big_packets || vi->mergeable_rx_bufs) { 5974 5972 ctx = kcalloc(total_vqs, sizeof(*ctx), GFP_KERNEL); 5975 5973 if (!ctx) ··· 5977 5981 5978 5982 /* Parameters for control virtqueue, if any */ 5979 5983 if (vi->has_cvq) { 5980 - callbacks[total_vqs - 1] = NULL; 5981 - names[total_vqs - 1] = "control"; 5984 + vqs_info[total_vqs - 1].name = "control"; 5982 5985 } 5983 5986 5984 5987 /* Allocate/initialize parameters for send/receive virtqueues */ 5985 5988 for (i = 0; i < vi->max_queue_pairs; i++) { 5986 - callbacks[rxq2vq(i)] = skb_recv_done; 5987 - callbacks[txq2vq(i)] = skb_xmit_done; 5989 + vqs_info[rxq2vq(i)].callback = skb_recv_done; 5990 + vqs_info[txq2vq(i)].callback = skb_xmit_done; 5988 5991 sprintf(vi->rq[i].name, "input.%u", i); 5989 5992 sprintf(vi->sq[i].name, "output.%u", i); 5990 - names[rxq2vq(i)] = vi->rq[i].name; 5991 - names[txq2vq(i)] = vi->sq[i].name; 5993 + vqs_info[rxq2vq(i)].name = vi->rq[i].name; 5994 + vqs_info[txq2vq(i)].name = vi->sq[i].name; 5992 5995 if (ctx) 5993 - ctx[rxq2vq(i)] = true; 5996 + vqs_info[rxq2vq(i)].ctx = true; 5994 5997 } 5995 5998 5996 - ret = virtio_find_vqs_ctx(vi->vdev, total_vqs, vqs, callbacks, 5997 - names, ctx, NULL); 5999 + ret = virtio_find_vqs(vi->vdev, total_vqs, vqs, vqs_info, NULL); 5998 6000 if (ret) 5999 6001 goto err_find; 6000 6002 ··· 6014 6020 err_find: 6015 6021 kfree(ctx); 6016 6022 err_ctx: 6017 - kfree(names); 6018 - err_names: 6019 - kfree(callbacks); 6020 - err_callback: 6023 + kfree(vqs_info); 6024 + err_vqs_info: 6021 6025 kfree(vqs); 6022 6026 err_vq: 6023 6027 return ret;
+4 -8
drivers/net/wireless/virtual/mac80211_hwsim.c
··· 6626 6626 6627 6627 static int init_vqs(struct virtio_device *vdev) 6628 6628 { 6629 - vq_callback_t *callbacks[HWSIM_NUM_VQS] = { 6630 - [HWSIM_VQ_TX] = hwsim_virtio_tx_done, 6631 - [HWSIM_VQ_RX] = hwsim_virtio_rx_done, 6632 - }; 6633 - const char *names[HWSIM_NUM_VQS] = { 6634 - [HWSIM_VQ_TX] = "tx", 6635 - [HWSIM_VQ_RX] = "rx", 6629 + struct virtqueue_info vqs_info[HWSIM_NUM_VQS] = { 6630 + [HWSIM_VQ_TX] = { "tx", hwsim_virtio_tx_done }, 6631 + [HWSIM_VQ_RX] = { "rx", hwsim_virtio_rx_done }, 6636 6632 }; 6637 6633 6638 6634 return virtio_find_vqs(vdev, HWSIM_NUM_VQS, 6639 - hwsim_vqs, callbacks, names, NULL); 6635 + hwsim_vqs, vqs_info, NULL); 6640 6636 } 6641 6637 6642 6638 static int fill_vq(struct virtqueue *vq)
+5 -5
drivers/platform/mellanox/mlxbf-tmfifo.c
··· 1058 1058 static int mlxbf_tmfifo_virtio_find_vqs(struct virtio_device *vdev, 1059 1059 unsigned int nvqs, 1060 1060 struct virtqueue *vqs[], 1061 - vq_callback_t *callbacks[], 1062 - const char * const names[], 1063 - const bool *ctx, 1061 + struct virtqueue_info vqs_info[], 1064 1062 struct irq_affinity *desc) 1065 1063 { 1066 1064 struct mlxbf_tmfifo_vdev *tm_vdev = mlxbf_vdev_to_tmfifo(vdev); ··· 1070 1072 return -EINVAL; 1071 1073 1072 1074 for (i = 0; i < nvqs; ++i) { 1073 - if (!names[i]) { 1075 + struct virtqueue_info *vqi = &vqs_info[i]; 1076 + 1077 + if (!vqi->name) { 1074 1078 ret = -EINVAL; 1075 1079 goto error; 1076 1080 } ··· 1084 1084 vq = vring_new_virtqueue(i, vring->num, vring->align, vdev, 1085 1085 false, false, vring->va, 1086 1086 mlxbf_tmfifo_virtio_notify, 1087 - callbacks[i], names[i]); 1087 + vqi->callback, vqi->name); 1088 1088 if (!vq) { 1089 1089 dev_err(&vdev->dev, "vring_new_virtqueue failed\n"); 1090 1090 ret = -ENOMEM;
+6 -6
drivers/remoteproc/remoteproc_virtio.c
··· 182 182 183 183 static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs, 184 184 struct virtqueue *vqs[], 185 - vq_callback_t *callbacks[], 186 - const char * const names[], 187 - const bool * ctx, 185 + struct virtqueue_info vqs_info[], 188 186 struct irq_affinity *desc) 189 187 { 190 188 int i, ret, queue_idx = 0; 191 189 192 190 for (i = 0; i < nvqs; ++i) { 193 - if (!names[i]) { 191 + struct virtqueue_info *vqi = &vqs_info[i]; 192 + 193 + if (!vqi->name) { 194 194 vqs[i] = NULL; 195 195 continue; 196 196 } 197 197 198 - vqs[i] = rp_find_vq(vdev, queue_idx++, callbacks[i], names[i], 199 - ctx ? ctx[i] : false); 198 + vqs[i] = rp_find_vq(vdev, queue_idx++, vqi->callback, 199 + vqi->name, vqi->ctx); 200 200 if (IS_ERR(vqs[i])) { 201 201 ret = PTR_ERR(vqs[i]); 202 202 goto error;
+5 -3
drivers/rpmsg/virtio_rpmsg_bus.c
··· 868 868 869 869 static int rpmsg_probe(struct virtio_device *vdev) 870 870 { 871 - vq_callback_t *vq_cbs[] = { rpmsg_recv_done, rpmsg_xmit_done }; 872 - static const char * const names[] = { "input", "output" }; 871 + struct virtqueue_info vqs_info[] = { 872 + { "input", rpmsg_recv_done }, 873 + { "output", rpmsg_xmit_done }, 874 + }; 873 875 struct virtqueue *vqs[2]; 874 876 struct virtproc_info *vrp; 875 877 struct virtio_rpmsg_channel *vch = NULL; ··· 893 891 init_waitqueue_head(&vrp->sendq); 894 892 895 893 /* We expect two virtqueues, rx and tx (and in this order) */ 896 - err = virtio_find_vqs(vdev, 2, vqs, vq_cbs, names, NULL); 894 + err = virtio_find_vqs(vdev, 2, vqs, vqs_info, NULL); 897 895 if (err) 898 896 goto free_vrp; 899 897
+6 -7
drivers/s390/virtio/virtio_ccw.c
··· 689 689 690 690 static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs, 691 691 struct virtqueue *vqs[], 692 - vq_callback_t *callbacks[], 693 - const char * const names[], 694 - const bool *ctx, 692 + struct virtqueue_info vqs_info[], 695 693 struct irq_affinity *desc) 696 694 { 697 695 struct virtio_ccw_device *vcdev = to_vc_device(vdev); ··· 703 705 return -ENOMEM; 704 706 705 707 for (i = 0; i < nvqs; ++i) { 706 - if (!names[i]) { 708 + struct virtqueue_info *vqi = &vqs_info[i]; 709 + 710 + if (!vqi->name) { 707 711 vqs[i] = NULL; 708 712 continue; 709 713 } 710 714 711 - vqs[i] = virtio_ccw_setup_vq(vdev, queue_idx++, callbacks[i], 712 - names[i], ctx ? ctx[i] : false, 713 - ccw); 715 + vqs[i] = virtio_ccw_setup_vq(vdev, queue_idx++, vqi->callback, 716 + vqi->name, vqi->ctx, ccw); 714 717 if (IS_ERR(vqs[i])) { 715 718 ret = PTR_ERR(vqs[i]); 716 719 vqs[i] = NULL;
+13 -19
drivers/scsi/virtio_scsi.c
··· 841 841 int err; 842 842 u32 i; 843 843 u32 num_vqs, num_poll_vqs, num_req_vqs; 844 - vq_callback_t **callbacks; 845 - const char **names; 844 + struct virtqueue_info *vqs_info; 846 845 struct virtqueue **vqs; 847 846 struct irq_affinity desc = { .pre_vectors = 2 }; 848 847 849 848 num_req_vqs = vscsi->num_queues; 850 849 num_vqs = num_req_vqs + VIRTIO_SCSI_VQ_BASE; 851 850 vqs = kmalloc_array(num_vqs, sizeof(struct virtqueue *), GFP_KERNEL); 852 - callbacks = kmalloc_array(num_vqs, sizeof(vq_callback_t *), 853 - GFP_KERNEL); 854 - names = kmalloc_array(num_vqs, sizeof(char *), GFP_KERNEL); 851 + vqs_info = kcalloc(num_vqs, sizeof(*vqs_info), GFP_KERNEL); 855 852 856 - if (!callbacks || !vqs || !names) { 853 + if (!vqs || !vqs_info) { 857 854 err = -ENOMEM; 858 855 goto out; 859 856 } ··· 866 869 vscsi->io_queues[HCTX_TYPE_READ], 867 870 vscsi->io_queues[HCTX_TYPE_POLL]); 868 871 869 - callbacks[0] = virtscsi_ctrl_done; 870 - callbacks[1] = virtscsi_event_done; 871 - names[0] = "control"; 872 - names[1] = "event"; 872 + vqs_info[0].callback = virtscsi_ctrl_done; 873 + vqs_info[0].name = "control"; 874 + vqs_info[1].callback = virtscsi_event_done; 875 + vqs_info[1].name = "event"; 873 876 for (i = VIRTIO_SCSI_VQ_BASE; i < num_vqs - num_poll_vqs; i++) { 874 - callbacks[i] = virtscsi_req_done; 875 - names[i] = "request"; 877 + vqs_info[i].callback = virtscsi_req_done; 878 + vqs_info[i].name = "request"; 876 879 } 877 880 878 - for (; i < num_vqs; i++) { 879 - callbacks[i] = NULL; 880 - names[i] = "request_poll"; 881 - } 881 + for (; i < num_vqs; i++) 882 + vqs_info[i].name = "request_poll"; 882 883 883 884 /* Discover virtqueues and write information to configuration. */ 884 - err = virtio_find_vqs(vdev, num_vqs, vqs, callbacks, names, &desc); 885 + err = virtio_find_vqs(vdev, num_vqs, vqs, vqs_info, &desc); 885 886 if (err) 886 887 goto out; 887 888 ··· 895 900 err = 0; 896 901 897 902 out: 898 - kfree(names); 899 - kfree(callbacks); 903 + kfree(vqs_info); 900 904 kfree(vqs); 901 905 if (err) 902 906 virtscsi_remove_vqs(vdev);
+11
drivers/vdpa/Kconfig
··· 126 126 With this driver, the VirtIO dataplane can be 127 127 offloaded to an AMD/Pensando DSC device. 128 128 129 + config OCTEONEP_VDPA 130 + tristate "vDPA driver for Octeon DPU devices" 131 + depends on m 132 + depends on PCI_MSI 133 + help 134 + This is a vDPA driver designed for Marvell's Octeon DPU devices. 135 + This driver enables the offloading of the VirtIO dataplane to an 136 + Octeon DPU device. 137 + Please note that this driver must be built as a module and it 138 + cannot be loaded until the Octeon emulation software is running. 139 + 129 140 endif # VDPA
+1
drivers/vdpa/Makefile
··· 8 8 obj-$(CONFIG_ALIBABA_ENI_VDPA) += alibaba/ 9 9 obj-$(CONFIG_SNET_VDPA) += solidrun/ 10 10 obj-$(CONFIG_PDS_VDPA) += pds/ 11 + obj-$(CONFIG_OCTEONEP_VDPA) += octeon_ep/
+1
drivers/vdpa/ifcvf/ifcvf_main.c
··· 894 894 895 895 module_pci_driver(ifcvf_driver); 896 896 897 + MODULE_DESCRIPTION("Intel IFC VF NIC driver for virtio dataplane offloading"); 897 898 MODULE_LICENSE("GPL v2");
+290 -139
drivers/vdpa/mlx5/net/mlx5_vnet.c
··· 48 48 49 49 #define MLX5V_UNTAGGED 0x1000 50 50 51 + /* Device must start with 1 queue pair, as per VIRTIO v1.2 spec, section 52 + * 5.1.6.5.5 "Device operation in multiqueue mode": 53 + * 54 + * Multiqueue is disabled by default. 55 + * The driver enables multiqueue by sending a command using class 56 + * VIRTIO_NET_CTRL_MQ. The command selects the mode of multiqueue 57 + * operation, as follows: ... 58 + */ 59 + #define MLX5V_DEFAULT_VQ_COUNT 2 60 + 61 + #define MLX5V_DEFAULT_VQ_SIZE 256 62 + 51 63 struct mlx5_vdpa_cq_buf { 52 64 struct mlx5_frag_buf_ctrl fbc; 53 65 struct mlx5_frag_buf frag_buf; ··· 156 144 return idx <= mvdev->max_idx; 157 145 } 158 146 159 - static void free_resources(struct mlx5_vdpa_net *ndev); 160 - static void init_mvqs(struct mlx5_vdpa_net *ndev); 161 - static int setup_driver(struct mlx5_vdpa_dev *mvdev); 162 - static void teardown_driver(struct mlx5_vdpa_net *ndev); 147 + static void free_fixed_resources(struct mlx5_vdpa_net *ndev); 148 + static void mvqs_set_defaults(struct mlx5_vdpa_net *ndev); 149 + static int setup_vq_resources(struct mlx5_vdpa_net *ndev, bool filled); 150 + static void teardown_vq_resources(struct mlx5_vdpa_net *ndev); 151 + static int resume_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq); 163 152 164 153 static bool mlx5_vdpa_debug; 165 154 ··· 875 862 pci_msix_can_alloc_dyn(mvdev->mdev->pdev); 876 863 } 877 864 878 - static int create_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq) 865 + static int create_virtqueue(struct mlx5_vdpa_net *ndev, 866 + struct mlx5_vdpa_virtqueue *mvq, 867 + bool filled) 879 868 { 880 869 int inlen = MLX5_ST_SZ_BYTES(create_virtio_net_q_in); 881 870 u32 out[MLX5_ST_SZ_DW(create_virtio_net_q_out)] = {}; 882 871 struct mlx5_vdpa_dev *mvdev = &ndev->mvdev; 883 872 struct mlx5_vdpa_mr *vq_mr; 884 873 struct mlx5_vdpa_mr *vq_desc_mr; 874 + u64 features = filled ? mvdev->actual_features : mvdev->mlx_features; 885 875 void *obj_context; 886 876 u16 mlx_features; 887 877 void *cmd_hdr; ··· 902 886 goto err_alloc; 903 887 } 904 888 905 - mlx_features = get_features(ndev->mvdev.actual_features); 889 + mlx_features = get_features(features); 906 890 cmd_hdr = MLX5_ADDR_OF(create_virtio_net_q_in, in, general_obj_in_cmd_hdr); 907 891 908 892 MLX5_SET(general_obj_in_cmd_hdr, cmd_hdr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT); ··· 910 894 MLX5_SET(general_obj_in_cmd_hdr, cmd_hdr, uid, ndev->mvdev.res.uid); 911 895 912 896 obj_context = MLX5_ADDR_OF(create_virtio_net_q_in, in, obj_context); 913 - MLX5_SET(virtio_net_q_object, obj_context, hw_available_index, mvq->avail_idx); 914 - MLX5_SET(virtio_net_q_object, obj_context, hw_used_index, mvq->used_idx); 915 897 MLX5_SET(virtio_net_q_object, obj_context, queue_feature_bit_mask_12_3, 916 898 mlx_features >> 3); 917 899 MLX5_SET(virtio_net_q_object, obj_context, queue_feature_bit_mask_2_0, ··· 931 917 MLX5_SET(virtio_q, vq_ctx, queue_index, mvq->index); 932 918 MLX5_SET(virtio_q, vq_ctx, queue_size, mvq->num_ent); 933 919 MLX5_SET(virtio_q, vq_ctx, virtio_version_1_0, 934 - !!(ndev->mvdev.actual_features & BIT_ULL(VIRTIO_F_VERSION_1))); 935 - MLX5_SET64(virtio_q, vq_ctx, desc_addr, mvq->desc_addr); 936 - MLX5_SET64(virtio_q, vq_ctx, used_addr, mvq->device_addr); 937 - MLX5_SET64(virtio_q, vq_ctx, available_addr, mvq->driver_addr); 938 - vq_mr = mvdev->mr[mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP]]; 939 - if (vq_mr) 940 - MLX5_SET(virtio_q, vq_ctx, virtio_q_mkey, vq_mr->mkey); 920 + !!(features & BIT_ULL(VIRTIO_F_VERSION_1))); 941 921 942 - vq_desc_mr = mvdev->mr[mvdev->group2asid[MLX5_VDPA_DATAVQ_DESC_GROUP]]; 943 - if (vq_desc_mr && MLX5_CAP_DEV_VDPA_EMULATION(mvdev->mdev, desc_group_mkey_supported)) 944 - MLX5_SET(virtio_q, vq_ctx, desc_group_mkey, vq_desc_mr->mkey); 922 + if (filled) { 923 + MLX5_SET(virtio_net_q_object, obj_context, hw_available_index, mvq->avail_idx); 924 + MLX5_SET(virtio_net_q_object, obj_context, hw_used_index, mvq->used_idx); 925 + 926 + MLX5_SET64(virtio_q, vq_ctx, desc_addr, mvq->desc_addr); 927 + MLX5_SET64(virtio_q, vq_ctx, used_addr, mvq->device_addr); 928 + MLX5_SET64(virtio_q, vq_ctx, available_addr, mvq->driver_addr); 929 + 930 + vq_mr = mvdev->mr[mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP]]; 931 + if (vq_mr) 932 + MLX5_SET(virtio_q, vq_ctx, virtio_q_mkey, vq_mr->mkey); 933 + 934 + vq_desc_mr = mvdev->mr[mvdev->group2asid[MLX5_VDPA_DATAVQ_DESC_GROUP]]; 935 + if (vq_desc_mr && 936 + MLX5_CAP_DEV_VDPA_EMULATION(mvdev->mdev, desc_group_mkey_supported)) 937 + MLX5_SET(virtio_q, vq_ctx, desc_group_mkey, vq_desc_mr->mkey); 938 + } else { 939 + /* If there is no mr update, make sure that the existing ones are set 940 + * modify to ready. 941 + */ 942 + vq_mr = mvdev->mr[mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP]]; 943 + if (vq_mr) 944 + mvq->modified_fields |= MLX5_VIRTQ_MODIFY_MASK_VIRTIO_Q_MKEY; 945 + 946 + vq_desc_mr = mvdev->mr[mvdev->group2asid[MLX5_VDPA_DATAVQ_DESC_GROUP]]; 947 + if (vq_desc_mr) 948 + mvq->modified_fields |= MLX5_VIRTQ_MODIFY_MASK_DESC_GROUP_MKEY; 949 + } 945 950 946 951 MLX5_SET(virtio_q, vq_ctx, umem_1_id, mvq->umem1.id); 947 952 MLX5_SET(virtio_q, vq_ctx, umem_1_size, mvq->umem1.size); ··· 980 947 kfree(in); 981 948 mvq->virtq_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 982 949 983 - mlx5_vdpa_get_mr(mvdev, vq_mr); 984 - mvq->vq_mr = vq_mr; 950 + if (filled) { 951 + mlx5_vdpa_get_mr(mvdev, vq_mr); 952 + mvq->vq_mr = vq_mr; 985 953 986 - if (vq_desc_mr && MLX5_CAP_DEV_VDPA_EMULATION(mvdev->mdev, desc_group_mkey_supported)) { 987 - mlx5_vdpa_get_mr(mvdev, vq_desc_mr); 988 - mvq->desc_mr = vq_desc_mr; 954 + if (vq_desc_mr && 955 + MLX5_CAP_DEV_VDPA_EMULATION(mvdev->mdev, desc_group_mkey_supported)) { 956 + mlx5_vdpa_get_mr(mvdev, vq_desc_mr); 957 + mvq->desc_mr = vq_desc_mr; 958 + } 989 959 } 990 960 991 961 return 0; ··· 1309 1273 if (mvq->modified_fields & MLX5_VIRTQ_MODIFY_MASK_VIRTIO_Q_USED_IDX) 1310 1274 MLX5_SET(virtio_net_q_object, obj_context, hw_used_index, mvq->used_idx); 1311 1275 1276 + if (mvq->modified_fields & MLX5_VIRTQ_MODIFY_MASK_QUEUE_VIRTIO_VERSION) 1277 + MLX5_SET(virtio_q, vq_ctx, virtio_version_1_0, 1278 + !!(ndev->mvdev.actual_features & BIT_ULL(VIRTIO_F_VERSION_1))); 1279 + 1280 + if (mvq->modified_fields & MLX5_VIRTQ_MODIFY_MASK_QUEUE_FEATURES) { 1281 + u16 mlx_features = get_features(ndev->mvdev.actual_features); 1282 + 1283 + MLX5_SET(virtio_net_q_object, obj_context, queue_feature_bit_mask_12_3, 1284 + mlx_features >> 3); 1285 + MLX5_SET(virtio_net_q_object, obj_context, queue_feature_bit_mask_2_0, 1286 + mlx_features & 7); 1287 + } 1288 + 1312 1289 if (mvq->modified_fields & MLX5_VIRTQ_MODIFY_MASK_VIRTIO_Q_MKEY) { 1313 1290 vq_mr = mvdev->mr[mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP]]; 1314 1291 ··· 1466 1417 } 1467 1418 } 1468 1419 1469 - static int setup_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq) 1420 + static int setup_vq(struct mlx5_vdpa_net *ndev, 1421 + struct mlx5_vdpa_virtqueue *mvq, 1422 + bool filled) 1470 1423 { 1471 1424 u16 idx = mvq->index; 1472 1425 int err; 1473 - 1474 - if (!mvq->num_ent) 1475 - return 0; 1476 1426 1477 1427 if (mvq->initialized) 1478 1428 return 0; ··· 1497 1449 goto err_connect; 1498 1450 1499 1451 alloc_vector(ndev, mvq); 1500 - err = create_virtqueue(ndev, mvq); 1452 + err = create_virtqueue(ndev, mvq, filled); 1501 1453 if (err) 1502 1454 goto err_vq; 1503 1455 1456 + mvq->initialized = true; 1457 + 1504 1458 if (mvq->ready) { 1505 - err = modify_virtqueue_state(ndev, mvq, MLX5_VIRTIO_NET_Q_OBJECT_STATE_RDY); 1506 - if (err) { 1507 - mlx5_vdpa_warn(&ndev->mvdev, "failed to modify to ready vq idx %d(%d)\n", 1508 - idx, err); 1459 + err = resume_vq(ndev, mvq); 1460 + if (err) 1509 1461 goto err_modify; 1510 - } 1511 1462 } 1512 1463 1513 - mvq->initialized = true; 1514 1464 return 0; 1515 1465 1516 1466 err_modify: ··· 1525 1479 return err; 1526 1480 } 1527 1481 1528 - static void suspend_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq) 1482 + static int suspend_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq) 1529 1483 { 1530 1484 struct mlx5_virtq_attr attr; 1485 + int err; 1531 1486 1532 1487 if (!mvq->initialized) 1533 - return; 1488 + return 0; 1534 1489 1535 1490 if (mvq->fw_state != MLX5_VIRTIO_NET_Q_OBJECT_STATE_RDY) 1536 - return; 1491 + return 0; 1537 1492 1538 - if (modify_virtqueue_state(ndev, mvq, MLX5_VIRTIO_NET_Q_OBJECT_STATE_SUSPEND)) 1539 - mlx5_vdpa_warn(&ndev->mvdev, "modify to suspend failed\n"); 1540 - 1541 - if (query_virtqueue(ndev, mvq, &attr)) { 1542 - mlx5_vdpa_warn(&ndev->mvdev, "failed to query virtqueue\n"); 1543 - return; 1493 + err = modify_virtqueue_state(ndev, mvq, MLX5_VIRTIO_NET_Q_OBJECT_STATE_SUSPEND); 1494 + if (err) { 1495 + mlx5_vdpa_warn(&ndev->mvdev, "modify to suspend failed, err: %d\n", err); 1496 + return err; 1544 1497 } 1498 + 1499 + err = query_virtqueue(ndev, mvq, &attr); 1500 + if (err) { 1501 + mlx5_vdpa_warn(&ndev->mvdev, "failed to query virtqueue, err: %d\n", err); 1502 + return err; 1503 + } 1504 + 1545 1505 mvq->avail_idx = attr.available_index; 1546 1506 mvq->used_idx = attr.used_index; 1507 + 1508 + return 0; 1547 1509 } 1548 1510 1549 - static void suspend_vqs(struct mlx5_vdpa_net *ndev) 1511 + static int suspend_vqs(struct mlx5_vdpa_net *ndev) 1550 1512 { 1513 + int err = 0; 1551 1514 int i; 1552 1515 1553 - for (i = 0; i < ndev->mvdev.max_vqs; i++) 1554 - suspend_vq(ndev, &ndev->vqs[i]); 1516 + for (i = 0; i < ndev->cur_num_vqs; i++) { 1517 + int local_err = suspend_vq(ndev, &ndev->vqs[i]); 1518 + 1519 + err = local_err ? local_err : err; 1520 + } 1521 + 1522 + return err; 1555 1523 } 1556 1524 1557 - static void resume_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq) 1525 + static int resume_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq) 1558 1526 { 1559 - if (!mvq->initialized || !is_resumable(ndev)) 1560 - return; 1527 + int err; 1561 1528 1562 - if (mvq->fw_state != MLX5_VIRTIO_NET_Q_OBJECT_STATE_SUSPEND) 1563 - return; 1529 + if (!mvq->initialized) 1530 + return 0; 1564 1531 1565 - if (modify_virtqueue_state(ndev, mvq, MLX5_VIRTIO_NET_Q_OBJECT_STATE_RDY)) 1566 - mlx5_vdpa_warn(&ndev->mvdev, "modify to resume failed for vq %u\n", mvq->index); 1532 + if (mvq->index >= ndev->cur_num_vqs) 1533 + return 0; 1534 + 1535 + switch (mvq->fw_state) { 1536 + case MLX5_VIRTIO_NET_Q_OBJECT_STATE_INIT: 1537 + /* Due to a FW quirk we need to modify the VQ fields first then change state. 1538 + * This should be fixed soon. After that, a single command can be used. 1539 + */ 1540 + err = modify_virtqueue(ndev, mvq, 0); 1541 + if (err) { 1542 + mlx5_vdpa_warn(&ndev->mvdev, 1543 + "modify vq properties failed for vq %u, err: %d\n", 1544 + mvq->index, err); 1545 + return err; 1546 + } 1547 + break; 1548 + case MLX5_VIRTIO_NET_Q_OBJECT_STATE_SUSPEND: 1549 + if (!is_resumable(ndev)) { 1550 + mlx5_vdpa_warn(&ndev->mvdev, "vq %d is not resumable\n", mvq->index); 1551 + return -EINVAL; 1552 + } 1553 + break; 1554 + case MLX5_VIRTIO_NET_Q_OBJECT_STATE_RDY: 1555 + return 0; 1556 + default: 1557 + mlx5_vdpa_warn(&ndev->mvdev, "resume vq %u called from bad state %d\n", 1558 + mvq->index, mvq->fw_state); 1559 + return -EINVAL; 1560 + } 1561 + 1562 + err = modify_virtqueue_state(ndev, mvq, MLX5_VIRTIO_NET_Q_OBJECT_STATE_RDY); 1563 + if (err) 1564 + mlx5_vdpa_warn(&ndev->mvdev, "modify to resume failed for vq %u, err: %d\n", 1565 + mvq->index, err); 1566 + 1567 + return err; 1567 1568 } 1568 1569 1569 - static void resume_vqs(struct mlx5_vdpa_net *ndev) 1570 + static int resume_vqs(struct mlx5_vdpa_net *ndev) 1570 1571 { 1571 - for (int i = 0; i < ndev->mvdev.max_vqs; i++) 1572 - resume_vq(ndev, &ndev->vqs[i]); 1572 + int err = 0; 1573 + 1574 + for (int i = 0; i < ndev->cur_num_vqs; i++) { 1575 + int local_err = resume_vq(ndev, &ndev->vqs[i]); 1576 + 1577 + err = local_err ? local_err : err; 1578 + } 1579 + 1580 + return err; 1573 1581 } 1574 1582 1575 1583 static void teardown_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq) ··· 2133 2033 if (err) 2134 2034 return err; 2135 2035 2136 - for (i = ndev->cur_num_vqs - 1; i >= 2 * newqps; i--) 2137 - teardown_vq(ndev, &ndev->vqs[i]); 2036 + for (i = ndev->cur_num_vqs - 1; i >= 2 * newqps; i--) { 2037 + struct mlx5_vdpa_virtqueue *mvq = &ndev->vqs[i]; 2038 + 2039 + if (is_resumable(ndev)) 2040 + suspend_vq(ndev, mvq); 2041 + else 2042 + teardown_vq(ndev, mvq); 2043 + } 2138 2044 2139 2045 ndev->cur_num_vqs = 2 * newqps; 2140 2046 } else { 2141 2047 ndev->cur_num_vqs = 2 * newqps; 2142 2048 for (i = cur_qps * 2; i < 2 * newqps; i++) { 2143 - err = setup_vq(ndev, &ndev->vqs[i]); 2049 + struct mlx5_vdpa_virtqueue *mvq = &ndev->vqs[i]; 2050 + 2051 + err = mvq->initialized ? resume_vq(ndev, mvq) : setup_vq(ndev, mvq, true); 2144 2052 if (err) 2145 2053 goto clean_added; 2146 2054 } ··· 2393 2285 } 2394 2286 2395 2287 mvq = &ndev->vqs[idx]; 2288 + ndev->needs_teardown = num != mvq->num_ent; 2396 2289 mvq->num_ent = num; 2397 2290 } 2398 2291 ··· 2433 2324 struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); 2434 2325 struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); 2435 2326 struct mlx5_vdpa_virtqueue *mvq; 2436 - int err; 2437 2327 2438 2328 if (!mvdev->actual_features) 2439 2329 return; ··· 2448 2340 mvq = &ndev->vqs[idx]; 2449 2341 if (!ready) { 2450 2342 suspend_vq(ndev, mvq); 2451 - } else { 2452 - err = modify_virtqueue_state(ndev, mvq, MLX5_VIRTIO_NET_Q_OBJECT_STATE_RDY); 2453 - if (err) { 2454 - mlx5_vdpa_warn(mvdev, "modify VQ %d to ready failed (%d)\n", idx, err); 2343 + } else if (mvdev->status & VIRTIO_CONFIG_S_DRIVER_OK) { 2344 + if (resume_vq(ndev, mvq)) 2455 2345 ready = false; 2456 - } 2457 2346 } 2458 - 2459 2347 2460 2348 mvq->ready = ready; 2461 2349 } ··· 2640 2536 return 0; 2641 2537 } 2642 2538 2643 - static int setup_virtqueues(struct mlx5_vdpa_dev *mvdev) 2539 + static int setup_virtqueues(struct mlx5_vdpa_dev *mvdev, bool filled) 2644 2540 { 2645 2541 struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); 2646 2542 int err; 2647 2543 int i; 2648 2544 2649 2545 for (i = 0; i < mvdev->max_vqs; i++) { 2650 - err = setup_vq(ndev, &ndev->vqs[i]); 2546 + err = setup_vq(ndev, &ndev->vqs[i], filled); 2651 2547 if (err) 2652 2548 goto err_vq; 2653 2549 } ··· 2663 2559 2664 2560 static void teardown_virtqueues(struct mlx5_vdpa_net *ndev) 2665 2561 { 2666 - struct mlx5_vdpa_virtqueue *mvq; 2667 2562 int i; 2668 2563 2669 - for (i = ndev->mvdev.max_vqs - 1; i >= 0; i--) { 2670 - mvq = &ndev->vqs[i]; 2671 - if (!mvq->initialized) 2672 - continue; 2673 - 2674 - teardown_vq(ndev, mvq); 2675 - } 2564 + for (i = ndev->mvdev.max_vqs - 1; i >= 0; i--) 2565 + teardown_vq(ndev, &ndev->vqs[i]); 2676 2566 } 2677 2567 2678 2568 static void update_cvq_info(struct mlx5_vdpa_dev *mvdev) ··· 2803 2705 { 2804 2706 struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); 2805 2707 struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); 2708 + u64 old_features = mvdev->actual_features; 2709 + u64 diff_features; 2806 2710 int err; 2807 2711 2808 2712 print_features(mvdev, features, true); ··· 2814 2714 return err; 2815 2715 2816 2716 ndev->mvdev.actual_features = features & ndev->mvdev.mlx_features; 2817 - if (ndev->mvdev.actual_features & BIT_ULL(VIRTIO_NET_F_MQ)) 2818 - ndev->rqt_size = mlx5vdpa16_to_cpu(mvdev, ndev->config.max_virtqueue_pairs); 2819 - else 2820 - ndev->rqt_size = 1; 2821 2717 2822 - /* Device must start with 1 queue pair, as per VIRTIO v1.2 spec, section 2823 - * 5.1.6.5.5 "Device operation in multiqueue mode": 2824 - * 2825 - * Multiqueue is disabled by default. 2826 - * The driver enables multiqueue by sending a command using class 2827 - * VIRTIO_NET_CTRL_MQ. The command selects the mode of multiqueue 2828 - * operation, as follows: ... 2829 - */ 2830 - ndev->cur_num_vqs = 2; 2718 + /* Interested in changes of vq features only. */ 2719 + if (get_features(old_features) != get_features(mvdev->actual_features)) { 2720 + for (int i = 0; i < mvdev->max_vqs; ++i) { 2721 + struct mlx5_vdpa_virtqueue *mvq = &ndev->vqs[i]; 2722 + 2723 + mvq->modified_fields |= ( 2724 + MLX5_VIRTQ_MODIFY_MASK_QUEUE_VIRTIO_VERSION | 2725 + MLX5_VIRTQ_MODIFY_MASK_QUEUE_FEATURES 2726 + ); 2727 + } 2728 + } 2729 + 2730 + /* When below features diverge from initial device features, VQs need a full teardown. */ 2731 + #define NEEDS_TEARDOWN_MASK (BIT_ULL(VIRTIO_NET_F_MRG_RXBUF) | \ 2732 + BIT_ULL(VIRTIO_NET_F_CSUM) | \ 2733 + BIT_ULL(VIRTIO_F_VERSION_1)) 2734 + 2735 + diff_features = mvdev->mlx_features ^ mvdev->actual_features; 2736 + ndev->needs_teardown = !!(diff_features & NEEDS_TEARDOWN_MASK); 2831 2737 2832 2738 update_cvq_info(mvdev); 2833 2739 return err; ··· 2922 2816 int i; 2923 2817 2924 2818 mlx5_clear_vqs(ndev); 2925 - init_mvqs(ndev); 2819 + mvqs_set_defaults(ndev); 2926 2820 for (i = 0; i < ndev->mvdev.max_vqs; i++) { 2927 2821 mvq = &ndev->vqs[i]; 2928 2822 ri = &mvq->ri; ··· 2954 2848 if (err) 2955 2849 return err; 2956 2850 2957 - teardown_driver(ndev); 2851 + teardown_vq_resources(ndev); 2958 2852 } 2959 2853 2960 2854 mlx5_vdpa_update_mr(mvdev, new_mr, asid); 2961 2855 2962 - for (int i = 0; i < ndev->cur_num_vqs; i++) 2856 + for (int i = 0; i < mvdev->max_vqs; i++) 2963 2857 ndev->vqs[i].modified_fields |= MLX5_VIRTQ_MODIFY_MASK_VIRTIO_Q_MKEY | 2964 2858 MLX5_VIRTQ_MODIFY_MASK_DESC_GROUP_MKEY; 2965 2859 ··· 2968 2862 2969 2863 if (teardown) { 2970 2864 restore_channels_info(ndev); 2971 - err = setup_driver(mvdev); 2865 + err = setup_vq_resources(ndev, true); 2972 2866 if (err) 2973 2867 return err; 2974 2868 } ··· 2979 2873 } 2980 2874 2981 2875 /* reslock must be held for this function */ 2982 - static int setup_driver(struct mlx5_vdpa_dev *mvdev) 2876 + static int setup_vq_resources(struct mlx5_vdpa_net *ndev, bool filled) 2983 2877 { 2984 - struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); 2878 + struct mlx5_vdpa_dev *mvdev = &ndev->mvdev; 2985 2879 int err; 2986 2880 2987 2881 WARN_ON(!rwsem_is_locked(&ndev->reslock)); ··· 2997 2891 if (err) 2998 2892 goto err_setup; 2999 2893 3000 - err = setup_virtqueues(mvdev); 2894 + err = setup_virtqueues(mvdev, filled); 3001 2895 if (err) { 3002 2896 mlx5_vdpa_warn(mvdev, "setup_virtqueues\n"); 3003 2897 goto err_setup; ··· 3037 2931 } 3038 2932 3039 2933 /* reslock must be held for this function */ 3040 - static void teardown_driver(struct mlx5_vdpa_net *ndev) 2934 + static void teardown_vq_resources(struct mlx5_vdpa_net *ndev) 3041 2935 { 3042 2936 3043 2937 WARN_ON(!rwsem_is_locked(&ndev->reslock)); ··· 3051 2945 destroy_rqt(ndev); 3052 2946 teardown_virtqueues(ndev); 3053 2947 ndev->setup = false; 3054 - } 3055 - 3056 - static void clear_vqs_ready(struct mlx5_vdpa_net *ndev) 3057 - { 3058 - int i; 3059 - 3060 - for (i = 0; i < ndev->mvdev.max_vqs; i++) { 3061 - ndev->vqs[i].ready = false; 3062 - ndev->vqs[i].modified_fields = 0; 3063 - } 3064 - 3065 - ndev->mvdev.cvq.ready = false; 2948 + ndev->needs_teardown = false; 3066 2949 } 3067 2950 3068 2951 static int setup_cvq_vring(struct mlx5_vdpa_dev *mvdev) ··· 3092 2997 goto err_setup; 3093 2998 } 3094 2999 register_link_notifier(ndev); 3095 - err = setup_driver(mvdev); 3096 - if (err) { 3097 - mlx5_vdpa_warn(mvdev, "failed to setup driver\n"); 3098 - goto err_driver; 3000 + 3001 + if (ndev->needs_teardown) 3002 + teardown_vq_resources(ndev); 3003 + 3004 + if (ndev->setup) { 3005 + err = resume_vqs(ndev); 3006 + if (err) { 3007 + mlx5_vdpa_warn(mvdev, "failed to resume VQs\n"); 3008 + goto err_driver; 3009 + } 3010 + } else { 3011 + err = setup_vq_resources(ndev, true); 3012 + if (err) { 3013 + mlx5_vdpa_warn(mvdev, "failed to setup driver\n"); 3014 + goto err_driver; 3015 + } 3099 3016 } 3100 3017 } else { 3101 3018 mlx5_vdpa_warn(mvdev, "did not expect DRIVER_OK to be cleared\n"); ··· 3137 3030 mvdev->group2asid[i] = 0; 3138 3031 } 3139 3032 3033 + static bool needs_vqs_reset(const struct mlx5_vdpa_dev *mvdev) 3034 + { 3035 + struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); 3036 + struct mlx5_vdpa_virtqueue *mvq = &ndev->vqs[0]; 3037 + 3038 + if (mvdev->status & VIRTIO_CONFIG_S_DRIVER_OK) 3039 + return true; 3040 + 3041 + if (mvq->fw_state != MLX5_VIRTIO_NET_Q_OBJECT_STATE_INIT) 3042 + return true; 3043 + 3044 + return mvq->modified_fields & ( 3045 + MLX5_VIRTQ_MODIFY_MASK_STATE | 3046 + MLX5_VIRTQ_MODIFY_MASK_VIRTIO_Q_ADDRS | 3047 + MLX5_VIRTQ_MODIFY_MASK_VIRTIO_Q_AVAIL_IDX | 3048 + MLX5_VIRTQ_MODIFY_MASK_VIRTIO_Q_USED_IDX 3049 + ); 3050 + } 3051 + 3140 3052 static int mlx5_vdpa_compat_reset(struct vdpa_device *vdev, u32 flags) 3141 3053 { 3142 3054 struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); 3143 3055 struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); 3056 + bool vq_reset; 3144 3057 3145 3058 print_status(mvdev, 0, true); 3146 3059 mlx5_vdpa_info(mvdev, "performing device reset\n"); 3147 3060 3148 3061 down_write(&ndev->reslock); 3149 3062 unregister_link_notifier(ndev); 3150 - teardown_driver(ndev); 3151 - clear_vqs_ready(ndev); 3063 + vq_reset = needs_vqs_reset(mvdev); 3064 + if (vq_reset) { 3065 + teardown_vq_resources(ndev); 3066 + mvqs_set_defaults(ndev); 3067 + } 3068 + 3152 3069 if (flags & VDPA_RESET_F_CLEAN_MAP) 3153 3070 mlx5_vdpa_destroy_mr_resources(&ndev->mvdev); 3154 3071 ndev->mvdev.status = 0; 3155 3072 ndev->mvdev.suspended = false; 3156 - ndev->cur_num_vqs = 0; 3073 + ndev->cur_num_vqs = MLX5V_DEFAULT_VQ_COUNT; 3074 + ndev->mvdev.cvq.ready = false; 3157 3075 ndev->mvdev.cvq.received_desc = 0; 3158 3076 ndev->mvdev.cvq.completed_desc = 0; 3159 3077 memset(ndev->event_cbs, 0, sizeof(*ndev->event_cbs) * (mvdev->max_vqs + 1)); ··· 3191 3059 if (mlx5_vdpa_create_dma_mr(mvdev)) 3192 3060 mlx5_vdpa_warn(mvdev, "create MR failed\n"); 3193 3061 } 3062 + if (vq_reset) 3063 + setup_vq_resources(ndev, false); 3194 3064 up_write(&ndev->reslock); 3195 3065 3196 3066 return 0; ··· 3331 3197 3332 3198 ndev = to_mlx5_vdpa_ndev(mvdev); 3333 3199 3334 - free_resources(ndev); 3200 + free_fixed_resources(ndev); 3335 3201 mlx5_vdpa_destroy_mr_resources(mvdev); 3336 3202 if (!is_zero_ether_addr(ndev->config.mac)) { 3337 3203 pfmdev = pci_get_drvdata(pci_physfn(mvdev->mdev->pdev)); ··· 3495 3361 { 3496 3362 struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); 3497 3363 struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); 3498 - struct mlx5_vdpa_virtqueue *mvq; 3499 - int i; 3364 + int err; 3500 3365 3501 3366 mlx5_vdpa_info(mvdev, "suspending device\n"); 3502 3367 3503 3368 down_write(&ndev->reslock); 3504 3369 unregister_link_notifier(ndev); 3505 - for (i = 0; i < ndev->cur_num_vqs; i++) { 3506 - mvq = &ndev->vqs[i]; 3507 - suspend_vq(ndev, mvq); 3508 - } 3370 + err = suspend_vqs(ndev); 3509 3371 mlx5_vdpa_cvq_suspend(mvdev); 3510 3372 mvdev->suspended = true; 3511 3373 up_write(&ndev->reslock); 3512 - return 0; 3374 + 3375 + return err; 3513 3376 } 3514 3377 3515 3378 static int mlx5_vdpa_resume(struct vdpa_device *vdev) 3516 3379 { 3517 3380 struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); 3518 3381 struct mlx5_vdpa_net *ndev; 3382 + int err; 3519 3383 3520 3384 ndev = to_mlx5_vdpa_ndev(mvdev); 3521 3385 ··· 3521 3389 3522 3390 down_write(&ndev->reslock); 3523 3391 mvdev->suspended = false; 3524 - resume_vqs(ndev); 3392 + err = resume_vqs(ndev); 3525 3393 register_link_notifier(ndev); 3526 3394 up_write(&ndev->reslock); 3527 - return 0; 3395 + 3396 + return err; 3528 3397 } 3529 3398 3530 3399 static int mlx5_set_group_asid(struct vdpa_device *vdev, u32 group, ··· 3600 3467 return 0; 3601 3468 } 3602 3469 3603 - static int alloc_resources(struct mlx5_vdpa_net *ndev) 3470 + static int alloc_fixed_resources(struct mlx5_vdpa_net *ndev) 3604 3471 { 3605 3472 struct mlx5_vdpa_net_resources *res = &ndev->res; 3606 3473 int err; ··· 3627 3494 return err; 3628 3495 } 3629 3496 3630 - static void free_resources(struct mlx5_vdpa_net *ndev) 3497 + static void free_fixed_resources(struct mlx5_vdpa_net *ndev) 3631 3498 { 3632 3499 struct mlx5_vdpa_net_resources *res = &ndev->res; 3633 3500 ··· 3639 3506 res->valid = false; 3640 3507 } 3641 3508 3642 - static void init_mvqs(struct mlx5_vdpa_net *ndev) 3509 + static void mvqs_set_defaults(struct mlx5_vdpa_net *ndev) 3643 3510 { 3644 3511 struct mlx5_vdpa_virtqueue *mvq; 3645 3512 int i; ··· 3651 3518 mvq->ndev = ndev; 3652 3519 mvq->fwqp.fw = true; 3653 3520 mvq->fw_state = MLX5_VIRTIO_NET_Q_OBJECT_NONE; 3654 - } 3655 - for (; i < ndev->mvdev.max_vqs; i++) { 3656 - mvq = &ndev->vqs[i]; 3657 - memset(mvq, 0, offsetof(struct mlx5_vdpa_virtqueue, ri)); 3658 - mvq->index = i; 3659 - mvq->ndev = ndev; 3521 + mvq->num_ent = MLX5V_DEFAULT_VQ_SIZE; 3660 3522 } 3661 3523 } 3662 3524 ··· 3788 3660 err = -ENOMEM; 3789 3661 goto err_alloc; 3790 3662 } 3663 + ndev->cur_num_vqs = MLX5V_DEFAULT_VQ_COUNT; 3791 3664 3792 - init_mvqs(ndev); 3665 + mvqs_set_defaults(ndev); 3793 3666 allocate_irqs(ndev); 3794 3667 init_rwsem(&ndev->reslock); 3795 3668 config = &ndev->config; ··· 3847 3718 goto err_alloc; 3848 3719 } 3849 3720 3850 - if (device_features & BIT_ULL(VIRTIO_NET_F_MQ)) 3721 + if (device_features & BIT_ULL(VIRTIO_NET_F_MQ)) { 3851 3722 config->max_virtqueue_pairs = cpu_to_mlx5vdpa16(mvdev, max_vqs / 2); 3723 + ndev->rqt_size = max_vqs / 2; 3724 + } else { 3725 + ndev->rqt_size = 1; 3726 + } 3852 3727 3853 3728 ndev->mvdev.mlx_features = device_features; 3854 3729 mvdev->vdev.dma_dev = &mdev->pdev->dev; ··· 3868 3735 goto err_res; 3869 3736 } 3870 3737 3871 - err = alloc_resources(ndev); 3738 + err = alloc_fixed_resources(ndev); 3872 3739 if (err) 3873 3740 goto err_mr; 3874 3741 ··· 3886 3753 goto err_reg; 3887 3754 3888 3755 mgtdev->ndev = ndev; 3756 + 3757 + /* For virtio-vdpa, the device was set up during device register. */ 3758 + if (ndev->setup) 3759 + return 0; 3760 + 3761 + down_write(&ndev->reslock); 3762 + err = setup_vq_resources(ndev, false); 3763 + up_write(&ndev->reslock); 3764 + if (err) 3765 + goto err_setup_vq_res; 3766 + 3889 3767 return 0; 3890 3768 3769 + err_setup_vq_res: 3770 + _vdpa_unregister_device(&mvdev->vdev); 3891 3771 err_reg: 3892 3772 destroy_workqueue(mvdev->wq); 3893 3773 err_res2: 3894 - free_resources(ndev); 3774 + free_fixed_resources(ndev); 3895 3775 err_mr: 3896 3776 mlx5_vdpa_destroy_mr_resources(mvdev); 3897 3777 err_res: ··· 3926 3780 3927 3781 unregister_link_notifier(ndev); 3928 3782 _vdpa_unregister_device(dev); 3783 + 3784 + down_write(&ndev->reslock); 3785 + teardown_vq_resources(ndev); 3786 + up_write(&ndev->reslock); 3787 + 3929 3788 wq = mvdev->wq; 3930 3789 mvdev->wq = NULL; 3931 3790 destroy_workqueue(wq);
+1
drivers/vdpa/mlx5/net/mlx5_vnet.h
··· 56 56 struct dentry *rx_dent; 57 57 struct dentry *rx_table_dent; 58 58 bool setup; 59 + bool needs_teardown; 59 60 u32 cur_num_vqs; 60 61 u32 rqt_size; 61 62 bool nb_registered;
+4
drivers/vdpa/octeon_ep/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + obj-$(CONFIG_OCTEONEP_VDPA) += octep_vdpa.o 3 + octep_vdpa-$(CONFIG_OCTEONEP_VDPA) += octep_vdpa_main.o 4 + octep_vdpa-$(CONFIG_OCTEONEP_VDPA) += octep_vdpa_hw.o
+94
drivers/vdpa/octeon_ep/octep_vdpa.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only 2 + * Copyright (C) 2024 Marvell. 3 + */ 4 + #ifndef __OCTEP_VDPA_H__ 5 + #define __OCTEP_VDPA_H__ 6 + 7 + #include <linux/pci.h> 8 + #include <linux/pci_regs.h> 9 + #include <linux/vdpa.h> 10 + #include <linux/virtio_pci_modern.h> 11 + #include <uapi/linux/virtio_net.h> 12 + #include <uapi/linux/virtio_blk.h> 13 + #include <uapi/linux/virtio_config.h> 14 + #include <uapi/linux/virtio_pci.h> 15 + #include <uapi/linux/vdpa.h> 16 + 17 + #define OCTEP_VDPA_DEVID_CN106K_PF 0xb900 18 + #define OCTEP_VDPA_DEVID_CN106K_VF 0xb903 19 + #define OCTEP_VDPA_DEVID_CN105K_PF 0xba00 20 + #define OCTEP_VDPA_DEVID_CN105K_VF 0xba03 21 + #define OCTEP_VDPA_DEVID_CN103K_PF 0xbd00 22 + #define OCTEP_VDPA_DEVID_CN103K_VF 0xbd03 23 + 24 + #define OCTEP_HW_MBOX_BAR 0 25 + #define OCTEP_HW_CAPS_BAR 4 26 + 27 + #define OCTEP_DEV_READY_SIGNATURE 0xBABABABA 28 + 29 + #define OCTEP_EPF_RINFO(x) (0x000209f0 | ((x) << 25)) 30 + #define OCTEP_VF_MBOX_DATA(x) (0x00010210 | ((x) << 17)) 31 + #define OCTEP_PF_MBOX_DATA(x) (0x00022000 | ((x) << 4)) 32 + 33 + #define OCTEP_EPF_RINFO_RPVF(val) (((val) >> 32) & 0xF) 34 + #define OCTEP_EPF_RINFO_NVFS(val) (((val) >> 48) & 0x7F) 35 + 36 + #define OCTEP_FW_READY_SIGNATURE0 0xFEEDFEED 37 + #define OCTEP_FW_READY_SIGNATURE1 0x3355ffaa 38 + 39 + enum octep_vdpa_dev_status { 40 + OCTEP_VDPA_DEV_STATUS_INVALID, 41 + OCTEP_VDPA_DEV_STATUS_ALLOC, 42 + OCTEP_VDPA_DEV_STATUS_WAIT_FOR_BAR_INIT, 43 + OCTEP_VDPA_DEV_STATUS_INIT, 44 + OCTEP_VDPA_DEV_STATUS_READY, 45 + OCTEP_VDPA_DEV_STATUS_UNINIT 46 + }; 47 + 48 + struct octep_vring_info { 49 + struct vdpa_callback cb; 50 + void __iomem *notify_addr; 51 + u32 __iomem *cb_notify_addr; 52 + phys_addr_t notify_pa; 53 + char msix_name[256]; 54 + }; 55 + 56 + struct octep_hw { 57 + struct pci_dev *pdev; 58 + u8 __iomem *base[PCI_STD_NUM_BARS]; 59 + struct virtio_pci_common_cfg __iomem *common_cfg; 60 + u8 __iomem *dev_cfg; 61 + u8 __iomem *isr; 62 + void __iomem *notify_base; 63 + phys_addr_t notify_base_pa; 64 + u32 notify_off_multiplier; 65 + u8 notify_bar; 66 + struct octep_vring_info *vqs; 67 + struct vdpa_callback config_cb; 68 + u64 features; 69 + u16 nr_vring; 70 + u32 config_size; 71 + int irq; 72 + }; 73 + 74 + u8 octep_hw_get_status(struct octep_hw *oct_hw); 75 + void octep_hw_set_status(struct octep_hw *dev, uint8_t status); 76 + void octep_hw_reset(struct octep_hw *oct_hw); 77 + void octep_write_queue_select(struct octep_hw *oct_hw, u16 queue_id); 78 + void octep_notify_queue(struct octep_hw *oct_hw, u16 qid); 79 + void octep_read_dev_config(struct octep_hw *oct_hw, u64 offset, void *dst, int length); 80 + int octep_set_vq_address(struct octep_hw *oct_hw, u16 qid, u64 desc_area, u64 driver_area, 81 + u64 device_area); 82 + void octep_set_vq_num(struct octep_hw *oct_hw, u16 qid, u32 num); 83 + void octep_set_vq_ready(struct octep_hw *oct_hw, u16 qid, bool ready); 84 + bool octep_get_vq_ready(struct octep_hw *oct_hw, u16 qid); 85 + int octep_set_vq_state(struct octep_hw *oct_hw, u16 qid, const struct vdpa_vq_state *state); 86 + int octep_get_vq_state(struct octep_hw *oct_hw, u16 qid, struct vdpa_vq_state *state); 87 + u16 octep_get_vq_size(struct octep_hw *oct_hw); 88 + int octep_hw_caps_read(struct octep_hw *oct_hw, struct pci_dev *pdev); 89 + u64 octep_hw_get_dev_features(struct octep_hw *oct_hw); 90 + void octep_hw_set_drv_features(struct octep_hw *oct_hw, u64 features); 91 + u64 octep_hw_get_drv_features(struct octep_hw *oct_hw); 92 + int octep_verify_features(u64 features); 93 + 94 + #endif /* __OCTEP_VDPA_H__ */
+517
drivers/vdpa/octeon_ep/octep_vdpa_hw.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright (C) 2024 Marvell. */ 3 + 4 + #include <linux/iopoll.h> 5 + 6 + #include "octep_vdpa.h" 7 + 8 + enum octep_mbox_ids { 9 + OCTEP_MBOX_MSG_SET_VQ_STATE = 1, 10 + OCTEP_MBOX_MSG_GET_VQ_STATE, 11 + }; 12 + 13 + #define OCTEP_HW_TIMEOUT 10000000 14 + 15 + #define MBOX_OFFSET 64 16 + #define MBOX_RSP_MASK 0x00000001 17 + #define MBOX_RC_MASK 0x0000FFFE 18 + 19 + #define MBOX_RSP_TO_ERR(val) (-(((val) & MBOX_RC_MASK) >> 2)) 20 + #define MBOX_AVAIL(val) (((val) & MBOX_RSP_MASK)) 21 + #define MBOX_RSP(val) ((val) & (MBOX_RC_MASK | MBOX_RSP_MASK)) 22 + 23 + #define DEV_RST_ACK_BIT 7 24 + #define FEATURE_SEL_ACK_BIT 15 25 + #define QUEUE_SEL_ACK_BIT 15 26 + 27 + struct octep_mbox_hdr { 28 + u8 ver; 29 + u8 rsvd1; 30 + u16 id; 31 + u16 rsvd2; 32 + #define MBOX_REQ_SIG (0xdead) 33 + #define MBOX_RSP_SIG (0xbeef) 34 + u16 sig; 35 + }; 36 + 37 + struct octep_mbox_sts { 38 + u16 rsp:1; 39 + u16 rc:15; 40 + u16 rsvd; 41 + }; 42 + 43 + struct octep_mbox { 44 + struct octep_mbox_hdr hdr; 45 + struct octep_mbox_sts sts; 46 + u64 rsvd; 47 + u32 data[]; 48 + }; 49 + 50 + static inline struct octep_mbox __iomem *octep_get_mbox(struct octep_hw *oct_hw) 51 + { 52 + return (struct octep_mbox __iomem *)(oct_hw->dev_cfg + MBOX_OFFSET); 53 + } 54 + 55 + static inline int octep_wait_for_mbox_avail(struct octep_mbox __iomem *mbox) 56 + { 57 + u32 val; 58 + 59 + return readx_poll_timeout(ioread32, &mbox->sts, val, MBOX_AVAIL(val), 10, 60 + OCTEP_HW_TIMEOUT); 61 + } 62 + 63 + static inline int octep_wait_for_mbox_rsp(struct octep_mbox __iomem *mbox) 64 + { 65 + u32 val; 66 + 67 + return readx_poll_timeout(ioread32, &mbox->sts, val, MBOX_RSP(val), 10, 68 + OCTEP_HW_TIMEOUT); 69 + } 70 + 71 + static inline void octep_write_hdr(struct octep_mbox __iomem *mbox, u16 id, u16 sig) 72 + { 73 + iowrite16(id, &mbox->hdr.id); 74 + iowrite16(sig, &mbox->hdr.sig); 75 + } 76 + 77 + static inline u32 octep_read_sig(struct octep_mbox __iomem *mbox) 78 + { 79 + return ioread16(&mbox->hdr.sig); 80 + } 81 + 82 + static inline void octep_write_sts(struct octep_mbox __iomem *mbox, u32 sts) 83 + { 84 + iowrite32(sts, &mbox->sts); 85 + } 86 + 87 + static inline u32 octep_read_sts(struct octep_mbox __iomem *mbox) 88 + { 89 + return ioread32(&mbox->sts); 90 + } 91 + 92 + static inline u32 octep_read32_word(struct octep_mbox __iomem *mbox, u16 word_idx) 93 + { 94 + return ioread32(&mbox->data[word_idx]); 95 + } 96 + 97 + static inline void octep_write32_word(struct octep_mbox __iomem *mbox, u16 word_idx, u32 word) 98 + { 99 + return iowrite32(word, &mbox->data[word_idx]); 100 + } 101 + 102 + static int octep_process_mbox(struct octep_hw *oct_hw, u16 id, u16 qid, void *buffer, 103 + u32 buf_size, bool write) 104 + { 105 + struct octep_mbox __iomem *mbox = octep_get_mbox(oct_hw); 106 + struct pci_dev *pdev = oct_hw->pdev; 107 + u32 *p = (u32 *)buffer; 108 + u16 data_wds; 109 + int ret, i; 110 + u32 val; 111 + 112 + if (!IS_ALIGNED(buf_size, 4)) 113 + return -EINVAL; 114 + 115 + /* Make sure mbox space is available */ 116 + ret = octep_wait_for_mbox_avail(mbox); 117 + if (ret) { 118 + dev_warn(&pdev->dev, "Timeout waiting for previous mbox data to be consumed\n"); 119 + return ret; 120 + } 121 + data_wds = buf_size / 4; 122 + 123 + if (write) { 124 + for (i = 1; i <= data_wds; i++) { 125 + octep_write32_word(mbox, i, *p); 126 + p++; 127 + } 128 + } 129 + octep_write32_word(mbox, 0, (u32)qid); 130 + octep_write_sts(mbox, 0); 131 + 132 + octep_write_hdr(mbox, id, MBOX_REQ_SIG); 133 + 134 + ret = octep_wait_for_mbox_rsp(mbox); 135 + if (ret) { 136 + dev_warn(&pdev->dev, "Timeout waiting for mbox : %d response\n", id); 137 + return ret; 138 + } 139 + 140 + val = octep_read_sig(mbox); 141 + if ((val & 0xFFFF) != MBOX_RSP_SIG) { 142 + dev_warn(&pdev->dev, "Invalid Signature from mbox : %d response\n", id); 143 + return ret; 144 + } 145 + 146 + val = octep_read_sts(mbox); 147 + if (val & MBOX_RC_MASK) { 148 + ret = MBOX_RSP_TO_ERR(val); 149 + dev_warn(&pdev->dev, "Error while processing mbox : %d, err %d\n", id, ret); 150 + return ret; 151 + } 152 + 153 + if (!write) 154 + for (i = 1; i <= data_wds; i++) 155 + *p++ = octep_read32_word(mbox, i); 156 + 157 + return 0; 158 + } 159 + 160 + static void octep_mbox_init(struct octep_mbox __iomem *mbox) 161 + { 162 + iowrite32(1, &mbox->sts); 163 + } 164 + 165 + int octep_verify_features(u64 features) 166 + { 167 + /* Minimum features to expect */ 168 + if (!(features & BIT_ULL(VIRTIO_F_VERSION_1))) 169 + return -EOPNOTSUPP; 170 + 171 + if (!(features & BIT_ULL(VIRTIO_F_NOTIFICATION_DATA))) 172 + return -EOPNOTSUPP; 173 + 174 + if (!(features & BIT_ULL(VIRTIO_F_RING_PACKED))) 175 + return -EOPNOTSUPP; 176 + 177 + return 0; 178 + } 179 + 180 + u8 octep_hw_get_status(struct octep_hw *oct_hw) 181 + { 182 + return ioread8(&oct_hw->common_cfg->device_status); 183 + } 184 + 185 + void octep_hw_set_status(struct octep_hw *oct_hw, u8 status) 186 + { 187 + iowrite8(status, &oct_hw->common_cfg->device_status); 188 + } 189 + 190 + void octep_hw_reset(struct octep_hw *oct_hw) 191 + { 192 + u8 val; 193 + 194 + octep_hw_set_status(oct_hw, 0 | BIT(DEV_RST_ACK_BIT)); 195 + if (readx_poll_timeout(ioread8, &oct_hw->common_cfg->device_status, val, !val, 10, 196 + OCTEP_HW_TIMEOUT)) { 197 + dev_warn(&oct_hw->pdev->dev, "Octeon device reset timeout\n"); 198 + return; 199 + } 200 + } 201 + 202 + static int feature_sel_write_with_timeout(struct octep_hw *oct_hw, u32 select, void __iomem *addr) 203 + { 204 + u32 val; 205 + 206 + iowrite32(select | BIT(FEATURE_SEL_ACK_BIT), addr); 207 + 208 + if (readx_poll_timeout(ioread32, addr, val, val == select, 10, OCTEP_HW_TIMEOUT)) { 209 + dev_warn(&oct_hw->pdev->dev, "Feature select%d write timeout\n", select); 210 + return -1; 211 + } 212 + return 0; 213 + } 214 + 215 + u64 octep_hw_get_dev_features(struct octep_hw *oct_hw) 216 + { 217 + u32 features_lo, features_hi; 218 + 219 + if (feature_sel_write_with_timeout(oct_hw, 0, &oct_hw->common_cfg->device_feature_select)) 220 + return 0; 221 + 222 + features_lo = ioread32(&oct_hw->common_cfg->device_feature); 223 + 224 + if (feature_sel_write_with_timeout(oct_hw, 1, &oct_hw->common_cfg->device_feature_select)) 225 + return 0; 226 + 227 + features_hi = ioread32(&oct_hw->common_cfg->device_feature); 228 + 229 + return ((u64)features_hi << 32) | features_lo; 230 + } 231 + 232 + u64 octep_hw_get_drv_features(struct octep_hw *oct_hw) 233 + { 234 + u32 features_lo, features_hi; 235 + 236 + if (feature_sel_write_with_timeout(oct_hw, 0, &oct_hw->common_cfg->guest_feature_select)) 237 + return 0; 238 + 239 + features_lo = ioread32(&oct_hw->common_cfg->guest_feature); 240 + 241 + if (feature_sel_write_with_timeout(oct_hw, 1, &oct_hw->common_cfg->guest_feature_select)) 242 + return 0; 243 + 244 + features_hi = ioread32(&oct_hw->common_cfg->guest_feature); 245 + 246 + return ((u64)features_hi << 32) | features_lo; 247 + } 248 + 249 + void octep_hw_set_drv_features(struct octep_hw *oct_hw, u64 features) 250 + { 251 + if (feature_sel_write_with_timeout(oct_hw, 0, &oct_hw->common_cfg->guest_feature_select)) 252 + return; 253 + 254 + iowrite32(features & (BIT_ULL(32) - 1), &oct_hw->common_cfg->guest_feature); 255 + 256 + if (feature_sel_write_with_timeout(oct_hw, 1, &oct_hw->common_cfg->guest_feature_select)) 257 + return; 258 + 259 + iowrite32(features >> 32, &oct_hw->common_cfg->guest_feature); 260 + } 261 + 262 + void octep_write_queue_select(struct octep_hw *oct_hw, u16 queue_id) 263 + { 264 + u16 val; 265 + 266 + iowrite16(queue_id | BIT(QUEUE_SEL_ACK_BIT), &oct_hw->common_cfg->queue_select); 267 + 268 + if (readx_poll_timeout(ioread16, &oct_hw->common_cfg->queue_select, val, val == queue_id, 269 + 10, OCTEP_HW_TIMEOUT)) { 270 + dev_warn(&oct_hw->pdev->dev, "Queue select write timeout\n"); 271 + return; 272 + } 273 + } 274 + 275 + void octep_notify_queue(struct octep_hw *oct_hw, u16 qid) 276 + { 277 + iowrite16(qid, oct_hw->vqs[qid].notify_addr); 278 + } 279 + 280 + void octep_read_dev_config(struct octep_hw *oct_hw, u64 offset, void *dst, int length) 281 + { 282 + u8 old_gen, new_gen, *p; 283 + int i; 284 + 285 + if (WARN_ON(offset + length > oct_hw->config_size)) 286 + return; 287 + 288 + do { 289 + old_gen = ioread8(&oct_hw->common_cfg->config_generation); 290 + p = dst; 291 + for (i = 0; i < length; i++) 292 + *p++ = ioread8(oct_hw->dev_cfg + offset + i); 293 + 294 + new_gen = ioread8(&oct_hw->common_cfg->config_generation); 295 + } while (old_gen != new_gen); 296 + } 297 + 298 + int octep_set_vq_address(struct octep_hw *oct_hw, u16 qid, u64 desc_area, u64 driver_area, 299 + u64 device_area) 300 + { 301 + struct virtio_pci_common_cfg __iomem *cfg = oct_hw->common_cfg; 302 + 303 + octep_write_queue_select(oct_hw, qid); 304 + vp_iowrite64_twopart(desc_area, &cfg->queue_desc_lo, 305 + &cfg->queue_desc_hi); 306 + vp_iowrite64_twopart(driver_area, &cfg->queue_avail_lo, 307 + &cfg->queue_avail_hi); 308 + vp_iowrite64_twopart(device_area, &cfg->queue_used_lo, 309 + &cfg->queue_used_hi); 310 + 311 + return 0; 312 + } 313 + 314 + int octep_get_vq_state(struct octep_hw *oct_hw, u16 qid, struct vdpa_vq_state *state) 315 + { 316 + return octep_process_mbox(oct_hw, OCTEP_MBOX_MSG_GET_VQ_STATE, qid, state, 317 + sizeof(*state), 0); 318 + } 319 + 320 + int octep_set_vq_state(struct octep_hw *oct_hw, u16 qid, const struct vdpa_vq_state *state) 321 + { 322 + struct vdpa_vq_state q_state; 323 + 324 + memcpy(&q_state, state, sizeof(struct vdpa_vq_state)); 325 + return octep_process_mbox(oct_hw, OCTEP_MBOX_MSG_SET_VQ_STATE, qid, &q_state, 326 + sizeof(*state), 1); 327 + } 328 + 329 + void octep_set_vq_num(struct octep_hw *oct_hw, u16 qid, u32 num) 330 + { 331 + struct virtio_pci_common_cfg __iomem *cfg = oct_hw->common_cfg; 332 + 333 + octep_write_queue_select(oct_hw, qid); 334 + iowrite16(num, &cfg->queue_size); 335 + } 336 + 337 + void octep_set_vq_ready(struct octep_hw *oct_hw, u16 qid, bool ready) 338 + { 339 + struct virtio_pci_common_cfg __iomem *cfg = oct_hw->common_cfg; 340 + 341 + octep_write_queue_select(oct_hw, qid); 342 + iowrite16(ready, &cfg->queue_enable); 343 + } 344 + 345 + bool octep_get_vq_ready(struct octep_hw *oct_hw, u16 qid) 346 + { 347 + struct virtio_pci_common_cfg __iomem *cfg = oct_hw->common_cfg; 348 + 349 + octep_write_queue_select(oct_hw, qid); 350 + return ioread16(&cfg->queue_enable); 351 + } 352 + 353 + u16 octep_get_vq_size(struct octep_hw *oct_hw) 354 + { 355 + octep_write_queue_select(oct_hw, 0); 356 + return ioread16(&oct_hw->common_cfg->queue_size); 357 + } 358 + 359 + static u32 octep_get_config_size(struct octep_hw *oct_hw) 360 + { 361 + return sizeof(struct virtio_net_config); 362 + } 363 + 364 + static void __iomem *octep_get_cap_addr(struct octep_hw *oct_hw, struct virtio_pci_cap *cap) 365 + { 366 + struct device *dev = &oct_hw->pdev->dev; 367 + u32 length = le32_to_cpu(cap->length); 368 + u32 offset = le32_to_cpu(cap->offset); 369 + u8 bar = cap->bar; 370 + u32 len; 371 + 372 + if (bar != OCTEP_HW_CAPS_BAR) { 373 + dev_err(dev, "Invalid bar: %u\n", bar); 374 + return NULL; 375 + } 376 + if (offset + length < offset) { 377 + dev_err(dev, "offset(%u) + length(%u) overflows\n", 378 + offset, length); 379 + return NULL; 380 + } 381 + len = pci_resource_len(oct_hw->pdev, bar); 382 + if (offset + length > len) { 383 + dev_err(dev, "invalid cap: overflows bar space: %u > %u\n", 384 + offset + length, len); 385 + return NULL; 386 + } 387 + return oct_hw->base[bar] + offset; 388 + } 389 + 390 + /* In Octeon DPU device, the virtio config space is completely 391 + * emulated by the device's firmware. So, the standard pci config 392 + * read apis can't be used for reading the virtio capability. 393 + */ 394 + static void octep_pci_caps_read(struct octep_hw *oct_hw, void *buf, size_t len, off_t offset) 395 + { 396 + u8 __iomem *bar = oct_hw->base[OCTEP_HW_CAPS_BAR]; 397 + u8 *p = buf; 398 + size_t i; 399 + 400 + for (i = 0; i < len; i++) 401 + *p++ = ioread8(bar + offset + i); 402 + } 403 + 404 + static int octep_pci_signature_verify(struct octep_hw *oct_hw) 405 + { 406 + u32 signature[2]; 407 + 408 + octep_pci_caps_read(oct_hw, &signature, sizeof(signature), 0); 409 + 410 + if (signature[0] != OCTEP_FW_READY_SIGNATURE0) 411 + return -1; 412 + 413 + if (signature[1] != OCTEP_FW_READY_SIGNATURE1) 414 + return -1; 415 + 416 + return 0; 417 + } 418 + 419 + int octep_hw_caps_read(struct octep_hw *oct_hw, struct pci_dev *pdev) 420 + { 421 + struct octep_mbox __iomem *mbox; 422 + struct device *dev = &pdev->dev; 423 + struct virtio_pci_cap cap; 424 + u16 notify_off; 425 + int i, ret; 426 + u8 pos; 427 + 428 + oct_hw->pdev = pdev; 429 + ret = octep_pci_signature_verify(oct_hw); 430 + if (ret) { 431 + dev_err(dev, "Octeon Virtio FW is not initialized\n"); 432 + return -EIO; 433 + } 434 + 435 + octep_pci_caps_read(oct_hw, &pos, 1, PCI_CAPABILITY_LIST); 436 + 437 + while (pos) { 438 + octep_pci_caps_read(oct_hw, &cap, 2, pos); 439 + 440 + if (cap.cap_vndr != PCI_CAP_ID_VNDR) { 441 + dev_err(dev, "Found invalid capability vndr id: %d\n", cap.cap_vndr); 442 + break; 443 + } 444 + 445 + octep_pci_caps_read(oct_hw, &cap, sizeof(cap), pos); 446 + 447 + dev_info(dev, "[%2x] cfg type: %u, bar: %u, offset: %04x, len: %u\n", 448 + pos, cap.cfg_type, cap.bar, cap.offset, cap.length); 449 + 450 + switch (cap.cfg_type) { 451 + case VIRTIO_PCI_CAP_COMMON_CFG: 452 + oct_hw->common_cfg = octep_get_cap_addr(oct_hw, &cap); 453 + break; 454 + case VIRTIO_PCI_CAP_NOTIFY_CFG: 455 + octep_pci_caps_read(oct_hw, &oct_hw->notify_off_multiplier, 456 + 4, pos + sizeof(cap)); 457 + 458 + oct_hw->notify_base = octep_get_cap_addr(oct_hw, &cap); 459 + oct_hw->notify_bar = cap.bar; 460 + oct_hw->notify_base_pa = pci_resource_start(pdev, cap.bar) + 461 + le32_to_cpu(cap.offset); 462 + break; 463 + case VIRTIO_PCI_CAP_DEVICE_CFG: 464 + oct_hw->dev_cfg = octep_get_cap_addr(oct_hw, &cap); 465 + break; 466 + case VIRTIO_PCI_CAP_ISR_CFG: 467 + oct_hw->isr = octep_get_cap_addr(oct_hw, &cap); 468 + break; 469 + } 470 + 471 + pos = cap.cap_next; 472 + } 473 + if (!oct_hw->common_cfg || !oct_hw->notify_base || 474 + !oct_hw->dev_cfg || !oct_hw->isr) { 475 + dev_err(dev, "Incomplete PCI capabilities"); 476 + return -EIO; 477 + } 478 + dev_info(dev, "common cfg mapped at: 0x%016llx\n", (u64)(uintptr_t)oct_hw->common_cfg); 479 + dev_info(dev, "device cfg mapped at: 0x%016llx\n", (u64)(uintptr_t)oct_hw->dev_cfg); 480 + dev_info(dev, "isr cfg mapped at: 0x%016llx\n", (u64)(uintptr_t)oct_hw->isr); 481 + dev_info(dev, "notify base: 0x%016llx, notify off multiplier: %u\n", 482 + (u64)(uintptr_t)oct_hw->notify_base, oct_hw->notify_off_multiplier); 483 + 484 + oct_hw->config_size = octep_get_config_size(oct_hw); 485 + oct_hw->features = octep_hw_get_dev_features(oct_hw); 486 + 487 + ret = octep_verify_features(oct_hw->features); 488 + if (ret) { 489 + dev_err(&pdev->dev, "Couldn't read features from the device FW\n"); 490 + return ret; 491 + } 492 + oct_hw->nr_vring = vp_ioread16(&oct_hw->common_cfg->num_queues); 493 + 494 + oct_hw->vqs = devm_kcalloc(&pdev->dev, oct_hw->nr_vring, sizeof(*oct_hw->vqs), GFP_KERNEL); 495 + if (!oct_hw->vqs) 496 + return -ENOMEM; 497 + 498 + oct_hw->irq = -1; 499 + 500 + dev_info(&pdev->dev, "Device features : %llx\n", oct_hw->features); 501 + dev_info(&pdev->dev, "Maximum queues : %u\n", oct_hw->nr_vring); 502 + 503 + for (i = 0; i < oct_hw->nr_vring; i++) { 504 + octep_write_queue_select(oct_hw, i); 505 + notify_off = vp_ioread16(&oct_hw->common_cfg->queue_notify_off); 506 + oct_hw->vqs[i].notify_addr = oct_hw->notify_base + 507 + notify_off * oct_hw->notify_off_multiplier; 508 + oct_hw->vqs[i].cb_notify_addr = (u32 __iomem *)oct_hw->vqs[i].notify_addr + 1; 509 + oct_hw->vqs[i].notify_pa = oct_hw->notify_base_pa + 510 + notify_off * oct_hw->notify_off_multiplier; 511 + } 512 + mbox = octep_get_mbox(oct_hw); 513 + octep_mbox_init(mbox); 514 + dev_info(dev, "mbox mapped at: 0x%016llx\n", (u64)(uintptr_t)mbox); 515 + 516 + return 0; 517 + }
+857
drivers/vdpa/octeon_ep/octep_vdpa_main.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright (C) 2024 Marvell. */ 3 + 4 + #include <linux/interrupt.h> 5 + #include <linux/io-64-nonatomic-lo-hi.h> 6 + #include <linux/module.h> 7 + #include <linux/iommu.h> 8 + #include "octep_vdpa.h" 9 + 10 + #define OCTEP_VDPA_DRIVER_NAME "octep_vdpa" 11 + 12 + struct octep_pf { 13 + u8 __iomem *base[PCI_STD_NUM_BARS]; 14 + struct pci_dev *pdev; 15 + struct resource res; 16 + u64 vf_base; 17 + int enabled_vfs; 18 + u32 vf_stride; 19 + u16 vf_devid; 20 + }; 21 + 22 + struct octep_vdpa { 23 + struct vdpa_device vdpa; 24 + struct octep_hw *oct_hw; 25 + struct pci_dev *pdev; 26 + }; 27 + 28 + struct octep_vdpa_mgmt_dev { 29 + struct vdpa_mgmt_dev mdev; 30 + struct octep_hw oct_hw; 31 + struct pci_dev *pdev; 32 + /* Work entry to handle device setup */ 33 + struct work_struct setup_task; 34 + /* Device status */ 35 + atomic_t status; 36 + }; 37 + 38 + static struct octep_hw *vdpa_to_octep_hw(struct vdpa_device *vdpa_dev) 39 + { 40 + struct octep_vdpa *oct_vdpa; 41 + 42 + oct_vdpa = container_of(vdpa_dev, struct octep_vdpa, vdpa); 43 + 44 + return oct_vdpa->oct_hw; 45 + } 46 + 47 + static irqreturn_t octep_vdpa_intr_handler(int irq, void *data) 48 + { 49 + struct octep_hw *oct_hw = data; 50 + int i; 51 + 52 + for (i = 0; i < oct_hw->nr_vring; i++) { 53 + if (oct_hw->vqs[i].cb.callback && ioread32(oct_hw->vqs[i].cb_notify_addr)) { 54 + /* Acknowledge the per queue notification to the device */ 55 + iowrite32(0, oct_hw->vqs[i].cb_notify_addr); 56 + oct_hw->vqs[i].cb.callback(oct_hw->vqs[i].cb.private); 57 + } 58 + } 59 + 60 + return IRQ_HANDLED; 61 + } 62 + 63 + static void octep_free_irqs(struct octep_hw *oct_hw) 64 + { 65 + struct pci_dev *pdev = oct_hw->pdev; 66 + 67 + if (oct_hw->irq != -1) { 68 + devm_free_irq(&pdev->dev, oct_hw->irq, oct_hw); 69 + oct_hw->irq = -1; 70 + } 71 + pci_free_irq_vectors(pdev); 72 + } 73 + 74 + static int octep_request_irqs(struct octep_hw *oct_hw) 75 + { 76 + struct pci_dev *pdev = oct_hw->pdev; 77 + int ret, irq; 78 + 79 + /* Currently HW device provisions one IRQ per VF, hence 80 + * allocate one IRQ for all virtqueues call interface. 81 + */ 82 + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX); 83 + if (ret < 0) { 84 + dev_err(&pdev->dev, "Failed to alloc msix vector"); 85 + return ret; 86 + } 87 + 88 + snprintf(oct_hw->vqs->msix_name, sizeof(oct_hw->vqs->msix_name), 89 + OCTEP_VDPA_DRIVER_NAME "-vf-%d", pci_iov_vf_id(pdev)); 90 + 91 + irq = pci_irq_vector(pdev, 0); 92 + ret = devm_request_irq(&pdev->dev, irq, octep_vdpa_intr_handler, 0, 93 + oct_hw->vqs->msix_name, oct_hw); 94 + if (ret) { 95 + dev_err(&pdev->dev, "Failed to register interrupt handler\n"); 96 + goto free_irq_vec; 97 + } 98 + oct_hw->irq = irq; 99 + 100 + return 0; 101 + 102 + free_irq_vec: 103 + pci_free_irq_vectors(pdev); 104 + return ret; 105 + } 106 + 107 + static u64 octep_vdpa_get_device_features(struct vdpa_device *vdpa_dev) 108 + { 109 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 110 + 111 + return oct_hw->features; 112 + } 113 + 114 + static int octep_vdpa_set_driver_features(struct vdpa_device *vdpa_dev, u64 features) 115 + { 116 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 117 + int ret; 118 + 119 + pr_debug("Driver Features: %llx\n", features); 120 + 121 + ret = octep_verify_features(features); 122 + if (ret) { 123 + dev_warn(&oct_hw->pdev->dev, 124 + "Must negotiate minimum features 0x%llx for this device", 125 + BIT_ULL(VIRTIO_F_VERSION_1) | BIT_ULL(VIRTIO_F_NOTIFICATION_DATA) | 126 + BIT_ULL(VIRTIO_F_RING_PACKED)); 127 + return ret; 128 + } 129 + octep_hw_set_drv_features(oct_hw, features); 130 + 131 + return 0; 132 + } 133 + 134 + static u64 octep_vdpa_get_driver_features(struct vdpa_device *vdpa_dev) 135 + { 136 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 137 + 138 + return octep_hw_get_drv_features(oct_hw); 139 + } 140 + 141 + static u8 octep_vdpa_get_status(struct vdpa_device *vdpa_dev) 142 + { 143 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 144 + 145 + return octep_hw_get_status(oct_hw); 146 + } 147 + 148 + static void octep_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status) 149 + { 150 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 151 + u8 status_old; 152 + 153 + status_old = octep_hw_get_status(oct_hw); 154 + 155 + if (status_old == status) 156 + return; 157 + 158 + if ((status & VIRTIO_CONFIG_S_DRIVER_OK) && 159 + !(status_old & VIRTIO_CONFIG_S_DRIVER_OK)) { 160 + if (octep_request_irqs(oct_hw)) 161 + status = status_old | VIRTIO_CONFIG_S_FAILED; 162 + } 163 + octep_hw_set_status(oct_hw, status); 164 + } 165 + 166 + static int octep_vdpa_reset(struct vdpa_device *vdpa_dev) 167 + { 168 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 169 + u8 status = octep_hw_get_status(oct_hw); 170 + u16 qid; 171 + 172 + if (status == 0) 173 + return 0; 174 + 175 + for (qid = 0; qid < oct_hw->nr_vring; qid++) { 176 + oct_hw->vqs[qid].cb.callback = NULL; 177 + oct_hw->vqs[qid].cb.private = NULL; 178 + oct_hw->config_cb.callback = NULL; 179 + oct_hw->config_cb.private = NULL; 180 + } 181 + octep_hw_reset(oct_hw); 182 + 183 + if (status & VIRTIO_CONFIG_S_DRIVER_OK) 184 + octep_free_irqs(oct_hw); 185 + 186 + return 0; 187 + } 188 + 189 + static u16 octep_vdpa_get_vq_num_max(struct vdpa_device *vdpa_dev) 190 + { 191 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 192 + 193 + return octep_get_vq_size(oct_hw); 194 + } 195 + 196 + static int octep_vdpa_get_vq_state(struct vdpa_device *vdpa_dev, u16 qid, 197 + struct vdpa_vq_state *state) 198 + { 199 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 200 + 201 + return octep_get_vq_state(oct_hw, qid, state); 202 + } 203 + 204 + static int octep_vdpa_set_vq_state(struct vdpa_device *vdpa_dev, u16 qid, 205 + const struct vdpa_vq_state *state) 206 + { 207 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 208 + 209 + return octep_set_vq_state(oct_hw, qid, state); 210 + } 211 + 212 + static void octep_vdpa_set_vq_cb(struct vdpa_device *vdpa_dev, u16 qid, struct vdpa_callback *cb) 213 + { 214 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 215 + 216 + oct_hw->vqs[qid].cb = *cb; 217 + } 218 + 219 + static void octep_vdpa_set_vq_ready(struct vdpa_device *vdpa_dev, u16 qid, bool ready) 220 + { 221 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 222 + 223 + octep_set_vq_ready(oct_hw, qid, ready); 224 + } 225 + 226 + static bool octep_vdpa_get_vq_ready(struct vdpa_device *vdpa_dev, u16 qid) 227 + { 228 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 229 + 230 + return octep_get_vq_ready(oct_hw, qid); 231 + } 232 + 233 + static void octep_vdpa_set_vq_num(struct vdpa_device *vdpa_dev, u16 qid, u32 num) 234 + { 235 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 236 + 237 + octep_set_vq_num(oct_hw, qid, num); 238 + } 239 + 240 + static int octep_vdpa_set_vq_address(struct vdpa_device *vdpa_dev, u16 qid, u64 desc_area, 241 + u64 driver_area, u64 device_area) 242 + { 243 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 244 + 245 + pr_debug("qid[%d]: desc_area: %llx\n", qid, desc_area); 246 + pr_debug("qid[%d]: driver_area: %llx\n", qid, driver_area); 247 + pr_debug("qid[%d]: device_area: %llx\n\n", qid, device_area); 248 + 249 + return octep_set_vq_address(oct_hw, qid, desc_area, driver_area, device_area); 250 + } 251 + 252 + static void octep_vdpa_kick_vq(struct vdpa_device *vdpa_dev, u16 qid) 253 + { 254 + /* Not supported */ 255 + } 256 + 257 + static void octep_vdpa_kick_vq_with_data(struct vdpa_device *vdpa_dev, u32 data) 258 + { 259 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 260 + u16 idx = data & 0xFFFF; 261 + 262 + vp_iowrite32(data, oct_hw->vqs[idx].notify_addr); 263 + } 264 + 265 + static u32 octep_vdpa_get_generation(struct vdpa_device *vdpa_dev) 266 + { 267 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 268 + 269 + return vp_ioread8(&oct_hw->common_cfg->config_generation); 270 + } 271 + 272 + static u32 octep_vdpa_get_device_id(struct vdpa_device *vdpa_dev) 273 + { 274 + return VIRTIO_ID_NET; 275 + } 276 + 277 + static u32 octep_vdpa_get_vendor_id(struct vdpa_device *vdpa_dev) 278 + { 279 + return PCI_VENDOR_ID_CAVIUM; 280 + } 281 + 282 + static u32 octep_vdpa_get_vq_align(struct vdpa_device *vdpa_dev) 283 + { 284 + return PAGE_SIZE; 285 + } 286 + 287 + static size_t octep_vdpa_get_config_size(struct vdpa_device *vdpa_dev) 288 + { 289 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 290 + 291 + return oct_hw->config_size; 292 + } 293 + 294 + static void octep_vdpa_get_config(struct vdpa_device *vdpa_dev, unsigned int offset, void *buf, 295 + unsigned int len) 296 + { 297 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 298 + 299 + octep_read_dev_config(oct_hw, offset, buf, len); 300 + } 301 + 302 + static void octep_vdpa_set_config(struct vdpa_device *vdpa_dev, unsigned int offset, 303 + const void *buf, unsigned int len) 304 + { 305 + /* Not supported */ 306 + } 307 + 308 + static void octep_vdpa_set_config_cb(struct vdpa_device *vdpa_dev, struct vdpa_callback *cb) 309 + { 310 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 311 + 312 + oct_hw->config_cb.callback = cb->callback; 313 + oct_hw->config_cb.private = cb->private; 314 + } 315 + 316 + static struct vdpa_notification_area octep_get_vq_notification(struct vdpa_device *vdpa_dev, 317 + u16 idx) 318 + { 319 + struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev); 320 + struct vdpa_notification_area area; 321 + 322 + area.addr = oct_hw->vqs[idx].notify_pa; 323 + area.size = PAGE_SIZE; 324 + 325 + return area; 326 + } 327 + 328 + static struct vdpa_config_ops octep_vdpa_ops = { 329 + .get_device_features = octep_vdpa_get_device_features, 330 + .set_driver_features = octep_vdpa_set_driver_features, 331 + .get_driver_features = octep_vdpa_get_driver_features, 332 + .get_status = octep_vdpa_get_status, 333 + .set_status = octep_vdpa_set_status, 334 + .reset = octep_vdpa_reset, 335 + .get_vq_num_max = octep_vdpa_get_vq_num_max, 336 + .get_vq_state = octep_vdpa_get_vq_state, 337 + .set_vq_state = octep_vdpa_set_vq_state, 338 + .set_vq_cb = octep_vdpa_set_vq_cb, 339 + .set_vq_ready = octep_vdpa_set_vq_ready, 340 + .get_vq_ready = octep_vdpa_get_vq_ready, 341 + .set_vq_num = octep_vdpa_set_vq_num, 342 + .set_vq_address = octep_vdpa_set_vq_address, 343 + .get_vq_irq = NULL, 344 + .kick_vq = octep_vdpa_kick_vq, 345 + .kick_vq_with_data = octep_vdpa_kick_vq_with_data, 346 + .get_generation = octep_vdpa_get_generation, 347 + .get_device_id = octep_vdpa_get_device_id, 348 + .get_vendor_id = octep_vdpa_get_vendor_id, 349 + .get_vq_align = octep_vdpa_get_vq_align, 350 + .get_config_size = octep_vdpa_get_config_size, 351 + .get_config = octep_vdpa_get_config, 352 + .set_config = octep_vdpa_set_config, 353 + .set_config_cb = octep_vdpa_set_config_cb, 354 + .get_vq_notification = octep_get_vq_notification, 355 + }; 356 + 357 + static int octep_iomap_region(struct pci_dev *pdev, u8 __iomem **tbl, u8 bar) 358 + { 359 + int ret; 360 + 361 + ret = pci_request_region(pdev, bar, OCTEP_VDPA_DRIVER_NAME); 362 + if (ret) { 363 + dev_err(&pdev->dev, "Failed to request BAR:%u region\n", bar); 364 + return ret; 365 + } 366 + 367 + tbl[bar] = pci_iomap(pdev, bar, pci_resource_len(pdev, bar)); 368 + if (!tbl[bar]) { 369 + dev_err(&pdev->dev, "Failed to iomap BAR:%u\n", bar); 370 + pci_release_region(pdev, bar); 371 + ret = -ENOMEM; 372 + } 373 + 374 + return ret; 375 + } 376 + 377 + static void octep_iounmap_region(struct pci_dev *pdev, u8 __iomem **tbl, u8 bar) 378 + { 379 + pci_iounmap(pdev, tbl[bar]); 380 + pci_release_region(pdev, bar); 381 + } 382 + 383 + static void octep_vdpa_pf_bar_shrink(struct octep_pf *octpf) 384 + { 385 + struct pci_dev *pf_dev = octpf->pdev; 386 + struct resource *res = pf_dev->resource + PCI_STD_RESOURCES + 4; 387 + struct pci_bus_region bus_region; 388 + 389 + octpf->res.start = res->start; 390 + octpf->res.end = res->end; 391 + octpf->vf_base = res->start; 392 + 393 + bus_region.start = res->start; 394 + bus_region.end = res->start - 1; 395 + 396 + pcibios_bus_to_resource(pf_dev->bus, res, &bus_region); 397 + } 398 + 399 + static void octep_vdpa_pf_bar_expand(struct octep_pf *octpf) 400 + { 401 + struct pci_dev *pf_dev = octpf->pdev; 402 + struct resource *res = pf_dev->resource + PCI_STD_RESOURCES + 4; 403 + struct pci_bus_region bus_region; 404 + 405 + bus_region.start = octpf->res.start; 406 + bus_region.end = octpf->res.end; 407 + 408 + pcibios_bus_to_resource(pf_dev->bus, res, &bus_region); 409 + } 410 + 411 + static void octep_vdpa_remove_pf(struct pci_dev *pdev) 412 + { 413 + struct octep_pf *octpf = pci_get_drvdata(pdev); 414 + 415 + pci_disable_sriov(pdev); 416 + 417 + if (octpf->base[OCTEP_HW_CAPS_BAR]) 418 + octep_iounmap_region(pdev, octpf->base, OCTEP_HW_CAPS_BAR); 419 + 420 + if (octpf->base[OCTEP_HW_MBOX_BAR]) 421 + octep_iounmap_region(pdev, octpf->base, OCTEP_HW_MBOX_BAR); 422 + 423 + octep_vdpa_pf_bar_expand(octpf); 424 + } 425 + 426 + static void octep_vdpa_vf_bar_shrink(struct pci_dev *pdev) 427 + { 428 + struct resource *vf_res = pdev->resource + PCI_STD_RESOURCES + 4; 429 + 430 + memset(vf_res, 0, sizeof(*vf_res)); 431 + } 432 + 433 + static void octep_vdpa_remove_vf(struct pci_dev *pdev) 434 + { 435 + struct octep_vdpa_mgmt_dev *mgmt_dev = pci_get_drvdata(pdev); 436 + struct octep_hw *oct_hw; 437 + int status; 438 + 439 + oct_hw = &mgmt_dev->oct_hw; 440 + status = atomic_read(&mgmt_dev->status); 441 + atomic_set(&mgmt_dev->status, OCTEP_VDPA_DEV_STATUS_UNINIT); 442 + 443 + cancel_work_sync(&mgmt_dev->setup_task); 444 + if (status == OCTEP_VDPA_DEV_STATUS_READY) 445 + vdpa_mgmtdev_unregister(&mgmt_dev->mdev); 446 + 447 + if (oct_hw->base[OCTEP_HW_CAPS_BAR]) 448 + octep_iounmap_region(pdev, oct_hw->base, OCTEP_HW_CAPS_BAR); 449 + 450 + if (oct_hw->base[OCTEP_HW_MBOX_BAR]) 451 + octep_iounmap_region(pdev, oct_hw->base, OCTEP_HW_MBOX_BAR); 452 + 453 + octep_vdpa_vf_bar_shrink(pdev); 454 + } 455 + 456 + static void octep_vdpa_remove(struct pci_dev *pdev) 457 + { 458 + if (pdev->is_virtfn) 459 + octep_vdpa_remove_vf(pdev); 460 + else 461 + octep_vdpa_remove_pf(pdev); 462 + } 463 + 464 + static int octep_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name, 465 + const struct vdpa_dev_set_config *config) 466 + { 467 + struct octep_vdpa_mgmt_dev *mgmt_dev = container_of(mdev, struct octep_vdpa_mgmt_dev, mdev); 468 + struct octep_hw *oct_hw = &mgmt_dev->oct_hw; 469 + struct pci_dev *pdev = oct_hw->pdev; 470 + struct vdpa_device *vdpa_dev; 471 + struct octep_vdpa *oct_vdpa; 472 + u64 device_features; 473 + int ret; 474 + 475 + oct_vdpa = vdpa_alloc_device(struct octep_vdpa, vdpa, &pdev->dev, &octep_vdpa_ops, 1, 1, 476 + NULL, false); 477 + if (IS_ERR(oct_vdpa)) { 478 + dev_err(&pdev->dev, "Failed to allocate vDPA structure for octep vdpa device"); 479 + return PTR_ERR(oct_vdpa); 480 + } 481 + 482 + oct_vdpa->pdev = pdev; 483 + oct_vdpa->vdpa.dma_dev = &pdev->dev; 484 + oct_vdpa->vdpa.mdev = mdev; 485 + oct_vdpa->oct_hw = oct_hw; 486 + vdpa_dev = &oct_vdpa->vdpa; 487 + 488 + device_features = oct_hw->features; 489 + if (config->mask & BIT_ULL(VDPA_ATTR_DEV_FEATURES)) { 490 + if (config->device_features & ~device_features) { 491 + dev_err(&pdev->dev, "The provisioned features 0x%llx are not supported by this device with features 0x%llx\n", 492 + config->device_features, device_features); 493 + ret = -EINVAL; 494 + goto vdpa_dev_put; 495 + } 496 + device_features &= config->device_features; 497 + } 498 + 499 + oct_hw->features = device_features; 500 + dev_info(&pdev->dev, "Vdpa management device features : %llx\n", device_features); 501 + 502 + ret = octep_verify_features(device_features); 503 + if (ret) { 504 + dev_warn(mdev->device, 505 + "Must provision minimum features 0x%llx for this device", 506 + BIT_ULL(VIRTIO_F_VERSION_1) | BIT_ULL(VIRTIO_F_ACCESS_PLATFORM) | 507 + BIT_ULL(VIRTIO_F_NOTIFICATION_DATA) | BIT_ULL(VIRTIO_F_RING_PACKED)); 508 + goto vdpa_dev_put; 509 + } 510 + if (name) 511 + ret = dev_set_name(&vdpa_dev->dev, "%s", name); 512 + else 513 + ret = dev_set_name(&vdpa_dev->dev, "vdpa%u", vdpa_dev->index); 514 + 515 + ret = _vdpa_register_device(&oct_vdpa->vdpa, oct_hw->nr_vring); 516 + if (ret) { 517 + dev_err(&pdev->dev, "Failed to register to vDPA bus"); 518 + goto vdpa_dev_put; 519 + } 520 + return 0; 521 + 522 + vdpa_dev_put: 523 + put_device(&oct_vdpa->vdpa.dev); 524 + return ret; 525 + } 526 + 527 + static void octep_vdpa_dev_del(struct vdpa_mgmt_dev *mdev, struct vdpa_device *vdpa_dev) 528 + { 529 + _vdpa_unregister_device(vdpa_dev); 530 + } 531 + 532 + static const struct vdpa_mgmtdev_ops octep_vdpa_mgmt_dev_ops = { 533 + .dev_add = octep_vdpa_dev_add, 534 + .dev_del = octep_vdpa_dev_del 535 + }; 536 + 537 + static bool get_device_ready_status(u8 __iomem *addr) 538 + { 539 + u64 signature = readq(addr + OCTEP_VF_MBOX_DATA(0)); 540 + 541 + if (signature == OCTEP_DEV_READY_SIGNATURE) { 542 + writeq(0, addr + OCTEP_VF_MBOX_DATA(0)); 543 + return true; 544 + } 545 + 546 + return false; 547 + } 548 + 549 + static struct virtio_device_id id_table[] = { 550 + { VIRTIO_ID_NET, VIRTIO_DEV_ANY_ID }, 551 + { 0 }, 552 + }; 553 + 554 + static void octep_vdpa_setup_task(struct work_struct *work) 555 + { 556 + struct octep_vdpa_mgmt_dev *mgmt_dev = container_of(work, struct octep_vdpa_mgmt_dev, 557 + setup_task); 558 + struct pci_dev *pdev = mgmt_dev->pdev; 559 + struct device *dev = &pdev->dev; 560 + struct octep_hw *oct_hw; 561 + unsigned long timeout; 562 + int ret; 563 + 564 + oct_hw = &mgmt_dev->oct_hw; 565 + 566 + atomic_set(&mgmt_dev->status, OCTEP_VDPA_DEV_STATUS_WAIT_FOR_BAR_INIT); 567 + 568 + /* Wait for a maximum of 5 sec */ 569 + timeout = jiffies + msecs_to_jiffies(5000); 570 + while (!time_after(jiffies, timeout)) { 571 + if (get_device_ready_status(oct_hw->base[OCTEP_HW_MBOX_BAR])) { 572 + atomic_set(&mgmt_dev->status, OCTEP_VDPA_DEV_STATUS_INIT); 573 + break; 574 + } 575 + 576 + if (atomic_read(&mgmt_dev->status) >= OCTEP_VDPA_DEV_STATUS_READY) { 577 + dev_info(dev, "Stopping vDPA setup task.\n"); 578 + return; 579 + } 580 + 581 + usleep_range(1000, 1500); 582 + } 583 + 584 + if (atomic_read(&mgmt_dev->status) != OCTEP_VDPA_DEV_STATUS_INIT) { 585 + dev_err(dev, "BAR initialization is timed out\n"); 586 + return; 587 + } 588 + 589 + ret = octep_iomap_region(pdev, oct_hw->base, OCTEP_HW_CAPS_BAR); 590 + if (ret) 591 + return; 592 + 593 + ret = octep_hw_caps_read(oct_hw, pdev); 594 + if (ret < 0) 595 + goto unmap_region; 596 + 597 + mgmt_dev->mdev.ops = &octep_vdpa_mgmt_dev_ops; 598 + mgmt_dev->mdev.id_table = id_table; 599 + mgmt_dev->mdev.max_supported_vqs = oct_hw->nr_vring; 600 + mgmt_dev->mdev.supported_features = oct_hw->features; 601 + mgmt_dev->mdev.config_attr_mask = (1 << VDPA_ATTR_DEV_FEATURES); 602 + mgmt_dev->mdev.device = dev; 603 + 604 + ret = vdpa_mgmtdev_register(&mgmt_dev->mdev); 605 + if (ret) { 606 + dev_err(dev, "Failed to register vdpa management interface\n"); 607 + goto unmap_region; 608 + } 609 + 610 + atomic_set(&mgmt_dev->status, OCTEP_VDPA_DEV_STATUS_READY); 611 + 612 + return; 613 + 614 + unmap_region: 615 + octep_iounmap_region(pdev, oct_hw->base, OCTEP_HW_CAPS_BAR); 616 + oct_hw->base[OCTEP_HW_CAPS_BAR] = NULL; 617 + } 618 + 619 + static int octep_vdpa_probe_vf(struct pci_dev *pdev) 620 + { 621 + struct octep_vdpa_mgmt_dev *mgmt_dev; 622 + struct device *dev = &pdev->dev; 623 + int ret; 624 + 625 + ret = pcim_enable_device(pdev); 626 + if (ret) { 627 + dev_err(dev, "Failed to enable device\n"); 628 + return ret; 629 + } 630 + 631 + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); 632 + if (ret) { 633 + dev_err(dev, "No usable DMA configuration\n"); 634 + return ret; 635 + } 636 + pci_set_master(pdev); 637 + 638 + mgmt_dev = devm_kzalloc(dev, sizeof(struct octep_vdpa_mgmt_dev), GFP_KERNEL); 639 + if (!mgmt_dev) 640 + return -ENOMEM; 641 + 642 + ret = octep_iomap_region(pdev, mgmt_dev->oct_hw.base, OCTEP_HW_MBOX_BAR); 643 + if (ret) 644 + return ret; 645 + 646 + mgmt_dev->pdev = pdev; 647 + pci_set_drvdata(pdev, mgmt_dev); 648 + 649 + atomic_set(&mgmt_dev->status, OCTEP_VDPA_DEV_STATUS_ALLOC); 650 + INIT_WORK(&mgmt_dev->setup_task, octep_vdpa_setup_task); 651 + schedule_work(&mgmt_dev->setup_task); 652 + dev_info(&pdev->dev, "octep vdpa mgmt device setup task is queued\n"); 653 + 654 + return 0; 655 + } 656 + 657 + static void octep_vdpa_assign_barspace(struct pci_dev *vf_dev, struct pci_dev *pf_dev, u8 idx) 658 + { 659 + struct resource *vf_res = vf_dev->resource + PCI_STD_RESOURCES + 4; 660 + struct resource *pf_res = pf_dev->resource + PCI_STD_RESOURCES + 4; 661 + struct octep_pf *pf = pci_get_drvdata(pf_dev); 662 + struct pci_bus_region bus_region; 663 + 664 + vf_res->name = pci_name(vf_dev); 665 + vf_res->flags = pf_res->flags; 666 + vf_res->parent = (pf_dev->resource + PCI_STD_RESOURCES)->parent; 667 + 668 + bus_region.start = pf->vf_base + idx * pf->vf_stride; 669 + bus_region.end = bus_region.start + pf->vf_stride - 1; 670 + pcibios_bus_to_resource(vf_dev->bus, vf_res, &bus_region); 671 + } 672 + 673 + static int octep_sriov_enable(struct pci_dev *pdev, int num_vfs) 674 + { 675 + struct octep_pf *pf = pci_get_drvdata(pdev); 676 + u8 __iomem *addr = pf->base[OCTEP_HW_MBOX_BAR]; 677 + struct pci_dev *vf_pdev = NULL; 678 + bool done = false; 679 + int index = 0; 680 + int ret, i; 681 + 682 + ret = pci_enable_sriov(pdev, num_vfs); 683 + if (ret) 684 + return ret; 685 + 686 + pf->enabled_vfs = num_vfs; 687 + 688 + while ((vf_pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM, PCI_ANY_ID, vf_pdev))) { 689 + if (vf_pdev->device != pf->vf_devid) 690 + continue; 691 + 692 + octep_vdpa_assign_barspace(vf_pdev, pdev, index); 693 + if (++index == num_vfs) { 694 + done = true; 695 + break; 696 + } 697 + } 698 + 699 + if (done) { 700 + for (i = 0; i < pf->enabled_vfs; i++) 701 + writeq(OCTEP_DEV_READY_SIGNATURE, addr + OCTEP_PF_MBOX_DATA(i)); 702 + } 703 + 704 + return num_vfs; 705 + } 706 + 707 + static int octep_sriov_disable(struct pci_dev *pdev) 708 + { 709 + struct octep_pf *pf = pci_get_drvdata(pdev); 710 + 711 + if (!pci_num_vf(pdev)) 712 + return 0; 713 + 714 + pci_disable_sriov(pdev); 715 + pf->enabled_vfs = 0; 716 + 717 + return 0; 718 + } 719 + 720 + static int octep_vdpa_sriov_configure(struct pci_dev *pdev, int num_vfs) 721 + { 722 + if (num_vfs > 0) 723 + return octep_sriov_enable(pdev, num_vfs); 724 + else 725 + return octep_sriov_disable(pdev); 726 + } 727 + 728 + static u16 octep_get_vf_devid(struct pci_dev *pdev) 729 + { 730 + u16 did; 731 + 732 + switch (pdev->device) { 733 + case OCTEP_VDPA_DEVID_CN106K_PF: 734 + did = OCTEP_VDPA_DEVID_CN106K_VF; 735 + break; 736 + case OCTEP_VDPA_DEVID_CN105K_PF: 737 + did = OCTEP_VDPA_DEVID_CN105K_VF; 738 + break; 739 + case OCTEP_VDPA_DEVID_CN103K_PF: 740 + did = OCTEP_VDPA_DEVID_CN103K_VF; 741 + break; 742 + default: 743 + did = 0xFFFF; 744 + break; 745 + } 746 + 747 + return did; 748 + } 749 + 750 + static int octep_vdpa_pf_setup(struct octep_pf *octpf) 751 + { 752 + u8 __iomem *addr = octpf->base[OCTEP_HW_MBOX_BAR]; 753 + struct pci_dev *pdev = octpf->pdev; 754 + int totalvfs; 755 + size_t len; 756 + u64 val; 757 + 758 + totalvfs = pci_sriov_get_totalvfs(pdev); 759 + if (unlikely(!totalvfs)) { 760 + dev_info(&pdev->dev, "Total VFs are %d in PF sriov configuration\n", totalvfs); 761 + return 0; 762 + } 763 + 764 + addr = octpf->base[OCTEP_HW_MBOX_BAR]; 765 + val = readq(addr + OCTEP_EPF_RINFO(0)); 766 + if (val == 0) { 767 + dev_err(&pdev->dev, "Invalid device configuration\n"); 768 + return -EINVAL; 769 + } 770 + 771 + if (OCTEP_EPF_RINFO_RPVF(val) != BIT_ULL(0)) { 772 + val &= ~GENMASK_ULL(35, 32); 773 + val |= BIT_ULL(32); 774 + writeq(val, addr + OCTEP_EPF_RINFO(0)); 775 + } 776 + 777 + len = pci_resource_len(pdev, OCTEP_HW_CAPS_BAR); 778 + 779 + octpf->vf_stride = len / totalvfs; 780 + octpf->vf_devid = octep_get_vf_devid(pdev); 781 + 782 + octep_vdpa_pf_bar_shrink(octpf); 783 + 784 + return 0; 785 + } 786 + 787 + static int octep_vdpa_probe_pf(struct pci_dev *pdev) 788 + { 789 + struct device *dev = &pdev->dev; 790 + struct octep_pf *octpf; 791 + int ret; 792 + 793 + ret = pcim_enable_device(pdev); 794 + if (ret) { 795 + dev_err(dev, "Failed to enable device\n"); 796 + return ret; 797 + } 798 + 799 + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); 800 + if (ret) { 801 + dev_err(dev, "No usable DMA configuration\n"); 802 + return ret; 803 + } 804 + octpf = devm_kzalloc(dev, sizeof(*octpf), GFP_KERNEL); 805 + if (!octpf) 806 + return -ENOMEM; 807 + 808 + ret = octep_iomap_region(pdev, octpf->base, OCTEP_HW_MBOX_BAR); 809 + if (ret) 810 + return ret; 811 + 812 + pci_set_master(pdev); 813 + pci_set_drvdata(pdev, octpf); 814 + octpf->pdev = pdev; 815 + 816 + ret = octep_vdpa_pf_setup(octpf); 817 + if (ret) 818 + goto unmap_region; 819 + 820 + return 0; 821 + 822 + unmap_region: 823 + octep_iounmap_region(pdev, octpf->base, OCTEP_HW_MBOX_BAR); 824 + return ret; 825 + } 826 + 827 + static int octep_vdpa_probe(struct pci_dev *pdev, const struct pci_device_id *id) 828 + { 829 + if (pdev->is_virtfn) 830 + return octep_vdpa_probe_vf(pdev); 831 + else 832 + return octep_vdpa_probe_pf(pdev); 833 + } 834 + 835 + static struct pci_device_id octep_pci_vdpa_map[] = { 836 + { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_VDPA_DEVID_CN106K_PF) }, 837 + { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_VDPA_DEVID_CN106K_VF) }, 838 + { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_VDPA_DEVID_CN105K_PF) }, 839 + { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_VDPA_DEVID_CN105K_VF) }, 840 + { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_VDPA_DEVID_CN103K_PF) }, 841 + { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_VDPA_DEVID_CN103K_VF) }, 842 + { 0 }, 843 + }; 844 + 845 + static struct pci_driver octep_pci_vdpa = { 846 + .name = OCTEP_VDPA_DRIVER_NAME, 847 + .id_table = octep_pci_vdpa_map, 848 + .probe = octep_vdpa_probe, 849 + .remove = octep_vdpa_remove, 850 + .sriov_configure = octep_vdpa_sriov_configure 851 + }; 852 + 853 + module_pci_driver(octep_pci_vdpa); 854 + 855 + MODULE_AUTHOR("Marvell"); 856 + MODULE_DESCRIPTION("Marvell Octeon PCIe endpoint vDPA driver"); 857 + MODULE_LICENSE("GPL");
+1
drivers/vdpa/vdpa.c
··· 1538 1538 module_exit(vdpa_exit); 1539 1539 1540 1540 MODULE_AUTHOR("Jason Wang <jasowang@redhat.com>"); 1541 + MODULE_DESCRIPTION("vDPA bus"); 1541 1542 MODULE_LICENSE("GPL v2");
+42 -63
drivers/vhost/vhost.c
··· 1346 1346 mutex_unlock(&d->vqs[i]->mutex); 1347 1347 } 1348 1348 1349 - static inline int vhost_get_avail_idx(struct vhost_virtqueue *vq, 1350 - __virtio16 *idx) 1349 + static inline int vhost_get_avail_idx(struct vhost_virtqueue *vq) 1351 1350 { 1352 - return vhost_get_avail(vq, *idx, &vq->avail->idx); 1351 + __virtio16 idx; 1352 + int r; 1353 + 1354 + r = vhost_get_avail(vq, idx, &vq->avail->idx); 1355 + if (unlikely(r < 0)) { 1356 + vq_err(vq, "Failed to access available index at %p (%d)\n", 1357 + &vq->avail->idx, r); 1358 + return r; 1359 + } 1360 + 1361 + /* Check it isn't doing very strange thing with available indexes */ 1362 + vq->avail_idx = vhost16_to_cpu(vq, idx); 1363 + if (unlikely((u16)(vq->avail_idx - vq->last_avail_idx) > vq->num)) { 1364 + vq_err(vq, "Invalid available index change from %u to %u", 1365 + vq->last_avail_idx, vq->avail_idx); 1366 + return -EINVAL; 1367 + } 1368 + 1369 + /* We're done if there is nothing new */ 1370 + if (vq->avail_idx == vq->last_avail_idx) 1371 + return 0; 1372 + 1373 + /* 1374 + * We updated vq->avail_idx so we need a memory barrier between 1375 + * the index read above and the caller reading avail ring entries. 1376 + */ 1377 + smp_rmb(); 1378 + return 1; 1353 1379 } 1354 1380 1355 1381 static inline int vhost_get_avail_head(struct vhost_virtqueue *vq, ··· 2580 2554 { 2581 2555 struct vring_desc desc; 2582 2556 unsigned int i, head, found = 0; 2583 - u16 last_avail_idx; 2584 - __virtio16 avail_idx; 2557 + u16 last_avail_idx = vq->last_avail_idx; 2585 2558 __virtio16 ring_head; 2586 2559 int ret, access; 2587 2560 2588 - /* Check it isn't doing very strange things with descriptor numbers. */ 2589 - last_avail_idx = vq->last_avail_idx; 2590 - 2591 2561 if (vq->avail_idx == vq->last_avail_idx) { 2592 - if (unlikely(vhost_get_avail_idx(vq, &avail_idx))) { 2593 - vq_err(vq, "Failed to access avail idx at %p\n", 2594 - &vq->avail->idx); 2595 - return -EFAULT; 2596 - } 2597 - vq->avail_idx = vhost16_to_cpu(vq, avail_idx); 2562 + ret = vhost_get_avail_idx(vq); 2563 + if (unlikely(ret < 0)) 2564 + return ret; 2598 2565 2599 - if (unlikely((u16)(vq->avail_idx - last_avail_idx) > vq->num)) { 2600 - vq_err(vq, "Guest moved avail index from %u to %u", 2601 - last_avail_idx, vq->avail_idx); 2602 - return -EFAULT; 2603 - } 2604 - 2605 - /* If there's nothing new since last we looked, return 2606 - * invalid. 2607 - */ 2608 - if (vq->avail_idx == last_avail_idx) 2566 + if (!ret) 2609 2567 return vq->num; 2610 - 2611 - /* Only get avail ring entries after they have been 2612 - * exposed by guest. 2613 - */ 2614 - smp_rmb(); 2615 2568 } 2616 2569 2617 2570 /* Grab the next descriptor number they're advertising, and increment ··· 2851 2846 /* return true if we're sure that avaiable ring is empty */ 2852 2847 bool vhost_vq_avail_empty(struct vhost_dev *dev, struct vhost_virtqueue *vq) 2853 2848 { 2854 - __virtio16 avail_idx; 2855 2849 int r; 2856 2850 2857 2851 if (vq->avail_idx != vq->last_avail_idx) 2858 2852 return false; 2859 2853 2860 - r = vhost_get_avail_idx(vq, &avail_idx); 2861 - if (unlikely(r)) 2862 - return false; 2854 + r = vhost_get_avail_idx(vq); 2863 2855 2864 - vq->avail_idx = vhost16_to_cpu(vq, avail_idx); 2865 - if (vq->avail_idx != vq->last_avail_idx) { 2866 - /* Since we have updated avail_idx, the following 2867 - * call to vhost_get_vq_desc() will read available 2868 - * ring entries. Make sure that read happens after 2869 - * the avail_idx read. 2870 - */ 2871 - smp_rmb(); 2872 - return false; 2873 - } 2874 - 2875 - return true; 2856 + /* Note: we treat error as non-empty here */ 2857 + return r == 0; 2876 2858 } 2877 2859 EXPORT_SYMBOL_GPL(vhost_vq_avail_empty); 2878 2860 2879 2861 /* OK, now we need to know about added descriptors. */ 2880 2862 bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq) 2881 2863 { 2882 - __virtio16 avail_idx; 2883 2864 int r; 2884 2865 2885 2866 if (!(vq->used_flags & VRING_USED_F_NO_NOTIFY)) ··· 2889 2898 /* They could have slipped one in as we were doing that: make 2890 2899 * sure it's written, then check again. */ 2891 2900 smp_mb(); 2892 - r = vhost_get_avail_idx(vq, &avail_idx); 2893 - if (r) { 2894 - vq_err(vq, "Failed to check avail idx at %p: %d\n", 2895 - &vq->avail->idx, r); 2901 + 2902 + r = vhost_get_avail_idx(vq); 2903 + /* Note: we treat error as empty here */ 2904 + if (unlikely(r < 0)) 2896 2905 return false; 2897 - } 2898 2906 2899 - vq->avail_idx = vhost16_to_cpu(vq, avail_idx); 2900 - if (vq->avail_idx != vq->last_avail_idx) { 2901 - /* Since we have updated avail_idx, the following 2902 - * call to vhost_get_vq_desc() will read available 2903 - * ring entries. Make sure that read happens after 2904 - * the avail_idx read. 2905 - */ 2906 - smp_rmb(); 2907 - return true; 2908 - } 2909 - 2910 - return false; 2907 + return r; 2911 2908 } 2912 2909 EXPORT_SYMBOL_GPL(vhost_enable_notify); 2913 2910
+1
drivers/vhost/vringh.c
··· 1614 1614 1615 1615 #endif 1616 1616 1617 + MODULE_DESCRIPTION("host side of a virtio ring"); 1617 1618 MODULE_LICENSE("GPL");
+2 -2
drivers/vhost/vsock.c
··· 667 667 } 668 668 669 669 vsock->guest_cid = 0; /* no CID assigned yet */ 670 + vsock->seqpacket_allow = false; 670 671 671 672 atomic_set(&vsock->queued_replies, 0); 672 673 ··· 811 810 goto err; 812 811 } 813 812 814 - if (features & (1ULL << VIRTIO_VSOCK_F_SEQPACKET)) 815 - vsock->seqpacket_allow = true; 813 + vsock->seqpacket_allow = features & (1ULL << VIRTIO_VSOCK_F_SEQPACKET); 816 814 817 815 for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) { 818 816 vq = &vsock->vqs[i];
+1
drivers/virtio/virtio.c
··· 609 609 core_initcall(virtio_init); 610 610 module_exit(virtio_exit); 611 611 612 + MODULE_DESCRIPTION("Virtio core interface"); 612 613 MODULE_LICENSE("GPL");
+41 -34
drivers/virtio/virtio_balloon.c
··· 349 349 350 350 #define pages_to_bytes(x) ((u64)(x) << PAGE_SHIFT) 351 351 352 - static unsigned int update_balloon_stats(struct virtio_balloon *vb) 352 + #ifdef CONFIG_VM_EVENT_COUNTERS 353 + /* Return the number of entries filled by vm events */ 354 + static inline unsigned int update_balloon_vm_stats(struct virtio_balloon *vb) 353 355 { 354 356 unsigned long events[NR_VM_EVENT_ITEMS]; 355 - struct sysinfo i; 356 357 unsigned int idx = 0; 357 - long available; 358 - unsigned long caches; 359 358 360 359 all_vm_events(events); 361 - si_meminfo(&i); 362 - 363 - available = si_mem_available(); 364 - caches = global_node_page_state(NR_FILE_PAGES); 365 - 366 - #ifdef CONFIG_VM_EVENT_COUNTERS 367 360 update_stat(vb, idx++, VIRTIO_BALLOON_S_SWAP_IN, 368 - pages_to_bytes(events[PSWPIN])); 361 + pages_to_bytes(events[PSWPIN])); 369 362 update_stat(vb, idx++, VIRTIO_BALLOON_S_SWAP_OUT, 370 - pages_to_bytes(events[PSWPOUT])); 363 + pages_to_bytes(events[PSWPOUT])); 371 364 update_stat(vb, idx++, VIRTIO_BALLOON_S_MAJFLT, events[PGMAJFAULT]); 372 365 update_stat(vb, idx++, VIRTIO_BALLOON_S_MINFLT, events[PGFAULT]); 366 + 373 367 #ifdef CONFIG_HUGETLB_PAGE 374 368 update_stat(vb, idx++, VIRTIO_BALLOON_S_HTLB_PGALLOC, 375 369 events[HTLB_BUDDY_PGALLOC]); 376 370 update_stat(vb, idx++, VIRTIO_BALLOON_S_HTLB_PGFAIL, 377 371 events[HTLB_BUDDY_PGALLOC_FAIL]); 378 - #endif 379 - #endif 372 + #endif /* CONFIG_HUGETLB_PAGE */ 373 + 374 + return idx; 375 + } 376 + #else /* CONFIG_VM_EVENT_COUNTERS */ 377 + static inline unsigned int update_balloon_vm_stats(struct virtio_balloon *vb) 378 + { 379 + return 0; 380 + } 381 + #endif /* CONFIG_VM_EVENT_COUNTERS */ 382 + 383 + static unsigned int update_balloon_stats(struct virtio_balloon *vb) 384 + { 385 + struct sysinfo i; 386 + unsigned int idx; 387 + long available; 388 + unsigned long caches; 389 + 390 + idx = update_balloon_vm_stats(vb); 391 + 392 + si_meminfo(&i); 393 + available = si_mem_available(); 394 + caches = global_node_page_state(NR_FILE_PAGES); 380 395 update_stat(vb, idx++, VIRTIO_BALLOON_S_MEMFREE, 381 396 pages_to_bytes(i.freeram)); 382 397 update_stat(vb, idx++, VIRTIO_BALLOON_S_MEMTOT, ··· 560 545 561 546 static int init_vqs(struct virtio_balloon *vb) 562 547 { 548 + struct virtqueue_info vqs_info[VIRTIO_BALLOON_VQ_MAX] = {}; 563 549 struct virtqueue *vqs[VIRTIO_BALLOON_VQ_MAX]; 564 - vq_callback_t *callbacks[VIRTIO_BALLOON_VQ_MAX]; 565 - const char *names[VIRTIO_BALLOON_VQ_MAX]; 566 550 int err; 567 551 568 552 /* ··· 569 555 * will be NULL if the related feature is not enabled, which will 570 556 * cause no allocation for the corresponding virtqueue in find_vqs. 571 557 */ 572 - callbacks[VIRTIO_BALLOON_VQ_INFLATE] = balloon_ack; 573 - names[VIRTIO_BALLOON_VQ_INFLATE] = "inflate"; 574 - callbacks[VIRTIO_BALLOON_VQ_DEFLATE] = balloon_ack; 575 - names[VIRTIO_BALLOON_VQ_DEFLATE] = "deflate"; 576 - callbacks[VIRTIO_BALLOON_VQ_STATS] = NULL; 577 - names[VIRTIO_BALLOON_VQ_STATS] = NULL; 578 - callbacks[VIRTIO_BALLOON_VQ_FREE_PAGE] = NULL; 579 - names[VIRTIO_BALLOON_VQ_FREE_PAGE] = NULL; 580 - names[VIRTIO_BALLOON_VQ_REPORTING] = NULL; 558 + vqs_info[VIRTIO_BALLOON_VQ_INFLATE].callback = balloon_ack; 559 + vqs_info[VIRTIO_BALLOON_VQ_INFLATE].name = "inflate"; 560 + vqs_info[VIRTIO_BALLOON_VQ_DEFLATE].callback = balloon_ack; 561 + vqs_info[VIRTIO_BALLOON_VQ_DEFLATE].name = "deflate"; 581 562 582 563 if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) { 583 - names[VIRTIO_BALLOON_VQ_STATS] = "stats"; 584 - callbacks[VIRTIO_BALLOON_VQ_STATS] = stats_request; 564 + vqs_info[VIRTIO_BALLOON_VQ_STATS].name = "stats"; 565 + vqs_info[VIRTIO_BALLOON_VQ_STATS].callback = stats_request; 585 566 } 586 567 587 - if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) { 588 - names[VIRTIO_BALLOON_VQ_FREE_PAGE] = "free_page_vq"; 589 - callbacks[VIRTIO_BALLOON_VQ_FREE_PAGE] = NULL; 590 - } 568 + if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) 569 + vqs_info[VIRTIO_BALLOON_VQ_FREE_PAGE].name = "free_page_vq"; 591 570 592 571 if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) { 593 - names[VIRTIO_BALLOON_VQ_REPORTING] = "reporting_vq"; 594 - callbacks[VIRTIO_BALLOON_VQ_REPORTING] = balloon_ack; 572 + vqs_info[VIRTIO_BALLOON_VQ_REPORTING].name = "reporting_vq"; 573 + vqs_info[VIRTIO_BALLOON_VQ_REPORTING].callback = balloon_ack; 595 574 } 596 575 597 576 err = virtio_find_vqs(vb->vdev, VIRTIO_BALLOON_VQ_MAX, vqs, 598 - callbacks, names, NULL); 577 + vqs_info, NULL); 599 578 if (err) 600 579 return err; 601 580
+5 -4
drivers/virtio/virtio_input.c
··· 185 185 186 186 static int virtinput_init_vqs(struct virtio_input *vi) 187 187 { 188 + struct virtqueue_info vqs_info[] = { 189 + { "events", virtinput_recv_events }, 190 + { "status", virtinput_recv_status }, 191 + }; 188 192 struct virtqueue *vqs[2]; 189 - vq_callback_t *cbs[] = { virtinput_recv_events, 190 - virtinput_recv_status }; 191 - static const char * const names[] = { "events", "status" }; 192 193 int err; 193 194 194 - err = virtio_find_vqs(vi->vdev, 2, vqs, cbs, names, NULL); 195 + err = virtio_find_vqs(vi->vdev, 2, vqs, vqs_info, NULL); 195 196 if (err) 196 197 return err; 197 198 vi->evt = vqs[0];
+6 -6
drivers/virtio/virtio_mmio.c
··· 489 489 490 490 static int vm_find_vqs(struct virtio_device *vdev, unsigned int nvqs, 491 491 struct virtqueue *vqs[], 492 - vq_callback_t *callbacks[], 493 - const char * const names[], 494 - const bool *ctx, 492 + struct virtqueue_info vqs_info[], 495 493 struct irq_affinity *desc) 496 494 { 497 495 struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); ··· 508 510 enable_irq_wake(irq); 509 511 510 512 for (i = 0; i < nvqs; ++i) { 511 - if (!names[i]) { 513 + struct virtqueue_info *vqi = &vqs_info[i]; 514 + 515 + if (!vqi->name) { 512 516 vqs[i] = NULL; 513 517 continue; 514 518 } 515 519 516 - vqs[i] = vm_setup_vq(vdev, queue_idx++, callbacks[i], names[i], 517 - ctx ? ctx[i] : false); 520 + vqs[i] = vm_setup_vq(vdev, queue_idx++, vqi->callback, 521 + vqi->name, vqi->ctx); 518 522 if (IS_ERR(vqs[i])) { 519 523 vm_del_vqs(vdev); 520 524 return PTR_ERR(vqs[i]);
+26 -22
drivers/virtio/virtio_pci_common.c
··· 285 285 } 286 286 287 287 static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned int nvqs, 288 - struct virtqueue *vqs[], vq_callback_t *callbacks[], 289 - const char * const names[], bool per_vq_vectors, 290 - const bool *ctx, 291 - struct irq_affinity *desc) 288 + struct virtqueue *vqs[], 289 + struct virtqueue_info vqs_info[], 290 + bool per_vq_vectors, 291 + struct irq_affinity *desc) 292 292 { 293 293 struct virtio_pci_device *vp_dev = to_vp_device(vdev); 294 + struct virtqueue_info *vqi; 294 295 u16 msix_vec; 295 296 int i, err, nvectors, allocated_vectors, queue_idx = 0; 296 297 ··· 302 301 if (per_vq_vectors) { 303 302 /* Best option: one for change interrupt, one per vq. */ 304 303 nvectors = 1; 305 - for (i = 0; i < nvqs; ++i) 306 - if (names[i] && callbacks[i]) 304 + for (i = 0; i < nvqs; ++i) { 305 + vqi = &vqs_info[i]; 306 + if (vqi->name && vqi->callback) 307 307 ++nvectors; 308 + } 308 309 } else { 309 310 /* Second best: one for change, shared for all vqs. */ 310 311 nvectors = 2; ··· 320 317 vp_dev->per_vq_vectors = per_vq_vectors; 321 318 allocated_vectors = vp_dev->msix_used_vectors; 322 319 for (i = 0; i < nvqs; ++i) { 323 - if (!names[i]) { 320 + vqi = &vqs_info[i]; 321 + if (!vqi->name) { 324 322 vqs[i] = NULL; 325 323 continue; 326 324 } 327 325 328 - if (!callbacks[i]) 326 + if (!vqi->callback) 329 327 msix_vec = VIRTIO_MSI_NO_VECTOR; 330 328 else if (vp_dev->per_vq_vectors) 331 329 msix_vec = allocated_vectors++; 332 330 else 333 331 msix_vec = VP_MSIX_VQ_VECTOR; 334 - vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i], 335 - ctx ? ctx[i] : false, 336 - msix_vec); 332 + vqs[i] = vp_setup_vq(vdev, queue_idx++, vqi->callback, 333 + vqi->name, vqi->ctx, msix_vec); 337 334 if (IS_ERR(vqs[i])) { 338 335 err = PTR_ERR(vqs[i]); 339 336 goto error_find; ··· 346 343 snprintf(vp_dev->msix_names[msix_vec], 347 344 sizeof *vp_dev->msix_names, 348 345 "%s-%s", 349 - dev_name(&vp_dev->vdev.dev), names[i]); 346 + dev_name(&vp_dev->vdev.dev), vqi->name); 350 347 err = request_irq(pci_irq_vector(vp_dev->pci_dev, msix_vec), 351 348 vring_interrupt, 0, 352 349 vp_dev->msix_names[msix_vec], ··· 364 361 } 365 362 366 363 static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned int nvqs, 367 - struct virtqueue *vqs[], vq_callback_t *callbacks[], 368 - const char * const names[], const bool *ctx) 364 + struct virtqueue *vqs[], 365 + struct virtqueue_info vqs_info[]) 369 366 { 370 367 struct virtio_pci_device *vp_dev = to_vp_device(vdev); 371 368 int i, err, queue_idx = 0; ··· 382 379 vp_dev->intx_enabled = 1; 383 380 vp_dev->per_vq_vectors = false; 384 381 for (i = 0; i < nvqs; ++i) { 385 - if (!names[i]) { 382 + struct virtqueue_info *vqi = &vqs_info[i]; 383 + 384 + if (!vqi->name) { 386 385 vqs[i] = NULL; 387 386 continue; 388 387 } 389 - vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i], 390 - ctx ? ctx[i] : false, 388 + vqs[i] = vp_setup_vq(vdev, queue_idx++, vqi->callback, 389 + vqi->name, vqi->ctx, 391 390 VIRTIO_MSI_NO_VECTOR); 392 391 if (IS_ERR(vqs[i])) { 393 392 err = PTR_ERR(vqs[i]); ··· 405 400 406 401 /* the config->find_vqs() implementation */ 407 402 int vp_find_vqs(struct virtio_device *vdev, unsigned int nvqs, 408 - struct virtqueue *vqs[], vq_callback_t *callbacks[], 409 - const char * const names[], const bool *ctx, 403 + struct virtqueue *vqs[], struct virtqueue_info vqs_info[], 410 404 struct irq_affinity *desc) 411 405 { 412 406 int err; 413 407 414 408 /* Try MSI-X with one vector per queue. */ 415 - err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, true, ctx, desc); 409 + err = vp_find_vqs_msix(vdev, nvqs, vqs, vqs_info, true, desc); 416 410 if (!err) 417 411 return 0; 418 412 /* Fallback: MSI-X with one vector for config, one shared for queues. */ 419 - err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, false, ctx, desc); 413 + err = vp_find_vqs_msix(vdev, nvqs, vqs, vqs_info, false, desc); 420 414 if (!err) 421 415 return 0; 422 416 /* Is there an interrupt? If not give up. */ 423 417 if (!(to_vp_device(vdev)->pci_dev->irq)) 424 418 return err; 425 419 /* Finally fall back to regular interrupts. */ 426 - return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names, ctx); 420 + return vp_find_vqs_intx(vdev, nvqs, vqs, vqs_info); 427 421 } 428 422 429 423 const char *vp_bus_name(struct virtio_device *vdev)
+1 -2
drivers/virtio/virtio_pci_common.h
··· 127 127 void vp_del_vqs(struct virtio_device *vdev); 128 128 /* the config->find_vqs() implementation */ 129 129 int vp_find_vqs(struct virtio_device *vdev, unsigned int nvqs, 130 - struct virtqueue *vqs[], vq_callback_t *callbacks[], 131 - const char * const names[], const bool *ctx, 130 + struct virtqueue *vqs[], struct virtqueue_info vqs_info[], 132 131 struct irq_affinity *desc); 133 132 const char *vp_bus_name(struct virtio_device *vdev); 134 133
+2 -3
drivers/virtio/virtio_pci_modern.c
··· 595 595 596 596 static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned int nvqs, 597 597 struct virtqueue *vqs[], 598 - vq_callback_t *callbacks[], 599 - const char * const names[], const bool *ctx, 598 + struct virtqueue_info vqs_info[], 600 599 struct irq_affinity *desc) 601 600 { 602 601 struct virtio_pci_device *vp_dev = to_vp_device(vdev); 603 602 struct virtqueue *vq; 604 - int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc); 603 + int rc = vp_find_vqs(vdev, nvqs, vqs, vqs_info, desc); 605 604 606 605 if (rc) 607 606 return rc;
+4 -1
drivers/virtio/virtio_ring.c
··· 3121 3121 { 3122 3122 struct vring_virtqueue *vq = to_vvq(_vq); 3123 3123 3124 - if (!vq->use_dma_api) 3124 + if (!vq->use_dma_api) { 3125 + kmsan_handle_dma(virt_to_page(ptr), offset_in_page(ptr), size, dir); 3125 3126 return (dma_addr_t)virt_to_phys(ptr); 3127 + } 3126 3128 3127 3129 return dma_map_single_attrs(vring_dma_dev(vq), ptr, size, dir, attrs); 3128 3130 } ··· 3246 3244 } 3247 3245 EXPORT_SYMBOL_GPL(virtqueue_dma_sync_single_range_for_device); 3248 3246 3247 + MODULE_DESCRIPTION("Virtio ring implementation"); 3249 3248 MODULE_LICENSE("GPL");
+6 -7
drivers/virtio/virtio_vdpa.c
··· 358 358 359 359 static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned int nvqs, 360 360 struct virtqueue *vqs[], 361 - vq_callback_t *callbacks[], 362 - const char * const names[], 363 - const bool *ctx, 361 + struct virtqueue_info vqs_info[], 364 362 struct irq_affinity *desc) 365 363 { 366 364 struct virtio_vdpa_device *vd_dev = to_virtio_vdpa_device(vdev); ··· 377 379 } 378 380 379 381 for (i = 0; i < nvqs; ++i) { 380 - if (!names[i]) { 382 + struct virtqueue_info *vqi = &vqs_info[i]; 383 + 384 + if (!vqi->name) { 381 385 vqs[i] = NULL; 382 386 continue; 383 387 } 384 388 385 - vqs[i] = virtio_vdpa_setup_vq(vdev, queue_idx++, 386 - callbacks[i], names[i], ctx ? 387 - ctx[i] : false); 389 + vqs[i] = virtio_vdpa_setup_vq(vdev, queue_idx++, vqi->callback, 390 + vqi->name, vqi->ctx); 388 391 if (IS_ERR(vqs[i])) { 389 392 err = PTR_ERR(vqs[i]); 390 393 goto err_setup_vq;
+31 -31
fs/fuse/virtio_fs.c
··· 51 51 struct work_struct done_work; 52 52 struct list_head queued_reqs; 53 53 struct list_head end_reqs; /* End these requests */ 54 - struct delayed_work dispatch_work; 54 + struct work_struct dispatch_work; 55 55 struct fuse_dev *fud; 56 56 bool connected; 57 57 long in_flight; ··· 233 233 } 234 234 235 235 flush_work(&fsvq->done_work); 236 - flush_delayed_work(&fsvq->dispatch_work); 236 + flush_work(&fsvq->dispatch_work); 237 237 } 238 238 239 239 static void virtio_fs_drain_all_queues_locked(struct virtio_fs *fs) ··· 408 408 dec_in_flight_req(fsvq); 409 409 } 410 410 } while (!virtqueue_enable_cb(vq)); 411 + 412 + if (!list_empty(&fsvq->queued_reqs)) 413 + schedule_work(&fsvq->dispatch_work); 414 + 411 415 spin_unlock(&fsvq->lock); 412 416 } 413 417 ··· 419 415 { 420 416 struct fuse_req *req; 421 417 struct virtio_fs_vq *fsvq = container_of(work, struct virtio_fs_vq, 422 - dispatch_work.work); 418 + dispatch_work); 423 419 int ret; 424 420 425 421 pr_debug("virtio-fs: worker %s called.\n", __func__); ··· 451 447 452 448 ret = virtio_fs_enqueue_req(fsvq, req, true); 453 449 if (ret < 0) { 454 - if (ret == -ENOMEM || ret == -ENOSPC) { 450 + if (ret == -ENOSPC) { 455 451 spin_lock(&fsvq->lock); 456 452 list_add_tail(&req->list, &fsvq->queued_reqs); 457 - schedule_delayed_work(&fsvq->dispatch_work, 458 - msecs_to_jiffies(1)); 459 453 spin_unlock(&fsvq->lock); 460 454 return; 461 455 } ··· 496 494 497 495 ret = virtqueue_add_outbuf(vq, &sg, 1, forget, GFP_ATOMIC); 498 496 if (ret < 0) { 499 - if (ret == -ENOMEM || ret == -ENOSPC) { 497 + if (ret == -ENOSPC) { 500 498 pr_debug("virtio-fs: Could not queue FORGET: err=%d. Will try later\n", 501 499 ret); 502 500 list_add_tail(&forget->list, &fsvq->queued_reqs); 503 - schedule_delayed_work(&fsvq->dispatch_work, 504 - msecs_to_jiffies(1)); 505 501 if (!in_flight) 506 502 inc_in_flight_req(fsvq); 507 503 /* Queue is full */ ··· 531 531 { 532 532 struct virtio_fs_forget *forget; 533 533 struct virtio_fs_vq *fsvq = container_of(work, struct virtio_fs_vq, 534 - dispatch_work.work); 534 + dispatch_work); 535 535 pr_debug("virtio-fs: worker %s called.\n", __func__); 536 536 while (1) { 537 537 spin_lock(&fsvq->lock); ··· 709 709 virtio_fs_request_complete(req, fsvq); 710 710 } 711 711 } 712 + 713 + /* Try to push previously queued requests, as the queue might no longer be full */ 714 + spin_lock(&fsvq->lock); 715 + if (!list_empty(&fsvq->queued_reqs)) 716 + schedule_work(&fsvq->dispatch_work); 717 + spin_unlock(&fsvq->lock); 712 718 } 713 719 714 720 static void virtio_fs_map_queues(struct virtio_device *vdev, struct virtio_fs *fs) ··· 776 770 777 771 if (vq_type == VQ_REQUEST) { 778 772 INIT_WORK(&fsvq->done_work, virtio_fs_requests_done_work); 779 - INIT_DELAYED_WORK(&fsvq->dispatch_work, 780 - virtio_fs_request_dispatch_work); 773 + INIT_WORK(&fsvq->dispatch_work, 774 + virtio_fs_request_dispatch_work); 781 775 } else { 782 776 INIT_WORK(&fsvq->done_work, virtio_fs_hiprio_done_work); 783 - INIT_DELAYED_WORK(&fsvq->dispatch_work, 784 - virtio_fs_hiprio_dispatch_work); 777 + INIT_WORK(&fsvq->dispatch_work, 778 + virtio_fs_hiprio_dispatch_work); 785 779 } 786 780 } 787 781 ··· 789 783 static int virtio_fs_setup_vqs(struct virtio_device *vdev, 790 784 struct virtio_fs *fs) 791 785 { 786 + struct virtqueue_info *vqs_info; 792 787 struct virtqueue **vqs; 793 - vq_callback_t **callbacks; 794 788 /* Specify pre_vectors to ensure that the queues before the 795 789 * request queues (e.g. hiprio) don't claim any of the CPUs in 796 790 * the multi-queue mapping and interrupt affinities 797 791 */ 798 792 struct irq_affinity desc = { .pre_vectors = VQ_REQUEST }; 799 - const char **names; 800 793 unsigned int i; 801 794 int ret = 0; 802 795 ··· 813 808 return -ENOMEM; 814 809 815 810 vqs = kmalloc_array(fs->nvqs, sizeof(vqs[VQ_HIPRIO]), GFP_KERNEL); 816 - callbacks = kmalloc_array(fs->nvqs, sizeof(callbacks[VQ_HIPRIO]), 817 - GFP_KERNEL); 818 - names = kmalloc_array(fs->nvqs, sizeof(names[VQ_HIPRIO]), GFP_KERNEL); 819 811 fs->mq_map = kcalloc_node(nr_cpu_ids, sizeof(*fs->mq_map), GFP_KERNEL, 820 812 dev_to_node(&vdev->dev)); 821 - if (!vqs || !callbacks || !names || !fs->mq_map) { 813 + vqs_info = kcalloc(fs->nvqs, sizeof(*vqs_info), GFP_KERNEL); 814 + if (!vqs || !vqs_info || !fs->mq_map) { 822 815 ret = -ENOMEM; 823 816 goto out; 824 817 } 825 818 826 819 /* Initialize the hiprio/forget request virtqueue */ 827 - callbacks[VQ_HIPRIO] = virtio_fs_vq_done; 820 + vqs_info[VQ_HIPRIO].callback = virtio_fs_vq_done; 828 821 virtio_fs_init_vq(&fs->vqs[VQ_HIPRIO], "hiprio", VQ_HIPRIO); 829 - names[VQ_HIPRIO] = fs->vqs[VQ_HIPRIO].name; 822 + vqs_info[VQ_HIPRIO].name = fs->vqs[VQ_HIPRIO].name; 830 823 831 824 /* Initialize the requests virtqueues */ 832 825 for (i = VQ_REQUEST; i < fs->nvqs; i++) { ··· 832 829 833 830 snprintf(vq_name, VQ_NAME_LEN, "requests.%u", i - VQ_REQUEST); 834 831 virtio_fs_init_vq(&fs->vqs[i], vq_name, VQ_REQUEST); 835 - callbacks[i] = virtio_fs_vq_done; 836 - names[i] = fs->vqs[i].name; 832 + vqs_info[i].callback = virtio_fs_vq_done; 833 + vqs_info[i].name = fs->vqs[i].name; 837 834 } 838 835 839 - ret = virtio_find_vqs(vdev, fs->nvqs, vqs, callbacks, names, &desc); 836 + ret = virtio_find_vqs(vdev, fs->nvqs, vqs, vqs_info, &desc); 840 837 if (ret < 0) 841 838 goto out; 842 839 ··· 845 842 846 843 virtio_fs_start_all_queues(fs); 847 844 out: 848 - kfree(names); 849 - kfree(callbacks); 845 + kfree(vqs_info); 850 846 kfree(vqs); 851 847 if (ret) { 852 848 kfree(fs->vqs); ··· 1369 1367 fsvq = &fs->vqs[queue_id]; 1370 1368 ret = virtio_fs_enqueue_req(fsvq, req, false); 1371 1369 if (ret < 0) { 1372 - if (ret == -ENOMEM || ret == -ENOSPC) { 1370 + if (ret == -ENOSPC) { 1373 1371 /* 1374 1372 * Virtqueue full. Retry submission from worker 1375 1373 * context as we might be holding fc->bg_lock. ··· 1377 1375 spin_lock(&fsvq->lock); 1378 1376 list_add_tail(&req->list, &fsvq->queued_reqs); 1379 1377 inc_in_flight_req(fsvq); 1380 - schedule_delayed_work(&fsvq->dispatch_work, 1381 - msecs_to_jiffies(1)); 1382 1378 spin_unlock(&fsvq->lock); 1383 1379 return; 1384 1380 } ··· 1386 1386 /* Can't end request in submission context. Use a worker */ 1387 1387 spin_lock(&fsvq->lock); 1388 1388 list_add_tail(&req->list, &fsvq->end_reqs); 1389 - schedule_delayed_work(&fsvq->dispatch_work, 0); 1389 + schedule_work(&fsvq->dispatch_work); 1390 1390 spin_unlock(&fsvq->lock); 1391 1391 return; 1392 1392 }
+2
include/linux/mlx5/mlx5_ifc_vdpa.h
··· 148 148 MLX5_VIRTQ_MODIFY_MASK_VIRTIO_Q_ADDRS = (u64)1 << 6, 149 149 MLX5_VIRTQ_MODIFY_MASK_VIRTIO_Q_AVAIL_IDX = (u64)1 << 7, 150 150 MLX5_VIRTQ_MODIFY_MASK_VIRTIO_Q_USED_IDX = (u64)1 << 8, 151 + MLX5_VIRTQ_MODIFY_MASK_QUEUE_VIRTIO_VERSION = (u64)1 << 10, 151 152 MLX5_VIRTQ_MODIFY_MASK_VIRTIO_Q_MKEY = (u64)1 << 11, 153 + MLX5_VIRTQ_MODIFY_MASK_QUEUE_FEATURES = (u64)1 << 12, 152 154 MLX5_VIRTQ_MODIFY_MASK_DESC_GROUP_MKEY = (u64)1 << 14, 153 155 }; 154 156
+33 -31
include/linux/virtio_config.h
··· 19 19 typedef void vq_callback_t(struct virtqueue *); 20 20 21 21 /** 22 + * struct virtqueue_info - Info for a virtqueue passed to find_vqs(). 23 + * @name: virtqueue description. Used mainly for debugging, NULL for 24 + * a virtqueue unused by the driver. 25 + * @callback: A callback to invoke on a used buffer notification. 26 + * NULL for a virtqueue that does not need a callback. 27 + * @ctx: A flag to indicate to maintain an extra context per virtqueue. 28 + */ 29 + struct virtqueue_info { 30 + const char *name; 31 + vq_callback_t *callback; 32 + bool ctx; 33 + }; 34 + 35 + /** 22 36 * struct virtio_config_ops - operations for configuring a virtio device 23 37 * Note: Do not assume that a transport implements all of the operations 24 38 * getting/setting a value as a simple read/write! Generally speaking, ··· 67 53 * vdev: the virtio_device 68 54 * nvqs: the number of virtqueues to find 69 55 * vqs: on success, includes new virtqueues 70 - * callbacks: array of callbacks, for each virtqueue 71 - * include a NULL entry for vqs that do not need a callback 72 - * names: array of virtqueue names (mainly for debugging) 73 - * include a NULL entry for vqs unused by driver 56 + * vqs_info: array of virtqueue info structures 74 57 * Returns 0 on success or error status 75 58 * @del_vqs: free virtqueues found by find_vqs(). 76 59 * @synchronize_cbs: synchronize with the virtqueue callbacks (optional) ··· 116 105 u8 (*get_status)(struct virtio_device *vdev); 117 106 void (*set_status)(struct virtio_device *vdev, u8 status); 118 107 void (*reset)(struct virtio_device *vdev); 119 - int (*find_vqs)(struct virtio_device *, unsigned nvqs, 120 - struct virtqueue *vqs[], vq_callback_t *callbacks[], 121 - const char * const names[], const bool *ctx, 108 + int (*find_vqs)(struct virtio_device *vdev, unsigned int nvqs, 109 + struct virtqueue *vqs[], 110 + struct virtqueue_info vqs_info[], 122 111 struct irq_affinity *desc); 123 112 void (*del_vqs)(struct virtio_device *); 124 113 void (*synchronize_cbs)(struct virtio_device *); ··· 128 117 int (*set_vq_affinity)(struct virtqueue *vq, 129 118 const struct cpumask *cpu_mask); 130 119 const struct cpumask *(*get_vq_affinity)(struct virtio_device *vdev, 131 - int index); 120 + int index); 132 121 bool (*get_shm_region)(struct virtio_device *vdev, 133 122 struct virtio_shm_region *region, u8 id); 134 123 int (*disable_vq_and_reset)(struct virtqueue *vq); ··· 222 211 } 223 212 224 213 static inline 214 + int virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs, 215 + struct virtqueue *vqs[], 216 + struct virtqueue_info vqs_info[], 217 + struct irq_affinity *desc) 218 + { 219 + return vdev->config->find_vqs(vdev, nvqs, vqs, vqs_info, desc); 220 + } 221 + 222 + static inline 225 223 struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev, 226 224 vq_callback_t *c, const char *n) 227 225 { 228 - vq_callback_t *callbacks[] = { c }; 229 - const char *names[] = { n }; 226 + struct virtqueue_info vqs_info[] = { 227 + { n, c }, 228 + }; 230 229 struct virtqueue *vq; 231 - int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL, 232 - NULL); 230 + int err = virtio_find_vqs(vdev, 1, &vq, vqs_info, NULL); 231 + 233 232 if (err < 0) 234 233 return ERR_PTR(err); 235 234 return vq; 236 - } 237 - 238 - static inline 239 - int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs, 240 - struct virtqueue *vqs[], vq_callback_t *callbacks[], 241 - const char * const names[], 242 - struct irq_affinity *desc) 243 - { 244 - return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc); 245 - } 246 - 247 - static inline 248 - int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs, 249 - struct virtqueue *vqs[], vq_callback_t *callbacks[], 250 - const char * const names[], const bool *ctx, 251 - struct irq_affinity *desc) 252 - { 253 - return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, 254 - desc); 255 235 } 256 236 257 237 /**
+11
include/linux/virtio_net.h
··· 56 56 unsigned int thlen = 0; 57 57 unsigned int p_off = 0; 58 58 unsigned int ip_proto; 59 + u64 ret, remainder, gso_size; 59 60 60 61 if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { 61 62 switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { ··· 98 97 u32 start = __virtio16_to_cpu(little_endian, hdr->csum_start); 99 98 u32 off = __virtio16_to_cpu(little_endian, hdr->csum_offset); 100 99 u32 needed = start + max_t(u32, thlen, off + sizeof(__sum16)); 100 + 101 + if (hdr->gso_size) { 102 + gso_size = __virtio16_to_cpu(little_endian, hdr->gso_size); 103 + ret = div64_u64_rem(skb->len, gso_size, &remainder); 104 + if (!(ret && (hdr->gso_size > needed) && 105 + ((remainder > needed) || (remainder == 0)))) { 106 + return -EINVAL; 107 + } 108 + skb_shinfo(skb)->tx_flags |= SKBFL_SHARED_FRAG; 109 + } 101 110 102 111 if (!pskb_may_pull(skb, needed)) 103 112 return -EINVAL;
+5 -11
net/vmw_vsock/virtio_transport.c
··· 617 617 static int virtio_vsock_vqs_init(struct virtio_vsock *vsock) 618 618 { 619 619 struct virtio_device *vdev = vsock->vdev; 620 - static const char * const names[] = { 621 - "rx", 622 - "tx", 623 - "event", 624 - }; 625 - vq_callback_t *callbacks[] = { 626 - virtio_vsock_rx_done, 627 - virtio_vsock_tx_done, 628 - virtio_vsock_event_done, 620 + struct virtqueue_info vqs_info[] = { 621 + { "rx", virtio_vsock_rx_done }, 622 + { "tx", virtio_vsock_tx_done }, 623 + { "event", virtio_vsock_event_done }, 629 624 }; 630 625 int ret; 631 626 632 - ret = virtio_find_vqs(vdev, VSOCK_VQ_MAX, vsock->vqs, callbacks, names, 633 - NULL); 627 + ret = virtio_find_vqs(vdev, VSOCK_VQ_MAX, vsock->vqs, vqs_info, NULL); 634 628 if (ret < 0) 635 629 return ret; 636 630
+10 -13
sound/virtio/virtio_card.c
··· 110 110 static int virtsnd_find_vqs(struct virtio_snd *snd) 111 111 { 112 112 struct virtio_device *vdev = snd->vdev; 113 - static vq_callback_t *callbacks[VIRTIO_SND_VQ_MAX] = { 114 - [VIRTIO_SND_VQ_CONTROL] = virtsnd_ctl_notify_cb, 115 - [VIRTIO_SND_VQ_EVENT] = virtsnd_event_notify_cb, 116 - [VIRTIO_SND_VQ_TX] = virtsnd_pcm_tx_notify_cb, 117 - [VIRTIO_SND_VQ_RX] = virtsnd_pcm_rx_notify_cb 118 - }; 119 - static const char *names[VIRTIO_SND_VQ_MAX] = { 120 - [VIRTIO_SND_VQ_CONTROL] = "virtsnd-ctl", 121 - [VIRTIO_SND_VQ_EVENT] = "virtsnd-event", 122 - [VIRTIO_SND_VQ_TX] = "virtsnd-tx", 123 - [VIRTIO_SND_VQ_RX] = "virtsnd-rx" 113 + struct virtqueue_info vqs_info[VIRTIO_SND_VQ_MAX] = { 114 + [VIRTIO_SND_VQ_CONTROL] = { "virtsnd-ctl", 115 + virtsnd_ctl_notify_cb }, 116 + [VIRTIO_SND_VQ_EVENT] = { "virtsnd-event", 117 + virtsnd_event_notify_cb }, 118 + [VIRTIO_SND_VQ_TX] = { "virtsnd-tx", 119 + virtsnd_pcm_tx_notify_cb }, 120 + [VIRTIO_SND_VQ_RX] = { "virtsnd-rx", 121 + virtsnd_pcm_rx_notify_cb }, 124 122 }; 125 123 struct virtqueue *vqs[VIRTIO_SND_VQ_MAX] = { 0 }; 126 124 unsigned int i; 127 125 unsigned int n; 128 126 int rc; 129 127 130 - rc = virtio_find_vqs(vdev, VIRTIO_SND_VQ_MAX, vqs, callbacks, names, 131 - NULL); 128 + rc = virtio_find_vqs(vdev, VIRTIO_SND_VQ_MAX, vqs, vqs_info, NULL); 132 129 if (rc) { 133 130 dev_err(&vdev->dev, "failed to initialize virtqueues\n"); 134 131 return rc;
+6 -3
tools/virtio/vringh_test.c
··· 139 139 bool fast_vringh) 140 140 { 141 141 void *host_map, *guest_map; 142 - int fd, mapsize, to_guest[2], to_host[2]; 142 + int pipe_ret, fd, mapsize, to_guest[2], to_host[2]; 143 143 unsigned long xfers = 0, notifies = 0, receives = 0; 144 144 unsigned int first_cpu, last_cpu; 145 145 cpu_set_t cpu_set; ··· 161 161 host_map = mmap(NULL, mapsize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 162 162 guest_map = mmap(NULL, mapsize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 163 163 164 - pipe(to_guest); 165 - pipe(to_host); 164 + pipe_ret = pipe(to_guest); 165 + assert(!pipe_ret); 166 + 167 + pipe_ret = pipe(to_host); 168 + assert(!pipe_ret); 166 169 167 170 CPU_ZERO(&cpu_set); 168 171 find_cpus(&first_cpu, &last_cpu);