diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 656a02e28e26..a7e9ad9b213a 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -305,7 +305,7 @@ static int receive_mergeable(struct receive_queue *rq, struct sk_buff *head_skb) struct sk_buff *curr_skb = head_skb; char *buf; struct page *page; - int num_buf, len; + int num_buf, len, offset; num_buf = hdr->mhdr.num_buffers; while (--num_buf) { @@ -342,9 +342,16 @@ static int receive_mergeable(struct receive_queue *rq, struct sk_buff *head_skb) head_skb->truesize += MAX_PACKET_LEN; } page = virt_to_head_page(buf); - skb_add_rx_frag(curr_skb, num_skb_frags, page, - buf - (char *)page_address(page), len, - MAX_PACKET_LEN); + offset = buf - (char *)page_address(page); + if (skb_can_coalesce(curr_skb, num_skb_frags, page, offset)) { + put_page(page); + skb_coalesce_rx_frag(curr_skb, num_skb_frags - 1, + len, MAX_PACKET_LEN); + } else { + skb_add_rx_frag(curr_skb, num_skb_frags, page, + offset, len, + MAX_PACKET_LEN); + } --rq->num; } return 0;