--diff --git a/drivers/xen/v2v/Kconfig b/drivers/xen/v2v/Kconfig
- index dd48eaf..e56706d 100644
-index 5966234..b3b6ef4 100644
----- a/drivers/xen/v2v/Kconfig
--+++ b/drivers/xen/v2v/Kconfig
--@@ -22,3 +22,10 @@ config XEN_V2V_DRV
- default n
- default n
-- help
-- Sample for Xen V2V interdomain communication services.
--+
--+config XEN_V2V_DEV
--+ tristate "Xen V2V device"
--+ depends on XEN_V2V
- + default m
-+ default m
--+ help
--+ Xen V2V char device for userland v2v.
--diff --git a/drivers/xen/v2v/Makefile b/drivers/xen/v2v/Makefile
- index 8e35e62..c390314 100644
-index f3442d9..5230cd6 100644
----- a/drivers/xen/v2v/Makefile
--+++ b/drivers/xen/v2v/Makefile
- @@ -5,4 +5,7 @@ obj-$(CONFIG_XEN_V2V_DRV) += v2vdrv.o
- v2vdrv-objs =
- v2vdrv-objs += v2vsamp.o v2vops.o
-@@ -4,5 +4,6 @@
--
- v2vdrv-objs =
- v2vdrv-objs += v2vsamp.o v2vops.o
--+obj-$(CONFIG_XEN_V2V_DEV) += v2vdev.o
- +
- +
-
-- ccflags-$(CONFIG_XEN_V2V_DEBUG) += -DDEBUG
diff --git a/drivers/xen/v2v/v2vdev.c b/drivers/xen/v2v/v2vdev.c
new file mode 100644
- index 0000000..39d0a84
-index 0000000..c7afdf3
++index 0000000..adfc6c8
--- /dev/null
+++ b/drivers/xen/v2v/v2vdev.c
-@@ -0,0 +1,400 @@
+@@ -0,0 +1,511 @@
+/******************************************************************************
+ * drivers/xen/v2v/v2vdev.c
+ *
+ * V2V broker.
--+ *
+++ *
+ * Copyright (c) 2009 Jean Guyader
+ * Copyright (c) 2009 Citrix Systems, Inc.
+ *
+ err = v2v_connect(path, &ctx->channel, 0);
+ if (err)
+ {
- + DPRINTK("failure in connect() - err: %d\n", err);
-+ printk(V2VDEV_LOG" failure in connect() - err: %d\n", err);
+++ DPRINTK("failure in connect() - err: %d\n", err);
+ return err;
+ }
+
+ size_t count, loff_t *ppos)
+{
+ struct v2vdev_context *ctx = filp->private_data;
-+ ssize_t n, size;
-+ uint16_t tag;
-+
-+ if (ctx->last_err)
-+ return -ctx->last_err;
++ struct v2v_wait *wait_state;
++ size_t red=0;
++ size_t n;
++ int nonblock=filp->f_flags & O_NONBLOCK;
++ u8 reasons_mask = V2V_WAKE_REASON_CONTROL | V2V_WAKE_REASON_RECEIVE;
++ u8 reason;
++ enum v2v_endpoint_state state;
+
-+ size = MIN(count, ctx->buff_size);
-+ n = copy_to_user(buf, ctx->buff, size);
-+ ctx->buff_size -= size;
-+ if (ctx->buff_size == 0)
-+ {
-+ kfree(ctx->buff);
-+ ctx->buff = NULL;
-+ }
-+ else
-+ ctx->buff += size;
++ DUMP_CTX(ctx);
- + if (!ctx->connected)
+++ if (!ctx->connected)
++ return -ENOTCONN;
++
++ while (count) {
++
++ if (!ctx->data_len) {
++
- + if (ctx->last_err)
+++ if (ctx->last_err)
++ return ctx->last_err;
++
++ if (nonblock && !v2v_receive_in_queue(ctx)) {
++ DPRINTK("v2vdev_read needed got %d/%d\n",red,count+red);
++ return red ? red:-EAGAIN;
++ }
- +
+++
++ wait_state = v2v_get_wait_state(ctx->channel);
++ wait_event(wait_state->wait_event,
++ atomic_xchg(&wait_state->wait_condition, 0) == 1);
++ reason = v2v_get_wake_reason(ctx->channel, reasons_mask);
++ if (reason & V2V_WAKE_REASON_CONTROL)
++ {
++ if (v2v_get_remote_state(ctx->channel, &state) == 0 &&
++ state != v2v_state_connected)
++ {
++ ctx->connected = 0;
++ v2v_disconnect(ctx->channel);
++ return 0;
++ }
++ }
++ v2vdev_message_get(ctx);
++ }
++ DUMP_CTX(ctx);
++
++ n=MIN(count,ctx->data_len);
++
++ if (n) {
++ if (copy_to_user(buf, ctx->data_ptr, n))
++ return -EFAULT;
++ red+=n;
++ count-=n;
++ ctx->data_ptr+=n;
++ ctx->data_len-=n;
++ buf+=n;
++
++ DUMP_CTX(ctx);
++ }
++ }
- +
+++
++ DPRINTK("v2vdev_read needed got %d/%d\n",red,red);
+
-+ v2v_nc2_finish_message(ctx->channel);
-+ v2v_set_wake_reason(ctx->channel, V2V_WAKE_REASON_RECEIVE);
-+ return size - n;
++ return red;
+}
+
+static ssize_t v2vdev_write(struct file *filp, const char __user *buf,
+ volatile void *msg;
+ int err;
+
-+ err = v2v_nc2_prep_message(ctx->channel, count, ctx->type, 0, &msg);
++ DUMP_CTX(ctx);
- + if (!ctx->connected)
+++ if (!ctx->connected)
++ return -ENOTCONN;
- +
+++
++ err = v2v_nc2_prep_message(ctx->channel, count, 1, 0, &msg);
+ if (err)
+ {
-+ printk(V2VDEV_LOG" failure in v2v_nc2_prep_message() - error: %d\n", err);
-+ return -EAGAIN;
-+ }
-+
-+ if (copy_from_user((void *)msg, buf, count) != 0)
-+ {
-+ printk(V2VDEV_LOG" failure in copy_from_user()\n");
-+ return 0;
++ DPRINTK("failure in v2v_nc2_prep_message() - error: %d\n", err);
++ return -EIO;
+ }
+
-+ hexdump(">", msg, count);
++ if (copy_from_user((void *)msg, buf, count))
++ return -EFAULT;
- +
+++
++ hexdump(">", (void *) msg, count);
+ v2v_nc2_send_messages(ctx->channel);
+ v2v_set_wake_reason(ctx->channel, V2V_WAKE_REASON_SEND);
+ return count;
+
+static long v2vdev_ioctl(struct file *filp,
+ unsigned int cmd, unsigned long arg)
--+{
-+ int rc;
-+ struct v2vdev_context *ctx = filp->private_data;
-+
+++{
++ int rc;
++ void __user *p = (void __user *)arg;
++ struct v2vdev_context *ctx = filp->private_data;
- +
+++
+ rc = -ENOSYS;
+ switch (cmd) {
+ default:
+ wait_state = v2v_get_wait_state(ctx->channel);
+ poll_wait(filp, &wait_state->wait_event, wait);
+
-+ if (!ctx->connected && ctx->listenner)
-+ if (v2v_accept(ctx->channel, 1) != EAGAIN)
++ if (ctx->connected)
++ reasons_mask |= V2V_WAKE_REASON_RECEIVE;
++
++ reason = v2v_get_wake_reason(ctx->channel, reasons_mask);
++ if (reason & V2V_WAKE_REASON_CONTROL)
++ {
++ if (!ctx->connected) {
++ err = v2v_get_remote_state(ctx->channel, &state);
++ if (ctx->listenner && (err == 0 && state == v2v_state_connected) &&
++ v2v_accept(ctx->channel, 1) == 0)
++ {
++ v2vdev_wait_connected(ctx);
++ v2v_set_wake_reason(ctx->channel, V2V_WAKE_REASON_SEND);
++ DPRINTK("connected !\n");
++ return 0;
++ }
++ }
++ else
+ {
-+ v2vdev_wait_connected(ctx);
-+ printk(V2VDEV_LOG" connected !\n");
-+ return 0;
++ err = v2v_get_remote_state(ctx->channel, &state);
++ if (err == 0 && ctx->connected && state != v2v_state_connected)
++ {
- + DPRINTK("Remote end %s, v2v_disconnect\n", v2v_endpoint_state_name(state));
+++ DPRINTK("Remote end %s, v2v_disconnect\n", v2v_endpoint_state_name(state));
++ ctx->connected = 0;
++ v2v_disconnect(ctx->channel);
++ return POLLIN | POLLRDNORM;
++ }
+ }
++ }
++ else if (reason & V2V_WAKE_REASON_RECEIVE)
++ {
++ DUMP_CTX(ctx);
++ v2vdev_message_get(ctx);
++ }
++
++ if (ctx->data_len)
++ mask = POLLIN | POLLRDNORM;
++
+
-+ reason = v2v_get_wake_reason(ctx->channel, reasons_mask);
-+ if (reason & V2V_WAKE_REASON_RECEIVE)
-+ if (v2vdev_message_get(ctx) == 0)
-+ mask = POLLIN | POLLRDNORM;
+ return mask;
+}
+
+
+ err = misc_register(&v2vdev_miscdev);
+ if (err != 0) {
-+ printk(KERN_ALERT "Could not register /dev/v2v\n");
++ DPRINTK(KERN_ALERT "Could not register /dev/v2v\n");
+ return err;
+ }
--+
-+ printk("Xen V2V device installed.\n");
+++
++ DPRINTK("Xen V2V device installed.\n");
+
+ return 0;
+}