]> git.openfabrics.org - ~shefty/libibverbs.git/commitdiff
refresh
authorSean Hefty <sean.hefty@intel.com>
Fri, 28 Sep 2012 17:44:45 +0000 (10:44 -0700)
committerSean Hefty <sean.hefty@intel.com>
Fri, 28 Sep 2012 17:44:45 +0000 (10:44 -0700)
meta
patches/refresh-temp [deleted file]
patches/xrc_qp

diff --git a/meta b/meta
index 415e2f5166a94a07ec9df5979c782a19a9bd4c6b..15ed961e2a2adb393dfb0914bb2c646a85a77508 100644 (file)
--- a/meta
+++ b/meta
@@ -1,12 +1,11 @@
 Version: 1
-Previous: 9c927a492c4b681fa8f6f01004d811187ae7c1b2
-Head: b301fa827367508d386a607cfad5b9863372f456
+Previous: 15fbbd6a1651ac1cd8fdf42d86c640c350d8d2bf
+Head: 092bcc697d9bb0d4fe8cc322d57b9248800d2e71
 Applied:
   verbs-ext: b1cc207d04e9df91c000aadd20d3612f3cb58552
   xrcd: f2b48b365d126d1c4bc61b3b3ea1ab9b7f2544f4
   srq_ex: 91fdc5b4aaf078280ff31bd0cf35760a6ae5dd10
-  xrc_qp: a98e29562c1d727dd492cfa66b628369460969f6
-  refresh-temp: b301fa827367508d386a607cfad5b9863372f456
+  xrc_qp: 092bcc697d9bb0d4fe8cc322d57b9248800d2e71
 Unapplied:
   open_qp: 02ed1a5b57528c104aefa6608f45bdf2d718ded3
   open_qp_man: 3ba2056186d67520b8302137c5906a0083891d7f
diff --git a/patches/refresh-temp b/patches/refresh-temp
deleted file mode 100644 (file)
index 045d7eb..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-Bottom: f12a9640338b48e3a608e0b2ec69517ecd34327e
-Top:    61b6c90445f6c7731dcbedec80b9701b071ba0f8
-Author: Sean Hefty <sean.hefty@intel.com>
-Date:   2012-09-28 10:44:45 -0700
-
-Refresh of xrc_qp
-
----
-
-diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h
-index 05ff730..d43ae07 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,
-@@ -152,6 +162,10 @@ 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, 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 3d72fa7..b6d5ce9 100644
---- a/include/infiniband/kern-abi.h
-+++ b/include/infiniband/kern-abi.h
-@@ -617,6 +617,11 @@ struct ibv_kern_send_wr {
-                       __u32 remote_qkey;
-                       __u32 reserved;
-               } ud;
-+              struct {
-+                      __u64 reserved[3];
-+                      __u32 reserved2;
-+                      __u32 remote_srqn;
-+              } xrc;
-       } wr;
- };
-diff --git a/include/infiniband/verbs.h b/include/infiniband/verbs.h
-index 6465aae..1356757 100644
---- a/include/infiniband/verbs.h
-+++ b/include/infiniband/verbs.h
-@@ -91,21 +91,22 @@ enum ibv_transport_type {
- };
- enum ibv_device_cap_flags {
--      IBV_DEVICE_RESIZE_MAX_WR = 1,
--      IBV_DEVICE_BAD_PKEY_CNTR = 1 << 1,
--      IBV_DEVICE_BAD_QKEY_CNTR = 1 << 2,
--      IBV_DEVICE_RAW_MULTI = 1 << 3,
--      IBV_DEVICE_AUTO_PATH_MIG = 1 << 4,
--      IBV_DEVICE_CHANGE_PHY_PORT = 1 << 5,
--      IBV_DEVICE_UD_AV_PORT_ENFORCE = 1 << 6,
--      IBV_DEVICE_CURR_QP_STATE_MOD = 1 << 7,
--      IBV_DEVICE_SHUTDOWN_PORT = 1 << 8,
--      IBV_DEVICE_INIT_TYPE = 1 << 9,
--      IBV_DEVICE_PORT_ACTIVE_EVENT = 1 << 10,
--      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_RESIZE_MAX_WR        = 1,
-+      IBV_DEVICE_BAD_PKEY_CNTR        = 1 <<  1,
-+      IBV_DEVICE_BAD_QKEY_CNTR        = 1 <<  2,
-+      IBV_DEVICE_RAW_MULTI            = 1 <<  3,
-+      IBV_DEVICE_AUTO_PATH_MIG        = 1 <<  4,
-+      IBV_DEVICE_CHANGE_PHY_PORT      = 1 <<  5,
-+      IBV_DEVICE_UD_AV_PORT_ENFORCE   = 1 <<  6,
-+      IBV_DEVICE_CURR_QP_STATE_MOD    = 1 <<  7,
-+      IBV_DEVICE_SHUTDOWN_PORT        = 1 <<  8,
-+      IBV_DEVICE_INIT_TYPE            = 1 <<  9,
-+      IBV_DEVICE_PORT_ACTIVE_EVENT    = 1 << 10,
-+      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_XRC                  = 1 << 20
- };
- enum ibv_atomic_cap {
-@@ -445,7 +446,11 @@ struct ibv_srq_init_attr_ex {
- };
- enum ibv_qp_type {
--      IBV_QPT_RC = 2, IBV_QPT_UC, IBV_QPT_UD
-+      IBV_QPT_RC = 2,
-+      IBV_QPT_UC,
-+      IBV_QPT_UD,
-+      IBV_QPT_XRC_SEND = 9,
-+      IBV_QPT_XRC_RECV
- };
- struct ibv_qp_cap {
-@@ -466,6 +471,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,
-@@ -579,6 +604,11 @@ struct ibv_send_wr {
-                       uint32_t remote_qpn;
-                       uint32_t remote_qkey;
-               } ud;
-+              struct {
-+                      uint64_t        reserved[3];
-+                      uint32_t        reserved2;
-+                      uint32_t        remote_srqn;
-+              } xrc;
-       } wr;
- };
-@@ -755,7 +785,8 @@ 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 {
-@@ -763,6 +794,8 @@ struct verbs_context {
-       int (*drv_new_func1) ();        new corresponding provider call of func1
-       int (*lib_new_func1) ();        New library call func1
-       */
-+      struct ibv_qp *         (*create_qp_ex)(struct ibv_context *context,
-+                                              struct ibv_qp_init_attr_ex *qp_init_attr_ex);
-       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);
-@@ -1123,6 +1156,23 @@ 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)) && (mask & IBV_QP_INIT_ATTR_PD))
-+              return ibv_create_qp(qp_init_attr_ex->pd,
-+                                   (struct ibv_qp_init_attr *) qp_init_attr_ex);
-+
-+      if (!(vctx = verbs_get_ctx_op(context, create_qp_ex))) {
-+              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 641ab28..87ac062 100644
---- a/src/cmd.c
-+++ b/src/cmd.c
-@@ -666,6 +666,98 @@ 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, 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 (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,
-@@ -674,7 +766,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 c8ec645..4249793 100644
---- a/src/libibverbs.map
-+++ b/src/libibverbs.map
-@@ -101,5 +101,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;
index b0900b453838830efdb5215241d9256f1f4436d9..4ef06011a765ca666f588b257cbdba7942cf3262 100644 (file)
@@ -1,5 +1,5 @@
 Bottom: f12a9640338b48e3a608e0b2ec69517ecd34327e
-Top:    f12a9640338b48e3a608e0b2ec69517ecd34327e
+Top:    61b6c90445f6c7731dcbedec80b9701b071ba0f8
 Author: Sean Hefty <sean.hefty@intel.com>
 Date:   2012-09-17 16:00:12 -0700
 
@@ -31,4 +31,311 @@ Signed-off-by: Sean Hefty <sean.hefty@intel.com>
 
 ---
 
-
+diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h
+index 05ff730..d43ae07 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,
+@@ -152,6 +162,10 @@ 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, 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 3d72fa7..b6d5ce9 100644
+--- a/include/infiniband/kern-abi.h
++++ b/include/infiniband/kern-abi.h
+@@ -617,6 +617,11 @@ struct ibv_kern_send_wr {
+                       __u32 remote_qkey;
+                       __u32 reserved;
+               } ud;
++              struct {
++                      __u64 reserved[3];
++                      __u32 reserved2;
++                      __u32 remote_srqn;
++              } xrc;
+       } wr;
+ };
+diff --git a/include/infiniband/verbs.h b/include/infiniband/verbs.h
+index 6465aae..1356757 100644
+--- a/include/infiniband/verbs.h
++++ b/include/infiniband/verbs.h
+@@ -91,21 +91,22 @@ enum ibv_transport_type {
+ };
+ enum ibv_device_cap_flags {
+-      IBV_DEVICE_RESIZE_MAX_WR = 1,
+-      IBV_DEVICE_BAD_PKEY_CNTR = 1 << 1,
+-      IBV_DEVICE_BAD_QKEY_CNTR = 1 << 2,
+-      IBV_DEVICE_RAW_MULTI = 1 << 3,
+-      IBV_DEVICE_AUTO_PATH_MIG = 1 << 4,
+-      IBV_DEVICE_CHANGE_PHY_PORT = 1 << 5,
+-      IBV_DEVICE_UD_AV_PORT_ENFORCE = 1 << 6,
+-      IBV_DEVICE_CURR_QP_STATE_MOD = 1 << 7,
+-      IBV_DEVICE_SHUTDOWN_PORT = 1 << 8,
+-      IBV_DEVICE_INIT_TYPE = 1 << 9,
+-      IBV_DEVICE_PORT_ACTIVE_EVENT = 1 << 10,
+-      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_RESIZE_MAX_WR        = 1,
++      IBV_DEVICE_BAD_PKEY_CNTR        = 1 <<  1,
++      IBV_DEVICE_BAD_QKEY_CNTR        = 1 <<  2,
++      IBV_DEVICE_RAW_MULTI            = 1 <<  3,
++      IBV_DEVICE_AUTO_PATH_MIG        = 1 <<  4,
++      IBV_DEVICE_CHANGE_PHY_PORT      = 1 <<  5,
++      IBV_DEVICE_UD_AV_PORT_ENFORCE   = 1 <<  6,
++      IBV_DEVICE_CURR_QP_STATE_MOD    = 1 <<  7,
++      IBV_DEVICE_SHUTDOWN_PORT        = 1 <<  8,
++      IBV_DEVICE_INIT_TYPE            = 1 <<  9,
++      IBV_DEVICE_PORT_ACTIVE_EVENT    = 1 << 10,
++      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_XRC                  = 1 << 20
+ };
+ enum ibv_atomic_cap {
+@@ -445,7 +446,11 @@ struct ibv_srq_init_attr_ex {
+ };
+ enum ibv_qp_type {
+-      IBV_QPT_RC = 2, IBV_QPT_UC, IBV_QPT_UD
++      IBV_QPT_RC = 2,
++      IBV_QPT_UC,
++      IBV_QPT_UD,
++      IBV_QPT_XRC_SEND = 9,
++      IBV_QPT_XRC_RECV
+ };
+ struct ibv_qp_cap {
+@@ -466,6 +471,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,
+@@ -579,6 +604,11 @@ struct ibv_send_wr {
+                       uint32_t remote_qpn;
+                       uint32_t remote_qkey;
+               } ud;
++              struct {
++                      uint64_t        reserved[3];
++                      uint32_t        reserved2;
++                      uint32_t        remote_srqn;
++              } xrc;
+       } wr;
+ };
+@@ -755,7 +785,8 @@ 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 {
+@@ -763,6 +794,8 @@ struct verbs_context {
+       int (*drv_new_func1) ();        new corresponding provider call of func1
+       int (*lib_new_func1) ();        New library call func1
+       */
++      struct ibv_qp *         (*create_qp_ex)(struct ibv_context *context,
++                                              struct ibv_qp_init_attr_ex *qp_init_attr_ex);
+       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);
+@@ -1123,6 +1156,23 @@ 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)) && (mask & IBV_QP_INIT_ATTR_PD))
++              return ibv_create_qp(qp_init_attr_ex->pd,
++                                   (struct ibv_qp_init_attr *) qp_init_attr_ex);
++
++      if (!(vctx = verbs_get_ctx_op(context, create_qp_ex))) {
++              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 641ab28..87ac062 100644
+--- a/src/cmd.c
++++ b/src/cmd.c
+@@ -666,6 +666,98 @@ 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, 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 (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,
+@@ -674,7 +766,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 c8ec645..4249793 100644
+--- a/src/libibverbs.map
++++ b/src/libibverbs.map
+@@ -101,5 +101,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;