--- /dev/null
+Bottom: eb069dacc3502ba7f9e575f462e80f48ec5b8fd4
+Top: 5d8a697fd1103edb9ae822dea6fc96fd0b09f5ba
+Author: Sean Hefty <sean.hefty@intel.com>
+Date: 2012-09-26 11:44:14 -0700
+
+Refresh of xrc_qp
+
+---
+
+diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h
+index dccfd1f..406eb7d 100644
+--- a/include/infiniband/driver.h
++++ b/include/infiniband/driver.h
+@@ -150,6 +150,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_pd *pd,
++ struct ibv_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 e67bf21..71b5ef2 100644
+--- a/include/infiniband/verbs.h
++++ b/include/infiniband/verbs.h
+@@ -107,7 +107,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 {
+@@ -440,7 +441,9 @@ struct ibv_srq_init_attr_ex {
+ enum ibv_qp_type {
+ IBV_QPT_RC = 2,
+ IBV_QPT_UC,
+- IBV_QPT_UD
++ IBV_QPT_UD,
++ IBV_QPT_XRC_SEND = 9,
++ IBV_QPT_XRC_RECV
+ };
+
+ struct ibv_qp_cap {
+@@ -461,6 +464,24 @@ struct ibv_qp_init_attr {
+ int sq_sig_all;
+ };
+
++enum ibv_qp_init_attr_mask {
++ IBV_QP_INIT_ATTR_XRCD = 1 << 0,
++ IBV_QP_INIT_ATTR_RESERVED = 1 << 1
++};
++
++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;
++
++ uint64_t comp_mask;
++ struct ibv_xrcd *xrcd;
++};
++
+ enum ibv_qp_attr_mask {
+ IBV_QP_STATE = 1 << 0,
+ IBV_QP_CUR_STATE = 1 << 1,
+@@ -576,6 +597,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;
+ };
+
+@@ -606,6 +632,11 @@ struct ibv_srq {
+ uint32_t events_completed;
+ };
+
++enum ibv_qp_mask {
++ IBV_QP_XRCD = 1 << 0,
++ IBV_QP_RESERVED = 1 << 1
++};
++
+ struct ibv_qp {
+ struct ibv_context *context;
+ void *qp_context;
+@@ -621,6 +652,9 @@ struct ibv_qp {
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ uint32_t events_completed;
++
++ uint32_t comp_mask;
++ struct ibv_xrcd *xrcd;
+ };
+
+ struct ibv_comp_channel {
+@@ -759,6 +793,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_pd *pd,
++ 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_pd *pd,
+ struct ibv_srq_init_attr_ex *srq_init_attr_ex);
+@@ -1118,6 +1154,9 @@ 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);
+
++struct ibv_qp *ibv_create_qp_ex(struct ibv_pd *pd,
++ struct ibv_qp_init_attr_ex *qp_init_attr_ex);
++
+ /**
+ * ibv_modify_qp - Modify a queue pair.
+ */
+diff --git a/src/cmd.c b/src/cmd.c
+index e03676d..ccadb94 100644
+--- a/src/cmd.c
++++ b/src/cmd.c
+@@ -653,43 +653,56 @@ int ibv_cmd_destroy_srq(struct ibv_srq *srq)
+ 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,
+- struct ibv_create_qp_resp *resp, size_t resp_size)
++int ibv_cmd_create_qp_ex(struct ibv_pd *pd,
++ struct ibv_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 ibv_context *context;
++
+ IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_QP, resp, resp_size);
+
+ cmd->user_handle = (uintptr_t) qp;
+- 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;
+- cmd->max_send_wr = attr->cap.max_send_wr;
+- cmd->max_recv_wr = attr->cap.max_recv_wr;
+- cmd->max_send_sge = attr->cap.max_send_sge;
+- cmd->max_recv_sge = attr->cap.max_recv_sge;
+- cmd->max_inline_data = attr->cap.max_inline_data;
+- cmd->sq_sig_all = attr->sq_sig_all;
+- cmd->qp_type = attr->qp_type;
+- cmd->is_srq = !!attr->srq;
++
++ if (attr_ex->comp_mask & IBV_QP_INIT_ATTR_XRCD) {
++ context = attr_ex->xrcd->context;
++ cmd->pd_handle = attr_ex->xrcd->handle;
++ } else {
++ context = pd->context;
++ cmd->pd_handle = 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(pd->context->cmd_fd, cmd, cmd_size) != cmd_size)
++ if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
+ return errno;
+
+ (void) VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
+
+ qp->handle = resp->qp_handle;
+ qp->qp_num = resp->qpn;
+- qp->context = pd->context;
++ qp->context = context;
+
+ if (abi_ver > 3) {
+- attr->cap.max_recv_sge = resp->max_recv_sge;
+- attr->cap.max_send_sge = resp->max_send_sge;
+- attr->cap.max_recv_wr = resp->max_recv_wr;
+- attr->cap.max_send_wr = resp->max_send_wr;
+- attr->cap.max_inline_data = resp->max_inline_data;
++ 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) {
+@@ -711,6 +724,23 @@ int ibv_cmd_create_qp(struct ibv_pd *pd,
+ 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,
++ struct ibv_create_qp_resp *resp, size_t resp_size)
++{
++ struct ibv_qp_init_attr_ex attr_ex;
++ int ret;
++
++ memcpy(&attr_ex, attr, sizeof *attr);
++ attr_ex.comp_mask = 0;
++ ret = ibv_cmd_create_qp_ex(pd, qp, &attr_ex, cmd, cmd_size, resp, resp_size);
++ if (!ret)
++ memcpy(attr, &attr_ex, sizeof *attr);
++
++ return ret;
++}
++
+ 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 c8ec645..f458679 100644
+--- a/src/libibverbs.map
++++ b/src/libibverbs.map
+@@ -101,5 +101,7 @@ IBVERBS_1.1 {
+ ibv_cmd_open_xrcd;
+ ibv_cmd_close_xrcd;
+ ibv_cmd_create_srq_ex;
++ ibv_create_qp_ex;
++ ibv_cmd_create_qp_ex;
+
+ } IBVERBS_1.0;
+diff --git a/src/verbs.c b/src/verbs.c
+index b5938f2..81385ed 100644
+--- a/src/verbs.c
++++ b/src/verbs.c
+@@ -395,19 +395,45 @@ int __ibv_destroy_srq(struct ibv_srq *srq)
+ }
+ default_symver(__ibv_destroy_srq, ibv_destroy_srq);
+
+-struct ibv_qp *__ibv_create_qp(struct ibv_pd *pd,
+- struct ibv_qp_init_attr *qp_init_attr)
+-{
+- struct ibv_qp *qp = pd->context->ops.create_qp(pd, qp_init_attr);
++struct ibv_qp *__ibv_create_qp_ex(struct ibv_pd *pd,
++ struct ibv_qp_init_attr_ex *qp_init_attr_ex)
++{
++ struct verbs_context *context_ex;
++ struct ibv_context *context = NULL;
++ struct ibv_qp *qp;
++
++ if (pd) {
++ context = pd->context;
++ } else {
++ if (qp_init_attr_ex->comp_mask & IBV_QP_INIT_ATTR_XRCD)
++ context = qp_init_attr_ex->xrcd->context;
++ }
++ if (!context) {
++ errno = EINVAL;
++ return NULL;
++ }
++
++ context_ex = verbs_get_ctx(context);
++ if (qp_init_attr_ex->comp_mask) {
++ if (!context_ex->create_qp_ex ||
++ qp_init_attr_ex->comp_mask >= IBV_QP_INIT_ATTR_RESERVED) {
++ errno = ENOSYS;
++ return NULL;
++ }
++ qp = context_ex->create_qp_ex(pd, qp_init_attr_ex);
++ } else {
++ qp = context->ops.create_qp(pd, (struct ibv_qp_init_attr *)
++ qp_init_attr_ex);
++ }
+
+ if (qp) {
+- qp->context = pd->context;
+- qp->qp_context = qp_init_attr->qp_context;
++ qp->context = context;
++ qp->qp_context = qp_init_attr_ex->qp_context;
+ qp->pd = pd;
+- qp->send_cq = qp_init_attr->send_cq;
+- qp->recv_cq = qp_init_attr->recv_cq;
+- qp->srq = qp_init_attr->srq;
+- qp->qp_type = qp_init_attr->qp_type;
++ qp->send_cq = qp_init_attr_ex->send_cq;
++ qp->recv_cq = qp_init_attr_ex->recv_cq;
++ qp->srq = qp_init_attr_ex->srq;
++ qp->qp_type = qp_init_attr_ex->qp_type;
+ qp->state = IBV_QPS_RESET;
+ qp->events_completed = 0;
+ pthread_mutex_init(&qp->mutex, NULL);
+@@ -416,6 +442,22 @@ struct ibv_qp *__ibv_create_qp(struct ibv_pd *pd,
+
+ return qp;
+ }
++default_symver(__ibv_create_qp_ex, ibv_create_qp_ex);
++
++struct ibv_qp *__ibv_create_qp(struct ibv_pd *pd,
++ struct ibv_qp_init_attr *qp_init_attr)
++{
++ struct ibv_qp_init_attr_ex qp_init_attr_ex;
++ struct ibv_qp *qp;
++
++ memcpy(&qp_init_attr_ex, qp_init_attr, sizeof *qp_init_attr);
++ qp_init_attr_ex.comp_mask = 0;
++ qp = ibv_create_qp_ex(pd, &qp_init_attr_ex);
++ if (qp)
++ memcpy(qp_init_attr, &qp_init_attr_ex, sizeof *qp_init_attr);
++
++ return qp;
++}
+ default_symver(__ibv_create_qp, ibv_create_qp);
+
+ int __ibv_query_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,