diff options
Diffstat (limited to 'drivers/net/virtio_net.c')
| -rw-r--r-- | drivers/net/virtio_net.c | 56 |
1 files changed, 28 insertions, 28 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 25dc77ccbf58..b0a85d038796 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/virtio_net.h> | 25 | #include <linux/virtio_net.h> |
| 26 | #include <linux/scatterlist.h> | 26 | #include <linux/scatterlist.h> |
| 27 | #include <linux/if_vlan.h> | 27 | #include <linux/if_vlan.h> |
| 28 | #include <linux/slab.h> | ||
| 28 | 29 | ||
| 29 | static int napi_weight = 128; | 30 | static int napi_weight = 128; |
| 30 | module_param(napi_weight, int, 0444); | 31 | module_param(napi_weight, int, 0444); |
| @@ -39,8 +40,7 @@ module_param(gso, bool, 0444); | |||
| 39 | 40 | ||
| 40 | #define VIRTNET_SEND_COMMAND_SG_MAX 2 | 41 | #define VIRTNET_SEND_COMMAND_SG_MAX 2 |
| 41 | 42 | ||
| 42 | struct virtnet_info | 43 | struct virtnet_info { |
| 43 | { | ||
| 44 | struct virtio_device *vdev; | 44 | struct virtio_device *vdev; |
| 45 | struct virtqueue *rvq, *svq, *cvq; | 45 | struct virtqueue *rvq, *svq, *cvq; |
| 46 | struct net_device *dev; | 46 | struct net_device *dev; |
| @@ -61,6 +61,10 @@ struct virtnet_info | |||
| 61 | 61 | ||
| 62 | /* Chain pages by the private ptr. */ | 62 | /* Chain pages by the private ptr. */ |
| 63 | struct page *pages; | 63 | struct page *pages; |
| 64 | |||
| 65 | /* fragments + linear part + virtio header */ | ||
| 66 | struct scatterlist rx_sg[MAX_SKB_FRAGS + 2]; | ||
| 67 | struct scatterlist tx_sg[MAX_SKB_FRAGS + 2]; | ||
| 64 | }; | 68 | }; |
| 65 | 69 | ||
| 66 | struct skb_vnet_hdr { | 70 | struct skb_vnet_hdr { |
| @@ -323,7 +327,6 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp) | |||
| 323 | { | 327 | { |
| 324 | struct sk_buff *skb; | 328 | struct sk_buff *skb; |
| 325 | struct skb_vnet_hdr *hdr; | 329 | struct skb_vnet_hdr *hdr; |
| 326 | struct scatterlist sg[2]; | ||
| 327 | int err; | 330 | int err; |
| 328 | 331 | ||
| 329 | skb = netdev_alloc_skb_ip_align(vi->dev, MAX_PACKET_LEN); | 332 | skb = netdev_alloc_skb_ip_align(vi->dev, MAX_PACKET_LEN); |
| @@ -333,11 +336,11 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp) | |||
| 333 | skb_put(skb, MAX_PACKET_LEN); | 336 | skb_put(skb, MAX_PACKET_LEN); |
| 334 | 337 | ||
| 335 | hdr = skb_vnet_hdr(skb); | 338 | hdr = skb_vnet_hdr(skb); |
| 336 | sg_set_buf(sg, &hdr->hdr, sizeof hdr->hdr); | 339 | sg_set_buf(vi->rx_sg, &hdr->hdr, sizeof hdr->hdr); |
| 337 | 340 | ||
| 338 | skb_to_sgvec(skb, sg + 1, 0, skb->len); | 341 | skb_to_sgvec(skb, vi->rx_sg + 1, 0, skb->len); |
| 339 | 342 | ||
| 340 | err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, 2, skb); | 343 | err = vi->rvq->vq_ops->add_buf(vi->rvq, vi->rx_sg, 0, 2, skb); |
| 341 | if (err < 0) | 344 | if (err < 0) |
| 342 | dev_kfree_skb(skb); | 345 | dev_kfree_skb(skb); |
| 343 | 346 | ||
| @@ -346,12 +349,11 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp) | |||
| 346 | 349 | ||
| 347 | static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp) | 350 | static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp) |
| 348 | { | 351 | { |
| 349 | struct scatterlist sg[MAX_SKB_FRAGS + 2]; | ||
| 350 | struct page *first, *list = NULL; | 352 | struct page *first, *list = NULL; |
| 351 | char *p; | 353 | char *p; |
| 352 | int i, err, offset; | 354 | int i, err, offset; |
| 353 | 355 | ||
| 354 | /* page in sg[MAX_SKB_FRAGS + 1] is list tail */ | 356 | /* page in vi->rx_sg[MAX_SKB_FRAGS + 1] is list tail */ |
| 355 | for (i = MAX_SKB_FRAGS + 1; i > 1; --i) { | 357 | for (i = MAX_SKB_FRAGS + 1; i > 1; --i) { |
| 356 | first = get_a_page(vi, gfp); | 358 | first = get_a_page(vi, gfp); |
| 357 | if (!first) { | 359 | if (!first) { |
| @@ -359,7 +361,7 @@ static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp) | |||
| 359 | give_pages(vi, list); | 361 | give_pages(vi, list); |
| 360 | return -ENOMEM; | 362 | return -ENOMEM; |
| 361 | } | 363 | } |
| 362 | sg_set_buf(&sg[i], page_address(first), PAGE_SIZE); | 364 | sg_set_buf(&vi->rx_sg[i], page_address(first), PAGE_SIZE); |
| 363 | 365 | ||
| 364 | /* chain new page in list head to match sg */ | 366 | /* chain new page in list head to match sg */ |
| 365 | first->private = (unsigned long)list; | 367 | first->private = (unsigned long)list; |
| @@ -373,17 +375,17 @@ static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp) | |||
| 373 | } | 375 | } |
| 374 | p = page_address(first); | 376 | p = page_address(first); |
| 375 | 377 | ||
| 376 | /* sg[0], sg[1] share the same page */ | 378 | /* vi->rx_sg[0], vi->rx_sg[1] share the same page */ |
| 377 | /* a separated sg[0] for virtio_net_hdr only during to QEMU bug*/ | 379 | /* a separated vi->rx_sg[0] for virtio_net_hdr only due to QEMU bug */ |
| 378 | sg_set_buf(&sg[0], p, sizeof(struct virtio_net_hdr)); | 380 | sg_set_buf(&vi->rx_sg[0], p, sizeof(struct virtio_net_hdr)); |
| 379 | 381 | ||
| 380 | /* sg[1] for data packet, from offset */ | 382 | /* vi->rx_sg[1] for data packet, from offset */ |
| 381 | offset = sizeof(struct padded_vnet_hdr); | 383 | offset = sizeof(struct padded_vnet_hdr); |
| 382 | sg_set_buf(&sg[1], p + offset, PAGE_SIZE - offset); | 384 | sg_set_buf(&vi->rx_sg[1], p + offset, PAGE_SIZE - offset); |
| 383 | 385 | ||
| 384 | /* chain first in list head */ | 386 | /* chain first in list head */ |
| 385 | first->private = (unsigned long)list; | 387 | first->private = (unsigned long)list; |
| 386 | err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, MAX_SKB_FRAGS + 2, | 388 | err = vi->rvq->vq_ops->add_buf(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2, |
| 387 | first); | 389 | first); |
| 388 | if (err < 0) | 390 | if (err < 0) |
| 389 | give_pages(vi, first); | 391 | give_pages(vi, first); |
| @@ -394,16 +396,15 @@ static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp) | |||
| 394 | static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp) | 396 | static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp) |
| 395 | { | 397 | { |
| 396 | struct page *page; | 398 | struct page *page; |
| 397 | struct scatterlist sg; | ||
| 398 | int err; | 399 | int err; |
| 399 | 400 | ||
| 400 | page = get_a_page(vi, gfp); | 401 | page = get_a_page(vi, gfp); |
| 401 | if (!page) | 402 | if (!page) |
| 402 | return -ENOMEM; | 403 | return -ENOMEM; |
| 403 | 404 | ||
| 404 | sg_init_one(&sg, page_address(page), PAGE_SIZE); | 405 | sg_init_one(vi->rx_sg, page_address(page), PAGE_SIZE); |
| 405 | 406 | ||
| 406 | err = vi->rvq->vq_ops->add_buf(vi->rvq, &sg, 0, 1, page); | 407 | err = vi->rvq->vq_ops->add_buf(vi->rvq, vi->rx_sg, 0, 1, page); |
| 407 | if (err < 0) | 408 | if (err < 0) |
| 408 | give_pages(vi, page); | 409 | give_pages(vi, page); |
| 409 | 410 | ||
| @@ -512,12 +513,9 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi) | |||
| 512 | 513 | ||
| 513 | static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) | 514 | static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) |
| 514 | { | 515 | { |
| 515 | struct scatterlist sg[2+MAX_SKB_FRAGS]; | ||
| 516 | struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb); | 516 | struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb); |
| 517 | const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; | 517 | const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; |
| 518 | 518 | ||
| 519 | sg_init_table(sg, 2+MAX_SKB_FRAGS); | ||
| 520 | |||
| 521 | pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest); | 519 | pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest); |
| 522 | 520 | ||
| 523 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 521 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
| @@ -551,12 +549,13 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) | |||
| 551 | 549 | ||
| 552 | /* Encode metadata header at front. */ | 550 | /* Encode metadata header at front. */ |
| 553 | if (vi->mergeable_rx_bufs) | 551 | if (vi->mergeable_rx_bufs) |
| 554 | sg_set_buf(sg, &hdr->mhdr, sizeof hdr->mhdr); | 552 | sg_set_buf(vi->tx_sg, &hdr->mhdr, sizeof hdr->mhdr); |
| 555 | else | 553 | else |
| 556 | sg_set_buf(sg, &hdr->hdr, sizeof hdr->hdr); | 554 | sg_set_buf(vi->tx_sg, &hdr->hdr, sizeof hdr->hdr); |
| 557 | 555 | ||
| 558 | hdr->num_sg = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1; | 556 | hdr->num_sg = skb_to_sgvec(skb, vi->tx_sg + 1, 0, skb->len) + 1; |
| 559 | return vi->svq->vq_ops->add_buf(vi->svq, sg, hdr->num_sg, 0, skb); | 557 | return vi->svq->vq_ops->add_buf(vi->svq, vi->tx_sg, hdr->num_sg, |
| 558 | 0, skb); | ||
| 560 | } | 559 | } |
| 561 | 560 | ||
| 562 | static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) | 561 | static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) |
| @@ -719,7 +718,6 @@ static void virtnet_set_rx_mode(struct net_device *dev) | |||
| 719 | struct scatterlist sg[2]; | 718 | struct scatterlist sg[2]; |
| 720 | u8 promisc, allmulti; | 719 | u8 promisc, allmulti; |
| 721 | struct virtio_net_ctrl_mac *mac_data; | 720 | struct virtio_net_ctrl_mac *mac_data; |
| 722 | struct dev_addr_list *addr; | ||
| 723 | struct netdev_hw_addr *ha; | 721 | struct netdev_hw_addr *ha; |
| 724 | int uc_count; | 722 | int uc_count; |
| 725 | int mc_count; | 723 | int mc_count; |
| @@ -776,8 +774,8 @@ static void virtnet_set_rx_mode(struct net_device *dev) | |||
| 776 | 774 | ||
| 777 | mac_data->entries = mc_count; | 775 | mac_data->entries = mc_count; |
| 778 | i = 0; | 776 | i = 0; |
| 779 | netdev_for_each_mc_addr(addr, dev) | 777 | netdev_for_each_mc_addr(ha, dev) |
| 780 | memcpy(&mac_data->macs[i++][0], addr->da_addr, ETH_ALEN); | 778 | memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN); |
| 781 | 779 | ||
| 782 | sg_set_buf(&sg[1], mac_data, | 780 | sg_set_buf(&sg[1], mac_data, |
| 783 | sizeof(mac_data->entries) + (mc_count * ETH_ALEN)); | 781 | sizeof(mac_data->entries) + (mc_count * ETH_ALEN)); |
| @@ -939,6 +937,8 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
| 939 | vdev->priv = vi; | 937 | vdev->priv = vi; |
| 940 | vi->pages = NULL; | 938 | vi->pages = NULL; |
| 941 | INIT_DELAYED_WORK(&vi->refill, refill_work); | 939 | INIT_DELAYED_WORK(&vi->refill, refill_work); |
| 940 | sg_init_table(vi->rx_sg, ARRAY_SIZE(vi->rx_sg)); | ||
| 941 | sg_init_table(vi->tx_sg, ARRAY_SIZE(vi->tx_sg)); | ||
| 942 | 942 | ||
| 943 | /* If we can receive ANY GSO packets, we must allocate large ones. */ | 943 | /* If we can receive ANY GSO packets, we must allocate large ones. */ |
| 944 | if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) || | 944 | if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) || |
