[vmw_vmci 02/11] Apply VMCI datagram code
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
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) { +