On Thu, Jun 20, 2024 at 12:19:05AM +0800, Heng Qi wrote: > If the device does not respond to a request for a long time, > then control vq polling elevates CPU utilization, a problem that > exacerbates with more command requests. > > Enabling control vq's irq is advantageous for the guest, and > this still doesn't support concurrent requests. > > Suggested-by: Jason Wang <jasowang@xxxxxxxxxx> > Signed-off-by: Heng Qi <hengqi@xxxxxxxxxxxxxxxxx> > --- > drivers/net/virtio_net.c | 22 +++++++++++++--------- > 1 file changed, 13 insertions(+), 9 deletions(-) > > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c > index b45f58a902e3..ed10084997d3 100644 > --- a/drivers/net/virtio_net.c > +++ b/drivers/net/virtio_net.c > @@ -372,6 +372,8 @@ struct virtio_net_ctrl_rss { > struct control_buf { > struct virtio_net_ctrl_hdr hdr; > virtio_net_ctrl_ack status; > + /* Wait for the device to complete the cvq request. */ > + struct completion completion; > }; > > struct virtnet_info { > @@ -664,6 +666,13 @@ static bool virtqueue_napi_complete(struct napi_struct *napi, > return false; > } > > +static void virtnet_cvq_done(struct virtqueue *cvq) > +{ > + struct virtnet_info *vi = cvq->vdev->priv; > + > + complete(&vi->ctrl->completion); > +} > + > static void skb_xmit_done(struct virtqueue *vq) > { > struct virtnet_info *vi = vq->vdev->priv; > @@ -2724,14 +2733,8 @@ static bool virtnet_send_command_reply(struct virtnet_info *vi, > if (unlikely(!virtqueue_kick(vi->cvq))) > goto unlock; > > - /* Spin for a response, the kick causes an ioport write, trapping > - * into the hypervisor, so the request should be handled immediately. > - */ > - while (!virtqueue_get_buf(vi->cvq, &tmp) && > - !virtqueue_is_broken(vi->cvq)) { > - cond_resched(); > - cpu_relax(); > - } > + wait_for_completion(&ctrl->completion); > + virtqueue_get_buf(vi->cvq, &tmp); > > unlock: > ok = ctrl->status == VIRTIO_NET_OK; Hmm no this is not a good idea, code should be robust in case of spurious interrupts. Also suprise removal is now broken ... > @@ -5312,7 +5315,7 @@ static int virtnet_find_vqs(struct virtnet_info *vi) > > /* Parameters for control virtqueue, if any */ > if (vi->has_cvq) { > - callbacks[total_vqs - 1] = NULL; > + callbacks[total_vqs - 1] = virtnet_cvq_done; > names[total_vqs - 1] = "control"; > } > > @@ -5832,6 +5835,7 @@ static int virtnet_probe(struct virtio_device *vdev) > if (vi->has_rss || vi->has_rss_hash_report) > virtnet_init_default_rss(vi); > > + init_completion(&vi->ctrl->completion); > enable_rx_mode_work(vi); > > /* serialize netdev register + virtio_device_ready() with ndo_open() */ > -- > 2.32.0.3.g01195cf9f