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 
43 struct ibv_pd_1_0 {
44 	struct ibv_context_1_0 *context;
45 	uint32_t		handle;
46 
47 	struct ibv_pd	       *real_pd;
48 };
49 
50 struct 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 
60 struct 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 
73 struct 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 
83 struct 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 
110 struct 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 
117 struct 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 
136 struct 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 
150 struct 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 
158 struct 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 
165 struct 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 
217 struct 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 
227 typedef 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  */
234 struct ibv_device_1_0 **__ibv_get_device_list_1_0(int *num);
235 void __ibv_free_device_list_1_0(struct ibv_device_1_0 **list);
236 const 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);
238 struct ibv_context_1_0 *__ibv_open_device_1_0(struct ibv_device_1_0 *device);
239 int __ibv_close_device_1_0(struct ibv_context_1_0 *context);
240 int __ibv_get_async_event_1_0(struct ibv_context_1_0 *context,
241 			      struct ibv_async_event *event);
242 void __ibv_ack_async_event_1_0(struct ibv_async_event *event);
243 int __ibv_query_device_1_0(struct ibv_context_1_0 *context,
244 			   struct ibv_device_attr *device_attr);
245 int __ibv_query_port_1_0(struct ibv_context_1_0 *context, uint8_t port_num,
246 			 struct ibv_port_attr *port_attr);
247 int __ibv_query_gid_1_0(struct ibv_context_1_0 *context, uint8_t port_num,
248 			int index, union ibv_gid *gid);
249 int __ibv_query_pkey_1_0(struct ibv_context_1_0 *context, uint8_t port_num,
250 			 int index, __be16 *pkey);
251 struct ibv_pd_1_0 *__ibv_alloc_pd_1_0(struct ibv_context_1_0 *context);
252 int __ibv_dealloc_pd_1_0(struct ibv_pd_1_0 *pd);
253 struct ibv_mr_1_0 *__ibv_reg_mr_1_0(struct ibv_pd_1_0 *pd, void *addr,
254 				    size_t length, int access);
255 int __ibv_dereg_mr_1_0(struct ibv_mr_1_0 *mr);
256 struct 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);
260 int __ibv_resize_cq_1_0(struct ibv_cq_1_0 *cq, int cqe);
261 int __ibv_destroy_cq_1_0(struct ibv_cq_1_0 *cq);
262 int __ibv_get_cq_event_1_0(struct ibv_comp_channel *channel,
263 			   struct ibv_cq_1_0 **cq, void **cq_context);
264 void __ibv_ack_cq_events_1_0(struct ibv_cq_1_0 *cq, unsigned int nevents);
265 struct 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);
268 int __ibv_modify_srq_1_0(struct ibv_srq_1_0 *srq, struct ibv_srq_attr *srq_attr,
269 			 int srq_attr_mask);
270 int __ibv_query_srq_1_0(struct ibv_srq_1_0 *srq, struct ibv_srq_attr *srq_attr);
271 int __ibv_destroy_srq_1_0(struct ibv_srq_1_0 *srq);
272 struct 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);
275 int __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);
277 int __ibv_modify_qp_1_0(struct ibv_qp_1_0 *qp, struct ibv_qp_attr *attr,
278 			int attr_mask);
279 int __ibv_destroy_qp_1_0(struct ibv_qp_1_0 *qp);
280 struct ibv_ah_1_0 *__ibv_create_ah_1_0(struct ibv_pd_1_0 *pd,
281 				       struct ibv_ah_attr *attr);
282 int __ibv_destroy_ah_1_0(struct ibv_ah_1_0 *ah);
283 int __ibv_attach_mcast_1_0(struct ibv_qp_1_0 *qp, union ibv_gid *gid,
284 			   uint16_t lid);
285 int __ibv_detach_mcast_1_0(struct ibv_qp_1_0 *qp, union ibv_gid *gid,
286 			   uint16_t lid);
287 void __ibv_register_driver_1_1(const char *name,
288 			       ibv_driver_init_func_1_1 init_func);
289 
290 struct 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 
318 fail:
319 	for (i = 1; i <= n; ++i)
320 		if (l[i])
321 			free(l[i]);
322 	free(l);
323 
324 free_device_list:
325 	ibv_free_device_list(real_list);
326 	return NULL;
327 }
328 symver(__ibv_get_device_list_1_0, ibv_get_device_list, IBVERBS_1.0);
329 
330 void __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 }
342 symver(__ibv_free_device_list_1_0, ibv_free_device_list, IBVERBS_1.0);
343 
344 const char *__ibv_get_device_name_1_0(struct ibv_device_1_0 *device)
345 {
346 	return ibv_get_device_name(device->real_device);
347 }
348 symver(__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 }
354 symver(__ibv_get_device_guid_1_0, ibv_get_device_guid, IBVERBS_1.0);
355 
356 static 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 
362 static 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 
367 static 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 
404 static 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 
485 static 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 
522 struct 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 }
548 symver(__ibv_open_device_1_0, ibv_open_device, IBVERBS_1.0);
549 
550 int __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 }
561 symver(__ibv_close_device_1_0, ibv_close_device, IBVERBS_1.0);
562 
563 int __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 }
599 symver(__ibv_get_async_event_1_0, ibv_get_async_event, IBVERBS_1.0);
600 
601 void __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 }
635 symver(__ibv_ack_async_event_1_0, ibv_ack_async_event, IBVERBS_1.0);
636 
637 int __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 }
642 symver(__ibv_query_device_1_0, ibv_query_device, IBVERBS_1.0);
643 
644 int __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 }
649 symver(__ibv_query_port_1_0, ibv_query_port, IBVERBS_1.0);
650 
651 int __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 }
656 symver(__ibv_query_gid_1_0, ibv_query_gid, IBVERBS_1.0);
657 
658 int __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 }
663 symver(__ibv_query_pkey_1_0, ibv_query_pkey, IBVERBS_1.0);
664 
665 struct 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 }
685 symver(__ibv_alloc_pd_1_0, ibv_alloc_pd, IBVERBS_1.0);
686 
687 int __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 }
698 symver(__ibv_dealloc_pd_1_0, ibv_dealloc_pd, IBVERBS_1.0);
699 
700 struct 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 }
724 symver(__ibv_reg_mr_1_0, ibv_reg_mr, IBVERBS_1.0);
725 
726 int __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 }
737 symver(__ibv_dereg_mr_1_0, ibv_dereg_mr, IBVERBS_1.0);
738 
739 struct 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 }
767 symver(__ibv_create_cq_1_0, ibv_create_cq, IBVERBS_1.0);
768 
769 int __ibv_resize_cq_1_0(struct ibv_cq_1_0 *cq, int cqe)
770 {
771 	return ibv_resize_cq(cq->real_cq, cqe);
772 }
773 symver(__ibv_resize_cq_1_0, ibv_resize_cq, IBVERBS_1.0);
774 
775 int __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 }
786 symver(__ibv_destroy_cq_1_0, ibv_destroy_cq, IBVERBS_1.0);
787 
788 int __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 }
804 symver(__ibv_get_cq_event_1_0, ibv_get_cq_event, IBVERBS_1.0);
805 
806 void __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 }
810 symver(__ibv_ack_cq_events_1_0, ibv_ack_cq_events, IBVERBS_1.0);
811 
812 struct 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 }
837 symver(__ibv_create_srq_1_0, ibv_create_srq, IBVERBS_1.0);
838 
839 int __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 }
845 symver(__ibv_modify_srq_1_0, ibv_modify_srq, IBVERBS_1.0);
846 
847 int __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 }
851 symver(__ibv_query_srq_1_0, ibv_query_srq, IBVERBS_1.0);
852 
853 int __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 }
864 symver(__ibv_destroy_srq_1_0, ibv_destroy_srq, IBVERBS_1.0);
865 
866 struct 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 }
908 symver(__ibv_create_qp_1_0, ibv_create_qp, IBVERBS_1.0);
909 
910 int __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 }
931 symver(__ibv_query_qp_1_0, ibv_query_qp, IBVERBS_1.0);
932 
933 int __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 }
938 symver(__ibv_modify_qp_1_0, ibv_modify_qp, IBVERBS_1.0);
939 
940 int __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 }
951 symver(__ibv_destroy_qp_1_0, ibv_destroy_qp, IBVERBS_1.0);
952 
953 struct 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 }
975 symver(__ibv_create_ah_1_0, ibv_create_ah, IBVERBS_1.0);
976 
977 int __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 }
988 symver(__ibv_destroy_ah_1_0, ibv_destroy_ah, IBVERBS_1.0);
989 
990 int __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 }
994 symver(__ibv_attach_mcast_1_0, ibv_attach_mcast, IBVERBS_1.0);
995 
996 int __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 }
1000 symver(__ibv_detach_mcast_1_0, ibv_detach_mcast, IBVERBS_1.0);
1001 
1002 void __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 }
1009 symver(__ibv_register_driver_1_1, ibv_register_driver, IBVERBS_1.1);
1010