--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2004, 2011 Intel Corporation. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2005 PathScale, 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.
+ */
+
+#ifndef OFVERBS_DEFS_H
+#define OFVERBS_DEFS_H
+
+/*
+ * Include this file before verbs.h or at the top of verbs.h. This will
+ * map the names of the ibv_* structures to _real_ibv_*. The
+ * ofv_* structure names are then mapped to ibv_*.
+ */
+#ifdef OFED_VERBS
+
+#define ibv_srq _real_ibv_srq
+#define ibv_qp _real_ibv_qp
+#define ibv_qp_init_attr _real_ibv_qp_init_attr
+#define ibv_send_wr _real_ibv_send_wr
+#define ibv_async_event _real_ibv_async_event
+
+#endif /* OFED_VERBS */
+
+#endif /* OFVERBS_DEFS_H */
--- /dev/null
+/*
+ * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
+ * Copyright (c) 2004, 2011 Intel Corporation. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2005 PathScale, 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.
+ */
+
+#ifndef OFVERBS_H
+#define OFVERBS_H
+
+/*
+ * Include this file after verbs.h or at the end of verbs.h. This will
+ * replace ibv_* structures and calls with syntax matching that shipped
+ * with the OFED version of libibverbs.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <errno.h>
+
+#ifdef __cplusplus
+# define BEGIN_C_DECLS extern "C" {
+# define END_C_DECLS }
+#else /* !__cplusplus */
+# define BEGIN_C_DECLS
+# define END_C_DECLS
+#endif /* __cplusplus */
+
+#if __GNUC__ >= 3
+# define __attribute_const __attribute__((const))
+#else
+# define __attribute_const
+#endif
+
+BEGIN_C_DECLS
+
+/* Unmap defines from ofverbs-defs.h */
+#if OFED_VERBS
+#undef ibv_srq
+#undef ibv_qp
+#undef ibv_qp_init_attr
+#undef ibv_send_wr
+#undef ibv_async_event
+
+#define ofv_srq ibv_srq
+#define ofv_qp ibv_qp
+#define ofv_qp_init_attr ibv_qp_init_attr
+#define ofv_send_wr ibv_send_wr
+#define ofv_async_event ibv_async_event
+#define ofv_xrc_domain ibv_xrc_domain
+
+#define OFV_XRC_QP_EVENT_FLAG IBV_XRC_QP_EVENT_FLAG
+
+#else
+
+#define _real_ibv_srq ibv_srq
+#define _real_ibv_qp ibv_qp
+#define _real_ibv_qp_init_attr ibv_qp_init_attr
+#define _real_ibv_send_wr ibv_send_wr
+#define _real_ibv_async_event ibv_async_event
+#endif /* OFED_VERBS */
+
+enum ofv_event_flags {
+ OFV_XRC_QP_EVENT_FLAG = 0x80000000,
+};
+
+struct ofv_async_event {
+ union {
+ struct ibv_cq *cq;
+ struct ofv_qp *qp;
+ struct ofv_srq *srq;
+ int port_num;
+ uint32_t xrc_qp_num;
+ } element;
+ enum ibv_event_type event_type;
+ void *private;
+};
+
+int ofv_get_async_event(struct ibv_context *context,
+ struct ofv_async_event *event);
+
+void ofv_ack_async_event(struct ofv_async_event *event);
+
+struct ofv_xrc_domain {
+ struct ibv_context *context;
+ uint32_t handle;
+
+ struct ibv_xrcd *xrcd;
+ void *qp_tree;
+};
+
+struct ofv_xrc_domain *ofv_open_xrc_domain(struct ibv_context *context,
+ int fd, int oflags);
+
+int ofv_close_xrc_domain(struct ofv_xrc_domain *xrcd);
+
+enum {
+ OFV_QPT_XRC = IBV_QPT_XRC_SEND
+};
+
+struct ofv_srq {
+ struct ibv_context *context;
+ void *srq_context;
+ struct ibv_pd *pd;
+ uint32_t handle;
+
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ uint32_t events_completed;
+
+ enum ibv_srq_type srq_type;
+ struct ofv_xrc_domain *xrc_domain;
+ struct ibv_cq *xrc_cq;
+ uint32_t xrc_srq_num;
+};
+
+static inline struct ofv_srq *
+ofv_create_srq(struct ibv_pd *pd, struct ibv_srq_init_attr *srq_init_attr)
+{
+ return (struct ofv_srq *) ibv_create_srq(pd, srq_init_attr);
+}
+
+static inline struct ofv_srq *
+ofv_create_xrc_srq(struct ibv_pd *pd, struct ofv_xrc_domain *xrc_domain,
+ struct ibv_cq *xrc_cq, struct ibv_srq_init_attr *srq_init_attr)
+{
+ srq_init_attr->srq_type = IBV_SRQT_XRC;
+ srq_init_attr->ext.xrc.xrcd = xrc_domain->xrcd;
+ srq_init_attr->ext.xrc.cq = xrc_cq;
+ return (struct ofv_srq *) ibv_create_xsrq(pd, srq_init_attr);
+}
+
+static inline int
+ofv_modify_srq(struct ofv_srq *srq, struct ibv_srq_attr *srq_attr, int srq_attr_mask)
+{
+ return ibv_modify_srq((struct _real_ibv_srq *) srq, srq_attr, srq_attr_mask);
+}
+
+static inline int ofv_query_srq(struct ofv_srq *srq, struct ibv_srq_attr *srq_attr)
+{
+ return ibv_query_srq((struct _real_ibv_srq *) srq, srq_attr);
+}
+
+static inline int ofv_destroy_srq(struct ofv_srq *srq)
+{
+ return ibv_destroy_srq((struct _real_ibv_srq *) srq);
+}
+
+static inline int ofv_post_srq_recv(struct ofv_srq *srq,
+ struct ibv_recv_wr *recv_wr,
+ struct ibv_recv_wr **bad_recv_wr)
+{
+ return ibv_post_srq_recv((struct _real_ibv_srq *) srq, recv_wr, bad_recv_wr);
+}
+
+struct ofv_qp_init_attr {
+ void *qp_context;
+ struct ibv_cq *send_cq;
+ struct ibv_cq *recv_cq;
+ struct ofv_srq *srq;
+ struct ibv_qp_cap cap;
+ enum ibv_qp_type qp_type;
+ int sq_sig_all;
+
+ struct ofv_xrc_domain *xrc_domain;
+};
+
+struct ofv_qp {
+ struct ibv_context *context;
+ void *qp_context;
+ struct ibv_pd *pd;
+ struct ibv_cq *send_cq;
+ struct ibv_cq *recv_cq;
+ struct ofv_srq *srq;
+ uint32_t handle;
+ uint32_t qp_num;
+ enum ibv_qp_state state;
+ enum ibv_qp_type qp_type;
+
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ uint32_t events_completed;
+
+ struct ofv_xrc_domain *xrc_domain;
+};
+
+static inline struct ofv_qp *
+ofv_create_qp(struct ibv_pd *pd, struct ofv_qp_init_attr *qp_init_attr)
+{
+ return (struct ofv_qp *)
+ ibv_create_qp(pd, (struct _real_ibv_qp_init_attr *) qp_init_attr);
+}
+
+static inline int ofv_modify_qp(struct ofv_qp *qp, struct ibv_qp_attr *attr,
+ int attr_mask)
+{
+ return ibv_modify_qp((struct _real_ibv_qp *) qp, attr, attr_mask);
+}
+
+static inline int ofv_query_qp(struct ofv_qp *qp, struct ibv_qp_attr *attr,
+ int attr_mask, struct ofv_qp_init_attr *init_attr)
+{
+ return ibv_query_qp((struct _real_ibv_qp *) qp, attr, attr_mask,
+ (struct _real_ibv_qp_init_attr *) init_attr);
+}
+
+
+static inline int ofv_destroy_qp(struct ofv_qp *qp)
+{
+ return ibv_destroy_qp((struct _real_ibv_qp *) qp);
+}
+
+struct ofv_send_wr {
+ uint64_t wr_id;
+ struct ibv_send_wr *next;
+ struct ibv_sge *sg_list;
+ int num_sge;
+ enum ibv_wr_opcode opcode;
+ int send_flags;
+ uint32_t imm_data; /* in network byte order */
+ union {
+ union {
+ struct {
+ uint64_t remote_addr;
+ uint32_t rkey;
+ } rdma;
+ struct {
+ uint64_t remote_addr;
+ uint64_t compare_add;
+ uint64_t swap;
+ uint32_t rkey;
+ } atomic;
+ struct {
+ struct ibv_ah *ah;
+ uint32_t remote_qpn;
+ uint32_t remote_qkey;
+ } ud;
+ struct {
+ uint64_t reserved[3];
+ uint32_t reserved2;
+ uint32_t remote_srqn;
+ } xrc;
+ } wr;
+ struct {
+ uint64_t reserved[3];
+ uint32_t reserved2;
+ uint32_t xrc_remote_srq_num;
+ };
+ };
+};
+
+static inline int ofv_post_send(struct ofv_qp *qp, struct ofv_send_wr *wr,
+ struct ofv_send_wr **bad_wr)
+{
+ return ibv_post_send((struct _real_ibv_qp *) qp, (struct _real_ibv_send_wr *) wr,
+ (struct _real_ibv_send_wr **) bad_wr);
+}
+
+static inline int ofv_post_recv(struct ofv_qp *qp, struct ibv_recv_wr *wr,
+ struct ibv_recv_wr **bad_wr)
+{
+ return ibv_post_recv((struct _real_ibv_qp *) qp, wr, bad_wr);
+}
+
+static inline int ofv_attach_mcast(struct ofv_qp *qp, const union ibv_gid *gid,
+ uint16_t lid)
+{
+ return ibv_attach_mcast((struct _real_ibv_qp *) qp, gid, lid);
+}
+
+static inline int ofv_detach_mcast(struct ofv_qp *qp, const union ibv_gid *gid,
+ uint16_t lid)
+{
+ return ibv_detach_mcast((struct _real_ibv_qp *) qp, gid, lid);
+}
+
+int ofv_create_xrc_rcv_qp(struct ofv_qp_init_attr *init_attr, uint32_t *xrc_rcv_qpn);
+
+int ofv_modify_xrc_rcv_qp(struct ofv_xrc_domain *xrc_domain,
+ uint32_t xrc_qp_num,
+ struct ibv_qp_attr *attr, int attr_mask);
+
+int ofv_query_xrc_rcv_qp(struct ofv_xrc_domain *xrc_domain,
+ uint32_t xrc_qp_num,
+ struct ibv_qp_attr *attr, int attr_mask,
+ struct ofv_qp_init_attr *init_attr);
+
+int ofv_reg_xrc_rcv_qp(struct ofv_xrc_domain *xrc_domain, uint32_t xrc_qp_num);
+
+int ofv_unreg_xrc_rcv_qp(struct ofv_xrc_domain *xrc_domain, uint32_t xrc_qp_num);
+
+/*
+ * Map the ibv_* calls to OFED verbs versions.
+ */
+#ifdef OFED_VERBS
+#define ibv_get_async_event(c,e) ofv_get_async_event(c,e)
+#define ibv_ack_async_event(e) ofv_ack_async_event(e)
+
+#define ibv_open_xrc_domain(c,f,g) ofv_open_xrc_domain(c,f,g)
+#define ibv_close_xrc_domain(d) ofv_close_xrc_domain(d)
+
+#define ibv_create_srq(p,a) ofv_create_srq(p,a)
+#define ibv_create_xrc_srq(p,d,c,a) ofv_create_xrc_srq(p,d,c,a)
+#define ibv_modify_srq(s,a,m) ofv_modify_srq(s,a,m)
+#define ibv_query_srq(s,a) ofv_query_srq(s,a)
+#define ibv_destroy_srq(s) ofv_destroy_srq(s)
+#define ibv_post_srq_recv(s,w,b) ofv_post_srq_recv(s,w,b)
+
+#define IBV_QPT_XRC ((enum ibv_qp_type) OFV_QPT_XRC)
+#define ibv_create_qp(p,a) ofv_create_qp(p,a)
+#define ibv_query_qp(q,a,m,i) ofv_query_qp(p,a,m,i)
+#define ibv_modify_qp(q,a,m) ofv_modify_qp(q,a,m)
+#define ibv_query_qp(q,a,m,i) ofv_query_qp(q,a,m,i)
+#define ibv_destroy_qp(q) ofv_destroy_qp(q)
+#define ibv_post_send(q,w,b) ofv_post_send(q,w,b)
+#define ibv_post_recv(q,w,b) ofv_post_recv(q,w,b)
+#define ibv_attach_mcast(q,g,l) ofv_attach_mcast(q,g,l)
+#define ibv_detach_mcast(q,g,l) ofv_detach_mcast(q,g,l)
+
+#define ibv_create_xrc_rcv_qp(a,q) ofv_create_xrc_rcv_qp(a,q)
+#define ibv_modify_xrc_rcv_qp(d,q,a,m) ofv_modify_xrc_rcv_qp(d,q,a,m)
+#define ibv_query_xrc_rcv_qp(d,q,a,m,i) ofv_query_xrc_rcv_qp(d,q,a,m,i)
+#define ibv_reg_xrc_rcv_qp(d,q) ofv_reg_xrc_rcv_qp(d,q)
+#define ibv_unreg_xrc_rcv_qp(d,q) ofv_unreg_xrc_rcv_qp(d,q)
+#endif /* OFED_VERBS */
+
+END_C_DECLS
+
+# undef __attribute_const
+
+#endif /* OFVERBS_H */
--- /dev/null
+/*
+ * Copyright (c) 2011 Intel Corporation, 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 <stdint.h>
+#include <search.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <errno.h>
+
+#include <infiniband/ofverbs-defs.h>
+#include <infiniband/verbs.h>
+#include <infiniband/ofverbs.h>
+#include "ibverbs.h"
+
+int __ofv_get_async_event(struct ibv_context *context,
+ struct ofv_async_event *event)
+{
+ int ret;
+
+ ret = ibv_get_async_event(context, (struct ibv_async_event *) event);
+ if (!ret) {
+ switch (event->event_type) {
+ 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_PATH_MIG:
+ case IBV_EVENT_PATH_MIG_ERR:
+ case IBV_EVENT_QP_LAST_WQE_REACHED:
+ if (event->element.qp->qp_type == IBV_QPT_XRC_RECV) {
+ event->private = event->element.qp;
+ event->event_type |= OFV_XRC_QP_EVENT_FLAG;
+ event->element.xrc_qp_num = event->element.qp->qp_num;
+ }
+ default:
+ break;
+ }
+ }
+ return ret;
+}
+default_symver(__ofv_get_async_event, ofv_get_async_event);
+
+void ofv_ack_async_event(struct ofv_async_event *event)
+{
+ if (event->event_type & OFV_XRC_QP_EVENT_FLAG) {
+ event->element.qp = event->private;
+ event->event_type &= ~OFV_XRC_QP_EVENT_FLAG;
+ }
+ ibv_ack_async_event((struct ibv_async_event *) event);
+}
+default_symver(__ofv_ack_async_event, ofv_ack_async_event);
+
+struct ofv_xrc_domain *
+__ofv_open_xrc_domain(struct ibv_context *context, int fd, int oflags)
+{
+ struct ofv_xrc_domain *xrcd;
+
+ xrcd = calloc(1, sizeof *xrcd);
+ if (!xrcd)
+ return NULL;
+
+ xrcd->xrcd = ibv_open_xrcd(context, fd, oflags);
+ if (!xrcd->xrcd) {
+ free(xrcd);
+ return NULL;
+ }
+
+ xrcd->context = context;
+ xrcd->handle = xrcd->xrcd->handle;
+ return xrcd;
+}
+default_symver(__ofv_open_xrc_domain, ofv_open_xrc_domain);
+
+static void ofv_free_node(void *node)
+{
+}
+
+int __ofv_close_xrc_domain(struct ofv_xrc_domain *xrcd)
+{
+ int ret;
+
+ ret = ibv_close_xrcd(xrcd->xrcd);
+ if (ret)
+ return ret;
+
+ tdestroy(xrcd->qp_tree, ofv_free_node);
+ free(xrcd);
+ return 0;
+}
+default_symver(__ofv_close_xrc_domain, ofv_close_xrc_domain);
+
+static int ofv_qp_compare(const void *a, const void *b)
+{
+ if ((*(uint32_t *) a) < (*(uint32_t *) b))
+ return -1;
+ else if ((*(uint32_t *) a) > (*(uint32_t *) b))
+ return 1;
+ else
+ return 0;
+}
+
+int __ofv_create_xrc_rcv_qp(struct ofv_qp_init_attr *init_attr, uint32_t *xrc_rcv_qpn)
+{
+ struct ofv_xrc_domain *xrcd;
+ struct ibv_qp *qp;
+
+ xrcd = init_attr->xrc_domain;
+ init_attr->qp_type = IBV_QPT_XRC_RECV;
+ ((struct ibv_qp_init_attr *) init_attr)->ext.xrc_recv.xrcd = xrcd->xrcd;
+ qp = ibv_create_qp(NULL, (struct ibv_qp_init_attr *) init_attr);
+ init_attr->xrc_domain = xrcd;
+ if (!qp)
+ return ENOMEM;
+
+ tsearch(&qp->qp_num, &xrcd->qp_tree, ofv_qp_compare);
+ *xrc_rcv_qpn = qp->qp_num;
+ return 0;
+}
+default_symver(__ofv_create_xrc_rcv_qp, ofv_create_xrc_rcv_qp);
+
+int __ofv_modify_xrc_rcv_qp(struct ofv_xrc_domain *xrc_domain,
+ uint32_t xrc_qp_num,
+ struct ibv_qp_attr *attr, int attr_mask)
+{
+ struct ibv_qp *qp;
+ uint32_t **qpn;
+
+ qpn = tfind(&xrc_qp_num, &xrc_domain->qp_tree, ofv_qp_compare);
+ if (!qpn)
+ return EINVAL;
+
+ qp = ((struct ibv_qp *) ((void *) *qpn - offsetof(struct ibv_qp, qp_num)));
+ return ibv_modify_qp(qp, attr, attr_mask);
+}
+default_symver(__ofv_modify_xrc_rcv_qp, ofv_modify_xrc_rcv_qp);
+
+int __ofv_query_xrc_rcv_qp(struct ofv_xrc_domain *xrc_domain,
+ uint32_t xrc_qp_num,
+ struct ibv_qp_attr *attr, int attr_mask,
+ struct ofv_qp_init_attr *init_attr)
+{
+ struct ibv_qp *qp;
+ uint32_t **qpn;
+
+ qpn = tfind(&xrc_qp_num, &xrc_domain->qp_tree, ofv_qp_compare);
+ if (!qpn)
+ return EINVAL;
+
+ qp = ((struct ibv_qp *) ((void *) *qpn - offsetof(struct ibv_qp, qp_num)));
+ return ibv_query_qp(qp, attr, attr_mask,
+ (struct ibv_qp_init_attr *) init_attr);
+}
+default_symver(__ofv_query_xrc_rcv_qp, ofv_query_xrc_rcv_qp);
+
+int ofv_reg_xrc_rcv_qp(struct ofv_xrc_domain *xrc_domain, uint32_t xrc_qp_num)
+{
+ struct ibv_qp *qp;
+ struct ibv_qp_open_attr attr;
+
+ attr.qp_context = xrc_domain;
+ attr.qp_num = xrc_qp_num;
+ attr.qp_type = IBV_QPT_XRC_RECV;
+
+ qp = ibv_open_qp(xrc_domain->xrcd, &attr);
+ if (!qp)
+ return ENOMEM;
+
+ tsearch(&qp->qp_num, &xrc_domain->qp_tree, ofv_qp_compare);
+ return 0;
+}
+default_symver(__ofv_reg_xrc_rcv_qp, ofv_reg_xrc_rcv_qp);
+
+int ofv_unreg_xrc_rcv_qp(struct ofv_xrc_domain *xrc_domain, uint32_t xrc_qp_num)
+{
+ struct ibv_qp *qp;
+ uint32_t **qpn;
+
+ qpn = tfind(&xrc_qp_num, &xrc_domain->qp_tree, ofv_qp_compare);
+ if (!qpn)
+ return EINVAL;
+
+ qp = ((struct ibv_qp *) ((void *) *qpn - offsetof(struct ibv_qp, qp_num)));
+ return ibv_destroy_qp(qp);
+}
+default_symver(__ofv_unreg_xrc_rcv_qp, ofv_unreg_xrc_rcv_qp);