[vmw_vmci 02/11] Apply VMCI datagram code

2012-07-26 Thread Andrew Stiegmann (stieg)
Implements datagrams to allow data to be sent between host
and guest.

Signed-off-by: Andrew Stiegmann (stieg) 
---
 drivers/misc/vmw_vmci/vmci_datagram.c |  586 +
 drivers/misc/vmw_vmci/vmci_datagram.h |   56 
 2 files changed, 642 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_datagram.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_datagram.h

diff --git a/drivers/misc/vmw_vmci/vmci_datagram.c 
b/drivers/misc/vmw_vmci/vmci_datagram.c
new file mode 100644
index 000..a804f99
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_datagram.c
@@ -0,0 +1,586 @@
+/*
+ * VMware VMCI Driver
+ *
+ * Copyright (C) 2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vmci_common_int.h"
+#include "vmci_context.h"
+#include "vmci_datagram.h"
+#include "vmci_driver.h"
+#include "vmci_event.h"
+#include "vmci_hash_table.h"
+#include "vmci_resource.h"
+#include "vmci_route.h"
+
+/*
+ * struct datagram_entry describes the datagram entity. It is used for datagram
+ * entities created only on the host.
+ */
+struct datagram_entry {
+   struct vmci_resource resource;
+   uint32_t flags;
+   bool runDelayed;
+   VMCIDatagramRecvCB recvCB;
+   void *clientData;
+   wait_queue_head_t destroyEvent;
+   uint32_t privFlags;
+};
+
+struct delayed_datagram_info {
+   bool inDGHostQueue;
+   struct datagram_entry *entry;
+   struct vmci_dg msg;
+};
+
+static atomic_t delayedDGHostQueueSize;
+
+static void dg_free_cb(void *clientData)
+{
+   struct datagram_entry *entry = (struct datagram_entry *)clientData;
+   ASSERT(entry);
+
+   /*
+* Entry is freed in VMCIDatagram_DestroyHnd, who waits for
+* the signal.
+*/
+   wake_up(>destroyEvent);
+}
+
+static int dg_release_cb(void *clientData)
+{
+   struct datagram_entry *entry = (struct datagram_entry *)clientData;
+   ASSERT(entry);
+   vmci_resource_release(>resource);
+   return 0;
+}
+
+/*
+ * Create a datagram entry given a handle pointer.
+ */
+static int dg_create_handle(uint32_t resourceID,
+   uint32_t flags,
+   uint32_t privFlags,
+   VMCIDatagramRecvCB recvCB,
+   void *clientData,
+   struct vmci_handle *outHandle)
+{
+   int result;
+   uint32_t contextID;
+   struct vmci_handle handle;
+   struct datagram_entry *entry;
+
+   ASSERT(recvCB != NULL);
+   ASSERT(outHandle != NULL);
+   ASSERT(!(privFlags & ~VMCI_PRIVILEGE_ALL_FLAGS));
+
+   if ((flags & VMCI_FLAG_WELLKNOWN_DG_HND) != 0) {
+   return VMCI_ERROR_INVALID_ARGS;
+   } else {
+   if ((flags & VMCI_FLAG_ANYCID_DG_HND) != 0) {
+   contextID = VMCI_INVALID_ID;
+   } else {
+   contextID = VMCI_GetContextID();
+   if (contextID == VMCI_INVALID_ID)
+   return VMCI_ERROR_NO_RESOURCES;
+   }
+
+   if (resourceID == VMCI_INVALID_ID) {
+   resourceID = vmci_resource_get_id(contextID);
+   if (resourceID == VMCI_INVALID_ID)
+   return VMCI_ERROR_NO_HANDLE;
+   }
+
+   handle = vmci_make_handle(contextID, resourceID);
+   }
+
+   entry = kmalloc(sizeof *entry, GFP_KERNEL);
+   if (entry == NULL) {
+   pr_warn("Failed allocating memory for datagram entry.");
+   return VMCI_ERROR_NO_MEM;
+   }
+
+   entry->runDelayed = (flags & VMCI_FLAG_DG_DELAYED_CB) ? true : false;
+   entry->flags = flags;
+   entry->recvCB = recvCB;
+   entry->clientData = clientData;
+   init_waitqueue_head(>destroyEvent);
+   entry->privFlags = privFlags;
+
+   /* Make datagram resource live. */
+   result = vmci_resource_add(>resource,
+  VMCI_RESOURCE_TYPE_DATAGRAM,
+  handle, dg_free_cb, entry);
+   if (result != VMCI_SUCCESS) {
+   pr_warn("Failed to add new resource (handle=0x%x:0x%x).",
+   

[vmw_vmci 02/11] Apply VMCI datagram code

2012-07-26 Thread Andrew Stiegmann (stieg)
Implements datagrams to allow data to be sent between host
and guest.

Signed-off-by: Andrew Stiegmann (stieg) astiegm...@vmware.com
---
 drivers/misc/vmw_vmci/vmci_datagram.c |  586 +
 drivers/misc/vmw_vmci/vmci_datagram.h |   56 
 2 files changed, 642 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/vmw_vmci/vmci_datagram.c
 create mode 100644 drivers/misc/vmw_vmci/vmci_datagram.h

diff --git a/drivers/misc/vmw_vmci/vmci_datagram.c 
b/drivers/misc/vmw_vmci/vmci_datagram.c
new file mode 100644
index 000..a804f99
--- /dev/null
+++ b/drivers/misc/vmw_vmci/vmci_datagram.c
@@ -0,0 +1,586 @@
+/*
+ * VMware VMCI Driver
+ *
+ * Copyright (C) 2012 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include linux/bug.h
+#include linux/module.h
+#include linux/sched.h
+#include linux/vmw_vmci_api.h
+#include linux/vmw_vmci_defs.h
+
+#include vmci_common_int.h
+#include vmci_context.h
+#include vmci_datagram.h
+#include vmci_driver.h
+#include vmci_event.h
+#include vmci_hash_table.h
+#include vmci_resource.h
+#include vmci_route.h
+
+/*
+ * struct datagram_entry describes the datagram entity. It is used for datagram
+ * entities created only on the host.
+ */
+struct datagram_entry {
+   struct vmci_resource resource;
+   uint32_t flags;
+   bool runDelayed;
+   VMCIDatagramRecvCB recvCB;
+   void *clientData;
+   wait_queue_head_t destroyEvent;
+   uint32_t privFlags;
+};
+
+struct delayed_datagram_info {
+   bool inDGHostQueue;
+   struct datagram_entry *entry;
+   struct vmci_dg msg;
+};
+
+static atomic_t delayedDGHostQueueSize;
+
+static void dg_free_cb(void *clientData)
+{
+   struct datagram_entry *entry = (struct datagram_entry *)clientData;
+   ASSERT(entry);
+
+   /*
+* Entry is freed in VMCIDatagram_DestroyHnd, who waits for
+* the signal.
+*/
+   wake_up(entry-destroyEvent);
+}
+
+static int dg_release_cb(void *clientData)
+{
+   struct datagram_entry *entry = (struct datagram_entry *)clientData;
+   ASSERT(entry);
+   vmci_resource_release(entry-resource);
+   return 0;
+}
+
+/*
+ * Create a datagram entry given a handle pointer.
+ */
+static int dg_create_handle(uint32_t resourceID,
+   uint32_t flags,
+   uint32_t privFlags,
+   VMCIDatagramRecvCB recvCB,
+   void *clientData,
+   struct vmci_handle *outHandle)
+{
+   int result;
+   uint32_t contextID;
+   struct vmci_handle handle;
+   struct datagram_entry *entry;
+
+   ASSERT(recvCB != NULL);
+   ASSERT(outHandle != NULL);
+   ASSERT(!(privFlags  ~VMCI_PRIVILEGE_ALL_FLAGS));
+
+   if ((flags  VMCI_FLAG_WELLKNOWN_DG_HND) != 0) {
+   return VMCI_ERROR_INVALID_ARGS;
+   } else {
+   if ((flags  VMCI_FLAG_ANYCID_DG_HND) != 0) {
+   contextID = VMCI_INVALID_ID;
+   } else {
+   contextID = VMCI_GetContextID();
+   if (contextID == VMCI_INVALID_ID)
+   return VMCI_ERROR_NO_RESOURCES;
+   }
+
+   if (resourceID == VMCI_INVALID_ID) {
+   resourceID = vmci_resource_get_id(contextID);
+   if (resourceID == VMCI_INVALID_ID)
+   return VMCI_ERROR_NO_HANDLE;
+   }
+
+   handle = vmci_make_handle(contextID, resourceID);
+   }
+
+   entry = kmalloc(sizeof *entry, GFP_KERNEL);
+   if (entry == NULL) {
+   pr_warn(Failed allocating memory for datagram entry.);
+   return VMCI_ERROR_NO_MEM;
+   }
+
+   entry-runDelayed = (flags  VMCI_FLAG_DG_DELAYED_CB) ? true : false;
+   entry-flags = flags;
+   entry-recvCB = recvCB;
+   entry-clientData = clientData;
+   init_waitqueue_head(entry-destroyEvent);
+   entry-privFlags = privFlags;
+
+   /* Make datagram resource live. */
+   result = vmci_resource_add(entry-resource,
+  VMCI_RESOURCE_TYPE_DATAGRAM,
+  handle, dg_free_cb, entry);
+   if (result != VMCI_SUCCESS) {
+