---
 Documentation/lguest/lguest.c |    5 ++++
 drivers/net/tun.c             |    5 +++-
 drivers/net/virtio_net.c      |   49 ++++++++++++++++++++++++++++++++++++------
 3 files changed, 51 insertions(+), 8 deletions(-)

diff -r 8dc11495974c Documentation/lguest/lguest.c
--- a/Documentation/lguest/lguest.c	Mon May 05 15:35:42 2008 +1000
+++ b/Documentation/lguest/lguest.c	Mon May 05 22:07:24 2008 +1000
@@ -1354,6 +1354,11 @@ static bool xmitfd_used(int fd, struct d
 	/* Read to clear it. */
 	if (read(ni->xmitfd, NULL, 0) != 0)
 		err(1, "%s: reading xmitfd", dev->name);
+	printf("xmitq: %stelling about new pkt %u/%u\n",
+	       	ni->xmit_vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT ?
+	       "not " : "",
+	       ni->xmit_vq->vring.used->idx,
+	       vring_last_used(&ni->xmit_vq->vring));
 	trigger_irq(fd, ni->xmit_vq);
 
 	return true;
diff -r 8dc11495974c drivers/net/tun.c
--- a/drivers/net/tun.c	Mon May 05 15:35:42 2008 +1000
+++ b/drivers/net/tun.c	Mon May 05 22:07:24 2008 +1000
@@ -156,6 +156,7 @@ static int tun_net_xmit(struct sk_buff *
 		if (!(tun->flags & TUN_ONE_QUEUE)) {
 			/* Normal queueing mode. */
 			/* Packet scheduler handles dropping of further packets. */
+			printk("We don't want any more!\n");
 			netif_stop_queue(dev);
 
 			/* We won't see all dropped packets individually, so overrun
@@ -542,8 +543,10 @@ static int pull_recv_skbs(void *_tun)
 	if (skb)
 		skb_queue_head(&tun->readq, skb);
 
-	if (num_copied)
+	if (num_copied) {
+		printk("Waking tun queue\n");
 		netif_wake_queue(tun->dev);
+	}
 
 	return err;
 }
diff -r 8dc11495974c drivers/net/virtio_net.c
--- a/drivers/net/virtio_net.c	Mon May 05 15:35:42 2008 +1000
+++ b/drivers/net/virtio_net.c	Mon May 05 22:07:24 2008 +1000
@@ -35,6 +35,14 @@ module_param(gso, bool, 0444);
 /* FIXME: MTU in config. */
 #define MAX_PACKET_LEN (ETH_HLEN+ETH_DATA_LEN)
 
+static ktime_t get_ktime(void)
+{
+	struct timespec now;
+
+	ktime_get_ts(&now);
+	return timespec_to_ktime(now);
+}
+
 struct virtnet_info
 {
 	struct virtio_device *vdev;
@@ -42,15 +50,15 @@ struct virtnet_info
 	struct net_device *dev;
 	struct napi_struct napi;
 
-	/* The skb we couldn't send because buffers were full. */
-	struct sk_buff *last_xmit_skb;
-
 	/* Number of input buffers, and max we've ever had. */
 	unsigned int num, max;
 
 	/* Receive & send queues. */
 	struct sk_buff_head recv;
 	struct sk_buff_head send;
+
+	/* Last time we were stopped */
+	ktime_t last_stopped;
 };
 
 static inline struct virtio_net_hdr *skb_vnet_hdr(struct sk_buff *skb)
@@ -69,8 +77,22 @@ static void skb_xmit_done(struct virtque
 
 	/* Suppress further interrupts. */
 	svq->vq_ops->disable_cb(svq);
+	{
+		ktime_t now = get_ktime();
+		s64 diff = ktime_to_ns(ktime_sub(now, vi->last_stopped));
+		/* More than 1/10th sec? */
+		if (diff > 100000000)
+			printk("%s: stopped for %llu ns\n",
+			       vi->dev->name, diff);
+		vi->last_stopped = now;
+	}
+
 	/* We were waiting for more output buffers. */
-	netif_wake_queue(vi->dev);
+	if (test_and_clear_bit(__LINK_STATE_XOFF, &vi->dev->state)) {
+		printk("Waking\n");
+		__netif_schedule(vi->dev);
+	} else
+		printk("Not waking\n");
 }
 
 static void receive_skb(struct net_device *dev, struct sk_buff *skb,
@@ -256,16 +278,17 @@ static void free_old_xmit_skbs(struct vi
 	}
 }
 
-static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
+static int start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	int num;
+	struct virtnet_info *vi = netdev_priv(dev);
+	int num, err;
 	struct scatterlist sg[2+MAX_SKB_FRAGS];
 	struct virtio_net_hdr *hdr;
 	const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
 
 	sg_init_table(sg, 2+MAX_SKB_FRAGS);
 
-	pr_debug("%s: xmit %p " MAC_FMT "\n", vi->dev->name, skb,
+	pr_debug("%s: xmit %p " MAC_FMT "\n", dev->name, skb,
 		 dest[0], dest[1], dest[2],
 		 dest[3], dest[4], dest[5]);
 
@@ -308,6 +331,7 @@ static int start_xmit(struct sk_buff *sk
 {
 	struct virtnet_info *vi = netdev_priv(dev);
 
+	printk("xmitting\n");
 again:
 	/* Free up any pending old buffers before queueing new ones. */
 	free_old_xmit_skbs(vi);
@@ -315,6 +339,7 @@ again:
 	/* If we has a buffer left over from last time, send it now. */
 	if (vi->last_xmit_skb) {
 		if (xmit_skb(vi, vi->last_xmit_skb) != 0) {
+			printk("Dropping last_xmit_skb\n");
 			/* Drop this skb: we only queue one. */
 			vi->dev->stats.tx_dropped++;
 			kfree_skb(skb);
@@ -326,8 +351,14 @@ again:
 	/* Put new one in send queue and do transmit */
 	__skb_queue_head(&vi->send, skb);
 	if (xmit_skb(vi, skb) != 0) {
+#if 0
 		vi->last_xmit_skb = skb;
 		goto stop_queue;
+#else
+		__skb_unlink(skb, &vi->send);
+		netif_stop_queue(dev);
+		return NETDEV_TX_BUSY;
+#endif
 	}
 done:
 	vi->svq->vq_ops->kick(vi->svq);
@@ -342,8 +373,11 @@ stop_queue:
 	if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) {
 		vi->svq->vq_ops->disable_cb(vi->svq);
 		netif_start_queue(dev);
+		printk("Restart\n");
 		goto again;
 	}
+	printk("Stopped\n");
+	vi->last_stopped = get_ktime();
 	goto done;
 }
 
@@ -459,6 +493,7 @@ static int virtnet_probe(struct virtio_d
 	vi->dev = dev;
 	vi->vdev = vdev;
 	vdev->priv = vi;
+	vi->last_stopped = ktime_get();
 
 	/* We expect two virtqueues, receive then send. */
 	vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done);
