diff options
| -rw-r--r-- | drivers/net/virtio_net.c | 44 |
1 files changed, 3 insertions, 41 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index c1f66d8bfb7b..e53365a86ca3 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
| @@ -344,11 +344,7 @@ static void virtnet_xdp_xmit(struct virtnet_info *vi, | |||
| 344 | /* Free up any pending old buffers before queueing new ones. */ | 344 | /* Free up any pending old buffers before queueing new ones. */ |
| 345 | while ((xdp_sent = virtqueue_get_buf(sq->vq, &len)) != NULL) { | 345 | while ((xdp_sent = virtqueue_get_buf(sq->vq, &len)) != NULL) { |
| 346 | struct page *sent_page = virt_to_head_page(xdp_sent); | 346 | struct page *sent_page = virt_to_head_page(xdp_sent); |
| 347 | 347 | put_page(sent_page); | |
| 348 | if (vi->mergeable_rx_bufs) | ||
| 349 | put_page(sent_page); | ||
| 350 | else | ||
| 351 | give_pages(rq, sent_page); | ||
| 352 | } | 348 | } |
| 353 | 349 | ||
| 354 | /* Zero header and leave csum up to XDP layers */ | 350 | /* Zero header and leave csum up to XDP layers */ |
| @@ -360,15 +356,8 @@ static void virtnet_xdp_xmit(struct virtnet_info *vi, | |||
| 360 | err = virtqueue_add_outbuf(sq->vq, sq->sg, num_sg, | 356 | err = virtqueue_add_outbuf(sq->vq, sq->sg, num_sg, |
| 361 | xdp->data, GFP_ATOMIC); | 357 | xdp->data, GFP_ATOMIC); |
| 362 | if (unlikely(err)) { | 358 | if (unlikely(err)) { |
| 363 | if (vi->mergeable_rx_bufs) | 359 | put_page(page); |
| 364 | put_page(page); | ||
| 365 | else | ||
| 366 | give_pages(rq, page); | ||
| 367 | return; // On error abort to avoid unnecessary kick | 360 | return; // On error abort to avoid unnecessary kick |
| 368 | } else if (!vi->mergeable_rx_bufs) { | ||
| 369 | /* If not mergeable bufs must be big packets so cleanup pages */ | ||
| 370 | give_pages(rq, (struct page *)page->private); | ||
| 371 | page->private = 0; | ||
| 372 | } | 361 | } |
| 373 | 362 | ||
| 374 | virtqueue_kick(sq->vq); | 363 | virtqueue_kick(sq->vq); |
| @@ -430,44 +419,17 @@ static struct sk_buff *receive_big(struct net_device *dev, | |||
| 430 | void *buf, | 419 | void *buf, |
| 431 | unsigned int len) | 420 | unsigned int len) |
| 432 | { | 421 | { |
| 433 | struct bpf_prog *xdp_prog; | ||
| 434 | struct page *page = buf; | 422 | struct page *page = buf; |
| 435 | struct sk_buff *skb; | 423 | struct sk_buff *skb = page_to_skb(vi, rq, page, 0, len, PAGE_SIZE); |
| 436 | |||
| 437 | rcu_read_lock(); | ||
| 438 | xdp_prog = rcu_dereference(rq->xdp_prog); | ||
| 439 | if (xdp_prog) { | ||
| 440 | struct virtio_net_hdr_mrg_rxbuf *hdr = buf; | ||
| 441 | u32 act; | ||
| 442 | |||
| 443 | if (unlikely(hdr->hdr.gso_type)) | ||
| 444 | goto err_xdp; | ||
| 445 | act = do_xdp_prog(vi, rq, xdp_prog, page, 0, len); | ||
| 446 | switch (act) { | ||
| 447 | case XDP_PASS: | ||
| 448 | break; | ||
| 449 | case XDP_TX: | ||
| 450 | rcu_read_unlock(); | ||
| 451 | goto xdp_xmit; | ||
| 452 | case XDP_DROP: | ||
| 453 | default: | ||
| 454 | goto err_xdp; | ||
| 455 | } | ||
| 456 | } | ||
| 457 | rcu_read_unlock(); | ||
| 458 | 424 | ||
| 459 | skb = page_to_skb(vi, rq, page, 0, len, PAGE_SIZE); | ||
| 460 | if (unlikely(!skb)) | 425 | if (unlikely(!skb)) |
| 461 | goto err; | 426 | goto err; |
| 462 | 427 | ||
| 463 | return skb; | 428 | return skb; |
| 464 | 429 | ||
| 465 | err_xdp: | ||
| 466 | rcu_read_unlock(); | ||
| 467 | err: | 430 | err: |
| 468 | dev->stats.rx_dropped++; | 431 | dev->stats.rx_dropped++; |
| 469 | give_pages(rq, page); | 432 | give_pages(rq, page); |
| 470 | xdp_xmit: | ||
| 471 | return NULL; | 433 | return NULL; |
| 472 | } | 434 | } |
| 473 | 435 | ||
