diff options
| -rw-r--r-- | drivers/vhost/net.c | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 986058a57917..eeaf6739215f 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c | |||
| @@ -105,7 +105,9 @@ struct vhost_net_virtqueue { | |||
| 105 | /* vhost zerocopy support fields below: */ | 105 | /* vhost zerocopy support fields below: */ |
| 106 | /* last used idx for outstanding DMA zerocopy buffers */ | 106 | /* last used idx for outstanding DMA zerocopy buffers */ |
| 107 | int upend_idx; | 107 | int upend_idx; |
| 108 | /* first used idx for DMA done zerocopy buffers */ | 108 | /* For TX, first used idx for DMA done zerocopy buffers |
| 109 | * For RX, number of batched heads | ||
| 110 | */ | ||
| 109 | int done_idx; | 111 | int done_idx; |
| 110 | /* an array of userspace buffers info */ | 112 | /* an array of userspace buffers info */ |
| 111 | struct ubuf_info *ubuf_info; | 113 | struct ubuf_info *ubuf_info; |
| @@ -626,6 +628,18 @@ static int sk_has_rx_data(struct sock *sk) | |||
| 626 | return skb_queue_empty(&sk->sk_receive_queue); | 628 | return skb_queue_empty(&sk->sk_receive_queue); |
| 627 | } | 629 | } |
| 628 | 630 | ||
| 631 | static void vhost_rx_signal_used(struct vhost_net_virtqueue *nvq) | ||
| 632 | { | ||
| 633 | struct vhost_virtqueue *vq = &nvq->vq; | ||
| 634 | struct vhost_dev *dev = vq->dev; | ||
| 635 | |||
| 636 | if (!nvq->done_idx) | ||
| 637 | return; | ||
| 638 | |||
| 639 | vhost_add_used_and_signal_n(dev, vq, vq->heads, nvq->done_idx); | ||
| 640 | nvq->done_idx = 0; | ||
| 641 | } | ||
| 642 | |||
| 629 | static int vhost_net_rx_peek_head_len(struct vhost_net *net, struct sock *sk) | 643 | static int vhost_net_rx_peek_head_len(struct vhost_net *net, struct sock *sk) |
| 630 | { | 644 | { |
| 631 | struct vhost_net_virtqueue *rvq = &net->vqs[VHOST_NET_VQ_RX]; | 645 | struct vhost_net_virtqueue *rvq = &net->vqs[VHOST_NET_VQ_RX]; |
| @@ -635,6 +649,8 @@ static int vhost_net_rx_peek_head_len(struct vhost_net *net, struct sock *sk) | |||
| 635 | int len = peek_head_len(rvq, sk); | 649 | int len = peek_head_len(rvq, sk); |
| 636 | 650 | ||
| 637 | if (!len && vq->busyloop_timeout) { | 651 | if (!len && vq->busyloop_timeout) { |
| 652 | /* Flush batched heads first */ | ||
| 653 | vhost_rx_signal_used(rvq); | ||
| 638 | /* Both tx vq and rx socket were polled here */ | 654 | /* Both tx vq and rx socket were polled here */ |
| 639 | mutex_lock_nested(&vq->mutex, 1); | 655 | mutex_lock_nested(&vq->mutex, 1); |
| 640 | vhost_disable_notify(&net->dev, vq); | 656 | vhost_disable_notify(&net->dev, vq); |
| @@ -762,7 +778,7 @@ static void handle_rx(struct vhost_net *net) | |||
| 762 | }; | 778 | }; |
| 763 | size_t total_len = 0; | 779 | size_t total_len = 0; |
| 764 | int err, mergeable; | 780 | int err, mergeable; |
| 765 | s16 headcount, nheads = 0; | 781 | s16 headcount; |
| 766 | size_t vhost_hlen, sock_hlen; | 782 | size_t vhost_hlen, sock_hlen; |
| 767 | size_t vhost_len, sock_len; | 783 | size_t vhost_len, sock_len; |
| 768 | struct socket *sock; | 784 | struct socket *sock; |
| @@ -790,8 +806,8 @@ static void handle_rx(struct vhost_net *net) | |||
| 790 | while ((sock_len = vhost_net_rx_peek_head_len(net, sock->sk))) { | 806 | while ((sock_len = vhost_net_rx_peek_head_len(net, sock->sk))) { |
| 791 | sock_len += sock_hlen; | 807 | sock_len += sock_hlen; |
| 792 | vhost_len = sock_len + vhost_hlen; | 808 | vhost_len = sock_len + vhost_hlen; |
| 793 | headcount = get_rx_bufs(vq, vq->heads + nheads, vhost_len, | 809 | headcount = get_rx_bufs(vq, vq->heads + nvq->done_idx, |
| 794 | &in, vq_log, &log, | 810 | vhost_len, &in, vq_log, &log, |
| 795 | likely(mergeable) ? UIO_MAXIOV : 1); | 811 | likely(mergeable) ? UIO_MAXIOV : 1); |
| 796 | /* On error, stop handling until the next kick. */ | 812 | /* On error, stop handling until the next kick. */ |
| 797 | if (unlikely(headcount < 0)) | 813 | if (unlikely(headcount < 0)) |
| @@ -862,12 +878,9 @@ static void handle_rx(struct vhost_net *net) | |||
| 862 | vhost_discard_vq_desc(vq, headcount); | 878 | vhost_discard_vq_desc(vq, headcount); |
| 863 | goto out; | 879 | goto out; |
| 864 | } | 880 | } |
| 865 | nheads += headcount; | 881 | nvq->done_idx += headcount; |
| 866 | if (nheads > VHOST_RX_BATCH) { | 882 | if (nvq->done_idx > VHOST_RX_BATCH) |
| 867 | vhost_add_used_and_signal_n(&net->dev, vq, vq->heads, | 883 | vhost_rx_signal_used(nvq); |
| 868 | nheads); | ||
| 869 | nheads = 0; | ||
| 870 | } | ||
| 871 | if (unlikely(vq_log)) | 884 | if (unlikely(vq_log)) |
| 872 | vhost_log_write(vq, vq_log, log, vhost_len); | 885 | vhost_log_write(vq, vq_log, log, vhost_len); |
| 873 | total_len += vhost_len; | 886 | total_len += vhost_len; |
| @@ -878,9 +891,7 @@ static void handle_rx(struct vhost_net *net) | |||
| 878 | } | 891 | } |
| 879 | vhost_net_enable_vq(net, vq); | 892 | vhost_net_enable_vq(net, vq); |
| 880 | out: | 893 | out: |
| 881 | if (nheads) | 894 | vhost_rx_signal_used(nvq); |
| 882 | vhost_add_used_and_signal_n(&net->dev, vq, vq->heads, | ||
| 883 | nheads); | ||
| 884 | mutex_unlock(&vq->mutex); | 895 | mutex_unlock(&vq->mutex); |
| 885 | } | 896 | } |
| 886 | 897 | ||
