--- /dev/null
+Bottom: b2b2b839d978bb240b0641dff8459eaee9553d17
+Top: f06f319e68cf5d25276fb6ebf4f17e74c323361e
+Author: Sean Hefty <sean.hefty@intel.com>
+Date: 2012-09-12 10:37:27 -0700
+
+Refresh of xrc
+
+---
+
+diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h
+index 5af0d7f..03225cd 100644
+--- a/include/infiniband/driver.h
++++ b/include/infiniband/driver.h
+@@ -76,6 +76,11 @@ 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 ibv_xrcd *xrcd,
++ int fd, int oflags,
++ 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 ibv_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,
+@@ -100,6 +105,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_pd *pd,
++ struct ibv_srq *srq, struct ibv_srq_init_attr_ex *attr_ex,
++ struct ibv_create_srq_ex *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,
+diff --git a/include/infiniband/kern-abi.h b/include/infiniband/kern-abi.h
+index 619ea7e..58867c3 100644
+--- a/include/infiniband/kern-abi.h
++++ b/include/infiniband/kern-abi.h
+@@ -85,7 +85,10 @@ 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,
++ IB_USER_VERBS_CMD_CREATE_XSRQ
+ };
+
+ /*
+@@ -246,6 +249,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;
+@@ -593,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;
+ };
+
+@@ -707,11 +736,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 {
+@@ -804,6 +850,9 @@ 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,
++ 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 a2577d8..2b32730 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.
+ *
+@@ -106,7 +106,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 {
+@@ -312,6 +313,18 @@ struct ibv_pd {
+ uint32_t handle;
+ };
+
++enum ibv_xrcd_mask {
++ IBV_XRCD_CONTEXT = 1 << 0,
++ IBV_XRCD_HANDLE = 1 << 1,
++ IBV_XRCD_RESERVED = 1 << 2
++};
++
++struct ibv_xrcd {
++ uint64_t comp_mask;
++ struct ibv_context *context;
++ uint32_t handle;
++};
++
+ enum ibv_rereg_mr_flags {
+ IBV_REREG_MR_CHANGE_TRANSLATION = (1 << 0),
+ IBV_REREG_MR_CHANGE_PD = (1 << 1),
+@@ -410,10 +423,34 @@ 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_SRQ_TYPE = 1 << 0,
++ IBV_SRQ_INIT_ATTR_XRCD = 1 << 1,
++ IBV_SRQ_INIT_ATTR_CQ = 1 << 2,
++ IBV_SRQ_INIT_ATTR_RESERVED = 1 << 3
++};
++
++struct ibv_srq_init_attr_ex {
++ void *srq_context;
++ struct ibv_srq_attr attr;
++
++ uint64_t comp_mask;
++ enum ibv_srq_type srq_type;
++ struct ibv_xrcd *xrcd;
++ struct ibv_cq *cq;
++};
++
+ 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 {
+@@ -434,6 +471,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,
+@@ -549,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;
+ };
+
+@@ -568,6 +628,14 @@ struct ibv_mw_bind {
+ int mw_access_flags;
+ };
+
++enum ibv_srq_mask {
++ IBV_SRQ_TYPE = 1 << 0,
++ IBV_SRQ_XRCD = 1 << 1,
++ IBV_SRQ_CQ = 1 << 2,
++ IBV_SRQ_NUM = 1 << 3,
++ IBV_SRQ_RESERVED = 1 << 4
++};
++
+ struct ibv_srq {
+ struct ibv_context *context;
+ void *srq_context;
+@@ -577,6 +645,17 @@ struct ibv_srq {
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ uint32_t events_completed;
++
++ uint64_t comp_mask;
++ enum ibv_srq_type srq_type;
++ struct ibv_xrcd *xrcd;
++ struct ibv_cq *cq;
++ uint32_t srq_num;
++};
++
++enum ibv_qp_mask {
++ IBV_QP_XRCD = 1 << 0,
++ IBV_QP_RESERVED = 1 << 1
+ };
+
+ struct ibv_qp {
+@@ -594,6 +673,9 @@ struct ibv_qp {
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ uint32_t events_completed;
++
++ uint64_t comp_mask;
++ struct ibv_xrcd *xrcd;
+ };
+
+ struct ibv_comp_channel {
+@@ -728,11 +810,17 @@ struct ibv_context {
+ };
+
+ 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
+ */
++ struct ibv_qp * (*create_qp_ex)(struct ibv_pd *pd,
++ struct ibv_qp_init_attr_ex *attr_ex);
++ struct ibv_srq * (*create_srq_ex)(struct ibv_pd *pd,
++ 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);
+ size_t sz; /* Set by library on struct allocation,must be
+ * located right before struct ibv_context
+ */
+@@ -832,7 +920,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;
+
+@@ -865,6 +953,16 @@ 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
++ */
++struct ibv_xrcd *ibv_open_xrcd(struct ibv_context *context, int fd, int oflags);
++
++/**
++ * ibv_close_xrcd - Close an extended connection domain
++ */
++int ibv_close_xrcd(struct ibv_xrcd *xrcd);
++
++/**
+ * ibv_reg_mr - Register a memory region
+ */
+ struct ibv_mr *ibv_reg_mr(struct ibv_pd *pd, void *addr,
+@@ -987,6 +1085,9 @@ 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);
+
++struct ibv_srq *ibv_create_srq_ex(struct ibv_pd *pd,
++ struct ibv_srq_init_attr_ex *srq_init_attr_ex);
++
+ /**
+ * ibv_modify_srq - Modifies the attributes for the specified SRQ.
+ * @srq: The SRQ to modify.
+@@ -1037,6 +1138,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 dab8930..ed5ea6b 100644
+--- a/src/cmd.c
++++ b/src/cmd.c
+@@ -194,6 +194,39 @@ int ibv_cmd_dealloc_pd(struct ibv_pd *pd)
+ return 0;
+ }
+
++int ibv_cmd_open_xrcd(struct ibv_context *context, struct ibv_xrcd *xrcd,
++ int fd, int oflags,
++ 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);
++
++ cmd->fd = fd;
++ cmd->oflags = oflags;
++ if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
++ return errno;
++
++ VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
++
++ xrcd->handle = resp->xrcd_handle;
++ xrcd->context = context;
++
++ return 0;
++}
++
++int ibv_cmd_close_xrcd(struct ibv_xrcd *xrcd)
++{
++ struct ibv_close_xrcd cmd;
++
++ IBV_INIT_CMD(&cmd, sizeof cmd, CLOSE_XRCD);
++ cmd.xrcd_handle = xrcd->handle;
++
++ if (write(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,
+@@ -447,6 +480,50 @@ int ibv_cmd_create_srq(struct ibv_pd *pd,
+ return 0;
+ }
+
++int ibv_cmd_create_srq_ex(struct ibv_pd *pd,
++ struct ibv_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)
++{
++ IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_XSRQ, resp, resp_size);
++ cmd->user_handle = (uintptr_t) srq;
++ cmd->pd_handle = 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;
++
++ if (attr_ex->comp_mask & IBV_SRQ_INIT_ATTR_SRQ_TYPE) {
++ cmd->srq_type = attr_ex->srq_type;
++ switch (attr_ex->srq_type) {
++ case IBV_SRQT_XRC:
++ cmd->xrcd_handle = attr_ex->xrcd->handle;
++ cmd->cq_handle = attr_ex->cq->handle;
++ break;
++ default:
++ break;
++ }
++ } else {
++ cmd->srq_type = IBV_SRQT_BASIC;
++ }
++
++ if (write(pd->context->cmd_fd, cmd, cmd_size) != cmd_size)
++ return errno;
++
++ VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
++
++ srq->handle = resp->srq_handle;
++ srq->context = pd->context;
++ if (cmd->srq_type == IBV_SRQT_XRC) {
++ srq->comp_mask |= IBV_SRQ_NUM;
++ srq->srq_num = resp->srqn;
++ }
++
++ 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,
+@@ -561,13 +638,26 @@ int ibv_cmd_create_qp(struct ibv_pd *pd,
+ 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;
++
++ if (attr->qp_type == IBV_QPT_XRC_RECV) {
++ context = attr->ext.xrc_recv.xrcd->context;
++ cmd->pd_handle = attr->ext.xrc_recv.xrcd->handle;
++ } else {
++ context = pd->context;
++ cmd->pd_handle = pd->handle;
++ cmd->send_cq_handle = attr->send_cq->handle;
++
++ if (attr->qp_type != IBV_QPT_XRC_SEND) {
++ 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;
+@@ -578,14 +668,14 @@ int ibv_cmd_create_qp(struct ibv_pd *pd,
+ cmd->is_srq = !!attr->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;
+diff --git a/src/libibverbs.map b/src/libibverbs.map
+index ee9adea..b98349c 100644
+--- a/src/libibverbs.map
++++ b/src/libibverbs.map
+@@ -97,4 +97,12 @@ IBVERBS_1.1 {
+ ibv_port_state_str;
+ ibv_event_type_str;
+ ibv_wc_status_str;
++
++ ibv_cmd_open_xrcd;
++ ibv_cmd_close_xrcd;
++ ibv_cmd_create_xsrq;
++ ibv_open_xrcd;
++ ibv_close_xrcd;
++ ibv_create_xsrq;
++
+ } IBVERBS_1.0;
+diff --git a/src/verbs.c b/src/verbs.c
+index b5938f2..0c64d29 100644
+--- a/src/verbs.c
++++ b/src/verbs.c
+@@ -154,6 +154,32 @@ int __ibv_dealloc_pd(struct ibv_pd *pd)
+ }
+ default_symver(__ibv_dealloc_pd, ibv_dealloc_pd);
+
++struct ibv_xrcd *__ibv_open_xrcd(struct ibv_context *context, int fd, int oflags)
++{
++ struct ibv_xrc_ops *ops;
++ struct ibv_xrcd *xrcd;
++
++ ops = ibv_get_ext_ops(context, IBV_XRC_OPS);
++ if (!ops || !ops->open_xrcd)
++ return NULL;
++
++ xrcd = ops->open_xrcd(context, fd, oflags);
++ if (xrcd)
++ xrcd->context = context;
++
++ return xrcd;
++}
++default_symver(__ibv_open_xrcd, ibv_open_xrcd);
++
++int __ibv_close_xrcd(struct ibv_xrcd *xrcd)
++{
++ struct ibv_xrc_ops *ops;
++
++ ops = ibv_get_ext_ops(xrcd->context, IBV_XRC_OPS);
++ return ops->close_xrcd(xrcd);
++}
++default_symver(__ibv_close_xrcd, ibv_close_xrcd);
++
+ struct ibv_mr *__ibv_reg_mr(struct ibv_pd *pd, void *addr,
+ size_t length, int access)
+ {
+@@ -353,12 +379,40 @@ void __ibv_ack_cq_events(struct ibv_cq *cq, unsigned int nevents)
+ }
+ default_symver(__ibv_ack_cq_events, ibv_ack_cq_events);
+
++/*
++ * Existing apps may be using an older, smaller version of srq_init_attr.
++ */
+ struct ibv_srq *__ibv_create_srq(struct ibv_pd *pd,
+ struct ibv_srq_init_attr *srq_init_attr)
+ {
++ struct ibv_srq_init_attr attr;
+ struct ibv_srq *srq;
+
+- if (!pd->context->ops.create_srq)
++ attr.srq_context = srq_init_attr->srq_context;
++ attr.attr = srq_init_attr->attr;
++ attr.srq_type = IBV_SRQT_BASIC;
++
++ srq = ibv_create_xsrq(pd, &attr);
++ if (srq)
++ srq_init_attr->attr = attr.attr;
++
++ return srq;
++}
++default_symver(__ibv_create_srq, ibv_create_srq);
++
++struct ibv_srq *__ibv_create_srq_ex(struct ibv_pd *pd,
++ struct ibv_srq_init_attr_ex *srq_init_attr_ex)
++{
++ struct verbs_context *vcontext;
++ struct ibv_srq *srq;
++
++ vcontext = verbs_get_ctx(pd->context);
++ if (!vcontext || !vcontext->create_srq_ex)
++ return NULL;
++
++ if (!pd->context->ops.create_srq ||
++ (srq_init_attr->srq_type != IBV_SRQT_BASIC &&
++ !ibv_get_ext_support(pd->context->device)))
+ return NULL;
+
+ srq = pd->context->ops.create_srq(pd, srq_init_attr);
+@@ -369,11 +423,19 @@ struct ibv_srq *__ibv_create_srq(struct ibv_pd *pd,
+ srq->events_completed = 0;
+ pthread_mutex_init(&srq->mutex, NULL);
+ pthread_cond_init(&srq->cond, NULL);
++
++ if (srq_init_attr->srq_type == IBV_SRQT_XRC) {
++ srq->ext.xrc.xrcd = srq_init_attr->ext.xrc.xrcd;
++ srq->ext.xrc.cq = srq_init_attr->ext.xrc.cq;
++ }
++
++ if (ibv_get_ext_support(pd->context->device))
++ srq->srq_type = srq_init_attr->srq_type;
+ }
+
+ return srq;
+ }
+-default_symver(__ibv_create_srq, ibv_create_srq);
++default_symver(__ibv_create_xsrq, ibv_create_xsrq);
+
+ int __ibv_modify_srq(struct ibv_srq *srq,
+ struct ibv_srq_attr *srq_attr,
+@@ -398,15 +460,33 @@ 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_context *context;
++ struct ibv_qp *qp;
+
++ context = pd ? pd->context : qp_init_attr->ext.xrc_recv.xrcd->context;
++ qp = context->ops.create_qp(pd, qp_init_attr);
+ if (qp) {
+- qp->context = pd->context;
+- qp->qp_context = qp_init_attr->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->context = context;
++ qp->qp_context = qp_init_attr->qp_context;
++
++ if (qp_init_attr->qp_type == IBV_QPT_XRC_RECV) {
++ qp->pd = NULL;
++ qp->send_cq = qp->recv_cq = NULL;
++ qp->srq = NULL;
++ qp->ext.xrc_recv.xrcd = qp_init_attr->ext.xrc_recv.xrcd;
++ } else {
++ if (qp_init_attr->qp_type == IBV_QPT_XRC_SEND) {
++ qp->recv_cq = NULL;
++ qp->srq = NULL;
++ } else {
++ qp->recv_cq = qp_init_attr->recv_cq;
++ qp->srq = qp_init_attr->srq;
++ }
++
++ qp->pd = pd;
++ qp->send_cq = qp_init_attr->send_cq;
++ }
++
+ qp->qp_type = qp_init_attr->qp_type;
+ qp->state = IBV_QPS_RESET;
+ qp->events_completed = 0;