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

diff --git a/meta b/meta
index dc1c11ba6227580bbfa8cd2f22e62860c2d9ae1d..2568f3a935bd4ba2cf952fe52a65acae3d8c541e 100644 (file)
--- a/meta
+++ b/meta
@@ -1,9 +1,10 @@
 Version: 1
-Previous: 287e4651822d976d4507beea53ecd231a1f80be6
-Head: 3dd85d0f315692be4f31f56206a7e9107cc34a2f
+Previous: b4036f355233420f6717014708bcebd13aa5641a
+Head: 8a1ec6fb0b32743cd96e37374bf23fe23c75c1f8
 Applied:
   verbs-ext: 6fbf2b29ca68fc10b7ee47dc0c09f54db0b32320
   compat-ex: 3dd85d0f315692be4f31f56206a7e9107cc34a2f
+  refresh-temp: 8a1ec6fb0b32743cd96e37374bf23fe23c75c1f8
 Unapplied:
   xrcd: 0e21cac2fc216f26a141a34cfb9e6ce5adfcd9f0
 Hidden:
diff --git a/patches/refresh-temp b/patches/refresh-temp
new file mode 100644 (file)
index 0000000..c807bdd
--- /dev/null
@@ -0,0 +1,974 @@
+Bottom: ff097d1ced43527502d645f75ecff80782d96d2d
+Top:    15914285befe61b6f050f9b8c56512b8ec98cbfe
+Author: Sean Hefty <sean.hefty@intel.com>
+Date:   2012-09-12 16:34:59 -0700
+
+Refresh of compat-ex
+
+---
+
+diff --git a/src/compat-ex.c b/src/compat-ex.c
+index 254747c..d822f73 100644
+--- a/src/compat-ex.c
++++ b/src/compat-ex.c
+@@ -43,773 +43,356 @@
+ #include "ibverbs.h"
+-struct ibv_pd_ex {
++struct _ibv_pd_ex {
+       struct ibv_pd  pd;
+       struct ibv_pd *real_pd;
+ };
+-struct ibv_mr_ex {
++struct _ibv_mr_ex {
+       struct ibv_mr  mr;
+       struct ibv_mr *real_mr;
+ };
+-struct ibv_mw_ex {
+-      struct ibv_mw  mw;
+-      struct ibv_mw *real_mw;
+-};
+-
+-struct ibv_srq_ex {
++struct _ibv_srq_ex {
+       struct ibv_srq  srq;
+       struct ibv_srq *real_srq;
+ };
+-struct ibv_qp_ex {
++struct _ibv_qp_ex {
+       struct ibv_qp  qp;
+       struct ibv_qp *real_qp;
+ };
+-struct ibv_cq_ex {
++struct _ibv_cq_ex {
+       struct ibv_cq  cq;
+       struct ibv_cq *real_cq;
+ };
+-struct ibv_ah_ex {
++struct _ibv_ah_ex {
+       struct ibv_ah  ah;
+       struct ibv_ah *real_ah;
+ };
+-struct ibv_context_ops_1_0 {
+-      int                     (*query_device)(struct ibv_context *context,
+-                                            struct ibv_device_attr *device_attr);
+-      int                     (*query_port)(struct ibv_context *context, uint8_t port_num,
+-                                            struct ibv_port_attr *port_attr);
+-      struct ibv_pd *         (*alloc_pd)(struct ibv_context *context);
+-      int                     (*dealloc_pd)(struct ibv_pd *pd);
+-      struct ibv_mr *         (*reg_mr)(struct ibv_pd *pd, void *addr, size_t length,
+-                                        int access);
+-      int                     (*dereg_mr)(struct ibv_mr *mr);
+-      struct ibv_cq *         (*create_cq)(struct ibv_context *context, int cqe,
+-                                           struct ibv_comp_channel *channel,
+-                                           int comp_vector);
+-      int                     (*poll_cq)(struct ibv_cq_1_0 *cq, int num_entries,
+-                                         struct ibv_wc *wc);
+-      int                     (*req_notify_cq)(struct ibv_cq_1_0 *cq,
+-                                               int solicited_only);
+-      void                    (*cq_event)(struct ibv_cq *cq);
+-      int                     (*resize_cq)(struct ibv_cq *cq, int cqe);
+-      int                     (*destroy_cq)(struct ibv_cq *cq);
+-      struct ibv_srq *        (*create_srq)(struct ibv_pd *pd,
+-                                            struct ibv_srq_init_attr *srq_init_attr);
+-      int                     (*modify_srq)(struct ibv_srq *srq,
+-                                            struct ibv_srq_attr *srq_attr,
+-                                            int srq_attr_mask);
+-      int                     (*query_srq)(struct ibv_srq *srq,
+-                                           struct ibv_srq_attr *srq_attr);
+-      int                     (*destroy_srq)(struct ibv_srq *srq);
+-      int                     (*post_srq_recv)(struct ibv_srq_1_0 *srq,
+-                                               struct ibv_recv_wr_1_0 *recv_wr,
+-                                               struct ibv_recv_wr_1_0 **bad_recv_wr);
+-      struct ibv_qp *         (*create_qp)(struct ibv_pd *pd, struct ibv_qp_init_attr *attr);
+-      int                     (*query_qp)(struct ibv_qp *qp, struct ibv_qp_attr *attr,
+-                                          int attr_mask,
+-                                          struct ibv_qp_init_attr *init_attr);
+-      int                     (*modify_qp)(struct ibv_qp *qp, struct ibv_qp_attr *attr,
+-                                           int attr_mask);
+-      int                     (*destroy_qp)(struct ibv_qp *qp);
+-      int                     (*post_send)(struct ibv_qp_1_0 *qp,
+-                                           struct ibv_send_wr_1_0 *wr,
+-                                           struct ibv_send_wr_1_0 **bad_wr);
+-      int                     (*post_recv)(struct ibv_qp_1_0 *qp,
+-                                           struct ibv_recv_wr_1_0 *wr,
+-                                           struct ibv_recv_wr_1_0 **bad_wr);
+-      struct ibv_ah *         (*create_ah)(struct ibv_pd *pd, struct ibv_ah_attr *attr);
+-      int                     (*destroy_ah)(struct ibv_ah *ah);
+-      int                     (*attach_mcast)(struct ibv_qp *qp, union ibv_gid *gid,
+-                                              uint16_t lid);
+-      int                     (*detach_mcast)(struct ibv_qp *qp, union ibv_gid *gid,
+-                                              uint16_t lid);
+-};
+-
+-struct ibv_context_1_0 {
+-      struct ibv_device_1_0          *device;
+-      struct ibv_context_ops_1_0      ops;
+-      int                             cmd_fd;
+-      int                             async_fd;
+-      int                             num_comp_vectors;
+-
+-      struct ibv_context             *real_context; /* was abi_compat member */
++struct _ibv_context_ex {
++      struct ibv_context  context;
++      struct ibv_context *real_context;
+ };
+-struct ibv_device_1_0 **__ibv_get_device_list_1_0(int *num)
+-{
+-      struct ibv_device **real_list;
+-      struct ibv_device_1_0 **l;
+-      int i, n;
+-
+-      real_list = ibv_get_device_list(&n);
+-      if (!real_list)
+-              return NULL;
+-
+-      l = calloc(n + 2, sizeof (struct ibv_device_1_0 *));
+-      if (!l)
+-              goto free_device_list;
+-
+-      l[0] = (void *) real_list;
+-
+-      for (i = 0; i < n; ++i) {
+-              l[i + 1] = calloc(1, sizeof (struct ibv_device_1_0));
+-              if (!l[i + 1])
+-                      goto fail;
+-              l[i + 1]->real_device = real_list[i];
+-      }
+-
+-      if (num)
+-              *num = n;
+-
+-      return l + 1;
+-
+-fail:
+-      for (i = 1; i <= n; ++i)
+-              if (l[i])
+-                      free(l[i]);
+-      free(l);
+-
+-free_device_list:
+-      ibv_free_device_list(real_list);
+-      return NULL;
+-}
+-symver(__ibv_get_device_list_1_0, ibv_get_device_list, IBVERBS_1.0);
+-
+-void __ibv_free_device_list_1_0(struct ibv_device_1_0 **list)
+-{
+-      struct ibv_device_1_0 **l = list;
+-
+-      while (*l) {
+-              free(*l);
+-              ++l;
+-      }
+-
+-      ibv_free_device_list((void *) list[-1]);
+-      free(list - 1);
+-}
+-symver(__ibv_free_device_list_1_0, ibv_free_device_list, IBVERBS_1.0);
+-
+-const char *__ibv_get_device_name_1_0(struct ibv_device_1_0 *device)
+-{
+-      return ibv_get_device_name(device->real_device);
+-}
+-symver(__ibv_get_device_name_1_0, ibv_get_device_name, IBVERBS_1.0);
+-
+-uint64_t __ibv_get_device_guid_1_0(struct ibv_device_1_0 *device)
+-{
+-      return ibv_get_device_guid(device->real_device);
+-}
+-symver(__ibv_get_device_guid_1_0, ibv_get_device_guid, IBVERBS_1.0);
+-
+-static int poll_cq_wrapper_1_0(struct ibv_cq_1_0 *cq, int num_entries,
+-                             struct ibv_wc *wc)
++static int _ibv_query_device_ex(struct ibv_context *context,
++                              struct ibv_device_attr *device_attr)
+ {
+-      return cq->context->real_context->ops.poll_cq(cq->real_cq, num_entries, wc);
++      struct _ibv_context_ex *context_ex;
++      context_ex = container_of(context, struct _ibv_context_ex, context);
++      return ibv_query_device(context_ex->real_context, device_attr);
+ }
+-static int req_notify_cq_wrapper_1_0(struct ibv_cq_1_0 *cq, int sol_only)
++static int _ibv_query_port_ex(struct ibv_context *context, uint8_t port_num,
++                            struct ibv_port_attr *port_attr)
+ {
+-      return cq->context->real_context->ops.req_notify_cq(cq->real_cq, sol_only);
++      struct _ibv_context_ex *context_ex;
++      context_ex = container_of(context, struct _ibv_context_ex, context);
++      return ibv_query_port(context_ex->real_context, port_num, port_attr);
+ }
+-static int post_srq_recv_wrapper_1_0(struct ibv_srq_1_0 *srq, struct ibv_recv_wr_1_0 *wr,
+-                               struct ibv_recv_wr_1_0 **bad_wr)
++static struct ibv_pd *_ibv_alloc_pd_ex(struct ibv_context *context)
+ {
+-      struct ibv_recv_wr_1_0 *w;
+-      struct ibv_recv_wr *real_wr, *head_wr = NULL, *tail_wr = NULL, *real_bad_wr;
+-      int ret;
+-
+-      for (w = wr; w; w = w->next) {
+-              real_wr = alloca(sizeof *real_wr);
+-              real_wr->wr_id   = w->wr_id;
+-              real_wr->sg_list = w->sg_list;
+-              real_wr->num_sge = w->num_sge;
+-              real_wr->next    = NULL;
+-              if (tail_wr)
+-                      tail_wr->next = real_wr;
+-              else
+-                      head_wr = real_wr;
+-
+-              tail_wr = real_wr;
+-      }
+-
+-      ret = srq->context->real_context->ops.post_srq_recv(srq->real_srq, head_wr,
+-                                                          &real_bad_wr);
+-
+-      if (ret) {
+-              for (real_wr = head_wr, w = wr;
+-                   real_wr;
+-                   real_wr = real_wr->next, w = w->next)
+-                      if (real_wr == real_bad_wr) {
+-                              *bad_wr = w;
+-                              break;
+-                      }
+-      }
+-
+-      return ret;
+-}
+-
+-static int post_send_wrapper_1_0(struct ibv_qp_1_0 *qp, struct ibv_send_wr_1_0 *wr,
+-                               struct ibv_send_wr_1_0 **bad_wr)
+-{
+-      struct ibv_send_wr_1_0 *w;
+-      struct ibv_send_wr *real_wr, *head_wr = NULL, *tail_wr = NULL, *real_bad_wr;
+-      int is_ud = qp->qp_type == IBV_QPT_UD;
+-      int ret;
++      struct _ibv_context_ex *context_ex;
++      struct _ibv_pd_ex *pd_ex;
+-      for (w = wr; w; w = w->next) {
+-              real_wr = alloca(sizeof *real_wr);
+-              real_wr->wr_id = w->wr_id;
+-              real_wr->next  = NULL;
+-
+-              memcpy(&real_wr->sg_list, &w->sg_list,
+-                     sizeof *w - offsetof(struct ibv_send_wr, sg_list));
+-
+-              if (is_ud)
+-                      real_wr->wr.ud.ah = w->wr.ud.ah->real_ah;
+-
+-              if (tail_wr)
+-                      tail_wr->next = real_wr;
+-              else
+-                      head_wr = real_wr;
+-
+-              tail_wr = real_wr;
+-      }
++      context_ex = container_of(context, struct _ibv_context_ex, context);
++      pd_ex = calloc(1, sizeof *pd_ex);
++      if (!pd_ex)
++              return NULL;
+-      ret = qp->context->real_context->ops.post_send(qp->real_qp, head_wr,
+-                                                     &real_bad_wr);
+-
+-      if (ret) {
+-              for (real_wr = head_wr, w = wr;
+-                   real_wr;
+-                   real_wr = real_wr->next, w = w->next)
+-                      if (real_wr == real_bad_wr) {
+-                              *bad_wr = w;
+-                              break;
+-                      }
++      pd_ex->real_pd = ibv_alloc_pd(context_ex->real_context);
++      if (!pd_ex->real_pd) {
++              free(pd_ex);
++              return NULL;
+       }
+-      return ret;
++      return &pd_ex->pd;
+ }
+-static int post_recv_wrapper_1_0(struct ibv_qp_1_0 *qp, struct ibv_recv_wr_1_0 *wr,
+-                               struct ibv_recv_wr_1_0 **bad_wr)
++static int _ibv_dealloc_pd_ex(struct ibv_pd *pd)
+ {
+-      struct ibv_recv_wr_1_0 *w;
+-      struct ibv_recv_wr *real_wr, *head_wr = NULL, *tail_wr = NULL, *real_bad_wr;
++      struct _ibv_pd_ex *pd_ex = container_of(pd, struct _ibv_pd_ex, pd);
+       int ret;
+-      for (w = wr; w; w = w->next) {
+-              real_wr = alloca(sizeof *real_wr);
+-              real_wr->wr_id   = w->wr_id;
+-              real_wr->sg_list = w->sg_list;
+-              real_wr->num_sge = w->num_sge;
+-              real_wr->next    = NULL;
+-              if (tail_wr)
+-                      tail_wr->next = real_wr;
+-              else
+-                      head_wr = real_wr;
+-
+-              tail_wr = real_wr;
+-      }
+-
+-      ret = qp->context->real_context->ops.post_recv(qp->real_qp, head_wr,
+-                                                     &real_bad_wr);
+-
+-      if (ret) {
+-              for (real_wr = head_wr, w = wr;
+-                   real_wr;
+-                   real_wr = real_wr->next, w = w->next)
+-                      if (real_wr == real_bad_wr) {
+-                              *bad_wr = w;
+-                              break;
+-                      }
+-      }
++      ret = ibv_dealloc_pd(pd_ex->real_pd);
++      if (ret)
++              return ret;
+-      return ret;
++      free(pd_ex);
++      return 0;
+ }
+-struct ibv_context_1_0 *__ibv_open_device_1_0(struct ibv_device_1_0 *device)
++static struct ibv_mr *_ibv_reg_mr_ex(struct ibv_pd *pd, void *addr, size_t length,
++                                   int access)
+ {
+-      struct ibv_context     *real_ctx;
+-      struct ibv_context_1_0 *ctx;
++      struct _ibv_pd_ex *pd_ex = container_of(pd, struct _ibv_pd_ex, pd);
++      struct _ibv_mr_ex *mr_ex;
+-      ctx = malloc(sizeof *ctx);
+-      if (!ctx)
++      mr_ex = calloc(1, sizeof *mr_ex);
++      if (!mr_ex)
+               return NULL;
+-      real_ctx = ibv_open_device(device->real_device);
+-      if (!real_ctx) {
+-              free(ctx);
++      mr_ex->real_mr = ibv_reg_mr(pd_ex->real_pd, addr, length, access);
++      if (!mr_ex->real_mr) {
++              free(mr_ex);
+               return NULL;
+       }
+-      ctx->device       = device;
+-      ctx->real_context = real_ctx;
+-
+-      ctx->ops.poll_cq       = poll_cq_wrapper_1_0;
+-      ctx->ops.req_notify_cq = req_notify_cq_wrapper_1_0;
+-      ctx->ops.post_send     = post_send_wrapper_1_0;
+-      ctx->ops.post_recv     = post_recv_wrapper_1_0;
+-      ctx->ops.post_srq_recv = post_srq_recv_wrapper_1_0;
+-
+-      return ctx;
++      mr_ex->mr.lkey = mr_ex->real_mr->lkey;
++      mr_ex->mr.rkey = mr_ex->real_mr->rkey;
++      return &mr_ex->mr;
+ }
+-symver(__ibv_open_device_1_0, ibv_open_device, IBVERBS_1.0);
+-int __ibv_close_device_1_0(struct ibv_context_1_0 *context)
++static int _ibv_dereg_mr_ex(struct ibv_mr *mr)
+ {
++      struct _ibv_mr_ex *mr_ex = container_of(mr, struct _ibv_mr_ex, mr);
+       int ret;
+-      ret = ibv_close_device(context->real_context);
++      ret = ibv_dereg_mr(mr_ex->real_mr);
+       if (ret)
+               return ret;
+-      free(context);
++      free(mr_ex);
+       return 0;
+ }
+-symver(__ibv_close_device_1_0, ibv_close_device, IBVERBS_1.0);
+-int __ibv_get_async_event_1_0(struct ibv_context_1_0 *context,
+-                            struct ibv_async_event *event)
++/*
++ * ibv_create_cq holds the channel mutex while calling the provider.  We
++ * cannot call ibv_create_cq recursively, so we need to call the provider
++ * directly and duplicate initializing the ibv_cq.
++ */
++struct ibv_cq *_ibv_create_cq_ex(struct ibv_context *context, int cqe,
++                               struct ibv_comp_channel *channel,
++                               int comp_vector)
+ {
+-      int ret;
+-
+-      ret = ibv_get_async_event(context->real_context, event);
+-      if (ret)
+-              return ret;
+-
+-      switch (event->event_type) {
+-      case IBV_EVENT_CQ_ERR:
+-              event->element.cq = event->element.cq->cq_context;
+-              break;
+-
+-      case IBV_EVENT_QP_FATAL:
+-      case IBV_EVENT_QP_REQ_ERR:
+-      case IBV_EVENT_QP_ACCESS_ERR:
+-      case IBV_EVENT_COMM_EST:
+-      case IBV_EVENT_SQ_DRAINED:
+-      case IBV_EVENT_PATH_MIG:
+-      case IBV_EVENT_PATH_MIG_ERR:
+-      case IBV_EVENT_QP_LAST_WQE_REACHED:
+-              event->element.qp = event->element.qp->qp_context;
+-              break;
+-
+-      case IBV_EVENT_SRQ_ERR:
+-      case IBV_EVENT_SRQ_LIMIT_REACHED:
+-              event->element.srq = event->element.srq->srq_context;
+-              break;
+-
+-      default:
+-              break;
+-      }
++      struct _ibv_context_ex *context_ex;
++      struct _ibv_cq_ex *cq_ex;
+-      return ret;
+-}
+-symver(__ibv_get_async_event_1_0, ibv_get_async_event, IBVERBS_1.0);
++      context_ex = container_of(context, struct _ibv_context_ex, context);
++      cq_ex = calloc(1, sizeof *cq_ex);
++      if (!cq_ex)
++              return NULL;
+-void __ibv_ack_async_event_1_0(struct ibv_async_event *event)
+-{
+-      struct ibv_async_event real_event = *event;
+-
+-      switch (event->event_type) {
+-      case IBV_EVENT_CQ_ERR:
+-              real_event.element.cq =
+-                      ((struct ibv_cq_1_0 *) event->element.cq)->real_cq;
+-              break;
+-
+-      case IBV_EVENT_QP_FATAL:
+-      case IBV_EVENT_QP_REQ_ERR:
+-      case IBV_EVENT_QP_ACCESS_ERR:
+-      case IBV_EVENT_COMM_EST:
+-      case IBV_EVENT_SQ_DRAINED:
+-      case IBV_EVENT_PATH_MIG:
+-      case IBV_EVENT_PATH_MIG_ERR:
+-      case IBV_EVENT_QP_LAST_WQE_REACHED:
+-              real_event.element.qp =
+-                      ((struct ibv_qp_1_0 *) event->element.qp)->real_qp;
+-              break;
+-
+-      case IBV_EVENT_SRQ_ERR:
+-      case IBV_EVENT_SRQ_LIMIT_REACHED:
+-              real_event.element.srq =
+-                      ((struct ibv_srq_1_0 *) event->element.srq)->real_srq;
+-              break;
+-
+-      default:
+-              break;
++      cq_ex->real_cq = context_ex->real_context->ops.create_cq(context_ex->real_context,
++                                                               cqe, channel, comp_vector);
++      if (!cq_ex->real_cq) {
++              free(cq_ex);
++              return NULL;
+       }
+-      ibv_ack_async_event(&real_event);
+-}
+-symver(__ibv_ack_async_event_1_0, ibv_ack_async_event, IBVERBS_1.0);
+-
+-int __ibv_query_device_1_0(struct ibv_context_1_0 *context,
+-                         struct ibv_device_attr *device_attr)
+-{
+-      return ibv_query_device(context->real_context, device_attr);
+-}
+-symver(__ibv_query_device_1_0, ibv_query_device, IBVERBS_1.0);
++      cq_ex->real_cq->context = context_ex->real_context;
++      cq_ex->real_cq->channel = channel;
++      if (channel)
++              ++channel->refcnt;
++      cq_ex->real_cq->cq_context = cq_ex;
++      cq_ex->real_cq->comp_events_completed  = 0;
++      cq_ex->real_cq->async_events_completed = 0;
++      pthread_mutex_init(&cq_ex->real_cq->mutex, NULL);
++      pthread_cond_init(&cq_ex->real_cq->cond, NULL);
+-int __ibv_query_port_1_0(struct ibv_context_1_0 *context, uint8_t port_num,
+-                       struct ibv_port_attr *port_attr)
+-{
+-      return ibv_query_port(context->real_context, port_num, port_attr);
++      cq_ex->cq.cqe = cq_ex->real_cq->cqe;
++      return &cq_ex->cq;
+ }
+-symver(__ibv_query_port_1_0, ibv_query_port, IBVERBS_1.0);
+-int __ibv_query_gid_1_0(struct ibv_context_1_0 *context, uint8_t port_num,
+-                      int index, union ibv_gid *gid)
++static int _ibv_poll_cq_ex(struct ibv_cq *cq, int num_entries, struct ibv_wc *wc)
+ {
+-      return ibv_query_gid(context->real_context, port_num, index, gid);
++      struct _ibv_cq_ex *cq_ex = container_of(cq, struct _ibv_cq_ex, cq);
++      return ibv_poll_cq(cq_ex->real_cq, num_entries, wc);
+ }
+-symver(__ibv_query_gid_1_0, ibv_query_gid, IBVERBS_1.0);
+-int __ibv_query_pkey_1_0(struct ibv_context_1_0 *context, uint8_t port_num,
+-                       int index, uint16_t *pkey)
++static int _ibv_req_notify_cq_ex(struct ibv_cq *cq, int solicited_only)
+ {
+-      return ibv_query_pkey(context->real_context, port_num, index, pkey);
++      struct _ibv_cq_ex *cq_ex = container_of(cq, struct _ibv_cq_ex, cq);
++      return ibv_req_notify_cq(cq_ex->real_cq, solicited_only);
+ }
+-symver(__ibv_query_pkey_1_0, ibv_query_pkey, IBVERBS_1.0);
+-struct ibv_pd_1_0 *__ibv_alloc_pd_1_0(struct ibv_context_1_0 *context)
++static void _ibv_cq_event_ex(struct ibv_cq *cq)
+ {
+-      struct ibv_pd *real_pd;
+-      struct ibv_pd_1_0 *pd;
+-
+-      pd = malloc(sizeof *pd);
+-      if (!pd)
+-              return NULL;
++      struct _ibv_cq_ex *cq_ex = container_of(cq, struct _ibv_cq_ex, cq);
++      struct _ibv_context_ex *context_ex;
+-      real_pd = ibv_alloc_pd(context->real_context);
+-      if (!real_pd) {
+-              free(pd);
+-              return NULL;
+-      }
+-
+-      pd->context = context;
+-      pd->real_pd = real_pd;
+-
+-      return pd;
++      context_ex = container_of(cq->context, struct _ibv_context_ex, context);
++      return context_ex->real_context->ops.cq_event(cq_ex->real_cq);
+ }
+-symver(__ibv_alloc_pd_1_0, ibv_alloc_pd, IBVERBS_1.0);
+-int __ibv_dealloc_pd_1_0(struct ibv_pd_1_0 *pd)
++static int _ibv_resize_cq_ex(struct ibv_cq *cq, int cqe)
+ {
++      struct _ibv_cq_ex *cq_ex = container_of(cq, struct _ibv_cq_ex, cq);
+       int ret;
+-      ret = ibv_dealloc_pd(pd->real_pd);
++      ret = ibv_resize_cq(cq_ex->real_cq, cqe);
+       if (ret)
+               return ret;
+-      free(pd);
++      cq_ex->cq.cqe = cq_ex->real_cq->cqe;
+       return 0;
+ }
+-symver(__ibv_dealloc_pd_1_0, ibv_dealloc_pd, IBVERBS_1.0);
+-
+-struct ibv_mr_1_0 *__ibv_reg_mr_1_0(struct ibv_pd_1_0 *pd, void *addr,
+-                                  size_t length, int access)
+-{
+-      struct ibv_mr *real_mr;
+-      struct ibv_mr_1_0 *mr;
+-
+-      mr = malloc(sizeof *mr);
+-      if (!mr)
+-              return NULL;
+-
+-      real_mr = ibv_reg_mr(pd->real_pd, addr, length, access);
+-      if (!real_mr) {
+-              free(mr);
+-              return NULL;
+-      }
+-
+-      mr->context = pd->context;
+-      mr->pd      = pd;
+-      mr->lkey    = real_mr->lkey;
+-      mr->rkey    = real_mr->rkey;
+-      mr->real_mr = real_mr;
+-
+-      return mr;
+-}
+-symver(__ibv_reg_mr_1_0, ibv_reg_mr, IBVERBS_1.0);
+-int __ibv_dereg_mr_1_0(struct ibv_mr_1_0 *mr)
++/*
++ * ibv_destroy_cq holds the mutex to any corresponding channel.  Call the
++ * provider directly.
++ */
++static int _ibv_destroy_cq_ex(struct ibv_cq *cq)
+ {
++      struct _ibv_cq_ex *cq_ex = container_of(cq, struct _ibv_cq_ex, cq);
+       int ret;
+-      ret = ibv_dereg_mr(mr->real_mr);
++      ret = cq_ex->real_cq->context->ops.destroy_cq(cq_ex->real_cq);
+       if (ret)
+               return ret;
+-      free(mr);
++      if (cq_ex->cq.channel)
++              --cq_ex->cq.channel->refcnt;
++
++      free(cq_ex);
+       return 0;
+ }
+-symver(__ibv_dereg_mr_1_0, ibv_dereg_mr, IBVERBS_1.0);
+-struct ibv_cq_1_0 *__ibv_create_cq_1_0(struct ibv_context_1_0 *context, int cqe,
+-                                     void *cq_context,
+-                                     struct ibv_comp_channel *channel,
+-                                     int comp_vector)
++static struct ibv_srq *_ibv_create_srq_ex(struct ibv_pd *pd,
++                                        struct ibv_srq_init_attr *srq_init_attr)
+ {
+-      struct ibv_cq *real_cq;
+-      struct ibv_cq_1_0 *cq;
++      struct _ibv_pd_ex *pd_ex = container_of(pd, struct _ibv_pd_ex, pd);
++      struct _ibv_srq_ex *srq_ex;
+-      cq = malloc(sizeof *cq);
+-      if (!cq)
++      srq_ex = calloc(1, sizeof *srq_ex);
++      if (!srq_ex)
+               return NULL;
+-      real_cq = ibv_create_cq(context->real_context, cqe, cq_context,
+-                              channel, comp_vector);
+-      if (!real_cq) {
+-              free(cq);
++      srq_ex->real_srq = ibv_create_srq(pd_ex->real_pd, srq_init_attr);
++      if (!srq_ex->real_srq) {
++              free(srq_ex);
+               return NULL;
+       }
+-      cq->context    = context;
+-      cq->cq_context = cq_context;
+-      cq->cqe        = cqe;
+-      cq->real_cq    = real_cq;
+-
+-      real_cq->cq_context = cq;
+-
+-      return cq;
++      return &srq_ex->srq;
+ }
+-symver(__ibv_create_cq_1_0, ibv_create_cq, IBVERBS_1.0);
+-int __ibv_resize_cq_1_0(struct ibv_cq_1_0 *cq, int cqe)
++static int _ibv_modify_srq_ex(struct ibv_srq *srq,
++                            struct ibv_srq_attr *srq_attr,
++                            int srq_attr_mask)
+ {
+-      return ibv_resize_cq(cq->real_cq, cqe);
++      struct _ibv_srq_ex *srq_ex;
++      srq_ex = container_of(srq, struct _ibv_srq_ex, srq);
++
+ }
+-symver(__ibv_resize_cq_1_0, ibv_resize_cq, IBVERBS_1.0);
+-int __ibv_destroy_cq_1_0(struct ibv_cq_1_0 *cq)
++static int _ibv_query_srq_ex(struct ibv_srq *srq,
++                           struct ibv_srq_attr *srq_attr)
+ {
+-      int ret;
+-
+-      ret = ibv_destroy_cq(cq->real_cq);
+-      if (ret)
+-              return ret;
++      struct _ibv_srq_ex *srq_ex;
++      srq_ex = container_of(srq, struct _ibv_srq_ex, srq);
+-      free(cq);
+-      return 0;
+ }
+-symver(__ibv_destroy_cq_1_0, ibv_destroy_cq, IBVERBS_1.0);
+-int __ibv_get_cq_event_1_0(struct ibv_comp_channel *channel,
+-                         struct ibv_cq_1_0 **cq, void **cq_context)
++static int _ibv_destroy_srq_ex(struct ibv_srq *srq)
+ {
+-      struct ibv_cq *real_cq;
+-      void *cq_ptr;
+-      int ret;
+-
+-      ret = ibv_get_cq_event(channel, &real_cq, &cq_ptr);
+-      if (ret)
+-              return ret;
+-
+-      *cq         = cq_ptr;
+-      *cq_context = (*cq)->cq_context;
++      struct _ibv_srq_ex *srq_ex;
++      srq_ex = container_of(srq, struct _ibv_srq_ex, srq);
+-      return 0;
+ }
+-symver(__ibv_get_cq_event_1_0, ibv_get_cq_event, IBVERBS_1.0);
+-void __ibv_ack_cq_events_1_0(struct ibv_cq_1_0 *cq, unsigned int nevents)
++static int  _ibv_post_srq_recv_ex(struct ibv_srq *srq,
++                                struct ibv_recv_wr *recv_wr,
++                                struct ibv_recv_wr **bad_recv_wr)
+ {
+-      ibv_ack_cq_events(cq->real_cq, nevents);
++      struct _ibv_srq_ex *srq_ex;
++      srq_ex = container_of(srq, struct _ibv_srq_ex, srq);
++
+ }
+-symver(__ibv_ack_cq_events_1_0, ibv_ack_cq_events, IBVERBS_1.0);
+-struct ibv_srq_1_0 *__ibv_create_srq_1_0(struct ibv_pd_1_0 *pd,
+-                                       struct ibv_srq_init_attr *srq_init_attr)
++static struct ibv_qp *_ibv_create_qp_ex(struct ibv_pd *pd, struct ibv_qp_init_attr *attr)
+ {
+-      struct ibv_srq *real_srq;
+-      struct ibv_srq_1_0 *srq;
+-
+-      srq = malloc(sizeof *srq);
+-      if (!srq)
+-              return NULL;
+-
+-      real_srq = ibv_create_srq(pd->real_pd, srq_init_attr);
+-      if (!real_srq) {
+-              free(srq);
+-              return NULL;
+-      }
+-
+-      srq->context     = pd->context;
+-      srq->srq_context = srq_init_attr->srq_context;
+-      srq->pd          = pd;
+-      srq->real_srq    = real_srq;
+-
+-      real_srq->srq_context = srq;
++      struct _ibv_pd_ex *pd_ex;
++      pd_ex = container_of(pd, struct _ibv_pd_ex, pd);
+-      return srq;
+ }
+-symver(__ibv_create_srq_1_0, ibv_create_srq, IBVERBS_1.0);
+-int __ibv_modify_srq_1_0(struct ibv_srq_1_0 *srq,
+-                       struct ibv_srq_attr *srq_attr,
+-                       int srq_attr_mask)
++static int _ibv_query_qp_ex(struct ibv_qp *qp, struct ibv_qp_attr *attr,
++                          int attr_mask,
++                           struct ibv_qp_init_attr *init_attr)
+ {
+-      return ibv_modify_srq(srq->real_srq, srq_attr, srq_attr_mask);
+-}
+-symver(__ibv_modify_srq_1_0, ibv_modify_srq, IBVERBS_1.0);
++      struct _ibv_qp_ex *qp_ex;
++      qp_ex = container_of(qp, struct _ibv_qp_ex, qp);
+-int __ibv_query_srq_1_0(struct ibv_srq_1_0 *srq, struct ibv_srq_attr *srq_attr)
+-{
+-      return ibv_query_srq(srq->real_srq, srq_attr);
+ }
+-symver(__ibv_query_srq_1_0, ibv_query_srq, IBVERBS_1.0);
+-int __ibv_destroy_srq_1_0(struct ibv_srq_1_0 *srq)
++static int _ibv_modify_qp_ex(struct ibv_qp *qp, struct ibv_qp_attr *attr,
++                           int attr_mask)
+ {
+-      int ret;
++      struct _ibv_qp_ex *qp_ex;
++      qp_ex = container_of(qp, struct _ibv_qp_ex, qp);
+-      ret = ibv_destroy_srq(srq->real_srq);
+-      if (ret)
+-              return ret;
+-
+-      free(srq);
+-      return 0;
+ }
+-symver(__ibv_destroy_srq_1_0, ibv_destroy_srq, IBVERBS_1.0);
+-struct ibv_qp_1_0 *__ibv_create_qp_1_0(struct ibv_pd_1_0 *pd,
+-                                     struct ibv_qp_init_attr_1_0 *qp_init_attr)
++static int _ibv_destroy_qp_ex(struct ibv_qp *qp)
+ {
+-      struct ibv_qp *real_qp;
+-      struct ibv_qp_1_0 *qp;
+-      struct ibv_qp_init_attr real_init_attr;
+-
+-      qp = malloc(sizeof *qp);
+-      if (!qp)
+-              return NULL;
+-
+-      real_init_attr.qp_context = qp_init_attr->qp_context;
+-      real_init_attr.send_cq    = qp_init_attr->send_cq->real_cq;
+-      real_init_attr.recv_cq    = qp_init_attr->recv_cq->real_cq;
+-      real_init_attr.srq        = qp_init_attr->srq ?
+-              qp_init_attr->srq->real_srq : NULL;
+-      real_init_attr.cap        = qp_init_attr->cap;
+-      real_init_attr.qp_type    = qp_init_attr->qp_type;
+-      real_init_attr.sq_sig_all = qp_init_attr->sq_sig_all;
+-
+-      real_qp = ibv_create_qp(pd->real_pd, &real_init_attr);
+-      if (!real_qp) {
+-              free(qp);
+-              return NULL;
+-      }
+-
+-      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->qp_type    = qp_init_attr->qp_type;
+-      qp->qp_num     = real_qp->qp_num;
+-      qp->real_qp    = real_qp;
+-
+-      qp_init_attr->cap = real_init_attr.cap;
++      struct _ibv_qp_ex *qp_ex;
++      qp_ex = container_of(qp, struct _ibv_qp_ex, qp);
+-      real_qp->qp_context = qp;
+-
+-      return qp;
+ }
+-symver(__ibv_create_qp_1_0, ibv_create_qp, IBVERBS_1.0);
+-int __ibv_query_qp_1_0(struct ibv_qp_1_0 *qp, struct ibv_qp_attr *attr,
+-                     int attr_mask,
+-                     struct ibv_qp_init_attr_1_0 *init_attr)
++static int _ibv_post_send_ex(struct ibv_qp *qp, struct ibv_send_wr *wr,
++                           struct ibv_send_wr **bad_wr)
+ {
+-      struct ibv_qp_init_attr real_init_attr;
+-      int ret;
++      struct _ibv_qp_ex *qp_ex;
++      qp_ex = container_of(qp, struct _ibv_qp_ex, qp);
+-      ret = ibv_query_qp(qp->real_qp, attr, attr_mask, &real_init_attr);
+-      if (ret)
+-              return ret;
++}
+-      init_attr->qp_context = qp->qp_context;
+-      init_attr->send_cq    = real_init_attr.send_cq->cq_context;
+-      init_attr->recv_cq    = real_init_attr.recv_cq->cq_context;
+-      init_attr->srq        = real_init_attr.srq->srq_context;
+-      init_attr->qp_type    = real_init_attr.qp_type;
+-      init_attr->cap        = real_init_attr.cap;
+-      init_attr->sq_sig_all = real_init_attr.sq_sig_all;
++static int _ibv_post_recv_ex(struct ibv_qp *qp, struct ibv_recv_wr *wr,
++                           struct ibv_recv_wr **bad_wr)
++{
++      struct _ibv_qp_ex *qp_ex;
++      qp_ex = container_of(qp, struct _ibv_qp_ex, qp);
+-      return 0;
+ }
+-symver(__ibv_query_qp_1_0, ibv_query_qp, IBVERBS_1.0);
+-int __ibv_modify_qp_1_0(struct ibv_qp_1_0 *qp, struct ibv_qp_attr *attr,
+-                      int attr_mask)
++static struct ibv_ah *_ibv_create_ah_ex(struct ibv_pd *pd, struct ibv_ah_attr *attr)
+ {
+-      return ibv_modify_qp(qp->real_qp, attr, attr_mask);
++      struct _ibv_pd_ex *pd_ex;
++      struct _ibv_ah_ex *ah_ex;
++      pd_ex = container_of(pd, struct _ibv_pd_ex, pd);
++
+ }
+-symver(__ibv_modify_qp_1_0, ibv_modify_qp, IBVERBS_1.0);
+-int __ibv_destroy_qp_1_0(struct ibv_qp_1_0 *qp)
++static int _ibv_destroy_ah_ex(struct ibv_ah *ah)
+ {
+-      int ret;
+-
+-      ret = ibv_destroy_qp(qp->real_qp);
+-      if (ret)
+-              return ret;
++      struct _ibv_ah_ex *ah_ex;
++      ah_ex = container_of(ah, struct _ibv_ah_ex, ah);
+-      free(qp);
+-      return 0;
+ }
+-symver(__ibv_destroy_qp_1_0, ibv_destroy_qp, IBVERBS_1.0);
+-struct ibv_ah_1_0 *__ibv_create_ah_1_0(struct ibv_pd_1_0 *pd,
+-                                     struct ibv_ah_attr *attr)
++static int _ibv_attach_mcast_ex(struct ibv_qp *qp, const union ibv_gid *gid,
++                              uint16_t lid)
+ {
+-      struct ibv_ah *real_ah;
+-      struct ibv_ah_1_0 *ah;
++      struct _ibv_qp_ex *qp_ex;
++      qp_ex = container_of(qp, struct _ibv_qp_ex, qp);
+-      ah = malloc(sizeof *ah);
+-      if (!ah)
+-              return NULL;
+-
+-      real_ah = ibv_create_ah(pd->real_pd, attr);
+-      if (!real_ah) {
+-              free(ah);
+-              return NULL;
+-      }
++}
+-      ah->context = pd->context;
+-      ah->pd      = pd;
+-      ah->real_ah = real_ah;
++static int _ibv_detach_mcast_ex(struct ibv_qp *qp, const union ibv_gid *gid,
++                              uint16_t lid)
++{
++      struct _ibv_qp_ex *qp_ex;
++      qp_ex = container_of(qp, struct _ibv_qp_ex, qp);
+-      return ah;
+ }
+-symver(__ibv_create_ah_1_0, ibv_create_ah, IBVERBS_1.0);
+-int __ibv_destroy_ah_1_0(struct ibv_ah_1_0 *ah)
++static void _ibv_async_event_ex(struct ibv_async_event *event)
+ {
+-      int ret;
+-
+-      ret = ibv_destroy_ah(ah->real_ah);
+-      if (ret)
+-              return ret;
+-      free(ah);
+-      return 0;
+ }
+-symver(__ibv_destroy_ah_1_0, ibv_destroy_ah, IBVERBS_1.0);
+-int __ibv_attach_mcast_1_0(struct ibv_qp_1_0 *qp, union ibv_gid *gid, uint16_t lid)
++struct ibv_context *_ibv_open_device_ex(struct ibv_device *device)
+ {
+-      return ibv_attach_mcast(qp->real_qp, gid, lid);
++
+ }
+-symver(__ibv_attach_mcast_1_0, ibv_attach_mcast, IBVERBS_1.0);
+-int __ibv_detach_mcast_1_0(struct ibv_qp_1_0 *qp, union ibv_gid *gid, uint16_t lid)
++int _ibv_close_device_ex(struct ibv_context *context)
+ {
+-      return ibv_detach_mcast(qp->real_qp, gid, lid);
++
+ }
+-symver(__ibv_detach_mcast_1_0, ibv_detach_mcast, IBVERBS_1.0);