1/*
2 * Copyright (c) 2007 Cisco Systems, Inc.  All rights reserved.
3 *
4 * This software is available to you under a choice of one of two
5 * licenses.  You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 *     Redistribution and use in source and binary forms, with or
11 *     without modification, are permitted provided that the following
12 *     conditions are met:
13 *
14 *      - Redistributions of source code must retain the above
15 *        copyright notice, this list of conditions and the following
16 *        disclaimer.
17 *
18 *      - Redistributions in binary form must reproduce the above
19 *        copyright notice, this list of conditions and the following
20 *        disclaimer in the documentation and/or other materials
21 *        provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 */
32
33#if HAVE_CONFIG_H
34#  include <config.h>
35#endif /* HAVE_CONFIG_H */
36
37#include <string.h>
38#include <stddef.h>
39#include <stdlib.h>
40#include <unistd.h>
41#include <alloca.h>
42
43#include "ibverbs.h"
44
45struct ibv_pd_1_0 {
46	struct ibv_context_1_0 *context;
47	uint32_t		handle;
48
49	struct ibv_pd	       *real_pd;
50};
51
52struct ibv_mr_1_0 {
53	struct ibv_context_1_0 *context;
54	struct ibv_pd_1_0      *pd;
55	uint32_t		handle;
56	uint32_t		lkey;
57	uint32_t		rkey;
58
59	struct ibv_mr	       *real_mr;
60};
61
62struct ibv_srq_1_0 {
63	struct ibv_context_1_0 *context;
64	void		       *srq_context;
65	struct ibv_pd_1_0      *pd;
66	uint32_t		handle;
67
68	pthread_mutex_t		mutex;
69	pthread_cond_t		cond;
70	uint32_t		events_completed;
71
72	struct ibv_srq	       *real_srq;
73};
74
75struct ibv_qp_init_attr_1_0 {
76	void		       *qp_context;
77	struct ibv_cq_1_0      *send_cq;
78	struct ibv_cq_1_0      *recv_cq;
79	struct ibv_srq_1_0     *srq;
80	struct ibv_qp_cap	cap;
81	enum ibv_qp_type	qp_type;
82	int			sq_sig_all;
83};
84
85struct ibv_send_wr_1_0 {
86	struct ibv_send_wr_1_0 *next;
87	uint64_t		wr_id;
88	struct ibv_sge	       *sg_list;
89	int			num_sge;
90	enum ibv_wr_opcode	opcode;
91	int			send_flags;
92	uint32_t		imm_data;	/* in network byte order */
93	union {
94		struct {
95			uint64_t	remote_addr;
96			uint32_t	rkey;
97		} rdma;
98		struct {
99			uint64_t	remote_addr;
100			uint64_t	compare_add;
101			uint64_t	swap;
102			uint32_t	rkey;
103		} atomic;
104		struct {
105			struct ibv_ah_1_0 *ah;
106			uint32_t	remote_qpn;
107			uint32_t	remote_qkey;
108		} ud;
109	} wr;
110};
111
112struct ibv_recv_wr_1_0 {
113	struct ibv_recv_wr_1_0 *next;
114	uint64_t		wr_id;
115	struct ibv_sge	       *sg_list;
116	int			num_sge;
117};
118
119struct ibv_qp_1_0 {
120	struct ibv_context_1_0 *context;
121	void		       *qp_context;
122	struct ibv_pd_1_0      *pd;
123	struct ibv_cq_1_0      *send_cq;
124	struct ibv_cq_1_0      *recv_cq;
125	struct ibv_srq_1_0     *srq;
126	uint32_t		handle;
127	uint32_t		qp_num;
128	enum ibv_qp_state       state;
129	enum ibv_qp_type	qp_type;
130
131	pthread_mutex_t		mutex;
132	pthread_cond_t		cond;
133	uint32_t		events_completed;
134
135	struct ibv_qp	       *real_qp;
136};
137
138struct ibv_cq_1_0 {
139	struct ibv_context_1_0 *context;
140	void		       *cq_context;
141	uint32_t		handle;
142	int			cqe;
143
144	pthread_mutex_t		mutex;
145	pthread_cond_t		cond;
146	uint32_t		comp_events_completed;
147	uint32_t		async_events_completed;
148
149	struct ibv_cq	       *real_cq;
150};
151
152struct ibv_ah_1_0 {
153	struct ibv_context_1_0 *context;
154	struct ibv_pd_1_0      *pd;
155	uint32_t		handle;
156
157	struct ibv_ah	       *real_ah;
158};
159
160struct ibv_device_1_0 {
161	void		       *obsolete_sysfs_dev;
162	void		       *obsolete_sysfs_ibdev;
163	struct ibv_device      *real_device; /* was obsolete driver member */
164	struct ibv_device_ops	ops;
165};
166
167struct ibv_context_ops_1_0 {
168	int			(*query_device)(struct ibv_context *context,
169					      struct ibv_device_attr *device_attr);
170	int			(*query_port)(struct ibv_context *context, uint8_t port_num,
171					      struct ibv_port_attr *port_attr);
172	struct ibv_pd *		(*alloc_pd)(struct ibv_context *context);
173	int			(*dealloc_pd)(struct ibv_pd *pd);
174	struct ibv_mr *		(*reg_mr)(struct ibv_pd *pd, void *addr, size_t length,
175					  int access);
176	int			(*dereg_mr)(struct ibv_mr *mr);
177	struct ibv_cq *		(*create_cq)(struct ibv_context *context, int cqe,
178					     struct ibv_comp_channel *channel,
179					     int comp_vector);
180	int			(*poll_cq)(struct ibv_cq_1_0 *cq, int num_entries,
181					   struct ibv_wc *wc);
182	int			(*req_notify_cq)(struct ibv_cq_1_0 *cq,
183						 int solicited_only);
184	void			(*cq_event)(struct ibv_cq *cq);
185	int			(*resize_cq)(struct ibv_cq *cq, int cqe);
186	int			(*destroy_cq)(struct ibv_cq *cq);
187	struct ibv_srq *	(*create_srq)(struct ibv_pd *pd,
188					      struct ibv_srq_init_attr *srq_init_attr);
189	int			(*modify_srq)(struct ibv_srq *srq,
190					      struct ibv_srq_attr *srq_attr,
191					      int srq_attr_mask);
192	int			(*query_srq)(struct ibv_srq *srq,
193					     struct ibv_srq_attr *srq_attr);
194	int			(*destroy_srq)(struct ibv_srq *srq);
195	int			(*post_srq_recv)(struct ibv_srq_1_0 *srq,
196						 struct ibv_recv_wr_1_0 *recv_wr,
197						 struct ibv_recv_wr_1_0 **bad_recv_wr);
198	struct ibv_qp *		(*create_qp)(struct ibv_pd *pd, struct ibv_qp_init_attr *attr);
199	int			(*query_qp)(struct ibv_qp *qp, struct ibv_qp_attr *attr,
200					    int attr_mask,
201					    struct ibv_qp_init_attr *init_attr);
202	int			(*modify_qp)(struct ibv_qp *qp, struct ibv_qp_attr *attr,
203					     int attr_mask);
204	int			(*destroy_qp)(struct ibv_qp *qp);
205	int			(*post_send)(struct ibv_qp_1_0 *qp,
206					     struct ibv_send_wr_1_0 *wr,
207					     struct ibv_send_wr_1_0 **bad_wr);
208	int			(*post_recv)(struct ibv_qp_1_0 *qp,
209					     struct ibv_recv_wr_1_0 *wr,
210					     struct ibv_recv_wr_1_0 **bad_wr);
211	struct ibv_ah *		(*create_ah)(struct ibv_pd *pd, struct ibv_ah_attr *attr);
212	int			(*destroy_ah)(struct ibv_ah *ah);
213	int			(*attach_mcast)(struct ibv_qp *qp, union ibv_gid *gid,
214						uint16_t lid);
215	int			(*detach_mcast)(struct ibv_qp *qp, union ibv_gid *gid,
216						uint16_t lid);
217};
218
219struct ibv_context_1_0 {
220	struct ibv_device_1_0	       *device;
221	struct ibv_context_ops_1_0	ops;
222	int				cmd_fd;
223	int				async_fd;
224	int				num_comp_vectors;
225
226	struct ibv_context	       *real_context; /* was abi_compat member */
227};
228
229struct ibv_device_1_0 **__ibv_get_device_list_1_0(int *num)
230{
231	struct ibv_device **real_list;
232	struct ibv_device_1_0 **l;
233	int i, n;
234
235	real_list = ibv_get_device_list(&n);
236	if (!real_list)
237		return NULL;
238
239	l = calloc(n + 2, sizeof (struct ibv_device_1_0 *));
240	if (!l)
241		return NULL;
242
243	l[0] = (void *) real_list;
244
245	for (i = 0; i < n; ++i) {
246		l[i + 1] = calloc(1, sizeof (struct ibv_device_1_0));
247		if (!l[i + 1])
248			goto fail;
249		l[i + 1]->real_device = real_list[i];
250	}
251
252	if (num)
253		*num = n;
254
255	return l + 1;
256
257fail:
258	for (i = 1; i <= n; ++i)
259		if (l[i])
260			free(l[i]);
261	ibv_free_device_list(real_list);
262	return NULL;
263}
264symver(__ibv_get_device_list_1_0, ibv_get_device_list, IBVERBS_1.0);
265
266void __ibv_free_device_list_1_0(struct ibv_device_1_0 **list)
267{
268	struct ibv_device_1_0 **l = list;
269
270	while (*l) {
271		free(*l);
272		++l;
273	}
274
275	ibv_free_device_list((void *) list[-1]);
276	free(list - 1);
277}
278symver(__ibv_free_device_list_1_0, ibv_free_device_list, IBVERBS_1.0);
279
280const char *__ibv_get_device_name_1_0(struct ibv_device_1_0 *device)
281{
282	return ibv_get_device_name(device->real_device);
283}
284symver(__ibv_get_device_name_1_0, ibv_get_device_name, IBVERBS_1.0);
285
286uint64_t __ibv_get_device_guid_1_0(struct ibv_device_1_0 *device)
287{
288	return ibv_get_device_guid(device->real_device);
289}
290symver(__ibv_get_device_guid_1_0, ibv_get_device_guid, IBVERBS_1.0);
291
292static int poll_cq_wrapper_1_0(struct ibv_cq_1_0 *cq, int num_entries,
293			       struct ibv_wc *wc)
294{
295	return cq->context->real_context->ops.poll_cq(cq->real_cq, num_entries, wc);
296}
297
298static int req_notify_cq_wrapper_1_0(struct ibv_cq_1_0 *cq, int sol_only)
299{
300	return cq->context->real_context->ops.req_notify_cq(cq->real_cq, sol_only);
301}
302
303static int post_srq_recv_wrapper_1_0(struct ibv_srq_1_0 *srq, struct ibv_recv_wr_1_0 *wr,
304				 struct ibv_recv_wr_1_0 **bad_wr)
305{
306	struct ibv_recv_wr_1_0 *w;
307	struct ibv_recv_wr *real_wr, *head_wr = NULL, *tail_wr = NULL, *real_bad_wr;
308	int ret;
309
310	for (w = wr; w; w = w->next) {
311		real_wr = alloca(sizeof *real_wr);
312		real_wr->wr_id   = w->wr_id;
313		real_wr->sg_list = w->sg_list;
314		real_wr->num_sge = w->num_sge;
315		real_wr->next    = NULL;
316		if (tail_wr)
317			tail_wr->next = real_wr;
318		else
319			head_wr = real_wr;
320
321		tail_wr = real_wr;
322	}
323
324	ret = srq->context->real_context->ops.post_srq_recv(srq->real_srq, head_wr,
325							    &real_bad_wr);
326
327	if (ret) {
328		for (real_wr = head_wr, w = wr;
329		     real_wr;
330		     real_wr = real_wr->next, w = w->next)
331			if (real_wr == real_bad_wr) {
332				*bad_wr = w;
333				break;
334			}
335	}
336
337	return ret;
338}
339
340static int post_send_wrapper_1_0(struct ibv_qp_1_0 *qp, struct ibv_send_wr_1_0 *wr,
341				 struct ibv_send_wr_1_0 **bad_wr)
342{
343	struct ibv_send_wr_1_0 *w;
344	struct ibv_send_wr *real_wr, *head_wr = NULL, *tail_wr = NULL, *real_bad_wr;
345	int is_ud = qp->qp_type == IBV_QPT_UD;
346	int ret;
347
348	for (w = wr; w; w = w->next) {
349		real_wr = alloca(sizeof *real_wr);
350		real_wr->wr_id = w->wr_id;
351		real_wr->next  = NULL;
352
353		memcpy(&real_wr->sg_list, &w->sg_list,
354		       sizeof *w - offsetof(struct ibv_send_wr, sg_list));
355
356		if (is_ud)
357			real_wr->wr.ud.ah = w->wr.ud.ah->real_ah;
358
359		if (tail_wr)
360			tail_wr->next = real_wr;
361		else
362			head_wr = real_wr;
363
364		tail_wr = real_wr;
365	}
366
367	ret = qp->context->real_context->ops.post_send(qp->real_qp, head_wr,
368						       &real_bad_wr);
369
370	if (ret) {
371		for (real_wr = head_wr, w = wr;
372		     real_wr;
373		     real_wr = real_wr->next, w = w->next)
374			if (real_wr == real_bad_wr) {
375				*bad_wr = w;
376				break;
377			}
378	}
379
380	return ret;
381}
382
383static int post_recv_wrapper_1_0(struct ibv_qp_1_0 *qp, struct ibv_recv_wr_1_0 *wr,
384				 struct ibv_recv_wr_1_0 **bad_wr)
385{
386	struct ibv_recv_wr_1_0 *w;
387	struct ibv_recv_wr *real_wr, *head_wr = NULL, *tail_wr = NULL, *real_bad_wr;
388	int ret;
389
390	for (w = wr; w; w = w->next) {
391		real_wr = alloca(sizeof *real_wr);
392		real_wr->wr_id   = w->wr_id;
393		real_wr->sg_list = w->sg_list;
394		real_wr->num_sge = w->num_sge;
395		real_wr->next    = NULL;
396		if (tail_wr)
397			tail_wr->next = real_wr;
398		else
399			head_wr = real_wr;
400
401		tail_wr = real_wr;
402	}
403
404	ret = qp->context->real_context->ops.post_recv(qp->real_qp, head_wr,
405						       &real_bad_wr);
406
407	if (ret) {
408		for (real_wr = head_wr, w = wr;
409		     real_wr;
410		     real_wr = real_wr->next, w = w->next)
411			if (real_wr == real_bad_wr) {
412				*bad_wr = w;
413				break;
414			}
415	}
416
417	return ret;
418}
419
420struct ibv_context_1_0 *__ibv_open_device_1_0(struct ibv_device_1_0 *device)
421{
422	struct ibv_context     *real_ctx;
423	struct ibv_context_1_0 *ctx;
424
425	ctx = malloc(sizeof *ctx);
426	if (!ctx)
427		return NULL;
428
429	real_ctx = ibv_open_device(device->real_device);
430	if (!real_ctx) {
431		free(ctx);
432		return NULL;
433	}
434
435	ctx->device       = device;
436	ctx->real_context = real_ctx;
437
438	ctx->ops.poll_cq       = poll_cq_wrapper_1_0;
439	ctx->ops.req_notify_cq = req_notify_cq_wrapper_1_0;
440	ctx->ops.post_send     = post_send_wrapper_1_0;
441	ctx->ops.post_recv     = post_recv_wrapper_1_0;
442	ctx->ops.post_srq_recv = post_srq_recv_wrapper_1_0;
443
444	return ctx;
445}
446symver(__ibv_open_device_1_0, ibv_open_device, IBVERBS_1.0);
447
448int __ibv_close_device_1_0(struct ibv_context_1_0 *context)
449{
450	int ret;
451
452	ret = ibv_close_device(context->real_context);
453	if (ret)
454		return ret;
455
456	free(context);
457	return 0;
458}
459symver(__ibv_close_device_1_0, ibv_close_device, IBVERBS_1.0);
460
461int __ibv_get_async_event_1_0(struct ibv_context_1_0 *context,
462			      struct ibv_async_event *event)
463{
464	int ret;
465
466	ret = ibv_get_async_event(context->real_context, event);
467	if (ret)
468		return ret;
469
470	switch (event->event_type) {
471	case IBV_EVENT_CQ_ERR:
472		event->element.cq = event->element.cq->cq_context;
473		break;
474
475	case IBV_EVENT_QP_FATAL:
476	case IBV_EVENT_QP_REQ_ERR:
477	case IBV_EVENT_QP_ACCESS_ERR:
478	case IBV_EVENT_COMM_EST:
479	case IBV_EVENT_SQ_DRAINED:
480	case IBV_EVENT_PATH_MIG:
481	case IBV_EVENT_PATH_MIG_ERR:
482	case IBV_EVENT_QP_LAST_WQE_REACHED:
483		event->element.qp = event->element.qp->qp_context;
484		break;
485
486	case IBV_EVENT_SRQ_ERR:
487	case IBV_EVENT_SRQ_LIMIT_REACHED:
488		event->element.srq = event->element.srq->srq_context;
489		break;
490
491	default:
492		break;
493	}
494
495	return ret;
496}
497symver(__ibv_get_async_event_1_0, ibv_get_async_event, IBVERBS_1.0);
498
499void __ibv_ack_async_event_1_0(struct ibv_async_event *event)
500{
501	struct ibv_async_event real_event = *event;
502
503	switch (event->event_type) {
504	case IBV_EVENT_CQ_ERR:
505		real_event.element.cq =
506			((struct ibv_cq_1_0 *) event->element.cq)->real_cq;
507		break;
508
509	case IBV_EVENT_QP_FATAL:
510	case IBV_EVENT_QP_REQ_ERR:
511	case IBV_EVENT_QP_ACCESS_ERR:
512	case IBV_EVENT_COMM_EST:
513	case IBV_EVENT_SQ_DRAINED:
514	case IBV_EVENT_PATH_MIG:
515	case IBV_EVENT_PATH_MIG_ERR:
516	case IBV_EVENT_QP_LAST_WQE_REACHED:
517		real_event.element.qp =
518			((struct ibv_qp_1_0 *) event->element.qp)->real_qp;
519		break;
520
521	case IBV_EVENT_SRQ_ERR:
522	case IBV_EVENT_SRQ_LIMIT_REACHED:
523		real_event.element.srq =
524			((struct ibv_srq_1_0 *) event->element.srq)->real_srq;
525		break;
526
527	default:
528		break;
529	}
530
531	ibv_ack_async_event(&real_event);
532}
533symver(__ibv_ack_async_event_1_0, ibv_ack_async_event, IBVERBS_1.0);
534
535int __ibv_query_device_1_0(struct ibv_context_1_0 *context,
536			   struct ibv_device_attr *device_attr)
537{
538	return ibv_query_device(context->real_context, device_attr);
539}
540symver(__ibv_query_device_1_0, ibv_query_device, IBVERBS_1.0);
541
542int __ibv_query_port_1_0(struct ibv_context_1_0 *context, uint8_t port_num,
543			 struct ibv_port_attr *port_attr)
544{
545	return ibv_query_port(context->real_context, port_num, port_attr);
546}
547symver(__ibv_query_port_1_0, ibv_query_port, IBVERBS_1.0);
548
549int __ibv_query_gid_1_0(struct ibv_context_1_0 *context, uint8_t port_num,
550			int index, union ibv_gid *gid)
551{
552	return ibv_query_gid(context->real_context, port_num, index, gid);
553}
554symver(__ibv_query_gid_1_0, ibv_query_gid, IBVERBS_1.0);
555
556int __ibv_query_pkey_1_0(struct ibv_context_1_0 *context, uint8_t port_num,
557			 int index, uint16_t *pkey)
558{
559	return ibv_query_pkey(context->real_context, port_num, index, pkey);
560}
561symver(__ibv_query_pkey_1_0, ibv_query_pkey, IBVERBS_1.0);
562
563struct ibv_pd_1_0 *__ibv_alloc_pd_1_0(struct ibv_context_1_0 *context)
564{
565	struct ibv_pd *real_pd;
566	struct ibv_pd_1_0 *pd;
567
568	pd = malloc(sizeof *pd);
569	if (!pd)
570		return NULL;
571
572	real_pd = ibv_alloc_pd(context->real_context);
573	if (!real_pd) {
574		free(pd);
575		return NULL;
576	}
577
578	pd->context = context;
579	pd->real_pd = real_pd;
580
581	return pd;
582}
583symver(__ibv_alloc_pd_1_0, ibv_alloc_pd, IBVERBS_1.0);
584
585int __ibv_dealloc_pd_1_0(struct ibv_pd_1_0 *pd)
586{
587	int ret;
588
589	ret = ibv_dealloc_pd(pd->real_pd);
590	if (ret)
591		return ret;
592
593	free(pd);
594	return 0;
595}
596symver(__ibv_dealloc_pd_1_0, ibv_dealloc_pd, IBVERBS_1.0);
597
598struct ibv_mr_1_0 *__ibv_reg_mr_1_0(struct ibv_pd_1_0 *pd, void *addr,
599				    size_t length, int access)
600{
601	struct ibv_mr *real_mr;
602	struct ibv_mr_1_0 *mr;
603
604	mr = malloc(sizeof *mr);
605	if (!mr)
606		return NULL;
607
608	real_mr = ibv_reg_mr(pd->real_pd, addr, length, access);
609	if (!real_mr) {
610		free(mr);
611		return NULL;
612	}
613
614	mr->context = pd->context;
615	mr->pd      = pd;
616	mr->lkey    = real_mr->lkey;
617	mr->rkey    = real_mr->rkey;
618	mr->real_mr = real_mr;
619
620	return mr;
621}
622symver(__ibv_reg_mr_1_0, ibv_reg_mr, IBVERBS_1.0);
623
624int __ibv_dereg_mr_1_0(struct ibv_mr_1_0 *mr)
625{
626	int ret;
627
628	ret = ibv_dereg_mr(mr->real_mr);
629	if (ret)
630		return ret;
631
632	free(mr);
633	return 0;
634}
635symver(__ibv_dereg_mr_1_0, ibv_dereg_mr, IBVERBS_1.0);
636
637struct ibv_cq_1_0 *__ibv_create_cq_1_0(struct ibv_context_1_0 *context, int cqe,
638				       void *cq_context,
639				       struct ibv_comp_channel *channel,
640				       int comp_vector)
641{
642	struct ibv_cq *real_cq;
643	struct ibv_cq_1_0 *cq;
644
645	cq = malloc(sizeof *cq);
646	if (!cq)
647		return NULL;
648
649	real_cq = ibv_create_cq(context->real_context, cqe, cq_context,
650				channel, comp_vector);
651	if (!real_cq) {
652		free(cq);
653		return NULL;
654	}
655
656	cq->context    = context;
657	cq->cq_context = cq_context;
658	cq->cqe        = cqe;
659	cq->real_cq    = real_cq;
660
661	real_cq->cq_context = cq;
662
663	return cq;
664}
665symver(__ibv_create_cq_1_0, ibv_create_cq, IBVERBS_1.0);
666
667int __ibv_resize_cq_1_0(struct ibv_cq_1_0 *cq, int cqe)
668{
669	return ibv_resize_cq(cq->real_cq, cqe);
670}
671symver(__ibv_resize_cq_1_0, ibv_resize_cq, IBVERBS_1.0);
672
673int __ibv_destroy_cq_1_0(struct ibv_cq_1_0 *cq)
674{
675	int ret;
676
677	ret = ibv_destroy_cq(cq->real_cq);
678	if (ret)
679		return ret;
680
681	free(cq);
682	return 0;
683}
684symver(__ibv_destroy_cq_1_0, ibv_destroy_cq, IBVERBS_1.0);
685
686int __ibv_get_cq_event_1_0(struct ibv_comp_channel *channel,
687			   struct ibv_cq_1_0 **cq, void **cq_context)
688{
689	struct ibv_cq *real_cq;
690	void *cq_ptr;
691	int ret;
692
693	ret = ibv_get_cq_event(channel, &real_cq, &cq_ptr);
694	if (ret)
695		return ret;
696
697	*cq         = cq_ptr;
698	*cq_context = (*cq)->cq_context;
699
700	return 0;
701}
702symver(__ibv_get_cq_event_1_0, ibv_get_cq_event, IBVERBS_1.0);
703
704void __ibv_ack_cq_events_1_0(struct ibv_cq_1_0 *cq, unsigned int nevents)
705{
706	ibv_ack_cq_events(cq->real_cq, nevents);
707}
708symver(__ibv_ack_cq_events_1_0, ibv_ack_cq_events, IBVERBS_1.0);
709
710struct ibv_srq_1_0 *__ibv_create_srq_1_0(struct ibv_pd_1_0 *pd,
711					 struct ibv_srq_init_attr *srq_init_attr)
712{
713	struct ibv_srq *real_srq;
714	struct ibv_srq_1_0 *srq;
715
716	srq = malloc(sizeof *srq);
717	if (!srq)
718		return NULL;
719
720	real_srq = ibv_create_srq(pd->real_pd, srq_init_attr);
721	if (!real_srq) {
722		free(srq);
723		return NULL;
724	}
725
726	srq->context     = pd->context;
727	srq->srq_context = srq_init_attr->srq_context;
728	srq->pd          = pd;
729	srq->real_srq    = real_srq;
730
731	real_srq->srq_context = srq;
732
733	return srq;
734}
735symver(__ibv_create_srq_1_0, ibv_create_srq, IBVERBS_1.0);
736
737int __ibv_modify_srq_1_0(struct ibv_srq_1_0 *srq,
738			 struct ibv_srq_attr *srq_attr,
739			 int srq_attr_mask)
740{
741	return ibv_modify_srq(srq->real_srq, srq_attr, srq_attr_mask);
742}
743symver(__ibv_modify_srq_1_0, ibv_modify_srq, IBVERBS_1.0);
744
745int __ibv_query_srq_1_0(struct ibv_srq_1_0 *srq, struct ibv_srq_attr *srq_attr)
746{
747	return ibv_query_srq(srq->real_srq, srq_attr);
748}
749symver(__ibv_query_srq_1_0, ibv_query_srq, IBVERBS_1.0);
750
751int __ibv_destroy_srq_1_0(struct ibv_srq_1_0 *srq)
752{
753	int ret;
754
755	ret = ibv_destroy_srq(srq->real_srq);
756	if (ret)
757		return ret;
758
759	free(srq);
760	return 0;
761}
762symver(__ibv_destroy_srq_1_0, ibv_destroy_srq, IBVERBS_1.0);
763
764struct ibv_qp_1_0 *__ibv_create_qp_1_0(struct ibv_pd_1_0 *pd,
765				       struct ibv_qp_init_attr_1_0 *qp_init_attr)
766{
767	struct ibv_qp *real_qp;
768	struct ibv_qp_1_0 *qp;
769	struct ibv_qp_init_attr real_init_attr;
770
771	qp = malloc(sizeof *qp);
772	if (!qp)
773		return NULL;
774
775	real_init_attr.qp_context = qp_init_attr->qp_context;
776	real_init_attr.send_cq    = qp_init_attr->send_cq->real_cq;
777	real_init_attr.recv_cq    = qp_init_attr->recv_cq->real_cq;
778	real_init_attr.srq        = qp_init_attr->srq ?
779		qp_init_attr->srq->real_srq : NULL;
780	real_init_attr.cap        = qp_init_attr->cap;
781	real_init_attr.qp_type    = qp_init_attr->qp_type;
782	real_init_attr.sq_sig_all = qp_init_attr->sq_sig_all;
783
784	real_qp = ibv_create_qp(pd->real_pd, &real_init_attr);
785	if (!real_qp) {
786		free(qp);
787		return NULL;
788	}
789
790	qp->context    = pd->context;
791	qp->qp_context = qp_init_attr->qp_context;
792	qp->pd         = pd;
793	qp->send_cq    = qp_init_attr->send_cq;
794	qp->recv_cq    = qp_init_attr->recv_cq;
795	qp->srq        = qp_init_attr->srq;
796	qp->qp_type    = qp_init_attr->qp_type;
797	qp->qp_num     = real_qp->qp_num;
798	qp->real_qp    = real_qp;
799
800	qp_init_attr->cap = real_init_attr.cap;
801
802	real_qp->qp_context = qp;
803
804	return qp;
805}
806symver(__ibv_create_qp_1_0, ibv_create_qp, IBVERBS_1.0);
807
808int __ibv_query_qp_1_0(struct ibv_qp_1_0 *qp, struct ibv_qp_attr *attr,
809		       int attr_mask,
810		       struct ibv_qp_init_attr_1_0 *init_attr)
811{
812	struct ibv_qp_init_attr real_init_attr;
813	int ret;
814
815	ret = ibv_query_qp(qp->real_qp, attr, attr_mask, &real_init_attr);
816	if (ret)
817		return ret;
818
819	init_attr->qp_context = qp->qp_context;
820	init_attr->send_cq    = real_init_attr.send_cq->cq_context;
821	init_attr->recv_cq    = real_init_attr.recv_cq->cq_context;
822	init_attr->srq        = real_init_attr.srq->srq_context;
823	init_attr->qp_type    = real_init_attr.qp_type;
824	init_attr->cap        = real_init_attr.cap;
825	init_attr->sq_sig_all = real_init_attr.sq_sig_all;
826
827	return 0;
828}
829symver(__ibv_query_qp_1_0, ibv_query_qp, IBVERBS_1.0);
830
831int __ibv_modify_qp_1_0(struct ibv_qp_1_0 *qp, struct ibv_qp_attr *attr,
832			int attr_mask)
833{
834	return ibv_modify_qp(qp->real_qp, attr, attr_mask);
835}
836symver(__ibv_modify_qp_1_0, ibv_modify_qp, IBVERBS_1.0);
837
838int __ibv_destroy_qp_1_0(struct ibv_qp_1_0 *qp)
839{
840	int ret;
841
842	ret = ibv_destroy_qp(qp->real_qp);
843	if (ret)
844		return ret;
845
846	free(qp);
847	return 0;
848}
849symver(__ibv_destroy_qp_1_0, ibv_destroy_qp, IBVERBS_1.0);
850
851struct ibv_ah_1_0 *__ibv_create_ah_1_0(struct ibv_pd_1_0 *pd,
852				       struct ibv_ah_attr *attr)
853{
854	struct ibv_ah *real_ah;
855	struct ibv_ah_1_0 *ah;
856
857	ah = malloc(sizeof *ah);
858	if (!ah)
859		return NULL;
860
861	real_ah = ibv_create_ah(pd->real_pd, attr);
862	if (!real_ah) {
863		free(ah);
864		return NULL;
865	}
866
867	ah->context = pd->context;
868	ah->pd      = pd;
869	ah->real_ah = real_ah;
870
871	return ah;
872}
873symver(__ibv_create_ah_1_0, ibv_create_ah, IBVERBS_1.0);
874
875int __ibv_destroy_ah_1_0(struct ibv_ah_1_0 *ah)
876{
877	int ret;
878
879	ret = ibv_destroy_ah(ah->real_ah);
880	if (ret)
881		return ret;
882
883	free(ah);
884	return 0;
885}
886symver(__ibv_destroy_ah_1_0, ibv_destroy_ah, IBVERBS_1.0);
887
888int __ibv_attach_mcast_1_0(struct ibv_qp_1_0 *qp, union ibv_gid *gid, uint16_t lid)
889{
890	return ibv_attach_mcast(qp->real_qp, gid, lid);
891}
892symver(__ibv_attach_mcast_1_0, ibv_attach_mcast, IBVERBS_1.0);
893
894int __ibv_detach_mcast_1_0(struct ibv_qp_1_0 *qp, union ibv_gid *gid, uint16_t lid)
895{
896	return ibv_detach_mcast(qp->real_qp, gid, lid);
897}
898symver(__ibv_detach_mcast_1_0, ibv_detach_mcast, IBVERBS_1.0);
899