diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 00:04:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 00:04:44 -0400 |
commit | f8965467f366fd18f01feafb5db10512d7b4422c (patch) | |
tree | 3706a9cd779859271ca61b85c63a1bc3f82d626e /drivers/net/virtio_net.c | |
parent | a26272e5200765691e67d6780e52b32498fdb659 (diff) | |
parent | 2ec8c6bb5d8f3a62a79f463525054bae1e3d4487 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1674 commits)
qlcnic: adding co maintainer
ixgbe: add support for active DA cables
ixgbe: dcb, do not tag tc_prio_control frames
ixgbe: fix ixgbe_tx_is_paused logic
ixgbe: always enable vlan strip/insert when DCB is enabled
ixgbe: remove some redundant code in setting FCoE FIP filter
ixgbe: fix wrong offset to fc_frame_header in ixgbe_fcoe_ddp
ixgbe: fix header len when unsplit packet overflows to data buffer
ipv6: Never schedule DAD timer on dead address
ipv6: Use POSTDAD state
ipv6: Use state_lock to protect ifa state
ipv6: Replace inet6_ifaddr->dead with state
cxgb4: notify upper drivers if the device is already up when they load
cxgb4: keep interrupts available when the ports are brought down
cxgb4: fix initial addition of MAC address
cnic: Return SPQ credit to bnx2x after ring setup and shutdown.
cnic: Convert cnic_local_flags to atomic ops.
can: Fix SJA1000 command register writes on SMP systems
bridge: fix build for CONFIG_SYSFS disabled
ARCNET: Limit com20020 PCI ID matches for SOHARD cards
...
Fix up various conflicts with pcmcia tree drivers/net/
{pcmcia/3c589_cs.c, wireless/orinoco/orinoco_cs.c and
wireless/orinoco/spectrum_cs.c} and feature removal
(Documentation/feature-removal-schedule.txt).
Also fix a non-content conflict due to pm_qos_requirement getting
renamed in the PM tree (now pm_qos_request) in net/mac80211/scan.c
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r-- | drivers/net/virtio_net.c | 57 |
1 files changed, 27 insertions, 30 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index b0577dd1a42d..b0a85d038796 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -40,8 +40,7 @@ module_param(gso, bool, 0444); | |||
40 | 40 | ||
41 | #define VIRTNET_SEND_COMMAND_SG_MAX 2 | 41 | #define VIRTNET_SEND_COMMAND_SG_MAX 2 |
42 | 42 | ||
43 | struct virtnet_info | 43 | struct virtnet_info { |
44 | { | ||
45 | struct virtio_device *vdev; | 44 | struct virtio_device *vdev; |
46 | struct virtqueue *rvq, *svq, *cvq; | 45 | struct virtqueue *rvq, *svq, *cvq; |
47 | struct net_device *dev; | 46 | struct net_device *dev; |
@@ -62,6 +61,10 @@ struct virtnet_info | |||
62 | 61 | ||
63 | /* Chain pages by the private ptr. */ | 62 | /* Chain pages by the private ptr. */ |
64 | 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]; | ||
65 | }; | 68 | }; |
66 | 69 | ||
67 | struct skb_vnet_hdr { | 70 | struct skb_vnet_hdr { |
@@ -324,10 +327,8 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp) | |||
324 | { | 327 | { |
325 | struct sk_buff *skb; | 328 | struct sk_buff *skb; |
326 | struct skb_vnet_hdr *hdr; | 329 | struct skb_vnet_hdr *hdr; |
327 | struct scatterlist sg[2]; | ||
328 | int err; | 330 | int err; |
329 | 331 | ||
330 | sg_init_table(sg, 2); | ||
331 | skb = netdev_alloc_skb_ip_align(vi->dev, MAX_PACKET_LEN); | 332 | skb = netdev_alloc_skb_ip_align(vi->dev, MAX_PACKET_LEN); |
332 | if (unlikely(!skb)) | 333 | if (unlikely(!skb)) |
333 | return -ENOMEM; | 334 | return -ENOMEM; |
@@ -335,11 +336,11 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp) | |||
335 | skb_put(skb, MAX_PACKET_LEN); | 336 | skb_put(skb, MAX_PACKET_LEN); |
336 | 337 | ||
337 | hdr = skb_vnet_hdr(skb); | 338 | hdr = skb_vnet_hdr(skb); |
338 | sg_set_buf(sg, &hdr->hdr, sizeof hdr->hdr); | 339 | sg_set_buf(vi->rx_sg, &hdr->hdr, sizeof hdr->hdr); |
339 | 340 | ||
340 | skb_to_sgvec(skb, sg + 1, 0, skb->len); | 341 | skb_to_sgvec(skb, vi->rx_sg + 1, 0, skb->len); |
341 | 342 | ||
342 | 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); |
343 | if (err < 0) | 344 | if (err < 0) |
344 | dev_kfree_skb(skb); | 345 | dev_kfree_skb(skb); |
345 | 346 | ||
@@ -348,13 +349,11 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp) | |||
348 | 349 | ||
349 | 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) |
350 | { | 351 | { |
351 | struct scatterlist sg[MAX_SKB_FRAGS + 2]; | ||
352 | struct page *first, *list = NULL; | 352 | struct page *first, *list = NULL; |
353 | char *p; | 353 | char *p; |
354 | int i, err, offset; | 354 | int i, err, offset; |
355 | 355 | ||
356 | sg_init_table(sg, MAX_SKB_FRAGS + 2); | 356 | /* page in vi->rx_sg[MAX_SKB_FRAGS + 1] is list tail */ |
357 | /* page in sg[MAX_SKB_FRAGS + 1] is list tail */ | ||
358 | for (i = MAX_SKB_FRAGS + 1; i > 1; --i) { | 357 | for (i = MAX_SKB_FRAGS + 1; i > 1; --i) { |
359 | first = get_a_page(vi, gfp); | 358 | first = get_a_page(vi, gfp); |
360 | if (!first) { | 359 | if (!first) { |
@@ -362,7 +361,7 @@ static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp) | |||
362 | give_pages(vi, list); | 361 | give_pages(vi, list); |
363 | return -ENOMEM; | 362 | return -ENOMEM; |
364 | } | 363 | } |
365 | sg_set_buf(&sg[i], page_address(first), PAGE_SIZE); | 364 | sg_set_buf(&vi->rx_sg[i], page_address(first), PAGE_SIZE); |
366 | 365 | ||
367 | /* chain new page in list head to match sg */ | 366 | /* chain new page in list head to match sg */ |
368 | first->private = (unsigned long)list; | 367 | first->private = (unsigned long)list; |
@@ -376,17 +375,17 @@ static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp) | |||
376 | } | 375 | } |
377 | p = page_address(first); | 376 | p = page_address(first); |
378 | 377 | ||
379 | /* sg[0], sg[1] share the same page */ | 378 | /* vi->rx_sg[0], vi->rx_sg[1] share the same page */ |
380 | /* 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 */ |
381 | 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)); |
382 | 381 | ||
383 | /* sg[1] for data packet, from offset */ | 382 | /* vi->rx_sg[1] for data packet, from offset */ |
384 | offset = sizeof(struct padded_vnet_hdr); | 383 | offset = sizeof(struct padded_vnet_hdr); |
385 | sg_set_buf(&sg[1], p + offset, PAGE_SIZE - offset); | 384 | sg_set_buf(&vi->rx_sg[1], p + offset, PAGE_SIZE - offset); |
386 | 385 | ||
387 | /* chain first in list head */ | 386 | /* chain first in list head */ |
388 | first->private = (unsigned long)list; | 387 | first->private = (unsigned long)list; |
389 | 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, |
390 | first); | 389 | first); |
391 | if (err < 0) | 390 | if (err < 0) |
392 | give_pages(vi, first); | 391 | give_pages(vi, first); |
@@ -397,16 +396,15 @@ static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp) | |||
397 | 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) |
398 | { | 397 | { |
399 | struct page *page; | 398 | struct page *page; |
400 | struct scatterlist sg; | ||
401 | int err; | 399 | int err; |
402 | 400 | ||
403 | page = get_a_page(vi, gfp); | 401 | page = get_a_page(vi, gfp); |
404 | if (!page) | 402 | if (!page) |
405 | return -ENOMEM; | 403 | return -ENOMEM; |
406 | 404 | ||
407 | sg_init_one(&sg, page_address(page), PAGE_SIZE); | 405 | sg_init_one(vi->rx_sg, page_address(page), PAGE_SIZE); |
408 | 406 | ||
409 | 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); |
410 | if (err < 0) | 408 | if (err < 0) |
411 | give_pages(vi, page); | 409 | give_pages(vi, page); |
412 | 410 | ||
@@ -515,12 +513,9 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi) | |||
515 | 513 | ||
516 | 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) |
517 | { | 515 | { |
518 | struct scatterlist sg[2+MAX_SKB_FRAGS]; | ||
519 | struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb); | 516 | struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb); |
520 | const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; | 517 | const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; |
521 | 518 | ||
522 | sg_init_table(sg, 2+MAX_SKB_FRAGS); | ||
523 | |||
524 | 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); |
525 | 520 | ||
526 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 521 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
@@ -554,12 +549,13 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) | |||
554 | 549 | ||
555 | /* Encode metadata header at front. */ | 550 | /* Encode metadata header at front. */ |
556 | if (vi->mergeable_rx_bufs) | 551 | if (vi->mergeable_rx_bufs) |
557 | sg_set_buf(sg, &hdr->mhdr, sizeof hdr->mhdr); | 552 | sg_set_buf(vi->tx_sg, &hdr->mhdr, sizeof hdr->mhdr); |
558 | else | 553 | else |
559 | sg_set_buf(sg, &hdr->hdr, sizeof hdr->hdr); | 554 | sg_set_buf(vi->tx_sg, &hdr->hdr, sizeof hdr->hdr); |
560 | 555 | ||
561 | 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; |
562 | 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); | ||
563 | } | 559 | } |
564 | 560 | ||
565 | 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) |
@@ -722,7 +718,6 @@ static void virtnet_set_rx_mode(struct net_device *dev) | |||
722 | struct scatterlist sg[2]; | 718 | struct scatterlist sg[2]; |
723 | u8 promisc, allmulti; | 719 | u8 promisc, allmulti; |
724 | struct virtio_net_ctrl_mac *mac_data; | 720 | struct virtio_net_ctrl_mac *mac_data; |
725 | struct dev_addr_list *addr; | ||
726 | struct netdev_hw_addr *ha; | 721 | struct netdev_hw_addr *ha; |
727 | int uc_count; | 722 | int uc_count; |
728 | int mc_count; | 723 | int mc_count; |
@@ -779,8 +774,8 @@ static void virtnet_set_rx_mode(struct net_device *dev) | |||
779 | 774 | ||
780 | mac_data->entries = mc_count; | 775 | mac_data->entries = mc_count; |
781 | i = 0; | 776 | i = 0; |
782 | netdev_for_each_mc_addr(addr, dev) | 777 | netdev_for_each_mc_addr(ha, dev) |
783 | memcpy(&mac_data->macs[i++][0], addr->da_addr, ETH_ALEN); | 778 | memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN); |
784 | 779 | ||
785 | sg_set_buf(&sg[1], mac_data, | 780 | sg_set_buf(&sg[1], mac_data, |
786 | sizeof(mac_data->entries) + (mc_count * ETH_ALEN)); | 781 | sizeof(mac_data->entries) + (mc_count * ETH_ALEN)); |
@@ -942,6 +937,8 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
942 | vdev->priv = vi; | 937 | vdev->priv = vi; |
943 | vi->pages = NULL; | 938 | vi->pages = NULL; |
944 | 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)); | ||
945 | 942 | ||
946 | /* 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. */ |
947 | if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) || | 944 | if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) || |