diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-10 14:33:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-10 14:33:08 -0400 |
commit | c44b59430393c38873fd933333d945f426857a59 (patch) | |
tree | 1af82d499fb4abb67487962f8d03f4088b367f37 | |
parent | 5ccd414080822d5257c3569f4aeca74f63f4a257 (diff) | |
parent | c8b0d7290657996a29f318b948d2397d30e70c36 (diff) |
Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
Pull virtio updates from Michael Tsirkin:
"Fixes, cleanups, performance
A bunch of changes to virtio, most affecting virtio net. Also ptr_ring
batched zeroing - first of batching enhancements that seems ready."
* tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost:
s390/virtio: change maintainership
tools/virtio: fix spelling mistake: "wakeus" -> "wakeups"
virtio_net: tidy a couple debug statements
ptr_ring: support testing different batching sizes
ringtest: support test specific parameters
ptr_ring: batch ring zeroing
virtio: virtio_driver doc
virtio_net: don't reset twice on XDP on/off
virtio_net: fix support for small rings
virtio_net: reduce alignment for buffers
virtio_net: rework mergeable buffer handling
virtio_net: allow specifying context for rx
virtio: allow extra context per descriptor
tools/virtio: fix build breakage
virtio: add context flag to find vqs
virtio: wrap find_vqs
ringtest: fix an assert statement
32 files changed, 330 insertions, 146 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 2decf40d28e1..66b1e1a2d203 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -13556,8 +13556,8 @@ F: include/uapi/linux/virtio_*.h | |||
13556 | F: drivers/crypto/virtio/ | 13556 | F: drivers/crypto/virtio/ |
13557 | 13557 | ||
13558 | VIRTIO DRIVERS FOR S390 | 13558 | VIRTIO DRIVERS FOR S390 |
13559 | M: Christian Borntraeger <borntraeger@de.ibm.com> | ||
13560 | M: Cornelia Huck <cornelia.huck@de.ibm.com> | 13559 | M: Cornelia Huck <cornelia.huck@de.ibm.com> |
13560 | M: Halil Pasic <pasic@linux.vnet.ibm.com> | ||
13561 | L: linux-s390@vger.kernel.org | 13561 | L: linux-s390@vger.kernel.org |
13562 | L: virtualization@lists.linux-foundation.org | 13562 | L: virtualization@lists.linux-foundation.org |
13563 | L: kvm@vger.kernel.org | 13563 | L: kvm@vger.kernel.org |
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 94173de1efaa..553cc4c542b4 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -452,8 +452,7 @@ static int init_vq(struct virtio_blk *vblk) | |||
452 | } | 452 | } |
453 | 453 | ||
454 | /* Discover virtqueues and write information to configuration. */ | 454 | /* Discover virtqueues and write information to configuration. */ |
455 | err = vdev->config->find_vqs(vdev, num_vqs, vqs, callbacks, names, | 455 | err = virtio_find_vqs(vdev, num_vqs, vqs, callbacks, names, &desc); |
456 | &desc); | ||
457 | if (err) | 456 | if (err) |
458 | goto out; | 457 | goto out; |
459 | 458 | ||
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 7d041d026680..ad843eb02ae7 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -1945,9 +1945,9 @@ static int init_vqs(struct ports_device *portdev) | |||
1945 | } | 1945 | } |
1946 | } | 1946 | } |
1947 | /* Find the queues. */ | 1947 | /* Find the queues. */ |
1948 | err = portdev->vdev->config->find_vqs(portdev->vdev, nr_queues, vqs, | 1948 | err = virtio_find_vqs(portdev->vdev, nr_queues, vqs, |
1949 | io_callbacks, | 1949 | io_callbacks, |
1950 | (const char **)io_names, NULL); | 1950 | (const char **)io_names, NULL); |
1951 | if (err) | 1951 | if (err) |
1952 | goto free; | 1952 | goto free; |
1953 | 1953 | ||
diff --git a/drivers/crypto/virtio/virtio_crypto_core.c b/drivers/crypto/virtio/virtio_crypto_core.c index 21472e427f6f..a111cd72797b 100644 --- a/drivers/crypto/virtio/virtio_crypto_core.c +++ b/drivers/crypto/virtio/virtio_crypto_core.c | |||
@@ -119,8 +119,7 @@ static int virtcrypto_find_vqs(struct virtio_crypto *vi) | |||
119 | names[i] = vi->data_vq[i].name; | 119 | names[i] = vi->data_vq[i].name; |
120 | } | 120 | } |
121 | 121 | ||
122 | ret = vi->vdev->config->find_vqs(vi->vdev, total_vqs, vqs, callbacks, | 122 | ret = virtio_find_vqs(vi->vdev, total_vqs, vqs, callbacks, names, NULL); |
123 | names, NULL); | ||
124 | if (ret) | 123 | if (ret) |
125 | goto err_find; | 124 | goto err_find; |
126 | 125 | ||
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index 491866865c33..1e1c90b30d4a 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c | |||
@@ -175,8 +175,7 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags) | |||
175 | DRM_INFO("virgl 3d acceleration not supported by guest\n"); | 175 | DRM_INFO("virgl 3d acceleration not supported by guest\n"); |
176 | #endif | 176 | #endif |
177 | 177 | ||
178 | ret = vgdev->vdev->config->find_vqs(vgdev->vdev, 2, vqs, | 178 | ret = virtio_find_vqs(vgdev->vdev, 2, vqs, callbacks, names, NULL); |
179 | callbacks, names, NULL); | ||
180 | if (ret) { | 179 | if (ret) { |
181 | DRM_ERROR("failed to find virt queues\n"); | 180 | DRM_ERROR("failed to find virt queues\n"); |
182 | goto err_vqs; | 181 | goto err_vqs; |
diff --git a/drivers/misc/mic/vop/vop_main.c b/drivers/misc/mic/vop/vop_main.c index c2e29d7f0de8..a341938c7e2c 100644 --- a/drivers/misc/mic/vop/vop_main.c +++ b/drivers/misc/mic/vop/vop_main.c | |||
@@ -278,7 +278,7 @@ static void vop_del_vqs(struct virtio_device *dev) | |||
278 | static struct virtqueue *vop_find_vq(struct virtio_device *dev, | 278 | static struct virtqueue *vop_find_vq(struct virtio_device *dev, |
279 | unsigned index, | 279 | unsigned index, |
280 | void (*callback)(struct virtqueue *vq), | 280 | void (*callback)(struct virtqueue *vq), |
281 | const char *name) | 281 | const char *name, bool ctx) |
282 | { | 282 | { |
283 | struct _vop_vdev *vdev = to_vopvdev(dev); | 283 | struct _vop_vdev *vdev = to_vopvdev(dev); |
284 | struct vop_device *vpdev = vdev->vpdev; | 284 | struct vop_device *vpdev = vdev->vpdev; |
@@ -314,6 +314,7 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev, | |||
314 | le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN, | 314 | le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN, |
315 | dev, | 315 | dev, |
316 | false, | 316 | false, |
317 | ctx, | ||
317 | (void __force *)va, vop_notify, callback, name); | 318 | (void __force *)va, vop_notify, callback, name); |
318 | if (!vq) { | 319 | if (!vq) { |
319 | err = -ENOMEM; | 320 | err = -ENOMEM; |
@@ -374,7 +375,8 @@ unmap: | |||
374 | static int vop_find_vqs(struct virtio_device *dev, unsigned nvqs, | 375 | static int vop_find_vqs(struct virtio_device *dev, unsigned nvqs, |
375 | struct virtqueue *vqs[], | 376 | struct virtqueue *vqs[], |
376 | vq_callback_t *callbacks[], | 377 | vq_callback_t *callbacks[], |
377 | const char * const names[], struct irq_affinity *desc) | 378 | const char * const names[], const bool *ctx, |
379 | struct irq_affinity *desc) | ||
378 | { | 380 | { |
379 | struct _vop_vdev *vdev = to_vopvdev(dev); | 381 | struct _vop_vdev *vdev = to_vopvdev(dev); |
380 | struct vop_device *vpdev = vdev->vpdev; | 382 | struct vop_device *vpdev = vdev->vpdev; |
@@ -388,7 +390,8 @@ static int vop_find_vqs(struct virtio_device *dev, unsigned nvqs, | |||
388 | for (i = 0; i < nvqs; ++i) { | 390 | for (i = 0; i < nvqs; ++i) { |
389 | dev_dbg(_vop_dev(vdev), "%s: %d: %s\n", | 391 | dev_dbg(_vop_dev(vdev), "%s: %d: %s\n", |
390 | __func__, i, names[i]); | 392 | __func__, i, names[i]); |
391 | vqs[i] = vop_find_vq(dev, i, callbacks[i], names[i]); | 393 | vqs[i] = vop_find_vq(dev, i, callbacks[i], names[i], |
394 | ctx ? ctx[i] : false); | ||
392 | if (IS_ERR(vqs[i])) { | 395 | if (IS_ERR(vqs[i])) { |
393 | err = PTR_ERR(vqs[i]); | 396 | err = PTR_ERR(vqs[i]); |
394 | goto error; | 397 | goto error; |
diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c index bc0eb47eccee..6122768c8644 100644 --- a/drivers/net/caif/caif_virtio.c +++ b/drivers/net/caif/caif_virtio.c | |||
@@ -679,8 +679,7 @@ static int cfv_probe(struct virtio_device *vdev) | |||
679 | goto err; | 679 | goto err; |
680 | 680 | ||
681 | /* Get the TX virtio ring. This is a "guest side vring". */ | 681 | /* Get the TX virtio ring. This is a "guest side vring". */ |
682 | err = vdev->config->find_vqs(vdev, 1, &cfv->vq_tx, &vq_cbs, &names, | 682 | err = virtio_find_vqs(vdev, 1, &cfv->vq_tx, &vq_cbs, &names, NULL); |
683 | NULL); | ||
684 | if (err) | 683 | if (err) |
685 | goto err; | 684 | goto err; |
686 | 685 | ||
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 1c6d3923c224..9320d96a1632 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/cpu.h> | 30 | #include <linux/cpu.h> |
31 | #include <linux/average.h> | 31 | #include <linux/average.h> |
32 | #include <net/route.h> | ||
32 | 33 | ||
33 | static int napi_weight = NAPI_POLL_WEIGHT; | 34 | static int napi_weight = NAPI_POLL_WEIGHT; |
34 | module_param(napi_weight, int, 0444); | 35 | module_param(napi_weight, int, 0444); |
@@ -54,17 +55,6 @@ module_param(napi_tx, bool, 0644); | |||
54 | */ | 55 | */ |
55 | DECLARE_EWMA(pkt_len, 0, 64) | 56 | DECLARE_EWMA(pkt_len, 0, 64) |
56 | 57 | ||
57 | /* With mergeable buffers we align buffer address and use the low bits to | ||
58 | * encode its true size. Buffer size is up to 1 page so we need to align to | ||
59 | * square root of page size to ensure we reserve enough bits to encode the true | ||
60 | * size. | ||
61 | */ | ||
62 | #define MERGEABLE_BUFFER_MIN_ALIGN_SHIFT ((PAGE_SHIFT + 1) / 2) | ||
63 | |||
64 | /* Minimum alignment for mergeable packet buffers. */ | ||
65 | #define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, \ | ||
66 | 1 << MERGEABLE_BUFFER_MIN_ALIGN_SHIFT) | ||
67 | |||
68 | #define VIRTNET_DRIVER_VERSION "1.0.0" | 58 | #define VIRTNET_DRIVER_VERSION "1.0.0" |
69 | 59 | ||
70 | struct virtnet_stats { | 60 | struct virtnet_stats { |
@@ -112,6 +102,9 @@ struct receive_queue { | |||
112 | /* RX: fragments + linear part + virtio header */ | 102 | /* RX: fragments + linear part + virtio header */ |
113 | struct scatterlist sg[MAX_SKB_FRAGS + 2]; | 103 | struct scatterlist sg[MAX_SKB_FRAGS + 2]; |
114 | 104 | ||
105 | /* Min single buffer size for mergeable buffers case. */ | ||
106 | unsigned int min_buf_len; | ||
107 | |||
115 | /* Name of this receive queue: input.$index */ | 108 | /* Name of this receive queue: input.$index */ |
116 | char name[40]; | 109 | char name[40]; |
117 | }; | 110 | }; |
@@ -277,24 +270,6 @@ static void skb_xmit_done(struct virtqueue *vq) | |||
277 | netif_wake_subqueue(vi->dev, vq2txq(vq)); | 270 | netif_wake_subqueue(vi->dev, vq2txq(vq)); |
278 | } | 271 | } |
279 | 272 | ||
280 | static unsigned int mergeable_ctx_to_buf_truesize(unsigned long mrg_ctx) | ||
281 | { | ||
282 | unsigned int truesize = mrg_ctx & (MERGEABLE_BUFFER_ALIGN - 1); | ||
283 | return (truesize + 1) * MERGEABLE_BUFFER_ALIGN; | ||
284 | } | ||
285 | |||
286 | static void *mergeable_ctx_to_buf_address(unsigned long mrg_ctx) | ||
287 | { | ||
288 | return (void *)(mrg_ctx & -MERGEABLE_BUFFER_ALIGN); | ||
289 | |||
290 | } | ||
291 | |||
292 | static unsigned long mergeable_buf_to_ctx(void *buf, unsigned int truesize) | ||
293 | { | ||
294 | unsigned int size = truesize / MERGEABLE_BUFFER_ALIGN; | ||
295 | return (unsigned long)buf | (size - 1); | ||
296 | } | ||
297 | |||
298 | /* Called from bottom half context */ | 273 | /* Called from bottom half context */ |
299 | static struct sk_buff *page_to_skb(struct virtnet_info *vi, | 274 | static struct sk_buff *page_to_skb(struct virtnet_info *vi, |
300 | struct receive_queue *rq, | 275 | struct receive_queue *rq, |
@@ -538,15 +513,13 @@ static struct page *xdp_linearize_page(struct receive_queue *rq, | |||
538 | 513 | ||
539 | while (--*num_buf) { | 514 | while (--*num_buf) { |
540 | unsigned int buflen; | 515 | unsigned int buflen; |
541 | unsigned long ctx; | ||
542 | void *buf; | 516 | void *buf; |
543 | int off; | 517 | int off; |
544 | 518 | ||
545 | ctx = (unsigned long)virtqueue_get_buf(rq->vq, &buflen); | 519 | buf = virtqueue_get_buf(rq->vq, &buflen); |
546 | if (unlikely(!ctx)) | 520 | if (unlikely(!buf)) |
547 | goto err_buf; | 521 | goto err_buf; |
548 | 522 | ||
549 | buf = mergeable_ctx_to_buf_address(ctx); | ||
550 | p = virt_to_head_page(buf); | 523 | p = virt_to_head_page(buf); |
551 | off = buf - page_address(p); | 524 | off = buf - page_address(p); |
552 | 525 | ||
@@ -575,10 +548,10 @@ err_buf: | |||
575 | static struct sk_buff *receive_mergeable(struct net_device *dev, | 548 | static struct sk_buff *receive_mergeable(struct net_device *dev, |
576 | struct virtnet_info *vi, | 549 | struct virtnet_info *vi, |
577 | struct receive_queue *rq, | 550 | struct receive_queue *rq, |
578 | unsigned long ctx, | 551 | void *buf, |
552 | void *ctx, | ||
579 | unsigned int len) | 553 | unsigned int len) |
580 | { | 554 | { |
581 | void *buf = mergeable_ctx_to_buf_address(ctx); | ||
582 | struct virtio_net_hdr_mrg_rxbuf *hdr = buf; | 555 | struct virtio_net_hdr_mrg_rxbuf *hdr = buf; |
583 | u16 num_buf = virtio16_to_cpu(vi->vdev, hdr->num_buffers); | 556 | u16 num_buf = virtio16_to_cpu(vi->vdev, hdr->num_buffers); |
584 | struct page *page = virt_to_head_page(buf); | 557 | struct page *page = virt_to_head_page(buf); |
@@ -666,7 +639,13 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, | |||
666 | } | 639 | } |
667 | rcu_read_unlock(); | 640 | rcu_read_unlock(); |
668 | 641 | ||
669 | truesize = max(len, mergeable_ctx_to_buf_truesize(ctx)); | 642 | if (unlikely(len > (unsigned long)ctx)) { |
643 | pr_debug("%s: rx error: len %u exceeds truesize %lu\n", | ||
644 | dev->name, len, (unsigned long)ctx); | ||
645 | dev->stats.rx_length_errors++; | ||
646 | goto err_skb; | ||
647 | } | ||
648 | truesize = (unsigned long)ctx; | ||
670 | head_skb = page_to_skb(vi, rq, page, offset, len, truesize); | 649 | head_skb = page_to_skb(vi, rq, page, offset, len, truesize); |
671 | curr_skb = head_skb; | 650 | curr_skb = head_skb; |
672 | 651 | ||
@@ -675,7 +654,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, | |||
675 | while (--num_buf) { | 654 | while (--num_buf) { |
676 | int num_skb_frags; | 655 | int num_skb_frags; |
677 | 656 | ||
678 | ctx = (unsigned long)virtqueue_get_buf(rq->vq, &len); | 657 | buf = virtqueue_get_buf_ctx(rq->vq, &len, &ctx); |
679 | if (unlikely(!ctx)) { | 658 | if (unlikely(!ctx)) { |
680 | pr_debug("%s: rx error: %d buffers out of %d missing\n", | 659 | pr_debug("%s: rx error: %d buffers out of %d missing\n", |
681 | dev->name, num_buf, | 660 | dev->name, num_buf, |
@@ -685,8 +664,14 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, | |||
685 | goto err_buf; | 664 | goto err_buf; |
686 | } | 665 | } |
687 | 666 | ||
688 | buf = mergeable_ctx_to_buf_address(ctx); | ||
689 | page = virt_to_head_page(buf); | 667 | page = virt_to_head_page(buf); |
668 | if (unlikely(len > (unsigned long)ctx)) { | ||
669 | pr_debug("%s: rx error: len %u exceeds truesize %lu\n", | ||
670 | dev->name, len, (unsigned long)ctx); | ||
671 | dev->stats.rx_length_errors++; | ||
672 | goto err_skb; | ||
673 | } | ||
674 | truesize = (unsigned long)ctx; | ||
690 | 675 | ||
691 | num_skb_frags = skb_shinfo(curr_skb)->nr_frags; | 676 | num_skb_frags = skb_shinfo(curr_skb)->nr_frags; |
692 | if (unlikely(num_skb_frags == MAX_SKB_FRAGS)) { | 677 | if (unlikely(num_skb_frags == MAX_SKB_FRAGS)) { |
@@ -702,7 +687,6 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, | |||
702 | head_skb->truesize += nskb->truesize; | 687 | head_skb->truesize += nskb->truesize; |
703 | num_skb_frags = 0; | 688 | num_skb_frags = 0; |
704 | } | 689 | } |
705 | truesize = max(len, mergeable_ctx_to_buf_truesize(ctx)); | ||
706 | if (curr_skb != head_skb) { | 690 | if (curr_skb != head_skb) { |
707 | head_skb->data_len += len; | 691 | head_skb->data_len += len; |
708 | head_skb->len += len; | 692 | head_skb->len += len; |
@@ -727,14 +711,14 @@ err_xdp: | |||
727 | err_skb: | 711 | err_skb: |
728 | put_page(page); | 712 | put_page(page); |
729 | while (--num_buf) { | 713 | while (--num_buf) { |
730 | ctx = (unsigned long)virtqueue_get_buf(rq->vq, &len); | 714 | buf = virtqueue_get_buf(rq->vq, &len); |
731 | if (unlikely(!ctx)) { | 715 | if (unlikely(!buf)) { |
732 | pr_debug("%s: rx error: %d buffers missing\n", | 716 | pr_debug("%s: rx error: %d buffers missing\n", |
733 | dev->name, num_buf); | 717 | dev->name, num_buf); |
734 | dev->stats.rx_length_errors++; | 718 | dev->stats.rx_length_errors++; |
735 | break; | 719 | break; |
736 | } | 720 | } |
737 | page = virt_to_head_page(mergeable_ctx_to_buf_address(ctx)); | 721 | page = virt_to_head_page(buf); |
738 | put_page(page); | 722 | put_page(page); |
739 | } | 723 | } |
740 | err_buf: | 724 | err_buf: |
@@ -745,7 +729,7 @@ xdp_xmit: | |||
745 | } | 729 | } |
746 | 730 | ||
747 | static int receive_buf(struct virtnet_info *vi, struct receive_queue *rq, | 731 | static int receive_buf(struct virtnet_info *vi, struct receive_queue *rq, |
748 | void *buf, unsigned int len) | 732 | void *buf, unsigned int len, void **ctx) |
749 | { | 733 | { |
750 | struct net_device *dev = vi->dev; | 734 | struct net_device *dev = vi->dev; |
751 | struct sk_buff *skb; | 735 | struct sk_buff *skb; |
@@ -756,9 +740,7 @@ static int receive_buf(struct virtnet_info *vi, struct receive_queue *rq, | |||
756 | pr_debug("%s: short packet %i\n", dev->name, len); | 740 | pr_debug("%s: short packet %i\n", dev->name, len); |
757 | dev->stats.rx_length_errors++; | 741 | dev->stats.rx_length_errors++; |
758 | if (vi->mergeable_rx_bufs) { | 742 | if (vi->mergeable_rx_bufs) { |
759 | unsigned long ctx = (unsigned long)buf; | 743 | put_page(virt_to_head_page(buf)); |
760 | void *base = mergeable_ctx_to_buf_address(ctx); | ||
761 | put_page(virt_to_head_page(base)); | ||
762 | } else if (vi->big_packets) { | 744 | } else if (vi->big_packets) { |
763 | give_pages(rq, buf); | 745 | give_pages(rq, buf); |
764 | } else { | 746 | } else { |
@@ -768,7 +750,7 @@ static int receive_buf(struct virtnet_info *vi, struct receive_queue *rq, | |||
768 | } | 750 | } |
769 | 751 | ||
770 | if (vi->mergeable_rx_bufs) | 752 | if (vi->mergeable_rx_bufs) |
771 | skb = receive_mergeable(dev, vi, rq, (unsigned long)buf, len); | 753 | skb = receive_mergeable(dev, vi, rq, buf, ctx, len); |
772 | else if (vi->big_packets) | 754 | else if (vi->big_packets) |
773 | skb = receive_big(dev, vi, rq, buf, len); | 755 | skb = receive_big(dev, vi, rq, buf, len); |
774 | else | 756 | else |
@@ -880,14 +862,15 @@ static int add_recvbuf_big(struct virtnet_info *vi, struct receive_queue *rq, | |||
880 | return err; | 862 | return err; |
881 | } | 863 | } |
882 | 864 | ||
883 | static unsigned int get_mergeable_buf_len(struct ewma_pkt_len *avg_pkt_len) | 865 | static unsigned int get_mergeable_buf_len(struct receive_queue *rq, |
866 | struct ewma_pkt_len *avg_pkt_len) | ||
884 | { | 867 | { |
885 | const size_t hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); | 868 | const size_t hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); |
886 | unsigned int len; | 869 | unsigned int len; |
887 | 870 | ||
888 | len = hdr_len + clamp_t(unsigned int, ewma_pkt_len_read(avg_pkt_len), | 871 | len = hdr_len + clamp_t(unsigned int, ewma_pkt_len_read(avg_pkt_len), |
889 | GOOD_PACKET_LEN, PAGE_SIZE - hdr_len); | 872 | rq->min_buf_len - hdr_len, PAGE_SIZE - hdr_len); |
890 | return ALIGN(len, MERGEABLE_BUFFER_ALIGN); | 873 | return ALIGN(len, L1_CACHE_BYTES); |
891 | } | 874 | } |
892 | 875 | ||
893 | static int add_recvbuf_mergeable(struct virtnet_info *vi, | 876 | static int add_recvbuf_mergeable(struct virtnet_info *vi, |
@@ -896,17 +879,17 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, | |||
896 | struct page_frag *alloc_frag = &rq->alloc_frag; | 879 | struct page_frag *alloc_frag = &rq->alloc_frag; |
897 | unsigned int headroom = virtnet_get_headroom(vi); | 880 | unsigned int headroom = virtnet_get_headroom(vi); |
898 | char *buf; | 881 | char *buf; |
899 | unsigned long ctx; | 882 | void *ctx; |
900 | int err; | 883 | int err; |
901 | unsigned int len, hole; | 884 | unsigned int len, hole; |
902 | 885 | ||
903 | len = get_mergeable_buf_len(&rq->mrg_avg_pkt_len); | 886 | len = get_mergeable_buf_len(rq, &rq->mrg_avg_pkt_len); |
904 | if (unlikely(!skb_page_frag_refill(len + headroom, alloc_frag, gfp))) | 887 | if (unlikely(!skb_page_frag_refill(len + headroom, alloc_frag, gfp))) |
905 | return -ENOMEM; | 888 | return -ENOMEM; |
906 | 889 | ||
907 | buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset; | 890 | buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset; |
908 | buf += headroom; /* advance address leaving hole at front of pkt */ | 891 | buf += headroom; /* advance address leaving hole at front of pkt */ |
909 | ctx = mergeable_buf_to_ctx(buf, len); | 892 | ctx = (void *)(unsigned long)len; |
910 | get_page(alloc_frag->page); | 893 | get_page(alloc_frag->page); |
911 | alloc_frag->offset += len + headroom; | 894 | alloc_frag->offset += len + headroom; |
912 | hole = alloc_frag->size - alloc_frag->offset; | 895 | hole = alloc_frag->size - alloc_frag->offset; |
@@ -921,7 +904,7 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, | |||
921 | } | 904 | } |
922 | 905 | ||
923 | sg_init_one(rq->sg, buf, len); | 906 | sg_init_one(rq->sg, buf, len); |
924 | err = virtqueue_add_inbuf(rq->vq, rq->sg, 1, (void *)ctx, gfp); | 907 | err = virtqueue_add_inbuf_ctx(rq->vq, rq->sg, 1, buf, ctx, gfp); |
925 | if (err < 0) | 908 | if (err < 0) |
926 | put_page(virt_to_head_page(buf)); | 909 | put_page(virt_to_head_page(buf)); |
927 | 910 | ||
@@ -1032,10 +1015,20 @@ static int virtnet_receive(struct receive_queue *rq, int budget) | |||
1032 | void *buf; | 1015 | void *buf; |
1033 | struct virtnet_stats *stats = this_cpu_ptr(vi->stats); | 1016 | struct virtnet_stats *stats = this_cpu_ptr(vi->stats); |
1034 | 1017 | ||
1035 | while (received < budget && | 1018 | if (vi->mergeable_rx_bufs) { |
1036 | (buf = virtqueue_get_buf(rq->vq, &len)) != NULL) { | 1019 | void *ctx; |
1037 | bytes += receive_buf(vi, rq, buf, len); | 1020 | |
1038 | received++; | 1021 | while (received < budget && |
1022 | (buf = virtqueue_get_buf_ctx(rq->vq, &len, &ctx))) { | ||
1023 | bytes += receive_buf(vi, rq, buf, len, ctx); | ||
1024 | received++; | ||
1025 | } | ||
1026 | } else { | ||
1027 | while (received < budget && | ||
1028 | (buf = virtqueue_get_buf(rq->vq, &len)) != NULL) { | ||
1029 | bytes += receive_buf(vi, rq, buf, len, NULL); | ||
1030 | received++; | ||
1031 | } | ||
1039 | } | 1032 | } |
1040 | 1033 | ||
1041 | if (rq->vq->num_free > virtqueue_get_vring_size(rq->vq) / 2) { | 1034 | if (rq->vq->num_free > virtqueue_get_vring_size(rq->vq) / 2) { |
@@ -1854,7 +1847,6 @@ static int virtnet_reset(struct virtnet_info *vi, int curr_qp, int xdp_qp) | |||
1854 | virtnet_freeze_down(dev); | 1847 | virtnet_freeze_down(dev); |
1855 | _remove_vq_common(vi); | 1848 | _remove_vq_common(vi); |
1856 | 1849 | ||
1857 | dev->config->reset(dev); | ||
1858 | virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); | 1850 | virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); |
1859 | virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER); | 1851 | virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER); |
1860 | 1852 | ||
@@ -2118,9 +2110,7 @@ static void free_unused_bufs(struct virtnet_info *vi) | |||
2118 | 2110 | ||
2119 | while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) { | 2111 | while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) { |
2120 | if (vi->mergeable_rx_bufs) { | 2112 | if (vi->mergeable_rx_bufs) { |
2121 | unsigned long ctx = (unsigned long)buf; | 2113 | put_page(virt_to_head_page(buf)); |
2122 | void *base = mergeable_ctx_to_buf_address(ctx); | ||
2123 | put_page(virt_to_head_page(base)); | ||
2124 | } else if (vi->big_packets) { | 2114 | } else if (vi->big_packets) { |
2125 | give_pages(&vi->rq[i], buf); | 2115 | give_pages(&vi->rq[i], buf); |
2126 | } else { | 2116 | } else { |
@@ -2141,6 +2131,21 @@ static void virtnet_del_vqs(struct virtnet_info *vi) | |||
2141 | virtnet_free_queues(vi); | 2131 | virtnet_free_queues(vi); |
2142 | } | 2132 | } |
2143 | 2133 | ||
2134 | /* How large should a single buffer be so a queue full of these can fit at | ||
2135 | * least one full packet? | ||
2136 | * Logic below assumes the mergeable buffer header is used. | ||
2137 | */ | ||
2138 | static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqueue *vq) | ||
2139 | { | ||
2140 | const unsigned int hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); | ||
2141 | unsigned int rq_size = virtqueue_get_vring_size(vq); | ||
2142 | unsigned int packet_len = vi->big_packets ? IP_MAX_MTU : vi->dev->max_mtu; | ||
2143 | unsigned int buf_len = hdr_len + ETH_HLEN + VLAN_HLEN + packet_len; | ||
2144 | unsigned int min_buf_len = DIV_ROUND_UP(buf_len, rq_size); | ||
2145 | |||
2146 | return max(min_buf_len, hdr_len); | ||
2147 | } | ||
2148 | |||
2144 | static int virtnet_find_vqs(struct virtnet_info *vi) | 2149 | static int virtnet_find_vqs(struct virtnet_info *vi) |
2145 | { | 2150 | { |
2146 | vq_callback_t **callbacks; | 2151 | vq_callback_t **callbacks; |
@@ -2148,6 +2153,7 @@ static int virtnet_find_vqs(struct virtnet_info *vi) | |||
2148 | int ret = -ENOMEM; | 2153 | int ret = -ENOMEM; |
2149 | int i, total_vqs; | 2154 | int i, total_vqs; |
2150 | const char **names; | 2155 | const char **names; |
2156 | bool *ctx; | ||
2151 | 2157 | ||
2152 | /* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by | 2158 | /* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by |
2153 | * possible N-1 RX/TX queue pairs used in multiqueue mode, followed by | 2159 | * possible N-1 RX/TX queue pairs used in multiqueue mode, followed by |
@@ -2166,6 +2172,13 @@ static int virtnet_find_vqs(struct virtnet_info *vi) | |||
2166 | names = kmalloc(total_vqs * sizeof(*names), GFP_KERNEL); | 2172 | names = kmalloc(total_vqs * sizeof(*names), GFP_KERNEL); |
2167 | if (!names) | 2173 | if (!names) |
2168 | goto err_names; | 2174 | goto err_names; |
2175 | if (vi->mergeable_rx_bufs) { | ||
2176 | ctx = kzalloc(total_vqs * sizeof(*ctx), GFP_KERNEL); | ||
2177 | if (!ctx) | ||
2178 | goto err_ctx; | ||
2179 | } else { | ||
2180 | ctx = NULL; | ||
2181 | } | ||
2169 | 2182 | ||
2170 | /* Parameters for control virtqueue, if any */ | 2183 | /* Parameters for control virtqueue, if any */ |
2171 | if (vi->has_cvq) { | 2184 | if (vi->has_cvq) { |
@@ -2181,10 +2194,12 @@ static int virtnet_find_vqs(struct virtnet_info *vi) | |||
2181 | sprintf(vi->sq[i].name, "output.%d", i); | 2194 | sprintf(vi->sq[i].name, "output.%d", i); |
2182 | names[rxq2vq(i)] = vi->rq[i].name; | 2195 | names[rxq2vq(i)] = vi->rq[i].name; |
2183 | names[txq2vq(i)] = vi->sq[i].name; | 2196 | names[txq2vq(i)] = vi->sq[i].name; |
2197 | if (ctx) | ||
2198 | ctx[rxq2vq(i)] = true; | ||
2184 | } | 2199 | } |
2185 | 2200 | ||
2186 | ret = vi->vdev->config->find_vqs(vi->vdev, total_vqs, vqs, callbacks, | 2201 | ret = vi->vdev->config->find_vqs(vi->vdev, total_vqs, vqs, callbacks, |
2187 | names, NULL); | 2202 | names, ctx, NULL); |
2188 | if (ret) | 2203 | if (ret) |
2189 | goto err_find; | 2204 | goto err_find; |
2190 | 2205 | ||
@@ -2196,6 +2211,7 @@ static int virtnet_find_vqs(struct virtnet_info *vi) | |||
2196 | 2211 | ||
2197 | for (i = 0; i < vi->max_queue_pairs; i++) { | 2212 | for (i = 0; i < vi->max_queue_pairs; i++) { |
2198 | vi->rq[i].vq = vqs[rxq2vq(i)]; | 2213 | vi->rq[i].vq = vqs[rxq2vq(i)]; |
2214 | vi->rq[i].min_buf_len = mergeable_min_buf_len(vi, vi->rq[i].vq); | ||
2199 | vi->sq[i].vq = vqs[txq2vq(i)]; | 2215 | vi->sq[i].vq = vqs[txq2vq(i)]; |
2200 | } | 2216 | } |
2201 | 2217 | ||
@@ -2206,6 +2222,8 @@ static int virtnet_find_vqs(struct virtnet_info *vi) | |||
2206 | return 0; | 2222 | return 0; |
2207 | 2223 | ||
2208 | err_find: | 2224 | err_find: |
2225 | kfree(ctx); | ||
2226 | err_ctx: | ||
2209 | kfree(names); | 2227 | kfree(names); |
2210 | err_names: | 2228 | err_names: |
2211 | kfree(callbacks); | 2229 | kfree(callbacks); |
@@ -2282,7 +2300,8 @@ static ssize_t mergeable_rx_buffer_size_show(struct netdev_rx_queue *queue, | |||
2282 | 2300 | ||
2283 | BUG_ON(queue_index >= vi->max_queue_pairs); | 2301 | BUG_ON(queue_index >= vi->max_queue_pairs); |
2284 | avg = &vi->rq[queue_index].mrg_avg_pkt_len; | 2302 | avg = &vi->rq[queue_index].mrg_avg_pkt_len; |
2285 | return sprintf(buf, "%u\n", get_mergeable_buf_len(avg)); | 2303 | return sprintf(buf, "%u\n", |
2304 | get_mergeable_buf_len(&vi->rq[queue_index], avg)); | ||
2286 | } | 2305 | } |
2287 | 2306 | ||
2288 | static struct rx_queue_attribute mergeable_rx_buffer_size_attribute = | 2307 | static struct rx_queue_attribute mergeable_rx_buffer_size_attribute = |
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c index 0142cc3f0c91..294634836b32 100644 --- a/drivers/remoteproc/remoteproc_virtio.c +++ b/drivers/remoteproc/remoteproc_virtio.c | |||
@@ -71,7 +71,7 @@ EXPORT_SYMBOL(rproc_vq_interrupt); | |||
71 | static struct virtqueue *rp_find_vq(struct virtio_device *vdev, | 71 | static struct virtqueue *rp_find_vq(struct virtio_device *vdev, |
72 | unsigned int id, | 72 | unsigned int id, |
73 | void (*callback)(struct virtqueue *vq), | 73 | void (*callback)(struct virtqueue *vq), |
74 | const char *name) | 74 | const char *name, bool ctx) |
75 | { | 75 | { |
76 | struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); | 76 | struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); |
77 | struct rproc *rproc = vdev_to_rproc(vdev); | 77 | struct rproc *rproc = vdev_to_rproc(vdev); |
@@ -103,8 +103,8 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev, | |||
103 | * Create the new vq, and tell virtio we're not interested in | 103 | * Create the new vq, and tell virtio we're not interested in |
104 | * the 'weak' smp barriers, since we're talking with a real device. | 104 | * the 'weak' smp barriers, since we're talking with a real device. |
105 | */ | 105 | */ |
106 | vq = vring_new_virtqueue(id, len, rvring->align, vdev, false, addr, | 106 | vq = vring_new_virtqueue(id, len, rvring->align, vdev, false, ctx, |
107 | rproc_virtio_notify, callback, name); | 107 | addr, rproc_virtio_notify, callback, name); |
108 | if (!vq) { | 108 | if (!vq) { |
109 | dev_err(dev, "vring_new_virtqueue %s failed\n", name); | 109 | dev_err(dev, "vring_new_virtqueue %s failed\n", name); |
110 | rproc_free_vring(rvring); | 110 | rproc_free_vring(rvring); |
@@ -138,12 +138,14 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs, | |||
138 | struct virtqueue *vqs[], | 138 | struct virtqueue *vqs[], |
139 | vq_callback_t *callbacks[], | 139 | vq_callback_t *callbacks[], |
140 | const char * const names[], | 140 | const char * const names[], |
141 | const bool * ctx, | ||
141 | struct irq_affinity *desc) | 142 | struct irq_affinity *desc) |
142 | { | 143 | { |
143 | int i, ret; | 144 | int i, ret; |
144 | 145 | ||
145 | for (i = 0; i < nvqs; ++i) { | 146 | for (i = 0; i < nvqs; ++i) { |
146 | vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i]); | 147 | vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i], |
148 | ctx ? ctx[i] : false); | ||
147 | if (IS_ERR(vqs[i])) { | 149 | if (IS_ERR(vqs[i])) { |
148 | ret = PTR_ERR(vqs[i]); | 150 | ret = PTR_ERR(vqs[i]); |
149 | goto error; | 151 | goto error; |
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index 5e66e081027e..f7cade09d38a 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c | |||
@@ -869,7 +869,7 @@ static int rpmsg_probe(struct virtio_device *vdev) | |||
869 | init_waitqueue_head(&vrp->sendq); | 869 | init_waitqueue_head(&vrp->sendq); |
870 | 870 | ||
871 | /* We expect two virtqueues, rx and tx (and in this order) */ | 871 | /* We expect two virtqueues, rx and tx (and in this order) */ |
872 | err = vdev->config->find_vqs(vdev, 2, vqs, vq_cbs, names, NULL); | 872 | err = virtio_find_vqs(vdev, 2, vqs, vq_cbs, names, NULL); |
873 | if (err) | 873 | if (err) |
874 | goto free_vrp; | 874 | goto free_vrp; |
875 | 875 | ||
diff --git a/drivers/s390/virtio/kvm_virtio.c b/drivers/s390/virtio/kvm_virtio.c index 2ce0b3eb2efe..a99d09a11f05 100644 --- a/drivers/s390/virtio/kvm_virtio.c +++ b/drivers/s390/virtio/kvm_virtio.c | |||
@@ -189,7 +189,7 @@ static bool kvm_notify(struct virtqueue *vq) | |||
189 | static struct virtqueue *kvm_find_vq(struct virtio_device *vdev, | 189 | static struct virtqueue *kvm_find_vq(struct virtio_device *vdev, |
190 | unsigned index, | 190 | unsigned index, |
191 | void (*callback)(struct virtqueue *vq), | 191 | void (*callback)(struct virtqueue *vq), |
192 | const char *name) | 192 | const char *name, bool ctx) |
193 | { | 193 | { |
194 | struct kvm_device *kdev = to_kvmdev(vdev); | 194 | struct kvm_device *kdev = to_kvmdev(vdev); |
195 | struct kvm_vqconfig *config; | 195 | struct kvm_vqconfig *config; |
@@ -211,7 +211,7 @@ static struct virtqueue *kvm_find_vq(struct virtio_device *vdev, | |||
211 | goto out; | 211 | goto out; |
212 | 212 | ||
213 | vq = vring_new_virtqueue(index, config->num, KVM_S390_VIRTIO_RING_ALIGN, | 213 | vq = vring_new_virtqueue(index, config->num, KVM_S390_VIRTIO_RING_ALIGN, |
214 | vdev, true, (void *) config->address, | 214 | vdev, true, ctx, (void *) config->address, |
215 | kvm_notify, callback, name); | 215 | kvm_notify, callback, name); |
216 | if (!vq) { | 216 | if (!vq) { |
217 | err = -ENOMEM; | 217 | err = -ENOMEM; |
@@ -256,6 +256,7 @@ static int kvm_find_vqs(struct virtio_device *vdev, unsigned nvqs, | |||
256 | struct virtqueue *vqs[], | 256 | struct virtqueue *vqs[], |
257 | vq_callback_t *callbacks[], | 257 | vq_callback_t *callbacks[], |
258 | const char * const names[], | 258 | const char * const names[], |
259 | const bool *ctx, | ||
259 | struct irq_affinity *desc) | 260 | struct irq_affinity *desc) |
260 | { | 261 | { |
261 | struct kvm_device *kdev = to_kvmdev(vdev); | 262 | struct kvm_device *kdev = to_kvmdev(vdev); |
@@ -266,7 +267,8 @@ static int kvm_find_vqs(struct virtio_device *vdev, unsigned nvqs, | |||
266 | return -ENOENT; | 267 | return -ENOENT; |
267 | 268 | ||
268 | for (i = 0; i < nvqs; ++i) { | 269 | for (i = 0; i < nvqs; ++i) { |
269 | vqs[i] = kvm_find_vq(vdev, i, callbacks[i], names[i]); | 270 | vqs[i] = kvm_find_vq(vdev, i, callbacks[i], names[i], |
271 | ctx ? ctx[i] : false); | ||
270 | if (IS_ERR(vqs[i])) | 272 | if (IS_ERR(vqs[i])) |
271 | goto error; | 273 | goto error; |
272 | } | 274 | } |
diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c index 0ed209f3d8b0..2a76ea78a0bf 100644 --- a/drivers/s390/virtio/virtio_ccw.c +++ b/drivers/s390/virtio/virtio_ccw.c | |||
@@ -484,7 +484,7 @@ static void virtio_ccw_del_vqs(struct virtio_device *vdev) | |||
484 | 484 | ||
485 | static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev, | 485 | static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev, |
486 | int i, vq_callback_t *callback, | 486 | int i, vq_callback_t *callback, |
487 | const char *name, | 487 | const char *name, bool ctx, |
488 | struct ccw1 *ccw) | 488 | struct ccw1 *ccw) |
489 | { | 489 | { |
490 | struct virtio_ccw_device *vcdev = to_vc_device(vdev); | 490 | struct virtio_ccw_device *vcdev = to_vc_device(vdev); |
@@ -522,7 +522,7 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev, | |||
522 | } | 522 | } |
523 | 523 | ||
524 | vq = vring_new_virtqueue(i, info->num, KVM_VIRTIO_CCW_RING_ALIGN, vdev, | 524 | vq = vring_new_virtqueue(i, info->num, KVM_VIRTIO_CCW_RING_ALIGN, vdev, |
525 | true, info->queue, virtio_ccw_kvm_notify, | 525 | true, ctx, info->queue, virtio_ccw_kvm_notify, |
526 | callback, name); | 526 | callback, name); |
527 | if (!vq) { | 527 | if (!vq) { |
528 | /* For now, we fail if we can't get the requested size. */ | 528 | /* For now, we fail if we can't get the requested size. */ |
@@ -629,6 +629,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs, | |||
629 | struct virtqueue *vqs[], | 629 | struct virtqueue *vqs[], |
630 | vq_callback_t *callbacks[], | 630 | vq_callback_t *callbacks[], |
631 | const char * const names[], | 631 | const char * const names[], |
632 | const bool *ctx, | ||
632 | struct irq_affinity *desc) | 633 | struct irq_affinity *desc) |
633 | { | 634 | { |
634 | struct virtio_ccw_device *vcdev = to_vc_device(vdev); | 635 | struct virtio_ccw_device *vcdev = to_vc_device(vdev); |
@@ -642,7 +643,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs, | |||
642 | 643 | ||
643 | for (i = 0; i < nvqs; ++i) { | 644 | for (i = 0; i < nvqs; ++i) { |
644 | vqs[i] = virtio_ccw_setup_vq(vdev, i, callbacks[i], names[i], | 645 | vqs[i] = virtio_ccw_setup_vq(vdev, i, callbacks[i], names[i], |
645 | ccw); | 646 | ctx ? ctx[i] : false, ccw); |
646 | if (IS_ERR(vqs[i])) { | 647 | if (IS_ERR(vqs[i])) { |
647 | ret = PTR_ERR(vqs[i]); | 648 | ret = PTR_ERR(vqs[i]); |
648 | vqs[i] = NULL; | 649 | vqs[i] = NULL; |
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index a29d068b7696..f8dbfeee6c63 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c | |||
@@ -894,8 +894,7 @@ static int virtscsi_init(struct virtio_device *vdev, | |||
894 | } | 894 | } |
895 | 895 | ||
896 | /* Discover virtqueues and write information to configuration. */ | 896 | /* Discover virtqueues and write information to configuration. */ |
897 | err = vdev->config->find_vqs(vdev, num_vqs, vqs, callbacks, names, | 897 | err = virtio_find_vqs(vdev, num_vqs, vqs, callbacks, names, &desc); |
898 | &desc); | ||
899 | if (err) | 898 | if (err) |
900 | goto out; | 899 | goto out; |
901 | 900 | ||
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 34adf9b9c053..408c174ef0d5 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c | |||
@@ -418,8 +418,7 @@ static int init_vqs(struct virtio_balloon *vb) | |||
418 | * optionally stat. | 418 | * optionally stat. |
419 | */ | 419 | */ |
420 | nvqs = virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ) ? 3 : 2; | 420 | nvqs = virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ) ? 3 : 2; |
421 | err = vb->vdev->config->find_vqs(vb->vdev, nvqs, vqs, callbacks, names, | 421 | err = virtio_find_vqs(vb->vdev, nvqs, vqs, callbacks, names, NULL); |
422 | NULL); | ||
423 | if (err) | 422 | if (err) |
424 | return err; | 423 | return err; |
425 | 424 | ||
diff --git a/drivers/virtio/virtio_input.c b/drivers/virtio/virtio_input.c index 79f1293cda93..3a0468f2ceb0 100644 --- a/drivers/virtio/virtio_input.c +++ b/drivers/virtio/virtio_input.c | |||
@@ -173,8 +173,7 @@ static int virtinput_init_vqs(struct virtio_input *vi) | |||
173 | static const char * const names[] = { "events", "status" }; | 173 | static const char * const names[] = { "events", "status" }; |
174 | int err; | 174 | int err; |
175 | 175 | ||
176 | err = vi->vdev->config->find_vqs(vi->vdev, 2, vqs, cbs, names, | 176 | err = virtio_find_vqs(vi->vdev, 2, vqs, cbs, names, NULL); |
177 | NULL); | ||
178 | if (err) | 177 | if (err) |
179 | return err; | 178 | return err; |
180 | vi->evt = vqs[0]; | 179 | vi->evt = vqs[0]; |
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 78343b8f9034..74dc7170fd35 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c | |||
@@ -351,7 +351,7 @@ static void vm_del_vqs(struct virtio_device *vdev) | |||
351 | 351 | ||
352 | static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index, | 352 | static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index, |
353 | void (*callback)(struct virtqueue *vq), | 353 | void (*callback)(struct virtqueue *vq), |
354 | const char *name) | 354 | const char *name, bool ctx) |
355 | { | 355 | { |
356 | struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); | 356 | struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); |
357 | struct virtio_mmio_vq_info *info; | 357 | struct virtio_mmio_vq_info *info; |
@@ -388,7 +388,7 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index, | |||
388 | 388 | ||
389 | /* Create the vring */ | 389 | /* Create the vring */ |
390 | vq = vring_create_virtqueue(index, num, VIRTIO_MMIO_VRING_ALIGN, vdev, | 390 | vq = vring_create_virtqueue(index, num, VIRTIO_MMIO_VRING_ALIGN, vdev, |
391 | true, true, vm_notify, callback, name); | 391 | true, true, ctx, vm_notify, callback, name); |
392 | if (!vq) { | 392 | if (!vq) { |
393 | err = -ENOMEM; | 393 | err = -ENOMEM; |
394 | goto error_new_virtqueue; | 394 | goto error_new_virtqueue; |
@@ -447,6 +447,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs, | |||
447 | struct virtqueue *vqs[], | 447 | struct virtqueue *vqs[], |
448 | vq_callback_t *callbacks[], | 448 | vq_callback_t *callbacks[], |
449 | const char * const names[], | 449 | const char * const names[], |
450 | const bool *ctx, | ||
450 | struct irq_affinity *desc) | 451 | struct irq_affinity *desc) |
451 | { | 452 | { |
452 | struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); | 453 | struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); |
@@ -459,7 +460,8 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs, | |||
459 | return err; | 460 | return err; |
460 | 461 | ||
461 | for (i = 0; i < nvqs; ++i) { | 462 | for (i = 0; i < nvqs; ++i) { |
462 | vqs[i] = vm_setup_vq(vdev, i, callbacks[i], names[i]); | 463 | vqs[i] = vm_setup_vq(vdev, i, callbacks[i], names[i], |
464 | ctx ? ctx[i] : false); | ||
463 | if (IS_ERR(vqs[i])) { | 465 | if (IS_ERR(vqs[i])) { |
464 | vm_del_vqs(vdev); | 466 | vm_del_vqs(vdev); |
465 | return PTR_ERR(vqs[i]); | 467 | return PTR_ERR(vqs[i]); |
diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c index 698d5d06fa03..007a4f366086 100644 --- a/drivers/virtio/virtio_pci_common.c +++ b/drivers/virtio/virtio_pci_common.c | |||
@@ -172,6 +172,7 @@ error: | |||
172 | static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned index, | 172 | static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned index, |
173 | void (*callback)(struct virtqueue *vq), | 173 | void (*callback)(struct virtqueue *vq), |
174 | const char *name, | 174 | const char *name, |
175 | bool ctx, | ||
175 | u16 msix_vec) | 176 | u16 msix_vec) |
176 | { | 177 | { |
177 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | 178 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); |
@@ -183,7 +184,7 @@ static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned index, | |||
183 | if (!info) | 184 | if (!info) |
184 | return ERR_PTR(-ENOMEM); | 185 | return ERR_PTR(-ENOMEM); |
185 | 186 | ||
186 | vq = vp_dev->setup_vq(vp_dev, info, index, callback, name, | 187 | vq = vp_dev->setup_vq(vp_dev, info, index, callback, name, ctx, |
187 | msix_vec); | 188 | msix_vec); |
188 | if (IS_ERR(vq)) | 189 | if (IS_ERR(vq)) |
189 | goto out_info; | 190 | goto out_info; |
@@ -274,6 +275,7 @@ void vp_del_vqs(struct virtio_device *vdev) | |||
274 | static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs, | 275 | static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs, |
275 | struct virtqueue *vqs[], vq_callback_t *callbacks[], | 276 | struct virtqueue *vqs[], vq_callback_t *callbacks[], |
276 | const char * const names[], bool per_vq_vectors, | 277 | const char * const names[], bool per_vq_vectors, |
278 | const bool *ctx, | ||
277 | struct irq_affinity *desc) | 279 | struct irq_affinity *desc) |
278 | { | 280 | { |
279 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | 281 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); |
@@ -315,6 +317,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs, | |||
315 | else | 317 | else |
316 | msix_vec = VP_MSIX_VQ_VECTOR; | 318 | msix_vec = VP_MSIX_VQ_VECTOR; |
317 | vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i], | 319 | vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i], |
320 | ctx ? ctx[i] : false, | ||
318 | msix_vec); | 321 | msix_vec); |
319 | if (IS_ERR(vqs[i])) { | 322 | if (IS_ERR(vqs[i])) { |
320 | err = PTR_ERR(vqs[i]); | 323 | err = PTR_ERR(vqs[i]); |
@@ -345,7 +348,7 @@ error_find: | |||
345 | 348 | ||
346 | static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs, | 349 | static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs, |
347 | struct virtqueue *vqs[], vq_callback_t *callbacks[], | 350 | struct virtqueue *vqs[], vq_callback_t *callbacks[], |
348 | const char * const names[]) | 351 | const char * const names[], const bool *ctx) |
349 | { | 352 | { |
350 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | 353 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); |
351 | int i, err; | 354 | int i, err; |
@@ -367,6 +370,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs, | |||
367 | continue; | 370 | continue; |
368 | } | 371 | } |
369 | vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i], | 372 | vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i], |
373 | ctx ? ctx[i] : false, | ||
370 | VIRTIO_MSI_NO_VECTOR); | 374 | VIRTIO_MSI_NO_VECTOR); |
371 | if (IS_ERR(vqs[i])) { | 375 | if (IS_ERR(vqs[i])) { |
372 | err = PTR_ERR(vqs[i]); | 376 | err = PTR_ERR(vqs[i]); |
@@ -383,20 +387,21 @@ out_del_vqs: | |||
383 | /* the config->find_vqs() implementation */ | 387 | /* the config->find_vqs() implementation */ |
384 | int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs, | 388 | int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs, |
385 | struct virtqueue *vqs[], vq_callback_t *callbacks[], | 389 | struct virtqueue *vqs[], vq_callback_t *callbacks[], |
386 | const char * const names[], struct irq_affinity *desc) | 390 | const char * const names[], const bool *ctx, |
391 | struct irq_affinity *desc) | ||
387 | { | 392 | { |
388 | int err; | 393 | int err; |
389 | 394 | ||
390 | /* Try MSI-X with one vector per queue. */ | 395 | /* Try MSI-X with one vector per queue. */ |
391 | err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, true, desc); | 396 | err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, true, ctx, desc); |
392 | if (!err) | 397 | if (!err) |
393 | return 0; | 398 | return 0; |
394 | /* Fallback: MSI-X with one vector for config, one shared for queues. */ | 399 | /* Fallback: MSI-X with one vector for config, one shared for queues. */ |
395 | err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, false, desc); | 400 | err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, false, ctx, desc); |
396 | if (!err) | 401 | if (!err) |
397 | return 0; | 402 | return 0; |
398 | /* Finally fall back to regular interrupts. */ | 403 | /* Finally fall back to regular interrupts. */ |
399 | return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names); | 404 | return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names, ctx); |
400 | } | 405 | } |
401 | 406 | ||
402 | const char *vp_bus_name(struct virtio_device *vdev) | 407 | const char *vp_bus_name(struct virtio_device *vdev) |
diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h index e96334aec1e0..135ee3cf7175 100644 --- a/drivers/virtio/virtio_pci_common.h +++ b/drivers/virtio/virtio_pci_common.h | |||
@@ -102,6 +102,7 @@ struct virtio_pci_device { | |||
102 | unsigned idx, | 102 | unsigned idx, |
103 | void (*callback)(struct virtqueue *vq), | 103 | void (*callback)(struct virtqueue *vq), |
104 | const char *name, | 104 | const char *name, |
105 | bool ctx, | ||
105 | u16 msix_vec); | 106 | u16 msix_vec); |
106 | void (*del_vq)(struct virtio_pci_vq_info *info); | 107 | void (*del_vq)(struct virtio_pci_vq_info *info); |
107 | 108 | ||
@@ -131,7 +132,8 @@ void vp_del_vqs(struct virtio_device *vdev); | |||
131 | /* the config->find_vqs() implementation */ | 132 | /* the config->find_vqs() implementation */ |
132 | int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs, | 133 | int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs, |
133 | struct virtqueue *vqs[], vq_callback_t *callbacks[], | 134 | struct virtqueue *vqs[], vq_callback_t *callbacks[], |
134 | const char * const names[], struct irq_affinity *desc); | 135 | const char * const names[], const bool *ctx, |
136 | struct irq_affinity *desc); | ||
135 | const char *vp_bus_name(struct virtio_device *vdev); | 137 | const char *vp_bus_name(struct virtio_device *vdev); |
136 | 138 | ||
137 | /* Setup the affinity for a virtqueue: | 139 | /* Setup the affinity for a virtqueue: |
diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c index 4bfa48fb1324..2780886e8ba3 100644 --- a/drivers/virtio/virtio_pci_legacy.c +++ b/drivers/virtio/virtio_pci_legacy.c | |||
@@ -116,6 +116,7 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, | |||
116 | unsigned index, | 116 | unsigned index, |
117 | void (*callback)(struct virtqueue *vq), | 117 | void (*callback)(struct virtqueue *vq), |
118 | const char *name, | 118 | const char *name, |
119 | bool ctx, | ||
119 | u16 msix_vec) | 120 | u16 msix_vec) |
120 | { | 121 | { |
121 | struct virtqueue *vq; | 122 | struct virtqueue *vq; |
@@ -135,7 +136,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, | |||
135 | /* create the vring */ | 136 | /* create the vring */ |
136 | vq = vring_create_virtqueue(index, num, | 137 | vq = vring_create_virtqueue(index, num, |
137 | VIRTIO_PCI_VRING_ALIGN, &vp_dev->vdev, | 138 | VIRTIO_PCI_VRING_ALIGN, &vp_dev->vdev, |
138 | true, false, vp_notify, callback, name); | 139 | true, false, ctx, |
140 | vp_notify, callback, name); | ||
139 | if (!vq) | 141 | if (!vq) |
140 | return ERR_PTR(-ENOMEM); | 142 | return ERR_PTR(-ENOMEM); |
141 | 143 | ||
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c index 8978f109d2d7..2555d80f6eec 100644 --- a/drivers/virtio/virtio_pci_modern.c +++ b/drivers/virtio/virtio_pci_modern.c | |||
@@ -297,6 +297,7 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, | |||
297 | unsigned index, | 297 | unsigned index, |
298 | void (*callback)(struct virtqueue *vq), | 298 | void (*callback)(struct virtqueue *vq), |
299 | const char *name, | 299 | const char *name, |
300 | bool ctx, | ||
300 | u16 msix_vec) | 301 | u16 msix_vec) |
301 | { | 302 | { |
302 | struct virtio_pci_common_cfg __iomem *cfg = vp_dev->common; | 303 | struct virtio_pci_common_cfg __iomem *cfg = vp_dev->common; |
@@ -328,7 +329,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, | |||
328 | /* create the vring */ | 329 | /* create the vring */ |
329 | vq = vring_create_virtqueue(index, num, | 330 | vq = vring_create_virtqueue(index, num, |
330 | SMP_CACHE_BYTES, &vp_dev->vdev, | 331 | SMP_CACHE_BYTES, &vp_dev->vdev, |
331 | true, true, vp_notify, callback, name); | 332 | true, true, ctx, |
333 | vp_notify, callback, name); | ||
332 | if (!vq) | 334 | if (!vq) |
333 | return ERR_PTR(-ENOMEM); | 335 | return ERR_PTR(-ENOMEM); |
334 | 336 | ||
@@ -387,12 +389,14 @@ err_map_notify: | |||
387 | } | 389 | } |
388 | 390 | ||
389 | static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs, | 391 | static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs, |
390 | struct virtqueue *vqs[], vq_callback_t *callbacks[], | 392 | struct virtqueue *vqs[], |
391 | const char * const names[], struct irq_affinity *desc) | 393 | vq_callback_t *callbacks[], |
394 | const char * const names[], const bool *ctx, | ||
395 | struct irq_affinity *desc) | ||
392 | { | 396 | { |
393 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | 397 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); |
394 | struct virtqueue *vq; | 398 | struct virtqueue *vq; |
395 | int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, desc); | 399 | int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc); |
396 | 400 | ||
397 | if (rc) | 401 | if (rc) |
398 | return rc; | 402 | return rc; |
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 409aeaa49246..5e1b548828e6 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c | |||
@@ -263,6 +263,7 @@ static inline int virtqueue_add(struct virtqueue *_vq, | |||
263 | unsigned int out_sgs, | 263 | unsigned int out_sgs, |
264 | unsigned int in_sgs, | 264 | unsigned int in_sgs, |
265 | void *data, | 265 | void *data, |
266 | void *ctx, | ||
266 | gfp_t gfp) | 267 | gfp_t gfp) |
267 | { | 268 | { |
268 | struct vring_virtqueue *vq = to_vvq(_vq); | 269 | struct vring_virtqueue *vq = to_vvq(_vq); |
@@ -275,6 +276,7 @@ static inline int virtqueue_add(struct virtqueue *_vq, | |||
275 | START_USE(vq); | 276 | START_USE(vq); |
276 | 277 | ||
277 | BUG_ON(data == NULL); | 278 | BUG_ON(data == NULL); |
279 | BUG_ON(ctx && vq->indirect); | ||
278 | 280 | ||
279 | if (unlikely(vq->broken)) { | 281 | if (unlikely(vq->broken)) { |
280 | END_USE(vq); | 282 | END_USE(vq); |
@@ -389,6 +391,8 @@ static inline int virtqueue_add(struct virtqueue *_vq, | |||
389 | vq->desc_state[head].data = data; | 391 | vq->desc_state[head].data = data; |
390 | if (indirect) | 392 | if (indirect) |
391 | vq->desc_state[head].indir_desc = desc; | 393 | vq->desc_state[head].indir_desc = desc; |
394 | if (ctx) | ||
395 | vq->desc_state[head].indir_desc = ctx; | ||
392 | 396 | ||
393 | /* Put entry in available array (but don't update avail->idx until they | 397 | /* Put entry in available array (but don't update avail->idx until they |
394 | * do sync). */ | 398 | * do sync). */ |
@@ -461,7 +465,8 @@ int virtqueue_add_sgs(struct virtqueue *_vq, | |||
461 | for (sg = sgs[i]; sg; sg = sg_next(sg)) | 465 | for (sg = sgs[i]; sg; sg = sg_next(sg)) |
462 | total_sg++; | 466 | total_sg++; |
463 | } | 467 | } |
464 | return virtqueue_add(_vq, sgs, total_sg, out_sgs, in_sgs, data, gfp); | 468 | return virtqueue_add(_vq, sgs, total_sg, out_sgs, in_sgs, |
469 | data, NULL, gfp); | ||
465 | } | 470 | } |
466 | EXPORT_SYMBOL_GPL(virtqueue_add_sgs); | 471 | EXPORT_SYMBOL_GPL(virtqueue_add_sgs); |
467 | 472 | ||
@@ -483,7 +488,7 @@ int virtqueue_add_outbuf(struct virtqueue *vq, | |||
483 | void *data, | 488 | void *data, |
484 | gfp_t gfp) | 489 | gfp_t gfp) |
485 | { | 490 | { |
486 | return virtqueue_add(vq, &sg, num, 1, 0, data, gfp); | 491 | return virtqueue_add(vq, &sg, num, 1, 0, data, NULL, gfp); |
487 | } | 492 | } |
488 | EXPORT_SYMBOL_GPL(virtqueue_add_outbuf); | 493 | EXPORT_SYMBOL_GPL(virtqueue_add_outbuf); |
489 | 494 | ||
@@ -505,11 +510,35 @@ int virtqueue_add_inbuf(struct virtqueue *vq, | |||
505 | void *data, | 510 | void *data, |
506 | gfp_t gfp) | 511 | gfp_t gfp) |
507 | { | 512 | { |
508 | return virtqueue_add(vq, &sg, num, 0, 1, data, gfp); | 513 | return virtqueue_add(vq, &sg, num, 0, 1, data, NULL, gfp); |
509 | } | 514 | } |
510 | EXPORT_SYMBOL_GPL(virtqueue_add_inbuf); | 515 | EXPORT_SYMBOL_GPL(virtqueue_add_inbuf); |
511 | 516 | ||
512 | /** | 517 | /** |
518 | * virtqueue_add_inbuf_ctx - expose input buffers to other end | ||
519 | * @vq: the struct virtqueue we're talking about. | ||
520 | * @sg: scatterlist (must be well-formed and terminated!) | ||
521 | * @num: the number of entries in @sg writable by other side | ||
522 | * @data: the token identifying the buffer. | ||
523 | * @ctx: extra context for the token | ||
524 | * @gfp: how to do memory allocations (if necessary). | ||
525 | * | ||
526 | * Caller must ensure we don't call this with other virtqueue operations | ||
527 | * at the same time (except where noted). | ||
528 | * | ||
529 | * Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO). | ||
530 | */ | ||
531 | int virtqueue_add_inbuf_ctx(struct virtqueue *vq, | ||
532 | struct scatterlist *sg, unsigned int num, | ||
533 | void *data, | ||
534 | void *ctx, | ||
535 | gfp_t gfp) | ||
536 | { | ||
537 | return virtqueue_add(vq, &sg, num, 0, 1, data, ctx, gfp); | ||
538 | } | ||
539 | EXPORT_SYMBOL_GPL(virtqueue_add_inbuf_ctx); | ||
540 | |||
541 | /** | ||
513 | * virtqueue_kick_prepare - first half of split virtqueue_kick call. | 542 | * virtqueue_kick_prepare - first half of split virtqueue_kick call. |
514 | * @vq: the struct virtqueue | 543 | * @vq: the struct virtqueue |
515 | * | 544 | * |
@@ -598,7 +627,8 @@ bool virtqueue_kick(struct virtqueue *vq) | |||
598 | } | 627 | } |
599 | EXPORT_SYMBOL_GPL(virtqueue_kick); | 628 | EXPORT_SYMBOL_GPL(virtqueue_kick); |
600 | 629 | ||
601 | static void detach_buf(struct vring_virtqueue *vq, unsigned int head) | 630 | static void detach_buf(struct vring_virtqueue *vq, unsigned int head, |
631 | void **ctx) | ||
602 | { | 632 | { |
603 | unsigned int i, j; | 633 | unsigned int i, j; |
604 | __virtio16 nextflag = cpu_to_virtio16(vq->vq.vdev, VRING_DESC_F_NEXT); | 634 | __virtio16 nextflag = cpu_to_virtio16(vq->vq.vdev, VRING_DESC_F_NEXT); |
@@ -622,10 +652,15 @@ static void detach_buf(struct vring_virtqueue *vq, unsigned int head) | |||
622 | /* Plus final descriptor */ | 652 | /* Plus final descriptor */ |
623 | vq->vq.num_free++; | 653 | vq->vq.num_free++; |
624 | 654 | ||
625 | /* Free the indirect table, if any, now that it's unmapped. */ | 655 | if (vq->indirect) { |
626 | if (vq->desc_state[head].indir_desc) { | ||
627 | struct vring_desc *indir_desc = vq->desc_state[head].indir_desc; | 656 | struct vring_desc *indir_desc = vq->desc_state[head].indir_desc; |
628 | u32 len = virtio32_to_cpu(vq->vq.vdev, vq->vring.desc[head].len); | 657 | u32 len; |
658 | |||
659 | /* Free the indirect table, if any, now that it's unmapped. */ | ||
660 | if (!indir_desc) | ||
661 | return; | ||
662 | |||
663 | len = virtio32_to_cpu(vq->vq.vdev, vq->vring.desc[head].len); | ||
629 | 664 | ||
630 | BUG_ON(!(vq->vring.desc[head].flags & | 665 | BUG_ON(!(vq->vring.desc[head].flags & |
631 | cpu_to_virtio16(vq->vq.vdev, VRING_DESC_F_INDIRECT))); | 666 | cpu_to_virtio16(vq->vq.vdev, VRING_DESC_F_INDIRECT))); |
@@ -634,8 +669,10 @@ static void detach_buf(struct vring_virtqueue *vq, unsigned int head) | |||
634 | for (j = 0; j < len / sizeof(struct vring_desc); j++) | 669 | for (j = 0; j < len / sizeof(struct vring_desc); j++) |
635 | vring_unmap_one(vq, &indir_desc[j]); | 670 | vring_unmap_one(vq, &indir_desc[j]); |
636 | 671 | ||
637 | kfree(vq->desc_state[head].indir_desc); | 672 | kfree(indir_desc); |
638 | vq->desc_state[head].indir_desc = NULL; | 673 | vq->desc_state[head].indir_desc = NULL; |
674 | } else if (ctx) { | ||
675 | *ctx = vq->desc_state[head].indir_desc; | ||
639 | } | 676 | } |
640 | } | 677 | } |
641 | 678 | ||
@@ -660,7 +697,8 @@ static inline bool more_used(const struct vring_virtqueue *vq) | |||
660 | * Returns NULL if there are no used buffers, or the "data" token | 697 | * Returns NULL if there are no used buffers, or the "data" token |
661 | * handed to virtqueue_add_*(). | 698 | * handed to virtqueue_add_*(). |
662 | */ | 699 | */ |
663 | void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len) | 700 | void *virtqueue_get_buf_ctx(struct virtqueue *_vq, unsigned int *len, |
701 | void **ctx) | ||
664 | { | 702 | { |
665 | struct vring_virtqueue *vq = to_vvq(_vq); | 703 | struct vring_virtqueue *vq = to_vvq(_vq); |
666 | void *ret; | 704 | void *ret; |
@@ -698,7 +736,7 @@ void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len) | |||
698 | 736 | ||
699 | /* detach_buf clears data, so grab it now. */ | 737 | /* detach_buf clears data, so grab it now. */ |
700 | ret = vq->desc_state[i].data; | 738 | ret = vq->desc_state[i].data; |
701 | detach_buf(vq, i); | 739 | detach_buf(vq, i, ctx); |
702 | vq->last_used_idx++; | 740 | vq->last_used_idx++; |
703 | /* If we expect an interrupt for the next entry, tell host | 741 | /* If we expect an interrupt for the next entry, tell host |
704 | * by writing event index and flush out the write before | 742 | * by writing event index and flush out the write before |
@@ -715,8 +753,13 @@ void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len) | |||
715 | END_USE(vq); | 753 | END_USE(vq); |
716 | return ret; | 754 | return ret; |
717 | } | 755 | } |
718 | EXPORT_SYMBOL_GPL(virtqueue_get_buf); | 756 | EXPORT_SYMBOL_GPL(virtqueue_get_buf_ctx); |
719 | 757 | ||
758 | void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len) | ||
759 | { | ||
760 | return virtqueue_get_buf_ctx(_vq, len, NULL); | ||
761 | } | ||
762 | EXPORT_SYMBOL_GPL(virtqueue_get_buf); | ||
720 | /** | 763 | /** |
721 | * virtqueue_disable_cb - disable callbacks | 764 | * virtqueue_disable_cb - disable callbacks |
722 | * @vq: the struct virtqueue we're talking about. | 765 | * @vq: the struct virtqueue we're talking about. |
@@ -878,7 +921,7 @@ void *virtqueue_detach_unused_buf(struct virtqueue *_vq) | |||
878 | continue; | 921 | continue; |
879 | /* detach_buf clears data, so grab it now. */ | 922 | /* detach_buf clears data, so grab it now. */ |
880 | buf = vq->desc_state[i].data; | 923 | buf = vq->desc_state[i].data; |
881 | detach_buf(vq, i); | 924 | detach_buf(vq, i, NULL); |
882 | vq->avail_idx_shadow--; | 925 | vq->avail_idx_shadow--; |
883 | vq->vring.avail->idx = cpu_to_virtio16(_vq->vdev, vq->avail_idx_shadow); | 926 | vq->vring.avail->idx = cpu_to_virtio16(_vq->vdev, vq->avail_idx_shadow); |
884 | END_USE(vq); | 927 | END_USE(vq); |
@@ -916,6 +959,7 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index, | |||
916 | struct vring vring, | 959 | struct vring vring, |
917 | struct virtio_device *vdev, | 960 | struct virtio_device *vdev, |
918 | bool weak_barriers, | 961 | bool weak_barriers, |
962 | bool context, | ||
919 | bool (*notify)(struct virtqueue *), | 963 | bool (*notify)(struct virtqueue *), |
920 | void (*callback)(struct virtqueue *), | 964 | void (*callback)(struct virtqueue *), |
921 | const char *name) | 965 | const char *name) |
@@ -950,7 +994,8 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index, | |||
950 | vq->last_add_time_valid = false; | 994 | vq->last_add_time_valid = false; |
951 | #endif | 995 | #endif |
952 | 996 | ||
953 | vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC); | 997 | vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) && |
998 | !context; | ||
954 | vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX); | 999 | vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX); |
955 | 1000 | ||
956 | /* No callback? Tell other side not to bother us. */ | 1001 | /* No callback? Tell other side not to bother us. */ |
@@ -1019,6 +1064,7 @@ struct virtqueue *vring_create_virtqueue( | |||
1019 | struct virtio_device *vdev, | 1064 | struct virtio_device *vdev, |
1020 | bool weak_barriers, | 1065 | bool weak_barriers, |
1021 | bool may_reduce_num, | 1066 | bool may_reduce_num, |
1067 | bool context, | ||
1022 | bool (*notify)(struct virtqueue *), | 1068 | bool (*notify)(struct virtqueue *), |
1023 | void (*callback)(struct virtqueue *), | 1069 | void (*callback)(struct virtqueue *), |
1024 | const char *name) | 1070 | const char *name) |
@@ -1058,7 +1104,7 @@ struct virtqueue *vring_create_virtqueue( | |||
1058 | queue_size_in_bytes = vring_size(num, vring_align); | 1104 | queue_size_in_bytes = vring_size(num, vring_align); |
1059 | vring_init(&vring, num, queue, vring_align); | 1105 | vring_init(&vring, num, queue, vring_align); |
1060 | 1106 | ||
1061 | vq = __vring_new_virtqueue(index, vring, vdev, weak_barriers, | 1107 | vq = __vring_new_virtqueue(index, vring, vdev, weak_barriers, context, |
1062 | notify, callback, name); | 1108 | notify, callback, name); |
1063 | if (!vq) { | 1109 | if (!vq) { |
1064 | vring_free_queue(vdev, queue_size_in_bytes, queue, | 1110 | vring_free_queue(vdev, queue_size_in_bytes, queue, |
@@ -1079,6 +1125,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int index, | |||
1079 | unsigned int vring_align, | 1125 | unsigned int vring_align, |
1080 | struct virtio_device *vdev, | 1126 | struct virtio_device *vdev, |
1081 | bool weak_barriers, | 1127 | bool weak_barriers, |
1128 | bool context, | ||
1082 | void *pages, | 1129 | void *pages, |
1083 | bool (*notify)(struct virtqueue *vq), | 1130 | bool (*notify)(struct virtqueue *vq), |
1084 | void (*callback)(struct virtqueue *vq), | 1131 | void (*callback)(struct virtqueue *vq), |
@@ -1086,7 +1133,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int index, | |||
1086 | { | 1133 | { |
1087 | struct vring vring; | 1134 | struct vring vring; |
1088 | vring_init(&vring, num, pages, vring_align); | 1135 | vring_init(&vring, num, pages, vring_align); |
1089 | return __vring_new_virtqueue(index, vring, vdev, weak_barriers, | 1136 | return __vring_new_virtqueue(index, vring, vdev, weak_barriers, context, |
1090 | notify, callback, name); | 1137 | notify, callback, name); |
1091 | } | 1138 | } |
1092 | EXPORT_SYMBOL_GPL(vring_new_virtqueue); | 1139 | EXPORT_SYMBOL_GPL(vring_new_virtqueue); |
diff --git a/include/linux/ptr_ring.h b/include/linux/ptr_ring.h index 6c70444da3b9..6b2e0dd88569 100644 --- a/include/linux/ptr_ring.h +++ b/include/linux/ptr_ring.h | |||
@@ -34,11 +34,13 @@ | |||
34 | struct ptr_ring { | 34 | struct ptr_ring { |
35 | int producer ____cacheline_aligned_in_smp; | 35 | int producer ____cacheline_aligned_in_smp; |
36 | spinlock_t producer_lock; | 36 | spinlock_t producer_lock; |
37 | int consumer ____cacheline_aligned_in_smp; | 37 | int consumer_head ____cacheline_aligned_in_smp; /* next valid entry */ |
38 | int consumer_tail; /* next entry to invalidate */ | ||
38 | spinlock_t consumer_lock; | 39 | spinlock_t consumer_lock; |
39 | /* Shared consumer/producer data */ | 40 | /* Shared consumer/producer data */ |
40 | /* Read-only by both the producer and the consumer */ | 41 | /* Read-only by both the producer and the consumer */ |
41 | int size ____cacheline_aligned_in_smp; /* max entries in queue */ | 42 | int size ____cacheline_aligned_in_smp; /* max entries in queue */ |
43 | int batch; /* number of entries to consume in a batch */ | ||
42 | void **queue; | 44 | void **queue; |
43 | }; | 45 | }; |
44 | 46 | ||
@@ -170,7 +172,7 @@ static inline int ptr_ring_produce_bh(struct ptr_ring *r, void *ptr) | |||
170 | static inline void *__ptr_ring_peek(struct ptr_ring *r) | 172 | static inline void *__ptr_ring_peek(struct ptr_ring *r) |
171 | { | 173 | { |
172 | if (likely(r->size)) | 174 | if (likely(r->size)) |
173 | return r->queue[r->consumer]; | 175 | return r->queue[r->consumer_head]; |
174 | return NULL; | 176 | return NULL; |
175 | } | 177 | } |
176 | 178 | ||
@@ -231,9 +233,38 @@ static inline bool ptr_ring_empty_bh(struct ptr_ring *r) | |||
231 | /* Must only be called after __ptr_ring_peek returned !NULL */ | 233 | /* Must only be called after __ptr_ring_peek returned !NULL */ |
232 | static inline void __ptr_ring_discard_one(struct ptr_ring *r) | 234 | static inline void __ptr_ring_discard_one(struct ptr_ring *r) |
233 | { | 235 | { |
234 | r->queue[r->consumer++] = NULL; | 236 | /* Fundamentally, what we want to do is update consumer |
235 | if (unlikely(r->consumer >= r->size)) | 237 | * index and zero out the entry so producer can reuse it. |
236 | r->consumer = 0; | 238 | * Doing it naively at each consume would be as simple as: |
239 | * r->queue[r->consumer++] = NULL; | ||
240 | * if (unlikely(r->consumer >= r->size)) | ||
241 | * r->consumer = 0; | ||
242 | * but that is suboptimal when the ring is full as producer is writing | ||
243 | * out new entries in the same cache line. Defer these updates until a | ||
244 | * batch of entries has been consumed. | ||
245 | */ | ||
246 | int head = r->consumer_head++; | ||
247 | |||
248 | /* Once we have processed enough entries invalidate them in | ||
249 | * the ring all at once so producer can reuse their space in the ring. | ||
250 | * We also do this when we reach end of the ring - not mandatory | ||
251 | * but helps keep the implementation simple. | ||
252 | */ | ||
253 | if (unlikely(r->consumer_head - r->consumer_tail >= r->batch || | ||
254 | r->consumer_head >= r->size)) { | ||
255 | /* Zero out entries in the reverse order: this way we touch the | ||
256 | * cache line that producer might currently be reading the last; | ||
257 | * producer won't make progress and touch other cache lines | ||
258 | * besides the first one until we write out all entries. | ||
259 | */ | ||
260 | while (likely(head >= r->consumer_tail)) | ||
261 | r->queue[head--] = NULL; | ||
262 | r->consumer_tail = r->consumer_head; | ||
263 | } | ||
264 | if (unlikely(r->consumer_head >= r->size)) { | ||
265 | r->consumer_head = 0; | ||
266 | r->consumer_tail = 0; | ||
267 | } | ||
237 | } | 268 | } |
238 | 269 | ||
239 | static inline void *__ptr_ring_consume(struct ptr_ring *r) | 270 | static inline void *__ptr_ring_consume(struct ptr_ring *r) |
@@ -345,14 +376,27 @@ static inline void **__ptr_ring_init_queue_alloc(int size, gfp_t gfp) | |||
345 | return kzalloc(ALIGN(size * sizeof(void *), SMP_CACHE_BYTES), gfp); | 376 | return kzalloc(ALIGN(size * sizeof(void *), SMP_CACHE_BYTES), gfp); |
346 | } | 377 | } |
347 | 378 | ||
379 | static inline void __ptr_ring_set_size(struct ptr_ring *r, int size) | ||
380 | { | ||
381 | r->size = size; | ||
382 | r->batch = SMP_CACHE_BYTES * 2 / sizeof(*(r->queue)); | ||
383 | /* We need to set batch at least to 1 to make logic | ||
384 | * in __ptr_ring_discard_one work correctly. | ||
385 | * Batching too much (because ring is small) would cause a lot of | ||
386 | * burstiness. Needs tuning, for now disable batching. | ||
387 | */ | ||
388 | if (r->batch > r->size / 2 || !r->batch) | ||
389 | r->batch = 1; | ||
390 | } | ||
391 | |||
348 | static inline int ptr_ring_init(struct ptr_ring *r, int size, gfp_t gfp) | 392 | static inline int ptr_ring_init(struct ptr_ring *r, int size, gfp_t gfp) |
349 | { | 393 | { |
350 | r->queue = __ptr_ring_init_queue_alloc(size, gfp); | 394 | r->queue = __ptr_ring_init_queue_alloc(size, gfp); |
351 | if (!r->queue) | 395 | if (!r->queue) |
352 | return -ENOMEM; | 396 | return -ENOMEM; |
353 | 397 | ||
354 | r->size = size; | 398 | __ptr_ring_set_size(r, size); |
355 | r->producer = r->consumer = 0; | 399 | r->producer = r->consumer_head = r->consumer_tail = 0; |
356 | spin_lock_init(&r->producer_lock); | 400 | spin_lock_init(&r->producer_lock); |
357 | spin_lock_init(&r->consumer_lock); | 401 | spin_lock_init(&r->consumer_lock); |
358 | 402 | ||
@@ -373,9 +417,10 @@ static inline void **__ptr_ring_swap_queue(struct ptr_ring *r, void **queue, | |||
373 | else if (destroy) | 417 | else if (destroy) |
374 | destroy(ptr); | 418 | destroy(ptr); |
375 | 419 | ||
376 | r->size = size; | 420 | __ptr_ring_set_size(r, size); |
377 | r->producer = producer; | 421 | r->producer = producer; |
378 | r->consumer = 0; | 422 | r->consumer_head = 0; |
423 | r->consumer_tail = 0; | ||
379 | old = r->queue; | 424 | old = r->queue; |
380 | r->queue = queue; | 425 | r->queue = queue; |
381 | 426 | ||
diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 7edfbdb55a99..28b0e965360f 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h | |||
@@ -44,6 +44,12 @@ int virtqueue_add_inbuf(struct virtqueue *vq, | |||
44 | void *data, | 44 | void *data, |
45 | gfp_t gfp); | 45 | gfp_t gfp); |
46 | 46 | ||
47 | int virtqueue_add_inbuf_ctx(struct virtqueue *vq, | ||
48 | struct scatterlist sg[], unsigned int num, | ||
49 | void *data, | ||
50 | void *ctx, | ||
51 | gfp_t gfp); | ||
52 | |||
47 | int virtqueue_add_sgs(struct virtqueue *vq, | 53 | int virtqueue_add_sgs(struct virtqueue *vq, |
48 | struct scatterlist *sgs[], | 54 | struct scatterlist *sgs[], |
49 | unsigned int out_sgs, | 55 | unsigned int out_sgs, |
@@ -59,6 +65,9 @@ bool virtqueue_notify(struct virtqueue *vq); | |||
59 | 65 | ||
60 | void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len); | 66 | void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len); |
61 | 67 | ||
68 | void *virtqueue_get_buf_ctx(struct virtqueue *vq, unsigned int *len, | ||
69 | void **ctx); | ||
70 | |||
62 | void virtqueue_disable_cb(struct virtqueue *vq); | 71 | void virtqueue_disable_cb(struct virtqueue *vq); |
63 | 72 | ||
64 | bool virtqueue_enable_cb(struct virtqueue *vq); | 73 | bool virtqueue_enable_cb(struct virtqueue *vq); |
@@ -156,9 +165,13 @@ int virtio_device_restore(struct virtio_device *dev); | |||
156 | * @feature_table_legacy: same as feature_table but when working in legacy mode. | 165 | * @feature_table_legacy: same as feature_table but when working in legacy mode. |
157 | * @feature_table_size_legacy: number of entries in feature table legacy array. | 166 | * @feature_table_size_legacy: number of entries in feature table legacy array. |
158 | * @probe: the function to call when a device is found. Returns 0 or -errno. | 167 | * @probe: the function to call when a device is found. Returns 0 or -errno. |
168 | * @scan: optional function to call after successful probe; intended | ||
169 | * for virtio-scsi to invoke a scan. | ||
159 | * @remove: the function to call when a device is removed. | 170 | * @remove: the function to call when a device is removed. |
160 | * @config_changed: optional function to call when the device configuration | 171 | * @config_changed: optional function to call when the device configuration |
161 | * changes; may be called in interrupt context. | 172 | * changes; may be called in interrupt context. |
173 | * @freeze: optional function to call during suspend/hibernation. | ||
174 | * @restore: optional function to call on resume. | ||
162 | */ | 175 | */ |
163 | struct virtio_driver { | 176 | struct virtio_driver { |
164 | struct device_driver driver; | 177 | struct device_driver driver; |
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index 8355bab175e1..0133d8a12ccd 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h | |||
@@ -72,7 +72,8 @@ struct virtio_config_ops { | |||
72 | void (*reset)(struct virtio_device *vdev); | 72 | void (*reset)(struct virtio_device *vdev); |
73 | int (*find_vqs)(struct virtio_device *, unsigned nvqs, | 73 | int (*find_vqs)(struct virtio_device *, unsigned nvqs, |
74 | struct virtqueue *vqs[], vq_callback_t *callbacks[], | 74 | struct virtqueue *vqs[], vq_callback_t *callbacks[], |
75 | const char * const names[], struct irq_affinity *desc); | 75 | const char * const names[], const bool *ctx, |
76 | struct irq_affinity *desc); | ||
76 | void (*del_vqs)(struct virtio_device *); | 77 | void (*del_vqs)(struct virtio_device *); |
77 | u64 (*get_features)(struct virtio_device *vdev); | 78 | u64 (*get_features)(struct virtio_device *vdev); |
78 | int (*finalize_features)(struct virtio_device *vdev); | 79 | int (*finalize_features)(struct virtio_device *vdev); |
@@ -173,12 +174,32 @@ struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev, | |||
173 | vq_callback_t *callbacks[] = { c }; | 174 | vq_callback_t *callbacks[] = { c }; |
174 | const char *names[] = { n }; | 175 | const char *names[] = { n }; |
175 | struct virtqueue *vq; | 176 | struct virtqueue *vq; |
176 | int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL); | 177 | int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL, |
178 | NULL); | ||
177 | if (err < 0) | 179 | if (err < 0) |
178 | return ERR_PTR(err); | 180 | return ERR_PTR(err); |
179 | return vq; | 181 | return vq; |
180 | } | 182 | } |
181 | 183 | ||
184 | static inline | ||
185 | int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs, | ||
186 | struct virtqueue *vqs[], vq_callback_t *callbacks[], | ||
187 | const char * const names[], | ||
188 | struct irq_affinity *desc) | ||
189 | { | ||
190 | return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc); | ||
191 | } | ||
192 | |||
193 | static inline | ||
194 | int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs, | ||
195 | struct virtqueue *vqs[], vq_callback_t *callbacks[], | ||
196 | const char * const names[], const bool *ctx, | ||
197 | struct irq_affinity *desc) | ||
198 | { | ||
199 | return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, | ||
200 | desc); | ||
201 | } | ||
202 | |||
182 | /** | 203 | /** |
183 | * virtio_device_ready - enable vq use in probe function | 204 | * virtio_device_ready - enable vq use in probe function |
184 | * @vdev: the device | 205 | * @vdev: the device |
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h index e8d36938f09a..270cfa81830e 100644 --- a/include/linux/virtio_ring.h +++ b/include/linux/virtio_ring.h | |||
@@ -71,6 +71,7 @@ struct virtqueue *vring_create_virtqueue(unsigned int index, | |||
71 | struct virtio_device *vdev, | 71 | struct virtio_device *vdev, |
72 | bool weak_barriers, | 72 | bool weak_barriers, |
73 | bool may_reduce_num, | 73 | bool may_reduce_num, |
74 | bool ctx, | ||
74 | bool (*notify)(struct virtqueue *vq), | 75 | bool (*notify)(struct virtqueue *vq), |
75 | void (*callback)(struct virtqueue *vq), | 76 | void (*callback)(struct virtqueue *vq), |
76 | const char *name); | 77 | const char *name); |
@@ -80,6 +81,7 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index, | |||
80 | struct vring vring, | 81 | struct vring vring, |
81 | struct virtio_device *vdev, | 82 | struct virtio_device *vdev, |
82 | bool weak_barriers, | 83 | bool weak_barriers, |
84 | bool ctx, | ||
83 | bool (*notify)(struct virtqueue *), | 85 | bool (*notify)(struct virtqueue *), |
84 | void (*callback)(struct virtqueue *), | 86 | void (*callback)(struct virtqueue *), |
85 | const char *name); | 87 | const char *name); |
@@ -93,6 +95,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int index, | |||
93 | unsigned int vring_align, | 95 | unsigned int vring_align, |
94 | struct virtio_device *vdev, | 96 | struct virtio_device *vdev, |
95 | bool weak_barriers, | 97 | bool weak_barriers, |
98 | bool ctx, | ||
96 | void *pages, | 99 | void *pages, |
97 | bool (*notify)(struct virtqueue *vq), | 100 | bool (*notify)(struct virtqueue *vq), |
98 | void (*callback)(struct virtqueue *vq), | 101 | void (*callback)(struct virtqueue *vq), |
diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c index 9dffe0282ad4..403d86e80162 100644 --- a/net/vmw_vsock/virtio_transport.c +++ b/net/vmw_vsock/virtio_transport.c | |||
@@ -576,9 +576,9 @@ static int virtio_vsock_probe(struct virtio_device *vdev) | |||
576 | 576 | ||
577 | vsock->vdev = vdev; | 577 | vsock->vdev = vdev; |
578 | 578 | ||
579 | ret = vsock->vdev->config->find_vqs(vsock->vdev, VSOCK_VQ_MAX, | 579 | ret = virtio_find_vqs(vsock->vdev, VSOCK_VQ_MAX, |
580 | vsock->vqs, callbacks, names, | 580 | vsock->vqs, callbacks, names, |
581 | NULL); | 581 | NULL); |
582 | if (ret < 0) | 582 | if (ret < 0) |
583 | goto out; | 583 | goto out; |
584 | 584 | ||
diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h index 9377c8b4ac16..d8f534025b7f 100644 --- a/tools/virtio/linux/virtio.h +++ b/tools/virtio/linux/virtio.h | |||
@@ -57,6 +57,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int index, | |||
57 | unsigned int vring_align, | 57 | unsigned int vring_align, |
58 | struct virtio_device *vdev, | 58 | struct virtio_device *vdev, |
59 | bool weak_barriers, | 59 | bool weak_barriers, |
60 | bool ctx, | ||
60 | void *pages, | 61 | void *pages, |
61 | bool (*notify)(struct virtqueue *vq), | 62 | bool (*notify)(struct virtqueue *vq), |
62 | void (*callback)(struct virtqueue *vq), | 63 | void (*callback)(struct virtqueue *vq), |
diff --git a/tools/virtio/ringtest/main.c b/tools/virtio/ringtest/main.c index f31353fac541..453ca3c21193 100644 --- a/tools/virtio/ringtest/main.c +++ b/tools/virtio/ringtest/main.c | |||
@@ -20,6 +20,7 @@ | |||
20 | int runcycles = 10000000; | 20 | int runcycles = 10000000; |
21 | int max_outstanding = INT_MAX; | 21 | int max_outstanding = INT_MAX; |
22 | int batch = 1; | 22 | int batch = 1; |
23 | int param = 0; | ||
23 | 24 | ||
24 | bool do_sleep = false; | 25 | bool do_sleep = false; |
25 | bool do_relax = false; | 26 | bool do_relax = false; |
@@ -86,7 +87,7 @@ void set_affinity(const char *arg) | |||
86 | cpu = strtol(arg, &endptr, 0); | 87 | cpu = strtol(arg, &endptr, 0); |
87 | assert(!*endptr); | 88 | assert(!*endptr); |
88 | 89 | ||
89 | assert(cpu >= 0 || cpu < CPU_SETSIZE); | 90 | assert(cpu >= 0 && cpu < CPU_SETSIZE); |
90 | 91 | ||
91 | self = pthread_self(); | 92 | self = pthread_self(); |
92 | CPU_ZERO(&cpuset); | 93 | CPU_ZERO(&cpuset); |
@@ -247,6 +248,11 @@ static const struct option longopts[] = { | |||
247 | .val = 'b', | 248 | .val = 'b', |
248 | }, | 249 | }, |
249 | { | 250 | { |
251 | .name = "param", | ||
252 | .has_arg = required_argument, | ||
253 | .val = 'p', | ||
254 | }, | ||
255 | { | ||
250 | .name = "sleep", | 256 | .name = "sleep", |
251 | .has_arg = no_argument, | 257 | .has_arg = no_argument, |
252 | .val = 's', | 258 | .val = 's', |
@@ -274,6 +280,7 @@ static void help(void) | |||
274 | " [--run-cycles C (default: %d)]" | 280 | " [--run-cycles C (default: %d)]" |
275 | " [--batch b]" | 281 | " [--batch b]" |
276 | " [--outstanding o]" | 282 | " [--outstanding o]" |
283 | " [--param p]" | ||
277 | " [--sleep]" | 284 | " [--sleep]" |
278 | " [--relax]" | 285 | " [--relax]" |
279 | " [--exit]" | 286 | " [--exit]" |
@@ -328,6 +335,12 @@ int main(int argc, char **argv) | |||
328 | assert(c > 0 && c < INT_MAX); | 335 | assert(c > 0 && c < INT_MAX); |
329 | max_outstanding = c; | 336 | max_outstanding = c; |
330 | break; | 337 | break; |
338 | case 'p': | ||
339 | c = strtol(optarg, &endptr, 0); | ||
340 | assert(!*endptr); | ||
341 | assert(c > 0 && c < INT_MAX); | ||
342 | param = c; | ||
343 | break; | ||
331 | case 'b': | 344 | case 'b': |
332 | c = strtol(optarg, &endptr, 0); | 345 | c = strtol(optarg, &endptr, 0); |
333 | assert(!*endptr); | 346 | assert(!*endptr); |
diff --git a/tools/virtio/ringtest/main.h b/tools/virtio/ringtest/main.h index 14142faf040b..90b0133004e1 100644 --- a/tools/virtio/ringtest/main.h +++ b/tools/virtio/ringtest/main.h | |||
@@ -10,6 +10,8 @@ | |||
10 | 10 | ||
11 | #include <stdbool.h> | 11 | #include <stdbool.h> |
12 | 12 | ||
13 | extern int param; | ||
14 | |||
13 | extern bool do_exit; | 15 | extern bool do_exit; |
14 | 16 | ||
15 | #if defined(__x86_64__) || defined(__i386__) | 17 | #if defined(__x86_64__) || defined(__i386__) |
diff --git a/tools/virtio/ringtest/ptr_ring.c b/tools/virtio/ringtest/ptr_ring.c index 635b07b4fdd3..7b22f1b20652 100644 --- a/tools/virtio/ringtest/ptr_ring.c +++ b/tools/virtio/ringtest/ptr_ring.c | |||
@@ -97,6 +97,9 @@ void alloc_ring(void) | |||
97 | { | 97 | { |
98 | int ret = ptr_ring_init(&array, ring_size, 0); | 98 | int ret = ptr_ring_init(&array, ring_size, 0); |
99 | assert(!ret); | 99 | assert(!ret); |
100 | /* Hacky way to poke at ring internals. Useful for testing though. */ | ||
101 | if (param) | ||
102 | array.batch = param; | ||
100 | } | 103 | } |
101 | 104 | ||
102 | /* guest side */ | 105 | /* guest side */ |
diff --git a/tools/virtio/virtio_test.c b/tools/virtio/virtio_test.c index e0445898f08f..0fecaec90d0d 100644 --- a/tools/virtio/virtio_test.c +++ b/tools/virtio/virtio_test.c | |||
@@ -100,7 +100,7 @@ static void vq_info_add(struct vdev_info *dev, int num) | |||
100 | vring_init(&info->vring, num, info->ring, 4096); | 100 | vring_init(&info->vring, num, info->ring, 4096); |
101 | info->vq = vring_new_virtqueue(info->idx, | 101 | info->vq = vring_new_virtqueue(info->idx, |
102 | info->vring.num, 4096, &dev->vdev, | 102 | info->vring.num, 4096, &dev->vdev, |
103 | true, info->ring, | 103 | true, false, info->ring, |
104 | vq_notify, vq_callback, "test"); | 104 | vq_notify, vq_callback, "test"); |
105 | assert(info->vq); | 105 | assert(info->vq); |
106 | info->vq->priv = info; | 106 | info->vq->priv = info; |
@@ -202,7 +202,7 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq, | |||
202 | test = 0; | 202 | test = 0; |
203 | r = ioctl(dev->control, VHOST_TEST_RUN, &test); | 203 | r = ioctl(dev->control, VHOST_TEST_RUN, &test); |
204 | assert(r >= 0); | 204 | assert(r >= 0); |
205 | fprintf(stderr, "spurious wakeus: 0x%llx\n", spurious); | 205 | fprintf(stderr, "spurious wakeups: 0x%llx\n", spurious); |
206 | } | 206 | } |
207 | 207 | ||
208 | const char optstring[] = "h"; | 208 | const char optstring[] = "h"; |
diff --git a/tools/virtio/vringh_test.c b/tools/virtio/vringh_test.c index 5f94f5105678..9476c616d064 100644 --- a/tools/virtio/vringh_test.c +++ b/tools/virtio/vringh_test.c | |||
@@ -314,7 +314,8 @@ static int parallel_test(u64 features, | |||
314 | err(1, "Could not set affinity to cpu %u", first_cpu); | 314 | err(1, "Could not set affinity to cpu %u", first_cpu); |
315 | 315 | ||
316 | vq = vring_new_virtqueue(0, RINGSIZE, ALIGN, &gvdev.vdev, true, | 316 | vq = vring_new_virtqueue(0, RINGSIZE, ALIGN, &gvdev.vdev, true, |
317 | guest_map, fast_vringh ? no_notify_host | 317 | false, guest_map, |
318 | fast_vringh ? no_notify_host | ||
318 | : parallel_notify_host, | 319 | : parallel_notify_host, |
319 | never_callback_guest, "guest vq"); | 320 | never_callback_guest, "guest vq"); |
320 | 321 | ||
@@ -479,7 +480,7 @@ int main(int argc, char *argv[]) | |||
479 | memset(__user_addr_min, 0, vring_size(RINGSIZE, ALIGN)); | 480 | memset(__user_addr_min, 0, vring_size(RINGSIZE, ALIGN)); |
480 | 481 | ||
481 | /* Set up guest side. */ | 482 | /* Set up guest side. */ |
482 | vq = vring_new_virtqueue(0, RINGSIZE, ALIGN, &vdev, true, | 483 | vq = vring_new_virtqueue(0, RINGSIZE, ALIGN, &vdev, true, false, |
483 | __user_addr_min, | 484 | __user_addr_min, |
484 | never_notify_host, never_callback_guest, | 485 | never_notify_host, never_callback_guest, |
485 | "guest vq"); | 486 | "guest vq"); |
@@ -663,7 +664,7 @@ int main(int argc, char *argv[]) | |||
663 | /* Force creation of direct, which we modify. */ | 664 | /* Force creation of direct, which we modify. */ |
664 | __virtio_clear_bit(&vdev, VIRTIO_RING_F_INDIRECT_DESC); | 665 | __virtio_clear_bit(&vdev, VIRTIO_RING_F_INDIRECT_DESC); |
665 | vq = vring_new_virtqueue(0, RINGSIZE, ALIGN, &vdev, true, | 666 | vq = vring_new_virtqueue(0, RINGSIZE, ALIGN, &vdev, true, |
666 | __user_addr_min, | 667 | false, __user_addr_min, |
667 | never_notify_host, | 668 | never_notify_host, |
668 | never_callback_guest, | 669 | never_callback_guest, |
669 | "guest vq"); | 670 | "guest vq"); |