]> git.openfabrics.org - ~shefty/libibverbs.git/commitdiff
refresh (create temporary patch)
authorSean Hefty <sean.hefty@intel.com>
Wed, 12 Sep 2012 17:37:28 +0000 (10:37 -0700)
committerSean Hefty <sean.hefty@intel.com>
Wed, 12 Sep 2012 17:37:28 +0000 (10:37 -0700)
meta
patches/refresh-temp [new file with mode: 0644]

diff --git a/meta b/meta
index 0b41ef6222d1db5b4f6b1109a0870813216924db..d29839dfe648d3daf54f2d2bba4c46519343bdaf 100644 (file)
--- a/meta
+++ b/meta
@@ -1,8 +1,9 @@
 Version: 1
-Previous: 58cbebedacbad09a7e4eb026fe4d3429d0f17908
-Head: b0b747e276b58ee5967383cf2ff60316af401054
+Previous: b33d351885f70a61cd6e305a856f50e08ee38531
+Head: 71ddc754431245a2b75b56afcb5bc975d7ef113c
 Applied:
   verbs-ext: 6fbf2b29ca68fc10b7ee47dc0c09f54db0b32320
   xrc: b0b747e276b58ee5967383cf2ff60316af401054
+  refresh-temp: 71ddc754431245a2b75b56afcb5bc975d7ef113c
 Unapplied:
 Hidden:
diff --git a/patches/refresh-temp b/patches/refresh-temp
new file mode 100644 (file)
index 0000000..642d5b9
--- /dev/null
@@ -0,0 +1,655 @@
+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;