Version: 1
-Previous: 4f0cafca2f51d6bd10b0a60518f5451f75b29e83
-Head: a438216d61a184cd5a12ad5ea3da4588d5c35c4e
+Previous: 952c5e0eac7b4b521c1596d0fa320e781a4ec845
+Head: 91fdc5b4aaf078280ff31bd0cf35760a6ae5dd10
Applied:
verbs-ext: b1cc207d04e9df91c000aadd20d3612f3cb58552
xrcd: f2b48b365d126d1c4bc61b3b3ea1ab9b7f2544f4
- srq_ex: a69bc0a89969285407e4301bb674ded66e42759e
- refresh-temp: a438216d61a184cd5a12ad5ea3da4588d5c35c4e
+ srq_ex: 91fdc5b4aaf078280ff31bd0cf35760a6ae5dd10
Unapplied:
xrc_qp: 41c4a902e322da2cc08caabd0ba56a1ffff4c43e
open_qp: 02ed1a5b57528c104aefa6608f45bdf2d718ded3
+++ /dev/null
-Bottom: 261f148eb3217529a654c1d876ec3902e40bcc3d
-Top: f12a9640338b48e3a608e0b2ec69517ecd34327e
-Author: Sean Hefty <sean.hefty@intel.com>
-Date: 2012-09-28 10:41:36 -0700
-
-Refresh of srq_ex
-
----
-
-diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h
-index ce88442..05ff730 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,
-@@ -118,6 +135,10 @@ 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, 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,
-@@ -162,4 +183,10 @@ 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 uint32_t verbs_get_srq_num(struct ibv_srq *srq)
-+{
-+ struct verbs_srq *vsrq = container_of(srq, struct verbs_srq, srq);
-+ return (vsrq->comp_mask & VERBS_SRQ_NUM) ? vsrq->srq_num : 0;
-+}
-+
- #endif /* INFINIBAND_DRIVER_H */
-diff --git a/include/infiniband/kern-abi.h b/include/infiniband/kern-abi.h
-index d7c673f..3d72fa7 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_destroy_cq_v1 {
-diff --git a/include/infiniband/verbs.h b/include/infiniband/verbs.h
-index 7e32e64..6465aae 100644
---- a/include/infiniband/verbs.h
-+++ b/include/infiniband/verbs.h
-@@ -420,6 +420,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, IBV_QPT_UD
- };
-@@ -730,21 +754,28 @@ 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 (*drv_new_func1) (); new corresponding provider call of func1
-- int (*lib_new_func1) (); New library call func1
-- */
-+ int (*drv_new_func1) (); new corresponding provider call of func1
-+ int (*lib_new_func1) (); New library call func1
-+ */
-+ uint32_t (*get_srq_num)(struct ibv_srq *srq);
-+ 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,
-+ int fd, int oflags);
-+ int (*close_xrcd)(struct ibv_xrcd *xrcd);
- 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; /* Set by library on struct allocation,must be
-- * located right before struct ibv_context
-- */
-+ size_t sz; /* Set by library on struct allocation,must be
-+ * located right before struct ibv_context
-+ */
- struct ibv_context context;/* Must be last field in the struct */
- };
-
-@@ -1014,6 +1045,27 @@ 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);
-+
-+ if (!(vctx = verbs_get_ctx_op(context, create_srq_ex))) {
-+ 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.
-@@ -1037,6 +1089,16 @@ int ibv_modify_srq(struct ibv_srq *srq, struct ibv_srq_attr *srq_attr,
- */
- int ibv_query_srq(struct ibv_srq *srq, struct ibv_srq_attr *srq_attr);
-
-+static inline uint32_t ibv_get_srq_num(struct ibv_srq *srq)
-+{
-+ struct verbs_context *vctx = verbs_get_ctx_op(srq->context, get_srq_num);
-+ if (!vctx) {
-+ errno = ENOSYS;
-+ return 0;
-+ }
-+ return vctx->get_srq_num(srq);
-+}
-+
- /**
- * ibv_destroy_srq - Destroys the specified SRQ.
- * @srq: The SRQ to destroy.
-diff --git a/src/cmd.c b/src/cmd.c
-index f0fb1dc..641ab28 100644
---- a/src/cmd.c
-+++ b/src/cmd.c
-@@ -488,6 +488,75 @@ 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, 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_XRCD) ||
-+ !(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);
-+
-+ 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 9a15f3f..c8ec645 100644
---- a/src/libibverbs.map
-+++ b/src/libibverbs.map
-@@ -100,5 +100,6 @@ IBVERBS_1.1 {
-
- ibv_cmd_open_xrcd;
- ibv_cmd_close_xrcd;
-+ ibv_cmd_create_srq_ex;
-
- } IBVERBS_1.0;
Bottom: 261f148eb3217529a654c1d876ec3902e40bcc3d
-Top: 261f148eb3217529a654c1d876ec3902e40bcc3d
+Top: f12a9640338b48e3a608e0b2ec69517ecd34327e
Author: Sean Hefty <sean.hefty@intel.com>
Date: 2012-09-17 12:34:55 -0700
---
-
+diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h
+index ce88442..05ff730 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,
+@@ -118,6 +135,10 @@ 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, 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,
+@@ -162,4 +183,10 @@ 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 uint32_t verbs_get_srq_num(struct ibv_srq *srq)
++{
++ struct verbs_srq *vsrq = container_of(srq, struct verbs_srq, srq);
++ return (vsrq->comp_mask & VERBS_SRQ_NUM) ? vsrq->srq_num : 0;
++}
++
+ #endif /* INFINIBAND_DRIVER_H */
+diff --git a/include/infiniband/kern-abi.h b/include/infiniband/kern-abi.h
+index d7c673f..3d72fa7 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_destroy_cq_v1 {
+diff --git a/include/infiniband/verbs.h b/include/infiniband/verbs.h
+index 7e32e64..6465aae 100644
+--- a/include/infiniband/verbs.h
++++ b/include/infiniband/verbs.h
+@@ -420,6 +420,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, IBV_QPT_UD
+ };
+@@ -730,21 +754,28 @@ 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 (*drv_new_func1) (); new corresponding provider call of func1
+- int (*lib_new_func1) (); New library call func1
+- */
++ int (*drv_new_func1) (); new corresponding provider call of func1
++ int (*lib_new_func1) (); New library call func1
++ */
++ uint32_t (*get_srq_num)(struct ibv_srq *srq);
++ 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,
++ int fd, int oflags);
++ int (*close_xrcd)(struct ibv_xrcd *xrcd);
+ 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; /* Set by library on struct allocation,must be
+- * located right before struct ibv_context
+- */
++ size_t sz; /* Set by library on struct allocation,must be
++ * located right before struct ibv_context
++ */
+ struct ibv_context context;/* Must be last field in the struct */
+ };
+
+@@ -1014,6 +1045,27 @@ 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);
++
++ if (!(vctx = verbs_get_ctx_op(context, create_srq_ex))) {
++ 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.
+@@ -1037,6 +1089,16 @@ int ibv_modify_srq(struct ibv_srq *srq, struct ibv_srq_attr *srq_attr,
+ */
+ int ibv_query_srq(struct ibv_srq *srq, struct ibv_srq_attr *srq_attr);
+
++static inline uint32_t ibv_get_srq_num(struct ibv_srq *srq)
++{
++ struct verbs_context *vctx = verbs_get_ctx_op(srq->context, get_srq_num);
++ if (!vctx) {
++ errno = ENOSYS;
++ return 0;
++ }
++ return vctx->get_srq_num(srq);
++}
++
+ /**
+ * ibv_destroy_srq - Destroys the specified SRQ.
+ * @srq: The SRQ to destroy.
+diff --git a/src/cmd.c b/src/cmd.c
+index f0fb1dc..641ab28 100644
+--- a/src/cmd.c
++++ b/src/cmd.c
+@@ -488,6 +488,75 @@ 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, 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_XRCD) ||
++ !(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);
++
++ 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 9a15f3f..c8ec645 100644
+--- a/src/libibverbs.map
++++ b/src/libibverbs.map
+@@ -100,5 +100,6 @@ IBVERBS_1.1 {
+
+ ibv_cmd_open_xrcd;
+ ibv_cmd_close_xrcd;
++ ibv_cmd_create_srq_ex;
+
+ } IBVERBS_1.0;