aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/virtio_net.c
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2010-04-08 00:01:41 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-08 00:01:41 -0400
commit5e01d2f91df62be4d6f282149bc2a8858992ceca (patch)
tree8124dc2ba305c27bc59c9bba3cb0810b77c14761 /drivers/net/virtio_net.c
parentb681ee77f8ad248b0fdcec2e5e8c4df6e757eba3 (diff)
virtio-net: move sg off stack
Move sg structure off stack and into virtnet_info structure. This helps remove extra sg_init_table calls as well as reduce stack usage. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Tested-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r--drivers/net/virtio_net.c52
1 files changed, 25 insertions, 27 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index ecec9a8527f3..b81e452d4ba2 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -39,8 +39,7 @@ module_param(gso, bool, 0444);
39 39
40#define VIRTNET_SEND_COMMAND_SG_MAX 2 40#define VIRTNET_SEND_COMMAND_SG_MAX 2
41 41
42struct virtnet_info 42struct virtnet_info {
43{
44 struct virtio_device *vdev; 43 struct virtio_device *vdev;
45 struct virtqueue *rvq, *svq, *cvq; 44 struct virtqueue *rvq, *svq, *cvq;
46 struct net_device *dev; 45 struct net_device *dev;
@@ -61,6 +60,10 @@ struct virtnet_info
61 60
62 /* Chain pages by the private ptr. */ 61 /* Chain pages by the private ptr. */
63 struct page *pages; 62 struct page *pages;
63
64 /* fragments + linear part + virtio header */
65 struct scatterlist rx_sg[MAX_SKB_FRAGS + 2];
66 struct scatterlist tx_sg[MAX_SKB_FRAGS + 2];
64}; 67};
65 68
66struct skb_vnet_hdr { 69struct skb_vnet_hdr {
@@ -323,10 +326,8 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp)
323{ 326{
324 struct sk_buff *skb; 327 struct sk_buff *skb;
325 struct skb_vnet_hdr *hdr; 328 struct skb_vnet_hdr *hdr;
326 struct scatterlist sg[2];
327 int err; 329 int err;
328 330
329 sg_init_table(sg, 2);
330 skb = netdev_alloc_skb_ip_align(vi->dev, MAX_PACKET_LEN); 331 skb = netdev_alloc_skb_ip_align(vi->dev, MAX_PACKET_LEN);
331 if (unlikely(!skb)) 332 if (unlikely(!skb))
332 return -ENOMEM; 333 return -ENOMEM;
@@ -334,11 +335,11 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp)
334 skb_put(skb, MAX_PACKET_LEN); 335 skb_put(skb, MAX_PACKET_LEN);
335 336
336 hdr = skb_vnet_hdr(skb); 337 hdr = skb_vnet_hdr(skb);
337 sg_set_buf(sg, &hdr->hdr, sizeof hdr->hdr); 338 sg_set_buf(vi->rx_sg, &hdr->hdr, sizeof hdr->hdr);
338 339
339 skb_to_sgvec(skb, sg + 1, 0, skb->len); 340 skb_to_sgvec(skb, vi->rx_sg + 1, 0, skb->len);
340 341
341 err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, 2, skb); 342 err = vi->rvq->vq_ops->add_buf(vi->rvq, vi->rx_sg, 0, 2, skb);
342 if (err < 0) 343 if (err < 0)
343 dev_kfree_skb(skb); 344 dev_kfree_skb(skb);
344 345
@@ -347,13 +348,11 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp)
347 348
348static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp) 349static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp)
349{ 350{
350 struct scatterlist sg[MAX_SKB_FRAGS + 2];
351 struct page *first, *list = NULL; 351 struct page *first, *list = NULL;
352 char *p; 352 char *p;
353 int i, err, offset; 353 int i, err, offset;
354 354
355 sg_init_table(sg, MAX_SKB_FRAGS + 2); 355 /* page in vi->rx_sg[MAX_SKB_FRAGS + 1] is list tail */
356 /* page in sg[MAX_SKB_FRAGS + 1] is list tail */
357 for (i = MAX_SKB_FRAGS + 1; i > 1; --i) { 356 for (i = MAX_SKB_FRAGS + 1; i > 1; --i) {
358 first = get_a_page(vi, gfp); 357 first = get_a_page(vi, gfp);
359 if (!first) { 358 if (!first) {
@@ -361,7 +360,7 @@ static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp)
361 give_pages(vi, list); 360 give_pages(vi, list);
362 return -ENOMEM; 361 return -ENOMEM;
363 } 362 }
364 sg_set_buf(&sg[i], page_address(first), PAGE_SIZE); 363 sg_set_buf(&vi->rx_sg[i], page_address(first), PAGE_SIZE);
365 364
366 /* chain new page in list head to match sg */ 365 /* chain new page in list head to match sg */
367 first->private = (unsigned long)list; 366 first->private = (unsigned long)list;
@@ -375,17 +374,17 @@ static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp)
375 } 374 }
376 p = page_address(first); 375 p = page_address(first);
377 376
378 /* sg[0], sg[1] share the same page */ 377 /* vi->rx_sg[0], vi->rx_sg[1] share the same page */
379 /* a separated sg[0] for virtio_net_hdr only during to QEMU bug*/ 378 /* a separated vi->rx_sg[0] for virtio_net_hdr only due to QEMU bug */
380 sg_set_buf(&sg[0], p, sizeof(struct virtio_net_hdr)); 379 sg_set_buf(&vi->rx_sg[0], p, sizeof(struct virtio_net_hdr));
381 380
382 /* sg[1] for data packet, from offset */ 381 /* vi->rx_sg[1] for data packet, from offset */
383 offset = sizeof(struct padded_vnet_hdr); 382 offset = sizeof(struct padded_vnet_hdr);
384 sg_set_buf(&sg[1], p + offset, PAGE_SIZE - offset); 383 sg_set_buf(&vi->rx_sg[1], p + offset, PAGE_SIZE - offset);
385 384
386 /* chain first in list head */ 385 /* chain first in list head */
387 first->private = (unsigned long)list; 386 first->private = (unsigned long)list;
388 err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, MAX_SKB_FRAGS + 2, 387 err = vi->rvq->vq_ops->add_buf(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2,
389 first); 388 first);
390 if (err < 0) 389 if (err < 0)
391 give_pages(vi, first); 390 give_pages(vi, first);
@@ -396,16 +395,15 @@ static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp)
396static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp) 395static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)
397{ 396{
398 struct page *page; 397 struct page *page;
399 struct scatterlist sg;
400 int err; 398 int err;
401 399
402 page = get_a_page(vi, gfp); 400 page = get_a_page(vi, gfp);
403 if (!page) 401 if (!page)
404 return -ENOMEM; 402 return -ENOMEM;
405 403
406 sg_init_one(&sg, page_address(page), PAGE_SIZE); 404 sg_init_one(vi->rx_sg, page_address(page), PAGE_SIZE);
407 405
408 err = vi->rvq->vq_ops->add_buf(vi->rvq, &sg, 0, 1, page); 406 err = vi->rvq->vq_ops->add_buf(vi->rvq, vi->rx_sg, 0, 1, page);
409 if (err < 0) 407 if (err < 0)
410 give_pages(vi, page); 408 give_pages(vi, page);
411 409
@@ -514,12 +512,9 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi)
514 512
515static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) 513static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
516{ 514{
517 struct scatterlist sg[2+MAX_SKB_FRAGS];
518 struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb); 515 struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb);
519 const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; 516 const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
520 517
521 sg_init_table(sg, 2+MAX_SKB_FRAGS);
522
523 pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest); 518 pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest);
524 519
525 if (skb->ip_summed == CHECKSUM_PARTIAL) { 520 if (skb->ip_summed == CHECKSUM_PARTIAL) {
@@ -553,12 +548,13 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
553 548
554 /* Encode metadata header at front. */ 549 /* Encode metadata header at front. */
555 if (vi->mergeable_rx_bufs) 550 if (vi->mergeable_rx_bufs)
556 sg_set_buf(sg, &hdr->mhdr, sizeof hdr->mhdr); 551 sg_set_buf(vi->tx_sg, &hdr->mhdr, sizeof hdr->mhdr);
557 else 552 else
558 sg_set_buf(sg, &hdr->hdr, sizeof hdr->hdr); 553 sg_set_buf(vi->tx_sg, &hdr->hdr, sizeof hdr->hdr);
559 554
560 hdr->num_sg = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1; 555 hdr->num_sg = skb_to_sgvec(skb, vi->tx_sg + 1, 0, skb->len) + 1;
561 return vi->svq->vq_ops->add_buf(vi->svq, sg, hdr->num_sg, 0, skb); 556 return vi->svq->vq_ops->add_buf(vi->svq, vi->tx_sg, hdr->num_sg,
557 0, skb);
562} 558}
563 559
564static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) 560static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -940,6 +936,8 @@ static int virtnet_probe(struct virtio_device *vdev)
940 vdev->priv = vi; 936 vdev->priv = vi;
941 vi->pages = NULL; 937 vi->pages = NULL;
942 INIT_DELAYED_WORK(&vi->refill, refill_work); 938 INIT_DELAYED_WORK(&vi->refill, refill_work);
939 sg_init_table(vi->rx_sg, ARRAY_SIZE(vi->rx_sg));
940 sg_init_table(vi->tx_sg, ARRAY_SIZE(vi->tx_sg));
943 941
944 /* If we can receive ANY GSO packets, we must allocate large ones. */ 942 /* If we can receive ANY GSO packets, we must allocate large ones. */
945 if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) || 943 if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||