compat-1_0.c revision 331769
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#include <config.h>
34
35#include <string.h>
36#include <stddef.h>
37#include <stdlib.h>
38#include <unistd.h>
39#include <alloca.h>
40
41#include "ibverbs.h"
42
43struct ibv_pd_1_0 {
44	struct ibv_context_1_0 *context;
45	uint32_t		handle;
46
47	struct ibv_pd	       *real_pd;
48};
49
50struct ibv_mr_1_0 {
51	struct ibv_context_1_0 *context;
52	struct ibv_pd_1_0      *pd;
53	uint32_t		handle;
54	uint32_t		lkey;
55	uint32_t		rkey;
56
57	struct ibv_mr	       *real_mr;
58};
59
60struct ibv_srq_1_0 {
61	struct ibv_context_1_0 *context;
62	void		       *srq_context;
63	struct ibv_pd_1_0      *pd;
64	uint32_t		handle;
65
66	pthread_mutex_t		mutex;
67	pthread_cond_t		cond;
68	uint32_t		events_completed;
69
70	struct ibv_srq	       *real_srq;
71};
72
73struct ibv_qp_init_attr_1_0 {
74	void		       *qp_context;
75	struct ibv_cq_1_0      *send_cq;
76	struct ibv_cq_1_0      *recv_cq;
77	struct ibv_srq_1_0     *srq;
78	struct ibv_qp_cap	cap;
79	enum ibv_qp_type	qp_type;
80	int			sq_sig_all;
81};
82
83struct ibv_send_wr_1_0 {
84	struct ibv_send_wr_1_0 *next;
85	uint64_t		wr_id;
86	struct ibv_sge	       *sg_list;
87	int			num_sge;
88	enum ibv_wr_opcode	opcode;
89	int			send_flags;
90	__be32			imm_data;
91	union {
92		struct {
93			uint64_t	remote_addr;
94			uint32_t	rkey;
95		} rdma;
96		struct {
97			uint64_t	remote_addr;
98			uint64_t	compare_add;
99			uint64_t	swap;
100			uint32_t	rkey;
101		} atomic;
102		struct {
103			struct ibv_ah_1_0 *ah;
104			uint32_t	remote_qpn;
105			uint32_t	remote_qkey;
106		} ud;
107	} wr;
108};
109
110struct ibv_recv_wr_1_0 {
111	struct ibv_recv_wr_1_0 *next;
112	uint64_t		wr_id;
113	struct ibv_sge	       *sg_list;
114	int			num_sge;
115};
116
117struct ibv_qp_1_0 {
118	struct ibv_context_1_0 *context;
119	void		       *qp_context;
120	struct ibv_pd_1_0      *pd;
121	struct ibv_cq_1_0      *send_cq;
122	struct ibv_cq_1_0      *recv_cq;
123	struct ibv_srq_1_0     *srq;
124	uint32_t		handle;
125	uint32_t		qp_num;
126	enum ibv_qp_state       state;
127	enum ibv_qp_type	qp_type;
128
129	pthread_mutex_t		mutex;
130	pthread_cond_t		cond;
131	uint32_t		events_completed;
132
133	struct ibv_qp	       *real_qp;
134};
135
136struct ibv_cq_1_0 {
137	struct ibv_context_1_0 *context;
138	void		       *cq_context;
139	uint32_t		handle;
140	int			cqe;
141
142	pthread_mutex_t		mutex;
143	pthread_cond_t		cond;
144	uint32_t		comp_events_completed;
145	uint32_t		async_events_completed;
146
147	struct ibv_cq	       *real_cq;
148};
149
150struct ibv_ah_1_0 {
151	struct ibv_context_1_0 *context;
152	struct ibv_pd_1_0      *pd;
153	uint32_t		handle;
154
155	struct ibv_ah	       *real_ah;
156};
157
158struct ibv_device_1_0 {
159	void		       *obsolete_sysfs_dev;
160	void		       *obsolete_sysfs_ibdev;
161	struct ibv_device      *real_device; /* was obsolete driver member */
162	struct _ibv_device_ops	_ops;
163};
164
165struct ibv_context_ops_1_0 {
166	int			(*query_device)(struct ibv_context *context,
167					      struct ibv_device_attr *device_attr);
168	int			(*query_port)(struct ibv_context *context, uint8_t port_num,
169					      struct ibv_port_attr *port_attr);
170	struct ibv_pd *		(*alloc_pd)(struct ibv_context *context);
171	int			(*dealloc_pd)(struct ibv_pd *pd);
172	struct ibv_mr *		(*reg_mr)(struct ibv_pd *pd, void *addr, size_t length,
173					  int access);
174	int			(*dereg_mr)(struct ibv_mr *mr);
175	struct ibv_cq *		(*create_cq)(struct ibv_context *context, int cqe,
176					     struct ibv_comp_channel *channel,
177					     int comp_vector);
178	int			(*poll_cq)(struct ibv_cq_1_0 *cq, int num_entries,
179					   struct ibv_wc *wc);
180	int			(*req_notify_cq)(struct ibv_cq_1_0 *cq,
181						 int solicited_only);
182	void			(*cq_event)(struct ibv_cq *cq);
183	int			(*resize_cq)(struct ibv_cq *cq, int cqe);
184	int			(*destroy_cq)(struct ibv_cq *cq);
185	struct ibv_srq *	(*create_srq)(struct ibv_pd *pd,
186					      struct ibv_srq_init_attr *srq_init_attr);
187	int			(*modify_srq)(struct ibv_srq *srq,
188					      struct ibv_srq_attr *srq_attr,
189					      int srq_attr_mask);
190	int			(*query_srq)(struct ibv_srq *srq,
191					     struct ibv_srq_attr *srq_attr);
192	int			(*destroy_srq)(struct ibv_srq *srq);
193	int			(*post_srq_recv)(struct ibv_srq_1_0 *srq,
194						 struct ibv_recv_wr_1_0 *recv_wr,
195						 struct ibv_recv_wr_1_0 **bad_recv_wr);
196	struct ibv_qp *		(*create_qp)(struct ibv_pd *pd, struct ibv_qp_init_attr *attr);
197	int			(*query_qp)(struct ibv_qp *qp, struct ibv_qp_attr *attr,
198					    int attr_mask,
199					    struct ibv_qp_init_attr *init_attr);
200	int			(*modify_qp)(struct ibv_qp *qp, struct ibv_qp_attr *attr,
201					     int attr_mask);
202	int			(*destroy_qp)(struct ibv_qp *qp);
203	int			(*post_send)(struct ibv_qp_1_0 *qp,
204					     struct ibv_send_wr_1_0 *wr,
205					     struct ibv_send_wr_1_0 **bad_wr);
206	int			(*post_recv)(struct ibv_qp_1_0 *qp,
207					     struct ibv_recv_wr_1_0 *wr,
208					     struct ibv_recv_wr_1_0 **bad_wr);
209	struct ibv_ah *		(*create_ah)(struct ibv_pd *pd, struct ibv_ah_attr *attr);
210	int			(*destroy_ah)(struct ibv_ah *ah);
211	int			(*attach_mcast)(struct ibv_qp *qp, union ibv_gid *gid,
212						uint16_t lid);
213	int			(*detach_mcast)(struct ibv_qp *qp, union ibv_gid *gid,
214						uint16_t lid);
215};
216
217struct ibv_context_1_0 {
218	struct ibv_device_1_0	       *device;
219	struct ibv_context_ops_1_0	ops;
220	int				cmd_fd;
221	int				async_fd;
222	int				num_comp_vectors;
223
224	struct ibv_context	       *real_context; /* was abi_compat member */
225};
226
227typedef struct ibv_device *(*ibv_driver_init_func_1_1)(const char *uverbs_sys_path,
228						       int abi_version);
229
230/* Hack to avoid GCC's -Wmissing-prototypes and the similar error from sparse
231   with these prototypes. Symbol versionining requires the goofy names, the
232   prototype must match the version in the historical 1.0 verbs.h.
233 */
234struct ibv_device_1_0 **__ibv_get_device_list_1_0(int *num);
235void __ibv_free_device_list_1_0(struct ibv_device_1_0 **list);
236const char *__ibv_get_device_name_1_0(struct ibv_device_1_0 *device);
237__be64 __ibv_get_device_guid_1_0(struct ibv_device_1_0 *device);
238struct ibv_context_1_0 *__ibv_open_device_1_0(struct ibv_device_1_0 *device);
239int __ibv_close_device_1_0(struct ibv_context_1_0 *context);
240int __ibv_get_async_event_1_0(struct ibv_context_1_0 *context,
241			      struct ibv_async_event *event);
242void __ibv_ack_async_event_1_0(struct ibv_async_event *event);
243int __ibv_query_device_1_0(struct ibv_context_1_0 *context,
244			   struct ibv_device_attr *device_attr);
245int __ibv_query_port_1_0(struct ibv_context_1_0 *context, uint8_t port_num,
246			 struct ibv_port_attr *port_attr);
247int __ibv_query_gid_1_0(struct ibv_context_1_0 *context, uint8_t port_num,
248			int index, union ibv_gid *gid);
249int __ibv_query_pkey_1_0(struct ibv_context_1_0 *context, uint8_t port_num,
250			 int index, __be16 *pkey);
251struct ibv_pd_1_0 *__ibv_alloc_pd_1_0(struct ibv_context_1_0 *context);
252int __ibv_dealloc_pd_1_0(struct ibv_pd_1_0 *pd);
253struct ibv_mr_1_0 *__ibv_reg_mr_1_0(struct ibv_pd_1_0 *pd, void *addr,
254				    size_t length, int access);
255int __ibv_dereg_mr_1_0(struct ibv_mr_1_0 *mr);
256struct ibv_cq_1_0 *__ibv_create_cq_1_0(struct ibv_context_1_0 *context, int cqe,
257				       void *cq_context,
258				       struct ibv_comp_channel *channel,
259				       int comp_vector);
260int __ibv_resize_cq_1_0(struct ibv_cq_1_0 *cq, int cqe);
261int __ibv_destroy_cq_1_0(struct ibv_cq_1_0 *cq);
262int __ibv_get_cq_event_1_0(struct ibv_comp_channel *channel,
263			   struct ibv_cq_1_0 **cq, void **cq_context);
264void __ibv_ack_cq_events_1_0(struct ibv_cq_1_0 *cq, unsigned int nevents);
265struct ibv_srq_1_0 *
266__ibv_create_srq_1_0(struct ibv_pd_1_0 *pd,
267		     struct ibv_srq_init_attr *srq_init_attr);
268int __ibv_modify_srq_1_0(struct ibv_srq_1_0 *srq, struct ibv_srq_attr *srq_attr,
269			 int srq_attr_mask);
270int __ibv_query_srq_1_0(struct ibv_srq_1_0 *srq, struct ibv_srq_attr *srq_attr);
271int __ibv_destroy_srq_1_0(struct ibv_srq_1_0 *srq);
272struct ibv_qp_1_0 *
273__ibv_create_qp_1_0(struct ibv_pd_1_0 *pd,
274		    struct ibv_qp_init_attr_1_0 *qp_init_attr);
275int __ibv_query_qp_1_0(struct ibv_qp_1_0 *qp, struct ibv_qp_attr *attr,
276		       int attr_mask, struct ibv_qp_init_attr_1_0 *init_attr);
277int __ibv_modify_qp_1_0(struct ibv_qp_1_0 *qp, struct ibv_qp_attr *attr,
278			int attr_mask);
279int __ibv_destroy_qp_1_0(struct ibv_qp_1_0 *qp);
280struct ibv_ah_1_0 *__ibv_create_ah_1_0(struct ibv_pd_1_0 *pd,
281				       struct ibv_ah_attr *attr);
282int __ibv_destroy_ah_1_0(struct ibv_ah_1_0 *ah);
283int __ibv_attach_mcast_1_0(struct ibv_qp_1_0 *qp, union ibv_gid *gid,
284			   uint16_t lid);
285int __ibv_detach_mcast_1_0(struct ibv_qp_1_0 *qp, union ibv_gid *gid,
286			   uint16_t lid);
287void __ibv_register_driver_1_1(const char *name,
288			       ibv_driver_init_func_1_1 init_func);
289
290struct ibv_device_1_0 **__ibv_get_device_list_1_0(int *num)
291{
292	struct ibv_device **real_list;
293	struct ibv_device_1_0 **l;
294	int i, n;
295
296	real_list = ibv_get_device_list(&n);
297	if (!real_list)
298		return NULL;
299
300	l = calloc(n + 2, sizeof (struct ibv_device_1_0 *));
301	if (!l)
302		goto free_device_list;
303
304	l[0] = (void *) real_list;
305
306	for (i = 0; i < n; ++i) {
307		l[i + 1] = calloc(1, sizeof (struct ibv_device_1_0));
308		if (!l[i + 1])
309			goto fail;
310		l[i + 1]->real_device = real_list[i];
311	}
312
313	if (num)
314		*num = n;
315
316	return l + 1;
317
318fail:
319	for (i = 1; i <= n; ++i)
320		if (l[i])
321			free(l[i]);
322	free(l);
323
324free_device_list:
325	ibv_free_device_list(real_list);
326	return NULL;
327}
328symver(__ibv_get_device_list_1_0, ibv_get_device_list, IBVERBS_1.0);
329
330void __ibv_free_device_list_1_0(struct ibv_device_1_0 **list)
331{
332	struct ibv_device_1_0 **l = list;
333
334	while (*l) {
335		free(*l);
336		++l;
337	}
338
339	ibv_free_device_list((void *) list[-1]);
340	free(list - 1);
341}
342symver(__ibv_free_device_list_1_0, ibv_free_device_list, IBVERBS_1.0);
343
344const char *__ibv_get_device_name_1_0(struct ibv_device_1_0 *device)
345{
346	return ibv_get_device_name(device->real_device);
347}
348symver(__ibv_get_device_name_1_0, ibv_get_device_name, IBVERBS_1.0);
349
350__be64 __ibv_get_device_guid_1_0(struct ibv_device_1_0 *device)
351{
352	return ibv_get_device_guid(device->real_device);
353}
354symver(__ibv_get_device_guid_1_0, ibv_get_device_guid, IBVERBS_1.0);
355
356static int poll_cq_wrapper_1_0(struct ibv_cq_1_0 *cq, int num_entries,
357			       struct ibv_wc *wc)
358{
359	return cq->context->real_context->ops.poll_cq(cq->real_cq, num_entries, wc);
360}
361
362static int req_notify_cq_wrapper_1_0(struct ibv_cq_1_0 *cq, int sol_only)
363{
364	return cq->context->real_context->ops.req_notify_cq(cq->real_cq, sol_only);
365}
366
367static int post_srq_recv_wrapper_1_0(struct ibv_srq_1_0 *srq, struct ibv_recv_wr_1_0 *wr,
368				 struct ibv_recv_wr_1_0 **bad_wr)
369{
370	struct ibv_recv_wr_1_0 *w;
371	struct ibv_recv_wr *real_wr, *head_wr = NULL, *tail_wr = NULL, *real_bad_wr;
372	int ret;
373
374	for (w = wr; w; w = w->next) {
375		real_wr = alloca(sizeof *real_wr);
376		real_wr->wr_id   = w->wr_id;
377		real_wr->sg_list = w->sg_list;
378		real_wr->num_sge = w->num_sge;
379		real_wr->next    = NULL;
380		if (tail_wr)
381			tail_wr->next = real_wr;
382		else
383			head_wr = real_wr;
384
385		tail_wr = real_wr;
386	}
387
388	ret = srq->context->real_context->ops.post_srq_recv(srq->real_srq, head_wr,
389							    &real_bad_wr);
390
391	if (ret) {
392		for (real_wr = head_wr, w = wr;
393		     real_wr;
394		     real_wr = real_wr->next, w = w->next)
395			if (real_wr == real_bad_wr) {
396				*bad_wr = w;
397				break;
398			}
399	}
400
401	return ret;
402}
403
404static int post_send_wrapper_1_0(struct ibv_qp_1_0 *qp, struct ibv_send_wr_1_0 *wr,
405				 struct ibv_send_wr_1_0 **bad_wr)
406{
407	struct ibv_send_wr_1_0 *w;
408	struct ibv_send_wr *real_wr, *head_wr = NULL, *tail_wr = NULL, *real_bad_wr;
409	int is_ud = qp->qp_type == IBV_QPT_UD;
410	int ret;
411
412	for (w = wr; w; w = w->next) {
413		real_wr = alloca(sizeof *real_wr);
414		real_wr->wr_id = w->wr_id;
415		real_wr->next  = NULL;
416
417#define TEST_SIZE_2_POINT(f1, f2)					\
418		((offsetof(struct ibv_send_wr, f1) - offsetof(struct ibv_send_wr, f2)) \
419		 == offsetof(struct ibv_send_wr_1_0, f1) - offsetof(struct ibv_send_wr_1_0, f2))
420#define TEST_SIZE_TO_END(f1)					    \
421		((sizeof(struct ibv_send_wr) - offsetof(struct ibv_send_wr, f1)) == \
422		 (sizeof(struct ibv_send_wr_1_0) - offsetof(struct ibv_send_wr_1_0, f1)))
423
424		if (TEST_SIZE_TO_END (sg_list))
425			memcpy(&real_wr->sg_list, &w->sg_list, sizeof *real_wr
426			       - offsetof(struct ibv_send_wr, sg_list));
427		else if (TEST_SIZE_2_POINT (imm_data, sg_list) &&
428			 TEST_SIZE_TO_END (wr)) {
429			/* we have alignment up to wr, but padding between
430			 * imm_data and wr, and we know wr itself is the
431			 * same size */
432			memcpy(&real_wr->sg_list, &w->sg_list,
433			       offsetof(struct ibv_send_wr, imm_data) -
434			       offsetof(struct ibv_send_wr, sg_list) +
435			       sizeof real_wr->imm_data);
436			memcpy(&real_wr->wr, &w->wr, sizeof real_wr->wr);
437		} else {
438			real_wr->sg_list = w->sg_list;
439			real_wr->num_sge = w->num_sge;
440			real_wr->opcode = w->opcode;
441			real_wr->send_flags = w->send_flags;
442			real_wr->imm_data = w->imm_data;
443			if (TEST_SIZE_TO_END (wr))
444				memcpy(&real_wr->wr, &w->wr,
445				       sizeof real_wr->wr);
446			else {
447				real_wr->wr.atomic.remote_addr =
448					w->wr.atomic.remote_addr;
449				real_wr->wr.atomic.compare_add =
450					w->wr.atomic.compare_add;
451				real_wr->wr.atomic.swap =
452					w->wr.atomic.swap;
453				real_wr->wr.atomic.rkey =
454					w->wr.atomic.rkey;
455			}
456		}
457
458		if (is_ud)
459			real_wr->wr.ud.ah = w->wr.ud.ah->real_ah;
460
461		if (tail_wr)
462			tail_wr->next = real_wr;
463		else
464			head_wr = real_wr;
465
466		tail_wr = real_wr;
467	}
468
469	ret = qp->context->real_context->ops.post_send(qp->real_qp, head_wr,
470						       &real_bad_wr);
471
472	if (ret) {
473		for (real_wr = head_wr, w = wr;
474		     real_wr;
475		     real_wr = real_wr->next, w = w->next)
476			if (real_wr == real_bad_wr) {
477				*bad_wr = w;
478				break;
479			}
480	}
481
482	return ret;
483}
484
485static int post_recv_wrapper_1_0(struct ibv_qp_1_0 *qp, struct ibv_recv_wr_1_0 *wr,
486				 struct ibv_recv_wr_1_0 **bad_wr)
487{
488	struct ibv_recv_wr_1_0 *w;
489	struct ibv_recv_wr *real_wr, *head_wr = NULL, *tail_wr = NULL, *real_bad_wr;
490	int ret;
491
492	for (w = wr; w; w = w->next) {
493		real_wr = alloca(sizeof *real_wr);
494		real_wr->wr_id   = w->wr_id;
495		real_wr->sg_list = w->sg_list;
496		real_wr->num_sge = w->num_sge;
497		real_wr->next    = NULL;
498		if (tail_wr)
499			tail_wr->next = real_wr;
500		else
501			head_wr = real_wr;
502
503		tail_wr = real_wr;
504	}
505
506	ret = qp->context->real_context->ops.post_recv(qp->real_qp, head_wr,
507						       &real_bad_wr);
508
509	if (ret) {
510		for (real_wr = head_wr, w = wr;
511		     real_wr;
512		     real_wr = real_wr->next, w = w->next)
513			if (real_wr == real_bad_wr) {
514				*bad_wr = w;
515				break;
516			}
517	}
518
519	return ret;
520}
521
522struct ibv_context_1_0 *__ibv_open_device_1_0(struct ibv_device_1_0 *device)
523{
524	struct ibv_context     *real_ctx;
525	struct ibv_context_1_0 *ctx;
526
527	ctx = malloc(sizeof *ctx);
528	if (!ctx)
529		return NULL;
530
531	real_ctx = ibv_open_device(device->real_device);
532	if (!real_ctx) {
533		free(ctx);
534		return NULL;
535	}
536
537	ctx->device       = device;
538	ctx->real_context = real_ctx;
539
540	ctx->ops.poll_cq       = poll_cq_wrapper_1_0;
541	ctx->ops.req_notify_cq = req_notify_cq_wrapper_1_0;
542	ctx->ops.post_send     = post_send_wrapper_1_0;
543	ctx->ops.post_recv     = post_recv_wrapper_1_0;
544	ctx->ops.post_srq_recv = post_srq_recv_wrapper_1_0;
545
546	return ctx;
547}
548symver(__ibv_open_device_1_0, ibv_open_device, IBVERBS_1.0);
549
550int __ibv_close_device_1_0(struct ibv_context_1_0 *context)
551{
552	int ret;
553
554	ret = ibv_close_device(context->real_context);
555	if (ret)
556		return ret;
557
558	free(context);
559	return 0;
560}
561symver(__ibv_close_device_1_0, ibv_close_device, IBVERBS_1.0);
562
563int __ibv_get_async_event_1_0(struct ibv_context_1_0 *context,
564			      struct ibv_async_event *event)
565{
566	int ret;
567
568	ret = ibv_get_async_event(context->real_context, event);
569	if (ret)
570		return ret;
571
572	switch (event->event_type) {
573	case IBV_EVENT_CQ_ERR:
574		event->element.cq = event->element.cq->cq_context;
575		break;
576
577	case IBV_EVENT_QP_FATAL:
578	case IBV_EVENT_QP_REQ_ERR:
579	case IBV_EVENT_QP_ACCESS_ERR:
580	case IBV_EVENT_COMM_EST:
581	case IBV_EVENT_SQ_DRAINED:
582	case IBV_EVENT_PATH_MIG:
583	case IBV_EVENT_PATH_MIG_ERR:
584	case IBV_EVENT_QP_LAST_WQE_REACHED:
585		event->element.qp = event->element.qp->qp_context;
586		break;
587
588	case IBV_EVENT_SRQ_ERR:
589	case IBV_EVENT_SRQ_LIMIT_REACHED:
590		event->element.srq = event->element.srq->srq_context;
591		break;
592
593	default:
594		break;
595	}
596
597	return ret;
598}
599symver(__ibv_get_async_event_1_0, ibv_get_async_event, IBVERBS_1.0);
600
601void __ibv_ack_async_event_1_0(struct ibv_async_event *event)
602{
603	struct ibv_async_event real_event = *event;
604
605	switch (event->event_type) {
606	case IBV_EVENT_CQ_ERR:
607		real_event.element.cq =
608			((struct ibv_cq_1_0 *) event->element.cq)->real_cq;
609		break;
610
611	case IBV_EVENT_QP_FATAL:
612	case IBV_EVENT_QP_REQ_ERR:
613	case IBV_EVENT_QP_ACCESS_ERR:
614	case IBV_EVENT_COMM_EST:
615	case IBV_EVENT_SQ_DRAINED:
616	case IBV_EVENT_PATH_MIG:
617	case IBV_EVENT_PATH_MIG_ERR:
618	case IBV_EVENT_QP_LAST_WQE_REACHED:
619		real_event.element.qp =
620			((struct ibv_qp_1_0 *) event->element.qp)->real_qp;
621		break;
622
623	case IBV_EVENT_SRQ_ERR:
624	case IBV_EVENT_SRQ_LIMIT_REACHED:
625		real_event.element.srq =
626			((struct ibv_srq_1_0 *) event->element.srq)->real_srq;
627		break;
628
629	default:
630		break;
631	}
632
633	ibv_ack_async_event(&real_event);
634}
635symver(__ibv_ack_async_event_1_0, ibv_ack_async_event, IBVERBS_1.0);
636
637int __ibv_query_device_1_0(struct ibv_context_1_0 *context,
638			   struct ibv_device_attr *device_attr)
639{
640	return ibv_query_device(context->real_context, device_attr);
641}
642symver(__ibv_query_device_1_0, ibv_query_device, IBVERBS_1.0);
643
644int __ibv_query_port_1_0(struct ibv_context_1_0 *context, uint8_t port_num,
645			 struct ibv_port_attr *port_attr)
646{
647	return ibv_query_port(context->real_context, port_num, port_attr);
648}
649symver(__ibv_query_port_1_0, ibv_query_port, IBVERBS_1.0);
650
651int __ibv_query_gid_1_0(struct ibv_context_1_0 *context, uint8_t port_num,
652			int index, union ibv_gid *gid)
653{
654	return ibv_query_gid(context->real_context, port_num, index, gid);
655}
656symver(__ibv_query_gid_1_0, ibv_query_gid, IBVERBS_1.0);
657
658int __ibv_query_pkey_1_0(struct ibv_context_1_0 *context, uint8_t port_num,
659			 int index, __be16 *pkey)
660{
661	return ibv_query_pkey(context->real_context, port_num, index, pkey);
662}
663symver(__ibv_query_pkey_1_0, ibv_query_pkey, IBVERBS_1.0);
664
665struct ibv_pd_1_0 *__ibv_alloc_pd_1_0(struct ibv_context_1_0 *context)
666{
667	struct ibv_pd *real_pd;
668	struct ibv_pd_1_0 *pd;
669
670	pd = malloc(sizeof *pd);
671	if (!pd)
672		return NULL;
673
674	real_pd = ibv_alloc_pd(context->real_context);
675	if (!real_pd) {
676		free(pd);
677		return NULL;
678	}
679
680	pd->context = context;
681	pd->real_pd = real_pd;
682
683	return pd;
684}
685symver(__ibv_alloc_pd_1_0, ibv_alloc_pd, IBVERBS_1.0);
686
687int __ibv_dealloc_pd_1_0(struct ibv_pd_1_0 *pd)
688{
689	int ret;
690
691	ret = ibv_dealloc_pd(pd->real_pd);
692	if (ret)
693		return ret;
694
695	free(pd);
696	return 0;
697}
698symver(__ibv_dealloc_pd_1_0, ibv_dealloc_pd, IBVERBS_1.0);
699
700struct ibv_mr_1_0 *__ibv_reg_mr_1_0(struct ibv_pd_1_0 *pd, void *addr,
701				    size_t length, int access)
702{
703	struct ibv_mr *real_mr;
704	struct ibv_mr_1_0 *mr;
705
706	mr = malloc(sizeof *mr);
707	if (!mr)
708		return NULL;
709
710	real_mr = ibv_reg_mr(pd->real_pd, addr, length, access);
711	if (!real_mr) {
712		free(mr);
713		return NULL;
714	}
715
716	mr->context = pd->context;
717	mr->pd      = pd;
718	mr->lkey    = real_mr->lkey;
719	mr->rkey    = real_mr->rkey;
720	mr->real_mr = real_mr;
721
722	return mr;
723}
724symver(__ibv_reg_mr_1_0, ibv_reg_mr, IBVERBS_1.0);
725
726int __ibv_dereg_mr_1_0(struct ibv_mr_1_0 *mr)
727{
728	int ret;
729
730	ret = ibv_dereg_mr(mr->real_mr);
731	if (ret)
732		return ret;
733
734	free(mr);
735	return 0;
736}
737symver(__ibv_dereg_mr_1_0, ibv_dereg_mr, IBVERBS_1.0);
738
739struct ibv_cq_1_0 *__ibv_create_cq_1_0(struct ibv_context_1_0 *context, int cqe,
740				       void *cq_context,
741				       struct ibv_comp_channel *channel,
742				       int comp_vector)
743{
744	struct ibv_cq *real_cq;
745	struct ibv_cq_1_0 *cq;
746
747	cq = malloc(sizeof *cq);
748	if (!cq)
749		return NULL;
750
751	real_cq = ibv_create_cq(context->real_context, cqe, cq_context,
752				channel, comp_vector);
753	if (!real_cq) {
754		free(cq);
755		return NULL;
756	}
757
758	cq->context    = context;
759	cq->cq_context = cq_context;
760	cq->cqe        = cqe;
761	cq->real_cq    = real_cq;
762
763	real_cq->cq_context = cq;
764
765	return cq;
766}
767symver(__ibv_create_cq_1_0, ibv_create_cq, IBVERBS_1.0);
768
769int __ibv_resize_cq_1_0(struct ibv_cq_1_0 *cq, int cqe)
770{
771	return ibv_resize_cq(cq->real_cq, cqe);
772}
773symver(__ibv_resize_cq_1_0, ibv_resize_cq, IBVERBS_1.0);
774
775int __ibv_destroy_cq_1_0(struct ibv_cq_1_0 *cq)
776{
777	int ret;
778
779	ret = ibv_destroy_cq(cq->real_cq);
780	if (ret)
781		return ret;
782
783	free(cq);
784	return 0;
785}
786symver(__ibv_destroy_cq_1_0, ibv_destroy_cq, IBVERBS_1.0);
787
788int __ibv_get_cq_event_1_0(struct ibv_comp_channel *channel,
789			   struct ibv_cq_1_0 **cq, void **cq_context)
790{
791	struct ibv_cq *real_cq;
792	void *cq_ptr;
793	int ret;
794
795	ret = ibv_get_cq_event(channel, &real_cq, &cq_ptr);
796	if (ret)
797		return ret;
798
799	*cq         = cq_ptr;
800	*cq_context = (*cq)->cq_context;
801
802	return 0;
803}
804symver(__ibv_get_cq_event_1_0, ibv_get_cq_event, IBVERBS_1.0);
805
806void __ibv_ack_cq_events_1_0(struct ibv_cq_1_0 *cq, unsigned int nevents)
807{
808	ibv_ack_cq_events(cq->real_cq, nevents);
809}
810symver(__ibv_ack_cq_events_1_0, ibv_ack_cq_events, IBVERBS_1.0);
811
812struct ibv_srq_1_0 *__ibv_create_srq_1_0(struct ibv_pd_1_0 *pd,
813					 struct ibv_srq_init_attr *srq_init_attr)
814{
815	struct ibv_srq *real_srq;
816	struct ibv_srq_1_0 *srq;
817
818	srq = malloc(sizeof *srq);
819	if (!srq)
820		return NULL;
821
822	real_srq = ibv_create_srq(pd->real_pd, srq_init_attr);
823	if (!real_srq) {
824		free(srq);
825		return NULL;
826	}
827
828	srq->context     = pd->context;
829	srq->srq_context = srq_init_attr->srq_context;
830	srq->pd          = pd;
831	srq->real_srq    = real_srq;
832
833	real_srq->srq_context = srq;
834
835	return srq;
836}
837symver(__ibv_create_srq_1_0, ibv_create_srq, IBVERBS_1.0);
838
839int __ibv_modify_srq_1_0(struct ibv_srq_1_0 *srq,
840			 struct ibv_srq_attr *srq_attr,
841			 int srq_attr_mask)
842{
843	return ibv_modify_srq(srq->real_srq, srq_attr, srq_attr_mask);
844}
845symver(__ibv_modify_srq_1_0, ibv_modify_srq, IBVERBS_1.0);
846
847int __ibv_query_srq_1_0(struct ibv_srq_1_0 *srq, struct ibv_srq_attr *srq_attr)
848{
849	return ibv_query_srq(srq->real_srq, srq_attr);
850}
851symver(__ibv_query_srq_1_0, ibv_query_srq, IBVERBS_1.0);
852
853int __ibv_destroy_srq_1_0(struct ibv_srq_1_0 *srq)
854{
855	int ret;
856
857	ret = ibv_destroy_srq(srq->real_srq);
858	if (ret)
859		return ret;
860
861	free(srq);
862	return 0;
863}
864symver(__ibv_destroy_srq_1_0, ibv_destroy_srq, IBVERBS_1.0);
865
866struct ibv_qp_1_0 *__ibv_create_qp_1_0(struct ibv_pd_1_0 *pd,
867				       struct ibv_qp_init_attr_1_0 *qp_init_attr)
868{
869	struct ibv_qp *real_qp;
870	struct ibv_qp_1_0 *qp;
871	struct ibv_qp_init_attr real_init_attr;
872
873	qp = malloc(sizeof *qp);
874	if (!qp)
875		return NULL;
876
877	real_init_attr.qp_context = qp_init_attr->qp_context;
878	real_init_attr.send_cq    = qp_init_attr->send_cq->real_cq;
879	real_init_attr.recv_cq    = qp_init_attr->recv_cq->real_cq;
880	real_init_attr.srq        = qp_init_attr->srq ?
881		qp_init_attr->srq->real_srq : NULL;
882	real_init_attr.cap        = qp_init_attr->cap;
883	real_init_attr.qp_type    = qp_init_attr->qp_type;
884	real_init_attr.sq_sig_all = qp_init_attr->sq_sig_all;
885
886	real_qp = ibv_create_qp(pd->real_pd, &real_init_attr);
887	if (!real_qp) {
888		free(qp);
889		return NULL;
890	}
891
892	qp->context    = pd->context;
893	qp->qp_context = qp_init_attr->qp_context;
894	qp->pd         = pd;
895	qp->send_cq    = qp_init_attr->send_cq;
896	qp->recv_cq    = qp_init_attr->recv_cq;
897	qp->srq        = qp_init_attr->srq;
898	qp->qp_type    = qp_init_attr->qp_type;
899	qp->qp_num     = real_qp->qp_num;
900	qp->real_qp    = real_qp;
901
902	qp_init_attr->cap = real_init_attr.cap;
903
904	real_qp->qp_context = qp;
905
906	return qp;
907}
908symver(__ibv_create_qp_1_0, ibv_create_qp, IBVERBS_1.0);
909
910int __ibv_query_qp_1_0(struct ibv_qp_1_0 *qp, struct ibv_qp_attr *attr,
911		       int attr_mask,
912		       struct ibv_qp_init_attr_1_0 *init_attr)
913{
914	struct ibv_qp_init_attr real_init_attr;
915	int ret;
916
917	ret = ibv_query_qp(qp->real_qp, attr, attr_mask, &real_init_attr);
918	if (ret)
919		return ret;
920
921	init_attr->qp_context = qp->qp_context;
922	init_attr->send_cq    = real_init_attr.send_cq->cq_context;
923	init_attr->recv_cq    = real_init_attr.recv_cq->cq_context;
924	init_attr->srq        = real_init_attr.srq->srq_context;
925	init_attr->qp_type    = real_init_attr.qp_type;
926	init_attr->cap        = real_init_attr.cap;
927	init_attr->sq_sig_all = real_init_attr.sq_sig_all;
928
929	return 0;
930}
931symver(__ibv_query_qp_1_0, ibv_query_qp, IBVERBS_1.0);
932
933int __ibv_modify_qp_1_0(struct ibv_qp_1_0 *qp, struct ibv_qp_attr *attr,
934			int attr_mask)
935{
936	return ibv_modify_qp(qp->real_qp, attr, attr_mask);
937}
938symver(__ibv_modify_qp_1_0, ibv_modify_qp, IBVERBS_1.0);
939
940int __ibv_destroy_qp_1_0(struct ibv_qp_1_0 *qp)
941{
942	int ret;
943
944	ret = ibv_destroy_qp(qp->real_qp);
945	if (ret)
946		return ret;
947
948	free(qp);
949	return 0;
950}
951symver(__ibv_destroy_qp_1_0, ibv_destroy_qp, IBVERBS_1.0);
952
953struct ibv_ah_1_0 *__ibv_create_ah_1_0(struct ibv_pd_1_0 *pd,
954				       struct ibv_ah_attr *attr)
955{
956	struct ibv_ah *real_ah;
957	struct ibv_ah_1_0 *ah;
958
959	ah = malloc(sizeof *ah);
960	if (!ah)
961		return NULL;
962
963	real_ah = ibv_create_ah(pd->real_pd, attr);
964	if (!real_ah) {
965		free(ah);
966		return NULL;
967	}
968
969	ah->context = pd->context;
970	ah->pd      = pd;
971	ah->real_ah = real_ah;
972
973	return ah;
974}
975symver(__ibv_create_ah_1_0, ibv_create_ah, IBVERBS_1.0);
976
977int __ibv_destroy_ah_1_0(struct ibv_ah_1_0 *ah)
978{
979	int ret;
980
981	ret = ibv_destroy_ah(ah->real_ah);
982	if (ret)
983		return ret;
984
985	free(ah);
986	return 0;
987}
988symver(__ibv_destroy_ah_1_0, ibv_destroy_ah, IBVERBS_1.0);
989
990int __ibv_attach_mcast_1_0(struct ibv_qp_1_0 *qp, union ibv_gid *gid, uint16_t lid)
991{
992	return ibv_attach_mcast(qp->real_qp, gid, lid);
993}
994symver(__ibv_attach_mcast_1_0, ibv_attach_mcast, IBVERBS_1.0);
995
996int __ibv_detach_mcast_1_0(struct ibv_qp_1_0 *qp, union ibv_gid *gid, uint16_t lid)
997{
998	return ibv_detach_mcast(qp->real_qp, gid, lid);
999}
1000symver(__ibv_detach_mcast_1_0, ibv_detach_mcast, IBVERBS_1.0);
1001
1002void __ibv_register_driver_1_1(const char *name, ibv_driver_init_func_1_1 init_func)
1003{
1004	/* The driver interface is private as of rdma-core 13. This stub is
1005	 * left to preserve dynamic-link compatibility with old libfabrics
1006	 * usnic providers which use this function only to suppress a fprintf
1007	 * in old versions of libibverbs. */
1008}
1009symver(__ibv_register_driver_1_1, ibv_register_driver, IBVERBS_1.1);
1010