[PATCH 02/12] VMCI: datagram implementation.
VMCI datagram Implements datagrams to allow data to be sent between host and guest. Signed-off-by: George Zhang georgezh...@vmware.com Acked-by: Andy king ack...@vmware.com Acked-by: Dmitry Torokhov d...@vmware.com --- drivers/misc/vmw_vmci/vmci_datagram.c | 500 + drivers/misc/vmw_vmci/vmci_datagram.h | 52 +++ 2 files changed, 552 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..ed5c433 --- /dev/null +++ b/drivers/misc/vmw_vmci/vmci_datagram.c @@ -0,0 +1,500 @@ +/* + * 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. + */ + +#include linux/vmw_vmci_defs.h +#include linux/vmw_vmci_api.h +#include linux/module.h +#include linux/sched.h +#include linux/slab.h +#include linux/bug.h + +#include vmci_datagram.h +#include vmci_resource.h +#include vmci_context.h +#include vmci_driver.h +#include vmci_event.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; + u32 flags; + bool run_delayed; + vmci_datagram_recv_cb recv_cb; + void *client_data; + u32 priv_flags; +}; + +struct delayed_datagram_info { + struct datagram_entry *entry; + struct vmci_datagram msg; + struct work_struct work; + bool in_dg_host_queue; +}; + +/* Number of in-flight host-host datagrams */ +static atomic_t delayed_dg_host_queue_size = ATOMIC_INIT(0); + +/* + * Create a datagram entry given a handle pointer. + */ +static int dg_create_handle(u32 resource_id, + u32 flags, + u32 priv_flags, + vmci_datagram_recv_cb recv_cb, + void *client_data, struct vmci_handle *out_handle) +{ + int result; + u32 context_id; + struct vmci_handle handle; + struct datagram_entry *entry; + + if ((flags VMCI_FLAG_WELLKNOWN_DG_HND) != 0) + return VMCI_ERROR_INVALID_ARGS; + + if ((flags VMCI_FLAG_ANYCID_DG_HND) != 0) { + context_id = VMCI_INVALID_ID; + } else { + context_id = vmci_get_context_id(); + if (context_id == VMCI_INVALID_ID) + return VMCI_ERROR_NO_RESOURCES; + } + + handle = vmci_make_handle(context_id, resource_id); + + entry = kmalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) { + pr_warn(Failed allocating memory for datagram entry\n); + return VMCI_ERROR_NO_MEM; + } + + entry-run_delayed = (flags VMCI_FLAG_DG_DELAYED_CB) ? true : false; + entry-flags = flags; + entry-recv_cb = recv_cb; + entry-client_data = client_data; + entry-priv_flags = priv_flags; + + /* Make datagram resource live. */ + result = vmci_resource_add(entry-resource, + VMCI_RESOURCE_TYPE_DATAGRAM, + handle); + if (result != VMCI_SUCCESS) { + pr_warn(Failed to add new resource (handle=0x%x:0x%x), error: %d\n, + handle.context, handle.resource, result); + kfree(entry); + return result; + } + + *out_handle = vmci_resource_handle(entry-resource); + return VMCI_SUCCESS; +} + +/* + * Internal utility function with the same purpose as + * vmci_datagram_get_priv_flags that also takes a context_id. + */ +static int vmci_datagram_get_priv_flags(u32 context_id, + struct vmci_handle handle, + u32 *priv_flags) +{ + if (context_id == VMCI_INVALID_ID) + return VMCI_ERROR_INVALID_ARGS; + + if (context_id == VMCI_HOST_CONTEXT_ID) { + struct datagram_entry *src_entry; + struct vmci_resource *resource; + + resource = vmci_resource_by_handle(handle, + VMCI_RESOURCE_TYPE_DATAGRAM); + if (!resource) + return VMCI_ERROR_INVALID_ARGS; + + src_entry = container_of(resource, struct datagram_entry, +
[PATCH 02/12] VMCI: datagram implementation.
VMCI datagram Implements datagrams to allow data to be sent between host and guest. Signed-off-by: George Zhang georgezh...@vmware.com Signed-off-by: Dmitry Torokhov d...@vmware.com Signed-off-by: Andy King ack...@vmware.com --- drivers/misc/vmw_vmci/vmci_datagram.c | 501 + drivers/misc/vmw_vmci/vmci_datagram.h | 52 +++ 2 files changed, 553 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..a6513f4 --- /dev/null +++ b/drivers/misc/vmw_vmci/vmci_datagram.c @@ -0,0 +1,501 @@ +/* + * 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. + */ + +#include linux/vmw_vmci_defs.h +#include linux/vmw_vmci_api.h +#include linux/module.h +#include linux/sched.h +#include linux/slab.h +#include linux/bug.h + +#include vmci_common_int.h +#include vmci_datagram.h +#include vmci_resource.h +#include vmci_context.h +#include vmci_driver.h +#include vmci_event.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; + u32 flags; + bool run_delayed; + vmci_datagram_recv_cb recv_cb; + void *client_data; + u32 priv_flags; +}; + +struct delayed_datagram_info { + struct datagram_entry *entry; + struct vmci_datagram msg; + struct work_struct work; + bool in_dg_host_queue; +}; + +/* Number of in-flight host-host datagrams */ +static atomic_t delayed_dg_host_queue_size = ATOMIC_INIT(0); + +/* + * Create a datagram entry given a handle pointer. + */ +static int dg_create_handle(u32 resource_id, + u32 flags, + u32 priv_flags, + vmci_datagram_recv_cb recv_cb, + void *client_data, struct vmci_handle *out_handle) +{ + int result; + u32 context_id; + struct vmci_handle handle; + struct datagram_entry *entry; + + if ((flags VMCI_FLAG_WELLKNOWN_DG_HND) != 0) + return VMCI_ERROR_INVALID_ARGS; + + if ((flags VMCI_FLAG_ANYCID_DG_HND) != 0) { + context_id = VMCI_INVALID_ID; + } else { + context_id = vmci_get_context_id(); + if (context_id == VMCI_INVALID_ID) + return VMCI_ERROR_NO_RESOURCES; + } + + handle = vmci_make_handle(context_id, resource_id); + + entry = kmalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) { + pr_warn(Failed allocating memory for datagram entry.\n); + return VMCI_ERROR_NO_MEM; + } + + entry-run_delayed = (flags VMCI_FLAG_DG_DELAYED_CB) ? true : false; + entry-flags = flags; + entry-recv_cb = recv_cb; + entry-client_data = client_data; + entry-priv_flags = priv_flags; + + /* Make datagram resource live. */ + result = vmci_resource_add(entry-resource, + VMCI_RESOURCE_TYPE_DATAGRAM, + handle); + if (result != VMCI_SUCCESS) { + pr_warn(Failed to add new resource (handle=0x%x:0x%x), error: %d\n, + handle.context, handle.resource, result); + kfree(entry); + return result; + } + + *out_handle = vmci_resource_handle(entry-resource); + return VMCI_SUCCESS; +} + +/* + * Internal utility function with the same purpose as + * vmci_datagram_get_priv_flags that also takes a context_id. + */ +static int vmci_datagram_get_priv_flags(u32 context_id, + struct vmci_handle handle, + u32 *priv_flags) +{ + if (context_id == VMCI_INVALID_ID) + return VMCI_ERROR_INVALID_ARGS; + + if (context_id == VMCI_HOST_CONTEXT_ID) { + struct datagram_entry *src_entry; + struct vmci_resource *resource; + + resource = vmci_resource_by_handle(handle, + VMCI_RESOURCE_TYPE_DATAGRAM); + if (!resource) + return VMCI_ERROR_INVALID_ARGS; + + src_entry = container_of(resource, struct
[PATCH 02/12] VMCI: datagram implementation.
VMCI datagram Implements datagrams to allow data to be sent between host and guest. Signed-off-by: George Zhang georgezh...@vmware.com --- drivers/misc/vmw_vmci/vmci_datagram.c | 506 + drivers/misc/vmw_vmci/vmci_datagram.h | 52 +++ 2 files changed, 558 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..d755e31 --- /dev/null +++ b/drivers/misc/vmw_vmci/vmci_datagram.c @@ -0,0 +1,506 @@ +/* + * 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. + */ + +#include linux/vmw_vmci_defs.h +#include linux/vmw_vmci_api.h +#include linux/module.h +#include linux/sched.h +#include linux/slab.h +#include linux/bug.h + +#include vmci_common_int.h +#include vmci_datagram.h +#include vmci_resource.h +#include vmci_context.h +#include vmci_driver.h +#include vmci_event.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; + u32 flags; + bool run_delayed; + vmci_datagram_recv_cb recv_cb; + void *client_data; + u32 priv_flags; +}; + +struct delayed_datagram_info { + struct datagram_entry *entry; + struct vmci_datagram msg; + struct work_struct work; + bool in_dg_host_queue; +}; + +/* Number of in-flight host-host datagrams */ +static atomic_t delayed_dg_host_queue_size = ATOMIC_INIT(0); + +/* + * Create a datagram entry given a handle pointer. + */ +static int dg_create_handle(u32 resource_id, + u32 flags, + u32 priv_flags, + vmci_datagram_recv_cb recv_cb, + void *client_data, struct vmci_handle *out_handle) +{ + int result; + u32 context_id; + struct vmci_handle handle; + struct datagram_entry *entry; + + BUG_ON(!recv_cb); + BUG_ON(!out_handle); + BUG_ON(priv_flags ~VMCI_PRIVILEGE_ALL_FLAGS); + + if ((flags VMCI_FLAG_WELLKNOWN_DG_HND) != 0) + return VMCI_ERROR_INVALID_ARGS; + + if ((flags VMCI_FLAG_ANYCID_DG_HND) != 0) { + context_id = VMCI_INVALID_ID; + } else { + context_id = vmci_get_context_id(); + if (context_id == VMCI_INVALID_ID) + return VMCI_ERROR_NO_RESOURCES; + } + + handle = vmci_make_handle(context_id, resource_id); + + entry = kmalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) { + pr_warn(Failed allocating memory for datagram entry.\n); + return VMCI_ERROR_NO_MEM; + } + + entry-run_delayed = (flags VMCI_FLAG_DG_DELAYED_CB) ? true : false; + entry-flags = flags; + entry-recv_cb = recv_cb; + entry-client_data = client_data; + entry-priv_flags = priv_flags; + + /* Make datagram resource live. */ + result = vmci_resource_add(entry-resource, + VMCI_RESOURCE_TYPE_DATAGRAM, + handle); + if (result != VMCI_SUCCESS) { + pr_warn(Failed to add new resource (handle=0x%x:0x%x), error: %d\n, + handle.context, handle.resource, result); + kfree(entry); + return result; + } + + *out_handle = vmci_resource_handle(entry-resource); + return VMCI_SUCCESS; +} + +/* + * Internal utility function with the same purpose as + * vmci_datagram_get_priv_flags that also takes a context_id. + */ +static int vmci_datagram_get_priv_flags(u32 context_id, + struct vmci_handle handle, + u32 *priv_flags) +{ + if (context_id == VMCI_INVALID_ID) + return VMCI_ERROR_INVALID_ARGS; + + if (context_id == VMCI_HOST_CONTEXT_ID) { + struct datagram_entry *src_entry; + struct vmci_resource *resource; + + resource = vmci_resource_by_handle(handle, + VMCI_RESOURCE_TYPE_DATAGRAM); + if (!resource) + return VMCI_ERROR_INVALID_ARGS; + + src_entry =