aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/virtio_net.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-06-04 20:39:33 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-06-04 20:39:33 -0400
commit3e387fcdc485d94fe2c4b52e7c30c0c4cd1fe364 (patch)
tree577de7b1aed18106b30e3e1d517b165f137e52ac /drivers/net/virtio_net.c
parent9489a0625854cd7482bb0e8b37de4406cdcd49e0 (diff)
parent24b95685ffcdb3dc28f64b9e8af6ea3e8360fbc5 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (56 commits) l2tp: Fix possible oops if transmitting or receiving when tunnel goes down tcp: Fix for race due to temporary drop of the socket lock in skb_splice_bits. tcp: Increment OUTRSTS in tcp_send_active_reset() raw: Raw socket leak. lt2p: Fix possible WARN_ON from socket code when UDP socket is closed USB ID for Philips CPWUA054/00 Wireless USB Adapter 11g ssb: Fix context assertion in ssb_pcicore_dev_irqvecs_enable libertas: fix command size for CMD_802_11_SUBSCRIBE_EVENT ipw2200: expire and use oldest BSS on adhoc create airo warning fix b43legacy: Fix controller restart crash sctp: Fix ECN markings for IPv6 sctp: Flush the queue only once during fast retransmit. sctp: Start T3-RTX timer when fast retransmitting lowest TSN sctp: Correctly implement Fast Recovery cwnd manipulations. sctp: Move sctp_v4_dst_saddr out of loop sctp: retran_path update bug fix tcp: fix skb vs fack_count out-of-sync condition sunhme: Cleanup use of deprecated calls to save_and_cli and restore_flags. xfrm: xfrm_algo: correct usage of RIPEMD-160 ...
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r--drivers/net/virtio_net.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index fe7cdf2a2a23..5450eac9e263 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -47,6 +47,9 @@ struct virtnet_info
47 /* Number of input buffers, and max we've ever had. */ 47 /* Number of input buffers, and max we've ever had. */
48 unsigned int num, max; 48 unsigned int num, max;
49 49
50 /* For cleaning up after transmission. */
51 struct tasklet_struct tasklet;
52
50 /* Receive & send queues. */ 53 /* Receive & send queues. */
51 struct sk_buff_head recv; 54 struct sk_buff_head recv;
52 struct sk_buff_head send; 55 struct sk_buff_head send;
@@ -68,8 +71,13 @@ static void skb_xmit_done(struct virtqueue *svq)
68 71
69 /* Suppress further interrupts. */ 72 /* Suppress further interrupts. */
70 svq->vq_ops->disable_cb(svq); 73 svq->vq_ops->disable_cb(svq);
74
71 /* We were waiting for more output buffers. */ 75 /* We were waiting for more output buffers. */
72 netif_wake_queue(vi->dev); 76 netif_wake_queue(vi->dev);
77
78 /* Make sure we re-xmit last_xmit_skb: if there are no more packets
79 * queued, start_xmit won't be called. */
80 tasklet_schedule(&vi->tasklet);
73} 81}
74 82
75static void receive_skb(struct net_device *dev, struct sk_buff *skb, 83static void receive_skb(struct net_device *dev, struct sk_buff *skb,
@@ -278,6 +286,18 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
278 return vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb); 286 return vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb);
279} 287}
280 288
289static void xmit_tasklet(unsigned long data)
290{
291 struct virtnet_info *vi = (void *)data;
292
293 netif_tx_lock_bh(vi->dev);
294 if (vi->last_xmit_skb && xmit_skb(vi, vi->last_xmit_skb) == 0) {
295 vi->svq->vq_ops->kick(vi->svq);
296 vi->last_xmit_skb = NULL;
297 }
298 netif_tx_unlock_bh(vi->dev);
299}
300
281static int start_xmit(struct sk_buff *skb, struct net_device *dev) 301static int start_xmit(struct sk_buff *skb, struct net_device *dev)
282{ 302{
283 struct virtnet_info *vi = netdev_priv(dev); 303 struct virtnet_info *vi = netdev_priv(dev);
@@ -287,21 +307,25 @@ again:
287 free_old_xmit_skbs(vi); 307 free_old_xmit_skbs(vi);
288 308
289 /* If we has a buffer left over from last time, send it now. */ 309 /* If we has a buffer left over from last time, send it now. */
290 if (vi->last_xmit_skb) { 310 if (unlikely(vi->last_xmit_skb)) {
291 if (xmit_skb(vi, vi->last_xmit_skb) != 0) { 311 if (xmit_skb(vi, vi->last_xmit_skb) != 0) {
292 /* Drop this skb: we only queue one. */ 312 /* Drop this skb: we only queue one. */
293 vi->dev->stats.tx_dropped++; 313 vi->dev->stats.tx_dropped++;
294 kfree_skb(skb); 314 kfree_skb(skb);
315 skb = NULL;
295 goto stop_queue; 316 goto stop_queue;
296 } 317 }
297 vi->last_xmit_skb = NULL; 318 vi->last_xmit_skb = NULL;
298 } 319 }
299 320
300 /* Put new one in send queue and do transmit */ 321 /* Put new one in send queue and do transmit */
301 __skb_queue_head(&vi->send, skb); 322 if (likely(skb)) {
302 if (xmit_skb(vi, skb) != 0) { 323 __skb_queue_head(&vi->send, skb);
303 vi->last_xmit_skb = skb; 324 if (xmit_skb(vi, skb) != 0) {
304 goto stop_queue; 325 vi->last_xmit_skb = skb;
326 skb = NULL;
327 goto stop_queue;
328 }
305 } 329 }
306done: 330done:
307 vi->svq->vq_ops->kick(vi->svq); 331 vi->svq->vq_ops->kick(vi->svq);
@@ -428,6 +452,8 @@ static int virtnet_probe(struct virtio_device *vdev)
428 skb_queue_head_init(&vi->recv); 452 skb_queue_head_init(&vi->recv);
429 skb_queue_head_init(&vi->send); 453 skb_queue_head_init(&vi->send);
430 454
455 tasklet_init(&vi->tasklet, xmit_tasklet, (unsigned long)vi);
456
431 err = register_netdev(dev); 457 err = register_netdev(dev);
432 if (err) { 458 if (err) {
433 pr_debug("virtio_net: registering device failed\n"); 459 pr_debug("virtio_net: registering device failed\n");