diff mbox

[6/8] libpvrdma: Add main library file

Message ID 1478216677-6150-7-git-send-email-aditr@vmware.com (mailing list archive)
State Accepted
Headers show

Commit Message

Adit Ranadive Nov. 3, 2016, 11:44 p.m. UTC
Registers the pvrdma library with libibverbs and allocates the user context.

Signed-off-by: Adit Ranadive <aditr@vmware.com>
---
 providers/pvrdma/pvrdma_main.c | 214 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 214 insertions(+)
 create mode 100644 providers/pvrdma/pvrdma_main.c
diff mbox

Patch

diff --git a/providers/pvrdma/pvrdma_main.c b/providers/pvrdma/pvrdma_main.c
new file mode 100644
index 0000000..909cf1e
--- /dev/null
+++ b/providers/pvrdma/pvrdma_main.c
@@ -0,0 +1,214 @@ 
+/*
+ * Copyright (c) 2012-2016 VMware, Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of EITHER the GNU General Public License
+ * version 2 as published by the Free Software Foundation or the BSD
+ * 2-Clause License. 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 version 2 for more details at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program available in the file COPYING in the main
+ * directory of this source tree.
+ *
+ * The BSD 2-Clause License
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "pvrdma.h"
+
+static struct ibv_context_ops pvrdma_ctx_ops = {
+	.query_device = pvrdma_query_device,
+	.query_port = pvrdma_query_port,
+	.alloc_pd = pvrdma_alloc_pd,
+	.dealloc_pd = pvrdma_free_pd,
+
+	.reg_mr = pvrdma_reg_mr,
+	.dereg_mr = pvrdma_dereg_mr,
+	.create_cq = pvrdma_create_cq,
+	.poll_cq = pvrdma_poll_cq,
+	.req_notify_cq = pvrdma_req_notify_cq,
+	.destroy_cq = pvrdma_destroy_cq,
+
+	.create_qp = pvrdma_create_qp,
+	.query_qp = pvrdma_query_qp,
+	.modify_qp = pvrdma_modify_qp,
+	.destroy_qp = pvrdma_destroy_qp,
+
+	.post_send = pvrdma_post_send,
+	.post_recv = pvrdma_post_recv,
+	.create_ah = pvrdma_create_ah,
+	.destroy_ah = pvrdma_destroy_ah,
+};
+
+int pvrdma_alloc_buf(struct pvrdma_buf *buf, size_t size, int page_size)
+{
+	int ret;
+
+	buf->length = align(size, page_size);
+	buf->buf = mmap(NULL, buf->length, PROT_READ | PROT_WRITE,
+			MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	if (buf->buf == MAP_FAILED)
+		return errno;
+
+	ret = ibv_dontfork_range(buf->buf, size);
+	if (ret)
+		munmap(buf->buf, buf->length);
+
+	return ret;
+}
+
+void pvrdma_free_buf(struct pvrdma_buf *buf)
+{
+	ibv_dofork_range(buf->buf, buf->length);
+	munmap(buf->buf, buf->length);
+}
+
+static int pvrdma_init_context_shared(struct pvrdma_context *context,
+				      struct ibv_device *ibdev,
+				      int cmd_fd)
+{
+	struct ibv_get_context cmd;
+	struct pvrdma_alloc_ucontext_resp resp;
+
+	context->ibv_ctx.cmd_fd = cmd_fd;
+	if (ibv_cmd_get_context(&context->ibv_ctx, &cmd, sizeof(cmd),
+				&resp.ibv_resp, sizeof(resp)))
+		return errno;
+
+	context->qp_tbl = calloc(resp.qp_tab_size & 0xFFFF,
+				 sizeof(struct pvrdma_qp *));
+	if (!context->qp_tbl)
+		return -ENOMEM;
+
+	context->uar = mmap(NULL, to_vdev(ibdev)->page_size, PROT_WRITE,
+			    MAP_SHARED, cmd_fd, 0);
+	if (context->uar == MAP_FAILED) {
+		free(context->qp_tbl);
+		return errno;
+	}
+
+	pthread_spin_init(&context->uar_lock, PTHREAD_PROCESS_PRIVATE);
+	context->ibv_ctx.ops = pvrdma_ctx_ops;
+
+	return 0;
+}
+
+static void pvrdma_free_context_shared(struct pvrdma_context *context,
+				       struct pvrdma_device *dev)
+{
+	munmap(context->uar, dev->page_size);
+	free(context->qp_tbl);
+}
+
+static struct ibv_context *pvrdma_alloc_context(struct ibv_device *ibdev,
+						int cmd_fd)
+{
+	struct pvrdma_context *context;
+
+	context = malloc(sizeof(*context));
+	if (!context)
+		return NULL;
+
+	memset(context, 0, sizeof(*context));
+
+	if (pvrdma_init_context_shared(context, ibdev, cmd_fd)) {
+		free(context);
+		return NULL;
+	}
+
+	return &context->ibv_ctx;
+}
+
+static void pvrdma_free_context(struct ibv_context *ibctx)
+{
+	struct pvrdma_context *context = to_vctx(ibctx);
+
+	pvrdma_free_context_shared(context, to_vdev(ibctx->device));
+	free(context);
+}
+
+static struct ibv_device_ops pvrdma_dev_ops = {
+	.alloc_context = pvrdma_alloc_context,
+	.free_context  = pvrdma_free_context
+};
+
+static struct pvrdma_device *pvrdma_driver_init_shared(
+						const char *uverbs_sys_path,
+						int abi_version)
+{
+	struct pvrdma_device *dev;
+	char name[16];
+
+	/* We support only a single ABI version for now. */
+	if (abi_version != PVRDMA_UVERBS_ABI_VERSION) {
+		fprintf(stderr, PFX "ABI version %d of %s is not "
+			"supported (supported %d)\n",
+			abi_version, uverbs_sys_path,
+			PVRDMA_UVERBS_ABI_VERSION);
+		return NULL;
+	}
+
+	if (ibv_read_sysfs_file(uverbs_sys_path,
+				"ibdev", name, sizeof(name)) < 0) {
+		fprintf(stderr, PFX "not ib device\n");
+		return NULL;
+	}
+
+	dev = malloc(sizeof(*dev));
+	if (!dev) {
+		fprintf(stderr, PFX "couldn't allocate device for %s\n",
+			uverbs_sys_path);
+		return NULL;
+	}
+
+	dev->abi_version = abi_version;
+	dev->page_size   = sysconf(_SC_PAGESIZE);
+	dev->ibv_dev.ops = pvrdma_dev_ops;
+
+	return dev;
+}
+
+static struct ibv_device *pvrdma_driver_init(const char *uverbs_sys_path,
+					     int abi_version)
+{
+	struct pvrdma_device *dev = pvrdma_driver_init_shared(uverbs_sys_path,
+							      abi_version);
+	if (!dev)
+		return NULL;
+
+	return &dev->ibv_dev;
+}
+
+static __attribute__((constructor)) void pvrdma_register_driver(void)
+{
+	ibv_register_driver("pvrdma", pvrdma_driver_init);
+}