Am Dienstag, 21. August 2007 schrieb Rusty Russell:
> The only reason that we don't do it in skb_xmit_done() is because
> kfree_skb() isn't supposed to be called from an interrupt.  But there's
> dev_kfree_skb_any() which can be used.

Ok, I now hacked something that works but I really dont like the 
local_irq_disable bits. I sent this patch nevertheless, but I will look into 
Arnds suggestion.

--- linux-2.6.22.orig/drivers/net/virtio_net.c
+++ linux-2.6.22/drivers/net/virtio_net.c
@@ -53,12 +52,31 @@ static void vnet_hdr_to_sg(struct scatte
        sg->length = sizeof(struct virtio_net_hdr);
 }
 
+static void free_old_xmit_skbs(struct virtnet_info *vi)
+{
+       struct sk_buff *skb;
+       unsigned int len;
+
+       netif_tx_lock(vi->ndev);
+       while ((skb = vi->vq_send->ops->get_buf(vi->vq_send, &len)) != NULL) {
+               /* They cannot have written to the packet. */
+               BUG_ON(len != 0);
+               pr_debug("Sent skb %p\n", skb);
+               __skb_unlink(skb, &vi->send);
+               vi->ndev->stats.tx_bytes += skb->len;
+               vi->ndev->stats.tx_packets++;
+               dev_kfree_skb_irq(skb);
+       }
+       netif_tx_unlock(vi->ndev);
+}
+
 static bool skb_xmit_done(struct virtqueue *vq)
 {
        struct virtnet_info *vi = vq->priv;
 
        /* In case we were waiting for output buffers. */
        netif_wake_queue(vi->ndev);
+       free_old_xmit_skbs(vi);
        return true;
 }
 
@@ -214,22 +232,6 @@ again:
        return 0;
 }
 
-static void free_old_xmit_skbs(struct virtnet_info *vi)
-{
-       struct sk_buff *skb;
-       unsigned int len;
-
-       while ((skb = vi->vq_send->ops->get_buf(vi->vq_send, &len)) != NULL) {
-               /* They cannot have written to the packet. */
-               BUG_ON(len != 0);
-               pr_debug("Sent skb %p\n", skb);
-               __skb_unlink(skb, &vi->send);
-               vi->ndev->stats.tx_bytes += skb->len;
-               vi->ndev->stats.tx_packets++;
-               kfree_skb(skb);
-       }
-}
-
 static int start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct virtnet_info *vi = netdev_priv(dev);
@@ -238,12 +240,12 @@ static int start_xmit(struct sk_buff *sk
        struct virtio_net_hdr *hdr;
        const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
 
+       local_irq_disable();
+       netif_tx_lock(vi->ndev);
        pr_debug("%s: xmit %p %02x:%02x:%02x:%02x:%02x:%02x\n",
                 dev->name, skb,
                 dest[0], dest[1], dest[2], dest[3], dest[4], dest[5]);
 
-       free_old_xmit_skbs(vi);
-
        /* Encode metadata header at front. */
        hdr = skb_vnet_hdr(skb);
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
@@ -280,10 +282,13 @@ static int start_xmit(struct sk_buff *sk
                pr_debug("%s: virtio not prepared to send\n", dev->name);
                skb_unlink(skb, &vi->send);
                netif_stop_queue(dev);
+               netif_tx_unlock(vi->ndev);
+               local_irq_enable();
                return NETDEV_TX_BUSY;
        }
        vi->vq_send->ops->sync(vi->vq_send);
-
+       netif_tx_unlock(vi->ndev);
+       local_irq_enable();
        return 0;
 }
 
@@ -343,7 +348,7 @@ struct net_device *virtnet_probe(struct 
        dev->poll = virtnet_poll;
        dev->hard_start_xmit = start_xmit;
        dev->weight = 16;
-       dev->features = features;
+       dev->features = features | NETIF_F_LLTX;
        SET_NETDEV_DEV(dev, device);
 
        vi = netdev_priv(dev);

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to