1219820Sjeff/*
2219820Sjeff * Copyright (c) 2007 Cisco Systems, Inc.  All rights reserved.
3219820Sjeff *
4219820Sjeff * This software is available to you under a choice of one of two
5219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
6219820Sjeff * General Public License (GPL) Version 2, available from the file
7219820Sjeff * COPYING in the main directory of this source tree, or the
8219820Sjeff * OpenIB.org BSD license below:
9219820Sjeff *
10219820Sjeff *     Redistribution and use in source and binary forms, with or
11219820Sjeff *     without modification, are permitted provided that the following
12219820Sjeff *     conditions are met:
13219820Sjeff *
14219820Sjeff *      - Redistributions of source code must retain the above
15219820Sjeff *        copyright notice, this list of conditions and the following
16219820Sjeff *        disclaimer.
17219820Sjeff *
18219820Sjeff *      - Redistributions in binary form must reproduce the above
19219820Sjeff *        copyright notice, this list of conditions and the following
20219820Sjeff *        disclaimer in the documentation and/or other materials
21219820Sjeff *        provided with the distribution.
22219820Sjeff *
23219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30219820Sjeff * SOFTWARE.
31219820Sjeff */
32219820Sjeff
33219820Sjeff#if HAVE_CONFIG_H
34219820Sjeff#  include <config.h>
35219820Sjeff#endif /* HAVE_CONFIG_H */
36219820Sjeff
37219820Sjeff#include <string.h>
38219820Sjeff#include <stddef.h>
39219820Sjeff#include <stdlib.h>
40219820Sjeff#include <unistd.h>
41219820Sjeff#include <alloca.h>
42219820Sjeff
43219820Sjeff#include "ibverbs.h"
44219820Sjeff
45219820Sjeffstruct ibv_pd_1_0 {
46219820Sjeff	struct ibv_context_1_0 *context;
47219820Sjeff	uint32_t		handle;
48219820Sjeff
49219820Sjeff	struct ibv_pd	       *real_pd;
50219820Sjeff};
51219820Sjeff
52219820Sjeffstruct ibv_mr_1_0 {
53219820Sjeff	struct ibv_context_1_0 *context;
54219820Sjeff	struct ibv_pd_1_0      *pd;
55219820Sjeff	uint32_t		handle;
56219820Sjeff	uint32_t		lkey;
57219820Sjeff	uint32_t		rkey;
58219820Sjeff
59219820Sjeff	struct ibv_mr	       *real_mr;
60219820Sjeff};
61219820Sjeff
62219820Sjeffstruct ibv_srq_1_0 {
63219820Sjeff	struct ibv_context_1_0 *context;
64219820Sjeff	void		       *srq_context;
65219820Sjeff	struct ibv_pd_1_0      *pd;
66219820Sjeff	uint32_t		handle;
67219820Sjeff
68219820Sjeff	pthread_mutex_t		mutex;
69219820Sjeff	pthread_cond_t		cond;
70219820Sjeff	uint32_t		events_completed;
71219820Sjeff
72219820Sjeff	struct ibv_srq	       *real_srq;
73219820Sjeff};
74219820Sjeff
75219820Sjeffstruct ibv_qp_init_attr_1_0 {
76219820Sjeff	void		       *qp_context;
77219820Sjeff	struct ibv_cq_1_0      *send_cq;
78219820Sjeff	struct ibv_cq_1_0      *recv_cq;
79219820Sjeff	struct ibv_srq_1_0     *srq;
80219820Sjeff	struct ibv_qp_cap	cap;
81219820Sjeff	enum ibv_qp_type	qp_type;
82219820Sjeff	int			sq_sig_all;
83219820Sjeff};
84219820Sjeff
85219820Sjeffstruct ibv_send_wr_1_0 {
86219820Sjeff	struct ibv_send_wr_1_0 *next;
87219820Sjeff	uint64_t		wr_id;
88219820Sjeff	struct ibv_sge	       *sg_list;
89219820Sjeff	int			num_sge;
90219820Sjeff	enum ibv_wr_opcode	opcode;
91219820Sjeff	int			send_flags;
92219820Sjeff	uint32_t		imm_data;	/* in network byte order */
93219820Sjeff	union {
94219820Sjeff		struct {
95219820Sjeff			uint64_t	remote_addr;
96219820Sjeff			uint32_t	rkey;
97219820Sjeff		} rdma;
98219820Sjeff		struct {
99219820Sjeff			uint64_t	remote_addr;
100219820Sjeff			uint64_t	compare_add;
101219820Sjeff			uint64_t	swap;
102219820Sjeff			uint32_t	rkey;
103219820Sjeff		} atomic;
104219820Sjeff		struct {
105219820Sjeff			struct ibv_ah_1_0 *ah;
106219820Sjeff			uint32_t	remote_qpn;
107219820Sjeff			uint32_t	remote_qkey;
108219820Sjeff		} ud;
109219820Sjeff	} wr;
110219820Sjeff};
111219820Sjeff
112219820Sjeffstruct ibv_recv_wr_1_0 {
113219820Sjeff	struct ibv_recv_wr_1_0 *next;
114219820Sjeff	uint64_t		wr_id;
115219820Sjeff	struct ibv_sge	       *sg_list;
116219820Sjeff	int			num_sge;
117219820Sjeff};
118219820Sjeff
119219820Sjeffstruct ibv_qp_1_0 {
120219820Sjeff	struct ibv_context_1_0 *context;
121219820Sjeff	void		       *qp_context;
122219820Sjeff	struct ibv_pd_1_0      *pd;
123219820Sjeff	struct ibv_cq_1_0      *send_cq;
124219820Sjeff	struct ibv_cq_1_0      *recv_cq;
125219820Sjeff	struct ibv_srq_1_0     *srq;
126219820Sjeff	uint32_t		handle;
127219820Sjeff	uint32_t		qp_num;
128219820Sjeff	enum ibv_qp_state       state;
129219820Sjeff	enum ibv_qp_type	qp_type;
130219820Sjeff
131219820Sjeff	pthread_mutex_t		mutex;
132219820Sjeff	pthread_cond_t		cond;
133219820Sjeff	uint32_t		events_completed;
134219820Sjeff
135219820Sjeff	struct ibv_qp	       *real_qp;
136219820Sjeff};
137219820Sjeff
138219820Sjeffstruct ibv_cq_1_0 {
139219820Sjeff	struct ibv_context_1_0 *context;
140219820Sjeff	void		       *cq_context;
141219820Sjeff	uint32_t		handle;
142219820Sjeff	int			cqe;
143219820Sjeff
144219820Sjeff	pthread_mutex_t		mutex;
145219820Sjeff	pthread_cond_t		cond;
146219820Sjeff	uint32_t		comp_events_completed;
147219820Sjeff	uint32_t		async_events_completed;
148219820Sjeff
149219820Sjeff	struct ibv_cq	       *real_cq;
150219820Sjeff};
151219820Sjeff
152219820Sjeffstruct ibv_ah_1_0 {
153219820Sjeff	struct ibv_context_1_0 *context;
154219820Sjeff	struct ibv_pd_1_0      *pd;
155219820Sjeff	uint32_t		handle;
156219820Sjeff
157219820Sjeff	struct ibv_ah	       *real_ah;
158219820Sjeff};
159219820Sjeff
160219820Sjeffstruct ibv_device_1_0 {
161219820Sjeff	void		       *obsolete_sysfs_dev;
162219820Sjeff	void		       *obsolete_sysfs_ibdev;
163219820Sjeff	struct ibv_device      *real_device; /* was obsolete driver member */
164219820Sjeff	struct ibv_device_ops	ops;
165219820Sjeff};
166219820Sjeff
167219820Sjeffstruct ibv_context_ops_1_0 {
168219820Sjeff	int			(*query_device)(struct ibv_context *context,
169219820Sjeff					      struct ibv_device_attr *device_attr);
170219820Sjeff	int			(*query_port)(struct ibv_context *context, uint8_t port_num,
171219820Sjeff					      struct ibv_port_attr *port_attr);
172219820Sjeff	struct ibv_pd *		(*alloc_pd)(struct ibv_context *context);
173219820Sjeff	int			(*dealloc_pd)(struct ibv_pd *pd);
174219820Sjeff	struct ibv_mr *		(*reg_mr)(struct ibv_pd *pd, void *addr, size_t length,
175219820Sjeff					  int access);
176219820Sjeff	int			(*dereg_mr)(struct ibv_mr *mr);
177219820Sjeff	struct ibv_cq *		(*create_cq)(struct ibv_context *context, int cqe,
178219820Sjeff					     struct ibv_comp_channel *channel,
179219820Sjeff					     int comp_vector);
180219820Sjeff	int			(*poll_cq)(struct ibv_cq_1_0 *cq, int num_entries,
181219820Sjeff					   struct ibv_wc *wc);
182219820Sjeff	int			(*req_notify_cq)(struct ibv_cq_1_0 *cq,
183219820Sjeff						 int solicited_only);
184219820Sjeff	void			(*cq_event)(struct ibv_cq *cq);
185219820Sjeff	int			(*resize_cq)(struct ibv_cq *cq, int cqe);
186219820Sjeff	int			(*destroy_cq)(struct ibv_cq *cq);
187219820Sjeff	struct ibv_srq *	(*create_srq)(struct ibv_pd *pd,
188219820Sjeff					      struct ibv_srq_init_attr *srq_init_attr);
189219820Sjeff	int			(*modify_srq)(struct ibv_srq *srq,
190219820Sjeff					      struct ibv_srq_attr *srq_attr,
191219820Sjeff					      int srq_attr_mask);
192219820Sjeff	int			(*query_srq)(struct ibv_srq *srq,
193219820Sjeff					     struct ibv_srq_attr *srq_attr);
194219820Sjeff	int			(*destroy_srq)(struct ibv_srq *srq);
195219820Sjeff	int			(*post_srq_recv)(struct ibv_srq_1_0 *srq,
196219820Sjeff						 struct ibv_recv_wr_1_0 *recv_wr,
197219820Sjeff						 struct ibv_recv_wr_1_0 **bad_recv_wr);
198219820Sjeff	struct ibv_qp *		(*create_qp)(struct ibv_pd *pd, struct ibv_qp_init_attr *attr);
199219820Sjeff	int			(*query_qp)(struct ibv_qp *qp, struct ibv_qp_attr *attr,
200219820Sjeff					    int attr_mask,
201219820Sjeff					    struct ibv_qp_init_attr *init_attr);
202219820Sjeff	int			(*modify_qp)(struct ibv_qp *qp, struct ibv_qp_attr *attr,
203219820Sjeff					     int attr_mask);
204219820Sjeff	int			(*destroy_qp)(struct ibv_qp *qp);
205219820Sjeff	int			(*post_send)(struct ibv_qp_1_0 *qp,
206219820Sjeff					     struct ibv_send_wr_1_0 *wr,
207219820Sjeff					     struct ibv_send_wr_1_0 **bad_wr);
208219820Sjeff	int			(*post_recv)(struct ibv_qp_1_0 *qp,
209219820Sjeff					     struct ibv_recv_wr_1_0 *wr,
210219820Sjeff					     struct ibv_recv_wr_1_0 **bad_wr);
211219820Sjeff	struct ibv_ah *		(*create_ah)(struct ibv_pd *pd, struct ibv_ah_attr *attr);
212219820Sjeff	int			(*destroy_ah)(struct ibv_ah *ah);
213219820Sjeff	int			(*attach_mcast)(struct ibv_qp *qp, union ibv_gid *gid,
214219820Sjeff						uint16_t lid);
215219820Sjeff	int			(*detach_mcast)(struct ibv_qp *qp, union ibv_gid *gid,
216219820Sjeff						uint16_t lid);
217219820Sjeff};
218219820Sjeff
219219820Sjeffstruct ibv_context_1_0 {
220219820Sjeff	struct ibv_device_1_0	       *device;
221219820Sjeff	struct ibv_context_ops_1_0	ops;
222219820Sjeff	int				cmd_fd;
223219820Sjeff	int				async_fd;
224219820Sjeff	int				num_comp_vectors;
225219820Sjeff
226219820Sjeff	struct ibv_context	       *real_context; /* was abi_compat member */
227219820Sjeff};
228219820Sjeff
229219820Sjeffstruct ibv_device_1_0 **__ibv_get_device_list_1_0(int *num)
230219820Sjeff{
231219820Sjeff	struct ibv_device **real_list;
232219820Sjeff	struct ibv_device_1_0 **l;
233219820Sjeff	int i, n;
234219820Sjeff
235219820Sjeff	real_list = ibv_get_device_list(&n);
236219820Sjeff	if (!real_list)
237219820Sjeff		return NULL;
238219820Sjeff
239219820Sjeff	l = calloc(n + 2, sizeof (struct ibv_device_1_0 *));
240219820Sjeff	if (!l)
241219820Sjeff		return NULL;
242219820Sjeff
243219820Sjeff	l[0] = (void *) real_list;
244219820Sjeff
245219820Sjeff	for (i = 0; i < n; ++i) {
246219820Sjeff		l[i + 1] = calloc(1, sizeof (struct ibv_device_1_0));
247219820Sjeff		if (!l[i + 1])
248219820Sjeff			goto fail;
249219820Sjeff		l[i + 1]->real_device = real_list[i];
250219820Sjeff	}
251219820Sjeff
252219820Sjeff	if (num)
253219820Sjeff		*num = n;
254219820Sjeff
255219820Sjeff	return l + 1;
256219820Sjeff
257219820Sjefffail:
258219820Sjeff	for (i = 1; i <= n; ++i)
259219820Sjeff		if (l[i])
260219820Sjeff			free(l[i]);
261219820Sjeff	ibv_free_device_list(real_list);
262219820Sjeff	return NULL;
263219820Sjeff}
264219820Sjeffsymver(__ibv_get_device_list_1_0, ibv_get_device_list, IBVERBS_1.0);
265219820Sjeff
266219820Sjeffvoid __ibv_free_device_list_1_0(struct ibv_device_1_0 **list)
267219820Sjeff{
268219820Sjeff	struct ibv_device_1_0 **l = list;
269219820Sjeff
270219820Sjeff	while (*l) {
271219820Sjeff		free(*l);
272219820Sjeff		++l;
273219820Sjeff	}
274219820Sjeff
275219820Sjeff	ibv_free_device_list((void *) list[-1]);
276219820Sjeff	free(list - 1);
277219820Sjeff}
278219820Sjeffsymver(__ibv_free_device_list_1_0, ibv_free_device_list, IBVERBS_1.0);
279219820Sjeff
280219820Sjeffconst char *__ibv_get_device_name_1_0(struct ibv_device_1_0 *device)
281219820Sjeff{
282219820Sjeff	return ibv_get_device_name(device->real_device);
283219820Sjeff}
284219820Sjeffsymver(__ibv_get_device_name_1_0, ibv_get_device_name, IBVERBS_1.0);
285219820Sjeff
286219820Sjeffuint64_t __ibv_get_device_guid_1_0(struct ibv_device_1_0 *device)
287219820Sjeff{
288219820Sjeff	return ibv_get_device_guid(device->real_device);
289219820Sjeff}
290219820Sjeffsymver(__ibv_get_device_guid_1_0, ibv_get_device_guid, IBVERBS_1.0);
291219820Sjeff
292219820Sjeffstatic int poll_cq_wrapper_1_0(struct ibv_cq_1_0 *cq, int num_entries,
293219820Sjeff			       struct ibv_wc *wc)
294219820Sjeff{
295219820Sjeff	return cq->context->real_context->ops.poll_cq(cq->real_cq, num_entries, wc);
296219820Sjeff}
297219820Sjeff
298219820Sjeffstatic int req_notify_cq_wrapper_1_0(struct ibv_cq_1_0 *cq, int sol_only)
299219820Sjeff{
300219820Sjeff	return cq->context->real_context->ops.req_notify_cq(cq->real_cq, sol_only);
301219820Sjeff}
302219820Sjeff
303219820Sjeffstatic int post_srq_recv_wrapper_1_0(struct ibv_srq_1_0 *srq, struct ibv_recv_wr_1_0 *wr,
304219820Sjeff				 struct ibv_recv_wr_1_0 **bad_wr)
305219820Sjeff{
306219820Sjeff	struct ibv_recv_wr_1_0 *w;
307219820Sjeff	struct ibv_recv_wr *real_wr, *head_wr = NULL, *tail_wr = NULL, *real_bad_wr;
308219820Sjeff	int ret;
309219820Sjeff
310219820Sjeff	for (w = wr; w; w = w->next) {
311219820Sjeff		real_wr = alloca(sizeof *real_wr);
312219820Sjeff		real_wr->wr_id   = w->wr_id;
313219820Sjeff		real_wr->sg_list = w->sg_list;
314219820Sjeff		real_wr->num_sge = w->num_sge;
315219820Sjeff		real_wr->next    = NULL;
316219820Sjeff		if (tail_wr)
317219820Sjeff			tail_wr->next = real_wr;
318219820Sjeff		else
319219820Sjeff			head_wr = real_wr;
320219820Sjeff
321219820Sjeff		tail_wr = real_wr;
322219820Sjeff	}
323219820Sjeff
324219820Sjeff	ret = srq->context->real_context->ops.post_srq_recv(srq->real_srq, head_wr,
325219820Sjeff							    &real_bad_wr);
326219820Sjeff
327219820Sjeff	if (ret) {
328219820Sjeff		for (real_wr = head_wr, w = wr;
329219820Sjeff		     real_wr;
330219820Sjeff		     real_wr = real_wr->next, w = w->next)
331219820Sjeff			if (real_wr == real_bad_wr) {
332219820Sjeff				*bad_wr = w;
333219820Sjeff				break;
334219820Sjeff			}
335219820Sjeff	}
336219820Sjeff
337219820Sjeff	return ret;
338219820Sjeff}
339219820Sjeff
340219820Sjeffstatic int post_send_wrapper_1_0(struct ibv_qp_1_0 *qp, struct ibv_send_wr_1_0 *wr,
341219820Sjeff				 struct ibv_send_wr_1_0 **bad_wr)
342219820Sjeff{
343219820Sjeff	struct ibv_send_wr_1_0 *w;
344219820Sjeff	struct ibv_send_wr *real_wr, *head_wr = NULL, *tail_wr = NULL, *real_bad_wr;
345219820Sjeff	int is_ud = qp->qp_type == IBV_QPT_UD;
346219820Sjeff	int ret;
347219820Sjeff
348219820Sjeff	for (w = wr; w; w = w->next) {
349219820Sjeff		real_wr = alloca(sizeof *real_wr);
350219820Sjeff		real_wr->wr_id = w->wr_id;
351219820Sjeff		real_wr->next  = NULL;
352219820Sjeff
353219820Sjeff		memcpy(&real_wr->sg_list, &w->sg_list,
354219820Sjeff		       sizeof *w - offsetof(struct ibv_send_wr, sg_list));
355219820Sjeff
356219820Sjeff		if (is_ud)
357219820Sjeff			real_wr->wr.ud.ah = w->wr.ud.ah->real_ah;
358219820Sjeff
359219820Sjeff		if (tail_wr)
360219820Sjeff			tail_wr->next = real_wr;
361219820Sjeff		else
362219820Sjeff			head_wr = real_wr;
363219820Sjeff
364219820Sjeff		tail_wr = real_wr;
365219820Sjeff	}
366219820Sjeff
367219820Sjeff	ret = qp->context->real_context->ops.post_send(qp->real_qp, head_wr,
368219820Sjeff						       &real_bad_wr);
369219820Sjeff
370219820Sjeff	if (ret) {
371219820Sjeff		for (real_wr = head_wr, w = wr;
372219820Sjeff		     real_wr;
373219820Sjeff		     real_wr = real_wr->next, w = w->next)
374219820Sjeff			if (real_wr == real_bad_wr) {
375219820Sjeff				*bad_wr = w;
376219820Sjeff				break;
377219820Sjeff			}
378219820Sjeff	}
379219820Sjeff
380219820Sjeff	return ret;
381219820Sjeff}
382219820Sjeff
383219820Sjeffstatic int post_recv_wrapper_1_0(struct ibv_qp_1_0 *qp, struct ibv_recv_wr_1_0 *wr,
384219820Sjeff				 struct ibv_recv_wr_1_0 **bad_wr)
385219820Sjeff{
386219820Sjeff	struct ibv_recv_wr_1_0 *w;
387219820Sjeff	struct ibv_recv_wr *real_wr, *head_wr = NULL, *tail_wr = NULL, *real_bad_wr;
388219820Sjeff	int ret;
389219820Sjeff
390219820Sjeff	for (w = wr; w; w = w->next) {
391219820Sjeff		real_wr = alloca(sizeof *real_wr);
392219820Sjeff		real_wr->wr_id   = w->wr_id;
393219820Sjeff		real_wr->sg_list = w->sg_list;
394219820Sjeff		real_wr->num_sge = w->num_sge;
395219820Sjeff		real_wr->next    = NULL;
396219820Sjeff		if (tail_wr)
397219820Sjeff			tail_wr->next = real_wr;
398219820Sjeff		else
399219820Sjeff			head_wr = real_wr;
400219820Sjeff
401219820Sjeff		tail_wr = real_wr;
402219820Sjeff	}
403219820Sjeff
404219820Sjeff	ret = qp->context->real_context->ops.post_recv(qp->real_qp, head_wr,
405219820Sjeff						       &real_bad_wr);
406219820Sjeff
407219820Sjeff	if (ret) {
408219820Sjeff		for (real_wr = head_wr, w = wr;
409219820Sjeff		     real_wr;
410219820Sjeff		     real_wr = real_wr->next, w = w->next)
411219820Sjeff			if (real_wr == real_bad_wr) {
412219820Sjeff				*bad_wr = w;
413219820Sjeff				break;
414219820Sjeff			}
415219820Sjeff	}
416219820Sjeff
417219820Sjeff	return ret;
418219820Sjeff}
419219820Sjeff
420219820Sjeffstruct ibv_context_1_0 *__ibv_open_device_1_0(struct ibv_device_1_0 *device)
421219820Sjeff{
422219820Sjeff	struct ibv_context     *real_ctx;
423219820Sjeff	struct ibv_context_1_0 *ctx;
424219820Sjeff
425219820Sjeff	ctx = malloc(sizeof *ctx);
426219820Sjeff	if (!ctx)
427219820Sjeff		return NULL;
428219820Sjeff
429219820Sjeff	real_ctx = ibv_open_device(device->real_device);
430219820Sjeff	if (!real_ctx) {
431219820Sjeff		free(ctx);
432219820Sjeff		return NULL;
433219820Sjeff	}
434219820Sjeff
435219820Sjeff	ctx->device       = device;
436219820Sjeff	ctx->real_context = real_ctx;
437219820Sjeff
438219820Sjeff	ctx->ops.poll_cq       = poll_cq_wrapper_1_0;
439219820Sjeff	ctx->ops.req_notify_cq = req_notify_cq_wrapper_1_0;
440219820Sjeff	ctx->ops.post_send     = post_send_wrapper_1_0;
441219820Sjeff	ctx->ops.post_recv     = post_recv_wrapper_1_0;
442219820Sjeff	ctx->ops.post_srq_recv = post_srq_recv_wrapper_1_0;
443219820Sjeff
444219820Sjeff	return ctx;
445219820Sjeff}
446219820Sjeffsymver(__ibv_open_device_1_0, ibv_open_device, IBVERBS_1.0);
447219820Sjeff
448219820Sjeffint __ibv_close_device_1_0(struct ibv_context_1_0 *context)
449219820Sjeff{
450219820Sjeff	int ret;
451219820Sjeff
452219820Sjeff	ret = ibv_close_device(context->real_context);
453219820Sjeff	if (ret)
454219820Sjeff		return ret;
455219820Sjeff
456219820Sjeff	free(context);
457219820Sjeff	return 0;
458219820Sjeff}
459219820Sjeffsymver(__ibv_close_device_1_0, ibv_close_device, IBVERBS_1.0);
460219820Sjeff
461219820Sjeffint __ibv_get_async_event_1_0(struct ibv_context_1_0 *context,
462219820Sjeff			      struct ibv_async_event *event)
463219820Sjeff{
464219820Sjeff	int ret;
465219820Sjeff
466219820Sjeff	ret = ibv_get_async_event(context->real_context, event);
467219820Sjeff	if (ret)
468219820Sjeff		return ret;
469219820Sjeff
470219820Sjeff	switch (event->event_type) {
471219820Sjeff	case IBV_EVENT_CQ_ERR:
472219820Sjeff		event->element.cq = event->element.cq->cq_context;
473219820Sjeff		break;
474219820Sjeff
475219820Sjeff	case IBV_EVENT_QP_FATAL:
476219820Sjeff	case IBV_EVENT_QP_REQ_ERR:
477219820Sjeff	case IBV_EVENT_QP_ACCESS_ERR:
478219820Sjeff	case IBV_EVENT_COMM_EST:
479219820Sjeff	case IBV_EVENT_SQ_DRAINED:
480219820Sjeff	case IBV_EVENT_PATH_MIG:
481219820Sjeff	case IBV_EVENT_PATH_MIG_ERR:
482219820Sjeff	case IBV_EVENT_QP_LAST_WQE_REACHED:
483219820Sjeff		event->element.qp = event->element.qp->qp_context;
484219820Sjeff		break;
485219820Sjeff
486219820Sjeff	case IBV_EVENT_SRQ_ERR:
487219820Sjeff	case IBV_EVENT_SRQ_LIMIT_REACHED:
488219820Sjeff		event->element.srq = event->element.srq->srq_context;
489219820Sjeff		break;
490219820Sjeff
491219820Sjeff	default:
492219820Sjeff		break;
493219820Sjeff	}
494219820Sjeff
495219820Sjeff	return ret;
496219820Sjeff}
497219820Sjeffsymver(__ibv_get_async_event_1_0, ibv_get_async_event, IBVERBS_1.0);
498219820Sjeff
499219820Sjeffvoid __ibv_ack_async_event_1_0(struct ibv_async_event *event)
500219820Sjeff{
501219820Sjeff	struct ibv_async_event real_event = *event;
502219820Sjeff
503219820Sjeff	switch (event->event_type) {
504219820Sjeff	case IBV_EVENT_CQ_ERR:
505219820Sjeff		real_event.element.cq =
506219820Sjeff			((struct ibv_cq_1_0 *) event->element.cq)->real_cq;
507219820Sjeff		break;
508219820Sjeff
509219820Sjeff	case IBV_EVENT_QP_FATAL:
510219820Sjeff	case IBV_EVENT_QP_REQ_ERR:
511219820Sjeff	case IBV_EVENT_QP_ACCESS_ERR:
512219820Sjeff	case IBV_EVENT_COMM_EST:
513219820Sjeff	case IBV_EVENT_SQ_DRAINED:
514219820Sjeff	case IBV_EVENT_PATH_MIG:
515219820Sjeff	case IBV_EVENT_PATH_MIG_ERR:
516219820Sjeff	case IBV_EVENT_QP_LAST_WQE_REACHED:
517219820Sjeff		real_event.element.qp =
518219820Sjeff			((struct ibv_qp_1_0 *) event->element.qp)->real_qp;
519219820Sjeff		break;
520219820Sjeff
521219820Sjeff	case IBV_EVENT_SRQ_ERR:
522219820Sjeff	case IBV_EVENT_SRQ_LIMIT_REACHED:
523219820Sjeff		real_event.element.srq =
524219820Sjeff			((struct ibv_srq_1_0 *) event->element.srq)->real_srq;
525219820Sjeff		break;
526219820Sjeff
527219820Sjeff	default:
528219820Sjeff		break;
529219820Sjeff	}
530219820Sjeff
531219820Sjeff	ibv_ack_async_event(&real_event);
532219820Sjeff}
533219820Sjeffsymver(__ibv_ack_async_event_1_0, ibv_ack_async_event, IBVERBS_1.0);
534219820Sjeff
535219820Sjeffint __ibv_query_device_1_0(struct ibv_context_1_0 *context,
536219820Sjeff			   struct ibv_device_attr *device_attr)
537219820Sjeff{
538219820Sjeff	return ibv_query_device(context->real_context, device_attr);
539219820Sjeff}
540219820Sjeffsymver(__ibv_query_device_1_0, ibv_query_device, IBVERBS_1.0);
541219820Sjeff
542219820Sjeffint __ibv_query_port_1_0(struct ibv_context_1_0 *context, uint8_t port_num,
543219820Sjeff			 struct ibv_port_attr *port_attr)
544219820Sjeff{
545219820Sjeff	return ibv_query_port(context->real_context, port_num, port_attr);
546219820Sjeff}
547219820Sjeffsymver(__ibv_query_port_1_0, ibv_query_port, IBVERBS_1.0);
548219820Sjeff
549219820Sjeffint __ibv_query_gid_1_0(struct ibv_context_1_0 *context, uint8_t port_num,
550219820Sjeff			int index, union ibv_gid *gid)
551219820Sjeff{
552219820Sjeff	return ibv_query_gid(context->real_context, port_num, index, gid);
553219820Sjeff}
554219820Sjeffsymver(__ibv_query_gid_1_0, ibv_query_gid, IBVERBS_1.0);
555219820Sjeff
556219820Sjeffint __ibv_query_pkey_1_0(struct ibv_context_1_0 *context, uint8_t port_num,
557219820Sjeff			 int index, uint16_t *pkey)
558219820Sjeff{
559219820Sjeff	return ibv_query_pkey(context->real_context, port_num, index, pkey);
560219820Sjeff}
561219820Sjeffsymver(__ibv_query_pkey_1_0, ibv_query_pkey, IBVERBS_1.0);
562219820Sjeff
563219820Sjeffstruct ibv_pd_1_0 *__ibv_alloc_pd_1_0(struct ibv_context_1_0 *context)
564219820Sjeff{
565219820Sjeff	struct ibv_pd *real_pd;
566219820Sjeff	struct ibv_pd_1_0 *pd;
567219820Sjeff
568219820Sjeff	pd = malloc(sizeof *pd);
569219820Sjeff	if (!pd)
570219820Sjeff		return NULL;
571219820Sjeff
572219820Sjeff	real_pd = ibv_alloc_pd(context->real_context);
573219820Sjeff	if (!real_pd) {
574219820Sjeff		free(pd);
575219820Sjeff		return NULL;
576219820Sjeff	}
577219820Sjeff
578219820Sjeff	pd->context = context;
579219820Sjeff	pd->real_pd = real_pd;
580219820Sjeff
581219820Sjeff	return pd;
582219820Sjeff}
583219820Sjeffsymver(__ibv_alloc_pd_1_0, ibv_alloc_pd, IBVERBS_1.0);
584219820Sjeff
585219820Sjeffint __ibv_dealloc_pd_1_0(struct ibv_pd_1_0 *pd)
586219820Sjeff{
587219820Sjeff	int ret;
588219820Sjeff
589219820Sjeff	ret = ibv_dealloc_pd(pd->real_pd);
590219820Sjeff	if (ret)
591219820Sjeff		return ret;
592219820Sjeff
593219820Sjeff	free(pd);
594219820Sjeff	return 0;
595219820Sjeff}
596219820Sjeffsymver(__ibv_dealloc_pd_1_0, ibv_dealloc_pd, IBVERBS_1.0);
597219820Sjeff
598219820Sjeffstruct ibv_mr_1_0 *__ibv_reg_mr_1_0(struct ibv_pd_1_0 *pd, void *addr,
599219820Sjeff				    size_t length, int access)
600219820Sjeff{
601219820Sjeff	struct ibv_mr *real_mr;
602219820Sjeff	struct ibv_mr_1_0 *mr;
603219820Sjeff
604219820Sjeff	mr = malloc(sizeof *mr);
605219820Sjeff	if (!mr)
606219820Sjeff		return NULL;
607219820Sjeff
608219820Sjeff	real_mr = ibv_reg_mr(pd->real_pd, addr, length, access);
609219820Sjeff	if (!real_mr) {
610219820Sjeff		free(mr);
611219820Sjeff		return NULL;
612219820Sjeff	}
613219820Sjeff
614219820Sjeff	mr->context = pd->context;
615219820Sjeff	mr->pd      = pd;
616219820Sjeff	mr->lkey    = real_mr->lkey;
617219820Sjeff	mr->rkey    = real_mr->rkey;
618219820Sjeff	mr->real_mr = real_mr;
619219820Sjeff
620219820Sjeff	return mr;
621219820Sjeff}
622219820Sjeffsymver(__ibv_reg_mr_1_0, ibv_reg_mr, IBVERBS_1.0);
623219820Sjeff
624219820Sjeffint __ibv_dereg_mr_1_0(struct ibv_mr_1_0 *mr)
625219820Sjeff{
626219820Sjeff	int ret;
627219820Sjeff
628219820Sjeff	ret = ibv_dereg_mr(mr->real_mr);
629219820Sjeff	if (ret)
630219820Sjeff		return ret;
631219820Sjeff
632219820Sjeff	free(mr);
633219820Sjeff	return 0;
634219820Sjeff}
635219820Sjeffsymver(__ibv_dereg_mr_1_0, ibv_dereg_mr, IBVERBS_1.0);
636219820Sjeff
637219820Sjeffstruct ibv_cq_1_0 *__ibv_create_cq_1_0(struct ibv_context_1_0 *context, int cqe,
638219820Sjeff				       void *cq_context,
639219820Sjeff				       struct ibv_comp_channel *channel,
640219820Sjeff				       int comp_vector)
641219820Sjeff{
642219820Sjeff	struct ibv_cq *real_cq;
643219820Sjeff	struct ibv_cq_1_0 *cq;
644219820Sjeff
645219820Sjeff	cq = malloc(sizeof *cq);
646219820Sjeff	if (!cq)
647219820Sjeff		return NULL;
648219820Sjeff
649219820Sjeff	real_cq = ibv_create_cq(context->real_context, cqe, cq_context,
650219820Sjeff				channel, comp_vector);
651219820Sjeff	if (!real_cq) {
652219820Sjeff		free(cq);
653219820Sjeff		return NULL;
654219820Sjeff	}
655219820Sjeff
656219820Sjeff	cq->context    = context;
657219820Sjeff	cq->cq_context = cq_context;
658219820Sjeff	cq->cqe        = cqe;
659219820Sjeff	cq->real_cq    = real_cq;
660219820Sjeff
661219820Sjeff	real_cq->cq_context = cq;
662219820Sjeff
663219820Sjeff	return cq;
664219820Sjeff}
665219820Sjeffsymver(__ibv_create_cq_1_0, ibv_create_cq, IBVERBS_1.0);
666219820Sjeff
667219820Sjeffint __ibv_resize_cq_1_0(struct ibv_cq_1_0 *cq, int cqe)
668219820Sjeff{
669219820Sjeff	return ibv_resize_cq(cq->real_cq, cqe);
670219820Sjeff}
671219820Sjeffsymver(__ibv_resize_cq_1_0, ibv_resize_cq, IBVERBS_1.0);
672219820Sjeff
673219820Sjeffint __ibv_destroy_cq_1_0(struct ibv_cq_1_0 *cq)
674219820Sjeff{
675219820Sjeff	int ret;
676219820Sjeff
677219820Sjeff	ret = ibv_destroy_cq(cq->real_cq);
678219820Sjeff	if (ret)
679219820Sjeff		return ret;
680219820Sjeff
681219820Sjeff	free(cq);
682219820Sjeff	return 0;
683219820Sjeff}
684219820Sjeffsymver(__ibv_destroy_cq_1_0, ibv_destroy_cq, IBVERBS_1.0);
685219820Sjeff
686219820Sjeffint __ibv_get_cq_event_1_0(struct ibv_comp_channel *channel,
687219820Sjeff			   struct ibv_cq_1_0 **cq, void **cq_context)
688219820Sjeff{
689219820Sjeff	struct ibv_cq *real_cq;
690219820Sjeff	void *cq_ptr;
691219820Sjeff	int ret;
692219820Sjeff
693219820Sjeff	ret = ibv_get_cq_event(channel, &real_cq, &cq_ptr);
694219820Sjeff	if (ret)
695219820Sjeff		return ret;
696219820Sjeff
697219820Sjeff	*cq         = cq_ptr;
698219820Sjeff	*cq_context = (*cq)->cq_context;
699219820Sjeff
700219820Sjeff	return 0;
701219820Sjeff}
702219820Sjeffsymver(__ibv_get_cq_event_1_0, ibv_get_cq_event, IBVERBS_1.0);
703219820Sjeff
704219820Sjeffvoid __ibv_ack_cq_events_1_0(struct ibv_cq_1_0 *cq, unsigned int nevents)
705219820Sjeff{
706219820Sjeff	ibv_ack_cq_events(cq->real_cq, nevents);
707219820Sjeff}
708219820Sjeffsymver(__ibv_ack_cq_events_1_0, ibv_ack_cq_events, IBVERBS_1.0);
709219820Sjeff
710219820Sjeffstruct ibv_srq_1_0 *__ibv_create_srq_1_0(struct ibv_pd_1_0 *pd,
711219820Sjeff					 struct ibv_srq_init_attr *srq_init_attr)
712219820Sjeff{
713219820Sjeff	struct ibv_srq *real_srq;
714219820Sjeff	struct ibv_srq_1_0 *srq;
715219820Sjeff
716219820Sjeff	srq = malloc(sizeof *srq);
717219820Sjeff	if (!srq)
718219820Sjeff		return NULL;
719219820Sjeff
720219820Sjeff	real_srq = ibv_create_srq(pd->real_pd, srq_init_attr);
721219820Sjeff	if (!real_srq) {
722219820Sjeff		free(srq);
723219820Sjeff		return NULL;
724219820Sjeff	}
725219820Sjeff
726219820Sjeff	srq->context     = pd->context;
727219820Sjeff	srq->srq_context = srq_init_attr->srq_context;
728219820Sjeff	srq->pd          = pd;
729219820Sjeff	srq->real_srq    = real_srq;
730219820Sjeff
731219820Sjeff	real_srq->srq_context = srq;
732219820Sjeff
733219820Sjeff	return srq;
734219820Sjeff}
735219820Sjeffsymver(__ibv_create_srq_1_0, ibv_create_srq, IBVERBS_1.0);
736219820Sjeff
737219820Sjeffint __ibv_modify_srq_1_0(struct ibv_srq_1_0 *srq,
738219820Sjeff			 struct ibv_srq_attr *srq_attr,
739219820Sjeff			 int srq_attr_mask)
740219820Sjeff{
741219820Sjeff	return ibv_modify_srq(srq->real_srq, srq_attr, srq_attr_mask);
742219820Sjeff}
743219820Sjeffsymver(__ibv_modify_srq_1_0, ibv_modify_srq, IBVERBS_1.0);
744219820Sjeff
745219820Sjeffint __ibv_query_srq_1_0(struct ibv_srq_1_0 *srq, struct ibv_srq_attr *srq_attr)
746219820Sjeff{
747219820Sjeff	return ibv_query_srq(srq->real_srq, srq_attr);
748219820Sjeff}
749219820Sjeffsymver(__ibv_query_srq_1_0, ibv_query_srq, IBVERBS_1.0);
750219820Sjeff
751219820Sjeffint __ibv_destroy_srq_1_0(struct ibv_srq_1_0 *srq)
752219820Sjeff{
753219820Sjeff	int ret;
754219820Sjeff
755219820Sjeff	ret = ibv_destroy_srq(srq->real_srq);
756219820Sjeff	if (ret)
757219820Sjeff		return ret;
758219820Sjeff
759219820Sjeff	free(srq);
760219820Sjeff	return 0;
761219820Sjeff}
762219820Sjeffsymver(__ibv_destroy_srq_1_0, ibv_destroy_srq, IBVERBS_1.0);
763219820Sjeff
764219820Sjeffstruct ibv_qp_1_0 *__ibv_create_qp_1_0(struct ibv_pd_1_0 *pd,
765219820Sjeff				       struct ibv_qp_init_attr_1_0 *qp_init_attr)
766219820Sjeff{
767219820Sjeff	struct ibv_qp *real_qp;
768219820Sjeff	struct ibv_qp_1_0 *qp;
769219820Sjeff	struct ibv_qp_init_attr real_init_attr;
770219820Sjeff
771219820Sjeff	qp = malloc(sizeof *qp);
772219820Sjeff	if (!qp)
773219820Sjeff		return NULL;
774219820Sjeff
775219820Sjeff	real_init_attr.qp_context = qp_init_attr->qp_context;
776219820Sjeff	real_init_attr.send_cq    = qp_init_attr->send_cq->real_cq;
777219820Sjeff	real_init_attr.recv_cq    = qp_init_attr->recv_cq->real_cq;
778219820Sjeff	real_init_attr.srq        = qp_init_attr->srq ?
779219820Sjeff		qp_init_attr->srq->real_srq : NULL;
780219820Sjeff	real_init_attr.cap        = qp_init_attr->cap;
781219820Sjeff	real_init_attr.qp_type    = qp_init_attr->qp_type;
782219820Sjeff	real_init_attr.sq_sig_all = qp_init_attr->sq_sig_all;
783219820Sjeff
784219820Sjeff	real_qp = ibv_create_qp(pd->real_pd, &real_init_attr);
785219820Sjeff	if (!real_qp) {
786219820Sjeff		free(qp);
787219820Sjeff		return NULL;
788219820Sjeff	}
789219820Sjeff
790219820Sjeff	qp->context    = pd->context;
791219820Sjeff	qp->qp_context = qp_init_attr->qp_context;
792219820Sjeff	qp->pd         = pd;
793219820Sjeff	qp->send_cq    = qp_init_attr->send_cq;
794219820Sjeff	qp->recv_cq    = qp_init_attr->recv_cq;
795219820Sjeff	qp->srq        = qp_init_attr->srq;
796219820Sjeff	qp->qp_type    = qp_init_attr->qp_type;
797219820Sjeff	qp->qp_num     = real_qp->qp_num;
798219820Sjeff	qp->real_qp    = real_qp;
799219820Sjeff
800219820Sjeff	qp_init_attr->cap = real_init_attr.cap;
801219820Sjeff
802219820Sjeff	real_qp->qp_context = qp;
803219820Sjeff
804219820Sjeff	return qp;
805219820Sjeff}
806219820Sjeffsymver(__ibv_create_qp_1_0, ibv_create_qp, IBVERBS_1.0);
807219820Sjeff
808219820Sjeffint __ibv_query_qp_1_0(struct ibv_qp_1_0 *qp, struct ibv_qp_attr *attr,
809219820Sjeff		       int attr_mask,
810219820Sjeff		       struct ibv_qp_init_attr_1_0 *init_attr)
811219820Sjeff{
812219820Sjeff	struct ibv_qp_init_attr real_init_attr;
813219820Sjeff	int ret;
814219820Sjeff
815219820Sjeff	ret = ibv_query_qp(qp->real_qp, attr, attr_mask, &real_init_attr);
816219820Sjeff	if (ret)
817219820Sjeff		return ret;
818219820Sjeff
819219820Sjeff	init_attr->qp_context = qp->qp_context;
820219820Sjeff	init_attr->send_cq    = real_init_attr.send_cq->cq_context;
821219820Sjeff	init_attr->recv_cq    = real_init_attr.recv_cq->cq_context;
822219820Sjeff	init_attr->srq        = real_init_attr.srq->srq_context;
823219820Sjeff	init_attr->qp_type    = real_init_attr.qp_type;
824219820Sjeff	init_attr->cap        = real_init_attr.cap;
825219820Sjeff	init_attr->sq_sig_all = real_init_attr.sq_sig_all;
826219820Sjeff
827219820Sjeff	return 0;
828219820Sjeff}
829219820Sjeffsymver(__ibv_query_qp_1_0, ibv_query_qp, IBVERBS_1.0);
830219820Sjeff
831219820Sjeffint __ibv_modify_qp_1_0(struct ibv_qp_1_0 *qp, struct ibv_qp_attr *attr,
832219820Sjeff			int attr_mask)
833219820Sjeff{
834219820Sjeff	return ibv_modify_qp(qp->real_qp, attr, attr_mask);
835219820Sjeff}
836219820Sjeffsymver(__ibv_modify_qp_1_0, ibv_modify_qp, IBVERBS_1.0);
837219820Sjeff
838219820Sjeffint __ibv_destroy_qp_1_0(struct ibv_qp_1_0 *qp)
839219820Sjeff{
840219820Sjeff	int ret;
841219820Sjeff
842219820Sjeff	ret = ibv_destroy_qp(qp->real_qp);
843219820Sjeff	if (ret)
844219820Sjeff		return ret;
845219820Sjeff
846219820Sjeff	free(qp);
847219820Sjeff	return 0;
848219820Sjeff}
849219820Sjeffsymver(__ibv_destroy_qp_1_0, ibv_destroy_qp, IBVERBS_1.0);
850219820Sjeff
851219820Sjeffstruct ibv_ah_1_0 *__ibv_create_ah_1_0(struct ibv_pd_1_0 *pd,
852219820Sjeff				       struct ibv_ah_attr *attr)
853219820Sjeff{
854219820Sjeff	struct ibv_ah *real_ah;
855219820Sjeff	struct ibv_ah_1_0 *ah;
856219820Sjeff
857219820Sjeff	ah = malloc(sizeof *ah);
858219820Sjeff	if (!ah)
859219820Sjeff		return NULL;
860219820Sjeff
861219820Sjeff	real_ah = ibv_create_ah(pd->real_pd, attr);
862219820Sjeff	if (!real_ah) {
863219820Sjeff		free(ah);
864219820Sjeff		return NULL;
865219820Sjeff	}
866219820Sjeff
867219820Sjeff	ah->context = pd->context;
868219820Sjeff	ah->pd      = pd;
869219820Sjeff	ah->real_ah = real_ah;
870219820Sjeff
871219820Sjeff	return ah;
872219820Sjeff}
873219820Sjeffsymver(__ibv_create_ah_1_0, ibv_create_ah, IBVERBS_1.0);
874219820Sjeff
875219820Sjeffint __ibv_destroy_ah_1_0(struct ibv_ah_1_0 *ah)
876219820Sjeff{
877219820Sjeff	int ret;
878219820Sjeff
879219820Sjeff	ret = ibv_destroy_ah(ah->real_ah);
880219820Sjeff	if (ret)
881219820Sjeff		return ret;
882219820Sjeff
883219820Sjeff	free(ah);
884219820Sjeff	return 0;
885219820Sjeff}
886219820Sjeffsymver(__ibv_destroy_ah_1_0, ibv_destroy_ah, IBVERBS_1.0);
887219820Sjeff
888219820Sjeffint __ibv_attach_mcast_1_0(struct ibv_qp_1_0 *qp, union ibv_gid *gid, uint16_t lid)
889219820Sjeff{
890219820Sjeff	return ibv_attach_mcast(qp->real_qp, gid, lid);
891219820Sjeff}
892219820Sjeffsymver(__ibv_attach_mcast_1_0, ibv_attach_mcast, IBVERBS_1.0);
893219820Sjeff
894219820Sjeffint __ibv_detach_mcast_1_0(struct ibv_qp_1_0 *qp, union ibv_gid *gid, uint16_t lid)
895219820Sjeff{
896219820Sjeff	return ibv_detach_mcast(qp->real_qp, gid, lid);
897219820Sjeff}
898219820Sjeffsymver(__ibv_detach_mcast_1_0, ibv_detach_mcast, IBVERBS_1.0);
899