]> git.openfabrics.org - ~shefty/libibverbs.git/commitdiff
Refresh of compat-ex
authorSean Hefty <sean.hefty@intel.com>
Wed, 26 Sep 2012 18:42:43 +0000 (11:42 -0700)
committerSean Hefty <sean.hefty@intel.com>
Wed, 26 Sep 2012 18:42:43 +0000 (11:42 -0700)
Makefile.am
include/infiniband/verbs.h
src/compat-ex.c [new file with mode: 0644]
src/device.c
src/ibverbs.h
src/verbs.c

index cd00a65777c2469b6096e22cc294014d4d9fde96..1cfb008e231f035fb7869d82f830636a1a5f7246 100644 (file)
@@ -11,7 +11,7 @@ libibverbs_version_script = @LIBIBVERBS_VERSION_SCRIPT@
 
 src_libibverbs_la_SOURCES = src/cmd.c src/compat-1_0.c src/device.c src/init.c \
                            src/marshall.c src/memory.c src/sysfs.c src/verbs.c \
-                           src/enum_strs.c
+                           src/enum_strs.c src/compat-ex.c
 src_libibverbs_la_LDFLAGS = -version-info 1 -export-dynamic \
     $(libibverbs_version_script)
 src_libibverbs_la_DEPENDENCIES = $(srcdir)/src/libibverbs.map
index e67bf21ed00016b4d86907302363be2936889f3a..81e3f6d1e78de6caede1dc8fb107f976fe33f423 100644 (file)
@@ -308,9 +308,14 @@ enum ibv_access_flags {
        IBV_ACCESS_MW_BIND              = (1<<4)
 };
 
+enum ibv_pd_mask {
+       IBV_PD_RESERVED                 = 1 << 0
+};
+
 struct ibv_pd {
        struct ibv_context     *context;
        uint32_t                handle;
+       uint32_t                comp_mask;
 };
 
 struct ibv_xrcd {
@@ -324,6 +329,10 @@ enum ibv_rereg_mr_flags {
        IBV_REREG_MR_KEEP_VALID         = (1 << 3)
 };
 
+enum ibv_mr_mask {
+       IBV_MR_RESERVED                 = 1 << 0
+};
+
 struct ibv_mr {
        struct ibv_context     *context;
        struct ibv_pd          *pd;
@@ -332,6 +341,7 @@ struct ibv_mr {
        uint32_t                handle;
        uint32_t                lkey;
        uint32_t                rkey;
+       uint32_t                comp_mask;
 };
 
 enum ibv_mw_type {
@@ -339,10 +349,15 @@ enum ibv_mw_type {
        IBV_MW_TYPE_2                   = 2
 };
 
+enum ibv_mw_mask {
+       IBV_MW_RESERVED                 = 1 << 0
+};
+
 struct ibv_mw {
        struct ibv_context     *context;
        struct ibv_pd          *pd;
        uint32_t                rkey;
+       uint32_t                comp_mask;
 };
 
 struct ibv_global_route {
@@ -595,6 +610,10 @@ struct ibv_mw_bind {
        int                     mw_access_flags;
 };
 
+enum ibv_srq_mask {
+       IBV_SRQ_RESERVED                = 1 << 0
+};
+
 struct ibv_srq {
        struct ibv_context     *context;
        void                   *srq_context;
@@ -604,6 +623,12 @@ struct ibv_srq {
        pthread_mutex_t         mutex;
        pthread_cond_t          cond;
        uint32_t                events_completed;
+
+       uint32_t                comp_mask;
+};
+
+enum ibv_qp_mask {
+       IBV_QP_RESERVED                 = 1 << 0
 };
 
 struct ibv_qp {
@@ -621,12 +646,24 @@ struct ibv_qp {
        pthread_mutex_t         mutex;
        pthread_cond_t          cond;
        uint32_t                events_completed;
+
+       uint32_t                comp_mask;
+};
+
+enum ibv_comp_channel_mask {
+       IBV_COMP_CHANNEL_RESERVED       = 1 << 0
 };
 
 struct ibv_comp_channel {
        struct ibv_context     *context;
        int                     fd;
        int                     refcnt;
+
+       uint32_t                comp_mask;
+};
+
+enum ibv_cq_mask {
+       IBV_CQ_RESERVED                 = 1 << 0
 };
 
 struct ibv_cq {
@@ -640,16 +677,25 @@ struct ibv_cq {
        pthread_cond_t          cond;
        uint32_t                comp_events_completed;
        uint32_t                async_events_completed;
+
+       uint32_t                comp_mask;
+};
+
+enum ibv_ah_mask {
+       IBV_AH_RESERVED                 = 1 << 0
 };
 
 struct ibv_ah {
        struct ibv_context     *context;
        struct ibv_pd          *pd;
        uint32_t                handle;
+
+       uint32_t                comp_mask;
 };
 
 struct ibv_device;
 struct ibv_context;
+struct verbs_context;
 
 struct ibv_device_ops {
        struct ibv_context *    (*alloc_context)(struct ibv_device *device, int cmd_fd);
@@ -682,7 +728,7 @@ struct verbs_device {
        int     (*init_context)(struct verbs_device *device,
                                struct ibv_context *ctx, int cmd_fd);
        void    (*uninit_context)(struct verbs_device *device,
-                               struct ibv_context *ctx);
+                                 struct ibv_context *ctx);
        /* future fields added here */
 };
 
@@ -771,12 +817,8 @@ struct verbs_context {
        struct ibv_context context;/* Must be last field in the struct */
 };
 
-static inline struct verbs_context *verbs_get_ctx(
-                                       const struct ibv_context *ctx)
+static inline struct verbs_context *verbs_get_ctx(const struct ibv_context *ctx)
 {
-       if (ctx->abi_compat != ((uint8_t *)NULL)-1)
-               return NULL;
-
        return container_of(ctx, struct verbs_context, context);
 }
 
diff --git a/src/compat-ex.c b/src/compat-ex.c
new file mode 100644 (file)
index 0000000..d335d70
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+ * Copyright (c) 2007 Cisco Systems, Inc.  All rights reserved.
+ * Copyright (c) 2012 Intel Corp., Inc.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <alloca.h>
+
+#include "ibverbs.h"
+
+struct _ibv_pd_ex {
+       struct ibv_pd  pd;
+       struct ibv_pd *real_pd;
+};
+
+struct _ibv_mr_ex {
+       struct ibv_mr  mr;
+       struct ibv_mr *real_mr;
+};
+
+struct _ibv_srq_ex {
+       struct ibv_srq  srq;
+       struct ibv_srq *real_srq;
+};
+
+struct _ibv_qp_ex {
+       struct ibv_qp  qp;
+       struct ibv_qp *real_qp;
+};
+
+struct _ibv_cq_ex {
+       struct ibv_cq  cq;
+       struct ibv_cq *real_cq;
+};
+
+struct _ibv_ah_ex {
+       struct ibv_ah  ah;
+       struct ibv_ah *real_ah;
+};
+
+struct ibv_context *_ibv_real_context(struct ibv_context *context)
+{
+       struct verbs_context_private *priv_ctx = ibv_private_context(context);
+       return priv_ctx->real_context;
+}
+
+struct ibv_srq *_ibv_real_srq(struct ibv_srq *srq)
+{
+       struct _ibv_srq_ex *srq_ex;
+
+       if (ibv_support_ex(srq->context))
+               return srq;
+
+       srq_ex = container_of(srq, struct _ibv_srq_ex, srq);
+       return srq_ex->real_srq;
+}
+
+struct ibv_qp *_ibv_real_qp(struct ibv_qp *qp)
+{
+       struct _ibv_qp_ex *qp_ex;
+
+       if (ibv_support_ex(qp->context))
+               return qp;
+
+       qp_ex = container_of(qp, struct _ibv_qp_ex, qp);
+       return qp_ex->real_qp;
+}
+
+struct ibv_cq *_ibv_real_cq(struct ibv_cq *cq)
+{
+       struct _ibv_cq_ex *cq_ex;
+
+       if (ibv_support_ex(cq->context))
+               return cq;
+
+       cq_ex = container_of(cq, struct _ibv_cq_ex, cq);
+       return cq_ex->real_cq;
+}
+
+struct ibv_srq *_ibv_verbs_srq(struct ibv_srq *srq)
+{
+       return ibv_support_ex(srq->context) ? srq : (struct ibv_srq *) srq->srq_context;
+}
+
+struct ibv_qp  *_ibv_verbs_qp(struct ibv_qp *qp)
+{
+       return ibv_support_ex(qp->context) ? qp : (struct ibv_qp *) qp->qp_context;
+}
+
+struct ibv_cq  *_ibv_verbs_cq(struct ibv_cq *cq)
+{
+       return ibv_support_ex(cq->context) ? cq : (struct ibv_cq *) cq->cq_context;
+}
+
+static int _ibv_query_device_ex(struct ibv_context *context,
+                               struct ibv_device_attr *device_attr)
+{
+       return ibv_query_device(_ibv_real_context(context), device_attr);
+}
+
+static int _ibv_query_port_ex(struct ibv_context *context, uint8_t port_num,
+                             struct ibv_port_attr *port_attr)
+{
+       return ibv_query_port(_ibv_real_context(context), port_num, port_attr);
+}
+
+static struct ibv_pd *_ibv_alloc_pd_ex(struct ibv_context *context)
+{
+       struct _ibv_pd_ex *pd_ex;
+
+       pd_ex = calloc(1, sizeof *pd_ex);
+       if (!pd_ex)
+               return NULL;
+
+       pd_ex->real_pd = ibv_alloc_pd(_ibv_real_context(context));
+       if (!pd_ex->real_pd) {
+               free(pd_ex);
+               return NULL;
+       }
+
+       return &pd_ex->pd;
+}
+
+static int _ibv_dealloc_pd_ex(struct ibv_pd *pd)
+{
+       struct _ibv_pd_ex *pd_ex = container_of(pd, struct _ibv_pd_ex, pd);
+       int ret;
+
+       ret = ibv_dealloc_pd(pd_ex->real_pd);
+       if (ret)
+               return ret;
+
+       free(pd_ex);
+       return 0;
+}
+
+static struct ibv_mr *_ibv_reg_mr_ex(struct ibv_pd *pd, void *addr, size_t length,
+                                    int access)
+{
+       struct _ibv_pd_ex *pd_ex = container_of(pd, struct _ibv_pd_ex, pd);
+       struct _ibv_mr_ex *mr_ex;
+
+       mr_ex = calloc(1, sizeof *mr_ex);
+       if (!mr_ex)
+               return NULL;
+
+       mr_ex->real_mr = ibv_reg_mr(pd_ex->real_pd, addr, length, access);
+       if (!mr_ex->real_mr) {
+               free(mr_ex);
+               return NULL;
+       }
+
+       mr_ex->mr.lkey = mr_ex->real_mr->lkey;
+       mr_ex->mr.rkey = mr_ex->real_mr->rkey;
+       return &mr_ex->mr;
+}
+
+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_dereg_mr(mr_ex->real_mr);
+       if (ret)
+               return ret;
+
+       free(mr_ex);
+       return 0;
+}
+
+/*
+ * 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)
+{
+       struct ibv_context *real_context= _ibv_real_context(context);
+       struct _ibv_cq_ex *cq_ex;
+
+       cq_ex = calloc(1, sizeof *cq_ex);
+       if (!cq_ex)
+               return NULL;
+
+       cq_ex->real_cq = real_context->ops.create_cq(real_context, cqe,
+                                                    channel, comp_vector);
+       if (!cq_ex->real_cq) {
+               free(cq_ex);
+               return NULL;
+       }
+
+       cq_ex->real_cq->context = 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);
+
+       cq_ex->cq.cqe = cq_ex->real_cq->cqe;
+       return &cq_ex->cq;
+}
+
+static int _ibv_poll_cq_ex(struct ibv_cq *cq, int num_entries, struct ibv_wc *wc)
+{
+       return ibv_poll_cq(_ibv_real_cq(cq), num_entries, wc);
+}
+
+static int _ibv_req_notify_cq_ex(struct ibv_cq *cq, int solicited_only)
+{
+       return ibv_req_notify_cq(_ibv_real_cq(cq), solicited_only);
+}
+
+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_resize_cq(cq_ex->real_cq, cqe);
+       if (ret)
+               return ret;
+
+       cq_ex->cq.cqe = cq_ex->real_cq->cqe;
+       return 0;
+}
+
+/*
+ * 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 = cq_ex->real_cq->context->ops.destroy_cq(cq_ex->real_cq);
+       if (ret)
+               return ret;
+
+       if (cq_ex->cq.channel)
+               --cq_ex->cq.channel->refcnt;
+
+       free(cq_ex);
+       return 0;
+}
+
+static struct ibv_srq *_ibv_create_srq_ex(struct ibv_pd *pd,
+                                         struct ibv_srq_init_attr *srq_init_attr)
+{
+       struct _ibv_pd_ex *pd_ex = container_of(pd, struct _ibv_pd_ex, pd);
+       struct _ibv_srq_ex *srq_ex;
+
+       srq_ex = calloc(1, sizeof *srq_ex);
+       if (!srq_ex)
+               return NULL;
+
+       srq_ex->real_srq = ibv_create_srq(pd_ex->real_pd, srq_init_attr);
+       if (!srq_ex->real_srq) {
+               free(srq_ex);
+               return NULL;
+       }
+
+       return &srq_ex->srq;
+}
+
+static int _ibv_modify_srq_ex(struct ibv_srq *srq,
+                             struct ibv_srq_attr *srq_attr,
+                             int srq_attr_mask)
+{
+       return ibv_modify_srq(_ibv_real_srq(srq), srq_attr, srq_attr_mask);
+}
+
+static int _ibv_query_srq_ex(struct ibv_srq *srq,
+                            struct ibv_srq_attr *srq_attr)
+{
+       return ibv_query_srq(_ibv_real_srq(srq), srq_attr);
+}
+
+static int _ibv_destroy_srq_ex(struct ibv_srq *srq)
+{
+       struct _ibv_srq_ex *srq_ex = container_of(srq, struct _ibv_srq_ex, srq);
+       int ret;
+
+       ret = ibv_destroy_srq(srq_ex->real_srq);
+       if (ret)
+               return ret;
+
+       free(srq_ex);
+       return 0;
+}
+
+static int _ibv_post_srq_recv_ex(struct ibv_srq *srq,
+                                struct ibv_recv_wr *recv_wr,
+                                struct ibv_recv_wr **bad_recv_wr)
+{
+       struct _ibv_srq_ex *srq_ex = container_of(srq, struct _ibv_srq_ex, srq);
+       return ibv_post_srq_recv(srq_ex->real_srq, recv_wr, bad_recv_wr);
+}
+
+static struct ibv_qp *_ibv_create_qp_ex(struct ibv_pd *pd, struct ibv_qp_init_attr *attr)
+{
+       struct _ibv_pd_ex *pd_ex = container_of(pd, struct _ibv_pd_ex, pd);
+       struct _ibv_qp_ex *qp_ex;
+       struct ibv_qp_init_attr real_attr;
+
+       qp_ex = calloc(1, sizeof *qp_ex);
+       if (!qp_ex)
+               return NULL;
+
+       real_attr.qp_context = qp_ex;
+       real_attr.send_cq    = attr->send_cq ? _ibv_real_cq(attr->send_cq) : NULL;
+       real_attr.recv_cq    = attr->recv_cq ? _ibv_real_cq(attr->recv_cq) : NULL;
+       real_attr.srq        = attr->srq     ? _ibv_real_srq(attr->srq) : NULL;
+       real_attr.cap        = attr->cap;
+       real_attr.qp_type    = attr->qp_type;
+       real_attr.sq_sig_all = attr->sq_sig_all;
+
+       qp_ex->real_qp = ibv_create_qp(pd_ex->real_pd, &real_attr);
+       if (!qp_ex->real_qp) {
+               free(qp_ex);
+               return NULL;
+       }
+
+       qp_ex->qp.qp_num = qp_ex->real_qp->qp_num;
+       return &qp_ex->qp;
+}
+
+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)
+{
+       struct _ibv_qp_ex *qp_ex = container_of(qp, struct _ibv_qp_ex, qp);
+       int ret;
+
+       ret = ibv_query_qp(qp_ex->real_qp, attr, attr_mask, init_attr);
+       if (ret)
+               return ret;
+
+       init_attr->qp_context = qp_ex->qp.qp_context;
+       init_attr->send_cq = qp_ex->qp.send_cq;
+       init_attr->recv_cq = qp_ex->qp.recv_cq;
+       init_attr->srq = qp_ex->qp.srq;
+       return 0;
+}
+
+static int _ibv_modify_qp_ex(struct ibv_qp *qp, struct ibv_qp_attr *attr,
+                            int attr_mask)
+{
+       return ibv_modify_qp(_ibv_real_qp(qp), attr, attr_mask);
+}
+
+static int _ibv_destroy_qp_ex(struct ibv_qp *qp)
+{
+       struct _ibv_qp_ex *qp_ex = container_of(qp, struct _ibv_qp_ex, qp);
+       int ret;
+
+       ret = ibv_destroy_qp(qp_ex->real_qp);
+       if (ret)
+               return ret;
+
+       free(qp_ex);
+       return 0;
+}
+
+static int _ibv_post_send_ex(struct ibv_qp *qp, struct ibv_send_wr *wr,
+                            struct ibv_send_wr **bad_wr)
+{
+       struct _ibv_qp_ex *qp_ex = container_of(qp, struct _ibv_qp_ex, qp);
+       struct _ibv_ah_ex *ah_ex;
+       struct ibv_send_wr real_wr, *cur_wr;
+       int ret;
+
+       if (qp->qp_type != IBV_QPT_UD)
+               return ibv_post_send(qp_ex->real_qp, wr, bad_wr);
+
+       for (cur_wr = wr, ret = 0; cur_wr && !ret; cur_wr = cur_wr->next) {
+               real_wr = *cur_wr;
+               real_wr.next = NULL;
+               ah_ex = container_of(cur_wr->wr.ud.ah, struct _ibv_ah_ex, ah);
+               real_wr.wr.ud.ah = ah_ex->real_ah;
+               ret = ibv_post_send(qp_ex->real_qp, &real_wr, bad_wr);
+       }
+       *bad_wr = cur_wr;
+       return ret;
+}
+
+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 = container_of(qp, struct _ibv_qp_ex, qp);
+       return ibv_post_recv(qp_ex->real_qp, wr, bad_wr);
+}
+
+static struct ibv_ah *_ibv_create_ah_ex(struct ibv_pd *pd, struct ibv_ah_attr *attr)
+{
+       struct _ibv_pd_ex *pd_ex = container_of(pd, struct _ibv_pd_ex, pd);
+       struct _ibv_ah_ex *ah_ex;
+
+       ah_ex = calloc(1, sizeof *ah_ex);
+       if (!ah_ex)
+               return NULL;
+
+       ah_ex->real_ah = ibv_create_ah(pd_ex->real_pd, attr);
+       if (!ah_ex->real_ah) {
+               free(ah_ex);
+               return NULL;
+       }
+
+       return &ah_ex->ah;
+}
+
+static int _ibv_destroy_ah_ex(struct ibv_ah *ah)
+{
+       struct _ibv_ah_ex *ah_ex = container_of(ah, struct _ibv_ah_ex, ah);
+       int ret;
+
+       ret = ibv_destroy_ah(ah_ex->real_ah);
+       if (ret)
+               return ret;
+
+       free(ah_ex);
+       return 0;
+}
+
+static int _ibv_attach_mcast_ex(struct ibv_qp *qp, const union ibv_gid *gid,
+                               uint16_t lid)
+{
+       return ibv_attach_mcast(_ibv_real_qp(qp), gid, lid);
+}
+
+static int _ibv_detach_mcast_ex(struct ibv_qp *qp, const union ibv_gid *gid,
+                               uint16_t lid)
+{
+       return ibv_detach_mcast(_ibv_real_qp(qp), gid, lid);
+}
+
+void _ibv_init_context(struct ibv_device *device,
+                      struct verbs_context_private *priv_ctx, int cmd_fd)
+{
+       struct ibv_context_ops *ops = &priv_ctx->context_ex.context.ops;
+
+       priv_ctx->real_context->device = device;
+       priv_ctx->real_context->cmd_fd = cmd_fd;
+       pthread_mutex_init(&priv_ctx->real_context->mutex, NULL);
+       priv_ctx->real_context->abi_compat = NULL;
+
+       ops->query_device  = _ibv_query_device_ex;
+       ops->query_port    = _ibv_query_port_ex;
+       ops->alloc_pd      = _ibv_alloc_pd_ex;
+       ops->dealloc_pd    = _ibv_dealloc_pd_ex;
+       ops->reg_mr        = _ibv_reg_mr_ex;
+       ops->dereg_mr      = _ibv_dereg_mr_ex;
+       ops->create_cq     = _ibv_create_cq_ex;
+       ops->poll_cq       = _ibv_poll_cq_ex;
+       ops->req_notify_cq = _ibv_req_notify_cq_ex;
+       ops->resize_cq     = _ibv_resize_cq_ex;
+       ops->destroy_cq    = _ibv_destroy_cq_ex;
+       ops->create_srq    = _ibv_create_srq_ex;
+       ops->modify_srq    = _ibv_modify_srq_ex;
+       ops->query_srq     = _ibv_query_srq_ex;
+       ops->destroy_srq   = _ibv_destroy_srq_ex;
+       ops->post_srq_recv = _ibv_post_srq_recv_ex;
+       ops->create_qp     = _ibv_create_qp_ex;
+       ops->query_qp      = _ibv_query_qp_ex;
+       ops->modify_qp     = _ibv_modify_qp_ex;
+       ops->destroy_qp    = _ibv_destroy_qp_ex;
+       ops->post_send     = _ibv_post_send_ex;
+       ops->post_recv     = _ibv_post_recv_ex;
+       ops->create_ah     = _ibv_create_ah_ex;
+       ops->destroy_ah    = _ibv_destroy_ah_ex;
+       ops->attach_mcast  = _ibv_attach_mcast_ex;
+       ops->detach_mcast  = _ibv_detach_mcast_ex;
+}
index 9e43138e2b8397085993ccdf275f10c6504eb27e..e9699b6bd36e9f8c4abc26d4fb0086c53a742e1e 100644 (file)
@@ -127,7 +127,9 @@ struct ibv_context *__ibv_open_device(struct ibv_device *device)
        char *devpath;
        int cmd_fd;
        struct ibv_context *context;
-       struct verbs_context *context_ex;
+       struct verbs_context_private *priv_ctx;
+       struct verbs_device *vdev;
+       size_t prov_ctx_size;
 
        if (asprintf(&devpath, "/dev/infiniband/%s", device->dev_name) < 0)
                return NULL;
@@ -144,49 +146,44 @@ struct ibv_context *__ibv_open_device(struct ibv_device *device)
 
        context = device->ops.alloc_context(device, cmd_fd);
        if (!context)
-               goto err;
-       if (context == (struct ibv_context *)(((uint8_t *)NULL)-1)) {
-               /* New provider that supports verbs extension was detected */
-               struct verbs_device *verbs_device =
-                                       verbs_get_device(device);
-               int ret;
-
-               /* Library now allocates the context */
-               context_ex = calloc(1, sizeof(*context_ex) +
-                       verbs_device->size_of_context);
-
-               if (!context_ex) {
-                       errno = ENOMEM;
-                       goto err;
-               }
-               context = &context_ex->context;
-               /* Init new verbs_context */
-               context_ex->context.abi_compat  = ((uint8_t *)NULL)-1;
-               context_ex->sz = sizeof(*context_ex);
-
-               /* Call provider to initialize its calls first */
-               ret = verbs_device->init_context(verbs_device,
-                                       &context_ex->context, cmd_fd);
-               if (ret)
-                       goto verbs_err;
-               /* initialize *all* library ops to either lib calls or
-                 * directly to provider calls.
-               context_ex-> lib_new_func1= __verbs_new_func1;
-               context_ex-> lib_new_func2= __verbs_new_func2;
-               */
+               goto err1;
+
+       if (context == IBV_EXTENDED_VERBS) {
+               vdev = verbs_get_device(device);
+               prov_ctx_size = vdev->size_of_context;
+       } else {
+               vdev = NULL;
+               prov_ctx_size = 0;
        }
 
-       context->device = device;
-       context->cmd_fd = cmd_fd;
-       pthread_mutex_init(&context->mutex, NULL);
+       priv_ctx = calloc(1, sizeof(*priv_ctx) + prov_ctx_size);
+       if (!priv_ctx) {
+               errno = ENOMEM;
+               goto err1;
+       }
 
-       return context;
+       priv_ctx->context_ex.sz = sizeof(struct verbs_context);
+       if (vdev) {
+               if (vdev->init_context(vdev, &priv_ctx->context_ex.context, cmd_fd))
+                       goto err2;
+
+               priv_ctx->real_context = &priv_ctx->context_ex.context;
+               priv_ctx->context_ex.context.abi_compat = IBV_EXTENDED_VERBS;
+       } else {
+               priv_ctx->real_context = context;
+               priv_ctx->context_ex.context.abi_compat = NULL;
+               _ibv_init_context(device, priv_ctx, cmd_fd);
+       }
 
-verbs_err:
-       free(context_ex);
-err:
-       close(cmd_fd);
+       priv_ctx->context_ex.context.device = device;
+       priv_ctx->context_ex.context.cmd_fd = cmd_fd;
+       pthread_mutex_init(&priv_ctx->context_ex.context.mutex, NULL);
+       return &priv_ctx->context_ex.context;
 
+err2:
+       free(priv_ctx);
+err1:
+       close(cmd_fd);
        return NULL;
 }
 default_symver(__ibv_open_device, ibv_open_device);
@@ -196,17 +193,15 @@ int __ibv_close_device(struct ibv_context *context)
        int async_fd = context->async_fd;
        int cmd_fd   = context->cmd_fd;
        int cq_fd    = -1;
-       struct verbs_context *context_ex;
-
-       context_ex = verbs_get_ctx(context);
-       if (context_ex) {
-               struct verbs_device *verbs_device =
-                                       verbs_get_device(context->device);
-               /* Provider supports verbs extension */
-               verbs_device->uninit_context(verbs_device, context);
-               free(context_ex);
-       } else
-               context->device->ops.free_context(context);
+       struct verbs_context_private *priv_ctx = ibv_private_context(context);
+
+       if (ibv_support_ex(context)) {
+               struct verbs_device *verbs_device = verbs_get_device(context->device);
+               verbs_device->uninit_context(verbs_device, &priv_ctx->context_ex.context);
+       } else {
+               context->device->ops.free_context(priv_ctx->real_context);
+       }
+       free(priv_ctx);
 
        close(async_fd);
        close(cmd_fd);
@@ -221,6 +216,7 @@ int __ibv_get_async_event(struct ibv_context *context,
                          struct ibv_async_event *event)
 {
        struct ibv_kern_async_event ev;
+       int cqe = 0, qpe = 0, srqe = 0;
 
        if (read(context->async_fd, &ev, sizeof ev) != sizeof ev)
                return -1;
@@ -230,6 +226,7 @@ int __ibv_get_async_event(struct ibv_context *context,
        switch (event->event_type) {
        case IBV_EVENT_CQ_ERR:
                event->element.cq = (void *) (uintptr_t) ev.element;
+               cqe = 1;
                break;
 
        case IBV_EVENT_QP_FATAL:
@@ -241,11 +238,13 @@ int __ibv_get_async_event(struct ibv_context *context,
        case IBV_EVENT_PATH_MIG_ERR:
        case IBV_EVENT_QP_LAST_WQE_REACHED:
                event->element.qp = (void *) (uintptr_t) ev.element;
+               qpe = 1;
                break;
 
        case IBV_EVENT_SRQ_ERR:
        case IBV_EVENT_SRQ_LIMIT_REACHED:
                event->element.srq = (void *) (uintptr_t) ev.element;
+               srqe = 1;
                break;
 
        default:
@@ -256,6 +255,13 @@ int __ibv_get_async_event(struct ibv_context *context,
        if (context->ops.async_event)
                context->ops.async_event(event);
 
+       if (cqe)
+               event->element.cq = _ibv_verbs_cq(event->element.cq);
+       else if (qpe)
+               event->element.qp = _ibv_verbs_qp(event->element.qp);
+       else if (srqe)
+               event->element.srq = _ibv_verbs_srq(event->element.srq);
+
        return 0;
 }
 default_symver(__ibv_get_async_event, ibv_get_async_event);
@@ -265,7 +271,7 @@ void __ibv_ack_async_event(struct ibv_async_event *event)
        switch (event->event_type) {
        case IBV_EVENT_CQ_ERR:
        {
-               struct ibv_cq *cq = event->element.cq;
+               struct ibv_cq *cq = _ibv_real_cq(event->element.cq);
 
                pthread_mutex_lock(&cq->mutex);
                ++cq->async_events_completed;
@@ -284,7 +290,7 @@ void __ibv_ack_async_event(struct ibv_async_event *event)
        case IBV_EVENT_PATH_MIG_ERR:
        case IBV_EVENT_QP_LAST_WQE_REACHED:
        {
-               struct ibv_qp *qp = event->element.qp;
+               struct ibv_qp *qp = _ibv_real_qp(event->element.qp);
 
                pthread_mutex_lock(&qp->mutex);
                ++qp->events_completed;
@@ -297,7 +303,7 @@ void __ibv_ack_async_event(struct ibv_async_event *event)
        case IBV_EVENT_SRQ_ERR:
        case IBV_EVENT_SRQ_LIMIT_REACHED:
        {
-               struct ibv_srq *srq = event->element.srq;
+               struct ibv_srq *srq = _ibv_real_srq(event->element.srq);
 
                pthread_mutex_lock(&srq->mutex);
                ++srq->events_completed;
index fa6cd419597b63c0dc627f774597bc5c507273b3..33049d406e5cb6c70414f2754929261bc0368ba8 100644 (file)
@@ -102,4 +102,33 @@ HIDDEN int ibverbs_init(struct ibv_device ***list);
                (cmd)->response  = (uintptr_t) (out);                   \
        } while (0)
 
+struct verbs_context_private {
+       struct ibv_context *real_context;
+       /* place internal data before verbs_context */
+       struct verbs_context context_ex;
+};
+
+#define IBV_EXTENDED_VERBS (((void *) NULL) - 1)
+
+static inline int ibv_support_ex(struct ibv_context *context)
+{
+       return context->abi_compat == IBV_EXTENDED_VERBS;
+}
+
+static inline struct verbs_context_private *
+ibv_private_context(struct ibv_context *context)
+{
+       return container_of(verbs_get_ctx(context),
+                           struct verbs_context_private, context_ex);
+}
+
+void _ibv_init_context(struct ibv_device *device,
+                      struct verbs_context_private *priv_ctx, int cmd_fd);
+struct ibv_srq *_ibv_real_srq(struct ibv_srq *srq);
+struct ibv_qp  *_ibv_real_qp(struct ibv_qp *qp);
+struct ibv_cq  *_ibv_real_cq(struct ibv_cq *cq);
+struct ibv_srq *_ibv_verbs_srq(struct ibv_srq *srq);
+struct ibv_qp  *_ibv_verbs_qp(struct ibv_qp *qp);
+struct ibv_cq  *_ibv_verbs_cq(struct ibv_cq *cq);
+
 #endif /* IB_VERBS_H */
index b5938f2b6a5dc06cc9236bc19dc554fe762d5b63..7973afc1ccbb41708ab8c3e8f8ae7e726ea45efe 100644 (file)
@@ -334,18 +334,21 @@ int __ibv_get_cq_event(struct ibv_comp_channel *channel,
        if (read(channel->fd, &ev, sizeof ev) != sizeof ev)
                return -1;
 
-       *cq         = (struct ibv_cq *) (uintptr_t) ev.cq_handle;
-       *cq_context = (*cq)->cq_context;
-
+       *cq = (struct ibv_cq *) (uintptr_t) ev.cq_handle;
        if ((*cq)->context->ops.cq_event)
                (*cq)->context->ops.cq_event(*cq);
 
+       if (!verbs_get_ctx((*cq)->context))
+               *cq = (struct ibv_cq *) (*cq)->cq_context;
+       *cq_context = (*cq)->cq_context;
+
        return 0;
 }
 default_symver(__ibv_get_cq_event, ibv_get_cq_event);
 
 void __ibv_ack_cq_events(struct ibv_cq *cq, unsigned int nevents)
 {
+       cq = _ibv_real_cq(cq);
        pthread_mutex_lock(&cq->mutex);
        cq->comp_events_completed += nevents;
        pthread_cond_signal(&cq->cond);