Now, if we want to judge the rx work mode, we have to use such codes: 1. merge mode: vi->mergeable_rx_bufs 2. big mode: vi->big_packets && !vi->mergeable_rx_bufs 3. small: !vi->big_packets && !vi->mergeable_rx_bufs This is inconvenient and abstract, and we also have this use case: if (vi->mergeable_rx_bufs) .... else if (vi->big_packets) .... else For this case, I think switch-case is the better choice. So here I introduce vi->mode to record the virtio-net work mode. That is helpful to judge the work mode and choose the branches. Signed-off-by: Xuan Zhuo <xuanzhuo@xxxxxxxxxxxxxxxxx> --- drivers/net/virtio_net.c | 61 +++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 59a99bbaf852..14809b614d62 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -385,6 +385,12 @@ struct control_buf { virtio_net_ctrl_ack status; }; +enum virtnet_mode { + VIRTNET_MODE_SMALL, + VIRTNET_MODE_MERGE, + VIRTNET_MODE_BIG +}; + struct virtnet_info { struct virtio_device *vdev; struct virtqueue *cvq; @@ -414,6 +420,8 @@ struct virtnet_info { /* Host will merge rx buffers for big packets (shake it! shake it!) */ bool mergeable_rx_bufs; + enum virtnet_mode mode; + /* Host supports rss and/or hash report */ bool has_rss; bool has_rss_hash_report; @@ -643,12 +651,15 @@ static struct page *get_a_page(struct receive_queue *rq, gfp_t gfp_mask) static void virtnet_rq_free_buf(struct virtnet_info *vi, struct receive_queue *rq, void *buf) { - if (vi->mergeable_rx_bufs) + switch (vi->mode) { + case VIRTNET_MODE_SMALL: + case VIRTNET_MODE_MERGE: put_page(virt_to_head_page(buf)); - else if (vi->big_packets) + break; + case VIRTNET_MODE_BIG: give_pages(rq, buf); - else - put_page(virt_to_head_page(buf)); + break; + } } static void enable_delayed_refill(struct virtnet_info *vi) @@ -1315,7 +1326,8 @@ static void virtnet_receive_xsk_buf(struct virtnet_info *vi, struct receive_queu flags = ((struct virtio_net_common_hdr *)(xdp->data - vi->hdr_len))->hdr.flags; - if (!vi->mergeable_rx_bufs) + /* We only support small and merge mode. */ + if (vi->mode == VIRTNET_MODE_SMALL) skb = virtnet_receive_xsk_small(dev, vi, rq, xdp, xdp_xmit, stats); else skb = virtnet_receive_xsk_merge(dev, vi, rq, xdp, xdp_xmit, stats); @@ -2389,13 +2401,20 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, */ flags = ((struct virtio_net_common_hdr *)buf)->hdr.flags; - if (vi->mergeable_rx_bufs) + switch (vi->mode) { + case VIRTNET_MODE_MERGE: skb = receive_mergeable(dev, vi, rq, buf, ctx, len, xdp_xmit, stats); - else if (vi->big_packets) + break; + + case VIRTNET_MODE_BIG: skb = receive_big(dev, vi, rq, buf, len, stats); - else + break; + + case VIRTNET_MODE_SMALL: skb = receive_small(dev, vi, rq, buf, ctx, len, xdp_xmit, stats); + break; + } if (unlikely(!skb)) return; @@ -2580,12 +2599,19 @@ static bool try_fill_recv(struct virtnet_info *vi, struct receive_queue *rq, } do { - if (vi->mergeable_rx_bufs) + switch (vi->mode) { + case VIRTNET_MODE_MERGE: err = add_recvbuf_mergeable(vi, rq, gfp); - else if (vi->big_packets) + break; + + case VIRTNET_MODE_BIG: err = add_recvbuf_big(vi, rq, gfp); - else + break; + + case VIRTNET_MODE_SMALL: err = add_recvbuf_small(vi, rq, gfp); + break; + } if (err) break; @@ -2703,7 +2729,7 @@ static int virtnet_receive_packets(struct virtnet_info *vi, int packets = 0; void *buf; - if (!vi->big_packets || vi->mergeable_rx_bufs) { + if (vi->mode != VIRTNET_MODE_BIG) { void *ctx; while (packets < budget && (buf = virtnet_rq_get_buf(rq, &len, &ctx))) { @@ -5510,7 +5536,7 @@ static int virtnet_xsk_pool_enable(struct net_device *dev, /* In big_packets mode, xdp cannot work, so there is no need to * initialize xsk of rq. */ - if (vi->big_packets && !vi->mergeable_rx_bufs) + if (vi->mode == VIRTNET_MODE_BIG) return -ENOENT; if (qid >= vi->curr_queue_pairs) @@ -6007,7 +6033,7 @@ static int virtnet_find_vqs(struct virtnet_info *vi) vqs_info = kcalloc(total_vqs, sizeof(*vqs_info), GFP_KERNEL); if (!vqs_info) goto err_vqs_info; - if (!vi->big_packets || vi->mergeable_rx_bufs) { + if (vi->mode != VIRTNET_MODE_BIG) { ctx = kcalloc(total_vqs, sizeof(*ctx), GFP_KERNEL); if (!ctx) goto err_ctx; @@ -6480,6 +6506,13 @@ static int virtnet_probe(struct virtio_device *vdev) virtnet_set_big_packets(vi, mtu); + if (vi->mergeable_rx_bufs) + vi->mode = VIRTNET_MODE_MERGE; + else if (vi->big_packets) + vi->mode = VIRTNET_MODE_BIG; + else + vi->mode = VIRTNET_MODE_SMALL; + if (vi->any_header_sg) dev->needed_headroom = vi->hdr_len; -- 2.32.0.3.g01195cf9f