xref: /trueos/contrib/ofed/libmthca/src/verbs.c (revision 8fe640108653f13042f1b15213769e338aa524f6)
1 /*
2  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
3  * Copyright (c) 2005, 2006 Cisco Systems.  All rights reserved.
4  *
5  * This software is available to you under a choice of one of two
6  * licenses.  You may choose to be licensed under the terms of the GNU
7  * General Public License (GPL) Version 2, available from the file
8  * COPYING in the main directory of this source tree, or the
9  * OpenIB.org BSD license below:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      - Redistributions of source code must retain the above
16  *        copyright notice, this list of conditions and the following
17  *        disclaimer.
18  *
19  *      - Redistributions in binary form must reproduce the above
20  *        copyright notice, this list of conditions and the following
21  *        disclaimer in the documentation and/or other materials
22  *        provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  */
33 
34 #if HAVE_CONFIG_H
35 #  include <config.h>
36 #endif /* HAVE_CONFIG_H */
37 
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <strings.h>
41 #include <pthread.h>
42 #include <errno.h>
43 #include <netinet/in.h>
44 
45 #include "mthca.h"
46 #include "mthca-abi.h"
47 
mthca_query_device(struct ibv_context * context,struct ibv_device_attr * attr)48 int mthca_query_device(struct ibv_context *context, struct ibv_device_attr *attr)
49 {
50 	struct ibv_query_device cmd;
51 	uint64_t raw_fw_ver;
52 	unsigned major, minor, sub_minor;
53 	int ret;
54 
55 	ret = ibv_cmd_query_device(context, attr, &raw_fw_ver, &cmd, sizeof cmd);
56 	if (ret)
57 		return ret;
58 
59 	major     = (raw_fw_ver >> 32) & 0xffff;
60 	minor     = (raw_fw_ver >> 16) & 0xffff;
61 	sub_minor = raw_fw_ver & 0xffff;
62 
63 	snprintf(attr->fw_ver, sizeof attr->fw_ver,
64 		 "%d.%d.%d", major, minor, sub_minor);
65 
66 	return 0;
67 }
68 
mthca_query_port(struct ibv_context * context,uint8_t port,struct ibv_port_attr * attr)69 int mthca_query_port(struct ibv_context *context, uint8_t port,
70 		     struct ibv_port_attr *attr)
71 {
72 	struct ibv_query_port cmd;
73 
74 	return ibv_cmd_query_port(context, port, attr, &cmd, sizeof cmd);
75 }
76 
mthca_alloc_pd(struct ibv_context * context)77 struct ibv_pd *mthca_alloc_pd(struct ibv_context *context)
78 {
79 	struct ibv_alloc_pd        cmd;
80 	struct mthca_alloc_pd_resp resp;
81 	struct mthca_pd           *pd;
82 
83 	pd = malloc(sizeof *pd);
84 	if (!pd)
85 		return NULL;
86 
87 	if (!mthca_is_memfree(context)) {
88 		pd->ah_list = NULL;
89 		if (pthread_mutex_init(&pd->ah_mutex, NULL)) {
90 			free(pd);
91 			return NULL;
92 		}
93 	}
94 
95 	if (ibv_cmd_alloc_pd(context, &pd->ibv_pd, &cmd, sizeof cmd,
96 			     &resp.ibv_resp, sizeof resp)) {
97 		free(pd);
98 		return NULL;
99 	}
100 
101 	pd->pdn = resp.pdn;
102 
103 	return &pd->ibv_pd;
104 }
105 
mthca_free_pd(struct ibv_pd * pd)106 int mthca_free_pd(struct ibv_pd *pd)
107 {
108 	int ret;
109 
110 	ret = ibv_cmd_dealloc_pd(pd);
111 	if (ret)
112 		return ret;
113 
114 	free(to_mpd(pd));
115 	return 0;
116 }
117 
__mthca_reg_mr(struct ibv_pd * pd,void * addr,size_t length,uint64_t hca_va,enum ibv_access_flags access,int dma_sync)118 static struct ibv_mr *__mthca_reg_mr(struct ibv_pd *pd, void *addr,
119 				     size_t length, uint64_t hca_va,
120 				     enum ibv_access_flags access,
121 				     int dma_sync)
122 {
123 	struct ibv_mr *mr;
124 	struct mthca_reg_mr cmd;
125 	int ret;
126 
127 	/*
128 	 * Old kernels just ignore the extra data we pass in with the
129 	 * reg_mr command structure, so there's no need to add an ABI
130 	 * version check here (and indeed the kernel ABI was not
131 	 * incremented due to this change).
132 	 */
133 	cmd.mr_attrs = dma_sync ? MTHCA_MR_DMASYNC : 0;
134 	cmd.reserved = 0;
135 
136 	mr = malloc(sizeof *mr);
137 	if (!mr)
138 		return NULL;
139 
140 #ifdef IBV_CMD_REG_MR_HAS_RESP_PARAMS
141 	{
142 		struct ibv_reg_mr_resp resp;
143 
144 		ret = ibv_cmd_reg_mr(pd, addr, length, hca_va, access, mr,
145 				     &cmd.ibv_cmd, sizeof cmd, &resp, sizeof resp);
146 	}
147 #else
148 	ret = ibv_cmd_reg_mr(pd, addr, length, hca_va, access, mr,
149 			     &cmd.ibv_cmd, sizeof cmd);
150 #endif
151 	if (ret) {
152 		free(mr);
153 		return NULL;
154 	}
155 
156 	return mr;
157 }
158 
mthca_reg_mr(struct ibv_pd * pd,void * addr,size_t length,enum ibv_access_flags access)159 struct ibv_mr *mthca_reg_mr(struct ibv_pd *pd, void *addr,
160 			    size_t length, enum ibv_access_flags access)
161 {
162 	return __mthca_reg_mr(pd, addr, length, (uintptr_t) addr, access, 0);
163 }
164 
mthca_dereg_mr(struct ibv_mr * mr)165 int mthca_dereg_mr(struct ibv_mr *mr)
166 {
167 	int ret;
168 
169 	ret = ibv_cmd_dereg_mr(mr);
170 	if (ret)
171 		return ret;
172 
173 	free(mr);
174 	return 0;
175 }
176 
align_cq_size(int cqe)177 static int align_cq_size(int cqe)
178 {
179 	int nent;
180 
181 	for (nent = 1; nent <= cqe; nent <<= 1)
182 		; /* nothing */
183 
184 	return nent;
185 }
186 
mthca_create_cq(struct ibv_context * context,int cqe,struct ibv_comp_channel * channel,int comp_vector)187 struct ibv_cq *mthca_create_cq(struct ibv_context *context, int cqe,
188 			       struct ibv_comp_channel *channel,
189 			       int comp_vector)
190 {
191 	struct mthca_create_cq      cmd;
192 	struct mthca_create_cq_resp resp;
193 	struct mthca_cq      	   *cq;
194 	int                  	    ret;
195 
196 	/* Sanity check CQ size before proceeding */
197 	if (cqe > 131072)
198 		return NULL;
199 
200 	cq = malloc(sizeof *cq);
201 	if (!cq)
202 		return NULL;
203 
204 	cq->cons_index = 0;
205 
206 	if (pthread_spin_init(&cq->lock, PTHREAD_PROCESS_PRIVATE))
207 		goto err;
208 
209 	cqe = align_cq_size(cqe);
210 	if (mthca_alloc_cq_buf(to_mdev(context->device), &cq->buf, cqe))
211 		goto err;
212 
213 	cq->mr = __mthca_reg_mr(to_mctx(context)->pd, cq->buf.buf,
214 				cqe * MTHCA_CQ_ENTRY_SIZE,
215 				0, IBV_ACCESS_LOCAL_WRITE, 1);
216 	if (!cq->mr)
217 		goto err_buf;
218 
219 	cq->mr->context = context;
220 
221 	if (mthca_is_memfree(context)) {
222 		cq->arm_sn          = 1;
223 		cq->set_ci_db_index = mthca_alloc_db(to_mctx(context)->db_tab,
224 						     MTHCA_DB_TYPE_CQ_SET_CI,
225 						     &cq->set_ci_db);
226 		if (cq->set_ci_db_index < 0)
227 			goto err_unreg;
228 
229 		cq->arm_db_index    = mthca_alloc_db(to_mctx(context)->db_tab,
230 						     MTHCA_DB_TYPE_CQ_ARM,
231 						     &cq->arm_db);
232 		if (cq->arm_db_index < 0)
233 			goto err_set_db;
234 
235 		cmd.arm_db_page  = db_align(cq->arm_db);
236 		cmd.set_db_page  = db_align(cq->set_ci_db);
237 		cmd.arm_db_index = cq->arm_db_index;
238 		cmd.set_db_index = cq->set_ci_db_index;
239 	} else {
240 		cmd.arm_db_page  = cmd.set_db_page  =
241 		cmd.arm_db_index = cmd.set_db_index = 0;
242 	}
243 
244 	cmd.lkey   = cq->mr->lkey;
245 	cmd.pdn    = to_mpd(to_mctx(context)->pd)->pdn;
246 	ret = ibv_cmd_create_cq(context, cqe - 1, channel, comp_vector,
247 				&cq->ibv_cq, &cmd.ibv_cmd, sizeof cmd,
248 				&resp.ibv_resp, sizeof resp);
249 	if (ret)
250 		goto err_arm_db;
251 
252 	cq->cqn = resp.cqn;
253 
254 	if (mthca_is_memfree(context)) {
255 		mthca_set_db_qn(cq->set_ci_db, MTHCA_DB_TYPE_CQ_SET_CI, cq->cqn);
256 		mthca_set_db_qn(cq->arm_db,    MTHCA_DB_TYPE_CQ_ARM,    cq->cqn);
257 	}
258 
259 	return &cq->ibv_cq;
260 
261 err_arm_db:
262 	if (mthca_is_memfree(context))
263 		mthca_free_db(to_mctx(context)->db_tab, MTHCA_DB_TYPE_CQ_ARM,
264 			      cq->arm_db_index);
265 
266 err_set_db:
267 	if (mthca_is_memfree(context))
268 		mthca_free_db(to_mctx(context)->db_tab, MTHCA_DB_TYPE_CQ_SET_CI,
269 			      cq->set_ci_db_index);
270 
271 err_unreg:
272 	mthca_dereg_mr(cq->mr);
273 
274 err_buf:
275 	mthca_free_buf(&cq->buf);
276 
277 err:
278 	free(cq);
279 
280 	return NULL;
281 }
282 
mthca_resize_cq(struct ibv_cq * ibcq,int cqe)283 int mthca_resize_cq(struct ibv_cq *ibcq, int cqe)
284 {
285 	struct mthca_cq *cq = to_mcq(ibcq);
286 	struct mthca_resize_cq cmd;
287 	struct ibv_mr *mr;
288 	struct mthca_buf buf;
289 	int old_cqe;
290 	int ret;
291 
292 	/* Sanity check CQ size before proceeding */
293 	if (cqe > 131072)
294 		return EINVAL;
295 
296 	pthread_spin_lock(&cq->lock);
297 
298 	cqe = align_cq_size(cqe);
299 	if (cqe == ibcq->cqe + 1) {
300 		ret = 0;
301 		goto out;
302 	}
303 
304 	ret = mthca_alloc_cq_buf(to_mdev(ibcq->context->device), &buf, cqe);
305 	if (ret)
306 		goto out;
307 
308 	mr = __mthca_reg_mr(to_mctx(ibcq->context)->pd, buf.buf,
309 			    cqe * MTHCA_CQ_ENTRY_SIZE,
310 			    0, IBV_ACCESS_LOCAL_WRITE, 1);
311 	if (!mr) {
312 		mthca_free_buf(&buf);
313 		ret = ENOMEM;
314 		goto out;
315 	}
316 
317 	mr->context = ibcq->context;
318 
319 	old_cqe = ibcq->cqe;
320 
321 	cmd.lkey = mr->lkey;
322 #ifdef IBV_CMD_RESIZE_CQ_HAS_RESP_PARAMS
323 	{
324 		struct ibv_resize_cq_resp resp;
325 		ret = ibv_cmd_resize_cq(ibcq, cqe - 1, &cmd.ibv_cmd, sizeof cmd,
326 					&resp, sizeof resp);
327 	}
328 #else
329 	ret = ibv_cmd_resize_cq(ibcq, cqe - 1, &cmd.ibv_cmd, sizeof cmd);
330 #endif
331 	if (ret) {
332 		mthca_dereg_mr(mr);
333 		mthca_free_buf(&buf);
334 		goto out;
335 	}
336 
337 	mthca_cq_resize_copy_cqes(cq, buf.buf, old_cqe);
338 
339 	mthca_dereg_mr(cq->mr);
340 	mthca_free_buf(&cq->buf);
341 
342 	cq->buf = buf;
343 	cq->mr  = mr;
344 
345 out:
346 	pthread_spin_unlock(&cq->lock);
347 	return ret;
348 }
349 
mthca_destroy_cq(struct ibv_cq * cq)350 int mthca_destroy_cq(struct ibv_cq *cq)
351 {
352 	int ret;
353 
354 	ret = ibv_cmd_destroy_cq(cq);
355 	if (ret)
356 		return ret;
357 
358 	if (mthca_is_memfree(cq->context)) {
359 		mthca_free_db(to_mctx(cq->context)->db_tab, MTHCA_DB_TYPE_CQ_SET_CI,
360 			      to_mcq(cq)->set_ci_db_index);
361 		mthca_free_db(to_mctx(cq->context)->db_tab, MTHCA_DB_TYPE_CQ_ARM,
362 			      to_mcq(cq)->arm_db_index);
363 	}
364 
365 	mthca_dereg_mr(to_mcq(cq)->mr);
366 	mthca_free_buf(&to_mcq(cq)->buf);
367 	free(to_mcq(cq));
368 
369 	return 0;
370 }
371 
align_queue_size(struct ibv_context * context,int size,int spare)372 static int align_queue_size(struct ibv_context *context, int size, int spare)
373 {
374 	int ret;
375 
376 	/*
377 	 * If someone asks for a 0-sized queue, presumably they're not
378 	 * going to use it.  So don't mess with their size.
379 	 */
380 	if (!size)
381 		return 0;
382 
383 	if (mthca_is_memfree(context)) {
384 		for (ret = 1; ret < size + spare; ret <<= 1)
385 			; /* nothing */
386 
387 		return ret;
388 	} else
389 		return size + spare;
390 }
391 
mthca_create_srq(struct ibv_pd * pd,struct ibv_srq_init_attr * attr)392 struct ibv_srq *mthca_create_srq(struct ibv_pd *pd,
393 				 struct ibv_srq_init_attr *attr)
394 {
395 	struct mthca_create_srq      cmd;
396 	struct mthca_create_srq_resp resp;
397 	struct mthca_srq            *srq;
398 	int                          ret;
399 
400 	/* Sanity check SRQ size before proceeding */
401 	if (attr->attr.max_wr > 1 << 16 || attr->attr.max_sge > 64)
402 		return NULL;
403 
404 	srq = malloc(sizeof *srq);
405 	if (!srq)
406 		return NULL;
407 
408 	if (pthread_spin_init(&srq->lock, PTHREAD_PROCESS_PRIVATE))
409 		goto err;
410 
411 	srq->max     = align_queue_size(pd->context, attr->attr.max_wr, 1);
412 	srq->max_gs  = attr->attr.max_sge;
413 	srq->counter = 0;
414 
415 	if (mthca_alloc_srq_buf(pd, &attr->attr, srq))
416 		goto err;
417 
418 	srq->mr = __mthca_reg_mr(pd, srq->buf.buf, srq->buf_size, 0, 0, 0);
419 	if (!srq->mr)
420 		goto err_free;
421 
422 	srq->mr->context = pd->context;
423 
424 	if (mthca_is_memfree(pd->context)) {
425 		srq->db_index = mthca_alloc_db(to_mctx(pd->context)->db_tab,
426 					       MTHCA_DB_TYPE_SRQ, &srq->db);
427 		if (srq->db_index < 0)
428 			goto err_unreg;
429 
430 		cmd.db_page  = db_align(srq->db);
431 		cmd.db_index = srq->db_index;
432 	} else {
433 		cmd.db_page  = cmd.db_index = 0;
434 	}
435 
436 	cmd.lkey = srq->mr->lkey;
437 
438 	ret = ibv_cmd_create_srq(pd, &srq->ibv_srq, attr,
439 				 &cmd.ibv_cmd, sizeof cmd,
440 				 &resp.ibv_resp, sizeof resp);
441 	if (ret)
442 		goto err_db;
443 
444 	srq->srqn = resp.srqn;
445 
446 	if (mthca_is_memfree(pd->context))
447 		mthca_set_db_qn(srq->db, MTHCA_DB_TYPE_SRQ, srq->srqn);
448 
449 	return &srq->ibv_srq;
450 
451 err_db:
452 	if (mthca_is_memfree(pd->context))
453 		mthca_free_db(to_mctx(pd->context)->db_tab, MTHCA_DB_TYPE_SRQ,
454 			      srq->db_index);
455 
456 err_unreg:
457 	mthca_dereg_mr(srq->mr);
458 
459 err_free:
460 	free(srq->wrid);
461 	mthca_free_buf(&srq->buf);
462 
463 err:
464 	free(srq);
465 
466 	return NULL;
467 }
468 
mthca_modify_srq(struct ibv_srq * srq,struct ibv_srq_attr * attr,enum ibv_srq_attr_mask attr_mask)469 int mthca_modify_srq(struct ibv_srq *srq,
470 		     struct ibv_srq_attr *attr,
471 		     enum ibv_srq_attr_mask attr_mask)
472 {
473 	struct ibv_modify_srq cmd;
474 
475 	return ibv_cmd_modify_srq(srq, attr, attr_mask, &cmd, sizeof cmd);
476 }
477 
mthca_query_srq(struct ibv_srq * srq,struct ibv_srq_attr * attr)478 int mthca_query_srq(struct ibv_srq *srq,
479 		    struct ibv_srq_attr *attr)
480 {
481 	struct ibv_query_srq cmd;
482 
483 	return ibv_cmd_query_srq(srq, attr, &cmd, sizeof cmd);
484 }
485 
mthca_destroy_srq(struct ibv_srq * srq)486 int mthca_destroy_srq(struct ibv_srq *srq)
487 {
488 	int ret;
489 
490 	ret = ibv_cmd_destroy_srq(srq);
491 	if (ret)
492 		return ret;
493 
494 	if (mthca_is_memfree(srq->context))
495 		mthca_free_db(to_mctx(srq->context)->db_tab, MTHCA_DB_TYPE_SRQ,
496 			      to_msrq(srq)->db_index);
497 
498 	mthca_dereg_mr(to_msrq(srq)->mr);
499 
500 	mthca_free_buf(&to_msrq(srq)->buf);
501 	free(to_msrq(srq)->wrid);
502 	free(to_msrq(srq));
503 
504 	return 0;
505 }
506 
mthca_create_qp(struct ibv_pd * pd,struct ibv_qp_init_attr * attr)507 struct ibv_qp *mthca_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr *attr)
508 {
509 	struct mthca_create_qp    cmd;
510 	struct ibv_create_qp_resp resp;
511 	struct mthca_qp          *qp;
512 	int                       ret;
513 
514 	/* Sanity check QP size before proceeding */
515 	if (attr->cap.max_send_wr     > 65536 ||
516 	    attr->cap.max_recv_wr     > 65536 ||
517 	    attr->cap.max_send_sge    > 64    ||
518 	    attr->cap.max_recv_sge    > 64    ||
519 	    attr->cap.max_inline_data > 1024)
520 		return NULL;
521 
522 	qp = malloc(sizeof *qp);
523 	if (!qp)
524 		return NULL;
525 
526 	qp->sq.max = align_queue_size(pd->context, attr->cap.max_send_wr, 0);
527 	qp->rq.max = align_queue_size(pd->context, attr->cap.max_recv_wr, 0);
528 
529 	if (mthca_alloc_qp_buf(pd, &attr->cap, attr->qp_type, qp))
530 		goto err;
531 
532 	mthca_init_qp_indices(qp);
533 
534 	if (pthread_spin_init(&qp->sq.lock, PTHREAD_PROCESS_PRIVATE) ||
535 	    pthread_spin_init(&qp->rq.lock, PTHREAD_PROCESS_PRIVATE))
536 		goto err_free;
537 
538 	qp->mr = __mthca_reg_mr(pd, qp->buf.buf, qp->buf_size, 0, 0, 0);
539 	if (!qp->mr)
540 		goto err_free;
541 
542 	qp->mr->context = pd->context;
543 
544 	cmd.lkey     = qp->mr->lkey;
545 	cmd.reserved = 0;
546 
547 	if (mthca_is_memfree(pd->context)) {
548 		qp->sq.db_index = mthca_alloc_db(to_mctx(pd->context)->db_tab,
549 						 MTHCA_DB_TYPE_SQ,
550 						 &qp->sq.db);
551 		if (qp->sq.db_index < 0)
552 			goto err_unreg;
553 
554 		qp->rq.db_index = mthca_alloc_db(to_mctx(pd->context)->db_tab,
555 						 MTHCA_DB_TYPE_RQ,
556 						 &qp->rq.db);
557 		if (qp->rq.db_index < 0)
558 			goto err_sq_db;
559 
560 		cmd.sq_db_page  = db_align(qp->sq.db);
561 		cmd.rq_db_page  = db_align(qp->rq.db);
562 		cmd.sq_db_index = qp->sq.db_index;
563 		cmd.rq_db_index = qp->rq.db_index;
564 	} else {
565 		cmd.sq_db_page  = cmd.rq_db_page  =
566 		cmd.sq_db_index = cmd.rq_db_index = 0;
567 	}
568 
569 	pthread_mutex_lock(&to_mctx(pd->context)->qp_table_mutex);
570 	ret = ibv_cmd_create_qp(pd, &qp->ibv_qp, attr, &cmd.ibv_cmd, sizeof cmd,
571 				&resp, sizeof resp);
572 	if (ret)
573 		goto err_rq_db;
574 
575 	if (mthca_is_memfree(pd->context)) {
576 		mthca_set_db_qn(qp->sq.db, MTHCA_DB_TYPE_SQ, qp->ibv_qp.qp_num);
577 		mthca_set_db_qn(qp->rq.db, MTHCA_DB_TYPE_RQ, qp->ibv_qp.qp_num);
578 	}
579 
580 	ret = mthca_store_qp(to_mctx(pd->context), qp->ibv_qp.qp_num, qp);
581 	if (ret)
582 		goto err_destroy;
583 	pthread_mutex_unlock(&to_mctx(pd->context)->qp_table_mutex);
584 
585 	qp->sq.max 	    = attr->cap.max_send_wr;
586 	qp->rq.max 	    = attr->cap.max_recv_wr;
587 	qp->sq.max_gs 	    = attr->cap.max_send_sge;
588 	qp->rq.max_gs 	    = attr->cap.max_recv_sge;
589 	qp->max_inline_data = attr->cap.max_inline_data;
590 
591 	return &qp->ibv_qp;
592 
593 err_destroy:
594 	ibv_cmd_destroy_qp(&qp->ibv_qp);
595 
596 err_rq_db:
597 	pthread_mutex_unlock(&to_mctx(pd->context)->qp_table_mutex);
598 	if (mthca_is_memfree(pd->context))
599 		mthca_free_db(to_mctx(pd->context)->db_tab, MTHCA_DB_TYPE_RQ,
600 			      qp->rq.db_index);
601 
602 err_sq_db:
603 	if (mthca_is_memfree(pd->context))
604 		mthca_free_db(to_mctx(pd->context)->db_tab, MTHCA_DB_TYPE_SQ,
605 			      qp->sq.db_index);
606 
607 err_unreg:
608 	mthca_dereg_mr(qp->mr);
609 
610 err_free:
611 	free(qp->wrid);
612 	mthca_free_buf(&qp->buf);
613 
614 err:
615 	free(qp);
616 
617 	return NULL;
618 }
619 
mthca_query_qp(struct ibv_qp * qp,struct ibv_qp_attr * attr,enum ibv_qp_attr_mask attr_mask,struct ibv_qp_init_attr * init_attr)620 int mthca_query_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,
621 		   enum ibv_qp_attr_mask attr_mask,
622 		   struct ibv_qp_init_attr *init_attr)
623 {
624 	struct ibv_query_qp cmd;
625 
626 	return ibv_cmd_query_qp(qp, attr, attr_mask, init_attr, &cmd, sizeof cmd);
627 }
628 
mthca_modify_qp(struct ibv_qp * qp,struct ibv_qp_attr * attr,enum ibv_qp_attr_mask attr_mask)629 int mthca_modify_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,
630 		    enum ibv_qp_attr_mask attr_mask)
631 {
632 	struct ibv_modify_qp cmd;
633 	int ret;
634 
635 	ret = ibv_cmd_modify_qp(qp, attr, attr_mask, &cmd, sizeof cmd);
636 
637 	if (!ret		       &&
638 	    (attr_mask & IBV_QP_STATE) &&
639 	    attr->qp_state == IBV_QPS_RESET) {
640 		mthca_cq_clean(to_mcq(qp->recv_cq), qp->qp_num,
641 			       qp->srq ? to_msrq(qp->srq) : NULL);
642 		if (qp->send_cq != qp->recv_cq)
643 			mthca_cq_clean(to_mcq(qp->send_cq), qp->qp_num, NULL);
644 
645 		mthca_init_qp_indices(to_mqp(qp));
646 
647 		if (mthca_is_memfree(qp->context)) {
648 			*to_mqp(qp)->sq.db = 0;
649 			*to_mqp(qp)->rq.db = 0;
650 		}
651 	}
652 
653 	return ret;
654 }
655 
mthca_lock_cqs(struct ibv_qp * qp)656 static void mthca_lock_cqs(struct ibv_qp *qp)
657 {
658 	struct mthca_cq *send_cq = to_mcq(qp->send_cq);
659 	struct mthca_cq *recv_cq = to_mcq(qp->recv_cq);
660 
661 	if (send_cq == recv_cq)
662 		pthread_spin_lock(&send_cq->lock);
663 	else if (send_cq->cqn < recv_cq->cqn) {
664 		pthread_spin_lock(&send_cq->lock);
665 		pthread_spin_lock(&recv_cq->lock);
666 	} else {
667 		pthread_spin_lock(&recv_cq->lock);
668 		pthread_spin_lock(&send_cq->lock);
669 	}
670 }
671 
mthca_unlock_cqs(struct ibv_qp * qp)672 static void mthca_unlock_cqs(struct ibv_qp *qp)
673 {
674 	struct mthca_cq *send_cq = to_mcq(qp->send_cq);
675 	struct mthca_cq *recv_cq = to_mcq(qp->recv_cq);
676 
677 	if (send_cq == recv_cq)
678 		pthread_spin_unlock(&send_cq->lock);
679 	else if (send_cq->cqn < recv_cq->cqn) {
680 		pthread_spin_unlock(&recv_cq->lock);
681 		pthread_spin_unlock(&send_cq->lock);
682 	} else {
683 		pthread_spin_unlock(&send_cq->lock);
684 		pthread_spin_unlock(&recv_cq->lock);
685 	}
686 }
687 
mthca_destroy_qp(struct ibv_qp * qp)688 int mthca_destroy_qp(struct ibv_qp *qp)
689 {
690 	int ret;
691 
692 	pthread_mutex_lock(&to_mctx(qp->context)->qp_table_mutex);
693 	ret = ibv_cmd_destroy_qp(qp);
694 	if (ret) {
695 		pthread_mutex_unlock(&to_mctx(qp->context)->qp_table_mutex);
696 		return ret;
697 	}
698 
699 	mthca_lock_cqs(qp);
700 
701 	__mthca_cq_clean(to_mcq(qp->recv_cq), qp->qp_num,
702 			 qp->srq ? to_msrq(qp->srq) : NULL);
703 	if (qp->send_cq != qp->recv_cq)
704 		__mthca_cq_clean(to_mcq(qp->send_cq), qp->qp_num, NULL);
705 
706 	mthca_clear_qp(to_mctx(qp->context), qp->qp_num);
707 
708 	mthca_unlock_cqs(qp);
709 	pthread_mutex_unlock(&to_mctx(qp->context)->qp_table_mutex);
710 
711 	if (mthca_is_memfree(qp->context)) {
712 		mthca_free_db(to_mctx(qp->context)->db_tab, MTHCA_DB_TYPE_RQ,
713 			      to_mqp(qp)->rq.db_index);
714 		mthca_free_db(to_mctx(qp->context)->db_tab, MTHCA_DB_TYPE_SQ,
715 			      to_mqp(qp)->sq.db_index);
716 	}
717 
718 	mthca_dereg_mr(to_mqp(qp)->mr);
719 	mthca_free_buf(&to_mqp(qp)->buf);
720 	free(to_mqp(qp)->wrid);
721 	free(to_mqp(qp));
722 
723 	return 0;
724 }
725 
mthca_create_ah(struct ibv_pd * pd,struct ibv_ah_attr * attr)726 struct ibv_ah *mthca_create_ah(struct ibv_pd *pd, struct ibv_ah_attr *attr)
727 {
728 	struct mthca_ah *ah;
729 
730 	ah = malloc(sizeof *ah);
731 	if (!ah)
732 		return NULL;
733 
734 	if (mthca_alloc_av(to_mpd(pd), attr, ah)) {
735 		free(ah);
736 		return NULL;
737 	}
738 
739 	return &ah->ibv_ah;
740 }
741 
mthca_destroy_ah(struct ibv_ah * ah)742 int mthca_destroy_ah(struct ibv_ah *ah)
743 {
744 	mthca_free_av(to_mah(ah));
745 	free(to_mah(ah));
746 
747 	return 0;
748 }
749 
mthca_attach_mcast(struct ibv_qp * qp,union ibv_gid * gid,uint16_t lid)750 int mthca_attach_mcast(struct ibv_qp *qp, union ibv_gid *gid, uint16_t lid)
751 {
752 	return ibv_cmd_attach_mcast(qp, gid, lid);
753 }
754 
mthca_detach_mcast(struct ibv_qp * qp,union ibv_gid * gid,uint16_t lid)755 int mthca_detach_mcast(struct ibv_qp *qp, union ibv_gid *gid, uint16_t lid)
756 {
757 	return ibv_cmd_detach_mcast(qp, gid, lid);
758 }
759