---
 Documentation/lguest/lguest.c |   23 ++++++++++++++++++++++-
 drivers/net/virtio_net.c      |   24 ++++++++++++++++++++++--
 2 files changed, 44 insertions(+), 3 deletions(-)

diff -r c1d09eff85a1 Documentation/lguest/lguest.c
--- a/Documentation/lguest/lguest.c	Tue May 06 21:18:01 2008 +1000
+++ b/Documentation/lguest/lguest.c	Tue May 06 22:33:48 2008 +1000
@@ -57,6 +57,8 @@ typedef uint16_t u16;
 typedef uint16_t u16;
 typedef uint8_t u8;
 /*:*/
+
+static struct vring *watch;
 
 #define PAGE_PRESENT 0x7 	/* Present, RW, Execute */
 #define NET_PEERNUM 1
@@ -299,6 +301,7 @@ static void *map_zeroed_pages(unsigned i
 		err(1, "Mmaping %u pages of /dev/zero", num);
 
 	verbose("Memory backing file is %s @ %p\n", memfile_path, addr);
+	memset(addr, 0, getpagesize() * num);
 	return addr;
 }
 
@@ -608,8 +611,19 @@ static void wake_parent(int pipefd, int 
 				FD_SET(fd, &devices.infds);
 			else
 				FD_CLR(-fd - 1, &devices.infds);
-		} else /* Send LHREQ_BREAK command. */
+		} else { /* Send LHREQ_BREAK command. */
+			printf("Waker before: %u/%u %u/%u\n",
+			       watch->avail->idx,
+			       vring_last_avail(watch),
+			       watch->used->idx,
+			       vring_last_used(watch));
 			pwrite(lguest_fd, args, sizeof(args), cpu_id);
+			printf("Waker after: %u/%u %u/%u\n",
+			       watch->avail->idx,
+			       vring_last_avail(watch),
+			       watch->used->idx,
+			       vring_last_used(watch));
+		}
 	}
 }
 
@@ -1162,6 +1176,7 @@ static void add_virtqueue(struct device 
 
 	/* Initialize the vring. */
 	vring_init(&vq->vring, num_descs, p, getpagesize());
+	memset(p, 0, vring_size(num_descs, getpagesize()));
 
 	/* Append virtqueue to this device's descriptor.  We use
 	 * device_config() to get the end of the device's current virtqueues;
@@ -1376,6 +1391,10 @@ static bool xmitfd_used(int fd, struct d
 {
 	struct virtio_net_info *ni = dev->priv;
 
+	printf("Launcher: %u/%u %u/%u\n",
+	       watch->avail->idx, vring_last_avail(watch),
+	       watch->used->idx, vring_last_used(watch));
+
 	/* Read to clear it. */
 	if (read(ni->xmitfd, NULL, 0) != 0)
 		err(1, "%s: reading xmitfd", dev->name);
@@ -1490,6 +1509,8 @@ static void setup_tun_net(const char *ar
 		/* Now we create the receive and xmit ringfds. */
 		ni->recvfd = map_vring(&dev->vq->vring);
 		ni->xmitfd = map_vring(&dev->vq->next->vring);
+
+		watch = &dev->vq->next->vring;
 
 		/* Tell the tunnet to use them. */
 		if (ioctl(netfd, TUNSETRECVVRING, ni->recvfd) != 0)
diff -r c1d09eff85a1 drivers/net/virtio_net.c
--- a/drivers/net/virtio_net.c	Tue May 06 21:18:01 2008 +1000
+++ b/drivers/net/virtio_net.c	Tue May 06 22:33:48 2008 +1000
@@ -48,6 +48,9 @@ struct virtnet_info
 	/* Number of input buffers, and max we've ever had. */
 	unsigned int num, max;
 
+	/* For cleaning up after transmission. */
+	struct tasklet_struct tasklet;
+
 	/* Receive & send queues. */
 	struct sk_buff_head recv;
 	struct sk_buff_head send;
@@ -69,8 +72,12 @@ static void skb_xmit_done(struct virtque
 
 	/* Suppress further interrupts. */
 	svq->vq_ops->disable_cb(svq);
-	/* We were waiting for more output buffers. */
-	netif_wake_queue(vi->dev);
+
+	/* Were we waiting for more output buffers? */
+	if (netif_queue_stopped(vi->dev))
+		netif_wake_queue(vi->dev);
+	else
+		tasklet_schedule(&vi->tasklet);
 }
 
 static void receive_skb(struct net_device *dev, struct sk_buff *skb,
@@ -304,6 +311,17 @@ static int xmit_skb(struct virtnet_info 
 	return vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb);
 }
 
+static void xmit_tasklet(unsigned long data)
+{
+	struct virtnet_info *vi = (void *)data;
+
+	netif_tx_lock_bh(vi->dev);
+	free_old_xmit_skbs(vi);
+	if (vi->last_xmit_skb && xmit_skb(vi, vi->last_xmit_skb) == 0)
+		vi->last_xmit_skb = NULL;
+	netif_tx_unlock_bh(vi->dev);
+}
+
 static int start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct virtnet_info *vi = netdev_priv(dev);
@@ -477,6 +495,8 @@ static int virtnet_probe(struct virtio_d
 	skb_queue_head_init(&vi->recv);
 	skb_queue_head_init(&vi->send);
 
+	tasklet_init(&vi->tasklet, xmit_tasklet, (unsigned long)vi);
+
 	err = register_netdev(dev);
 	if (err) {
 		pr_debug("virtio_net: registering device failed\n");
