aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/virtio_net.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 9a3b85e55ccc..156d76fee164 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -44,6 +44,8 @@ struct virtnet_info
44 /* The skb we couldn't send because buffers were full. */ 44 /* The skb we couldn't send because buffers were full. */
45 struct sk_buff *last_xmit_skb; 45 struct sk_buff *last_xmit_skb;
46 46
47 struct timer_list xmit_free_timer;
48
47 /* Number of input buffers, and max we've ever had. */ 49 /* Number of input buffers, and max we've ever had. */
48 unsigned int num, max; 50 unsigned int num, max;
49 51
@@ -240,9 +242,23 @@ static void free_old_xmit_skbs(struct virtnet_info *vi)
240 } 242 }
241} 243}
242 244
245static void xmit_free(unsigned long data)
246{
247 struct virtnet_info *vi = (void *)data;
248
249 netif_tx_lock(vi->dev);
250
251 free_old_xmit_skbs(vi);
252
253 if (!skb_queue_empty(&vi->send))
254 mod_timer(&vi->xmit_free_timer, jiffies + (HZ/10));
255
256 netif_tx_unlock(vi->dev);
257}
258
243static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) 259static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
244{ 260{
245 int num; 261 int num, err;
246 struct scatterlist sg[2+MAX_SKB_FRAGS]; 262 struct scatterlist sg[2+MAX_SKB_FRAGS];
247 struct virtio_net_hdr *hdr; 263 struct virtio_net_hdr *hdr;
248 const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; 264 const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
@@ -285,7 +301,11 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
285 vnet_hdr_to_sg(sg, skb); 301 vnet_hdr_to_sg(sg, skb);
286 num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1; 302 num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
287 303
288 return vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb); 304 err = vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb);
305 if (!err)
306 mod_timer(&vi->xmit_free_timer, jiffies + (HZ/10));
307
308 return err;
289} 309}
290 310
291static void xmit_tasklet(unsigned long data) 311static void xmit_tasklet(unsigned long data)
@@ -456,6 +476,8 @@ static int virtnet_probe(struct virtio_device *vdev)
456 476
457 tasklet_init(&vi->tasklet, xmit_tasklet, (unsigned long)vi); 477 tasklet_init(&vi->tasklet, xmit_tasklet, (unsigned long)vi);
458 478
479 setup_timer(&vi->xmit_free_timer, xmit_free, (unsigned long)vi);
480
459 err = register_netdev(dev); 481 err = register_netdev(dev);
460 if (err) { 482 if (err) {
461 pr_debug("virtio_net: registering device failed\n"); 483 pr_debug("virtio_net: registering device failed\n");
@@ -493,6 +515,8 @@ static void virtnet_remove(struct virtio_device *vdev)
493 /* Stop all the virtqueues. */ 515 /* Stop all the virtqueues. */
494 vdev->config->reset(vdev); 516 vdev->config->reset(vdev);
495 517
518 del_timer_sync(&vi->xmit_free_timer);
519
496 /* Free our skbs in send and recv queues, if any. */ 520 /* Free our skbs in send and recv queues, if any. */
497 while ((skb = __skb_dequeue(&vi->recv)) != NULL) { 521 while ((skb = __skb_dequeue(&vi->recv)) != NULL) {
498 kfree_skb(skb); 522 kfree_skb(skb);