]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ofed/libmthca/src/verbs.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ofed / libmthca / src / verbs.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }