Message ID | 20210610082209.91487-8-xuanzhuo@linux.alibaba.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | virtio-net: support xdp socket zero copy | expand |
Context | Check | Description |
---|---|---|
netdev/cover_letter | success | Link |
netdev/fixes_present | success | Link |
netdev/patch_count | success | Link |
netdev/tree_selection | success | Clearly marked for net-next |
netdev/subject_prefix | success | Link |
netdev/cc_maintainers | success | CCed 15 of 15 maintainers |
netdev/source_inline | success | Was 0 now: 0 |
netdev/verify_signedoff | success | Link |
netdev/module_param | success | Was 0 now: 0 |
netdev/build_32bit | fail | Errors and warnings before: 0 this patch: 3 |
netdev/kdoc | success | Errors and warnings before: 0 this patch: 0 |
netdev/verify_fixes | success | Link |
netdev/checkpatch | success | total: 0 errors, 0 warnings, 0 checks, 58 lines checked |
netdev/build_allmodconfig_warn | fail | Errors and warnings before: 0 this patch: 3 |
netdev/header_inline | success | Link |
在 2021/6/10 下午4:22, Xuan Zhuo 写道: > This logic is used by small and merge when adding buf, and the > subsequent patch will also use this logic, so it is separated as an > independent function. > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> Acked-by: Jason Wang <jasiowang@redhat.com> > --- > drivers/net/virtio_net.c | 29 ++++++++++++++++++++--------- > 1 file changed, 20 insertions(+), 9 deletions(-) > > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c > index d791543a8dd8..3fd87bf2b2ad 100644 > --- a/drivers/net/virtio_net.c > +++ b/drivers/net/virtio_net.c > @@ -264,6 +264,22 @@ static struct xdp_frame *ptr_to_xdp(void *ptr) > return (struct xdp_frame *)((unsigned long)ptr & ~VIRTIO_XDP_FLAG); > } > > +static char *virtnet_alloc_frag(struct receive_queue *rq, unsigned int len, > + int gfp) > +{ > + struct page_frag *alloc_frag = &rq->alloc_frag; > + char *buf; > + > + if (unlikely(!skb_page_frag_refill(len, alloc_frag, gfp))) > + return NULL; > + > + buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset; > + get_page(alloc_frag->page); > + alloc_frag->offset += len; > + > + return buf; > +} > + > static void __free_old_xmit(struct send_queue *sq, bool in_napi, > struct virtnet_sq_stats *stats) > { > @@ -1190,7 +1206,6 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, > static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq, > gfp_t gfp) > { > - struct page_frag *alloc_frag = &rq->alloc_frag; > char *buf; > unsigned int xdp_headroom = virtnet_get_headroom(vi); > void *ctx = (void *)(unsigned long)xdp_headroom; > @@ -1199,12 +1214,10 @@ static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq, > > len = SKB_DATA_ALIGN(len) + > SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); > - if (unlikely(!skb_page_frag_refill(len, alloc_frag, gfp))) > + buf = virtnet_alloc_frag(rq, len, gfp); > + if (unlikely(!buf)) > return -ENOMEM; > > - buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset; > - get_page(alloc_frag->page); > - alloc_frag->offset += len; > sg_init_one(rq->sg, buf + VIRTNET_RX_PAD + xdp_headroom, > vi->hdr_len + GOOD_PACKET_LEN); > err = virtqueue_add_inbuf_ctx(rq->vq, rq->sg, 1, buf, ctx, gfp); > @@ -1295,13 +1308,11 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, > * disabled GSO for XDP, it won't be a big issue. > */ > len = get_mergeable_buf_len(rq, &rq->mrg_avg_pkt_len, room); > - if (unlikely(!skb_page_frag_refill(len + room, alloc_frag, gfp))) > + buf = virtnet_alloc_frag(rq, len + room, gfp); > + if (unlikely(!buf)) > return -ENOMEM; > > - buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset; > buf += headroom; /* advance address leaving hole at front of pkt */ > - get_page(alloc_frag->page); > - alloc_frag->offset += len + room; > hole = alloc_frag->size - alloc_frag->offset; > if (hole < len + room) { > /* To avoid internal fragmentation, if there is very likely not
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index d791543a8dd8..3fd87bf2b2ad 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -264,6 +264,22 @@ static struct xdp_frame *ptr_to_xdp(void *ptr) return (struct xdp_frame *)((unsigned long)ptr & ~VIRTIO_XDP_FLAG); } +static char *virtnet_alloc_frag(struct receive_queue *rq, unsigned int len, + int gfp) +{ + struct page_frag *alloc_frag = &rq->alloc_frag; + char *buf; + + if (unlikely(!skb_page_frag_refill(len, alloc_frag, gfp))) + return NULL; + + buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset; + get_page(alloc_frag->page); + alloc_frag->offset += len; + + return buf; +} + static void __free_old_xmit(struct send_queue *sq, bool in_napi, struct virtnet_sq_stats *stats) { @@ -1190,7 +1206,6 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq, gfp_t gfp) { - struct page_frag *alloc_frag = &rq->alloc_frag; char *buf; unsigned int xdp_headroom = virtnet_get_headroom(vi); void *ctx = (void *)(unsigned long)xdp_headroom; @@ -1199,12 +1214,10 @@ static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq, len = SKB_DATA_ALIGN(len) + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); - if (unlikely(!skb_page_frag_refill(len, alloc_frag, gfp))) + buf = virtnet_alloc_frag(rq, len, gfp); + if (unlikely(!buf)) return -ENOMEM; - buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset; - get_page(alloc_frag->page); - alloc_frag->offset += len; sg_init_one(rq->sg, buf + VIRTNET_RX_PAD + xdp_headroom, vi->hdr_len + GOOD_PACKET_LEN); err = virtqueue_add_inbuf_ctx(rq->vq, rq->sg, 1, buf, ctx, gfp); @@ -1295,13 +1308,11 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, * disabled GSO for XDP, it won't be a big issue. */ len = get_mergeable_buf_len(rq, &rq->mrg_avg_pkt_len, room); - if (unlikely(!skb_page_frag_refill(len + room, alloc_frag, gfp))) + buf = virtnet_alloc_frag(rq, len + room, gfp); + if (unlikely(!buf)) return -ENOMEM; - buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset; buf += headroom; /* advance address leaving hole at front of pkt */ - get_page(alloc_frag->page); - alloc_frag->offset += len + room; hole = alloc_frag->size - alloc_frag->offset; if (hole < len + room) { /* To avoid internal fragmentation, if there is very likely not
This logic is used by small and merge when adding buf, and the subsequent patch will also use this logic, so it is separated as an independent function. Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> --- drivers/net/virtio_net.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-)