All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V8 libibverbs 0/7] Add extension and XRC QP support
@ 2013-07-25  8:38 Yishai Hadas
       [not found] ` <1374741488-30895-1-git-send-email-yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
  0 siblings, 1 reply; 15+ messages in thread
From: Yishai Hadas @ 2013-07-25  8:38 UTC (permalink / raw)
  To: linux-rdma-u79uwXL29TY76Z2rM5mHXA, roland-BHEL68pLQRGGvPXPguhicg
  Cc: ogerlitz-VPRAkNaXOzVWk0Htik3J/w, tzahio-VPRAkNaXOzVWk0Htik3J/w,
	yishaih-VPRAkNaXOzVWk0Htik3J/w

Extend XRC support to user space through libibverbs.  Because XRC requires
new verbs and extensions to existing verbs, we first introduce a generic
mechanism for extending verbs in a backward compatible manner.  XRC support
is built on top of that infrastructure.

Changes from v7:
Fix "container_of" macro to enable applications to compile with c99 standard (-std=c99).
Remove place holder for 6 function pointers in verbs_context.
Added an helper macro verbs_set_ctx_op to be used by providers to hook their extended functions.

Changes from v6:
Bug fixes, details in relevant patches.
ABI support with OFED release, added place holder for 6 function pointers
 in verbs_context to enable ABI compatibility with OFED release that already 
 used 6 extended verbs before XRC. 
Man pages were added.


Jay Sternberg (1):
  Add XRC sample application

Sean Hefty (5):
  Introduce XRC domains
  Add support for XRC SRQs
  Add support for XRC QPs
  Add ibv_open_qp
  XRC man pages

Yishai Hadas (1):
  Infrastructure to support verbs extensions

 Makefile.am                   |   12 +-
 examples/xsrq_pingpong.c      |  890 +++++++++++++++++++++++++++++++++++++++++
 include/infiniband/driver.h   |   72 ++++
 include/infiniband/kern-abi.h |  112 ++++--
 include/infiniband/verbs.h    |  256 ++++++++++++-
 man/ibv_create_qp_ex.3        |   83 ++++
 man/ibv_create_srq_ex.3       |   71 ++++
 man/ibv_get_srq_num.3         |   32 ++
 man/ibv_open_qp.3             |   51 +++
 man/ibv_open_xrcd.3           |   76 ++++
 src/cmd.c                     |  391 ++++++++++++------
 src/device.c                  |   53 ++-
 src/init.c                    |   41 ++-
 src/kern_abi.h                |  101 -----
 src/libibverbs.map            |    8 +
 15 files changed, 1953 insertions(+), 296 deletions(-)
 create mode 100644 examples/xsrq_pingpong.c
 create mode 100644 man/ibv_create_qp_ex.3
 create mode 100644 man/ibv_create_srq_ex.3
 create mode 100644 man/ibv_get_srq_num.3
 create mode 100644 man/ibv_open_qp.3
 create mode 100644 man/ibv_open_xrcd.3
 delete mode 100644 src/kern_abi.h

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH V8 libibverbs 1/7] Infrastructure to support verbs extensions
       [not found] ` <1374741488-30895-1-git-send-email-yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
@ 2013-07-25  8:38   ` Yishai Hadas
       [not found]     ` <1374741488-30895-2-git-send-email-yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
  2013-07-25  8:38   ` [PATCH V8 libibverbs 2/7] Introduce XRC domains Yishai Hadas
                     ` (5 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Yishai Hadas @ 2013-07-25  8:38 UTC (permalink / raw)
  To: linux-rdma-u79uwXL29TY76Z2rM5mHXA, roland-BHEL68pLQRGGvPXPguhicg
  Cc: ogerlitz-VPRAkNaXOzVWk0Htik3J/w, tzahio-VPRAkNaXOzVWk0Htik3J/w,
	yishaih-VPRAkNaXOzVWk0Htik3J/w, Sean Hefty

Infrastructure to support extended verbs capabilities in a forward/backward
manner.

Support for extensions is determeind by the provider calling
verbs_register_driver in place of ibv_register_driver.  When
extensions are enabled, ibverbs sets the current alloc_context /
free_context device operations to NULL.  These are used to
indicate that the struct ibv_device may be cast to struct
verbs_device.

With extensions, ibverbs allocates the ibv_context structure
and calls into the provider to initialize it.  The init call
is part of the verbs_device struct.

The abi_compat field of struct ibv_context is used to determine
support of verbs extensions.  As a result, support for ABI version <
2 is removed (corresponds to kernel releases 2.6.11-2.6.14 no
longer being supported).  The lowest ABI now supported is 3 (really
4 since 2.6.15 was ABI 4, I don't see that ABI 3 was in a release).

Signed-off-by: Yishai Hadas <yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Signed-off-by: Tzahi Oved <tzahio-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Signed-off-by: Sean Hefty <sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---

Change from v7:
Added an helper macro for v.ext, named verbs_set_ctx_op, being used in
farther patches.
Fixed "container_of" to match c99 standard.

 include/infiniband/driver.h   |    3 +
 include/infiniband/kern-abi.h |   43 +--------------
 include/infiniband/verbs.h    |   60 ++++++++++++++++++++
 src/cmd.c                     |  125 +----------------------------------------
 src/device.c                  |   53 +++++++++++++----
 src/init.c                    |   41 +++++++++++--
 src/kern_abi.h                |  101 ---------------------------------
 src/libibverbs.map            |    1 +
 8 files changed, 142 insertions(+), 285 deletions(-)
 delete mode 100644 src/kern_abi.h

diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h
index 9a81416..f22f287 100644
--- a/include/infiniband/driver.h
+++ b/include/infiniband/driver.h
@@ -55,8 +55,11 @@
 
 typedef struct ibv_device *(*ibv_driver_init_func)(const char *uverbs_sys_path,
 						   int abi_version);
+typedef struct verbs_device *(*verbs_driver_init_func)(const char *uverbs_sys_path,
+						       int abi_version);
 
 void ibv_register_driver(const char *name, ibv_driver_init_func init_func);
+void verbs_register_driver(const char *name, verbs_driver_init_func init_func);
 int ibv_cmd_get_context(struct ibv_context *context, struct ibv_get_context *cmd,
 			size_t cmd_size, struct ibv_get_context_resp *resp,
 			size_t resp_size);
diff --git a/include/infiniband/kern-abi.h b/include/infiniband/kern-abi.h
index 619ea7e..e7f8981 100644
--- a/include/infiniband/kern-abi.h
+++ b/include/infiniband/kern-abi.h
@@ -45,7 +45,7 @@
 /*
  * The minimum and maximum kernel ABI that we can handle.
  */
-#define IB_USER_VERBS_MIN_ABI_VERSION	1
+#define IB_USER_VERBS_MIN_ABI_VERSION	3
 #define IB_USER_VERBS_MAX_ABI_VERSION	6
 
 enum {
@@ -806,47 +806,6 @@ enum {
 	IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL_V2 = -1,
 };
 
-struct ibv_destroy_cq_v1 {
-	__u32 command;
-	__u16 in_words;
-	__u16 out_words;
-	__u32 cq_handle;
-};
-
-struct ibv_destroy_qp_v1 {
-	__u32 command;
-	__u16 in_words;
-	__u16 out_words;
-	__u32 qp_handle;
-};
-
-struct ibv_destroy_srq_v1 {
-	__u32 command;
-	__u16 in_words;
-	__u16 out_words;
-	__u32 srq_handle;
-};
-
-struct ibv_get_context_v2 {
-	__u32 command;
-	__u16 in_words;
-	__u16 out_words;
-	__u64 response;
-	__u64 cq_fd_tab;
-	__u64 driver_data[0];
-};
-
-struct ibv_create_cq_v2 {
-	__u32 command;
-	__u16 in_words;
-	__u16 out_words;
-	__u64 response;
-	__u64 user_handle;
-	__u32 cqe;
-	__u32 event_handler;
-	__u64 driver_data[0];
-};
-
 struct ibv_modify_srq_v3 {
 	__u32 command;
 	__u16 in_words;
diff --git a/include/infiniband/verbs.h b/include/infiniband/verbs.h
index 4b1ab57..ca300af 100644
--- a/include/infiniband/verbs.h
+++ b/include/infiniband/verbs.h
@@ -38,6 +38,7 @@
 
 #include <stdint.h>
 #include <pthread.h>
+#include <stddef.h>
 
 #ifdef __cplusplus
 #  define BEGIN_C_DECLS extern "C" {
@@ -63,6 +64,20 @@ union ibv_gid {
 	} global;
 };
 
+#ifndef container_of
+/**
+  * container_of - cast a member of a structure out to the containing structure
+  * @ptr:        the pointer to the member.
+  * @type:       the type of the container struct this is embedded in.
+  * @member:     the name of the member within the struct.
+  *
+ */
+#define container_of(ptr, type, member) \
+	((type *) ((char *)(ptr) - offsetof(type, member)))
+#endif
+
+#define vext_field_avail(type, fld, sz) (offsetof(type, fld) < (sz))
+
 enum ibv_node_type {
 	IBV_NODE_UNKNOWN	= -1,
 	IBV_NODE_CA 		= 1,
@@ -656,6 +671,17 @@ struct ibv_device {
 	char			ibdev_path[IBV_SYSFS_PATH_MAX];
 };
 
+struct verbs_device {
+	struct ibv_device device; /* Must be first */
+	size_t	sz;
+	size_t	size_of_context;
+	int	(*init_context)(struct verbs_device *device,
+				struct ibv_context *ctx, int cmd_fd);
+	void	(*uninit_context)(struct verbs_device *device,
+				struct ibv_context *ctx);
+	/* future fields added here */
+};
+
 struct ibv_context_ops {
 	int			(*query_device)(struct ibv_context *context,
 					      struct ibv_device_attr *device_attr);
@@ -724,6 +750,40 @@ struct ibv_context {
 	void		       *abi_compat;
 };
 
+enum verbs_context_mask {
+	VERBS_CONTEXT_RESERVED = 1 << 0
+};
+
+struct verbs_context {
+	/*  "grows up" - new fields go here */
+	uint64_t has_comp_mask;
+	size_t   sz;	/* Must be immediately before struct ibv_context */
+	struct ibv_context context;/* Must be last field in the struct */
+};
+
+static inline struct verbs_context *verbs_get_ctx(
+					const struct ibv_context *ctx)
+{
+	return (ctx->abi_compat != ((uint8_t *)NULL) - 1) ?
+		NULL : container_of(ctx, struct verbs_context, context);
+}
+
+#define verbs_get_ctx_op(ctx, op) ({ \
+	struct verbs_context *vctx = verbs_get_ctx(ctx); \
+	(!vctx || (vctx->sz < sizeof(*vctx) - offsetof(struct verbs_context, op)) || \
+	 !vctx->op) ? NULL : vctx; })
+
+#define verbs_set_ctx_op(vctx, op, ptr) ({ \
+	if (vctx && (vctx->sz >= sizeof(*vctx) - offsetof(struct verbs_context, op))) \
+		vctx->op = ptr; })
+
+static inline struct verbs_device *verbs_get_device(
+					const struct ibv_device *dev)
+{
+	return (dev->ops.alloc_context) ?
+		NULL : container_of(dev, struct verbs_device, device);
+}
+
 /**
  * ibv_get_device_list - Get list of IB devices currently available
  * @num_devices: optional.  if non-NULL, set to the number of devices
diff --git a/src/cmd.c b/src/cmd.c
index 9789092..86350fd 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -45,52 +45,13 @@
 
 #include "ibverbs.h"
 
-static int ibv_cmd_get_context_v2(struct ibv_context *context,
-				  struct ibv_get_context *new_cmd,
-				  size_t new_cmd_size,
-				  struct ibv_get_context_resp *resp,
-				  size_t resp_size)
-{
-	struct ibv_abi_compat_v2 *t;
-	struct ibv_get_context_v2 *cmd;
-	size_t cmd_size;
-	uint32_t cq_fd;
-
-	t = malloc(sizeof *t);
-	if (!t)
-		return ENOMEM;
-	pthread_mutex_init(&t->in_use, NULL);
-
-	cmd_size = sizeof *cmd + new_cmd_size - sizeof *new_cmd;
-	cmd      = alloca(cmd_size);
-	memcpy(cmd->driver_data, new_cmd->driver_data, new_cmd_size - sizeof *new_cmd);
-
-	IBV_INIT_CMD_RESP(cmd, cmd_size, GET_CONTEXT, resp, resp_size);
-	cmd->cq_fd_tab = (uintptr_t) &cq_fd;
-
-	if (write(context->cmd_fd, cmd, cmd_size) != cmd_size) {
-		free(t);
-		return errno;
-	}
-
-	(void) VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
-
-	context->async_fd         = resp->async_fd;
-	context->num_comp_vectors = 1;
-	t->channel.context        = context;
-	t->channel.fd		  = cq_fd;
-	t->channel.refcnt	  = 0;
-	context->abi_compat       = t;
-
-	return 0;
-}
 
 int ibv_cmd_get_context(struct ibv_context *context, struct ibv_get_context *cmd,
 			size_t cmd_size, struct ibv_get_context_resp *resp,
 			size_t resp_size)
 {
-	if (abi_ver <= 2)
-		return ibv_cmd_get_context_v2(context, cmd, cmd_size, resp, resp_size);
+	if (abi_ver < IB_USER_VERBS_MIN_ABI_VERSION)
+		return ENOSYS;
 
 	IBV_INIT_CMD_RESP(cmd, cmd_size, GET_CONTEXT, resp, resp_size);
 
@@ -274,45 +235,12 @@ int ibv_cmd_dereg_mr(struct ibv_mr *mr)
 	return 0;
 }
 
-static int ibv_cmd_create_cq_v2(struct ibv_context *context, int cqe,
-				struct ibv_cq *cq,
-				struct ibv_create_cq *new_cmd, size_t new_cmd_size,
-				struct ibv_create_cq_resp *resp, size_t resp_size)
-{
-	struct ibv_create_cq_v2 *cmd;
-	size_t cmd_size;
-
-	cmd_size = sizeof *cmd + new_cmd_size - sizeof *new_cmd;
-	cmd      = alloca(cmd_size);
-	memcpy(cmd->driver_data, new_cmd->driver_data, new_cmd_size - sizeof *new_cmd);
-
-	IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_CQ, resp, resp_size);
-	cmd->user_handle   = (uintptr_t) cq;
-	cmd->cqe           = cqe;
-	cmd->event_handler = 0;
-
-	if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
-		return errno;
-
-	(void) VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
-
-	cq->handle  = resp->cq_handle;
-	cq->cqe     = resp->cqe;
-	cq->context = context;
-
-	return 0;
-}
-
 int ibv_cmd_create_cq(struct ibv_context *context, int cqe,
 		      struct ibv_comp_channel *channel,
 		      int comp_vector, struct ibv_cq *cq,
 		      struct ibv_create_cq *cmd, size_t cmd_size,
 		      struct ibv_create_cq_resp *resp, size_t resp_size)
 {
-	if (abi_ver <= 2)
-		return ibv_cmd_create_cq_v2(context, cqe, cq,
-					    cmd, cmd_size, resp, resp_size);
-
 	IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_CQ, resp, resp_size);
 	cmd->user_handle   = (uintptr_t) cq;
 	cmd->cqe           = cqe;
@@ -397,7 +325,6 @@ int ibv_cmd_resize_cq(struct ibv_cq *cq, int cqe,
 		      struct ibv_resize_cq *cmd, size_t cmd_size,
 		      struct ibv_resize_cq_resp *resp, size_t resp_size)
 {
-
 	IBV_INIT_CMD_RESP(cmd, cmd_size, RESIZE_CQ, resp, resp_size);
 	cmd->cq_handle = cq->handle;
 	cmd->cqe       = cqe;
@@ -412,27 +339,11 @@ int ibv_cmd_resize_cq(struct ibv_cq *cq, int cqe,
 	return 0;
 }
 
-static int ibv_cmd_destroy_cq_v1(struct ibv_cq *cq)
-{
-	struct ibv_destroy_cq_v1 cmd;
-
-	IBV_INIT_CMD(&cmd, sizeof cmd, DESTROY_CQ);
-	cmd.cq_handle = cq->handle;
-
-	if (write(cq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
-		return errno;
-
-	return 0;
-}
-
 int ibv_cmd_destroy_cq(struct ibv_cq *cq)
 {
 	struct ibv_destroy_cq      cmd;
 	struct ibv_destroy_cq_resp resp;
 
-	if (abi_ver == 1)
-		return ibv_cmd_destroy_cq_v1(cq);
-
 	IBV_INIT_CMD_RESP(&cmd, sizeof cmd, DESTROY_CQ, &resp, sizeof resp);
 	cmd.cq_handle = cq->handle;
 	cmd.reserved  = 0;
@@ -557,27 +468,11 @@ int ibv_cmd_query_srq(struct ibv_srq *srq, struct ibv_srq_attr *srq_attr,
 	return 0;
 }
 
-static int ibv_cmd_destroy_srq_v1(struct ibv_srq *srq)
-{
-	struct ibv_destroy_srq_v1 cmd;
-
-	IBV_INIT_CMD(&cmd, sizeof cmd, DESTROY_SRQ);
-	cmd.srq_handle = srq->handle;
-
-	if (write(srq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
-		return errno;
-
-	return 0;
-}
-
 int ibv_cmd_destroy_srq(struct ibv_srq *srq)
 {
 	struct ibv_destroy_srq      cmd;
 	struct ibv_destroy_srq_resp resp;
 
-	if (abi_ver == 1)
-		return ibv_cmd_destroy_srq_v1(srq);
-
 	IBV_INIT_CMD_RESP(&cmd, sizeof cmd, DESTROY_SRQ, &resp, sizeof resp);
 	cmd.srq_handle = srq->handle;
 	cmd.reserved   = 0;
@@ -799,19 +694,6 @@ int ibv_cmd_modify_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,
 	return 0;
 }
 
-static int ibv_cmd_destroy_qp_v1(struct ibv_qp *qp)
-{
-	struct ibv_destroy_qp_v1 cmd;
-
-	IBV_INIT_CMD(&cmd, sizeof cmd, DESTROY_QP);
-	cmd.qp_handle = qp->handle;
-
-	if (write(qp->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
-		return errno;
-
-	return 0;
-}
-
 int ibv_cmd_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr,
 		      struct ibv_send_wr **bad_wr)
 {
@@ -1074,9 +956,6 @@ int ibv_cmd_destroy_qp(struct ibv_qp *qp)
 	struct ibv_destroy_qp      cmd;
 	struct ibv_destroy_qp_resp resp;
 
-	if (abi_ver == 1)
-		return ibv_cmd_destroy_qp_v1(qp);
-
 	IBV_INIT_CMD_RESP(&cmd, sizeof cmd, DESTROY_QP, &resp, sizeof resp);
 	cmd.qp_handle = qp->handle;
 	cmd.reserved  = 0;
diff --git a/src/device.c b/src/device.c
index 1923fa5..970375e 100644
--- a/src/device.c
+++ b/src/device.c
@@ -124,9 +124,11 @@ default_symver(__ibv_get_device_guid, ibv_get_device_guid);
 
 struct ibv_context *__ibv_open_device(struct ibv_device *device)
 {
+	struct verbs_device *verbs_device = verbs_get_device(device);
 	char *devpath;
-	int cmd_fd;
+	int cmd_fd, ret;
 	struct ibv_context *context;
+	struct verbs_context *context_ex;
 
 	if (asprintf(&devpath, "/dev/infiniband/%s", device->dev_name) < 0)
 		return NULL;
@@ -141,9 +143,33 @@ struct ibv_context *__ibv_open_device(struct ibv_device *device)
 	if (cmd_fd < 0)
 		return NULL;
 
-	context = device->ops.alloc_context(device, cmd_fd);
-	if (!context)
-		goto err;
+	if (!verbs_device) {
+		context = device->ops.alloc_context(device, cmd_fd);
+		if (!context)
+			goto err;
+	} else {
+		/* Library now allocates the context */
+		context_ex = calloc(1, sizeof(*context_ex) +
+				       verbs_device->size_of_context);
+		if (!context_ex) {
+			errno = ENOMEM;
+			goto err;
+		}
+
+		context_ex->context.abi_compat  = ((uint8_t *)NULL) - 1;
+		context_ex->sz = sizeof(*context_ex);
+
+		context = &context_ex->context;
+		ret = verbs_device->init_context(verbs_device, context, cmd_fd);
+		if (ret)
+			goto verbs_err;
+
+		/* initialize *all* library ops to either lib calls or
+		 * directly to provider calls.
+		 * context_ex->lib_new_func1 = __verbs_new_func1;
+		 * context_ex->lib_new_func2 = __verbs_new_func2;
+		 */
+	}
 
 	context->device = device;
 	context->cmd_fd = cmd_fd;
@@ -151,9 +177,10 @@ struct ibv_context *__ibv_open_device(struct ibv_device *device)
 
 	return context;
 
+verbs_err:
+	free(context_ex);
 err:
 	close(cmd_fd);
-
 	return NULL;
 }
 default_symver(__ibv_open_device, ibv_open_device);
@@ -163,15 +190,17 @@ int __ibv_close_device(struct ibv_context *context)
 	int async_fd = context->async_fd;
 	int cmd_fd   = context->cmd_fd;
 	int cq_fd    = -1;
-
-	if (abi_ver <= 2) {
-		struct ibv_abi_compat_v2 *t = context->abi_compat;
-		cq_fd = t->channel.fd;
-		free(context->abi_compat);
+	struct verbs_context *context_ex;
+
+	context_ex = verbs_get_ctx(context);
+	if (context_ex) {
+		struct verbs_device *verbs_device = verbs_get_device(context->device);
+		verbs_device->uninit_context(verbs_device, context);
+		free(context_ex);
+	} else {
+		context->device->ops.free_context(context);
 	}
 
-	context->device->ops.free_context(context);
-
 	close(async_fd);
 	close(cmd_fd);
 	if (abi_ver <= 2)
diff --git a/src/init.c b/src/init.c
index 8e93f3f..9fcb1ee 100644
--- a/src/init.c
+++ b/src/init.c
@@ -70,6 +70,7 @@ struct ibv_driver_name {
 struct ibv_driver {
 	const char	       *name;
 	ibv_driver_init_func	init_func;
+	verbs_driver_init_func	verbs_init_func;
 	struct ibv_driver      *next;
 };
 
@@ -153,7 +154,8 @@ static int find_sysfs_devs(void)
 	return ret;
 }
 
-void ibv_register_driver(const char *name, ibv_driver_init_func init_func)
+static void register_driver(const char *name, ibv_driver_init_func init_func,
+			    verbs_driver_init_func verbs_init_func)
 {
 	struct ibv_driver *driver;
 
@@ -163,9 +165,10 @@ void ibv_register_driver(const char *name, ibv_driver_init_func init_func)
 		return;
 	}
 
-	driver->name      = name;
-	driver->init_func = init_func;
-	driver->next      = NULL;
+	driver->name            = name;
+	driver->init_func	= init_func;
+	driver->verbs_init_func = verbs_init_func;
+	driver->next            = NULL;
 
 	if (tail_driver)
 		tail_driver->next = driver;
@@ -174,6 +177,19 @@ void ibv_register_driver(const char *name, ibv_driver_init_func init_func)
 	tail_driver = driver;
 }
 
+void ibv_register_driver(const char *name, ibv_driver_init_func init_func)
+{
+	register_driver(name, init_func, NULL);
+}
+
+/* New registration symbol with same functionality - used by providers to
+  * validate that library supports verbs extension.
+  */
+void verbs_register_driver(const char *name, verbs_driver_init_func init_func)
+{
+	register_driver(name, NULL, init_func);
+}
+
 static void load_driver(const char *name)
 {
 	char *so_name;
@@ -333,12 +349,23 @@ out:
 static struct ibv_device *try_driver(struct ibv_driver *driver,
 				     struct ibv_sysfs_dev *sysfs_dev)
 {
+	struct verbs_device *vdev;
 	struct ibv_device *dev;
 	char value[8];
 
-	dev = driver->init_func(sysfs_dev->sysfs_path, sysfs_dev->abi_ver);
-	if (!dev)
-		return NULL;
+	if (driver->init_func) {
+		dev = driver->init_func(sysfs_dev->sysfs_path, sysfs_dev->abi_ver);
+		if (!dev)
+			return NULL;
+	} else {
+		vdev = driver->verbs_init_func(sysfs_dev->sysfs_path, sysfs_dev->abi_ver);
+		if (!vdev)
+			return NULL;
+
+		dev = &vdev->device;
+		dev->ops.alloc_context = NULL;
+		dev->ops.free_context = NULL;
+	}
 
 	if (ibv_read_sysfs_file(sysfs_dev->ibdev_path, "node_type", value, sizeof value) < 0) {
 		fprintf(stderr, PFX "Warning: no node_type attr under %s.\n",
diff --git a/src/kern_abi.h b/src/kern_abi.h
deleted file mode 100644
index e055e75..0000000
--- a/src/kern_abi.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2005 Topspin Communications.  All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     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.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef KERN_ABI_H
-#define KERN_ABI_H
-
-#include <linux/types.h>
-
-/*
- * Increment this value if any changes that break userspace ABI
- * compatibility are made.
- */
-#define IB_USER_VERBS_ABI_VERSION	1
-
-enum {
-	IB_USER_VERBS_CMD_GET_CONTEXT,
-	IB_USER_VERBS_CMD_GET_EVENT_FDS,
-	IB_USER_VERBS_CMD_ALLOC_PD,
-	IB_USER_VERBS_CMD_DEALLOC_PD,
-	IB_USER_VERBS_CMD_REG_MR,
-	IB_USER_VERBS_CMD_DEREG_MR
-};
-
-/*
- * Make sure that all structs defined in this file remain laid out so
- * that they pack the same way on 32-bit and 64-bit architectures (to
- * avoid incompatibility between 32-bit userspace and 64-bit kernels).
- * In particular do not use pointer types -- pass pointers in __u64
- * instead.
- */
-
-struct ibv_kern_async_event {
-	__u32 event_type;
-	__u32 element;
-};
-
-struct ibv_comp_event {
-	__u32 cq_handle;
-};
-
-/*
- * All commands from userspace should start with a __u32 command field
- * followed by __u16 in_words and out_words fields (which give the
- * length of the command block and response buffer if any in 32-bit
- * words).  The kernel driver will read these fields first and read
- * the rest of the command struct based on these value.
- */
-
-struct ibv_get_context {
-	__u32 command;
-	__u16 in_words;
-	__u16 out_words;
-	__u64 response;
-};
-
-struct ibv_get_context_resp {
-	__u32 num_cq_events;
-};
-
-struct ibv_get_event_fds {
-	__u32 command;
-	__u16 in_words;
-	__u16 out_words;
-	__u64 response;
-};
-
-struct ibv_get_event_fds_resp {
-	__u32 async_fd;
-	__u32 cq_fd[1];
-};
-
-#endif /* KERN_ABI_H */
diff --git a/src/libibverbs.map b/src/libibverbs.map
index 7e722f4..6e35c37 100644
--- a/src/libibverbs.map
+++ b/src/libibverbs.map
@@ -91,6 +91,7 @@ IBVERBS_1.1 {
 		ibv_dontfork_range;
 		ibv_dofork_range;
 		ibv_register_driver;
+		verbs_register_driver;
 
 		ibv_node_type_str;
 		ibv_port_state_str;
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH V8 libibverbs 2/7] Introduce XRC domains
       [not found] ` <1374741488-30895-1-git-send-email-yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
  2013-07-25  8:38   ` [PATCH V8 libibverbs 1/7] Infrastructure to support verbs extensions Yishai Hadas
@ 2013-07-25  8:38   ` Yishai Hadas
  2013-07-25  8:38   ` [PATCH V8 libibverbs 3/7] Add support for XRC SRQs Yishai Hadas
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 15+ messages in thread
From: Yishai Hadas @ 2013-07-25  8:38 UTC (permalink / raw)
  To: linux-rdma-u79uwXL29TY76Z2rM5mHXA, roland-BHEL68pLQRGGvPXPguhicg
  Cc: ogerlitz-VPRAkNaXOzVWk0Htik3J/w, tzahio-VPRAkNaXOzVWk0Htik3J/w,
	yishaih-VPRAkNaXOzVWk0Htik3J/w, Sean Hefty

From: Sean Hefty <sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

XRC introduces several new concepts and structures, one of
which is the XRC domain.

XRC domains: xrcd's are a type of protection domain used to
associate shared receive queues with xrc queue pairs.  Since
xrcd are meant to be shared among multiple processes, we
introduce new APIs to open/close xrcd's.

The user to kernel ABI is extended to account for opening/
closing the xrcd.

Signed-off-by: Sean Hefty <sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Yishai Hadas <yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---

Changes from V7:
verbs_context - remove place holder for ABI compatibility with OFED.

 include/infiniband/driver.h   |   17 ++++++++++++++
 include/infiniband/kern-abi.h |   27 +++++++++++++++++++++-
 include/infiniband/verbs.h    |   50 ++++++++++++++++++++++++++++++++++++++--
 src/cmd.c                     |   45 ++++++++++++++++++++++++++++++++++++
 src/libibverbs.map            |    3 ++
 5 files changed, 138 insertions(+), 4 deletions(-)

diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h
index f22f287..08d8a82 100644
--- a/include/infiniband/driver.h
+++ b/include/infiniband/driver.h
@@ -53,6 +53,17 @@
  */
 #define IBV_DEVICE_LIBRARY_EXTENSION rdmav2
 
+enum verbs_xrcd_mask {
+	VERBS_XRCD_HANDLE	= 1 << 0,
+	VERBS_XRCD_RESERVED	= 1 << 1
+};
+
+struct verbs_xrcd {
+	struct ibv_xrcd		xrcd;
+	uint32_t		comp_mask;
+	uint32_t		handle;
+};
+
 typedef struct ibv_device *(*ibv_driver_init_func)(const char *uverbs_sys_path,
 						   int abi_version);
 typedef struct verbs_device *(*verbs_driver_init_func)(const char *uverbs_sys_path,
@@ -78,6 +89,12 @@ int ibv_cmd_alloc_pd(struct ibv_context *context, struct ibv_pd *pd,
 		     struct ibv_alloc_pd *cmd, size_t cmd_size,
 		     struct ibv_alloc_pd_resp *resp, size_t resp_size);
 int ibv_cmd_dealloc_pd(struct ibv_pd *pd);
+int ibv_cmd_open_xrcd(struct ibv_context *context, struct verbs_xrcd *xrcd,
+		      int vxrcd_size,
+		      struct ibv_xrcd_init_attr *attr,
+		      struct ibv_open_xrcd *cmd, size_t cmd_size,
+		      struct ibv_open_xrcd_resp *resp, size_t resp_size);
+int ibv_cmd_close_xrcd(struct verbs_xrcd *xrcd);
 #define IBV_CMD_REG_MR_HAS_RESP_PARAMS
 int ibv_cmd_reg_mr(struct ibv_pd *pd, void *addr, size_t length,
 		   uint64_t hca_va, int access,
diff --git a/include/infiniband/kern-abi.h b/include/infiniband/kern-abi.h
index e7f8981..6f40ad2 100644
--- a/include/infiniband/kern-abi.h
+++ b/include/infiniband/kern-abi.h
@@ -85,7 +85,9 @@ enum {
 	IB_USER_VERBS_CMD_MODIFY_SRQ,
 	IB_USER_VERBS_CMD_QUERY_SRQ,
 	IB_USER_VERBS_CMD_DESTROY_SRQ,
-	IB_USER_VERBS_CMD_POST_SRQ_RECV
+	IB_USER_VERBS_CMD_POST_SRQ_RECV,
+	IB_USER_VERBS_CMD_OPEN_XRCD,
+	IB_USER_VERBS_CMD_CLOSE_XRCD,
 };
 
 /*
@@ -246,6 +248,27 @@ struct ibv_dealloc_pd {
 	__u32 pd_handle;
 };
 
+struct ibv_open_xrcd {
+	__u32 command;
+	__u16 in_words;
+	__u16 out_words;
+	__u64 response;
+	__u32 fd;
+	__u32 oflags;
+	__u64 driver_data[0];
+};
+
+struct ibv_open_xrcd_resp {
+	__u32 xrcd_handle;
+};
+
+struct ibv_close_xrcd {
+	__u32 command;
+	__u16 in_words;
+	__u16 out_words;
+	__u32 xrcd_handle;
+};
+
 struct ibv_reg_mr {
 	__u32 command;
 	__u16 in_words;
@@ -804,6 +827,8 @@ enum {
 	 * trick opcodes in IBV_INIT_CMD() doesn't break.
 	 */
 	IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL_V2 = -1,
+	IB_USER_VERBS_CMD_OPEN_XRCD_V2 = -1,
+	IB_USER_VERBS_CMD_CLOSE_XRCD_V2 = -1,
 };
 
 struct ibv_modify_srq_v3 {
diff --git a/include/infiniband/verbs.h b/include/infiniband/verbs.h
index ca300af..7459119 100644
--- a/include/infiniband/verbs.h
+++ b/include/infiniband/verbs.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
- * Copyright (c) 2004 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2011-2012 Intel Corporation.  All rights reserved.
  * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc.  All rights reserved.
  * Copyright (c) 2005 PathScale, Inc.  All rights reserved.
  *
@@ -39,6 +39,7 @@
 #include <stdint.h>
 #include <pthread.h>
 #include <stddef.h>
+#include <errno.h>
 
 #ifdef __cplusplus
 #  define BEGIN_C_DECLS extern "C" {
@@ -313,6 +314,22 @@ struct ibv_pd {
 	uint32_t		handle;
 };
 
+enum ibv_xrcd_init_attr_mask {
+	IBV_XRCD_INIT_ATTR_FD	    = 1 << 0,
+	IBV_XRCD_INIT_ATTR_OFLAGS   = 1 << 1,
+	IBV_XRCD_INIT_ATTR_RESERVED = 1 << 2
+};
+
+struct ibv_xrcd_init_attr {
+	uint32_t comp_mask;
+	int	 fd;
+	int	 oflags;
+};
+
+struct ibv_xrcd {
+	struct ibv_context     *context;
+};
+
 enum ibv_rereg_mr_flags {
 	IBV_REREG_MR_CHANGE_TRANSLATION	= (1 << 0),
 	IBV_REREG_MR_CHANGE_PD		= (1 << 1),
@@ -751,11 +768,15 @@ struct ibv_context {
 };
 
 enum verbs_context_mask {
-	VERBS_CONTEXT_RESERVED = 1 << 0
+	VERBS_CONTEXT_XRCD	= 1 << 0,
+	VERBS_CONTEXT_RESERVED	= 1 << 1
 };
 
 struct verbs_context {
 	/*  "grows up" - new fields go here */
+	struct ibv_xrcd *	(*open_xrcd)(struct ibv_context *context,
+					     struct ibv_xrcd_init_attr *xrcd_init_attr);
+	int			(*close_xrcd)(struct ibv_xrcd *xrcd);
 	uint64_t has_comp_mask;
 	size_t   sz;	/* Must be immediately before struct ibv_context */
 	struct ibv_context context;/* Must be last field in the struct */
@@ -862,7 +883,7 @@ static inline int ___ibv_query_port(struct ibv_context *context,
 				    uint8_t port_num,
 				    struct ibv_port_attr *port_attr)
 {
-	/* For compatability when running with old libibverbs */
+	/* For compatibility when running with old libibverbs */
 	port_attr->link_layer = IBV_LINK_LAYER_UNSPECIFIED;
 	port_attr->reserved   = 0;
 
@@ -895,6 +916,29 @@ struct ibv_pd *ibv_alloc_pd(struct ibv_context *context);
 int ibv_dealloc_pd(struct ibv_pd *pd);
 
 /**
+ * ibv_open_xrcd - Open an extended connection domain
+ */
+static inline struct ibv_xrcd *
+ibv_open_xrcd(struct ibv_context *context, struct ibv_xrcd_init_attr *xrcd_init_attr)
+{
+	struct verbs_context *vctx = verbs_get_ctx_op(context, open_xrcd);
+	if (!vctx) {
+		errno = ENOSYS;
+		return NULL;
+	}
+	return vctx->open_xrcd(context, xrcd_init_attr);
+}
+
+/**
+ * ibv_close_xrcd - Close an extended connection domain
+ */
+static inline int ibv_close_xrcd(struct ibv_xrcd *xrcd)
+{
+	struct verbs_context *vctx = verbs_get_ctx(xrcd->context);
+	return vctx->close_xrcd(xrcd);
+}
+
+/**
  * ibv_reg_mr - Register a memory region
  */
 struct ibv_mr *ibv_reg_mr(struct ibv_pd *pd, void *addr,
diff --git a/src/cmd.c b/src/cmd.c
index 86350fd..f3d590a 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -194,6 +194,51 @@ int ibv_cmd_dealloc_pd(struct ibv_pd *pd)
 	return 0;
 }
 
+int ibv_cmd_open_xrcd(struct ibv_context *context, struct verbs_xrcd *xrcd,
+		      int vxrcd_size,
+		      struct ibv_xrcd_init_attr *attr,
+		      struct ibv_open_xrcd *cmd, size_t cmd_size,
+		      struct ibv_open_xrcd_resp *resp, size_t resp_size)
+{
+	IBV_INIT_CMD_RESP(cmd, cmd_size, OPEN_XRCD, resp, resp_size);
+
+	if (attr->comp_mask >= IBV_XRCD_INIT_ATTR_RESERVED)
+		return ENOSYS;
+
+	if (!(attr->comp_mask & IBV_XRCD_INIT_ATTR_FD) ||
+	    !(attr->comp_mask & IBV_XRCD_INIT_ATTR_OFLAGS))
+		return EINVAL;
+
+	cmd->fd = attr->fd;
+	cmd->oflags = attr->oflags;
+	if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
+		return errno;
+
+	VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
+
+	xrcd->xrcd.context = context;
+	xrcd->comp_mask = 0;
+	if (vext_field_avail(struct verbs_xrcd, handle, vxrcd_size)) {
+		xrcd->comp_mask = VERBS_XRCD_HANDLE;
+		xrcd->handle  = resp->xrcd_handle;
+	}
+
+	return 0;
+}
+
+int ibv_cmd_close_xrcd(struct verbs_xrcd *xrcd)
+{
+	struct ibv_close_xrcd cmd;
+
+	IBV_INIT_CMD(&cmd, sizeof cmd, CLOSE_XRCD);
+	cmd.xrcd_handle = xrcd->handle;
+
+	if (write(xrcd->xrcd.context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
+		return errno;
+
+	return 0;
+}
+
 int ibv_cmd_reg_mr(struct ibv_pd *pd, void *addr, size_t length,
 		   uint64_t hca_va, int access,
 		   struct ibv_mr *mr, struct ibv_reg_mr *cmd,
diff --git a/src/libibverbs.map b/src/libibverbs.map
index 6e35c37..c190eb9 100644
--- a/src/libibverbs.map
+++ b/src/libibverbs.map
@@ -100,4 +100,7 @@ IBVERBS_1.1 {
 
 		ibv_rate_to_mbps;
 		mbps_to_ibv_rate;
+
+		ibv_cmd_open_xrcd;
+		ibv_cmd_close_xrcd;
 } IBVERBS_1.0;
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH V8 libibverbs 3/7] Add support for XRC SRQs
       [not found] ` <1374741488-30895-1-git-send-email-yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
  2013-07-25  8:38   ` [PATCH V8 libibverbs 1/7] Infrastructure to support verbs extensions Yishai Hadas
  2013-07-25  8:38   ` [PATCH V8 libibverbs 2/7] Introduce XRC domains Yishai Hadas
@ 2013-07-25  8:38   ` Yishai Hadas
  2013-07-25  8:38   ` [PATCH V8 libibverbs 4/7] Add support for XRC QPs Yishai Hadas
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 15+ messages in thread
From: Yishai Hadas @ 2013-07-25  8:38 UTC (permalink / raw)
  To: linux-rdma-u79uwXL29TY76Z2rM5mHXA, roland-BHEL68pLQRGGvPXPguhicg
  Cc: ogerlitz-VPRAkNaXOzVWk0Htik3J/w, tzahio-VPRAkNaXOzVWk0Htik3J/w,
	yishaih-VPRAkNaXOzVWk0Htik3J/w, Sean Hefty

From: Sean Hefty <sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

XRC support requires the use of a new type of SRQ.
XRC shared receive queues: xrc srq's are similar to normal
srq's, except that they are bound to an xrcd, rather
than to a protection domain.  Based on the current spec
and implementation, they are only usable with xrc qps.  To
support xrc srq's, we define a new srq_init_attr structure
to include an srq type and other needed information.

The kernel ABI is also updated to allow creating extended
SRQs.

Signed-off-by: Sean Hefty <sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Yishai Hadas <yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 include/infiniband/driver.h   |   32 +++++++++++++++++
 include/infiniband/kern-abi.h |   21 +++++++++++-
 include/infiniband/verbs.h    |   62 +++++++++++++++++++++++++++++++++-
 src/cmd.c                     |   75 +++++++++++++++++++++++++++++++++++++++++
 src/libibverbs.map            |    2 +
 5 files changed, 190 insertions(+), 2 deletions(-)

diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h
index 08d8a82..11f52c2 100644
--- a/include/infiniband/driver.h
+++ b/include/infiniband/driver.h
@@ -64,6 +64,23 @@ struct verbs_xrcd {
 	uint32_t		handle;
 };
 
+enum verbs_srq_mask {
+	VERBS_SRQ_TYPE		= 1 << 0,
+	VERBS_SRQ_XRCD		= 1 << 1,
+	VERBS_SRQ_CQ		= 1 << 2,
+	VERBS_SRQ_NUM		= 1 << 3,
+	VERBS_SRQ_RESERVED	= 1 << 4
+};
+
+struct verbs_srq {
+	struct ibv_srq		srq;
+	uint32_t		comp_mask;
+	enum ibv_srq_type	srq_type;
+	struct verbs_xrcd      *xrcd;
+	struct ibv_cq	       *cq;
+	uint32_t		srq_num;
+};
+
 typedef struct ibv_device *(*ibv_driver_init_func)(const char *uverbs_sys_path,
 						   int abi_version);
 typedef struct verbs_device *(*verbs_driver_init_func)(const char *uverbs_sys_path,
@@ -119,6 +136,11 @@ int ibv_cmd_create_srq(struct ibv_pd *pd,
 		       struct ibv_srq *srq, struct ibv_srq_init_attr *attr,
 		       struct ibv_create_srq *cmd, size_t cmd_size,
 		       struct ibv_create_srq_resp *resp, size_t resp_size);
+int ibv_cmd_create_srq_ex(struct ibv_context *context,
+			  struct verbs_srq *srq, int vsrq_sz,
+			  struct ibv_srq_init_attr_ex *attr_ex,
+			  struct ibv_create_xsrq *cmd, size_t cmd_size,
+			  struct ibv_create_srq_resp *resp, size_t resp_size);
 int ibv_cmd_modify_srq(struct ibv_srq *srq,
 		       struct ibv_srq_attr *srq_attr,
 		       int srq_attr_mask,
@@ -163,4 +185,14 @@ const char *ibv_get_sysfs_path(void);
 int ibv_read_sysfs_file(const char *dir, const char *file,
 			char *buf, size_t size);
 
+static inline int verbs_get_srq_num(struct ibv_srq *srq, uint32_t *srq_num)
+{
+	struct verbs_srq *vsrq = container_of(srq, struct verbs_srq, srq);
+	if (vsrq->comp_mask & VERBS_SRQ_NUM) {
+		*srq_num = vsrq->srq_num;
+		return 0;
+	}
+	return ENOSYS;
+}
+
 #endif /* INFINIBAND_DRIVER_H */
diff --git a/include/infiniband/kern-abi.h b/include/infiniband/kern-abi.h
index 6f40ad2..ef93cc3 100644
--- a/include/infiniband/kern-abi.h
+++ b/include/infiniband/kern-abi.h
@@ -88,6 +88,7 @@ enum {
 	IB_USER_VERBS_CMD_POST_SRQ_RECV,
 	IB_USER_VERBS_CMD_OPEN_XRCD,
 	IB_USER_VERBS_CMD_CLOSE_XRCD,
+	IB_USER_VERBS_CMD_CREATE_XSRQ
 };
 
 /*
@@ -730,11 +731,28 @@ struct ibv_create_srq {
 	__u64 driver_data[0];
 };
 
+struct ibv_create_xsrq {
+	__u32 command;
+	__u16 in_words;
+	__u16 out_words;
+	__u64 response;
+	__u64 user_handle;
+	__u32 srq_type;
+	__u32 pd_handle;
+	__u32 max_wr;
+	__u32 max_sge;
+	__u32 srq_limit;
+	__u32 reserved;
+	__u32 xrcd_handle;
+	__u32 cq_handle;
+	__u64 driver_data[0];
+};
+
 struct ibv_create_srq_resp {
 	__u32 srq_handle;
 	__u32 max_wr;
 	__u32 max_sge;
-	__u32 reserved;
+	__u32 srqn;
 };
 
 struct ibv_modify_srq {
@@ -829,6 +847,7 @@ enum {
 	IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL_V2 = -1,
 	IB_USER_VERBS_CMD_OPEN_XRCD_V2 = -1,
 	IB_USER_VERBS_CMD_CLOSE_XRCD_V2 = -1,
+	IB_USER_VERBS_CMD_CREATE_XSRQ_V2 = -1
 };
 
 struct ibv_modify_srq_v3 {
diff --git a/include/infiniband/verbs.h b/include/infiniband/verbs.h
index 7459119..8074bfe 100644
--- a/include/infiniband/verbs.h
+++ b/include/infiniband/verbs.h
@@ -449,6 +449,30 @@ struct ibv_srq_init_attr {
 	struct ibv_srq_attr	attr;
 };
 
+enum ibv_srq_type {
+	IBV_SRQT_BASIC,
+	IBV_SRQT_XRC
+};
+
+enum ibv_srq_init_attr_mask {
+	IBV_SRQ_INIT_ATTR_TYPE		= 1 << 0,
+	IBV_SRQ_INIT_ATTR_PD		= 1 << 1,
+	IBV_SRQ_INIT_ATTR_XRCD		= 1 << 2,
+	IBV_SRQ_INIT_ATTR_CQ		= 1 << 3,
+	IBV_SRQ_INIT_ATTR_RESERVED	= 1 << 4
+};
+
+struct ibv_srq_init_attr_ex {
+	void		       *srq_context;
+	struct ibv_srq_attr	attr;
+
+	uint32_t		comp_mask;
+	enum ibv_srq_type	srq_type;
+	struct ibv_pd	       *pd;
+	struct ibv_xrcd	       *xrcd;
+	struct ibv_cq	       *cq;
+};
+
 enum ibv_qp_type {
 	IBV_QPT_RC = 2,
 	IBV_QPT_UC,
@@ -769,11 +793,15 @@ struct ibv_context {
 
 enum verbs_context_mask {
 	VERBS_CONTEXT_XRCD	= 1 << 0,
-	VERBS_CONTEXT_RESERVED	= 1 << 1
+	VERBS_CONTEXT_SRQ	= 1 << 1,
+	VERBS_CONTEXT_RESERVED	= 1 << 2
 };
 
 struct verbs_context {
 	/*  "grows up" - new fields go here */
+	int (*get_srq_num)(struct ibv_srq *srq, uint32_t *srq_num);
+	struct ibv_srq *	(*create_srq_ex)(struct ibv_context *context,
+						 struct ibv_srq_init_attr_ex *srq_init_attr_ex);
 	struct ibv_xrcd *	(*open_xrcd)(struct ibv_context *context,
 					     struct ibv_xrcd_init_attr *xrcd_init_attr);
 	int			(*close_xrcd)(struct ibv_xrcd *xrcd);
@@ -1061,6 +1089,28 @@ static inline int ibv_req_notify_cq(struct ibv_cq *cq, int solicited_only)
 struct ibv_srq *ibv_create_srq(struct ibv_pd *pd,
 			       struct ibv_srq_init_attr *srq_init_attr);
 
+static inline struct ibv_srq *
+ibv_create_srq_ex(struct ibv_context *context,
+		  struct ibv_srq_init_attr_ex *srq_init_attr_ex)
+{
+	struct verbs_context *vctx;
+	uint32_t mask = srq_init_attr_ex->comp_mask;
+
+	if (!(mask & ~(IBV_SRQ_INIT_ATTR_PD | IBV_SRQ_INIT_ATTR_TYPE)) &&
+	    (mask & IBV_SRQ_INIT_ATTR_PD) &&
+	    (!(mask & IBV_SRQ_INIT_ATTR_TYPE) ||
+	     (srq_init_attr_ex->srq_type == IBV_SRQT_BASIC)))
+		return ibv_create_srq(srq_init_attr_ex->pd,
+				      (struct ibv_srq_init_attr *)srq_init_attr_ex);
+
+	vctx = verbs_get_ctx_op(context, create_srq_ex);
+	if (!vctx) {
+		errno = ENOSYS;
+		return NULL;
+	}
+	return vctx->create_srq_ex(context, srq_init_attr_ex);
+}
+
 /**
  * ibv_modify_srq - Modifies the attributes for the specified SRQ.
  * @srq: The SRQ to modify.
@@ -1085,6 +1135,16 @@ int ibv_modify_srq(struct ibv_srq *srq,
  */
 int ibv_query_srq(struct ibv_srq *srq, struct ibv_srq_attr *srq_attr);
 
+static inline int ibv_get_srq_num(struct ibv_srq *srq, uint32_t *srq_num)
+{
+	struct verbs_context *vctx = verbs_get_ctx_op(srq->context, get_srq_num);
+
+	if (!vctx)
+		return ENOSYS;
+
+	return vctx->get_srq_num(srq, srq_num);
+}
+
 /**
  * ibv_destroy_srq - Destroys the specified SRQ.
  * @srq: The SRQ to destroy.
diff --git a/src/cmd.c b/src/cmd.c
index f3d590a..fae2846 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -442,6 +442,81 @@ int ibv_cmd_create_srq(struct ibv_pd *pd,
 	return 0;
 }
 
+int ibv_cmd_create_srq_ex(struct ibv_context *context,
+			  struct verbs_srq *srq, int vsrq_sz,
+			  struct ibv_srq_init_attr_ex *attr_ex,
+			  struct ibv_create_xsrq *cmd, size_t cmd_size,
+			  struct ibv_create_srq_resp *resp, size_t resp_size)
+{
+	struct verbs_xrcd *vxrcd = NULL;
+
+	IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_XSRQ, resp, resp_size);
+
+	if (attr_ex->comp_mask >= IBV_SRQ_INIT_ATTR_RESERVED)
+		return ENOSYS;
+
+	if (!(attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_PD))
+		return EINVAL;
+
+	cmd->user_handle = (uintptr_t) srq;
+	cmd->pd_handle   = attr_ex->pd->handle;
+	cmd->max_wr      = attr_ex->attr.max_wr;
+	cmd->max_sge     = attr_ex->attr.max_sge;
+	cmd->srq_limit   = attr_ex->attr.srq_limit;
+
+	cmd->srq_type = (attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_TYPE) ?
+			attr_ex->srq_type : IBV_SRQT_BASIC;
+	if (attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_XRCD) {
+		if (!(attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_CQ))
+			return EINVAL;
+
+		vxrcd = container_of(attr_ex->xrcd, struct verbs_xrcd, xrcd);
+		cmd->xrcd_handle = vxrcd->handle;
+		cmd->cq_handle   = attr_ex->cq->handle;
+	}
+
+	if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
+		return errno;
+
+	VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
+
+	srq->srq.handle           = resp->srq_handle;
+	srq->srq.context          = context;
+	srq->srq.srq_context      = attr_ex->srq_context;
+	srq->srq.pd               = attr_ex->pd;
+	srq->srq.events_completed = 0;
+	pthread_mutex_init(&srq->srq.mutex, NULL);
+	pthread_cond_init(&srq->srq.cond, NULL);
+
+	/*
+	 * check that the last field is available.
+	 * If it is than all the others exist as well
+	 */
+	if (vext_field_avail(struct verbs_srq, srq_num, vsrq_sz)) {
+		srq->comp_mask = IBV_SRQ_INIT_ATTR_TYPE;
+		srq->srq_type = (attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_TYPE) ?
+				attr_ex->srq_type : IBV_SRQT_BASIC;
+		if (srq->srq_type == IBV_SRQT_XRC) {
+			srq->comp_mask |= VERBS_SRQ_NUM;
+			srq->srq_num = resp->srqn;
+		}
+		if (attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_XRCD) {
+			srq->comp_mask |= VERBS_SRQ_XRCD;
+			srq->xrcd = vxrcd;
+		}
+		if (attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_CQ) {
+			srq->comp_mask |= VERBS_SRQ_CQ;
+			srq->cq = attr_ex->cq;
+		}
+	}
+
+	attr_ex->attr.max_wr = resp->max_wr;
+	attr_ex->attr.max_sge = resp->max_sge;
+
+	return 0;
+}
+
+
 static int ibv_cmd_modify_srq_v3(struct ibv_srq *srq,
 				 struct ibv_srq_attr *srq_attr,
 				 int srq_attr_mask,
diff --git a/src/libibverbs.map b/src/libibverbs.map
index c190eb9..a4b089f 100644
--- a/src/libibverbs.map
+++ b/src/libibverbs.map
@@ -103,4 +103,6 @@ IBVERBS_1.1 {
 
 		ibv_cmd_open_xrcd;
 		ibv_cmd_close_xrcd;
+		ibv_cmd_create_srq_ex;
+
 } IBVERBS_1.0;
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH V8 libibverbs 4/7] Add support for XRC QPs
       [not found] ` <1374741488-30895-1-git-send-email-yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
                     ` (2 preceding siblings ...)
  2013-07-25  8:38   ` [PATCH V8 libibverbs 3/7] Add support for XRC SRQs Yishai Hadas
@ 2013-07-25  8:38   ` Yishai Hadas
  2013-07-25  8:38   ` [PATCH V8 libibverbs 5/7] Add ibv_open_qp Yishai Hadas
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 15+ messages in thread
From: Yishai Hadas @ 2013-07-25  8:38 UTC (permalink / raw)
  To: linux-rdma-u79uwXL29TY76Z2rM5mHXA, roland-BHEL68pLQRGGvPXPguhicg
  Cc: ogerlitz-VPRAkNaXOzVWk0Htik3J/w, tzahio-VPRAkNaXOzVWk0Htik3J/w,
	yishaih-VPRAkNaXOzVWk0Htik3J/w, Sean Hefty

From: Sean Hefty <sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

XRC queue pairs: xrc defines two new types of QPs.  The
initiator, or send-side, xrc qp behaves similar to a send-
only RC qp.  xrc send qp's are managed through the existing
QP functions.  The send_wr structure is extended in a back-
wards compatible way to support posting sends on a send xrc
qp, which require specifying the remote xrc srq.

The target, or receive-side, xrc qp behaves differently
than other implemented qp's.  A recv xrc qp can be created,
modified, and destroyed like other qp's through the existing
calls.  The qp_init_attr structure is extended for xrc qp's.

Because xrc recv qp's are bound to an xrcd, rather than a pd,
it is intended to be used among multiple processes.  Any process
with access to an xrcd may allocate and connect an xrc recv qp.
The actual xrc recv qp is allocated and managed by the kernel.
If the owning process explicit destroys the xrc recv qp, it is
destroyed.  However, if the xrc recv qp is left open when the
user process exits or closes its device, then the lifetime of
the xrc recv qp is bound with the lifetime of the xrcd.

Signed-off-by: Sean Hefty <sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Yishai Hadas <yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 include/infiniband/driver.h   |   15 ++++++
 include/infiniband/kern-abi.h |    5 ++
 include/infiniband/verbs.h    |   55 ++++++++++++++++++++++-
 src/cmd.c                     |   96 ++++++++++++++++++++++++++++++++++++++++-
 src/libibverbs.map            |    1 +
 5 files changed, 168 insertions(+), 4 deletions(-)

diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h
index 11f52c2..91b5b12 100644
--- a/include/infiniband/driver.h
+++ b/include/infiniband/driver.h
@@ -81,6 +81,16 @@ struct verbs_srq {
 	uint32_t		srq_num;
 };
 
+enum verbs_qp_mask {
+	VERBS_QP_XRCD		= 1 << 0,
+	VERBS_QP_RESERVED	= 1 << 1
+};
+
+struct verbs_qp {
+	struct ibv_qp		qp;
+	uint32_t		comp_mask;
+	struct verbs_xrcd       *xrcd;
+};
 typedef struct ibv_device *(*ibv_driver_init_func)(const char *uverbs_sys_path,
 						   int abi_version);
 typedef struct verbs_device *(*verbs_driver_init_func)(const char *uverbs_sys_path,
@@ -154,6 +164,11 @@ int ibv_cmd_create_qp(struct ibv_pd *pd,
 		      struct ibv_qp *qp, struct ibv_qp_init_attr *attr,
 		      struct ibv_create_qp *cmd, size_t cmd_size,
 		      struct ibv_create_qp_resp *resp, size_t resp_size);
+int ibv_cmd_create_qp_ex(struct ibv_context *context,
+			 struct verbs_qp *qp, int vqp_sz,
+			 struct ibv_qp_init_attr_ex *attr_ex,
+			 struct ibv_create_qp *cmd, size_t cmd_size,
+			 struct ibv_create_qp_resp *resp, size_t resp_size);
 int ibv_cmd_query_qp(struct ibv_qp *qp, struct ibv_qp_attr *qp_attr,
 		     int attr_mask,
 		     struct ibv_qp_init_attr *qp_init_attr,
diff --git a/include/infiniband/kern-abi.h b/include/infiniband/kern-abi.h
index ef93cc3..65f3ffd 100644
--- a/include/infiniband/kern-abi.h
+++ b/include/infiniband/kern-abi.h
@@ -618,6 +618,11 @@ struct ibv_kern_send_wr {
 			__u32 reserved;
 		} ud;
 	} wr;
+	union {
+		struct {
+			__u32 remote_srqn;
+		} xrc;
+	} qp_type;
 };
 
 struct ibv_post_send {
diff --git a/include/infiniband/verbs.h b/include/infiniband/verbs.h
index 8074bfe..aba8dd6 100644
--- a/include/infiniband/verbs.h
+++ b/include/infiniband/verbs.h
@@ -108,7 +108,8 @@ enum ibv_device_cap_flags {
 	IBV_DEVICE_SYS_IMAGE_GUID	= 1 << 11,
 	IBV_DEVICE_RC_RNR_NAK_GEN	= 1 << 12,
 	IBV_DEVICE_SRQ_RESIZE		= 1 << 13,
-	IBV_DEVICE_N_NOTIFY_CQ		= 1 << 14
+	IBV_DEVICE_N_NOTIFY_CQ		= 1 << 14,
+	IBV_DEVICE_XRC			= 1 << 20
 };
 
 enum ibv_atomic_cap {
@@ -477,7 +478,9 @@ enum ibv_qp_type {
 	IBV_QPT_RC = 2,
 	IBV_QPT_UC,
 	IBV_QPT_UD,
-	IBV_QPT_RAW_PACKET = 8
+	IBV_QPT_RAW_PACKET = 8,
+	IBV_QPT_XRC_SEND = 9,
+	IBV_QPT_XRC_RECV
 };
 
 struct ibv_qp_cap {
@@ -498,6 +501,26 @@ struct ibv_qp_init_attr {
 	int			sq_sig_all;
 };
 
+enum ibv_qp_init_attr_mask {
+	IBV_QP_INIT_ATTR_PD		= 1 << 0,
+	IBV_QP_INIT_ATTR_XRCD		= 1 << 1,
+	IBV_QP_INIT_ATTR_RESERVED	= 1 << 2
+};
+
+struct ibv_qp_init_attr_ex {
+	void		       *qp_context;
+	struct ibv_cq	       *send_cq;
+	struct ibv_cq	       *recv_cq;
+	struct ibv_srq	       *srq;
+	struct ibv_qp_cap	cap;
+	enum ibv_qp_type	qp_type;
+	int			sq_sig_all;
+
+	uint32_t		comp_mask;
+	struct ibv_pd	       *pd;
+	struct ibv_xrcd	       *xrcd;
+};
+
 enum ibv_qp_attr_mask {
 	IBV_QP_STATE			= 1 << 	0,
 	IBV_QP_CUR_STATE		= 1 << 	1,
@@ -614,6 +637,11 @@ struct ibv_send_wr {
 			uint32_t	remote_qkey;
 		} ud;
 	} wr;
+	union {
+		struct {
+			uint32_t    remote_srqn;
+		} xrc;
+	} qp_type;
 };
 
 struct ibv_recv_wr {
@@ -794,11 +822,14 @@ struct ibv_context {
 enum verbs_context_mask {
 	VERBS_CONTEXT_XRCD	= 1 << 0,
 	VERBS_CONTEXT_SRQ	= 1 << 1,
-	VERBS_CONTEXT_RESERVED	= 1 << 2
+	VERBS_CONTEXT_QP	= 1 << 2,
+	VERBS_CONTEXT_RESERVED	= 1 << 3
 };
 
 struct verbs_context {
 	/*  "grows up" - new fields go here */
+	struct ibv_qp *(*create_qp_ex)(struct ibv_context *context,
+			struct ibv_qp_init_attr_ex *qp_init_attr_ex);
 	int (*get_srq_num)(struct ibv_srq *srq, uint32_t *srq_num);
 	struct ibv_srq *	(*create_srq_ex)(struct ibv_context *context,
 						 struct ibv_srq_init_attr_ex *srq_init_attr_ex);
@@ -1171,6 +1202,24 @@ static inline int ibv_post_srq_recv(struct ibv_srq *srq,
 struct ibv_qp *ibv_create_qp(struct ibv_pd *pd,
 			     struct ibv_qp_init_attr *qp_init_attr);
 
+static inline struct ibv_qp *
+ibv_create_qp_ex(struct ibv_context *context, struct ibv_qp_init_attr_ex *qp_init_attr_ex)
+{
+	struct verbs_context *vctx;
+	uint32_t mask = qp_init_attr_ex->comp_mask;
+
+	if (mask == IBV_QP_INIT_ATTR_PD)
+		return ibv_create_qp(qp_init_attr_ex->pd,
+				     (struct ibv_qp_init_attr *)qp_init_attr_ex);
+
+	vctx = verbs_get_ctx_op(context, create_qp_ex);
+	if (!vctx) {
+		errno = ENOSYS;
+		return NULL;
+	}
+	return vctx->create_qp_ex(context, qp_init_attr_ex);
+}
+
 /**
  * ibv_modify_qp - Modify a queue pair.
  */
diff --git a/src/cmd.c b/src/cmd.c
index fae2846..463b95b 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -610,6 +610,100 @@ int ibv_cmd_destroy_srq(struct ibv_srq *srq)
 	return 0;
 }
 
+int ibv_cmd_create_qp_ex(struct ibv_context *context,
+			 struct verbs_qp *qp, int vqp_sz,
+			 struct ibv_qp_init_attr_ex *attr_ex,
+			 struct ibv_create_qp *cmd, size_t cmd_size,
+			 struct ibv_create_qp_resp *resp, size_t resp_size)
+{
+	struct verbs_xrcd *vxrcd = NULL;
+
+	IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_QP, resp, resp_size);
+
+	if (attr_ex->comp_mask >= IBV_QP_INIT_ATTR_RESERVED)
+		return ENOSYS;
+
+	cmd->user_handle     = (uintptr_t) qp;
+
+	if (attr_ex->comp_mask & IBV_QP_INIT_ATTR_XRCD) {
+		vxrcd = container_of(attr_ex->xrcd, struct verbs_xrcd, xrcd);
+		cmd->pd_handle	= vxrcd->handle;
+	} else {
+		if (!(attr_ex->comp_mask & IBV_QP_INIT_ATTR_PD))
+			return EINVAL;
+
+		cmd->pd_handle	= attr_ex->pd->handle;
+		cmd->send_cq_handle = attr_ex->send_cq->handle;
+
+		if (attr_ex->qp_type != IBV_QPT_XRC_SEND) {
+			cmd->recv_cq_handle = attr_ex->recv_cq->handle;
+			cmd->srq_handle = attr_ex->srq ? attr_ex->srq->handle : 0;
+		}
+	}
+
+	cmd->max_send_wr     = attr_ex->cap.max_send_wr;
+	cmd->max_recv_wr     = attr_ex->cap.max_recv_wr;
+	cmd->max_send_sge    = attr_ex->cap.max_send_sge;
+	cmd->max_recv_sge    = attr_ex->cap.max_recv_sge;
+	cmd->max_inline_data = attr_ex->cap.max_inline_data;
+	cmd->sq_sig_all	     = attr_ex->sq_sig_all;
+	cmd->qp_type         = attr_ex->qp_type;
+	cmd->is_srq	     = !!attr_ex->srq;
+	cmd->reserved	     = 0;
+
+	if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
+		return errno;
+
+	(void) VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
+
+	if (abi_ver > 3) {
+		attr_ex->cap.max_recv_sge    = resp->max_recv_sge;
+		attr_ex->cap.max_send_sge    = resp->max_send_sge;
+		attr_ex->cap.max_recv_wr     = resp->max_recv_wr;
+		attr_ex->cap.max_send_wr     = resp->max_send_wr;
+		attr_ex->cap.max_inline_data = resp->max_inline_data;
+	}
+
+	if (abi_ver == 4) {
+		struct ibv_create_qp_resp_v4 *resp_v4 =
+			(struct ibv_create_qp_resp_v4 *)resp;
+
+		memmove((void *)resp + sizeof *resp,
+			(void *)resp_v4 + sizeof *resp_v4,
+			resp_size - sizeof *resp);
+	} else if (abi_ver <= 3) {
+		struct ibv_create_qp_resp_v3 *resp_v3 =
+			(struct ibv_create_qp_resp_v3 *)resp;
+
+		memmove((void *)resp + sizeof *resp,
+			(void *)resp_v3 + sizeof *resp_v3,
+			resp_size - sizeof *resp);
+	}
+
+	qp->qp.handle		= resp->qp_handle;
+	qp->qp.qp_num		= resp->qpn;
+	qp->qp.context		= context;
+	qp->qp.qp_context	= attr_ex->qp_context;
+	qp->qp.pd		= attr_ex->pd;
+	qp->qp.send_cq		= attr_ex->send_cq;
+	qp->qp.recv_cq		= attr_ex->recv_cq;
+	qp->qp.srq		= attr_ex->srq;
+	qp->qp.qp_type		= attr_ex->qp_type;
+	qp->qp.state		= IBV_QPS_RESET;
+	qp->qp.events_completed = 0;
+	pthread_mutex_init(&qp->qp.mutex, NULL);
+	pthread_cond_init(&qp->qp.cond, NULL);
+
+	qp->comp_mask = 0;
+	if (vext_field_avail(struct verbs_qp, xrcd, vqp_sz) &&
+			    (attr_ex->comp_mask & IBV_QP_INIT_ATTR_XRCD)) {
+		qp->comp_mask |= VERBS_QP_XRCD;
+		qp->xrcd = vxrcd;
+	}
+
+	return 0;
+}
+
 int ibv_cmd_create_qp(struct ibv_pd *pd,
 		      struct ibv_qp *qp, struct ibv_qp_init_attr *attr,
 		      struct ibv_create_qp *cmd, size_t cmd_size,
@@ -618,7 +712,7 @@ int ibv_cmd_create_qp(struct ibv_pd *pd,
 	IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_QP, resp, resp_size);
 
 	cmd->user_handle     = (uintptr_t) qp;
-	cmd->pd_handle 	     = pd->handle;
+	cmd->pd_handle       = pd->handle;
 	cmd->send_cq_handle  = attr->send_cq->handle;
 	cmd->recv_cq_handle  = attr->recv_cq->handle;
 	cmd->srq_handle      = attr->srq ? attr->srq->handle : 0;
diff --git a/src/libibverbs.map b/src/libibverbs.map
index a4b089f..6db5291 100644
--- a/src/libibverbs.map
+++ b/src/libibverbs.map
@@ -104,5 +104,6 @@ IBVERBS_1.1 {
 		ibv_cmd_open_xrcd;
 		ibv_cmd_close_xrcd;
 		ibv_cmd_create_srq_ex;
+		ibv_cmd_create_qp_ex;
 
 } IBVERBS_1.0;
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH V8 libibverbs 5/7] Add ibv_open_qp
       [not found] ` <1374741488-30895-1-git-send-email-yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
                     ` (3 preceding siblings ...)
  2013-07-25  8:38   ` [PATCH V8 libibverbs 4/7] Add support for XRC QPs Yishai Hadas
@ 2013-07-25  8:38   ` Yishai Hadas
  2013-07-25  8:38   ` [PATCH V8 libibverbs 6/7] XRC man pages Yishai Hadas
  2013-07-25  8:38   ` [PATCH V8 libibverbs 7/7] Add XRC sample application Yishai Hadas
  6 siblings, 0 replies; 15+ messages in thread
From: Yishai Hadas @ 2013-07-25  8:38 UTC (permalink / raw)
  To: linux-rdma-u79uwXL29TY76Z2rM5mHXA, roland-BHEL68pLQRGGvPXPguhicg
  Cc: ogerlitz-VPRAkNaXOzVWk0Htik3J/w, tzahio-VPRAkNaXOzVWk0Htik3J/w,
	yishaih-VPRAkNaXOzVWk0Htik3J/w, Sean Hefty

From: Sean Hefty <sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

XRC receive QPs are shareable across multiple processes.  Allow
any process with access to the xrc domain to open an existing
QP.  After opening the QP, the process will receive events
related to the QP and be able to modify the QP.

Signed-off-by: Sean Hefty <sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Yishai Hadas <yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 include/infiniband/driver.h   |    5 ++++
 include/infiniband/kern-abi.h |   20 ++++++++++++++-
 include/infiniband/verbs.h    |   35 +++++++++++++++++++++++++++-
 src/cmd.c                     |   50 +++++++++++++++++++++++++++++++++++++++++
 src/libibverbs.map            |    1 +
 5 files changed, 108 insertions(+), 3 deletions(-)

diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h
index 91b5b12..f69962e 100644
--- a/include/infiniband/driver.h
+++ b/include/infiniband/driver.h
@@ -169,6 +169,11 @@ int ibv_cmd_create_qp_ex(struct ibv_context *context,
 			 struct ibv_qp_init_attr_ex *attr_ex,
 			 struct ibv_create_qp *cmd, size_t cmd_size,
 			 struct ibv_create_qp_resp *resp, size_t resp_size);
+int ibv_cmd_open_qp(struct ibv_context *context,
+		    struct verbs_qp *qp,  int vqp_sz,
+		    struct ibv_qp_open_attr *attr,
+		    struct ibv_open_qp *cmd, size_t cmd_size,
+		    struct ibv_create_qp_resp *resp, size_t resp_size);
 int ibv_cmd_query_qp(struct ibv_qp *qp, struct ibv_qp_attr *qp_attr,
 		     int attr_mask,
 		     struct ibv_qp_init_attr *qp_init_attr,
diff --git a/include/infiniband/kern-abi.h b/include/infiniband/kern-abi.h
index 65f3ffd..064f1aa 100644
--- a/include/infiniband/kern-abi.h
+++ b/include/infiniband/kern-abi.h
@@ -88,7 +88,8 @@ enum {
 	IB_USER_VERBS_CMD_POST_SRQ_RECV,
 	IB_USER_VERBS_CMD_OPEN_XRCD,
 	IB_USER_VERBS_CMD_CLOSE_XRCD,
-	IB_USER_VERBS_CMD_CREATE_XSRQ
+	IB_USER_VERBS_CMD_CREATE_XSRQ,
+	IB_USER_VERBS_CMD_OPEN_QP
 };
 
 /*
@@ -476,6 +477,20 @@ struct ibv_create_qp {
 	__u64 driver_data[0];
 };
 
+struct ibv_open_qp {
+	__u32 command;
+	__u16 in_words;
+	__u16 out_words;
+	__u64 response;
+	__u64 user_handle;
+	__u32 pd_handle;
+	__u32 qpn;
+	__u8  qp_type;
+	__u8  reserved[7];
+	__u64 driver_data[0];
+};
+
+/* also used for open response */
 struct ibv_create_qp_resp {
 	__u32 qp_handle;
 	__u32 qpn;
@@ -852,7 +867,8 @@ enum {
 	IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL_V2 = -1,
 	IB_USER_VERBS_CMD_OPEN_XRCD_V2 = -1,
 	IB_USER_VERBS_CMD_CLOSE_XRCD_V2 = -1,
-	IB_USER_VERBS_CMD_CREATE_XSRQ_V2 = -1
+	IB_USER_VERBS_CMD_CREATE_XSRQ_V2 = -1,
+	IB_USER_VERBS_CMD_OPEN_QP_V2 = -1
 };
 
 struct ibv_modify_srq_v3 {
diff --git a/include/infiniband/verbs.h b/include/infiniband/verbs.h
index aba8dd6..6437811 100644
--- a/include/infiniband/verbs.h
+++ b/include/infiniband/verbs.h
@@ -521,6 +521,22 @@ struct ibv_qp_init_attr_ex {
 	struct ibv_xrcd	       *xrcd;
 };
 
+enum ibv_qp_open_attr_mask {
+	IBV_QP_OPEN_ATTR_NUM		= 1 << 0,
+	IBV_QP_OPEN_ATTR_XRCD	        = 1 << 1,
+	IBV_QP_OPEN_ATTR_CONTEXT	= 1 << 2,
+	IBV_QP_OPEN_ATTR_TYPE		= 1 << 3,
+	IBV_QP_OPEN_ATTR_RESERVED	= 1 << 4
+};
+
+struct ibv_qp_open_attr {
+	uint32_t		comp_mask;
+	uint32_t		qp_num;
+	struct ibv_xrcd        *xrcd;
+	void		       *qp_context;
+	enum ibv_qp_type	qp_type;
+};
+
 enum ibv_qp_attr_mask {
 	IBV_QP_STATE			= 1 << 	0,
 	IBV_QP_CUR_STATE		= 1 << 	1,
@@ -552,7 +568,8 @@ enum ibv_qp_state {
 	IBV_QPS_RTS,
 	IBV_QPS_SQD,
 	IBV_QPS_SQE,
-	IBV_QPS_ERR
+	IBV_QPS_ERR,
+	IBV_QPS_UNKNOWN
 };
 
 enum ibv_mig_state {
@@ -828,6 +845,8 @@ enum verbs_context_mask {
 
 struct verbs_context {
 	/*  "grows up" - new fields go here */
+	struct ibv_qp *(*open_qp)(struct ibv_context *context,
+			struct ibv_qp_open_attr *attr);
 	struct ibv_qp *(*create_qp_ex)(struct ibv_context *context,
 			struct ibv_qp_init_attr_ex *qp_init_attr_ex);
 	int (*get_srq_num)(struct ibv_srq *srq, uint32_t *srq_num);
@@ -1221,6 +1240,20 @@ ibv_create_qp_ex(struct ibv_context *context, struct ibv_qp_init_attr_ex *qp_ini
 }
 
 /**
+ * ibv_open_qp - Open a shareable queue pair.
+ */
+static inline struct ibv_qp *
+ibv_open_qp(struct ibv_context *context, struct ibv_qp_open_attr *qp_open_attr)
+{
+	struct verbs_context *vctx = verbs_get_ctx_op(context, open_qp);
+	if (!vctx) {
+		errno = ENOSYS;
+		return NULL;
+	}
+	return vctx->open_qp(context, qp_open_attr);
+}
+
+/**
  * ibv_modify_qp - Modify a queue pair.
  */
 int ibv_modify_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,
diff --git a/src/cmd.c b/src/cmd.c
index 463b95b..7c88666 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -762,6 +762,56 @@ int ibv_cmd_create_qp(struct ibv_pd *pd,
 	return 0;
 }
 
+int ibv_cmd_open_qp(struct ibv_context *context, struct verbs_qp *qp,
+		    int vqp_sz,
+		    struct ibv_qp_open_attr *attr,
+		    struct ibv_open_qp *cmd, size_t cmd_size,
+		    struct ibv_create_qp_resp *resp, size_t resp_size)
+{
+	struct verbs_xrcd *xrcd;
+	IBV_INIT_CMD_RESP(cmd, cmd_size, OPEN_QP, resp, resp_size);
+
+	if (attr->comp_mask >= IBV_QP_OPEN_ATTR_RESERVED)
+		return ENOSYS;
+
+	if (!(attr->comp_mask & IBV_QP_OPEN_ATTR_XRCD) ||
+	    !(attr->comp_mask & IBV_QP_OPEN_ATTR_NUM) ||
+	    !(attr->comp_mask & IBV_QP_OPEN_ATTR_TYPE))
+		return EINVAL;
+
+	xrcd = container_of(attr->xrcd, struct verbs_xrcd, xrcd);
+	cmd->user_handle = (uintptr_t) qp;
+	cmd->pd_handle   = xrcd->handle;
+	cmd->qpn         = attr->qp_num;
+	cmd->qp_type     = attr->qp_type;
+
+	if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
+		return errno;
+
+	VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
+
+	qp->qp.handle     = resp->qp_handle;
+	qp->qp.context    = context;
+	qp->qp.qp_context = attr->qp_context;
+	qp->qp.pd	  = NULL;
+	qp->qp.send_cq	  = NULL;
+	qp->qp.recv_cq    = NULL;
+	qp->qp.srq	  = NULL;
+	qp->qp.qp_num	  = attr->qp_num;
+	qp->qp.qp_type	  = attr->qp_type;
+	qp->qp.state	  = IBV_QPS_UNKNOWN;
+	qp->qp.events_completed = 0;
+	pthread_mutex_init(&qp->qp.mutex, NULL);
+	pthread_cond_init(&qp->qp.cond, NULL);
+	qp->comp_mask = 0;
+	if (vext_field_avail(struct verbs_qp, xrcd, vqp_sz)) {
+		qp->comp_mask = VERBS_QP_XRCD;
+		qp->xrcd	 = xrcd;
+	}
+
+	return 0;
+}
+
 int ibv_cmd_query_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,
 		     int attr_mask,
 		     struct ibv_qp_init_attr *init_attr,
diff --git a/src/libibverbs.map b/src/libibverbs.map
index 6db5291..bbc6de1 100644
--- a/src/libibverbs.map
+++ b/src/libibverbs.map
@@ -105,5 +105,6 @@ IBVERBS_1.1 {
 		ibv_cmd_close_xrcd;
 		ibv_cmd_create_srq_ex;
 		ibv_cmd_create_qp_ex;
+		ibv_cmd_open_qp;
 
 } IBVERBS_1.0;
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH V8 libibverbs 6/7] XRC man pages
       [not found] ` <1374741488-30895-1-git-send-email-yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
                     ` (4 preceding siblings ...)
  2013-07-25  8:38   ` [PATCH V8 libibverbs 5/7] Add ibv_open_qp Yishai Hadas
@ 2013-07-25  8:38   ` Yishai Hadas
  2013-07-25  8:38   ` [PATCH V8 libibverbs 7/7] Add XRC sample application Yishai Hadas
  6 siblings, 0 replies; 15+ messages in thread
From: Yishai Hadas @ 2013-07-25  8:38 UTC (permalink / raw)
  To: linux-rdma-u79uwXL29TY76Z2rM5mHXA, roland-BHEL68pLQRGGvPXPguhicg
  Cc: ogerlitz-VPRAkNaXOzVWk0Htik3J/w, tzahio-VPRAkNaXOzVWk0Htik3J/w,
	yishaih-VPRAkNaXOzVWk0Htik3J/w, Sean Hefty

From: Sean Hefty <sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

Signed-off-by: Sean Hefty <sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Yishai Hadas <yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 Makefile.am             |    8 +++-
 man/ibv_create_qp_ex.3  |   83 +++++++++++++++++++++++++++++++++++++++++++++++
 man/ibv_create_srq_ex.3 |   71 ++++++++++++++++++++++++++++++++++++++++
 man/ibv_get_srq_num.3   |   32 ++++++++++++++++++
 man/ibv_open_qp.3       |   51 +++++++++++++++++++++++++++++
 man/ibv_open_xrcd.3     |   76 +++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 319 insertions(+), 2 deletions(-)
 create mode 100644 man/ibv_create_qp_ex.3
 create mode 100644 man/ibv_create_srq_ex.3
 create mode 100644 man/ibv_get_srq_num.3
 create mode 100644 man/ibv_open_qp.3
 create mode 100644 man/ibv_open_xrcd.3

diff --git a/Makefile.am b/Makefile.am
index 40e83be..aa6097a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -54,7 +54,9 @@ man_MANS = man/ibv_asyncwatch.1 man/ibv_devices.1 man/ibv_devinfo.1	\
     man/ibv_post_srq_recv.3 man/ibv_query_device.3 man/ibv_query_gid.3	\
     man/ibv_query_pkey.3 man/ibv_query_port.3 man/ibv_query_qp.3	\
     man/ibv_query_srq.3 man/ibv_rate_to_mult.3 man/ibv_reg_mr.3		\
-    man/ibv_req_notify_cq.3 man/ibv_resize_cq.3 man/ibv_rate_to_mbps.3
+    man/ibv_req_notify_cq.3 man/ibv_resize_cq.3 man/ibv_rate_to_mbps.3  \
+    man/ibv_create_qp_ex.3 man/ibv_create_srq_ex.3 man/ibv_open_xrcd.3  \
+    man/ibv_get_srq_num.3 man/ibv_open_qp.3
 
 DEBIAN = debian/changelog debian/compat debian/control debian/copyright \
     debian/ibverbs-utils.install debian/libibverbs1.install \
@@ -89,6 +91,7 @@ install-data-hook:
 	$(RM) ibv_node_type_str.3 && \
 	$(RM) ibv_port_state_str.3 && \
 	$(RM) mbps_to_ibv_rate.3 && \
+	$(RM) ibv_close_xrcd.3 && \
 	$(LN_S) ibv_get_async_event.3 ibv_ack_async_event.3 && \
 	$(LN_S) ibv_get_cq_event.3 ibv_ack_cq_events.3 && \
 	$(LN_S) ibv_open_device.3 ibv_close_device.3 && \
@@ -105,4 +108,5 @@ install-data-hook:
 	$(LN_S) ibv_rate_to_mult.3 mult_to_ibv_rate.3 && \
 	$(LN_S) ibv_event_type_str.3 ibv_node_type_str.3 && \
 	$(LN_S) ibv_event_type_str.3 ibv_port_state_str.3 && \
-	$(LN_S) ibv_rate_to_mbps.3 mbps_to_ibv_rate.3
+	$(LN_S) ibv_rate_to_mbps.3 mbps_to_ibv_rate.3 && \
+	$(LN_S) ibv_open_xrcd.3 ibv_close_xrcd.3
diff --git a/man/ibv_create_qp_ex.3 b/man/ibv_create_qp_ex.3
new file mode 100644
index 0000000..f772a57
--- /dev/null
+++ b/man/ibv_create_qp_ex.3
@@ -0,0 +1,83 @@
+.\" -*- nroff -*-
+.\"
+.TH IBV_CREATE_QP_EX 3 2013-06-26 libibverbs "Libibverbs Programmer's Manual"
+.SH "NAME"
+ibv_create_qp_ex, ibv_destroy_qp \- create or destroy a queue pair (QP)
+.SH "SYNOPSIS"
+.nf
+.B #include <infiniband/verbs.h>
+.sp
+.BI "struct ibv_qp *ibv_create_qp_ex(struct ibv_context " "*context" ,
+.BI "                                struct ibv_qp_init_attr_ex " "*qp_init_attr" );
+.sp
+.BI "int ibv_destroy_qp(struct ibv_qp " "*qp" );
+.fi
+.SH "DESCRIPTION"
+.B ibv_create_qp_ex()
+creates a queue pair (QP) associated with the protection domain
+.I pd\fR.
+The argument
+.I qp_init_attr_ex
+is an ibv_qp_init_attr_ex struct, as defined in <infiniband/verbs.h>.
+.PP
+.nf
+struct ibv_qp_init_attr_ex {
+.in +8
+void                   *qp_context;     /* Associated context of the QP */
+struct ibv_cq          *send_cq;        /* CQ to be associated with the Send Queue (SQ) */
+struct ibv_cq          *recv_cq;        /* CQ to be associated with the Receive Queue (RQ) */
+struct ibv_srq         *srq;            /* SRQ handle if QP is to be associated with an SRQ, otherwise NULL */
+struct ibv_qp_cap       cap;            /* QP capabilities */
+enum ibv_qp_type        qp_type;        /* QP Transport Service Type: IBV_QPT_RC, IBV_QPT_UC, IBV_QPT_UD or IBV_QPT_RAW_PACKET */
+int                     sq_sig_all;     /* If set, each Work Request (WR) submitted to the SQ generates a completion entry */
+uint32_t                comp_mask;	/* Identifies valid fields */
+struct ibv_pd          *pd;		/* PD to be associated with the QP */
+struct ibv_xrcd        *xrcd;		/* XRC domain to be associated with the target QP */
+enum ibv_qp_create_flags create_flags;	/* Creation flags for this QP */
+.in -8
+};
+.sp
+.nf
+struct ibv_qp_cap {
+.in +8
+uint32_t                max_send_wr;    /* Requested max number of outstanding WRs in the SQ */
+uint32_t                max_recv_wr;    /* Requested max number of outstanding WRs in the RQ */
+uint32_t                max_send_sge;   /* Requested max number of scatter/gather (s/g) elements in a WR in the SQ */
+uint32_t                max_recv_sge;   /* Requested max number of s/g elements in a WR in the SQ */
+uint32_t                max_inline_data;/* Requested max number of data (bytes) that can be posted inline to the SQ, otherwise 0 */
+.in -8
+};
+.fi
+.PP
+The function
+.B ibv_create_qp_ex()
+will update the
+.I qp_init_attr_ex\fB\fR->cap
+struct with the actual \s-1QP\s0 values of the QP that was created;
+the values will be greater than or equal to the values requested.
+.PP
+.B ibv_destroy_qp()
+destroys the QP
+.I qp\fR.
+.SH "RETURN VALUE"
+.B ibv_create_qp_ex()
+returns a pointer to the created QP, or NULL if the request fails.
+Check the QP number (\fBqp_num\fR) in the returned QP.
+.PP
+.B ibv_destroy_qp()
+returns 0 on success, or the value of errno on failure (which indicates the failure reason).
+.SH "NOTES"
+.PP
+The attributes max_recv_wr and max_recv_sge are ignored by
+.B ibv_create_qp_ex()
+if the QP is to be associated with an SRQ.
+.PP
+.B ibv_destroy_qp()
+fails if the QP is attached to a multicast group.
+.SH "SEE ALSO"
+.BR ibv_alloc_pd (3),
+.BR ibv_modify_qp (3),
+.BR ibv_query_qp (3)
+.SH "AUTHORS"
+.TP
+Yishai Hadas <yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
diff --git a/man/ibv_create_srq_ex.3 b/man/ibv_create_srq_ex.3
new file mode 100644
index 0000000..9151d6e
--- /dev/null
+++ b/man/ibv_create_srq_ex.3
@@ -0,0 +1,71 @@
+.\" -*- nroff -*-
+.\"
+.TH IBV_CREATE_SRQ_EX 3 2013-06-26 libibverbs "Libibverbs Programmer's Manual"
+.SH "NAME"
+ibv_create_srq_ex, ibv_destroy_srq \- create or destroy a shared receive queue (SRQ)
+.SH "SYNOPSIS"
+.nf
+.B #include <infiniband/verbs.h>
+.sp
+.BI "struct ibv_srq *ibv_create_srq_ex(struct ibv_context " "*context" ", struct "
+.BI "                               ibv_srq_init_attr_ex " "*srq_init_attr_ex" );
+.sp
+.BI "int ibv_destroy_srq(struct ibv_srq " "*srq" );
+.fi
+.SH "DESCRIPTION"
+.B ibv_create_srq_ex()
+creates a shared receive queue (SRQ) supporting both basic and xrc modes.
+The argument
+.I srq_init_attr_ex
+is an ibv_srq_init_attr_ex struct, as defined in <infiniband/verbs.h>.
+.PP
+.nf
+struct ibv_srq_init_attr_ex {
+.in +8
+void                   *srq_context;    /* Associated context of the SRQ */
+struct ibv_srq_attr     attr;           /* SRQ attributes */
+uint32_t                comp_mask;      /* Identifies valid fields */
+enum ibv_srq_type       srq_type;       /* Basic / XRC */
+struct ibv_pd          *pd;             /* PD associated with the SRQ */
+struct ibv_xrcd        *xrcd;           /* XRC domain to associate with the SRQ */
+struct ibv_cq          *cq;             /* CQ to associate with the SRQ for XRC mode */
+.in -8
+};
+.sp
+.nf
+struct ibv_srq_attr {
+.in +8
+uint32_t                max_wr;         /* Requested max number of outstanding work requests (WRs) in the SRQ */
+uint32_t                max_sge;        /* Requested max number of scatter elements per WR */
+uint32_t                srq_limit;      /* The limit value of the SRQ */
+.in -8
+};
+.fi
+.PP
+The function
+.B ibv_create_srq_ex()
+will update the
+.I srq_init_attr_ex
+struct with the original values of the SRQ that was created; the
+values of max_wr and max_sge will be greater than or equal to the
+values requested.
+.PP
+.B ibv_destroy_srq()
+destroys the SRQ
+.I srq\fR.
+.SH "RETURN VALUE"
+.B ibv_create_srq_ex()
+returns a pointer to the created SRQ, or NULL if the request fails.
+.PP
+.B ibv_destroy_srq()
+returns 0 on success, or the value of errno on failure (which indicates the failure reason).
+.SH "NOTES"
+.B ibv_destroy_srq()
+fails if any queue pair is still associated with this SRQ.
+.SH "SEE ALSO"
+.BR ibv_alloc_pd (3),
+.BR ibv_modify_srq (3),
+.BR ibv_query_srq (3)
+.SH "AUTHORS"
+.TP
+Yishai Hadas <yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
diff --git a/man/ibv_get_srq_num.3 b/man/ibv_get_srq_num.3
new file mode 100644
index 0000000..00e4fb4
--- /dev/null
+++ b/man/ibv_get_srq_num.3
@@ -0,0 +1,32 @@
+.\" -*- nroff -*-
+.\"
+.TH IBV_GET_SRQ_NUM 3 2013-06-26 libibverbs "Libibverbs Programmer's Manual"
+.SH "NAME"
+ibv_get_srq_num  \- return srq number associated with the given shared receive queue (SRQ)
+.SH "SYNOPSIS"
+.nf
+.B #include <infiniband/verbs.h>
+.sp
+.BI "int ibv_get_srq_num(struct ibv_srq " "*srq" ,
+.BI "                    uint32_t " "*srq_num" );
+.fi
+.SH "DESCRIPTION"
+.B ibv_get_srq_num()
+return srq number associated with the given shared receive queue
+The argument
+.I srq
+is an ibv_srq struct, as defined in <infiniband/verbs.h>.
+.I srq_num
+is an output parameter that holds the returned srq number.
+.PP
+.nf
+.SH "RETURN VALUE"
+.B ibv_get_srq_num()
+returns 0 on success, or the value of errno on failure (which indicates the failure reason).
+.SH "SEE ALSO"
+.BR ibv_alloc_pd (3),
+.BR ibv_modify_srq (3),
+.BR ibv_create_srq_ex (3)
+.SH "AUTHORS"
+.TP
+Yishai Hadas <yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
diff --git a/man/ibv_open_qp.3 b/man/ibv_open_qp.3
new file mode 100644
index 0000000..71b5d46
--- /dev/null
+++ b/man/ibv_open_qp.3
@@ -0,0 +1,51 @@
+.\" -*- nroff -*-
+.\"
+.TH IBV_OPEN_QP 3 2011-08-12 libibverbs "Libibverbs Programmer's Manual"
+.SH "NAME"
+ibv_open_qp \- open a shareable queue pair (QP)
+.SH "SYNOPSIS"
+.nf
+.B #include <infiniband/verbs.h>
+.sp
+.BI "struct ibv_qp *ibv_open_qp(struct ibv_context " "*context" ,
+.BI "                           struct ibv_qp_open_attr " "*qp_open_attr" );
+.fi
+.SH "DESCRIPTION"
+.B ibv_open_qp()
+opens an existing queue pair (QP) associated with the extended protection domain
+.I xrcd\fR.
+The argument
+.I qp_open_attr
+is an ibv_qp_open_attr struct, as defined in <infiniband/verbs.h>.
+.PP
+.nf
+struct ibv_qp_open_attr {
+.in +8
+uint32_t          comp_mask;  /* Identifies valid fields */
+uint32_t          qp_num;     /* QP number */
+struct            *ibv_xrcd;  /* XRC domain */
+void             *qp_context; /* User defined opaque value */
+enum ibv_qp_type  qp_type;    /* QP transport service type */
+.fi
+.PP
+.B ibv_destroy_qp()
+closes the opened QP and destroys the underlying QP if it has no
+other references.
+.I qp\fR.
+.SH "RETURN VALUE"
+.B ibv_open_qp()
+returns a pointer to the opened QP, or NULL if the request fails.
+Check the QP number (\fBqp_num\fR) in the returned QP.
+.SH "NOTES"
+.B ibv_open_qp()
+will fail if a it is asked to open a QP that does not exist within
+the xrcd with the specified qp_num and qp_type.
+.SH "SEE ALSO"
+.BR ibv_alloc_pd (3),
+.BR ibv_create_qp (3),
+.BR ibv_create_qp_ex (3),
+.BR ibv_modify_qp (3),
+.BR ibv_query_qp (3)
+.SH "AUTHORS"
+.TP
+Sean Hefty <sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
diff --git a/man/ibv_open_xrcd.3 b/man/ibv_open_xrcd.3
new file mode 100644
index 0000000..b9724bf
--- /dev/null
+++ b/man/ibv_open_xrcd.3
@@ -0,0 +1,76 @@
+.\" -*- nroff -*-
+.\"
+.TH IBV_OPEN_XRCD 3 2011-06-17 libibverbs "Libibverbs Programmer's Manual"
+.SH "NAME"
+ibv_open_xrcd, ibv_close_xrcd \- open or close an XRC protection domain (XRCDs)
+.SH "SYNOPSIS"
+.nf
+.B #include <infiniband/verbs.h>
+.sp
+.BI "struct ibv_xrcd *ibv_open_xrcd(struct ibv_context " "*context" ","
+.BI "                               struct ibv_xrcd_init_attr " "*xrcd_init_attr" );
+.sp
+.BI "int ibv_close_xrcd(struct ibv_xrcd " "*xrcd" );
+.fi
+.SH "DESCRIPTION"
+.B ibv_open_xrcd()
+open an XRC domain for the RDMA device context
+.I context
+.I xrcd_init_attr
+is an ibv_xrcd_init_attr struct, as defined in <infiniband/verbs.h>.
+.PP
+.nf
+struct ibv_xrcd_init_attr {
+.in +8
+uint32_t         comp_mask;  /* Identifies valid fields */
+int              fd;
+int              oflag;
+.fi
+.PP
+.I fd
+is the file descriptor to associate with the XRCD.
+.I oflag
+describes the desired creation attributes.  It is a bitwise OR of zero or more
+of the following flags:
+.PP
+.TP
+.B O_CREAT
+Indicates that an XRCD should be created and associated with the inode referenced
+by the given fd.  If the XRCD exists, this flag has no effect except as noted under
+.BR O_EXCL
+below.\fR
+.TP
+.B O_EXCL
+If
+.BR O_EXCL
+and
+.BR O_CREAT
+are set, open will fail if an XRCD associated with the inode exists.
+.PP
+If
+.I fd
+equals -1, no inode is associated with the XRCD. To indicate that XRCD should be created, use
+.I oflag
+=
+.B O_CREAT\fR.
+.PP
+.B ibv_close_xrcd()
+closes the XRCD
+.I xrcd\fR.
+If this is the last reference, the XRCD will be destroyed.
+.SH "RETURN VALUE"
+.B ibv_open_xrcd()
+returns a pointer to the opened XRCD, or NULL if the request fails.
+.PP
+.B ibv_close_xrcd()
+returns 0 on success, or the value of errno on failure (which indicates the
+failure reason).
+.SH "NOTES"
+.B ibv_close_xrcd()
+may fail if any other resource is still associated with the XRCD being closed.
+.SH "SEE ALSO"
+.BR ibv_create_srq_ex (3),
+.BR ibv_create_qp_ex (3),
+.SH "AUTHORS"
+.TP
+Sean Hefty <sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH V8 libibverbs 7/7] Add XRC sample application
       [not found] ` <1374741488-30895-1-git-send-email-yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
                     ` (5 preceding siblings ...)
  2013-07-25  8:38   ` [PATCH V8 libibverbs 6/7] XRC man pages Yishai Hadas
@ 2013-07-25  8:38   ` Yishai Hadas
  6 siblings, 0 replies; 15+ messages in thread
From: Yishai Hadas @ 2013-07-25  8:38 UTC (permalink / raw)
  To: linux-rdma-u79uwXL29TY76Z2rM5mHXA, roland-BHEL68pLQRGGvPXPguhicg
  Cc: ogerlitz-VPRAkNaXOzVWk0Htik3J/w, tzahio-VPRAkNaXOzVWk0Htik3J/w,
	yishaih-VPRAkNaXOzVWk0Htik3J/w, Jay Sternberg, Sean Hefty

From: Jay Sternberg <jay.e.sternberg-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

Signed-off-by: Jay Sternberg <jay.e.sternberg-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Sean Hefty <sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Yishai Hadas <yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 Makefile.am              |    4 +-
 examples/xsrq_pingpong.c |  890 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 893 insertions(+), 1 deletions(-)
 create mode 100644 examples/xsrq_pingpong.c

diff --git a/Makefile.am b/Makefile.am
index aa6097a..a6767de 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -18,7 +18,7 @@ src_libibverbs_la_DEPENDENCIES = $(srcdir)/src/libibverbs.map
 
 bin_PROGRAMS = examples/ibv_devices examples/ibv_devinfo \
     examples/ibv_asyncwatch examples/ibv_rc_pingpong examples/ibv_uc_pingpong \
-    examples/ibv_ud_pingpong examples/ibv_srq_pingpong
+    examples/ibv_ud_pingpong examples/ibv_srq_pingpong examples/ibv_xsrq_pingpong
 examples_ibv_devices_SOURCES = examples/device_list.c
 examples_ibv_devices_LDADD = $(top_builddir)/src/libibverbs.la
 examples_ibv_devinfo_SOURCES = examples/devinfo.c
@@ -31,6 +31,8 @@ examples_ibv_ud_pingpong_SOURCES = examples/ud_pingpong.c examples/pingpong.c
 examples_ibv_ud_pingpong_LDADD = $(top_builddir)/src/libibverbs.la
 examples_ibv_srq_pingpong_SOURCES = examples/srq_pingpong.c examples/pingpong.c
 examples_ibv_srq_pingpong_LDADD = $(top_builddir)/src/libibverbs.la
+examples_ibv_xsrq_pingpong_SOURCES = examples/xsrq_pingpong.c examples/pingpong.c
+examples_ibv_xsrq_pingpong_LDADD = $(top_builddir)/src/libibverbs.la
 examples_ibv_asyncwatch_SOURCES = examples/asyncwatch.c
 examples_ibv_asyncwatch_LDADD = $(top_builddir)/src/libibverbs.la
 
diff --git a/examples/xsrq_pingpong.c b/examples/xsrq_pingpong.c
new file mode 100644
index 0000000..b5fc1b6
--- /dev/null
+++ b/examples/xsrq_pingpong.c
@@ -0,0 +1,890 @@
+/*
+ * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2011 Intel Corporation, Inc.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netdb.h>
+#include <malloc.h>
+#include <getopt.h>
+#include <arpa/inet.h>
+#include <time.h>
+
+#include "pingpong.h"
+
+#define MSG_FORMAT "%04x:%06x:%06x:%06x:%04x"
+#define MSG_SIZE   31
+#define MSG_SSCAN  "%x:%x:%x:%x:%x"
+#define ADDR_FORMAT \
+	"%8s: LID %04x, QPN RECV %06x SEND %06x, PSN %06x, SRQN %04x\n"
+static int page_size;
+
+struct pingpong_dest {
+	int lid;
+	int recv_qpn;
+	int send_qpn;
+	int recv_psn;
+	int send_psn;
+	int srqn;
+	int pp_cnt;
+};
+
+struct pingpong_context {
+	struct ibv_context	*context;
+	struct ibv_comp_channel *channel;
+	struct ibv_pd		*pd;
+	struct ibv_mr		*mr;
+	struct ibv_cq		*send_cq;
+	struct ibv_cq		*recv_cq;
+	struct ibv_srq		*srq;
+	struct ibv_xrcd		*xrcd;
+	struct ibv_qp		**recv_qp;
+	struct ibv_qp		**send_qp;
+	struct pingpong_dest	*rem_dest;
+	void			*buf;
+	int			 lid;
+	int			 sl;
+	enum ibv_mtu		 mtu;
+	int			 ib_port;
+	int			 fd;
+	int			 size;
+	int			 num_clients;
+	int			 num_tests;
+	int			 use_event;
+};
+
+struct pingpong_context ctx;
+
+
+static int open_device(char *ib_devname)
+{
+	struct ibv_device **dev_list;
+	int i = 0;
+
+	dev_list = ibv_get_device_list(NULL);
+	if (!dev_list) {
+		fprintf(stderr, "Failed to get IB devices list");
+		return -1;
+	}
+
+	if (ib_devname) {
+		for (; dev_list[i]; ++i) {
+			if (!strcmp(ibv_get_device_name(dev_list[i]), ib_devname))
+				break;
+		}
+	}
+	if (!dev_list[i]) {
+		fprintf(stderr, "IB device %s not found\n",
+			ib_devname ? ib_devname : "");
+		return -1;
+	}
+
+	ctx.context = ibv_open_device(dev_list[i]);
+	if (!ctx.context) {
+		fprintf(stderr, "Couldn't get context for %s\n",
+			ibv_get_device_name(dev_list[i]));
+		return -1;
+	}
+
+	ibv_free_device_list(dev_list);
+	return 0;
+}
+
+static int create_qps(void)
+{
+	struct ibv_qp_init_attr_ex init;
+	struct ibv_qp_attr mod;
+	int i;
+
+	for (i = 0; i < ctx.num_clients; ++i) {
+
+		memset(&init, 0, sizeof init);
+		init.qp_type = IBV_QPT_XRC_RECV;
+		init.comp_mask = IBV_QP_INIT_ATTR_XRCD;
+		init.xrcd = ctx.xrcd;
+
+		ctx.recv_qp[i] = ibv_create_qp_ex(ctx.context, &init);
+		if (!ctx.recv_qp[i])  {
+			fprintf(stderr, "Couldn't create recv QP[%d] errno %d\n",
+				i, errno);
+			return 1;
+		}
+
+		mod.qp_state        = IBV_QPS_INIT;
+		mod.pkey_index      = 0;
+		mod.port_num        = ctx.ib_port;
+		mod.qp_access_flags = IBV_ACCESS_REMOTE_WRITE | IBV_ACCESS_REMOTE_READ;
+
+		if (ibv_modify_qp(ctx.recv_qp[i], &mod,
+				  IBV_QP_STATE | IBV_QP_PKEY_INDEX |
+				  IBV_QP_PORT | IBV_QP_ACCESS_FLAGS)) {
+			fprintf(stderr, "Failed to modify recv QP[%d] to INIT\n", i);
+			return 1;
+		}
+
+		memset(&init, 0, sizeof init);
+		init.qp_type	      = IBV_QPT_XRC_SEND;
+		init.send_cq	      = ctx.send_cq;
+		init.cap.max_send_wr  = ctx.num_clients * ctx.num_tests;
+		init.cap.max_send_sge = 1;
+		init.comp_mask	      = IBV_QP_INIT_ATTR_PD;
+		init.pd		      = ctx.pd;
+
+		ctx.send_qp[i] = ibv_create_qp_ex(ctx.context, &init);
+		if (!ctx.send_qp[i])  {
+			fprintf(stderr, "Couldn't create send QP[%d] errno %d\n",
+				i, errno);
+			return 1;
+		}
+
+		mod.qp_state        = IBV_QPS_INIT;
+		mod.pkey_index      = 0;
+		mod.port_num        = ctx.ib_port;
+		mod.qp_access_flags = 0;
+
+		if (ibv_modify_qp(ctx.send_qp[i], &mod,
+				  IBV_QP_STATE | IBV_QP_PKEY_INDEX |
+				  IBV_QP_PORT | IBV_QP_ACCESS_FLAGS)) {
+			fprintf(stderr, "Failed to modify send QP[%d] to INIT\n", i);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static int pp_init_ctx(char *ib_devname)
+{
+	struct ibv_srq_init_attr_ex attr;
+	struct ibv_xrcd_init_attr xrcd_attr;
+
+	ctx.recv_qp = calloc(ctx.num_clients, sizeof *ctx.recv_qp);
+	ctx.send_qp = calloc(ctx.num_clients, sizeof *ctx.send_qp);
+	ctx.rem_dest = calloc(ctx.num_clients, sizeof *ctx.rem_dest);
+	if (!ctx.recv_qp || !ctx.send_qp || !ctx.rem_dest)
+		return 1;
+
+	if (open_device(ib_devname)) {
+		fprintf(stderr, "Failed to open device\n");
+		return 1;
+	}
+
+	ctx.lid = pp_get_local_lid(ctx.context, ctx.ib_port);
+	if (ctx.lid < 0) {
+		fprintf(stderr, "Failed to get SLID\n");
+		return 1;
+	}
+
+	ctx.buf = memalign(page_size, ctx.size);
+	if (!ctx.buf) {
+		fprintf(stderr, "Couldn't allocate work buf.\n");
+		return 1;
+	}
+
+	memset(ctx.buf, 0, ctx.size);
+
+	if (ctx.use_event) {
+		ctx.channel = ibv_create_comp_channel(ctx.context);
+		if (!ctx.channel) {
+			fprintf(stderr, "Couldn't create completion channel\n");
+			return 1;
+		}
+	}
+
+	ctx.pd = ibv_alloc_pd(ctx.context);
+	if (!ctx.pd) {
+		fprintf(stderr, "Couldn't allocate PD\n");
+		return 1;
+	}
+
+	ctx.mr = ibv_reg_mr(ctx.pd, ctx.buf, ctx.size, IBV_ACCESS_LOCAL_WRITE);
+	if (!ctx.mr) {
+		fprintf(stderr, "Couldn't register MR\n");
+		return 1;
+	}
+
+	ctx.fd = open("/tmp/xrc_domain", O_RDONLY | O_CREAT, S_IRUSR | S_IRGRP);
+	if (ctx.fd < 0) {
+		fprintf(stderr,
+			"Couldn't create the file for the XRC Domain "
+			"but not stopping %d\n", errno);
+		ctx.fd = -1;
+	}
+
+	memset(&xrcd_attr, 0, sizeof xrcd_attr);
+	xrcd_attr.comp_mask = IBV_XRCD_INIT_ATTR_FD | IBV_XRCD_INIT_ATTR_OFLAGS;
+	xrcd_attr.fd = ctx.fd;
+	xrcd_attr.oflags = O_CREAT;
+	ctx.xrcd = ibv_open_xrcd(ctx.context, &xrcd_attr);
+	if (!ctx.xrcd) {
+		fprintf(stderr, "Couldn't Open the XRC Domain %d\n", errno);
+		return 1;
+	}
+
+	ctx.recv_cq = ibv_create_cq(ctx.context, ctx.num_clients, &ctx.recv_cq,
+				    ctx.channel, 0);
+	if (!ctx.recv_cq) {
+		fprintf(stderr, "Couldn't create recv CQ\n");
+		return 1;
+	}
+
+	if (ctx.use_event) {
+		if (ibv_req_notify_cq(ctx.recv_cq, 0)) {
+			fprintf(stderr, "Couldn't request CQ notification\n");
+			return 1;
+		}
+	}
+
+	ctx.send_cq = ibv_create_cq(ctx.context, ctx.num_clients, NULL, NULL, 0);
+	if (!ctx.send_cq) {
+		fprintf(stderr, "Couldn't create send CQ\n");
+		return 1;
+	}
+
+	memset(&attr, 0, sizeof attr);
+	attr.attr.max_wr = ctx.num_clients;
+	attr.attr.max_sge = 1;
+	attr.comp_mask = IBV_SRQ_INIT_ATTR_TYPE | IBV_SRQ_INIT_ATTR_XRCD |
+			 IBV_SRQ_INIT_ATTR_CQ | IBV_SRQ_INIT_ATTR_PD;
+	attr.srq_type = IBV_SRQT_XRC;
+	attr.xrcd = ctx.xrcd;
+	attr.cq = ctx.recv_cq;
+	attr.pd = ctx.pd;
+
+	ctx.srq = ibv_create_srq_ex(ctx.context, &attr);
+	if (!ctx.srq)  {
+		fprintf(stderr, "Couldn't create SRQ\n");
+		return 1;
+	}
+
+	if (create_qps())
+		return 1;
+
+	return 0;
+}
+
+static int send_local_dest(int sockfd, int index)
+{
+	char msg[MSG_SIZE];
+	uint32_t srq_num;
+
+	ctx.rem_dest[index].recv_psn = lrand48() & 0xffffff;
+	if (ibv_get_srq_num(ctx.srq, &srq_num)) {
+		fprintf(stderr, "Couldn't get SRQ num\n");
+		return -1;
+	}
+
+	printf(ADDR_FORMAT, "local", ctx.lid, ctx.recv_qp[index]->qp_num,
+		ctx.send_qp[index]->qp_num, ctx.rem_dest[index].recv_psn,
+		srq_num);
+
+	sprintf(msg, MSG_FORMAT, ctx.lid, ctx.recv_qp[index]->qp_num,
+		ctx.send_qp[index]->qp_num, ctx.rem_dest[index].recv_psn,
+		srq_num);
+
+	if (write(sockfd, msg, MSG_SIZE) != MSG_SIZE) {
+		fprintf(stderr, "Couldn't send local address\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int recv_remote_dest(int sockfd, int index)
+{
+	struct pingpong_dest *rem_dest;
+	char msg[MSG_SIZE];
+	int n = 0, r;
+
+	while (n < MSG_SIZE) {
+		r = read(sockfd, msg + n, MSG_SIZE - n);
+		if (r < 0) {
+			perror("client read");
+			fprintf(stderr,
+				"%d/%d: Couldn't read remote address [%d]\n",
+				n, MSG_SIZE, index);
+			return -1;
+		}
+		n += r;
+	}
+
+	rem_dest = &ctx.rem_dest[index];
+	sscanf(msg, MSG_SSCAN, &rem_dest->lid, &rem_dest->recv_qpn,
+	       &rem_dest->send_qpn, &rem_dest->send_psn, &rem_dest->srqn);
+
+	printf(ADDR_FORMAT, "remote", rem_dest->lid, rem_dest->recv_qpn,
+	       rem_dest->send_qpn, rem_dest->send_psn, rem_dest->srqn);
+
+	return 0;
+}
+
+static int connect_qps(int index)
+{
+	struct ibv_qp_attr attr;
+
+	memset(&attr, 0, sizeof attr);
+	attr.qp_state	      = IBV_QPS_RTR;
+	attr.dest_qp_num      = ctx.rem_dest[index].send_qpn;
+	attr.path_mtu	      = ctx.mtu;
+	attr.rq_psn	      = ctx.rem_dest[index].send_psn;
+	attr.min_rnr_timer    = 12;
+	attr.ah_attr.dlid     = ctx.rem_dest[index].lid;
+	attr.ah_attr.sl	      = ctx.sl;
+	attr.ah_attr.port_num = ctx.ib_port;
+
+	if (ibv_modify_qp(ctx.recv_qp[index], &attr,
+			  IBV_QP_STATE | IBV_QP_AV | IBV_QP_PATH_MTU |
+			  IBV_QP_DEST_QPN | IBV_QP_RQ_PSN |
+			  IBV_QP_MAX_DEST_RD_ATOMIC | IBV_QP_MIN_RNR_TIMER)) {
+		fprintf(stderr, "Failed to modify send QP[%d] to RTR\n", index);
+		return 1;
+	}
+
+	memset(&attr, 0, sizeof attr);
+	attr.qp_state = IBV_QPS_RTS;
+	attr.timeout = 14;
+	attr.sq_psn = ctx.rem_dest[index].recv_psn;
+
+	if (ibv_modify_qp(ctx.recv_qp[index], &attr,
+			  IBV_QP_STATE | IBV_QP_TIMEOUT | IBV_QP_SQ_PSN)) {
+		fprintf(stderr, "Failed to modify recv QP[%d] to RTS\n", index);
+		return 1;
+	}
+
+	memset(&attr, 0, sizeof attr);
+	attr.qp_state	      = IBV_QPS_RTR;
+	attr.dest_qp_num      = ctx.rem_dest[index].recv_qpn;
+	attr.path_mtu	      = ctx.mtu;
+	attr.rq_psn	      = ctx.rem_dest[index].send_psn;
+	attr.ah_attr.dlid     = ctx.rem_dest[index].lid;
+	attr.ah_attr.sl	      = ctx.sl;
+	attr.ah_attr.port_num = ctx.ib_port;
+
+	if (ibv_modify_qp(ctx.send_qp[index], &attr,
+			  IBV_QP_STATE | IBV_QP_AV | IBV_QP_PATH_MTU |
+			  IBV_QP_DEST_QPN | IBV_QP_RQ_PSN)) {
+		fprintf(stderr, "Failed to modify send QP[%d] to RTR\n", index);
+		return 1;
+	}
+
+	memset(&attr, 0, sizeof attr);
+	attr.qp_state = IBV_QPS_RTS;
+	attr.timeout = 14;
+	attr.retry_cnt = 7;
+	attr.rnr_retry = 7;
+	attr.sq_psn = ctx.rem_dest[index].recv_psn;
+
+	if (ibv_modify_qp(ctx.send_qp[index], &attr,
+			  IBV_QP_STATE | IBV_QP_TIMEOUT | IBV_QP_SQ_PSN |
+			  IBV_QP_RETRY_CNT | IBV_QP_RNR_RETRY | IBV_QP_MAX_QP_RD_ATOMIC)) {
+		fprintf(stderr, "Failed to modify send QP[%d] to RTS\n", index);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int pp_client_connect(const char *servername, int port)
+{
+	struct addrinfo *res, *t;
+	char *service;
+	int ret;
+	int sockfd = -1;
+	struct addrinfo hints = {
+		.ai_family   = AF_UNSPEC,
+		.ai_socktype = SOCK_STREAM
+	};
+
+	if (asprintf(&service, "%d", port) < 0)
+		return 1;
+
+	ret = getaddrinfo(servername, service, &hints, &res);
+	if (ret < 0) {
+		fprintf(stderr, "%s for %s:%d\n", gai_strerror(ret), servername, port);
+		free(service);
+		return 1;
+	}
+
+	for (t = res; t; t = t->ai_next) {
+		sockfd = socket(t->ai_family, t->ai_socktype, t->ai_protocol);
+		if (sockfd >= 0) {
+			if (!connect(sockfd, t->ai_addr, t->ai_addrlen))
+				break;
+			close(sockfd);
+			sockfd = -1;
+		}
+	}
+
+	freeaddrinfo(res);
+	free(service);
+
+	if (sockfd < 0) {
+		fprintf(stderr, "Couldn't connect to %s:%d\n", servername, port);
+		return 1;
+	}
+
+	if (send_local_dest(sockfd, 0))
+		return 1;
+
+	if (recv_remote_dest(sockfd, 0))
+		return 1;
+
+	if (connect_qps(0))
+		return 1;
+
+	shutdown(sockfd, SHUT_RDWR);
+	close(sockfd);
+	return 0;
+}
+
+static int pp_server_connect(int port)
+{
+	struct addrinfo *res, *t;
+	char *service;
+	int ret, i, n;
+	int sockfd = -1, connfd;
+	struct addrinfo hints = {
+		.ai_flags    = AI_PASSIVE,
+		.ai_family   = AF_UNSPEC,
+		.ai_socktype = SOCK_STREAM
+	};
+
+	if (asprintf(&service, "%d", port) < 0)
+		return 1;
+
+	ret = getaddrinfo(NULL, service, &hints, &res);
+	if (ret < 0) {
+		fprintf(stderr, "%s for port %d\n", gai_strerror(ret), port);
+		free(service);
+		return 1;
+	}
+
+	for (t = res; t; t = t->ai_next) {
+		sockfd = socket(t->ai_family, t->ai_socktype, t->ai_protocol);
+		if (sockfd >= 0) {
+			n = 1;
+			setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof n);
+			if (!bind(sockfd, t->ai_addr, t->ai_addrlen))
+				break;
+			close(sockfd);
+			sockfd = -1;
+		}
+	}
+
+	freeaddrinfo(res);
+	free(service);
+
+	if (sockfd < 0) {
+		fprintf(stderr, "Couldn't listen to port %d\n", port);
+		return 1;
+	}
+
+	listen(sockfd, ctx.num_clients);
+
+	for (i = 0; i < ctx.num_clients; i++) {
+		connfd = accept(sockfd, NULL, 0);
+		if (connfd < 0) {
+			fprintf(stderr, "accept() failed for client %d\n", i);
+			return 1;
+		}
+
+		if (recv_remote_dest(connfd, i))
+			return 1;
+
+		if (send_local_dest(connfd, i))
+			return 1;
+
+		if (connect_qps(i))
+			return 1;
+
+		shutdown(connfd, SHUT_RDWR);
+		close(connfd);
+	}
+
+	close(sockfd);
+	return 0;
+}
+
+
+static int pp_close_ctx(void)
+{
+	int i;
+
+	for (i = 0; i < ctx.num_clients; ++i) {
+		/*
+		 * Receive QPs may be used by other clients.  Leave them, they
+		 * will be cleaned up when the xrcd is destroyed.
+		 */
+		if (ibv_destroy_qp(ctx.send_qp[i])) {
+			fprintf(stderr, "Couldn't destroy INI QP[%d]\n", i);
+			return 1;
+		}
+	}
+
+	if (ibv_destroy_srq(ctx.srq)) {
+		fprintf(stderr, "Couldn't destroy SRQ\n");
+		return 1;
+	}
+
+	if (!ctx.xrcd && ibv_close_xrcd(ctx.xrcd)) {
+		fprintf(stderr, "Couldn't close the XRC Domain\n");
+		return 1;
+	}
+	if (ctx.fd >= 0 && close(ctx.fd)) {
+		fprintf(stderr, "Couldn't close the file for the XRC Domain\n");
+		return 1;
+	}
+
+	if (ibv_destroy_cq(ctx.send_cq)) {
+		fprintf(stderr, "Couldn't destroy send CQ\n");
+		return 1;
+	}
+
+	if (ibv_destroy_cq(ctx.recv_cq)) {
+		fprintf(stderr, "Couldn't destroy recv CQ\n");
+		return 1;
+	}
+
+	if (ibv_dereg_mr(ctx.mr)) {
+		fprintf(stderr, "Couldn't deregister MR\n");
+		return 1;
+	}
+
+	if (ibv_dealloc_pd(ctx.pd)) {
+		fprintf(stderr, "Couldn't deallocate PD\n");
+		return 1;
+	}
+
+	if (ctx.channel) {
+		if (ibv_destroy_comp_channel(ctx.channel)) {
+			fprintf(stderr,
+				"Couldn't destroy completion channel\n");
+			return 1;
+		}
+	}
+
+	if (ibv_close_device(ctx.context)) {
+		fprintf(stderr, "Couldn't release context\n");
+		return 1;
+	}
+
+	free(ctx.buf);
+	free(ctx.rem_dest);
+	free(ctx.send_qp);
+	free(ctx.recv_qp);
+	return 0;
+}
+
+static int pp_post_recv(int cnt)
+{
+	struct ibv_sge sge;
+	struct ibv_recv_wr wr, *bad_wr;
+
+	sge.addr = (uintptr_t) ctx.buf;
+	sge.length = ctx.size;
+	sge.lkey = ctx.mr->lkey;
+
+	wr.next       = NULL;
+	wr.wr_id      = (uintptr_t) &ctx;
+	wr.sg_list    = &sge;
+	wr.num_sge    = 1;
+
+	while (cnt--) {
+		if (ibv_post_srq_recv(ctx.srq, &wr, &bad_wr)) {
+			fprintf(stderr, "Failed to post receive to SRQ\n");
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/*
+ * Send to each client round robin on each set of xrc send/recv qp.
+ * Generate a completion on the last send.
+ */
+static int pp_post_send(int index)
+{
+	struct ibv_sge sge;
+	struct ibv_send_wr wr, *bad_wr;
+	int qpi;
+
+	sge.addr = (uintptr_t) ctx.buf;
+	sge.length = ctx.size;
+	sge.lkey = ctx.mr->lkey;
+
+	wr.wr_id   = (uintptr_t) index;
+	wr.next    = NULL;
+	wr.sg_list = &sge;
+	wr.num_sge = 1;
+	wr.opcode  = IBV_WR_SEND;
+	wr.qp_type.xrc.remote_srqn = ctx.rem_dest[index].srqn;
+
+	qpi = (index + ctx.rem_dest[index].pp_cnt) % ctx.num_clients;
+	wr.send_flags = (++ctx.rem_dest[index].pp_cnt >= ctx.num_tests) ?
+			IBV_SEND_SIGNALED : 0;
+
+	return ibv_post_send(ctx.send_qp[qpi], &wr, &bad_wr);
+}
+
+static int find_qp(int qpn)
+{
+	int i;
+
+	if (ctx.num_clients == 1)
+		return 0;
+
+	for (i = 0; i < ctx.num_clients; ++i)
+		if (ctx.recv_qp[i]->qp_num == qpn)
+			return i;
+
+	fprintf(stderr, "Unable to find qp %x\n", qpn);
+	return 0;
+}
+
+static int get_cq_event(void)
+{
+	struct ibv_cq *ev_cq;
+	void          *ev_ctx;
+
+	if (ibv_get_cq_event(ctx.channel, &ev_cq, &ev_ctx)) {
+		fprintf(stderr, "Failed to get cq_event\n");
+		return 1;
+	}
+
+	if (ev_cq != ctx.recv_cq) {
+		fprintf(stderr, "CQ event for unknown CQ %p\n", ev_cq);
+		return 1;
+	}
+
+	if (ibv_req_notify_cq(ctx.recv_cq, 0)) {
+		fprintf(stderr, "Couldn't request CQ notification\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+static void init(void)
+{
+	srand48(getpid() * time(NULL));
+
+	ctx.size = 4096;
+	ctx.ib_port = 1;
+	ctx.num_clients  = 1;
+	ctx.num_tests = 5;
+	ctx.mtu = IBV_MTU_2048;
+	ctx.sl = 0;
+}
+
+static void usage(const char *argv0)
+{
+	printf("Usage:\n");
+	printf("  %s            start a server and wait for connection\n", argv0);
+	printf("  %s <host>     connect to server at <host>\n", argv0);
+	printf("\n");
+	printf("Options:\n");
+	printf("  -p, --port=<port>      listen on/connect to port <port> (default 18515)\n");
+	printf("  -d, --ib-dev=<dev>     use IB device <dev> (default first device found)\n");
+	printf("  -i, --ib-port=<port>   use port <port> of IB device (default 1)\n");
+	printf("  -s, --size=<size>      size of message to exchange (default 4096)\n");
+	printf("  -m, --mtu=<size>       path MTU (default 2048)\n");
+	printf("  -c, --clients=<n>      number of clients (on server only, default 1)\n");
+	printf("  -n, --num_tests=<n>    number of tests per client (default 5)\n");
+	printf("  -l, --sl=<sl>          service level value\n");
+	printf("  -e, --events           sleep on CQ events (default poll)\n");
+}
+
+int main(int argc, char *argv[])
+{
+	char          *ib_devname = NULL;
+	char          *servername = NULL;
+	int           port = 18515;
+	int           i, total, cnt = 0;
+	int           ne, qpi, num_cq_events = 0;
+	struct ibv_wc wc;
+
+	init();
+	while (1) {
+		int c;
+
+		static struct option long_options[] = {
+			{ .name = "port",      .has_arg = 1, .val = 'p' },
+			{ .name = "ib-dev",    .has_arg = 1, .val = 'd' },
+			{ .name = "ib-port",   .has_arg = 1, .val = 'i' },
+			{ .name = "size",      .has_arg = 1, .val = 's' },
+			{ .name = "mtu",       .has_arg = 1, .val = 'm' },
+			{ .name = "clients",   .has_arg = 1, .val = 'c' },
+			{ .name = "num_tests", .has_arg = 1, .val = 'n' },
+			{ .name = "sl",        .has_arg = 1, .val = 'l' },
+			{ .name = "events",    .has_arg = 0, .val = 'e' },
+			{ 0 }
+		};
+
+		c = getopt_long(argc, argv, "p:d:i:s:m:c:n:l:e", long_options,
+				NULL);
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 'p':
+			port = strtol(optarg, NULL, 0);
+			if (port < 0 || port > 65535) {
+				usage(argv[0]);
+				return 1;
+			}
+			break;
+		case 'd':
+			ib_devname = strdupa(optarg);
+			break;
+		case 'i':
+			ctx.ib_port = strtol(optarg, NULL, 0);
+			if (ctx.ib_port < 0) {
+				usage(argv[0]);
+				return 1;
+			}
+			break;
+		case 's':
+			ctx.size = strtol(optarg, NULL, 0);
+			break;
+		case 'm':
+			ctx.mtu = pp_mtu_to_enum(strtol(optarg, NULL, 0));
+			if (ctx.mtu < 0) {
+				usage(argv[0]);
+				return 1;
+			}
+			break;
+		case 'c':
+			ctx.num_clients = strtol(optarg, NULL, 0);
+			break;
+		case 'n':
+			ctx.num_tests = strtol(optarg, NULL, 0);
+			break;
+		case 'l':
+			ctx.sl = strtol(optarg, NULL, 0);
+			break;
+		case 'e':
+			ctx.use_event = 1;
+			break;
+		default:
+			usage(argv[0]);
+			return 1;
+		}
+	}
+
+	if (optind == argc - 1) {
+		servername = strdupa(argv[optind]);
+		ctx.num_clients = 1;
+	} else if (optind < argc) {
+		usage(argv[0]);
+		return 1;
+	}
+
+	page_size = sysconf(_SC_PAGESIZE);
+
+	if (pp_init_ctx(ib_devname))
+		return 1;
+
+	if (pp_post_recv(ctx.num_clients)) {
+		fprintf(stderr, "Couldn't post receives\n");
+		return 1;
+	}
+
+	if (servername) {
+		if (pp_client_connect(servername, port))
+			return 1;
+	} else {
+		if (pp_server_connect(port))
+			return 1;
+
+		for (i = 0; i < ctx.num_clients; i++)
+			pp_post_send(i);
+	}
+
+	total = ctx.num_clients * ctx.num_tests;
+	while (cnt < total) {
+		if (ctx.use_event) {
+			if (get_cq_event())
+				return 1;
+
+			++num_cq_events;
+		}
+
+		do {
+			ne = ibv_poll_cq(ctx.recv_cq, 1, &wc);
+			if (ne < 0) {
+				fprintf(stderr, "Error polling cq %d\n", ne);
+				return 1;
+			} else if (ne == 0) {
+				break;
+			}
+
+			if (wc.status) {
+				fprintf(stderr, "Work completion error %d\n", wc.status);
+				return 1;
+			}
+
+			pp_post_recv(ne);
+			qpi = find_qp(wc.qp_num);
+			if (ctx.rem_dest[qpi].pp_cnt < ctx.num_tests)
+				pp_post_send(qpi);
+			cnt += ne;
+		} while (ne > 0);
+	}
+
+	for (cnt = 0; cnt < ctx.num_clients; cnt += ne) {
+		ne = ibv_poll_cq(ctx.send_cq, 1, &wc);
+		if (ne < 0) {
+			fprintf(stderr, "Error polling cq %d\n", ne);
+			return 1;
+		}
+	}
+
+	if (ctx.use_event)
+		ibv_ack_cq_events(ctx.recv_cq, num_cq_events);
+
+	if (pp_close_ctx())
+		return 1;
+
+	printf("success\n");
+	return 0;
+}
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH V8 libibverbs 1/7] Infrastructure to support verbs extensions
       [not found]     ` <1374741488-30895-2-git-send-email-yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
@ 2013-07-25 17:14       ` Jason Gunthorpe
       [not found]         ` <20130725171408.GA17616-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
  0 siblings, 1 reply; 15+ messages in thread
From: Jason Gunthorpe @ 2013-07-25 17:14 UTC (permalink / raw)
  To: Yishai Hadas
  Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA, roland-BHEL68pLQRGGvPXPguhicg,
	ogerlitz-VPRAkNaXOzVWk0Htik3J/w, tzahio-VPRAkNaXOzVWk0Htik3J/w,
	Sean Hefty

On Thu, Jul 25, 2013 at 11:38:02AM +0300, Yishai Hadas wrote:

> +#ifndef container_of
> +/**
> +  * container_of - cast a member of a structure out to the containing structure
> +  * @ptr:        the pointer to the member.
> +  * @type:       the type of the container struct this is embedded in.
> +  * @member:     the name of the member within the struct.
> +  *
> + */
> +#define container_of(ptr, type, member) \
> +	((type *) ((char *)(ptr) - offsetof(type, member)))
                 ^^^^^^^^^^^^

This should be 'uint8_t'

> +#define vext_field_avail(type, fld, sz) (offsetof(type, fld) < (sz))

This is never used? Should it be? Ditch it?

> +static inline struct verbs_context *verbs_get_ctx(
> +					const struct ibv_context *ctx)
                  ^^^^^^^^^^^^^
const goes in, const goes out. Should be:

static inline const struct verbs_context *verbs_get_ctx(const struct ibv_context *ctx)

> +{
> +	return (ctx->abi_compat != ((uint8_t *)NULL) - 1) ?
                               ^^^^^^^^^^^^^^^^^^^^^^

Should this be a constant? __VERBS_ABI_IS_EXTENDED or something?

> +#define verbs_get_ctx_op(ctx, op) ({ \
> +	struct verbs_context *vctx = verbs_get_ctx(ctx); \
           ^^^^ const
> +	(!vctx || (vctx->sz < sizeof(*vctx) - offsetof(struct verbs_context, op)) || \
> +	 !vctx->op) ? NULL : vctx; })

An inline would be nicer, it will let the compiler merge these when
using -Os.

static inline const struct verbs_context *__verbs_get_ctx_op(const struct ibv_context *ctx, size_t off)
{
    const struct verbs_context *vctx = verbs_get_ctx(ctx);
    if (vctx && vctx->sz < sizeof(*vctx) - off && *(void **)((uint8_t *)vctx + off))
        return vctx;
    return null
}
#define verbs_get_ctx_op(ctx, op) __verbs_get_ctx_op(ctx, offsetof(struct verbs_context, op))

This also solves the problems the macro has with missing ()

> +#define verbs_set_ctx_op(vctx, op, ptr) ({ \
> +	if (vctx && (vctx->sz >= sizeof(*vctx) - offsetof(struct verbs_context, op))) \
> +		vctx->op = ptr; })

Lots of missing (), and no type check on vctx. This is better and
centralizes the tricky check into __verbs_get_ctx_op:

#define verbs_set_ctx_op(vctx, op, ptr) ({ \
   struct verbs_context *__vctx = (struct verbs_context *)verbs_get_ctx_op((vctx)->context, op); \
   if (__vctx) __vctx->op = ptr; })

> +		context_ex->context.abi_compat  = ((uint8_t *)NULL) - 1;
                                                ^^^^^^^^^^^^^^^^^^^^^^
Constant?

Otherwise this appears to be as we discussed and agreed last year, so
you can add my Ack to this patch.

Please confirm you have done testing with extending and shrinking
verbs_context to test that verbs_get_ctx_op truely works properly.

Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH V8 libibverbs 1/7] Infrastructure to support verbs extensions
       [not found]         ` <20130725171408.GA17616-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
@ 2013-07-26 12:16           ` Yishai Hadas
       [not found]             ` <51F268B1.9040003-LDSdmyG8hGV8YrgS2mwiifqBs+8SCbDb@public.gmane.org>
  0 siblings, 1 reply; 15+ messages in thread
From: Yishai Hadas @ 2013-07-26 12:16 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Yishai Hadas, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	roland-BHEL68pLQRGGvPXPguhicg, ogerlitz-VPRAkNaXOzVWk0Htik3J/w,
	tzahio-VPRAkNaXOzVWk0Htik3J/w, Sean Hefty

On 7/25/2013 8:14 PM, Jason Gunthorpe wrote:
> On Thu, Jul 25, 2013 at 11:38:02AM +0300, Yishai Hadas wrote:
>
>> +#ifndef container_of
>> +/**
>> +  * container_of - cast a member of a structure out to the containing structure
>> +  * @ptr:        the pointer to the member.
>> +  * @type:       the type of the container struct this is embedded in.
>> +  * @member:     the name of the member within the struct.
>> +  *
>> + */
>> +#define container_of(ptr, type, member) \
>> +	((type *) ((char *)(ptr) - offsetof(type, member)))
>                   ^^^^^^^^^^^^
>
> This should be 'uint8_t'
>
>> +#define vext_field_avail(type, fld, sz) (offsetof(type, fld) < (sz))
> This is never used? Should it be? Ditch it?
     It's used in further patches of libibverbs, please have a look at: 
ibv_cmd_create_qp_ex, ibv_cmd_create_srq_ex, etc.
>
>> +static inline struct verbs_context *verbs_get_ctx(
>> +					const struct ibv_context *ctx)
>                    ^^^^^^^^^^^^^
> const goes in, const goes out. Should be:
>
> static inline const struct verbs_context *verbs_get_ctx(const struct ibv_context *ctx)
>
>> +{
>> +	return (ctx->abi_compat != ((uint8_t *)NULL) - 1) ?
>                                 ^^^^^^^^^^^^^^^^^^^^^^
>
> Should this be a constant? __VERBS_ABI_IS_EXTENDED or something?
     Can you clarify your suggestion here ?
>
>> +#define verbs_get_ctx_op(ctx, op) ({ \
>> +	struct verbs_context *vctx = verbs_get_ctx(ctx); \
>             ^^^^ const
>> +	(!vctx || (vctx->sz < sizeof(*vctx) - offsetof(struct verbs_context, op)) || \
>> +	 !vctx->op) ? NULL : vctx; })
> An inline would be nicer, it will let the compiler merge these when
> using -Os.
>
> static inline const struct verbs_context *__verbs_get_ctx_op(const struct ibv_context *ctx, size_t off)
> {
>      const struct verbs_context *vctx = verbs_get_ctx(ctx);
>      if (vctx && vctx->sz < sizeof(*vctx) - off && *(void **)((uint8_t *)vctx + off))
>          return vctx;
>      return null
> }
> #define verbs_get_ctx_op(ctx, op) __verbs_get_ctx_op(ctx, offsetof(struct verbs_context, op))
>
> This also solves the problems the macro has with missing ()
     Which problems you refer to with missing () ?
>
>> +#define verbs_set_ctx_op(vctx, op, ptr) ({ \
>> +	if (vctx && (vctx->sz >= sizeof(*vctx) - offsetof(struct verbs_context, op))) \
>> +		vctx->op = ptr; })
> Lots of missing (), and no type check on vctx. This is better and
> centralizes the tricky check into __verbs_get_ctx_op:
>
> #define verbs_set_ctx_op(vctx, op, ptr) ({ \
>     struct verbs_context *__vctx = (struct verbs_context *)verbs_get_ctx_op((vctx)->context, op); \
>     if (__vctx) __vctx->op = ptr; })
>
>> +		context_ex->context.abi_compat  = ((uint8_t *)NULL) - 1;
>                                                  ^^^^^^^^^^^^^^^^^^^^^^
> Constant?
>
> Otherwise this appears to be as we discussed and agreed last year, so
> you can add my Ack to this patch.
     Thanks, any other input on V8 series ?
>
> Please confirm you have done testing with extending and shrinking
> verbs_context to test that verbs_get_ctx_op truely works properly.
     Already did, will do further testing after adapting to your 
suggestions above.
> Jason
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH V8 libibverbs 1/7] Infrastructure to support verbs extensions
       [not found]             ` <51F268B1.9040003-LDSdmyG8hGV8YrgS2mwiifqBs+8SCbDb@public.gmane.org>
@ 2013-07-29 23:30               ` Jason Gunthorpe
       [not found]                 ` <51F821A3.1010507@dev.mellanox.co.il>
  0 siblings, 1 reply; 15+ messages in thread
From: Jason Gunthorpe @ 2013-07-29 23:30 UTC (permalink / raw)
  To: Yishai Hadas
  Cc: Yishai Hadas, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	roland-BHEL68pLQRGGvPXPguhicg, ogerlitz-VPRAkNaXOzVWk0Htik3J/w,
	tzahio-VPRAkNaXOzVWk0Htik3J/w, Sean Hefty

On Fri, Jul 26, 2013 at 03:16:49PM +0300, Yishai Hadas wrote:

> >>+{
> >>+	return (ctx->abi_compat != ((uint8_t *)NULL) - 1) ?
> >                                ^^^^^^^^^^^^^^^^^^^^^^
> >
> >Should this be a constant? __VERBS_ABI_IS_EXTENDED or something?
>     Can you clarify your suggestion here ?

I was thinking:

static const void *__VERBS_ABI_IS_EXTENDED = (uint8_t *)NULL) - 1;

> >>+	struct verbs_context *vctx = verbs_get_ctx(ctx); \
> >            ^^^^ const
> >>+	(!vctx || (vctx->sz < sizeof(*vctx) - offsetof(struct verbs_context, op)) || \
> >>+	 !vctx->op) ? NULL : vctx; })
> >An inline would be nicer, it will let the compiler merge these when
> >using -Os.
> >
> >static inline const struct verbs_context *__verbs_get_ctx_op(const struct ibv_context *ctx, size_t off)
> >{
> >     const struct verbs_context *vctx = verbs_get_ctx(ctx);
> >     if (vctx && vctx->sz < sizeof(*vctx) - off && *(void **)((uint8_t *)vctx + off))
> >         return vctx;
> >     return null
> >}
> >#define verbs_get_ctx_op(ctx, op) __verbs_get_ctx_op(ctx, offsetof(struct verbs_context, op))
> >
> >This also solves the problems the macro has with missing ()
>     Which problems you refer to with missing () ?

Looks like only verbs_set_ctx_op had some missing (), verbs_get_ctx is fine.

> >Otherwise this appears to be as we discussed and agreed last year, so
> >you can add my Ack to this patch.
>     Thanks, any other input on V8 series ?

I haven't looked at the XRC elements, I am not too familiar with XRC.

Hopefully Roland will comment on this patch so things can progress.

Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH V8 libibverbs 1/7] Infrastructure to support verbs extensions
       [not found]                   ` <51F821A3.1010507-LDSdmyG8hGV8YrgS2mwiifqBs+8SCbDb@public.gmane.org>
@ 2013-07-30 22:15                     ` Jason Gunthorpe
       [not found]                       ` <20130730221548.GA14439-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
  0 siblings, 1 reply; 15+ messages in thread
From: Jason Gunthorpe @ 2013-07-30 22:15 UTC (permalink / raw)
  To: Yishai Hadas
  Cc: Yishai Hadas, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	roland-BHEL68pLQRGGvPXPguhicg, ogerlitz-VPRAkNaXOzVWk0Htik3J/w,
	tzahio-VPRAkNaXOzVWk0Htik3J/w, Sean Hefty

On Tue, Jul 30, 2013 at 11:27:15PM +0300, Yishai Hadas wrote:

> Can accept it, however as it's a const pointer may need some casting later
> which is not fully clean.

Drop the const from the definition then.

>     Your suggestion for verbs_set_ctx_op can't not work as it calls internally
> to verbs_get_ctx_op and will may fail as
>     at that step function pointer was not set and *(void **)((uint8_t *)vctx +
> off) will be NULL.

Yes, that is too bad in that case, but the old macro is still flawed:

+#define verbs_set_ctx_op(vctx, op, ptr) ({ \
+       if (vctx && (vctx->sz >= sizeof(*vctx) - offsetof(struct verbs_context, op))) \
+               vctx->op = ptr; })

- Missing () on all vctx usages
- Missing type enforcement on vctx

Something like this:

#define verbs_set_ctx_op(_vctx, op, ptr) ({ \
       struct verbs_context *vctx = _vctx; \
       if (vctx && (vctx->sz >= sizeof(*vctx) - offsetof(struct verbs_context, op))) \
               vctx->op = ptr; })

>     In addition changing to use const as part of returning from
> __verbs_get_ctx_op causes some necessary casting to non const in some places
> which
>     is not fully clean. (e.g. free((void *)context_ex); as part of
> __ibv_close_device, verbs_ctx->has_comp_mask = VERBS_CONTEXT_XRCD |
> VERBS_CONTEXT_SRQ |
>                     VERBS_CONTEXT_QP; as part of mlx4_init_context)

It is virtually impossible to do const-correctness fully and
transparently in C, since the language has no feature to silently
propogate the const.

If you want to be 100% clean then provide a non-const version --
verbs_get_ctx_nc that takes non-const input.

Functions that silently discard const are bad since it silently
defeats static analysis around const.

>     I recommend staying with V8 suggestion for both macros, in case
> you think there is any problem with missing () for the set operation
> please point on and may handle.

Using the inline to help the -Os case is definitely desirable, and the
fix to the () at least.
 
Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH V8 libibverbs 1/7] Infrastructure to support verbs extensions
       [not found]                       ` <20130730221548.GA14439-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
@ 2013-07-31  7:27                         ` Yishai Hadas
       [not found]                           ` <51F8BC4A.5010102-LDSdmyG8hGV8YrgS2mwiifqBs+8SCbDb@public.gmane.org>
  0 siblings, 1 reply; 15+ messages in thread
From: Yishai Hadas @ 2013-07-31  7:27 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Yishai Hadas, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	roland-BHEL68pLQRGGvPXPguhicg, ogerlitz-VPRAkNaXOzVWk0Htik3J/w,
	tzahio-VPRAkNaXOzVWk0Htik3J/w, Sean Hefty

On 7/31/2013 1:15 AM, Jason Gunthorpe wrote:
> On Tue, Jul 30, 2013 at 11:27:15PM +0300, Yishai Hadas wrote:
>
>> Can accept it, however as it's a const pointer may need some casting later
>> which is not fully clean.
> Drop the const from the definition then.
>
>>      Your suggestion for verbs_set_ctx_op can't not work as it calls internally
>> to verbs_get_ctx_op and will may fail as
>>      at that step function pointer was not set and *(void **)((uint8_t *)vctx +
>> off) will be NULL.
> Yes, that is too bad in that case, but the old macro is still flawed:
>
> +#define verbs_set_ctx_op(vctx, op, ptr) ({ \
> +       if (vctx && (vctx->sz >= sizeof(*vctx) - offsetof(struct verbs_context, op))) \
> +               vctx->op = ptr; })
>
> - Missing () on all vctx usages
> - Missing type enforcement on vctx
>
> Something like this:
>
> #define verbs_set_ctx_op(_vctx, op, ptr) ({ \
>         struct verbs_context *vctx = _vctx; \
>         if (vctx && (vctx->sz >= sizeof(*vctx) - offsetof(struct verbs_context, op))) \
>                 vctx->op = ptr; })
>
>>      In addition changing to use const as part of returning from
>> __verbs_get_ctx_op causes some necessary casting to non const in some places
>> which
>>      is not fully clean. (e.g. free((void *)context_ex); as part of
>> __ibv_close_device, verbs_ctx->has_comp_mask = VERBS_CONTEXT_XRCD |
>> VERBS_CONTEXT_SRQ |
>>                      VERBS_CONTEXT_QP; as part of mlx4_init_context)
> It is virtually impossible to do const-correctness fully and
> transparently in C, since the language has no feature to silently
> propogate the const.
>
> If you want to be 100% clean then provide a non-const version --
> verbs_get_ctx_nc that takes non-const input.
     Looking around ibv_context usage, it's used as non const input, in 
that case we can have only one version which takes non-const input and 
return
     non-const one, preventing any silent casting as below, can we agree 
on ?

static inline struct verbs_context *verbs_get_ctx(
                     struct ibv_context *ctx)
     {
     return (!ctx || (ctx->abi_compat != ((uint8_t *)NULL) - 1)) ?
         NULL : container_of(ctx, struct verbs_context, context);
     }

#define verbs_get_ctx_op(ctx, op) ({ \
     struct verbs_context *vctx = verbs_get_ctx(ctx); \
     (!vctx || (vctx->sz < sizeof(*vctx) - offsetof(struct 
verbs_context, op)) || \
     !vctx->op) ? NULL : vctx; })
>
> Functions that silently discard const are bad since it silently
> defeats static analysis around const.
>
>>      I recommend staying with V8 suggestion for both macros, in case
>> you think there is any problem with missing () for the set operation
>> please point on and may handle.
> Using the inline to help the -Os case is definitely desirable, and the
> fix to the () at least.
>   
     Will stay with the macro, improved to your suggestion above.
     Are you fine with below definition ? any other () needed ?

   #define verbs_set_ctx_op(_vctx, op, ptr) ({ \
        struct verbs_context *vctx = _vctx; \
        if (vctx && (vctx->sz >= sizeof(*vctx) - offsetof(struct verbs_context, op))) \
                vctx->op = ptr; })

> Jason

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH V8 libibverbs 1/7] Infrastructure to support verbs extensions
       [not found]                           ` <51F8BC4A.5010102-LDSdmyG8hGV8YrgS2mwiifqBs+8SCbDb@public.gmane.org>
@ 2013-07-31 16:52                             ` Jason Gunthorpe
       [not found]                               ` <20130731165205.GC27845-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
  0 siblings, 1 reply; 15+ messages in thread
From: Jason Gunthorpe @ 2013-07-31 16:52 UTC (permalink / raw)
  To: Yishai Hadas
  Cc: Yishai Hadas, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	roland-BHEL68pLQRGGvPXPguhicg, ogerlitz-VPRAkNaXOzVWk0Htik3J/w,
	tzahio-VPRAkNaXOzVWk0Htik3J/w, Sean Hefty

On Wed, Jul 31, 2013 at 10:27:06AM +0300, Yishai Hadas wrote:

>     Looking around ibv_context usage, it's used as non const input,
> in that case we can have only one version which takes non-const
> input and return non-const one, preventing any silent casting as
> below, can we agree on ?

Fair enough.

Why are you so against the inline version?

>     Are you fine with below definition ? any other () needed ?
> 
>   #define verbs_set_ctx_op(_vctx, op, ptr) ({ \
>        struct verbs_context *vctx = _vctx; \
>        if (vctx && (vctx->sz >= sizeof(*vctx) - offsetof(struct verbs_context, op))) \
>                vctx->op = ptr; })

This looks fine

Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH V8 libibverbs 1/7] Infrastructure to support verbs extensions
       [not found]                               ` <20130731165205.GC27845-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
@ 2013-08-01 16:01                                 ` Yishai Hadas
  0 siblings, 0 replies; 15+ messages in thread
From: Yishai Hadas @ 2013-08-01 16:01 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Yishai Hadas, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	roland-BHEL68pLQRGGvPXPguhicg, ogerlitz-VPRAkNaXOzVWk0Htik3J/w,
	tzahio-VPRAkNaXOzVWk0Htik3J/w, Sean Hefty

On 7/31/2013 7:52 PM, Jason Gunthorpe wrote:
> On Wed, Jul 31, 2013 at 10:27:06AM +0300, Yishai Hadas wrote:
>
>>      Looking around ibv_context usage, it's used as non const input,
>> in that case we can have only one version which takes non-const
>> input and return non-const one, preventing any silent casting as
>> below, can we agree on ?
> Fair enough.
     Thanks, will use as part of V9.
> Why are you so against the inline version?
     In V9 don't add them, macros are 2/3 lines code, seem to me 
redundant here.
     In addition verbs_get_ctx is inline so we partially have it.
>
>>      Are you fine with below definition ? any other () needed ?
>>
>>    #define verbs_set_ctx_op(_vctx, op, ptr) ({ \
>>         struct verbs_context *vctx = _vctx; \
>>         if (vctx && (vctx->sz >= sizeof(*vctx) - offsetof(struct verbs_context, op))) \
>>                 vctx->op = ptr; })
> This looks fine
     Thanks, will use as part of V9.
> Jason

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2013-08-01 16:01 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-25  8:38 [PATCH V8 libibverbs 0/7] Add extension and XRC QP support Yishai Hadas
     [not found] ` <1374741488-30895-1-git-send-email-yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
2013-07-25  8:38   ` [PATCH V8 libibverbs 1/7] Infrastructure to support verbs extensions Yishai Hadas
     [not found]     ` <1374741488-30895-2-git-send-email-yishaih-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
2013-07-25 17:14       ` Jason Gunthorpe
     [not found]         ` <20130725171408.GA17616-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2013-07-26 12:16           ` Yishai Hadas
     [not found]             ` <51F268B1.9040003-LDSdmyG8hGV8YrgS2mwiifqBs+8SCbDb@public.gmane.org>
2013-07-29 23:30               ` Jason Gunthorpe
     [not found]                 ` <51F821A3.1010507@dev.mellanox.co.il>
     [not found]                   ` <51F821A3.1010507-LDSdmyG8hGV8YrgS2mwiifqBs+8SCbDb@public.gmane.org>
2013-07-30 22:15                     ` Jason Gunthorpe
     [not found]                       ` <20130730221548.GA14439-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2013-07-31  7:27                         ` Yishai Hadas
     [not found]                           ` <51F8BC4A.5010102-LDSdmyG8hGV8YrgS2mwiifqBs+8SCbDb@public.gmane.org>
2013-07-31 16:52                             ` Jason Gunthorpe
     [not found]                               ` <20130731165205.GC27845-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2013-08-01 16:01                                 ` Yishai Hadas
2013-07-25  8:38   ` [PATCH V8 libibverbs 2/7] Introduce XRC domains Yishai Hadas
2013-07-25  8:38   ` [PATCH V8 libibverbs 3/7] Add support for XRC SRQs Yishai Hadas
2013-07-25  8:38   ` [PATCH V8 libibverbs 4/7] Add support for XRC QPs Yishai Hadas
2013-07-25  8:38   ` [PATCH V8 libibverbs 5/7] Add ibv_open_qp Yishai Hadas
2013-07-25  8:38   ` [PATCH V8 libibverbs 6/7] XRC man pages Yishai Hadas
2013-07-25  8:38   ` [PATCH V8 libibverbs 7/7] Add XRC sample application Yishai Hadas

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.