]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ofed/libibverbs/src/cmd.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ofed / libibverbs / src / cmd.c
1 /*
2  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
3  * Copyright (c) 2005 PathScale, Inc.  All rights reserved.
4  * Copyright (c) 2006 Cisco Systems, Inc.  All rights reserved.
5  *
6  * This software is available to you under a choice of one of two
7  * licenses.  You may choose to be licensed under the terms of the GNU
8  * General Public License (GPL) Version 2, available from the file
9  * COPYING in the main directory of this source tree, or the
10  * OpenIB.org BSD license below:
11  *
12  *     Redistribution and use in source and binary forms, with or
13  *     without modification, are permitted provided that the following
14  *     conditions are met:
15  *
16  *      - Redistributions of source code must retain the above
17  *        copyright notice, this list of conditions and the following
18  *        disclaimer.
19  *
20  *      - Redistributions in binary form must reproduce the above
21  *        copyright notice, this list of conditions and the following
22  *        disclaimer in the documentation and/or other materials
23  *        provided with the distribution.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32  * SOFTWARE.
33  */
34
35 #if HAVE_CONFIG_H
36 #  include <config.h>
37 #endif /* HAVE_CONFIG_H */
38
39 #include <stdio.h>
40 #include <unistd.h>
41 #include <stdlib.h>
42 #include <errno.h>
43 #include <alloca.h>
44 #include <string.h>
45
46 #include "ibverbs.h"
47
48 static int ibv_cmd_get_context_v2(struct ibv_context *context,
49                                   struct ibv_get_context *new_cmd,
50                                   size_t new_cmd_size,
51                                   struct ibv_get_context_resp *resp,
52                                   size_t resp_size)
53 {
54         struct ibv_abi_compat_v2 *t;
55         struct ibv_get_context_v2 *cmd;
56         size_t cmd_size;
57         uint32_t cq_fd;
58
59         t = malloc(sizeof *t);
60         if (!t)
61                 return ENOMEM;
62         pthread_mutex_init(&t->in_use, NULL);
63
64         cmd_size = sizeof *cmd + new_cmd_size - sizeof *new_cmd;
65         cmd      = alloca(cmd_size);
66         memcpy(cmd->driver_data, new_cmd->driver_data, new_cmd_size - sizeof *new_cmd);
67
68         IBV_INIT_CMD_RESP(cmd, cmd_size, GET_CONTEXT, resp, resp_size);
69         cmd->cq_fd_tab = (uintptr_t) &cq_fd;
70
71         if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
72                 return errno;
73
74         VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
75
76         context->async_fd         = resp->async_fd;
77         context->num_comp_vectors = 1;
78         t->channel.context        = context;
79         t->channel.fd             = cq_fd;
80         t->channel.refcnt         = 0;
81         context->abi_compat       = t;
82
83         return 0;
84 }
85
86 int ibv_cmd_get_context(struct ibv_context *context, struct ibv_get_context *cmd,
87                         size_t cmd_size, struct ibv_get_context_resp *resp,
88                         size_t resp_size)
89 {
90         if (abi_ver <= 2)
91                 return ibv_cmd_get_context_v2(context, cmd, cmd_size, resp, resp_size);
92
93         IBV_INIT_CMD_RESP(cmd, cmd_size, GET_CONTEXT, resp, resp_size);
94
95         if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
96                 return errno;
97
98         VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
99
100         context->async_fd         = resp->async_fd;
101         context->num_comp_vectors = resp->num_comp_vectors;
102
103         return 0;
104 }
105
106 int ibv_cmd_query_device(struct ibv_context *context,
107                          struct ibv_device_attr *device_attr,
108                          uint64_t *raw_fw_ver,
109                          struct ibv_query_device *cmd, size_t cmd_size)
110 {
111         struct ibv_query_device_resp resp;
112
113         IBV_INIT_CMD_RESP(cmd, cmd_size, QUERY_DEVICE, &resp, sizeof resp);
114
115         if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
116                 return errno;
117
118         VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
119
120         memset(device_attr->fw_ver, 0, sizeof device_attr->fw_ver);
121         *raw_fw_ver                            = resp.fw_ver;
122         device_attr->node_guid                 = resp.node_guid;
123         device_attr->sys_image_guid            = resp.sys_image_guid;
124         device_attr->max_mr_size               = resp.max_mr_size;
125         device_attr->page_size_cap             = resp.page_size_cap;
126         device_attr->vendor_id                 = resp.vendor_id;
127         device_attr->vendor_part_id            = resp.vendor_part_id;
128         device_attr->hw_ver                    = resp.hw_ver;
129         device_attr->max_qp                    = resp.max_qp;
130         device_attr->max_qp_wr                 = resp.max_qp_wr;
131         device_attr->device_cap_flags          = resp.device_cap_flags;
132         device_attr->max_sge                   = resp.max_sge;
133         device_attr->max_sge_rd                = resp.max_sge_rd;
134         device_attr->max_cq                    = resp.max_cq;
135         device_attr->max_cqe                   = resp.max_cqe;
136         device_attr->max_mr                    = resp.max_mr;
137         device_attr->max_pd                    = resp.max_pd;
138         device_attr->max_qp_rd_atom            = resp.max_qp_rd_atom;
139         device_attr->max_ee_rd_atom            = resp.max_ee_rd_atom;
140         device_attr->max_res_rd_atom           = resp.max_res_rd_atom;
141         device_attr->max_qp_init_rd_atom       = resp.max_qp_init_rd_atom;
142         device_attr->max_ee_init_rd_atom       = resp.max_ee_init_rd_atom;
143         device_attr->atomic_cap                = resp.atomic_cap;
144         device_attr->max_ee                    = resp.max_ee;
145         device_attr->max_rdd                   = resp.max_rdd;
146         device_attr->max_mw                    = resp.max_mw;
147         device_attr->max_raw_ipv6_qp           = resp.max_raw_ipv6_qp;
148         device_attr->max_raw_ethy_qp           = resp.max_raw_ethy_qp;
149         device_attr->max_mcast_grp             = resp.max_mcast_grp;
150         device_attr->max_mcast_qp_attach       = resp.max_mcast_qp_attach;
151         device_attr->max_total_mcast_qp_attach = resp.max_total_mcast_qp_attach;
152         device_attr->max_ah                    = resp.max_ah;
153         device_attr->max_fmr                   = resp.max_fmr;
154         device_attr->max_map_per_fmr           = resp.max_map_per_fmr;
155         device_attr->max_srq                   = resp.max_srq;
156         device_attr->max_srq_wr                = resp.max_srq_wr;
157         device_attr->max_srq_sge               = resp.max_srq_sge;
158         device_attr->max_pkeys                 = resp.max_pkeys;
159         device_attr->local_ca_ack_delay        = resp.local_ca_ack_delay;
160         device_attr->phys_port_cnt             = resp.phys_port_cnt;
161
162         return 0;
163 }
164
165 int ibv_cmd_query_port(struct ibv_context *context, uint8_t port_num,
166                        struct ibv_port_attr *port_attr,
167                        struct ibv_query_port *cmd, size_t cmd_size)
168 {
169         struct ibv_query_port_resp resp;
170
171         IBV_INIT_CMD_RESP(cmd, cmd_size, QUERY_PORT, &resp, sizeof resp);
172         cmd->port_num = port_num;
173         memset(cmd->reserved, 0, sizeof cmd->reserved);
174
175         if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
176                 return errno;
177
178         VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
179
180         port_attr->state           = resp.state;
181         port_attr->max_mtu         = resp.max_mtu;
182         port_attr->active_mtu      = resp.active_mtu;
183         port_attr->gid_tbl_len     = resp.gid_tbl_len;
184         port_attr->port_cap_flags  = resp.port_cap_flags;
185         port_attr->max_msg_sz      = resp.max_msg_sz;
186         port_attr->bad_pkey_cntr   = resp.bad_pkey_cntr;
187         port_attr->qkey_viol_cntr  = resp.qkey_viol_cntr;
188         port_attr->pkey_tbl_len    = resp.pkey_tbl_len;
189         port_attr->lid             = resp.lid;
190         port_attr->sm_lid          = resp.sm_lid;
191         port_attr->lmc             = resp.lmc;
192         port_attr->max_vl_num      = resp.max_vl_num;
193         port_attr->sm_sl           = resp.sm_sl;
194         port_attr->subnet_timeout  = resp.subnet_timeout;
195         port_attr->init_type_reply = resp.init_type_reply;
196         port_attr->active_width    = resp.active_width;
197         port_attr->active_speed    = resp.active_speed;
198         port_attr->phys_state      = resp.phys_state;
199         port_attr->link_layer      = resp.link_layer;
200
201         return 0;
202 }
203
204 int ibv_cmd_alloc_pd(struct ibv_context *context, struct ibv_pd *pd,
205                      struct ibv_alloc_pd *cmd, size_t cmd_size,
206                      struct ibv_alloc_pd_resp *resp, size_t resp_size)
207 {
208         IBV_INIT_CMD_RESP(cmd, cmd_size, ALLOC_PD, resp, resp_size);
209
210         if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
211                 return errno;
212
213         VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
214
215         pd->handle  = resp->pd_handle;
216         pd->context = context;
217
218         return 0;
219 }
220
221 int ibv_cmd_dealloc_pd(struct ibv_pd *pd)
222 {
223         struct ibv_dealloc_pd cmd;
224
225         IBV_INIT_CMD(&cmd, sizeof cmd, DEALLOC_PD);
226         cmd.pd_handle = pd->handle;
227
228         if (write(pd->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
229                 return errno;
230
231         return 0;
232 }
233
234 int ibv_cmd_reg_mr(struct ibv_pd *pd, void *addr, size_t length,
235                    uint64_t hca_va, int access,
236                    struct ibv_mr *mr, struct ibv_reg_mr *cmd,
237                    size_t cmd_size,
238                    struct ibv_reg_mr_resp *resp, size_t resp_size)
239 {
240
241         IBV_INIT_CMD_RESP(cmd, cmd_size, REG_MR, resp, resp_size);
242
243         cmd->start        = (uintptr_t) addr;
244         cmd->length       = length;
245         cmd->hca_va       = hca_va;
246         cmd->pd_handle    = pd->handle;
247         cmd->access_flags = access;
248
249         if (write(pd->context->cmd_fd, cmd, cmd_size) != cmd_size)
250                 return errno;
251
252         VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
253
254         mr->handle  = resp->mr_handle;
255         mr->lkey    = resp->lkey;
256         mr->rkey    = resp->rkey;
257         mr->context = pd->context;
258
259         return 0;
260 }
261
262 int ibv_cmd_dereg_mr(struct ibv_mr *mr)
263 {
264         struct ibv_dereg_mr cmd;
265
266         IBV_INIT_CMD(&cmd, sizeof cmd, DEREG_MR);
267         cmd.mr_handle = mr->handle;
268
269         if (write(mr->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
270                 return errno;
271
272         return 0;
273 }
274
275 static int ibv_cmd_create_cq_v2(struct ibv_context *context, int cqe,
276                                 struct ibv_cq *cq,
277                                 struct ibv_create_cq *new_cmd, size_t new_cmd_size,
278                                 struct ibv_create_cq_resp *resp, size_t resp_size)
279 {
280         struct ibv_create_cq_v2 *cmd;
281         size_t cmd_size;
282
283         cmd_size = sizeof *cmd + new_cmd_size - sizeof *new_cmd;
284         cmd      = alloca(cmd_size);
285         memcpy(cmd->driver_data, new_cmd->driver_data, new_cmd_size - sizeof *new_cmd);
286
287         IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_CQ, resp, resp_size);
288         cmd->user_handle   = (uintptr_t) cq;
289         cmd->cqe           = cqe;
290         cmd->event_handler = 0;
291
292         if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
293                 return errno;
294
295         VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
296
297         cq->handle  = resp->cq_handle;
298         cq->cqe     = resp->cqe;
299         cq->context = context;
300
301         return 0;
302 }
303
304 int ibv_cmd_create_cq(struct ibv_context *context, int cqe,
305                       struct ibv_comp_channel *channel,
306                       int comp_vector, struct ibv_cq *cq,
307                       struct ibv_create_cq *cmd, size_t cmd_size,
308                       struct ibv_create_cq_resp *resp, size_t resp_size)
309 {
310         if (abi_ver <= 2)
311                 return ibv_cmd_create_cq_v2(context, cqe, cq,
312                                             cmd, cmd_size, resp, resp_size);
313
314         IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_CQ, resp, resp_size);
315         cmd->user_handle   = (uintptr_t) cq;
316         cmd->cqe           = cqe;
317         cmd->comp_vector   = comp_vector;
318         cmd->comp_channel  = channel ? channel->fd : -1;
319         cmd->reserved      = 0;
320
321         if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
322                 return errno;
323
324         VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
325
326         cq->handle  = resp->cq_handle;
327         cq->cqe     = resp->cqe;
328         cq->context = context;
329
330         return 0;
331 }
332
333 int ibv_cmd_poll_cq(struct ibv_cq *ibcq, int ne, struct ibv_wc *wc)
334 {
335         struct ibv_poll_cq       cmd;
336         struct ibv_poll_cq_resp *resp;
337         int                      i;
338         int                      rsize;
339         int                      ret;
340
341         rsize = sizeof *resp + ne * sizeof(struct ibv_kern_wc);
342         resp  = malloc(rsize);
343         if (!resp)
344                 return -1;
345
346         IBV_INIT_CMD_RESP(&cmd, sizeof cmd, POLL_CQ, resp, rsize);
347         cmd.cq_handle = ibcq->handle;
348         cmd.ne        = ne;
349
350         if (write(ibcq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd) {
351                 ret = -1;
352                 goto out;
353         }
354
355         VALGRIND_MAKE_MEM_DEFINED(resp, rsize);
356
357         for (i = 0; i < resp->count; i++) {
358                 wc[i].wr_id          = resp->wc[i].wr_id;
359                 wc[i].status         = resp->wc[i].status;
360                 wc[i].opcode         = resp->wc[i].opcode;
361                 wc[i].vendor_err     = resp->wc[i].vendor_err;
362                 wc[i].byte_len       = resp->wc[i].byte_len;
363                 wc[i].imm_data       = resp->wc[i].imm_data;
364                 wc[i].qp_num         = resp->wc[i].qp_num;
365                 wc[i].src_qp         = resp->wc[i].src_qp;
366                 wc[i].wc_flags       = resp->wc[i].wc_flags;
367                 wc[i].pkey_index     = resp->wc[i].pkey_index;
368                 wc[i].slid           = resp->wc[i].slid;
369                 wc[i].sl             = resp->wc[i].sl;
370                 wc[i].dlid_path_bits = resp->wc[i].dlid_path_bits;
371         }
372
373         ret = resp->count;
374
375 out:
376         free(resp);
377         return ret;
378 }
379
380 int ibv_cmd_req_notify_cq(struct ibv_cq *ibcq, int solicited_only)
381 {
382         struct ibv_req_notify_cq cmd;
383
384         IBV_INIT_CMD(&cmd, sizeof cmd, REQ_NOTIFY_CQ);
385         cmd.cq_handle = ibcq->handle;
386         cmd.solicited = !!solicited_only;
387
388         if (write(ibcq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
389                 return errno;
390
391         return 0;
392 }
393
394 int ibv_cmd_resize_cq(struct ibv_cq *cq, int cqe,
395                       struct ibv_resize_cq *cmd, size_t cmd_size,
396                       struct ibv_resize_cq_resp *resp, size_t resp_size)
397 {
398
399         IBV_INIT_CMD_RESP(cmd, cmd_size, RESIZE_CQ, resp, resp_size);
400         cmd->cq_handle = cq->handle;
401         cmd->cqe       = cqe;
402
403         if (write(cq->context->cmd_fd, cmd, cmd_size) != cmd_size)
404                 return errno;
405
406         VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
407
408         cq->cqe = resp->cqe;
409
410         return 0;
411 }
412
413 static int ibv_cmd_destroy_cq_v1(struct ibv_cq *cq)
414 {
415         struct ibv_destroy_cq_v1 cmd;
416
417         IBV_INIT_CMD(&cmd, sizeof cmd, DESTROY_CQ);
418         cmd.cq_handle = cq->handle;
419
420         if (write(cq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
421                 return errno;
422
423         return 0;
424 }
425
426 int ibv_cmd_destroy_cq(struct ibv_cq *cq)
427 {
428         struct ibv_destroy_cq      cmd;
429         struct ibv_destroy_cq_resp resp;
430
431         if (abi_ver == 1)
432                 return ibv_cmd_destroy_cq_v1(cq);
433
434         IBV_INIT_CMD_RESP(&cmd, sizeof cmd, DESTROY_CQ, &resp, sizeof resp);
435         cmd.cq_handle = cq->handle;
436         cmd.reserved  = 0;
437
438         if (write(cq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
439                 return errno;
440
441         VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
442
443         pthread_mutex_lock(&cq->mutex);
444         while (cq->comp_events_completed  != resp.comp_events_reported ||
445                cq->async_events_completed != resp.async_events_reported)
446                 pthread_cond_wait(&cq->cond, &cq->mutex);
447         pthread_mutex_unlock(&cq->mutex);
448
449         return 0;
450 }
451
452 int ibv_cmd_create_srq(struct ibv_pd *pd,
453                        struct ibv_srq *srq, struct ibv_srq_init_attr *attr,
454                        struct ibv_create_srq *cmd, size_t cmd_size,
455                        struct ibv_create_srq_resp *resp, size_t resp_size)
456 {
457         IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_SRQ, resp, resp_size);
458         cmd->user_handle = (uintptr_t) srq;
459         cmd->pd_handle   = pd->handle;
460         cmd->max_wr      = attr->attr.max_wr;
461         cmd->max_sge     = attr->attr.max_sge;
462         cmd->srq_limit   = attr->attr.srq_limit;
463
464         if (write(pd->context->cmd_fd, cmd, cmd_size) != cmd_size)
465                 return errno;
466
467         VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
468
469         srq->handle  = resp->srq_handle;
470         srq->context = pd->context;
471
472         if (abi_ver > 5) {
473                 attr->attr.max_wr = resp->max_wr;
474                 attr->attr.max_sge = resp->max_sge;
475         } else {
476                 struct ibv_create_srq_resp_v5 *resp_v5 =
477                         (struct ibv_create_srq_resp_v5 *) resp;
478
479                 memmove((void *) resp + sizeof *resp,
480                         (void *) resp_v5 + sizeof *resp_v5,
481                         resp_size - sizeof *resp);
482         }
483
484         return 0;
485 }
486
487 int ibv_cmd_create_xrc_srq(struct ibv_pd *pd,
488                        struct ibv_srq *srq, struct ibv_srq_init_attr *attr,
489                        uint32_t xrcd_handle, uint32_t xrc_cq,
490                        struct ibv_create_xrc_srq *cmd, size_t cmd_size,
491                        struct ibv_create_srq_resp *resp, size_t resp_size)
492 {
493         IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_XRC_SRQ, resp, resp_size);
494         cmd->user_handle = (uintptr_t) srq;
495         cmd->pd_handle   = pd->handle;
496         cmd->max_wr      = attr->attr.max_wr;
497         cmd->max_sge     = attr->attr.max_sge;
498         cmd->srq_limit   = attr->attr.srq_limit;
499         cmd->xrcd_handle = xrcd_handle;
500         cmd->xrc_cq      = xrc_cq;
501
502         if (write(pd->context->cmd_fd, cmd, cmd_size) != cmd_size)
503                 return errno;
504
505         VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
506
507         srq->handle  = resp->srq_handle;
508         srq->context = pd->context;
509         attr->attr.max_wr = resp->max_wr;
510         attr->attr.max_sge = resp->max_sge;
511
512         return 0;
513 }
514
515 static int ibv_cmd_modify_srq_v3(struct ibv_srq *srq,
516                                  struct ibv_srq_attr *srq_attr,
517                                  int srq_attr_mask,
518                                  struct ibv_modify_srq *new_cmd,
519                                  size_t new_cmd_size)
520 {
521         struct ibv_modify_srq_v3 *cmd;
522         size_t cmd_size;
523
524         cmd_size = sizeof *cmd + new_cmd_size - sizeof *new_cmd;
525         cmd      = alloca(cmd_size);
526         memcpy(cmd->driver_data, new_cmd->driver_data, new_cmd_size - sizeof *new_cmd);
527
528         IBV_INIT_CMD(cmd, cmd_size, MODIFY_SRQ);
529
530         cmd->srq_handle = srq->handle;
531         cmd->attr_mask  = srq_attr_mask;
532         cmd->max_wr     = srq_attr->max_wr;
533         cmd->srq_limit  = srq_attr->srq_limit;
534         cmd->max_sge    = 0;
535         cmd->reserved   = 0;
536
537         if (write(srq->context->cmd_fd, cmd, cmd_size) != cmd_size)
538                 return errno;
539
540         return 0;
541 }
542
543 int ibv_cmd_modify_srq(struct ibv_srq *srq,
544                        struct ibv_srq_attr *srq_attr,
545                        int srq_attr_mask,
546                        struct ibv_modify_srq *cmd, size_t cmd_size)
547 {
548         if (abi_ver == 3)
549                 return ibv_cmd_modify_srq_v3(srq, srq_attr, srq_attr_mask,
550                                              cmd, cmd_size);
551
552         IBV_INIT_CMD(cmd, cmd_size, MODIFY_SRQ);
553
554         cmd->srq_handle = srq->handle;
555         cmd->attr_mask  = srq_attr_mask;
556         cmd->max_wr     = srq_attr->max_wr;
557         cmd->srq_limit  = srq_attr->srq_limit;
558
559         if (write(srq->context->cmd_fd, cmd, cmd_size) != cmd_size)
560                 return errno;
561
562         return 0;
563 }
564
565 int ibv_cmd_query_srq(struct ibv_srq *srq, struct ibv_srq_attr *srq_attr,
566                       struct ibv_query_srq *cmd, size_t cmd_size)
567 {
568         struct ibv_query_srq_resp resp;
569
570         IBV_INIT_CMD_RESP(cmd, cmd_size, QUERY_SRQ, &resp, sizeof resp);
571         cmd->srq_handle = srq->handle;
572         cmd->reserved   = 0;
573
574         if (write(srq->context->cmd_fd, cmd, cmd_size) != cmd_size)
575                 return errno;
576
577         VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
578
579         srq_attr->max_wr    = resp.max_wr;
580         srq_attr->max_sge   = resp.max_sge;
581         srq_attr->srq_limit = resp.srq_limit;
582
583         return 0;
584 }
585
586 static int ibv_cmd_destroy_srq_v1(struct ibv_srq *srq)
587 {
588         struct ibv_destroy_srq_v1 cmd;
589
590         IBV_INIT_CMD(&cmd, sizeof cmd, DESTROY_SRQ);
591         cmd.srq_handle = srq->handle;
592
593         if (write(srq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
594                 return errno;
595
596         return 0;
597 }
598
599 int ibv_cmd_destroy_srq(struct ibv_srq *srq)
600 {
601         struct ibv_destroy_srq      cmd;
602         struct ibv_destroy_srq_resp resp;
603
604         if (abi_ver == 1)
605                 return ibv_cmd_destroy_srq_v1(srq);
606
607         IBV_INIT_CMD_RESP(&cmd, sizeof cmd, DESTROY_SRQ, &resp, sizeof resp);
608         cmd.srq_handle = srq->handle;
609         cmd.reserved   = 0;
610
611         if (write(srq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
612                 return errno;
613
614         VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
615
616         pthread_mutex_lock(&srq->mutex);
617         while (srq->events_completed != resp.events_reported)
618                 pthread_cond_wait(&srq->cond, &srq->mutex);
619         pthread_mutex_unlock(&srq->mutex);
620
621         return 0;
622 }
623
624 int ibv_cmd_create_qp(struct ibv_pd *pd,
625                       struct ibv_qp *qp, struct ibv_qp_init_attr *attr,
626                       struct ibv_create_qp *cmd, size_t cmd_size,
627                       struct ibv_create_qp_resp *resp, size_t resp_size)
628 {
629         IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_QP, resp, resp_size);
630
631         cmd->user_handle     = (uintptr_t) qp;
632         cmd->pd_handle       = pd->handle;
633         cmd->send_cq_handle  = attr->send_cq->handle;
634         cmd->recv_cq_handle  = attr->recv_cq->handle;
635         cmd->max_send_wr     = attr->cap.max_send_wr;
636         cmd->max_recv_wr     = attr->cap.max_recv_wr;
637         cmd->max_send_sge    = attr->cap.max_send_sge;
638         cmd->max_recv_sge    = attr->cap.max_recv_sge;
639         cmd->max_inline_data = attr->cap.max_inline_data;
640         cmd->sq_sig_all      = attr->sq_sig_all;
641         cmd->qp_type         = attr->qp_type;
642         cmd->is_srq          = !!attr->srq;
643         cmd->srq_handle      = attr->qp_type == IBV_QPT_XRC ?
644                 (attr->xrc_domain ? attr->xrc_domain->handle : 0) :
645                 (attr->srq ? attr->srq->handle : 0);
646         cmd->reserved        = 0;
647
648         if (write(pd->context->cmd_fd, cmd, cmd_size) != cmd_size)
649                 return errno;
650
651         VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
652
653         qp->handle                = resp->qp_handle;
654         qp->qp_num                = resp->qpn;
655         qp->context               = pd->context;
656
657         if (abi_ver > 3) {
658                 attr->cap.max_recv_sge    = resp->max_recv_sge;
659                 attr->cap.max_send_sge    = resp->max_send_sge;
660                 attr->cap.max_recv_wr     = resp->max_recv_wr;
661                 attr->cap.max_send_wr     = resp->max_send_wr;
662                 attr->cap.max_inline_data = resp->max_inline_data;
663         }
664
665         if (abi_ver == 4) {
666                 struct ibv_create_qp_resp_v4 *resp_v4 =
667                         (struct ibv_create_qp_resp_v4 *) resp;
668
669                 memmove((void *) resp + sizeof *resp,
670                         (void *) resp_v4 + sizeof *resp_v4,
671                         resp_size - sizeof *resp);
672         } else if (abi_ver <= 3) {
673                 struct ibv_create_qp_resp_v3 *resp_v3 =
674                         (struct ibv_create_qp_resp_v3 *) resp;
675
676                 memmove((void *) resp + sizeof *resp,
677                         (void *) resp_v3 + sizeof *resp_v3,
678                         resp_size - sizeof *resp);
679         }
680
681         return 0;
682 }
683
684 int ibv_cmd_query_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,
685                      int attr_mask,
686                      struct ibv_qp_init_attr *init_attr,
687                      struct ibv_query_qp *cmd, size_t cmd_size)
688 {
689         struct ibv_query_qp_resp resp;
690
691         IBV_INIT_CMD_RESP(cmd, cmd_size, QUERY_QP, &resp, sizeof resp);
692         cmd->qp_handle = qp->handle;
693         cmd->attr_mask = attr_mask;
694
695         if (write(qp->context->cmd_fd, cmd, cmd_size) != cmd_size)
696                 return errno;
697
698         VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
699
700         attr->qkey                          = resp.qkey;
701         attr->rq_psn                        = resp.rq_psn;
702         attr->sq_psn                        = resp.sq_psn;
703         attr->dest_qp_num                   = resp.dest_qp_num;
704         attr->qp_access_flags               = resp.qp_access_flags;
705         attr->pkey_index                    = resp.pkey_index;
706         attr->alt_pkey_index                = resp.alt_pkey_index;
707         attr->qp_state                      = resp.qp_state;
708         attr->cur_qp_state                  = resp.cur_qp_state;
709         attr->path_mtu                      = resp.path_mtu;
710         attr->path_mig_state                = resp.path_mig_state;
711         attr->sq_draining                   = resp.sq_draining;
712         attr->max_rd_atomic                 = resp.max_rd_atomic;
713         attr->max_dest_rd_atomic            = resp.max_dest_rd_atomic;
714         attr->min_rnr_timer                 = resp.min_rnr_timer;
715         attr->port_num                      = resp.port_num;
716         attr->timeout                       = resp.timeout;
717         attr->retry_cnt                     = resp.retry_cnt;
718         attr->rnr_retry                     = resp.rnr_retry;
719         attr->alt_port_num                  = resp.alt_port_num;
720         attr->alt_timeout                   = resp.alt_timeout;
721         attr->cap.max_send_wr               = resp.max_send_wr;
722         attr->cap.max_recv_wr               = resp.max_recv_wr;
723         attr->cap.max_send_sge              = resp.max_send_sge;
724         attr->cap.max_recv_sge              = resp.max_recv_sge;
725         attr->cap.max_inline_data           = resp.max_inline_data;
726
727         memcpy(attr->ah_attr.grh.dgid.raw, resp.dest.dgid, 16);
728         attr->ah_attr.grh.flow_label        = resp.dest.flow_label;
729         attr->ah_attr.dlid                  = resp.dest.dlid;
730         attr->ah_attr.grh.sgid_index        = resp.dest.sgid_index;
731         attr->ah_attr.grh.hop_limit         = resp.dest.hop_limit;
732         attr->ah_attr.grh.traffic_class     = resp.dest.traffic_class;
733         attr->ah_attr.sl                    = resp.dest.sl;
734         attr->ah_attr.src_path_bits         = resp.dest.src_path_bits;
735         attr->ah_attr.static_rate           = resp.dest.static_rate;
736         attr->ah_attr.is_global             = resp.dest.is_global;
737         attr->ah_attr.port_num              = resp.dest.port_num;
738
739         memcpy(attr->alt_ah_attr.grh.dgid.raw, resp.alt_dest.dgid, 16);
740         attr->alt_ah_attr.grh.flow_label    = resp.alt_dest.flow_label;
741         attr->alt_ah_attr.dlid              = resp.alt_dest.dlid;
742         attr->alt_ah_attr.grh.sgid_index    = resp.alt_dest.sgid_index;
743         attr->alt_ah_attr.grh.hop_limit     = resp.alt_dest.hop_limit;
744         attr->alt_ah_attr.grh.traffic_class = resp.alt_dest.traffic_class;
745         attr->alt_ah_attr.sl                = resp.alt_dest.sl;
746         attr->alt_ah_attr.src_path_bits     = resp.alt_dest.src_path_bits;
747         attr->alt_ah_attr.static_rate       = resp.alt_dest.static_rate;
748         attr->alt_ah_attr.is_global         = resp.alt_dest.is_global;
749         attr->alt_ah_attr.port_num          = resp.alt_dest.port_num;
750
751         init_attr->qp_context               = qp->qp_context;
752         init_attr->send_cq                  = qp->send_cq;
753         init_attr->recv_cq                  = qp->recv_cq;
754         init_attr->srq                      = qp->srq;
755         init_attr->qp_type                  = qp->qp_type;
756         if (qp->qp_type == IBV_QPT_XRC)
757                 init_attr->xrc_domain = qp->xrc_domain;
758         init_attr->cap.max_send_wr          = resp.max_send_wr;
759         init_attr->cap.max_recv_wr          = resp.max_recv_wr;
760         init_attr->cap.max_send_sge         = resp.max_send_sge;
761         init_attr->cap.max_recv_sge         = resp.max_recv_sge;
762         init_attr->cap.max_inline_data      = resp.max_inline_data;
763         init_attr->sq_sig_all               = resp.sq_sig_all;
764
765         return 0;
766 }
767
768 int ibv_cmd_modify_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,
769                       int attr_mask,
770                       struct ibv_modify_qp *cmd, size_t cmd_size)
771 {
772         IBV_INIT_CMD(cmd, cmd_size, MODIFY_QP);
773
774         cmd->qp_handle           = qp->handle;
775         cmd->attr_mask           = attr_mask;
776         cmd->qkey                = attr->qkey;
777         cmd->rq_psn              = attr->rq_psn;
778         cmd->sq_psn              = attr->sq_psn;
779         cmd->dest_qp_num         = attr->dest_qp_num;
780         cmd->qp_access_flags     = attr->qp_access_flags;
781         cmd->pkey_index          = attr->pkey_index;
782         cmd->alt_pkey_index      = attr->alt_pkey_index;
783         cmd->qp_state            = attr->qp_state;
784         cmd->cur_qp_state        = attr->cur_qp_state;
785         cmd->path_mtu            = attr->path_mtu;
786         cmd->path_mig_state      = attr->path_mig_state;
787         cmd->en_sqd_async_notify = attr->en_sqd_async_notify;
788         cmd->max_rd_atomic       = attr->max_rd_atomic;
789         cmd->max_dest_rd_atomic  = attr->max_dest_rd_atomic;
790         cmd->min_rnr_timer       = attr->min_rnr_timer;
791         cmd->port_num            = attr->port_num;
792         cmd->timeout             = attr->timeout;
793         cmd->retry_cnt           = attr->retry_cnt;
794         cmd->rnr_retry           = attr->rnr_retry;
795         cmd->alt_port_num        = attr->alt_port_num;
796         cmd->alt_timeout         = attr->alt_timeout;
797
798         memcpy(cmd->dest.dgid, attr->ah_attr.grh.dgid.raw, 16);
799         cmd->dest.flow_label        = attr->ah_attr.grh.flow_label;
800         cmd->dest.dlid              = attr->ah_attr.dlid;
801         cmd->dest.reserved          = 0;
802         cmd->dest.sgid_index        = attr->ah_attr.grh.sgid_index;
803         cmd->dest.hop_limit         = attr->ah_attr.grh.hop_limit;
804         cmd->dest.traffic_class     = attr->ah_attr.grh.traffic_class;
805         cmd->dest.sl                = attr->ah_attr.sl;
806         cmd->dest.src_path_bits     = attr->ah_attr.src_path_bits;
807         cmd->dest.static_rate       = attr->ah_attr.static_rate;
808         cmd->dest.is_global         = attr->ah_attr.is_global;
809         cmd->dest.port_num          = attr->ah_attr.port_num;
810
811         memcpy(cmd->alt_dest.dgid, attr->alt_ah_attr.grh.dgid.raw, 16);
812         cmd->alt_dest.flow_label    = attr->alt_ah_attr.grh.flow_label;
813         cmd->alt_dest.dlid          = attr->alt_ah_attr.dlid;
814         cmd->alt_dest.reserved      = 0;
815         cmd->alt_dest.sgid_index    = attr->alt_ah_attr.grh.sgid_index;
816         cmd->alt_dest.hop_limit     = attr->alt_ah_attr.grh.hop_limit;
817         cmd->alt_dest.traffic_class = attr->alt_ah_attr.grh.traffic_class;
818         cmd->alt_dest.sl            = attr->alt_ah_attr.sl;
819         cmd->alt_dest.src_path_bits = attr->alt_ah_attr.src_path_bits;
820         cmd->alt_dest.static_rate   = attr->alt_ah_attr.static_rate;
821         cmd->alt_dest.is_global     = attr->alt_ah_attr.is_global;
822         cmd->alt_dest.port_num      = attr->alt_ah_attr.port_num;
823
824         cmd->reserved[0] = cmd->reserved[1] = 0;
825
826         if (write(qp->context->cmd_fd, cmd, cmd_size) != cmd_size)
827                 return errno;
828
829         return 0;
830 }
831
832 int ibv_cmd_create_xrc_rcv_qp(struct ibv_qp_init_attr *init_attr,
833                              uint32_t *xrc_rcv_qpn)
834 {
835         struct ibv_create_xrc_rcv_qp cmd;
836         struct ibv_create_xrc_rcv_qp_resp resp;
837
838         if (abi_ver < 6)
839                 return ENOSYS;
840
841         IBV_INIT_CMD_RESP(&cmd, sizeof cmd, CREATE_XRC_RCV_QP, &resp,
842                           sizeof resp);
843
844         cmd.xrc_domain_handle = init_attr->xrc_domain->handle;
845         cmd.max_send_wr     = init_attr->cap.max_send_wr;
846         cmd.max_recv_wr     = init_attr->cap.max_recv_wr;
847         cmd.max_send_sge    = init_attr->cap.max_send_sge;
848         cmd.max_recv_sge    = init_attr->cap.max_recv_sge;
849         cmd.max_inline_data = init_attr->cap.max_inline_data;
850         cmd.sq_sig_all       = init_attr->sq_sig_all;
851         cmd.qp_type          = init_attr->qp_type;
852         cmd.reserved[0] = cmd.reserved[1] = 0;
853
854         if (write(init_attr->xrc_domain->context->cmd_fd, &cmd, sizeof cmd) !=
855             sizeof cmd)
856                 return errno;
857
858         *xrc_rcv_qpn = resp.qpn;
859
860         return 0;
861 }
862
863 int ibv_cmd_modify_xrc_rcv_qp(struct ibv_xrc_domain *d, uint32_t xrc_qp_num,
864                               struct ibv_qp_attr *attr, int attr_mask)
865 {
866         struct ibv_modify_xrc_rcv_qp cmd;
867
868         if (abi_ver < 6)
869                 return ENOSYS;
870
871         IBV_INIT_CMD(&cmd, sizeof cmd, MODIFY_XRC_RCV_QP);
872
873         cmd.xrc_domain_handle    = d->handle;
874         cmd.qp_num               = xrc_qp_num;
875         cmd.attr_mask            = attr_mask;
876         cmd.qkey                 = attr->qkey;
877         cmd.rq_psn               = attr->rq_psn;
878         cmd.sq_psn               = attr->sq_psn;
879         cmd.dest_qp_num          = attr->dest_qp_num;
880         cmd.qp_access_flags      = attr->qp_access_flags;
881         cmd.pkey_index           = attr->pkey_index;
882         cmd.alt_pkey_index       = attr->alt_pkey_index;
883         cmd.qp_state             = attr->qp_state;
884         cmd.cur_qp_state         = attr->cur_qp_state;
885         cmd.path_mtu             = attr->path_mtu;
886         cmd.path_mig_state       = attr->path_mig_state;
887         cmd.en_sqd_async_notify  = attr->en_sqd_async_notify;
888         cmd.max_rd_atomic        = attr->max_rd_atomic;
889         cmd.max_dest_rd_atomic   = attr->max_dest_rd_atomic;
890         cmd.min_rnr_timer        = attr->min_rnr_timer;
891         cmd.port_num             = attr->port_num;
892         cmd.timeout              = attr->timeout;
893         cmd.retry_cnt            = attr->retry_cnt;
894         cmd.rnr_retry            = attr->rnr_retry;
895         cmd.alt_port_num         = attr->alt_port_num;
896         cmd.alt_timeout          = attr->alt_timeout;
897
898         memcpy(cmd.dest.dgid, attr->ah_attr.grh.dgid.raw, 16);
899         cmd.dest.flow_label         = attr->ah_attr.grh.flow_label;
900         cmd.dest.dlid               = attr->ah_attr.dlid;
901         cmd.dest.reserved           = 0;
902         cmd.dest.sgid_index         = attr->ah_attr.grh.sgid_index;
903         cmd.dest.hop_limit          = attr->ah_attr.grh.hop_limit;
904         cmd.dest.traffic_class      = attr->ah_attr.grh.traffic_class;
905         cmd.dest.sl                 = attr->ah_attr.sl;
906         cmd.dest.src_path_bits      = attr->ah_attr.src_path_bits;
907         cmd.dest.static_rate        = attr->ah_attr.static_rate;
908         cmd.dest.is_global          = attr->ah_attr.is_global;
909         cmd.dest.port_num           = attr->ah_attr.port_num;
910
911         memcpy(cmd.alt_dest.dgid, attr->alt_ah_attr.grh.dgid.raw, 16);
912         cmd.alt_dest.flow_label    = attr->alt_ah_attr.grh.flow_label;
913         cmd.alt_dest.dlid           = attr->alt_ah_attr.dlid;
914         cmd.alt_dest.reserved       = 0;
915         cmd.alt_dest.sgid_index    = attr->alt_ah_attr.grh.sgid_index;
916         cmd.alt_dest.hop_limit     = attr->alt_ah_attr.grh.hop_limit;
917         cmd.alt_dest.traffic_class = attr->alt_ah_attr.grh.traffic_class;
918         cmd.alt_dest.sl             = attr->alt_ah_attr.sl;
919         cmd.alt_dest.src_path_bits = attr->alt_ah_attr.src_path_bits;
920         cmd.alt_dest.static_rate   = attr->alt_ah_attr.static_rate;
921         cmd.alt_dest.is_global     = attr->alt_ah_attr.is_global;
922         cmd.alt_dest.port_num       = attr->alt_ah_attr.port_num;
923
924         cmd.reserved[0] = cmd.reserved[1] = 0;
925
926         if (write(d->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
927                 return errno;
928
929         return 0;
930 }
931
932 int ibv_cmd_query_xrc_rcv_qp(struct ibv_xrc_domain *d, uint32_t xrc_qp_num,
933                              struct ibv_qp_attr *attr, int attr_mask,
934                              struct ibv_qp_init_attr *init_attr)
935 {
936         struct ibv_query_xrc_rcv_qp cmd;
937         struct ibv_query_qp_resp resp;
938
939         if (abi_ver < 6)
940                 return ENOSYS;
941
942         IBV_INIT_CMD_RESP(&cmd, sizeof cmd, QUERY_XRC_RCV_QP, &resp,
943                           sizeof resp);
944         cmd.xrc_domain_handle = d->handle;
945         cmd.qp_num = xrc_qp_num;
946         cmd.attr_mask = attr_mask;
947
948         if (write(d->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
949                 return errno;
950
951         VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
952
953         attr->qkey                          = resp.qkey;
954         attr->rq_psn                        = resp.rq_psn;
955         attr->sq_psn                        = resp.sq_psn;
956         attr->dest_qp_num                   = resp.dest_qp_num;
957         attr->qp_access_flags               = resp.qp_access_flags;
958         attr->pkey_index                    = resp.pkey_index;
959         attr->alt_pkey_index                = resp.alt_pkey_index;
960         attr->qp_state                      = resp.qp_state;
961         attr->cur_qp_state                  = resp.cur_qp_state;
962         attr->path_mtu                      = resp.path_mtu;
963         attr->path_mig_state                = resp.path_mig_state;
964         attr->sq_draining                   = resp.sq_draining;
965         attr->max_rd_atomic                 = resp.max_rd_atomic;
966         attr->max_dest_rd_atomic            = resp.max_dest_rd_atomic;
967         attr->min_rnr_timer                 = resp.min_rnr_timer;
968         attr->port_num                      = resp.port_num;
969         attr->timeout                       = resp.timeout;
970         attr->retry_cnt                     = resp.retry_cnt;
971         attr->rnr_retry                     = resp.rnr_retry;
972         attr->alt_port_num                  = resp.alt_port_num;
973         attr->alt_timeout                   = resp.alt_timeout;
974         attr->cap.max_send_wr               = resp.max_send_wr;
975         attr->cap.max_recv_wr               = resp.max_recv_wr;
976         attr->cap.max_send_sge              = resp.max_send_sge;
977         attr->cap.max_recv_sge              = resp.max_recv_sge;
978         attr->cap.max_inline_data           = resp.max_inline_data;
979
980         memcpy(attr->ah_attr.grh.dgid.raw, resp.dest.dgid, 16);
981         attr->ah_attr.grh.flow_label        = resp.dest.flow_label;
982         attr->ah_attr.dlid                  = resp.dest.dlid;
983         attr->ah_attr.grh.sgid_index        = resp.dest.sgid_index;
984         attr->ah_attr.grh.hop_limit         = resp.dest.hop_limit;
985         attr->ah_attr.grh.traffic_class     = resp.dest.traffic_class;
986         attr->ah_attr.sl                    = resp.dest.sl;
987         attr->ah_attr.src_path_bits         = resp.dest.src_path_bits;
988         attr->ah_attr.static_rate           = resp.dest.static_rate;
989         attr->ah_attr.is_global             = resp.dest.is_global;
990         attr->ah_attr.port_num              = resp.dest.port_num;
991
992         memcpy(attr->alt_ah_attr.grh.dgid.raw, resp.alt_dest.dgid, 16);
993         attr->alt_ah_attr.grh.flow_label    = resp.alt_dest.flow_label;
994         attr->alt_ah_attr.dlid              = resp.alt_dest.dlid;
995         attr->alt_ah_attr.grh.sgid_index    = resp.alt_dest.sgid_index;
996         attr->alt_ah_attr.grh.hop_limit     = resp.alt_dest.hop_limit;
997         attr->alt_ah_attr.grh.traffic_class = resp.alt_dest.traffic_class;
998         attr->alt_ah_attr.sl                = resp.alt_dest.sl;
999         attr->alt_ah_attr.src_path_bits     = resp.alt_dest.src_path_bits;
1000         attr->alt_ah_attr.static_rate       = resp.alt_dest.static_rate;
1001         attr->alt_ah_attr.is_global         = resp.alt_dest.is_global;
1002         attr->alt_ah_attr.port_num          = resp.alt_dest.port_num;
1003
1004         init_attr->cap.max_send_wr          = resp.max_send_wr;
1005         init_attr->cap.max_recv_wr          = resp.max_recv_wr;
1006         init_attr->cap.max_send_sge         = resp.max_send_sge;
1007         init_attr->cap.max_recv_sge         = resp.max_recv_sge;
1008         init_attr->cap.max_inline_data      = resp.max_inline_data;
1009         init_attr->sq_sig_all               = resp.sq_sig_all;
1010
1011         return 0;
1012 }
1013
1014 static int ibv_cmd_destroy_qp_v1(struct ibv_qp *qp)
1015 {
1016         struct ibv_destroy_qp_v1 cmd;
1017
1018         IBV_INIT_CMD(&cmd, sizeof cmd, DESTROY_QP);
1019         cmd.qp_handle = qp->handle;
1020
1021         if (write(qp->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1022                 return errno;
1023
1024         return 0;
1025 }
1026
1027 int ibv_cmd_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr,
1028                       struct ibv_send_wr **bad_wr)
1029 {
1030         struct ibv_post_send     *cmd;
1031         struct ibv_post_send_resp resp;
1032         struct ibv_send_wr       *i;
1033         struct ibv_kern_send_wr  *n, *tmp;
1034         struct ibv_sge           *s;
1035         unsigned                  wr_count = 0;
1036         unsigned                  sge_count = 0;
1037         int                       cmd_size;
1038         int                       ret = 0;
1039
1040         for (i = wr; i; i = i->next) {
1041                 wr_count++;
1042                 sge_count += i->num_sge;
1043         }
1044
1045         cmd_size = sizeof *cmd + wr_count * sizeof *n + sge_count * sizeof *s;
1046         cmd  = alloca(cmd_size);
1047
1048         IBV_INIT_CMD_RESP(cmd, cmd_size, POST_SEND, &resp, sizeof resp);
1049         cmd->qp_handle = ibqp->handle;
1050         cmd->wr_count  = wr_count;
1051         cmd->sge_count = sge_count;
1052         cmd->wqe_size  = sizeof *n;
1053
1054         n = (struct ibv_kern_send_wr *) ((void *) cmd + sizeof *cmd);
1055         s = (struct ibv_sge *) (n + wr_count);
1056
1057         tmp = n;
1058         for (i = wr; i; i = i->next) {
1059                 tmp->wr_id      = i->wr_id;
1060                 tmp->num_sge    = i->num_sge;
1061                 tmp->opcode     = i->opcode;
1062                 tmp->send_flags = i->send_flags;
1063                 tmp->imm_data   = i->imm_data;
1064                 if (ibqp->qp_type == IBV_QPT_UD) {
1065                         tmp->wr.ud.ah          = i->wr.ud.ah->handle;
1066                         tmp->wr.ud.remote_qpn  = i->wr.ud.remote_qpn;
1067                         tmp->wr.ud.remote_qkey = i->wr.ud.remote_qkey;
1068                 } else {
1069                         switch (i->opcode) {
1070                         case IBV_WR_RDMA_WRITE:
1071                         case IBV_WR_RDMA_WRITE_WITH_IMM:
1072                         case IBV_WR_RDMA_READ:
1073                                 tmp->wr.rdma.remote_addr =
1074                                         i->wr.rdma.remote_addr;
1075                                 tmp->wr.rdma.rkey = i->wr.rdma.rkey;
1076                                 break;
1077                         case IBV_WR_ATOMIC_CMP_AND_SWP:
1078                         case IBV_WR_ATOMIC_FETCH_AND_ADD:
1079                                 tmp->wr.atomic.remote_addr =
1080                                         i->wr.atomic.remote_addr;
1081                                 tmp->wr.atomic.compare_add =
1082                                         i->wr.atomic.compare_add;
1083                                 tmp->wr.atomic.swap = i->wr.atomic.swap;
1084                                 tmp->wr.atomic.rkey = i->wr.atomic.rkey;
1085                                 break;
1086                         default:
1087                                 break;
1088                         }
1089                 }
1090
1091                 if (tmp->num_sge) {
1092                         memcpy(s, i->sg_list, tmp->num_sge * sizeof *s);
1093                         s += tmp->num_sge;
1094                 }
1095
1096                 tmp++;
1097         }
1098
1099         resp.bad_wr = 0;
1100         if (write(ibqp->context->cmd_fd, cmd, cmd_size) != cmd_size)
1101                 ret = errno;
1102
1103         VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
1104
1105         wr_count = resp.bad_wr;
1106         if (wr_count) {
1107                 i = wr;
1108                 while (--wr_count)
1109                         i = i->next;
1110                 *bad_wr = i;
1111         } else if (ret)
1112                 *bad_wr = wr;
1113
1114         return ret;
1115 }
1116
1117 int ibv_cmd_post_recv(struct ibv_qp *ibqp, struct ibv_recv_wr *wr,
1118                       struct ibv_recv_wr **bad_wr)
1119 {
1120         struct ibv_post_recv     *cmd;
1121         struct ibv_post_recv_resp resp;
1122         struct ibv_recv_wr       *i;
1123         struct ibv_kern_recv_wr  *n, *tmp;
1124         struct ibv_sge           *s;
1125         unsigned                  wr_count = 0;
1126         unsigned                  sge_count = 0;
1127         int                       cmd_size;
1128         int                       ret = 0;
1129
1130         for (i = wr; i; i = i->next) {
1131                 wr_count++;
1132                 sge_count += i->num_sge;
1133         }
1134
1135         cmd_size = sizeof *cmd + wr_count * sizeof *n + sge_count * sizeof *s;
1136         cmd  = alloca(cmd_size);
1137
1138         IBV_INIT_CMD_RESP(cmd, cmd_size, POST_RECV, &resp, sizeof resp);
1139         cmd->qp_handle = ibqp->handle;
1140         cmd->wr_count  = wr_count;
1141         cmd->sge_count = sge_count;
1142         cmd->wqe_size  = sizeof *n;
1143
1144         n = (struct ibv_kern_recv_wr *) ((void *) cmd + sizeof *cmd);
1145         s = (struct ibv_sge *) (n + wr_count);
1146
1147         tmp = n;
1148         for (i = wr; i; i = i->next) {
1149                 tmp->wr_id   = i->wr_id;
1150                 tmp->num_sge = i->num_sge;
1151
1152                 if (tmp->num_sge) {
1153                         memcpy(s, i->sg_list, tmp->num_sge * sizeof *s);
1154                         s += tmp->num_sge;
1155                 }
1156
1157                 tmp++;
1158         }
1159
1160         resp.bad_wr = 0;
1161         if (write(ibqp->context->cmd_fd, cmd, cmd_size) != cmd_size)
1162                 ret = errno;
1163
1164         VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
1165
1166         wr_count = resp.bad_wr;
1167         if (wr_count) {
1168                 i = wr;
1169                 while (--wr_count)
1170                         i = i->next;
1171                 *bad_wr = i;
1172         } else if (ret)
1173                 *bad_wr = wr;
1174
1175         return ret;
1176 }
1177
1178 int ibv_cmd_post_srq_recv(struct ibv_srq *srq, struct ibv_recv_wr *wr,
1179                       struct ibv_recv_wr **bad_wr)
1180 {
1181         struct ibv_post_srq_recv *cmd;
1182         struct ibv_post_srq_recv_resp resp;
1183         struct ibv_recv_wr       *i;
1184         struct ibv_kern_recv_wr  *n, *tmp;
1185         struct ibv_sge           *s;
1186         unsigned                  wr_count = 0;
1187         unsigned                  sge_count = 0;
1188         int                       cmd_size;
1189         int                       ret = 0;
1190
1191         for (i = wr; i; i = i->next) {
1192                 wr_count++;
1193                 sge_count += i->num_sge;
1194         }
1195
1196         cmd_size = sizeof *cmd + wr_count * sizeof *n + sge_count * sizeof *s;
1197         cmd  = alloca(cmd_size);
1198
1199         IBV_INIT_CMD_RESP(cmd, cmd_size, POST_SRQ_RECV, &resp, sizeof resp);
1200         cmd->srq_handle = srq->handle;
1201         cmd->wr_count  = wr_count;
1202         cmd->sge_count = sge_count;
1203         cmd->wqe_size  = sizeof *n;
1204
1205         n = (struct ibv_kern_recv_wr *) ((void *) cmd + sizeof *cmd);
1206         s = (struct ibv_sge *) (n + wr_count);
1207
1208         tmp = n;
1209         for (i = wr; i; i = i->next) {
1210                 tmp->wr_id = i->wr_id;
1211                 tmp->num_sge = i->num_sge;
1212
1213                 if (tmp->num_sge) {
1214                         memcpy(s, i->sg_list, tmp->num_sge * sizeof *s);
1215                         s += tmp->num_sge;
1216                 }
1217
1218                 tmp++;
1219         }
1220
1221         resp.bad_wr = 0;
1222         if (write(srq->context->cmd_fd, cmd, cmd_size) != cmd_size)
1223                 ret = errno;
1224
1225         VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
1226
1227         wr_count = resp.bad_wr;
1228         if (wr_count) {
1229                 i = wr;
1230                 while (--wr_count)
1231                         i = i->next;
1232                 *bad_wr = i;
1233         } else if (ret)
1234                 *bad_wr = wr;
1235
1236         return ret;
1237 }
1238
1239 int ibv_cmd_create_ah(struct ibv_pd *pd, struct ibv_ah *ah,
1240                       struct ibv_ah_attr *attr)
1241 {
1242         struct ibv_create_ah      cmd;
1243         struct ibv_create_ah_resp resp;
1244
1245         IBV_INIT_CMD_RESP(&cmd, sizeof cmd, CREATE_AH, &resp, sizeof resp);
1246         cmd.user_handle            = (uintptr_t) ah;
1247         cmd.pd_handle              = pd->handle;
1248         cmd.attr.dlid              = attr->dlid;
1249         cmd.attr.sl                = attr->sl;
1250         cmd.attr.src_path_bits     = attr->src_path_bits;
1251         cmd.attr.static_rate       = attr->static_rate;
1252         cmd.attr.is_global         = attr->is_global;
1253         cmd.attr.port_num          = attr->port_num;
1254         cmd.attr.grh.flow_label    = attr->grh.flow_label;
1255         cmd.attr.grh.sgid_index    = attr->grh.sgid_index;
1256         cmd.attr.grh.hop_limit     = attr->grh.hop_limit;
1257         cmd.attr.grh.traffic_class = attr->grh.traffic_class;
1258         memcpy(cmd.attr.grh.dgid, attr->grh.dgid.raw, 16);
1259
1260         if (write(pd->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1261                 return errno;
1262
1263         VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
1264
1265         ah->handle  = resp.handle;
1266         ah->context = pd->context;
1267
1268         return 0;
1269 }
1270
1271 int ibv_cmd_destroy_ah(struct ibv_ah *ah)
1272 {
1273         struct ibv_destroy_ah cmd;
1274
1275         IBV_INIT_CMD(&cmd, sizeof cmd, DESTROY_AH);
1276         cmd.ah_handle = ah->handle;
1277
1278         if (write(ah->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1279                 return errno;
1280
1281         return 0;
1282 }
1283
1284 int ibv_cmd_destroy_qp(struct ibv_qp *qp)
1285 {
1286         struct ibv_destroy_qp      cmd;
1287         struct ibv_destroy_qp_resp resp;
1288
1289         if (abi_ver == 1)
1290                 return ibv_cmd_destroy_qp_v1(qp);
1291
1292         IBV_INIT_CMD_RESP(&cmd, sizeof cmd, DESTROY_QP, &resp, sizeof resp);
1293         cmd.qp_handle = qp->handle;
1294         cmd.reserved  = 0;
1295
1296         if (write(qp->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1297                 return errno;
1298
1299         VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
1300
1301         pthread_mutex_lock(&qp->mutex);
1302         while (qp->events_completed != resp.events_reported)
1303                 pthread_cond_wait(&qp->cond, &qp->mutex);
1304         pthread_mutex_unlock(&qp->mutex);
1305
1306         return 0;
1307 }
1308
1309 int ibv_cmd_attach_mcast(struct ibv_qp *qp, const union ibv_gid *gid, uint16_t lid)
1310 {
1311         struct ibv_attach_mcast cmd;
1312
1313         IBV_INIT_CMD(&cmd, sizeof cmd, ATTACH_MCAST);
1314         memcpy(cmd.gid, gid->raw, sizeof cmd.gid);
1315         cmd.qp_handle = qp->handle;
1316         cmd.mlid      = lid;
1317         cmd.reserved  = 0;
1318
1319         if (write(qp->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1320                 return errno;
1321
1322         return 0;
1323 }
1324
1325 int ibv_cmd_detach_mcast(struct ibv_qp *qp, const union ibv_gid *gid, uint16_t lid)
1326 {
1327         struct ibv_detach_mcast cmd;
1328
1329         IBV_INIT_CMD(&cmd, sizeof cmd, DETACH_MCAST);
1330         memcpy(cmd.gid, gid->raw, sizeof cmd.gid);
1331         cmd.qp_handle = qp->handle;
1332         cmd.mlid      = lid;
1333         cmd.reserved  = 0;
1334
1335         if (write(qp->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1336                 return errno;
1337
1338         return 0;
1339 }
1340
1341 int ibv_cmd_open_xrc_domain(struct ibv_context *context, int fd, int oflag,
1342                             struct ibv_xrc_domain *d,
1343                             struct ibv_open_xrc_domain_resp *resp,
1344                             size_t resp_size)
1345 {
1346         struct ibv_open_xrc_domain cmd;
1347
1348         if (abi_ver < 6)
1349                 return ENOSYS;
1350
1351         IBV_INIT_CMD_RESP(&cmd, sizeof cmd, OPEN_XRC_DOMAIN, resp, resp_size);
1352         cmd.fd = fd;
1353         cmd.oflags = oflag;
1354
1355         if (write(context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1356                 return errno;
1357
1358         d->handle = resp->xrcd_handle;
1359
1360         return 0;
1361 }
1362
1363 int ibv_cmd_close_xrc_domain(struct ibv_xrc_domain *d)
1364 {
1365         struct ibv_close_xrc_domain cmd;
1366
1367         if (abi_ver < 6)
1368                 return ENOSYS;
1369
1370         IBV_INIT_CMD(&cmd, sizeof cmd, CLOSE_XRC_DOMAIN);
1371         cmd.xrcd_handle = d->handle;
1372
1373         if (write(d->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1374                 return errno;
1375         return 0;
1376 }
1377
1378 int ibv_cmd_reg_xrc_rcv_qp(struct ibv_xrc_domain *d, uint32_t xrc_qp_num)
1379 {
1380         struct ibv_reg_xrc_rcv_qp cmd;
1381
1382         if (abi_ver < 6)
1383                 return ENOSYS;
1384
1385         IBV_INIT_CMD(&cmd, sizeof cmd, REG_XRC_RCV_QP);
1386         cmd.xrc_domain_handle = d->handle;
1387         cmd.qp_num = xrc_qp_num;
1388
1389         if (write(d->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1390                 return errno;
1391         return 0;
1392 }
1393
1394 int ibv_cmd_unreg_xrc_rcv_qp(struct ibv_xrc_domain *d, uint32_t xrc_qp_num)
1395 {
1396         struct ibv_unreg_xrc_rcv_qp cmd;
1397
1398         if (abi_ver < 6)
1399                 return ENOSYS;
1400
1401         IBV_INIT_CMD(&cmd, sizeof cmd, UNREG_XRC_RCV_QP);
1402         cmd.xrc_domain_handle = d->handle;
1403         cmd.qp_num = xrc_qp_num;
1404
1405         if (write(d->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1406                 return errno;
1407         return 0;
1408 }
1409