]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/virtio_net.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6-omap-h63xx.git] / drivers / net / virtio_net.c
index be5688f5e9310d30376e5fb98c6221dd1b33bc4c..e66de0c12fc10e1455e4137f8f68271ca44505b5 100644 (file)
@@ -24,6 +24,9 @@
 #include <linux/virtio_net.h>
 #include <linux/scatterlist.h>
 
+static int napi_weight = 128;
+module_param(napi_weight, int, 0444);
+
 static int csum = 1, gso = 1;
 module_param(csum, bool, 0444);
 module_param(gso, bool, 0444);
@@ -56,11 +59,13 @@ static inline void vnet_hdr_to_sg(struct scatterlist *sg, struct sk_buff *skb)
        sg_init_one(sg, skb_vnet_hdr(skb), sizeof(struct virtio_net_hdr));
 }
 
-static void skb_xmit_done(struct virtqueue *rvq)
+static void skb_xmit_done(struct virtqueue *svq)
 {
-       struct virtnet_info *vi = rvq->vdev->priv;
+       struct virtnet_info *vi = svq->vdev->priv;
 
-       /* In case we were waiting for output buffers. */
+       /* Suppress further interrupts. */
+       svq->vq_ops->disable_cb(svq);
+       /* We were waiting for more output buffers. */
        netif_wake_queue(vi->dev);
 }
 
@@ -232,8 +237,6 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        pr_debug("%s: xmit %p %s\n", dev->name, skb, print_mac(mac, dest));
 
-       free_old_xmit_skbs(vi);
-
        /* Encode metadata header at front. */
        hdr = skb_vnet_hdr(skb);
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
@@ -266,11 +269,24 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev)
        vnet_hdr_to_sg(sg, skb);
        num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
        __skb_queue_head(&vi->send, skb);
+
+again:
+       /* Free up any pending old buffers before queueing new ones. */
+       free_old_xmit_skbs(vi);
        err = vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb);
        if (err) {
                pr_debug("%s: virtio not prepared to send\n", dev->name);
-               skb_unlink(skb, &vi->send);
                netif_stop_queue(dev);
+
+               /* Activate callback for using skbs: if this fails it
+                * means some were used in the meantime. */
+               if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) {
+                       printk("Unlikely: restart svq failed\n");
+                       netif_start_queue(dev);
+                       goto again;
+               }
+               __skb_unlink(skb, &vi->send);
+
                return NETDEV_TX_BUSY;
        }
        vi->svq->vq_ops->kick(vi->svq);
@@ -283,6 +299,13 @@ static int virtnet_open(struct net_device *dev)
        struct virtnet_info *vi = netdev_priv(dev);
 
        napi_enable(&vi->napi);
+
+       /* If all buffers were filled by other side before we napi_enabled, we
+        * won't get another interrupt, so process any outstanding packets
+        * now.  virtnet_poll wants re-enable the queue, so we disable here. */
+       vi->rvq->vq_ops->disable_cb(vi->rvq);
+       netif_rx_schedule(vi->dev, &vi->napi);
+
        return 0;
 }
 
@@ -333,7 +356,7 @@ static int virtnet_probe(struct virtio_device *vdev)
 
        /* Set up our device-specific information */
        vi = netdev_priv(dev);
-       netif_napi_add(dev, &vi->napi, virtnet_poll, 16);
+       netif_napi_add(dev, &vi->napi, virtnet_poll, napi_weight);
        vi->dev = dev;
        vi->vdev = vdev;