diff options
| -rw-r--r-- | drivers/net/virtio_net.c | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index fe4562d395e3..58ad40e17a74 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
| @@ -483,7 +483,7 @@ xdp_xmit: | |||
| 483 | * anymore. | 483 | * anymore. |
| 484 | */ | 484 | */ |
| 485 | static struct page *xdp_linearize_page(struct receive_queue *rq, | 485 | static struct page *xdp_linearize_page(struct receive_queue *rq, |
| 486 | u16 num_buf, | 486 | u16 *num_buf, |
| 487 | struct page *p, | 487 | struct page *p, |
| 488 | int offset, | 488 | int offset, |
| 489 | unsigned int *len) | 489 | unsigned int *len) |
| @@ -497,7 +497,7 @@ static struct page *xdp_linearize_page(struct receive_queue *rq, | |||
| 497 | memcpy(page_address(page) + page_off, page_address(p) + offset, *len); | 497 | memcpy(page_address(page) + page_off, page_address(p) + offset, *len); |
| 498 | page_off += *len; | 498 | page_off += *len; |
| 499 | 499 | ||
| 500 | while (--num_buf) { | 500 | while (--*num_buf) { |
| 501 | unsigned int buflen; | 501 | unsigned int buflen; |
| 502 | unsigned long ctx; | 502 | unsigned long ctx; |
| 503 | void *buf; | 503 | void *buf; |
| @@ -507,19 +507,22 @@ static struct page *xdp_linearize_page(struct receive_queue *rq, | |||
| 507 | if (unlikely(!ctx)) | 507 | if (unlikely(!ctx)) |
| 508 | goto err_buf; | 508 | goto err_buf; |
| 509 | 509 | ||
| 510 | buf = mergeable_ctx_to_buf_address(ctx); | ||
| 511 | p = virt_to_head_page(buf); | ||
| 512 | off = buf - page_address(p); | ||
| 513 | |||
| 510 | /* guard against a misconfigured or uncooperative backend that | 514 | /* guard against a misconfigured or uncooperative backend that |
| 511 | * is sending packet larger than the MTU. | 515 | * is sending packet larger than the MTU. |
| 512 | */ | 516 | */ |
| 513 | if ((page_off + buflen) > PAGE_SIZE) | 517 | if ((page_off + buflen) > PAGE_SIZE) { |
| 518 | put_page(p); | ||
| 514 | goto err_buf; | 519 | goto err_buf; |
| 515 | 520 | } | |
| 516 | buf = mergeable_ctx_to_buf_address(ctx); | ||
| 517 | p = virt_to_head_page(buf); | ||
| 518 | off = buf - page_address(p); | ||
| 519 | 521 | ||
| 520 | memcpy(page_address(page) + page_off, | 522 | memcpy(page_address(page) + page_off, |
| 521 | page_address(p) + off, buflen); | 523 | page_address(p) + off, buflen); |
| 522 | page_off += buflen; | 524 | page_off += buflen; |
| 525 | put_page(p); | ||
| 523 | } | 526 | } |
| 524 | 527 | ||
| 525 | *len = page_off; | 528 | *len = page_off; |
| @@ -555,7 +558,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, | |||
| 555 | /* This happens when rx buffer size is underestimated */ | 558 | /* This happens when rx buffer size is underestimated */ |
| 556 | if (unlikely(num_buf > 1)) { | 559 | if (unlikely(num_buf > 1)) { |
| 557 | /* linearize data for XDP */ | 560 | /* linearize data for XDP */ |
| 558 | xdp_page = xdp_linearize_page(rq, num_buf, | 561 | xdp_page = xdp_linearize_page(rq, &num_buf, |
| 559 | page, offset, &len); | 562 | page, offset, &len); |
| 560 | if (!xdp_page) | 563 | if (!xdp_page) |
| 561 | goto err_xdp; | 564 | goto err_xdp; |
