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
48static 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
86int 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
106int 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
165int 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
204int 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
221int 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
234int 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
262int 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
275static 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
304int 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
333int 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
375out:
376	free(resp);
377	return ret;
378}
379
380int 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
394int 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
413static 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
426int 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
452int 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
487int 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
515static 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
543int 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
565int 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
586static 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
599int 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
624int 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
684int 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
768int 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
832int 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
863int 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
932int 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
1014static 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
1027int 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
1117int 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
1178int 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
1239int 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
1271int 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
1284int 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
1309int 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
1325int 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
1341int 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
1363int 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
1378int 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
1394int 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