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
ibv_cmd_get_context_v2(struct ibv_context * context,struct ibv_get_context * new_cmd,size_t new_cmd_size,struct ibv_get_context_resp * resp,size_t resp_size)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
ibv_cmd_get_context(struct ibv_context * context,struct ibv_get_context * cmd,size_t cmd_size,struct ibv_get_context_resp * resp,size_t resp_size)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
ibv_cmd_query_device(struct ibv_context * context,struct ibv_device_attr * device_attr,uint64_t * raw_fw_ver,struct ibv_query_device * cmd,size_t cmd_size)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
ibv_cmd_query_port(struct ibv_context * context,uint8_t port_num,struct ibv_port_attr * port_attr,struct ibv_query_port * cmd,size_t cmd_size)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
ibv_cmd_alloc_pd(struct ibv_context * context,struct ibv_pd * pd,struct ibv_alloc_pd * cmd,size_t cmd_size,struct ibv_alloc_pd_resp * resp,size_t resp_size)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
ibv_cmd_dealloc_pd(struct ibv_pd * pd)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
ibv_cmd_reg_mr(struct ibv_pd * pd,void * addr,size_t length,uint64_t hca_va,int access,struct ibv_mr * mr,struct ibv_reg_mr * cmd,size_t cmd_size,struct ibv_reg_mr_resp * resp,size_t resp_size)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
ibv_cmd_dereg_mr(struct ibv_mr * mr)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
ibv_cmd_create_cq_v2(struct ibv_context * context,int cqe,struct ibv_cq * cq,struct ibv_create_cq * new_cmd,size_t new_cmd_size,struct ibv_create_cq_resp * resp,size_t resp_size)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
ibv_cmd_create_cq(struct ibv_context * context,int cqe,struct ibv_comp_channel * channel,int comp_vector,struct ibv_cq * cq,struct ibv_create_cq * cmd,size_t cmd_size,struct ibv_create_cq_resp * resp,size_t resp_size)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
ibv_cmd_poll_cq(struct ibv_cq * ibcq,int ne,struct ibv_wc * wc)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
ibv_cmd_req_notify_cq(struct ibv_cq * ibcq,int solicited_only)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
ibv_cmd_resize_cq(struct ibv_cq * cq,int cqe,struct ibv_resize_cq * cmd,size_t cmd_size,struct ibv_resize_cq_resp * resp,size_t resp_size)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
ibv_cmd_destroy_cq_v1(struct ibv_cq * cq)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
ibv_cmd_destroy_cq(struct ibv_cq * cq)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
ibv_cmd_create_srq(struct ibv_pd * pd,struct ibv_srq * srq,struct ibv_srq_init_attr * attr,struct ibv_create_srq * cmd,size_t cmd_size,struct ibv_create_srq_resp * resp,size_t resp_size)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
ibv_cmd_create_xrc_srq(struct ibv_pd * pd,struct ibv_srq * srq,struct ibv_srq_init_attr * attr,uint32_t xrcd_handle,uint32_t xrc_cq,struct ibv_create_xrc_srq * cmd,size_t cmd_size,struct ibv_create_srq_resp * resp,size_t resp_size)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
ibv_cmd_modify_srq_v3(struct ibv_srq * srq,struct ibv_srq_attr * srq_attr,int srq_attr_mask,struct ibv_modify_srq * new_cmd,size_t new_cmd_size)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
ibv_cmd_modify_srq(struct ibv_srq * srq,struct ibv_srq_attr * srq_attr,int srq_attr_mask,struct ibv_modify_srq * cmd,size_t cmd_size)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
ibv_cmd_query_srq(struct ibv_srq * srq,struct ibv_srq_attr * srq_attr,struct ibv_query_srq * cmd,size_t cmd_size)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
ibv_cmd_destroy_srq_v1(struct ibv_srq * srq)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
ibv_cmd_destroy_srq(struct ibv_srq * srq)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
ibv_cmd_create_qp(struct ibv_pd * pd,struct ibv_qp * qp,struct ibv_qp_init_attr * attr,struct ibv_create_qp * cmd,size_t cmd_size,struct ibv_create_qp_resp * resp,size_t resp_size)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
ibv_cmd_query_qp(struct ibv_qp * qp,struct ibv_qp_attr * attr,int attr_mask,struct ibv_qp_init_attr * init_attr,struct ibv_query_qp * cmd,size_t cmd_size)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
ibv_cmd_modify_qp(struct ibv_qp * qp,struct ibv_qp_attr * attr,int attr_mask,struct ibv_modify_qp * cmd,size_t cmd_size)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
ibv_cmd_create_xrc_rcv_qp(struct ibv_qp_init_attr * init_attr,uint32_t * xrc_rcv_qpn)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
ibv_cmd_modify_xrc_rcv_qp(struct ibv_xrc_domain * d,uint32_t xrc_qp_num,struct ibv_qp_attr * attr,int attr_mask)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
ibv_cmd_query_xrc_rcv_qp(struct ibv_xrc_domain * d,uint32_t xrc_qp_num,struct ibv_qp_attr * attr,int attr_mask,struct ibv_qp_init_attr * init_attr)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
ibv_cmd_destroy_qp_v1(struct ibv_qp * qp)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
ibv_cmd_post_send(struct ibv_qp * ibqp,struct ibv_send_wr * wr,struct ibv_send_wr ** bad_wr)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
ibv_cmd_post_recv(struct ibv_qp * ibqp,struct ibv_recv_wr * wr,struct ibv_recv_wr ** bad_wr)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
ibv_cmd_post_srq_recv(struct ibv_srq * srq,struct ibv_recv_wr * wr,struct ibv_recv_wr ** bad_wr)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
ibv_cmd_create_ah(struct ibv_pd * pd,struct ibv_ah * ah,struct ibv_ah_attr * attr)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
ibv_cmd_destroy_ah(struct ibv_ah * ah)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
ibv_cmd_destroy_qp(struct ibv_qp * qp)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
ibv_cmd_attach_mcast(struct ibv_qp * qp,const union ibv_gid * gid,uint16_t lid)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
ibv_cmd_detach_mcast(struct ibv_qp * qp,const union ibv_gid * gid,uint16_t lid)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
ibv_cmd_open_xrc_domain(struct ibv_context * context,int fd,int oflag,struct ibv_xrc_domain * d,struct ibv_open_xrc_domain_resp * resp,size_t resp_size)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
ibv_cmd_close_xrc_domain(struct ibv_xrc_domain * d)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
ibv_cmd_reg_xrc_rcv_qp(struct ibv_xrc_domain * d,uint32_t xrc_qp_num)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
ibv_cmd_unreg_xrc_rcv_qp(struct ibv_xrc_domain * d,uint32_t xrc_qp_num)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
1410