aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/virtio_net.c64
1 files changed, 40 insertions, 24 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 420388a4c5e8..effe8c685f77 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -1,4 +1,4 @@
1/* A simple network driver using virtio. 1/* A network driver using virtio.
2 * 2 *
3 * Copyright 2007 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation 3 * Copyright 2007 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
4 * 4 *
@@ -73,6 +73,7 @@ struct skb_vnet_hdr {
73 struct virtio_net_hdr hdr; 73 struct virtio_net_hdr hdr;
74 struct virtio_net_hdr_mrg_rxbuf mhdr; 74 struct virtio_net_hdr_mrg_rxbuf mhdr;
75 }; 75 };
76 unsigned int num_sg;
76}; 77};
77 78
78static inline struct skb_vnet_hdr *skb_vnet_hdr(struct sk_buff *skb) 79static inline struct skb_vnet_hdr *skb_vnet_hdr(struct sk_buff *skb)
@@ -442,23 +443,24 @@ again:
442 return received; 443 return received;
443} 444}
444 445
445static void free_old_xmit_skbs(struct virtnet_info *vi) 446static unsigned int free_old_xmit_skbs(struct virtnet_info *vi)
446{ 447{
447 struct sk_buff *skb; 448 struct sk_buff *skb;
448 unsigned int len; 449 unsigned int len, tot_sgs = 0;
449 450
450 while ((skb = vi->svq->vq_ops->get_buf(vi->svq, &len)) != NULL) { 451 while ((skb = vi->svq->vq_ops->get_buf(vi->svq, &len)) != NULL) {
451 pr_debug("Sent skb %p\n", skb); 452 pr_debug("Sent skb %p\n", skb);
452 __skb_unlink(skb, &vi->send); 453 __skb_unlink(skb, &vi->send);
453 vi->dev->stats.tx_bytes += skb->len; 454 vi->dev->stats.tx_bytes += skb->len;
454 vi->dev->stats.tx_packets++; 455 vi->dev->stats.tx_packets++;
456 tot_sgs += skb_vnet_hdr(skb)->num_sg;
455 kfree_skb(skb); 457 kfree_skb(skb);
456 } 458 }
459 return tot_sgs;
457} 460}
458 461
459static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) 462static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
460{ 463{
461 int num;
462 struct scatterlist sg[2+MAX_SKB_FRAGS]; 464 struct scatterlist sg[2+MAX_SKB_FRAGS];
463 struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb); 465 struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb);
464 const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; 466 const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
@@ -502,13 +504,14 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
502 else 504 else
503 sg_set_buf(sg, &hdr->hdr, sizeof(hdr->hdr)); 505 sg_set_buf(sg, &hdr->hdr, sizeof(hdr->hdr));
504 506
505 num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1; 507 hdr->num_sg = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
506 return vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb); 508 return vi->svq->vq_ops->add_buf(vi->svq, sg, hdr->num_sg, 0, skb);
507} 509}
508 510
509static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) 511static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
510{ 512{
511 struct virtnet_info *vi = netdev_priv(dev); 513 struct virtnet_info *vi = netdev_priv(dev);
514 int capacity;
512 515
513again: 516again:
514 /* Free up any pending old buffers before queueing new ones. */ 517 /* Free up any pending old buffers before queueing new ones. */
@@ -516,27 +519,40 @@ again:
516 519
517 /* Put new one in send queue and do transmit */ 520 /* Put new one in send queue and do transmit */
518 __skb_queue_head(&vi->send, skb); 521 __skb_queue_head(&vi->send, skb);
519 if (likely(xmit_skb(vi, skb) >= 0)) { 522 capacity = xmit_skb(vi, skb);
520 vi->svq->vq_ops->kick(vi->svq); 523
521 /* Don't wait up for transmitted skbs to be freed. */ 524 /* This can happen with OOM and indirect buffers. */
522 skb_orphan(skb); 525 if (unlikely(capacity < 0)) {
523 nf_reset(skb); 526 netif_stop_queue(dev);
524 return NETDEV_TX_OK; 527 dev_warn(&dev->dev, "Unexpected full queue\n");
528 if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) {
529 vi->svq->vq_ops->disable_cb(vi->svq);
530 netif_start_queue(dev);
531 goto again;
532 }
533 return NETDEV_TX_BUSY;
525 } 534 }
526 535
527 /* Ring too full for this packet, remove it from queue again. */ 536 vi->svq->vq_ops->kick(vi->svq);
528 pr_debug("%s: virtio not prepared to send\n", dev->name); 537 /* Don't wait up for transmitted skbs to be freed. */
529 __skb_unlink(skb, &vi->send); 538 skb_orphan(skb);
530 netif_stop_queue(dev); 539 nf_reset(skb);
531 540
532 /* Activate callback for using skbs: if this returns false it 541 /* Apparently nice girls don't return TX_BUSY; stop the queue
533 * means some were used in the meantime. */ 542 * before it gets out of hand. Naturally, this wastes entries. */
534 if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) { 543 if (capacity < 2+MAX_SKB_FRAGS) {
535 vi->svq->vq_ops->disable_cb(vi->svq); 544 netif_stop_queue(dev);
536 netif_start_queue(dev); 545 if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) {
537 goto again; 546 /* More just got used, free them then recheck. */
547 capacity += free_old_xmit_skbs(vi);
548 if (capacity >= 2+MAX_SKB_FRAGS) {
549 netif_start_queue(dev);
550 vi->svq->vq_ops->disable_cb(vi->svq);
551 }
552 }
538 } 553 }
539 return NETDEV_TX_BUSY; 554
555 return NETDEV_TX_OK;
540} 556}
541 557
542static int virtnet_set_mac_address(struct net_device *dev, void *p) 558static int virtnet_set_mac_address(struct net_device *dev, void *p)