---
 drivers/char/vring.c     |   25 ++++++++++++++++++++++---
 drivers/net/tun.c        |   26 +++++++++++++++++++++++++-
 drivers/net/virtio_net.c |    4 +++-
 include/linux/vring.h    |    2 ++
 4 files changed, 52 insertions(+), 5 deletions(-)

diff -r bfd81872c647 drivers/char/vring.c
--- a/drivers/char/vring.c	Thu May 01 15:32:01 2008 +1000
+++ b/drivers/char/vring.c	Thu May 01 20:53:54 2008 +1000
@@ -60,16 +60,26 @@ static unsigned int vring_poll(struct fi
 	poll_wait(filp, &vr->poll_wait, poll);
 
 	/* Poll can't error, so let's not go silly here. */
-	if (get_user(used, &vr->ring.used->idx))
+	if (get_user(used, &vr->ring.used->idx)) {
+		printk("vring_poll: Fault\n");
 		return 0;
+	}
 
 	/* More buffers have been used?  It's 'readable'. */
-	if (used != vr->last_used)
+	if (used != vr->last_used) {
+		if (vr->ops && vr->ops->debug)
+			printk("vring_poll: used %u vs last_used %u\n",
+			       used, vr->last_used);
 		return POLLIN | POLLRDNORM;
+	}
 
 	/* Are there more buffer that could be pulled into? */
-	if (get_avail(vr, &avail, &last_avail) != 0 || avail == last_avail)
+	if (get_avail(vr, &avail, &last_avail) != 0 || avail == last_avail) {
+		if (vr->ops && vr->ops->debug)
+			printk("vring_poll: np avail buffers (%i, %i)\n",
+			       avail, last_avail);
 		return 0;
+	}
 
 	/* If we need to pull, it's also readable. */
 	mutex_lock(&vr->lock);
@@ -78,6 +88,9 @@ static unsigned int vring_poll(struct fi
 	else
 		mask = 0;
 	mutex_unlock(&vr->lock);
+
+	if (vr->ops && vr->ops->debug)
+		printk("vring_poll: returning %u\n", mask);
 	return mask;
 }
 
@@ -87,6 +100,9 @@ static ssize_t vring_read(struct file *f
 {
 	struct vring_info *vr = filp->private_data;
 	int err;
+
+	if (vr->ops && vr->ops->debug)
+		printk("vring_read\n");
 
 	/* Some uses of vrings require updating in user context.  This
 	 * is best done close to the caller, ie. here. */
@@ -110,6 +126,9 @@ static ssize_t vring_write(struct file *
 {
 	struct vring_info *vr = filp->private_data;
 	int err;
+
+	if (vr->ops && vr->ops->debug)
+		printk("vring_write\n");
 
 	mutex_lock(&vr->lock);
 	if (vr->ops && vr->ops->push)
diff -r bfd81872c647 drivers/net/tun.c
--- a/drivers/net/tun.c	Thu May 01 15:32:01 2008 +1000
+++ b/drivers/net/tun.c	Thu May 01 20:53:54 2008 +1000
@@ -573,6 +573,9 @@ static int pull_finished_buffers(void *_
 	list_splice_init(&tun->outring_finished, &list);
 	spin_unlock_irq(&tun->outring_lock);
 
+	printk("pull_finished_buffers: %s\n",
+	       list_empty(&list) ? "empty" : "pulling");
+
 	while (!list_empty(&list)) {
 		i = list_first_entry(&list, struct skb_tun_hdr, list);
 
@@ -605,7 +608,7 @@ static void shinfo_finished(struct skb_s
 	vring_wake(tunh->tun->outring);
 }
 
-static int xmit_packets(void *_tun)
+static int _xmit_packets(void *_tun)
 {
 	struct tun_struct *tun = _tun;
 	struct iovec iov[2+MAX_SKB_FRAGS];
@@ -633,6 +636,7 @@ static int xmit_packets(void *_tun)
 			h.hdr_len = len;
 
 		skb = get_user_skb(tun, iov, h.hdr_len, len);
+//		skb = get_user_skb(tun, iov, len, len);
 		if (IS_ERR(skb))
 			return PTR_ERR(skb);
 
@@ -649,6 +653,7 @@ static int xmit_packets(void *_tun)
 			tunh->tun = tun;
 			dev_hold(tun->dev);
 			skb_shinfo(skb)->destructor = shinfo_finished;
+			BUG();
 		} else {
 			/* We're done already. */
 			err = vring_used_buffer(tun->outring, id, 0);
@@ -658,6 +663,7 @@ static int xmit_packets(void *_tun)
 			}
 			wake = 1;
 		}
+		printk("Sending packet\n");
 		netif_rx_ni(skb);
 	}
 
@@ -668,10 +674,25 @@ static int xmit_packets(void *_tun)
 	return id;
 }
 
+static int xmit_packets(void *_tun)
+{
+	int ret;
+
+	printk("xmit_packets\n");
+	ret = _xmit_packets(_tun);
+
+	if (ret) {
+		printk("xmit_packets: failed with %i\n", ret);
+		BUG();
+	}
+	return ret;
+}
+
 static struct vring_ops xmitops = {
 	.push = xmit_packets,
 	.needs_pull = finished_xmit_buffers,
 	.pull = pull_finished_buffers,
+	.debug = true,
 };
 
 static int set_recv_vring(struct tun_struct *tun, int fd)
@@ -1315,6 +1336,9 @@ static int tun_chr_close(struct inode *i
 	/* Free any final incoming packets. */
 	pull_finished_buffers(tun);
 
+	/* Free any final incoming packets. */
+	pull_finished_buffers(tun);
+
 	rtnl_lock();
 
 	/* Detach from net device */
diff -r bfd81872c647 drivers/net/virtio_net.c
--- a/drivers/net/virtio_net.c	Thu May 01 15:32:01 2008 +1000
+++ b/drivers/net/virtio_net.c	Thu May 01 20:53:54 2008 +1000
@@ -70,6 +70,7 @@ static void skb_xmit_done(struct virtque
 	/* Suppress further interrupts. */
 	svq->vq_ops->disable_cb(svq);
 	/* We were waiting for more output buffers. */
+	printk("Waking queue\n");
 	netif_wake_queue(vi->dev);
 }
 
@@ -333,12 +334,13 @@ done:
 	return NETDEV_TX_OK;
 
 stop_queue:
-	pr_debug("%s: virtio not prepared to send\n", dev->name);
+	printk("%s: virtio not prepared to send\n", dev->name);
 	netif_stop_queue(dev);
 
 	/* Activate callback for using skbs: if this returns false it
 	 * means some were used in the meantime. */
 	if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) {
+		printk("%s: virtio enable again\n", dev->name);
 		vi->svq->vq_ops->disable_cb(vi->svq);
 		netif_start_queue(dev);
 		goto again;
diff -r bfd81872c647 include/linux/vring.h
--- a/include/linux/vring.h	Thu May 01 15:32:01 2008 +1000
+++ b/include/linux/vring.h	Thu May 01 20:53:54 2008 +1000
@@ -42,6 +42,8 @@ struct vring_ops {
 
 	/* Returns 0 or negative errno. */
 	int (*push)(void *ops_data);
+
+	bool debug;
 };
 
 struct file;
