1219820Sjeff/*
2219820Sjeff * Copyright (c) 2005 Topspin Communications.  All rights reserved.
3219820Sjeff * Copyright (c) 2005 PathScale, Inc.  All rights reserved.
4219820Sjeff * Copyright (c) 2006 Cisco Systems, Inc.  All rights reserved.
5219820Sjeff *
6219820Sjeff * This software is available to you under a choice of one of two
7219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
8219820Sjeff * General Public License (GPL) Version 2, available from the file
9219820Sjeff * COPYING in the main directory of this source tree, or the
10219820Sjeff * OpenIB.org BSD license below:
11219820Sjeff *
12219820Sjeff *     Redistribution and use in source and binary forms, with or
13219820Sjeff *     without modification, are permitted provided that the following
14219820Sjeff *     conditions are met:
15219820Sjeff *
16219820Sjeff *      - Redistributions of source code must retain the above
17219820Sjeff *        copyright notice, this list of conditions and the following
18219820Sjeff *        disclaimer.
19219820Sjeff *
20219820Sjeff *      - Redistributions in binary form must reproduce the above
21219820Sjeff *        copyright notice, this list of conditions and the following
22219820Sjeff *        disclaimer in the documentation and/or other materials
23219820Sjeff *        provided with the distribution.
24219820Sjeff *
25219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32219820Sjeff * SOFTWARE.
33219820Sjeff */
34219820Sjeff
35219820Sjeff#if HAVE_CONFIG_H
36219820Sjeff#  include <config.h>
37219820Sjeff#endif /* HAVE_CONFIG_H */
38219820Sjeff
39219820Sjeff#include <stdio.h>
40219820Sjeff#include <unistd.h>
41219820Sjeff#include <stdlib.h>
42219820Sjeff#include <errno.h>
43219820Sjeff#include <alloca.h>
44219820Sjeff#include <string.h>
45219820Sjeff
46219820Sjeff#include "ibverbs.h"
47219820Sjeff
48219820Sjeffstatic int ibv_cmd_get_context_v2(struct ibv_context *context,
49219820Sjeff				  struct ibv_get_context *new_cmd,
50219820Sjeff				  size_t new_cmd_size,
51219820Sjeff				  struct ibv_get_context_resp *resp,
52219820Sjeff				  size_t resp_size)
53219820Sjeff{
54219820Sjeff	struct ibv_abi_compat_v2 *t;
55219820Sjeff	struct ibv_get_context_v2 *cmd;
56219820Sjeff	size_t cmd_size;
57219820Sjeff	uint32_t cq_fd;
58219820Sjeff
59219820Sjeff	t = malloc(sizeof *t);
60219820Sjeff	if (!t)
61219820Sjeff		return ENOMEM;
62219820Sjeff	pthread_mutex_init(&t->in_use, NULL);
63219820Sjeff
64219820Sjeff	cmd_size = sizeof *cmd + new_cmd_size - sizeof *new_cmd;
65219820Sjeff	cmd      = alloca(cmd_size);
66219820Sjeff	memcpy(cmd->driver_data, new_cmd->driver_data, new_cmd_size - sizeof *new_cmd);
67219820Sjeff
68219820Sjeff	IBV_INIT_CMD_RESP(cmd, cmd_size, GET_CONTEXT, resp, resp_size);
69219820Sjeff	cmd->cq_fd_tab = (uintptr_t) &cq_fd;
70219820Sjeff
71219820Sjeff	if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
72219820Sjeff		return errno;
73219820Sjeff
74219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
75219820Sjeff
76219820Sjeff	context->async_fd         = resp->async_fd;
77219820Sjeff	context->num_comp_vectors = 1;
78219820Sjeff	t->channel.context        = context;
79219820Sjeff	t->channel.fd		  = cq_fd;
80219820Sjeff	t->channel.refcnt	  = 0;
81219820Sjeff	context->abi_compat       = t;
82219820Sjeff
83219820Sjeff	return 0;
84219820Sjeff}
85219820Sjeff
86219820Sjeffint ibv_cmd_get_context(struct ibv_context *context, struct ibv_get_context *cmd,
87219820Sjeff			size_t cmd_size, struct ibv_get_context_resp *resp,
88219820Sjeff			size_t resp_size)
89219820Sjeff{
90219820Sjeff	if (abi_ver <= 2)
91219820Sjeff		return ibv_cmd_get_context_v2(context, cmd, cmd_size, resp, resp_size);
92219820Sjeff
93219820Sjeff	IBV_INIT_CMD_RESP(cmd, cmd_size, GET_CONTEXT, resp, resp_size);
94219820Sjeff
95219820Sjeff	if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
96219820Sjeff		return errno;
97219820Sjeff
98219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
99219820Sjeff
100219820Sjeff	context->async_fd         = resp->async_fd;
101219820Sjeff	context->num_comp_vectors = resp->num_comp_vectors;
102219820Sjeff
103219820Sjeff	return 0;
104219820Sjeff}
105219820Sjeff
106219820Sjeffint ibv_cmd_query_device(struct ibv_context *context,
107219820Sjeff			 struct ibv_device_attr *device_attr,
108219820Sjeff			 uint64_t *raw_fw_ver,
109219820Sjeff			 struct ibv_query_device *cmd, size_t cmd_size)
110219820Sjeff{
111219820Sjeff	struct ibv_query_device_resp resp;
112219820Sjeff
113219820Sjeff	IBV_INIT_CMD_RESP(cmd, cmd_size, QUERY_DEVICE, &resp, sizeof resp);
114219820Sjeff
115219820Sjeff	if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
116219820Sjeff		return errno;
117219820Sjeff
118219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
119219820Sjeff
120219820Sjeff	memset(device_attr->fw_ver, 0, sizeof device_attr->fw_ver);
121219820Sjeff	*raw_fw_ver			       = resp.fw_ver;
122219820Sjeff	device_attr->node_guid 		       = resp.node_guid;
123219820Sjeff	device_attr->sys_image_guid 	       = resp.sys_image_guid;
124219820Sjeff	device_attr->max_mr_size 	       = resp.max_mr_size;
125219820Sjeff	device_attr->page_size_cap 	       = resp.page_size_cap;
126219820Sjeff	device_attr->vendor_id 		       = resp.vendor_id;
127219820Sjeff	device_attr->vendor_part_id 	       = resp.vendor_part_id;
128219820Sjeff	device_attr->hw_ver 		       = resp.hw_ver;
129219820Sjeff	device_attr->max_qp 		       = resp.max_qp;
130219820Sjeff	device_attr->max_qp_wr 		       = resp.max_qp_wr;
131219820Sjeff	device_attr->device_cap_flags 	       = resp.device_cap_flags;
132219820Sjeff	device_attr->max_sge 		       = resp.max_sge;
133219820Sjeff	device_attr->max_sge_rd 	       = resp.max_sge_rd;
134219820Sjeff	device_attr->max_cq 		       = resp.max_cq;
135219820Sjeff	device_attr->max_cqe 		       = resp.max_cqe;
136219820Sjeff	device_attr->max_mr 		       = resp.max_mr;
137219820Sjeff	device_attr->max_pd 		       = resp.max_pd;
138219820Sjeff	device_attr->max_qp_rd_atom 	       = resp.max_qp_rd_atom;
139219820Sjeff	device_attr->max_ee_rd_atom 	       = resp.max_ee_rd_atom;
140219820Sjeff	device_attr->max_res_rd_atom 	       = resp.max_res_rd_atom;
141219820Sjeff	device_attr->max_qp_init_rd_atom       = resp.max_qp_init_rd_atom;
142219820Sjeff	device_attr->max_ee_init_rd_atom       = resp.max_ee_init_rd_atom;
143219820Sjeff	device_attr->atomic_cap 	       = resp.atomic_cap;
144219820Sjeff	device_attr->max_ee 		       = resp.max_ee;
145219820Sjeff	device_attr->max_rdd 		       = resp.max_rdd;
146219820Sjeff	device_attr->max_mw 		       = resp.max_mw;
147219820Sjeff	device_attr->max_raw_ipv6_qp 	       = resp.max_raw_ipv6_qp;
148219820Sjeff	device_attr->max_raw_ethy_qp 	       = resp.max_raw_ethy_qp;
149219820Sjeff	device_attr->max_mcast_grp 	       = resp.max_mcast_grp;
150219820Sjeff	device_attr->max_mcast_qp_attach       = resp.max_mcast_qp_attach;
151219820Sjeff	device_attr->max_total_mcast_qp_attach = resp.max_total_mcast_qp_attach;
152219820Sjeff	device_attr->max_ah 		       = resp.max_ah;
153219820Sjeff	device_attr->max_fmr 		       = resp.max_fmr;
154219820Sjeff	device_attr->max_map_per_fmr 	       = resp.max_map_per_fmr;
155219820Sjeff	device_attr->max_srq 		       = resp.max_srq;
156219820Sjeff	device_attr->max_srq_wr 	       = resp.max_srq_wr;
157219820Sjeff	device_attr->max_srq_sge 	       = resp.max_srq_sge;
158219820Sjeff	device_attr->max_pkeys 		       = resp.max_pkeys;
159219820Sjeff	device_attr->local_ca_ack_delay        = resp.local_ca_ack_delay;
160219820Sjeff	device_attr->phys_port_cnt	       = resp.phys_port_cnt;
161219820Sjeff
162219820Sjeff	return 0;
163219820Sjeff}
164219820Sjeff
165219820Sjeffint ibv_cmd_query_port(struct ibv_context *context, uint8_t port_num,
166219820Sjeff		       struct ibv_port_attr *port_attr,
167219820Sjeff		       struct ibv_query_port *cmd, size_t cmd_size)
168219820Sjeff{
169219820Sjeff	struct ibv_query_port_resp resp;
170219820Sjeff
171219820Sjeff	IBV_INIT_CMD_RESP(cmd, cmd_size, QUERY_PORT, &resp, sizeof resp);
172219820Sjeff	cmd->port_num = port_num;
173219820Sjeff	memset(cmd->reserved, 0, sizeof cmd->reserved);
174219820Sjeff
175219820Sjeff	if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
176219820Sjeff		return errno;
177219820Sjeff
178219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
179219820Sjeff
180219820Sjeff	port_attr->state      	   = resp.state;
181219820Sjeff	port_attr->max_mtu         = resp.max_mtu;
182219820Sjeff	port_attr->active_mtu      = resp.active_mtu;
183219820Sjeff	port_attr->gid_tbl_len     = resp.gid_tbl_len;
184219820Sjeff	port_attr->port_cap_flags  = resp.port_cap_flags;
185219820Sjeff	port_attr->max_msg_sz      = resp.max_msg_sz;
186219820Sjeff	port_attr->bad_pkey_cntr   = resp.bad_pkey_cntr;
187219820Sjeff	port_attr->qkey_viol_cntr  = resp.qkey_viol_cntr;
188219820Sjeff	port_attr->pkey_tbl_len    = resp.pkey_tbl_len;
189219820Sjeff	port_attr->lid 	      	   = resp.lid;
190219820Sjeff	port_attr->sm_lid 	   = resp.sm_lid;
191219820Sjeff	port_attr->lmc 	      	   = resp.lmc;
192219820Sjeff	port_attr->max_vl_num      = resp.max_vl_num;
193219820Sjeff	port_attr->sm_sl      	   = resp.sm_sl;
194219820Sjeff	port_attr->subnet_timeout  = resp.subnet_timeout;
195219820Sjeff	port_attr->init_type_reply = resp.init_type_reply;
196219820Sjeff	port_attr->active_width    = resp.active_width;
197219820Sjeff	port_attr->active_speed    = resp.active_speed;
198219820Sjeff	port_attr->phys_state      = resp.phys_state;
199219820Sjeff	port_attr->link_layer      = resp.link_layer;
200219820Sjeff
201219820Sjeff	return 0;
202219820Sjeff}
203219820Sjeff
204219820Sjeffint ibv_cmd_alloc_pd(struct ibv_context *context, struct ibv_pd *pd,
205219820Sjeff		     struct ibv_alloc_pd *cmd, size_t cmd_size,
206219820Sjeff		     struct ibv_alloc_pd_resp *resp, size_t resp_size)
207219820Sjeff{
208219820Sjeff	IBV_INIT_CMD_RESP(cmd, cmd_size, ALLOC_PD, resp, resp_size);
209219820Sjeff
210219820Sjeff	if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
211219820Sjeff		return errno;
212219820Sjeff
213219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
214219820Sjeff
215219820Sjeff	pd->handle  = resp->pd_handle;
216219820Sjeff	pd->context = context;
217219820Sjeff
218219820Sjeff	return 0;
219219820Sjeff}
220219820Sjeff
221219820Sjeffint ibv_cmd_dealloc_pd(struct ibv_pd *pd)
222219820Sjeff{
223219820Sjeff	struct ibv_dealloc_pd cmd;
224219820Sjeff
225219820Sjeff	IBV_INIT_CMD(&cmd, sizeof cmd, DEALLOC_PD);
226219820Sjeff	cmd.pd_handle = pd->handle;
227219820Sjeff
228219820Sjeff	if (write(pd->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
229219820Sjeff		return errno;
230219820Sjeff
231219820Sjeff	return 0;
232219820Sjeff}
233219820Sjeff
234219820Sjeffint ibv_cmd_reg_mr(struct ibv_pd *pd, void *addr, size_t length,
235219820Sjeff		   uint64_t hca_va, int access,
236219820Sjeff		   struct ibv_mr *mr, struct ibv_reg_mr *cmd,
237219820Sjeff		   size_t cmd_size,
238219820Sjeff		   struct ibv_reg_mr_resp *resp, size_t resp_size)
239219820Sjeff{
240219820Sjeff
241219820Sjeff	IBV_INIT_CMD_RESP(cmd, cmd_size, REG_MR, resp, resp_size);
242219820Sjeff
243219820Sjeff	cmd->start 	  = (uintptr_t) addr;
244219820Sjeff	cmd->length 	  = length;
245219820Sjeff	cmd->hca_va 	  = hca_va;
246219820Sjeff	cmd->pd_handle 	  = pd->handle;
247219820Sjeff	cmd->access_flags = access;
248219820Sjeff
249219820Sjeff	if (write(pd->context->cmd_fd, cmd, cmd_size) != cmd_size)
250219820Sjeff		return errno;
251219820Sjeff
252219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
253219820Sjeff
254219820Sjeff	mr->handle  = resp->mr_handle;
255219820Sjeff	mr->lkey    = resp->lkey;
256219820Sjeff	mr->rkey    = resp->rkey;
257219820Sjeff	mr->context = pd->context;
258219820Sjeff
259219820Sjeff	return 0;
260219820Sjeff}
261219820Sjeff
262219820Sjeffint ibv_cmd_dereg_mr(struct ibv_mr *mr)
263219820Sjeff{
264219820Sjeff	struct ibv_dereg_mr cmd;
265219820Sjeff
266219820Sjeff	IBV_INIT_CMD(&cmd, sizeof cmd, DEREG_MR);
267219820Sjeff	cmd.mr_handle = mr->handle;
268219820Sjeff
269219820Sjeff	if (write(mr->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
270219820Sjeff		return errno;
271219820Sjeff
272219820Sjeff	return 0;
273219820Sjeff}
274219820Sjeff
275219820Sjeffstatic int ibv_cmd_create_cq_v2(struct ibv_context *context, int cqe,
276219820Sjeff				struct ibv_cq *cq,
277219820Sjeff				struct ibv_create_cq *new_cmd, size_t new_cmd_size,
278219820Sjeff				struct ibv_create_cq_resp *resp, size_t resp_size)
279219820Sjeff{
280219820Sjeff	struct ibv_create_cq_v2 *cmd;
281219820Sjeff	size_t cmd_size;
282219820Sjeff
283219820Sjeff	cmd_size = sizeof *cmd + new_cmd_size - sizeof *new_cmd;
284219820Sjeff	cmd      = alloca(cmd_size);
285219820Sjeff	memcpy(cmd->driver_data, new_cmd->driver_data, new_cmd_size - sizeof *new_cmd);
286219820Sjeff
287219820Sjeff	IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_CQ, resp, resp_size);
288219820Sjeff	cmd->user_handle   = (uintptr_t) cq;
289219820Sjeff	cmd->cqe           = cqe;
290219820Sjeff	cmd->event_handler = 0;
291219820Sjeff
292219820Sjeff	if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
293219820Sjeff		return errno;
294219820Sjeff
295219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
296219820Sjeff
297219820Sjeff	cq->handle  = resp->cq_handle;
298219820Sjeff	cq->cqe     = resp->cqe;
299219820Sjeff	cq->context = context;
300219820Sjeff
301219820Sjeff	return 0;
302219820Sjeff}
303219820Sjeff
304219820Sjeffint ibv_cmd_create_cq(struct ibv_context *context, int cqe,
305219820Sjeff		      struct ibv_comp_channel *channel,
306219820Sjeff		      int comp_vector, struct ibv_cq *cq,
307219820Sjeff		      struct ibv_create_cq *cmd, size_t cmd_size,
308219820Sjeff		      struct ibv_create_cq_resp *resp, size_t resp_size)
309219820Sjeff{
310219820Sjeff	if (abi_ver <= 2)
311219820Sjeff		return ibv_cmd_create_cq_v2(context, cqe, cq,
312219820Sjeff					    cmd, cmd_size, resp, resp_size);
313219820Sjeff
314219820Sjeff	IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_CQ, resp, resp_size);
315219820Sjeff	cmd->user_handle   = (uintptr_t) cq;
316219820Sjeff	cmd->cqe           = cqe;
317219820Sjeff	cmd->comp_vector   = comp_vector;
318219820Sjeff	cmd->comp_channel  = channel ? channel->fd : -1;
319219820Sjeff	cmd->reserved      = 0;
320219820Sjeff
321219820Sjeff	if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
322219820Sjeff		return errno;
323219820Sjeff
324219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
325219820Sjeff
326219820Sjeff	cq->handle  = resp->cq_handle;
327219820Sjeff	cq->cqe     = resp->cqe;
328219820Sjeff	cq->context = context;
329219820Sjeff
330219820Sjeff	return 0;
331219820Sjeff}
332219820Sjeff
333219820Sjeffint ibv_cmd_poll_cq(struct ibv_cq *ibcq, int ne, struct ibv_wc *wc)
334219820Sjeff{
335219820Sjeff	struct ibv_poll_cq       cmd;
336219820Sjeff	struct ibv_poll_cq_resp *resp;
337219820Sjeff	int                      i;
338219820Sjeff	int                      rsize;
339219820Sjeff	int                      ret;
340219820Sjeff
341219820Sjeff	rsize = sizeof *resp + ne * sizeof(struct ibv_kern_wc);
342219820Sjeff	resp  = malloc(rsize);
343219820Sjeff	if (!resp)
344219820Sjeff		return -1;
345219820Sjeff
346219820Sjeff	IBV_INIT_CMD_RESP(&cmd, sizeof cmd, POLL_CQ, resp, rsize);
347219820Sjeff	cmd.cq_handle = ibcq->handle;
348219820Sjeff	cmd.ne        = ne;
349219820Sjeff
350219820Sjeff	if (write(ibcq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd) {
351219820Sjeff		ret = -1;
352219820Sjeff		goto out;
353219820Sjeff	}
354219820Sjeff
355219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(resp, rsize);
356219820Sjeff
357219820Sjeff	for (i = 0; i < resp->count; i++) {
358219820Sjeff		wc[i].wr_id 	     = resp->wc[i].wr_id;
359219820Sjeff		wc[i].status 	     = resp->wc[i].status;
360219820Sjeff		wc[i].opcode 	     = resp->wc[i].opcode;
361219820Sjeff		wc[i].vendor_err     = resp->wc[i].vendor_err;
362219820Sjeff		wc[i].byte_len 	     = resp->wc[i].byte_len;
363219820Sjeff		wc[i].imm_data 	     = resp->wc[i].imm_data;
364219820Sjeff		wc[i].qp_num 	     = resp->wc[i].qp_num;
365219820Sjeff		wc[i].src_qp 	     = resp->wc[i].src_qp;
366219820Sjeff		wc[i].wc_flags 	     = resp->wc[i].wc_flags;
367219820Sjeff		wc[i].pkey_index     = resp->wc[i].pkey_index;
368219820Sjeff		wc[i].slid 	     = resp->wc[i].slid;
369219820Sjeff		wc[i].sl 	     = resp->wc[i].sl;
370219820Sjeff		wc[i].dlid_path_bits = resp->wc[i].dlid_path_bits;
371219820Sjeff	}
372219820Sjeff
373219820Sjeff	ret = resp->count;
374219820Sjeff
375219820Sjeffout:
376219820Sjeff	free(resp);
377219820Sjeff	return ret;
378219820Sjeff}
379219820Sjeff
380219820Sjeffint ibv_cmd_req_notify_cq(struct ibv_cq *ibcq, int solicited_only)
381219820Sjeff{
382219820Sjeff	struct ibv_req_notify_cq cmd;
383219820Sjeff
384219820Sjeff	IBV_INIT_CMD(&cmd, sizeof cmd, REQ_NOTIFY_CQ);
385219820Sjeff	cmd.cq_handle = ibcq->handle;
386219820Sjeff	cmd.solicited = !!solicited_only;
387219820Sjeff
388219820Sjeff	if (write(ibcq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
389219820Sjeff		return errno;
390219820Sjeff
391219820Sjeff	return 0;
392219820Sjeff}
393219820Sjeff
394219820Sjeffint ibv_cmd_resize_cq(struct ibv_cq *cq, int cqe,
395219820Sjeff		      struct ibv_resize_cq *cmd, size_t cmd_size,
396219820Sjeff		      struct ibv_resize_cq_resp *resp, size_t resp_size)
397219820Sjeff{
398219820Sjeff
399219820Sjeff	IBV_INIT_CMD_RESP(cmd, cmd_size, RESIZE_CQ, resp, resp_size);
400219820Sjeff	cmd->cq_handle = cq->handle;
401219820Sjeff	cmd->cqe       = cqe;
402219820Sjeff
403219820Sjeff	if (write(cq->context->cmd_fd, cmd, cmd_size) != cmd_size)
404219820Sjeff		return errno;
405219820Sjeff
406219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
407219820Sjeff
408219820Sjeff	cq->cqe = resp->cqe;
409219820Sjeff
410219820Sjeff	return 0;
411219820Sjeff}
412219820Sjeff
413219820Sjeffstatic int ibv_cmd_destroy_cq_v1(struct ibv_cq *cq)
414219820Sjeff{
415219820Sjeff	struct ibv_destroy_cq_v1 cmd;
416219820Sjeff
417219820Sjeff	IBV_INIT_CMD(&cmd, sizeof cmd, DESTROY_CQ);
418219820Sjeff	cmd.cq_handle = cq->handle;
419219820Sjeff
420219820Sjeff	if (write(cq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
421219820Sjeff		return errno;
422219820Sjeff
423219820Sjeff	return 0;
424219820Sjeff}
425219820Sjeff
426219820Sjeffint ibv_cmd_destroy_cq(struct ibv_cq *cq)
427219820Sjeff{
428219820Sjeff	struct ibv_destroy_cq      cmd;
429219820Sjeff	struct ibv_destroy_cq_resp resp;
430219820Sjeff
431219820Sjeff	if (abi_ver == 1)
432219820Sjeff		return ibv_cmd_destroy_cq_v1(cq);
433219820Sjeff
434219820Sjeff	IBV_INIT_CMD_RESP(&cmd, sizeof cmd, DESTROY_CQ, &resp, sizeof resp);
435219820Sjeff	cmd.cq_handle = cq->handle;
436219820Sjeff	cmd.reserved  = 0;
437219820Sjeff
438219820Sjeff	if (write(cq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
439219820Sjeff		return errno;
440219820Sjeff
441219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
442219820Sjeff
443219820Sjeff	pthread_mutex_lock(&cq->mutex);
444219820Sjeff	while (cq->comp_events_completed  != resp.comp_events_reported ||
445219820Sjeff	       cq->async_events_completed != resp.async_events_reported)
446219820Sjeff		pthread_cond_wait(&cq->cond, &cq->mutex);
447219820Sjeff	pthread_mutex_unlock(&cq->mutex);
448219820Sjeff
449219820Sjeff	return 0;
450219820Sjeff}
451219820Sjeff
452219820Sjeffint ibv_cmd_create_srq(struct ibv_pd *pd,
453219820Sjeff		       struct ibv_srq *srq, struct ibv_srq_init_attr *attr,
454219820Sjeff		       struct ibv_create_srq *cmd, size_t cmd_size,
455219820Sjeff		       struct ibv_create_srq_resp *resp, size_t resp_size)
456219820Sjeff{
457219820Sjeff	IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_SRQ, resp, resp_size);
458219820Sjeff	cmd->user_handle = (uintptr_t) srq;
459219820Sjeff	cmd->pd_handle 	 = pd->handle;
460219820Sjeff	cmd->max_wr      = attr->attr.max_wr;
461219820Sjeff	cmd->max_sge     = attr->attr.max_sge;
462219820Sjeff	cmd->srq_limit   = attr->attr.srq_limit;
463219820Sjeff
464219820Sjeff	if (write(pd->context->cmd_fd, cmd, cmd_size) != cmd_size)
465219820Sjeff		return errno;
466219820Sjeff
467219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
468219820Sjeff
469219820Sjeff	srq->handle  = resp->srq_handle;
470219820Sjeff	srq->context = pd->context;
471219820Sjeff
472219820Sjeff	if (abi_ver > 5) {
473219820Sjeff		attr->attr.max_wr = resp->max_wr;
474219820Sjeff		attr->attr.max_sge = resp->max_sge;
475219820Sjeff	} else {
476219820Sjeff		struct ibv_create_srq_resp_v5 *resp_v5 =
477219820Sjeff			(struct ibv_create_srq_resp_v5 *) resp;
478219820Sjeff
479219820Sjeff		memmove((void *) resp + sizeof *resp,
480219820Sjeff			(void *) resp_v5 + sizeof *resp_v5,
481219820Sjeff			resp_size - sizeof *resp);
482219820Sjeff	}
483219820Sjeff
484219820Sjeff	return 0;
485219820Sjeff}
486219820Sjeff
487219820Sjeffint ibv_cmd_create_xrc_srq(struct ibv_pd *pd,
488219820Sjeff		       struct ibv_srq *srq, struct ibv_srq_init_attr *attr,
489219820Sjeff		       uint32_t xrcd_handle, uint32_t xrc_cq,
490219820Sjeff		       struct ibv_create_xrc_srq *cmd, size_t cmd_size,
491219820Sjeff		       struct ibv_create_srq_resp *resp, size_t resp_size)
492219820Sjeff{
493219820Sjeff	IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_XRC_SRQ, resp, resp_size);
494219820Sjeff	cmd->user_handle = (uintptr_t) srq;
495219820Sjeff	cmd->pd_handle 	 = pd->handle;
496219820Sjeff	cmd->max_wr      = attr->attr.max_wr;
497219820Sjeff	cmd->max_sge     = attr->attr.max_sge;
498219820Sjeff	cmd->srq_limit   = attr->attr.srq_limit;
499219820Sjeff	cmd->xrcd_handle = xrcd_handle;
500219820Sjeff	cmd->xrc_cq	 = xrc_cq;
501219820Sjeff
502219820Sjeff	if (write(pd->context->cmd_fd, cmd, cmd_size) != cmd_size)
503219820Sjeff		return errno;
504219820Sjeff
505219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
506219820Sjeff
507219820Sjeff	srq->handle  = resp->srq_handle;
508219820Sjeff	srq->context = pd->context;
509219820Sjeff	attr->attr.max_wr = resp->max_wr;
510219820Sjeff	attr->attr.max_sge = resp->max_sge;
511219820Sjeff
512219820Sjeff	return 0;
513219820Sjeff}
514219820Sjeff
515219820Sjeffstatic int ibv_cmd_modify_srq_v3(struct ibv_srq *srq,
516219820Sjeff				 struct ibv_srq_attr *srq_attr,
517219820Sjeff				 int srq_attr_mask,
518219820Sjeff				 struct ibv_modify_srq *new_cmd,
519219820Sjeff				 size_t new_cmd_size)
520219820Sjeff{
521219820Sjeff	struct ibv_modify_srq_v3 *cmd;
522219820Sjeff	size_t cmd_size;
523219820Sjeff
524219820Sjeff	cmd_size = sizeof *cmd + new_cmd_size - sizeof *new_cmd;
525219820Sjeff	cmd      = alloca(cmd_size);
526219820Sjeff	memcpy(cmd->driver_data, new_cmd->driver_data, new_cmd_size - sizeof *new_cmd);
527219820Sjeff
528219820Sjeff	IBV_INIT_CMD(cmd, cmd_size, MODIFY_SRQ);
529219820Sjeff
530219820Sjeff	cmd->srq_handle	= srq->handle;
531219820Sjeff	cmd->attr_mask	= srq_attr_mask;
532219820Sjeff	cmd->max_wr	= srq_attr->max_wr;
533219820Sjeff	cmd->srq_limit	= srq_attr->srq_limit;
534219820Sjeff	cmd->max_sge	= 0;
535219820Sjeff	cmd->reserved	= 0;
536219820Sjeff
537219820Sjeff	if (write(srq->context->cmd_fd, cmd, cmd_size) != cmd_size)
538219820Sjeff		return errno;
539219820Sjeff
540219820Sjeff	return 0;
541219820Sjeff}
542219820Sjeff
543219820Sjeffint ibv_cmd_modify_srq(struct ibv_srq *srq,
544219820Sjeff		       struct ibv_srq_attr *srq_attr,
545219820Sjeff		       int srq_attr_mask,
546219820Sjeff		       struct ibv_modify_srq *cmd, size_t cmd_size)
547219820Sjeff{
548219820Sjeff	if (abi_ver == 3)
549219820Sjeff		return ibv_cmd_modify_srq_v3(srq, srq_attr, srq_attr_mask,
550219820Sjeff					     cmd, cmd_size);
551219820Sjeff
552219820Sjeff	IBV_INIT_CMD(cmd, cmd_size, MODIFY_SRQ);
553219820Sjeff
554219820Sjeff	cmd->srq_handle	= srq->handle;
555219820Sjeff	cmd->attr_mask	= srq_attr_mask;
556219820Sjeff	cmd->max_wr	= srq_attr->max_wr;
557219820Sjeff	cmd->srq_limit	= srq_attr->srq_limit;
558219820Sjeff
559219820Sjeff	if (write(srq->context->cmd_fd, cmd, cmd_size) != cmd_size)
560219820Sjeff		return errno;
561219820Sjeff
562219820Sjeff	return 0;
563219820Sjeff}
564219820Sjeff
565219820Sjeffint ibv_cmd_query_srq(struct ibv_srq *srq, struct ibv_srq_attr *srq_attr,
566219820Sjeff		      struct ibv_query_srq *cmd, size_t cmd_size)
567219820Sjeff{
568219820Sjeff	struct ibv_query_srq_resp resp;
569219820Sjeff
570219820Sjeff	IBV_INIT_CMD_RESP(cmd, cmd_size, QUERY_SRQ, &resp, sizeof resp);
571219820Sjeff	cmd->srq_handle = srq->handle;
572219820Sjeff	cmd->reserved   = 0;
573219820Sjeff
574219820Sjeff	if (write(srq->context->cmd_fd, cmd, cmd_size) != cmd_size)
575219820Sjeff		return errno;
576219820Sjeff
577219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
578219820Sjeff
579219820Sjeff	srq_attr->max_wr    = resp.max_wr;
580219820Sjeff	srq_attr->max_sge   = resp.max_sge;
581219820Sjeff	srq_attr->srq_limit = resp.srq_limit;
582219820Sjeff
583219820Sjeff	return 0;
584219820Sjeff}
585219820Sjeff
586219820Sjeffstatic int ibv_cmd_destroy_srq_v1(struct ibv_srq *srq)
587219820Sjeff{
588219820Sjeff	struct ibv_destroy_srq_v1 cmd;
589219820Sjeff
590219820Sjeff	IBV_INIT_CMD(&cmd, sizeof cmd, DESTROY_SRQ);
591219820Sjeff	cmd.srq_handle = srq->handle;
592219820Sjeff
593219820Sjeff	if (write(srq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
594219820Sjeff		return errno;
595219820Sjeff
596219820Sjeff	return 0;
597219820Sjeff}
598219820Sjeff
599219820Sjeffint ibv_cmd_destroy_srq(struct ibv_srq *srq)
600219820Sjeff{
601219820Sjeff	struct ibv_destroy_srq      cmd;
602219820Sjeff	struct ibv_destroy_srq_resp resp;
603219820Sjeff
604219820Sjeff	if (abi_ver == 1)
605219820Sjeff		return ibv_cmd_destroy_srq_v1(srq);
606219820Sjeff
607219820Sjeff	IBV_INIT_CMD_RESP(&cmd, sizeof cmd, DESTROY_SRQ, &resp, sizeof resp);
608219820Sjeff	cmd.srq_handle = srq->handle;
609219820Sjeff	cmd.reserved   = 0;
610219820Sjeff
611219820Sjeff	if (write(srq->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
612219820Sjeff		return errno;
613219820Sjeff
614219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
615219820Sjeff
616219820Sjeff	pthread_mutex_lock(&srq->mutex);
617219820Sjeff	while (srq->events_completed != resp.events_reported)
618219820Sjeff		pthread_cond_wait(&srq->cond, &srq->mutex);
619219820Sjeff	pthread_mutex_unlock(&srq->mutex);
620219820Sjeff
621219820Sjeff	return 0;
622219820Sjeff}
623219820Sjeff
624219820Sjeffint ibv_cmd_create_qp(struct ibv_pd *pd,
625219820Sjeff		      struct ibv_qp *qp, struct ibv_qp_init_attr *attr,
626219820Sjeff		      struct ibv_create_qp *cmd, size_t cmd_size,
627219820Sjeff		      struct ibv_create_qp_resp *resp, size_t resp_size)
628219820Sjeff{
629219820Sjeff	IBV_INIT_CMD_RESP(cmd, cmd_size, CREATE_QP, resp, resp_size);
630219820Sjeff
631219820Sjeff	cmd->user_handle     = (uintptr_t) qp;
632219820Sjeff	cmd->pd_handle 	     = pd->handle;
633219820Sjeff	cmd->send_cq_handle  = attr->send_cq->handle;
634219820Sjeff	cmd->recv_cq_handle  = attr->recv_cq->handle;
635219820Sjeff	cmd->max_send_wr     = attr->cap.max_send_wr;
636219820Sjeff	cmd->max_recv_wr     = attr->cap.max_recv_wr;
637219820Sjeff	cmd->max_send_sge    = attr->cap.max_send_sge;
638219820Sjeff	cmd->max_recv_sge    = attr->cap.max_recv_sge;
639219820Sjeff	cmd->max_inline_data = attr->cap.max_inline_data;
640219820Sjeff	cmd->sq_sig_all	     = attr->sq_sig_all;
641219820Sjeff	cmd->qp_type 	     = attr->qp_type;
642219820Sjeff	cmd->is_srq 	     = !!attr->srq;
643219820Sjeff	cmd->srq_handle      = attr->qp_type == IBV_QPT_XRC ?
644219820Sjeff		(attr->xrc_domain ? attr->xrc_domain->handle : 0) :
645219820Sjeff		(attr->srq ? attr->srq->handle : 0);
646219820Sjeff	cmd->reserved	     = 0;
647219820Sjeff
648219820Sjeff	if (write(pd->context->cmd_fd, cmd, cmd_size) != cmd_size)
649219820Sjeff		return errno;
650219820Sjeff
651219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
652219820Sjeff
653219820Sjeff	qp->handle 		  = resp->qp_handle;
654219820Sjeff	qp->qp_num 		  = resp->qpn;
655219820Sjeff	qp->context		  = pd->context;
656219820Sjeff
657219820Sjeff	if (abi_ver > 3) {
658219820Sjeff		attr->cap.max_recv_sge    = resp->max_recv_sge;
659219820Sjeff		attr->cap.max_send_sge    = resp->max_send_sge;
660219820Sjeff		attr->cap.max_recv_wr     = resp->max_recv_wr;
661219820Sjeff		attr->cap.max_send_wr     = resp->max_send_wr;
662219820Sjeff		attr->cap.max_inline_data = resp->max_inline_data;
663219820Sjeff	}
664219820Sjeff
665219820Sjeff	if (abi_ver == 4) {
666219820Sjeff		struct ibv_create_qp_resp_v4 *resp_v4 =
667219820Sjeff			(struct ibv_create_qp_resp_v4 *) resp;
668219820Sjeff
669219820Sjeff		memmove((void *) resp + sizeof *resp,
670219820Sjeff			(void *) resp_v4 + sizeof *resp_v4,
671219820Sjeff			resp_size - sizeof *resp);
672219820Sjeff	} else if (abi_ver <= 3) {
673219820Sjeff		struct ibv_create_qp_resp_v3 *resp_v3 =
674219820Sjeff			(struct ibv_create_qp_resp_v3 *) resp;
675219820Sjeff
676219820Sjeff		memmove((void *) resp + sizeof *resp,
677219820Sjeff			(void *) resp_v3 + sizeof *resp_v3,
678219820Sjeff			resp_size - sizeof *resp);
679219820Sjeff	}
680219820Sjeff
681219820Sjeff	return 0;
682219820Sjeff}
683219820Sjeff
684219820Sjeffint ibv_cmd_query_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,
685219820Sjeff		     int attr_mask,
686219820Sjeff		     struct ibv_qp_init_attr *init_attr,
687219820Sjeff		     struct ibv_query_qp *cmd, size_t cmd_size)
688219820Sjeff{
689219820Sjeff	struct ibv_query_qp_resp resp;
690219820Sjeff
691219820Sjeff	IBV_INIT_CMD_RESP(cmd, cmd_size, QUERY_QP, &resp, sizeof resp);
692219820Sjeff	cmd->qp_handle = qp->handle;
693219820Sjeff	cmd->attr_mask = attr_mask;
694219820Sjeff
695219820Sjeff	if (write(qp->context->cmd_fd, cmd, cmd_size) != cmd_size)
696219820Sjeff		return errno;
697219820Sjeff
698219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
699219820Sjeff
700219820Sjeff	attr->qkey                          = resp.qkey;
701219820Sjeff	attr->rq_psn                        = resp.rq_psn;
702219820Sjeff	attr->sq_psn                        = resp.sq_psn;
703219820Sjeff	attr->dest_qp_num                   = resp.dest_qp_num;
704219820Sjeff	attr->qp_access_flags               = resp.qp_access_flags;
705219820Sjeff	attr->pkey_index                    = resp.pkey_index;
706219820Sjeff	attr->alt_pkey_index                = resp.alt_pkey_index;
707219820Sjeff	attr->qp_state                      = resp.qp_state;
708219820Sjeff	attr->cur_qp_state                  = resp.cur_qp_state;
709219820Sjeff	attr->path_mtu                      = resp.path_mtu;
710219820Sjeff	attr->path_mig_state                = resp.path_mig_state;
711219820Sjeff	attr->sq_draining                   = resp.sq_draining;
712219820Sjeff	attr->max_rd_atomic                 = resp.max_rd_atomic;
713219820Sjeff	attr->max_dest_rd_atomic            = resp.max_dest_rd_atomic;
714219820Sjeff	attr->min_rnr_timer                 = resp.min_rnr_timer;
715219820Sjeff	attr->port_num                      = resp.port_num;
716219820Sjeff	attr->timeout                       = resp.timeout;
717219820Sjeff	attr->retry_cnt                     = resp.retry_cnt;
718219820Sjeff	attr->rnr_retry                     = resp.rnr_retry;
719219820Sjeff	attr->alt_port_num                  = resp.alt_port_num;
720219820Sjeff	attr->alt_timeout                   = resp.alt_timeout;
721219820Sjeff	attr->cap.max_send_wr               = resp.max_send_wr;
722219820Sjeff	attr->cap.max_recv_wr               = resp.max_recv_wr;
723219820Sjeff	attr->cap.max_send_sge              = resp.max_send_sge;
724219820Sjeff	attr->cap.max_recv_sge              = resp.max_recv_sge;
725219820Sjeff	attr->cap.max_inline_data           = resp.max_inline_data;
726219820Sjeff
727219820Sjeff	memcpy(attr->ah_attr.grh.dgid.raw, resp.dest.dgid, 16);
728219820Sjeff	attr->ah_attr.grh.flow_label        = resp.dest.flow_label;
729219820Sjeff	attr->ah_attr.dlid                  = resp.dest.dlid;
730219820Sjeff	attr->ah_attr.grh.sgid_index        = resp.dest.sgid_index;
731219820Sjeff	attr->ah_attr.grh.hop_limit         = resp.dest.hop_limit;
732219820Sjeff	attr->ah_attr.grh.traffic_class     = resp.dest.traffic_class;
733219820Sjeff	attr->ah_attr.sl                    = resp.dest.sl;
734219820Sjeff	attr->ah_attr.src_path_bits         = resp.dest.src_path_bits;
735219820Sjeff	attr->ah_attr.static_rate           = resp.dest.static_rate;
736219820Sjeff	attr->ah_attr.is_global             = resp.dest.is_global;
737219820Sjeff	attr->ah_attr.port_num              = resp.dest.port_num;
738219820Sjeff
739219820Sjeff	memcpy(attr->alt_ah_attr.grh.dgid.raw, resp.alt_dest.dgid, 16);
740219820Sjeff	attr->alt_ah_attr.grh.flow_label    = resp.alt_dest.flow_label;
741219820Sjeff	attr->alt_ah_attr.dlid              = resp.alt_dest.dlid;
742219820Sjeff	attr->alt_ah_attr.grh.sgid_index    = resp.alt_dest.sgid_index;
743219820Sjeff	attr->alt_ah_attr.grh.hop_limit     = resp.alt_dest.hop_limit;
744219820Sjeff	attr->alt_ah_attr.grh.traffic_class = resp.alt_dest.traffic_class;
745219820Sjeff	attr->alt_ah_attr.sl                = resp.alt_dest.sl;
746219820Sjeff	attr->alt_ah_attr.src_path_bits     = resp.alt_dest.src_path_bits;
747219820Sjeff	attr->alt_ah_attr.static_rate       = resp.alt_dest.static_rate;
748219820Sjeff	attr->alt_ah_attr.is_global         = resp.alt_dest.is_global;
749219820Sjeff	attr->alt_ah_attr.port_num          = resp.alt_dest.port_num;
750219820Sjeff
751219820Sjeff	init_attr->qp_context               = qp->qp_context;
752219820Sjeff	init_attr->send_cq                  = qp->send_cq;
753219820Sjeff	init_attr->recv_cq                  = qp->recv_cq;
754219820Sjeff	init_attr->srq                      = qp->srq;
755219820Sjeff	init_attr->qp_type                  = qp->qp_type;
756219820Sjeff	if (qp->qp_type == IBV_QPT_XRC)
757219820Sjeff		init_attr->xrc_domain = qp->xrc_domain;
758219820Sjeff	init_attr->cap.max_send_wr          = resp.max_send_wr;
759219820Sjeff	init_attr->cap.max_recv_wr          = resp.max_recv_wr;
760219820Sjeff	init_attr->cap.max_send_sge         = resp.max_send_sge;
761219820Sjeff	init_attr->cap.max_recv_sge         = resp.max_recv_sge;
762219820Sjeff	init_attr->cap.max_inline_data      = resp.max_inline_data;
763219820Sjeff	init_attr->sq_sig_all               = resp.sq_sig_all;
764219820Sjeff
765219820Sjeff	return 0;
766219820Sjeff}
767219820Sjeff
768219820Sjeffint ibv_cmd_modify_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,
769219820Sjeff		      int attr_mask,
770219820Sjeff		      struct ibv_modify_qp *cmd, size_t cmd_size)
771219820Sjeff{
772219820Sjeff	IBV_INIT_CMD(cmd, cmd_size, MODIFY_QP);
773219820Sjeff
774219820Sjeff	cmd->qp_handle 		 = qp->handle;
775219820Sjeff	cmd->attr_mask 		 = attr_mask;
776219820Sjeff	cmd->qkey 		 = attr->qkey;
777219820Sjeff	cmd->rq_psn 		 = attr->rq_psn;
778219820Sjeff	cmd->sq_psn 		 = attr->sq_psn;
779219820Sjeff	cmd->dest_qp_num 	 = attr->dest_qp_num;
780219820Sjeff	cmd->qp_access_flags 	 = attr->qp_access_flags;
781219820Sjeff	cmd->pkey_index		 = attr->pkey_index;
782219820Sjeff	cmd->alt_pkey_index 	 = attr->alt_pkey_index;
783219820Sjeff	cmd->qp_state 		 = attr->qp_state;
784219820Sjeff	cmd->cur_qp_state 	 = attr->cur_qp_state;
785219820Sjeff	cmd->path_mtu 		 = attr->path_mtu;
786219820Sjeff	cmd->path_mig_state 	 = attr->path_mig_state;
787219820Sjeff	cmd->en_sqd_async_notify = attr->en_sqd_async_notify;
788219820Sjeff	cmd->max_rd_atomic 	 = attr->max_rd_atomic;
789219820Sjeff	cmd->max_dest_rd_atomic  = attr->max_dest_rd_atomic;
790219820Sjeff	cmd->min_rnr_timer 	 = attr->min_rnr_timer;
791219820Sjeff	cmd->port_num 		 = attr->port_num;
792219820Sjeff	cmd->timeout 		 = attr->timeout;
793219820Sjeff	cmd->retry_cnt 		 = attr->retry_cnt;
794219820Sjeff	cmd->rnr_retry 		 = attr->rnr_retry;
795219820Sjeff	cmd->alt_port_num 	 = attr->alt_port_num;
796219820Sjeff	cmd->alt_timeout 	 = attr->alt_timeout;
797219820Sjeff
798219820Sjeff	memcpy(cmd->dest.dgid, attr->ah_attr.grh.dgid.raw, 16);
799219820Sjeff	cmd->dest.flow_label 	    = attr->ah_attr.grh.flow_label;
800219820Sjeff	cmd->dest.dlid 		    = attr->ah_attr.dlid;
801219820Sjeff	cmd->dest.reserved	    = 0;
802219820Sjeff	cmd->dest.sgid_index 	    = attr->ah_attr.grh.sgid_index;
803219820Sjeff	cmd->dest.hop_limit 	    = attr->ah_attr.grh.hop_limit;
804219820Sjeff	cmd->dest.traffic_class     = attr->ah_attr.grh.traffic_class;
805219820Sjeff	cmd->dest.sl 		    = attr->ah_attr.sl;
806219820Sjeff	cmd->dest.src_path_bits     = attr->ah_attr.src_path_bits;
807219820Sjeff	cmd->dest.static_rate 	    = attr->ah_attr.static_rate;
808219820Sjeff	cmd->dest.is_global 	    = attr->ah_attr.is_global;
809219820Sjeff	cmd->dest.port_num 	    = attr->ah_attr.port_num;
810219820Sjeff
811219820Sjeff	memcpy(cmd->alt_dest.dgid, attr->alt_ah_attr.grh.dgid.raw, 16);
812219820Sjeff	cmd->alt_dest.flow_label    = attr->alt_ah_attr.grh.flow_label;
813219820Sjeff	cmd->alt_dest.dlid 	    = attr->alt_ah_attr.dlid;
814219820Sjeff	cmd->alt_dest.reserved	    = 0;
815219820Sjeff	cmd->alt_dest.sgid_index    = attr->alt_ah_attr.grh.sgid_index;
816219820Sjeff	cmd->alt_dest.hop_limit     = attr->alt_ah_attr.grh.hop_limit;
817219820Sjeff	cmd->alt_dest.traffic_class = attr->alt_ah_attr.grh.traffic_class;
818219820Sjeff	cmd->alt_dest.sl 	    = attr->alt_ah_attr.sl;
819219820Sjeff	cmd->alt_dest.src_path_bits = attr->alt_ah_attr.src_path_bits;
820219820Sjeff	cmd->alt_dest.static_rate   = attr->alt_ah_attr.static_rate;
821219820Sjeff	cmd->alt_dest.is_global     = attr->alt_ah_attr.is_global;
822219820Sjeff	cmd->alt_dest.port_num 	    = attr->alt_ah_attr.port_num;
823219820Sjeff
824219820Sjeff	cmd->reserved[0] = cmd->reserved[1] = 0;
825219820Sjeff
826219820Sjeff	if (write(qp->context->cmd_fd, cmd, cmd_size) != cmd_size)
827219820Sjeff		return errno;
828219820Sjeff
829219820Sjeff	return 0;
830219820Sjeff}
831219820Sjeff
832219820Sjeffint ibv_cmd_create_xrc_rcv_qp(struct ibv_qp_init_attr *init_attr,
833219820Sjeff			     uint32_t *xrc_rcv_qpn)
834219820Sjeff{
835219820Sjeff	struct ibv_create_xrc_rcv_qp cmd;
836219820Sjeff	struct ibv_create_xrc_rcv_qp_resp resp;
837219820Sjeff
838219820Sjeff	if (abi_ver < 6)
839219820Sjeff		return ENOSYS;
840219820Sjeff
841219820Sjeff	IBV_INIT_CMD_RESP(&cmd, sizeof cmd, CREATE_XRC_RCV_QP, &resp,
842219820Sjeff			  sizeof resp);
843219820Sjeff
844219820Sjeff	cmd.xrc_domain_handle = init_attr->xrc_domain->handle;
845219820Sjeff	cmd.max_send_wr     = init_attr->cap.max_send_wr;
846219820Sjeff	cmd.max_recv_wr     = init_attr->cap.max_recv_wr;
847219820Sjeff	cmd.max_send_sge    = init_attr->cap.max_send_sge;
848219820Sjeff	cmd.max_recv_sge    = init_attr->cap.max_recv_sge;
849219820Sjeff	cmd.max_inline_data = init_attr->cap.max_inline_data;
850219820Sjeff	cmd.sq_sig_all	     = init_attr->sq_sig_all;
851219820Sjeff	cmd.qp_type 	     = init_attr->qp_type;
852219820Sjeff	cmd.reserved[0] = cmd.reserved[1] = 0;
853219820Sjeff
854219820Sjeff	if (write(init_attr->xrc_domain->context->cmd_fd, &cmd, sizeof cmd) !=
855219820Sjeff	    sizeof cmd)
856219820Sjeff		return errno;
857219820Sjeff
858219820Sjeff	*xrc_rcv_qpn = resp.qpn;
859219820Sjeff
860219820Sjeff	return 0;
861219820Sjeff}
862219820Sjeff
863219820Sjeffint ibv_cmd_modify_xrc_rcv_qp(struct ibv_xrc_domain *d, uint32_t xrc_qp_num,
864219820Sjeff			      struct ibv_qp_attr *attr, int attr_mask)
865219820Sjeff{
866219820Sjeff	struct ibv_modify_xrc_rcv_qp cmd;
867219820Sjeff
868219820Sjeff	if (abi_ver < 6)
869219820Sjeff		return ENOSYS;
870219820Sjeff
871219820Sjeff	IBV_INIT_CMD(&cmd, sizeof cmd, MODIFY_XRC_RCV_QP);
872219820Sjeff
873219820Sjeff	cmd.xrc_domain_handle	 = d->handle;
874219820Sjeff	cmd.qp_num 		 = xrc_qp_num;
875219820Sjeff	cmd.attr_mask 		 = attr_mask;
876219820Sjeff	cmd.qkey 		 = attr->qkey;
877219820Sjeff	cmd.rq_psn 		 = attr->rq_psn;
878219820Sjeff	cmd.sq_psn 		 = attr->sq_psn;
879219820Sjeff	cmd.dest_qp_num 	 = attr->dest_qp_num;
880219820Sjeff	cmd.qp_access_flags 	 = attr->qp_access_flags;
881219820Sjeff	cmd.pkey_index		 = attr->pkey_index;
882219820Sjeff	cmd.alt_pkey_index 	 = attr->alt_pkey_index;
883219820Sjeff	cmd.qp_state 		 = attr->qp_state;
884219820Sjeff	cmd.cur_qp_state 	 = attr->cur_qp_state;
885219820Sjeff	cmd.path_mtu 		 = attr->path_mtu;
886219820Sjeff	cmd.path_mig_state 	 = attr->path_mig_state;
887219820Sjeff	cmd.en_sqd_async_notify  = attr->en_sqd_async_notify;
888219820Sjeff	cmd.max_rd_atomic 	 = attr->max_rd_atomic;
889219820Sjeff	cmd.max_dest_rd_atomic   = attr->max_dest_rd_atomic;
890219820Sjeff	cmd.min_rnr_timer 	 = attr->min_rnr_timer;
891219820Sjeff	cmd.port_num 		 = attr->port_num;
892219820Sjeff	cmd.timeout 		 = attr->timeout;
893219820Sjeff	cmd.retry_cnt 		 = attr->retry_cnt;
894219820Sjeff	cmd.rnr_retry 		 = attr->rnr_retry;
895219820Sjeff	cmd.alt_port_num 	 = attr->alt_port_num;
896219820Sjeff	cmd.alt_timeout 	 = attr->alt_timeout;
897219820Sjeff
898219820Sjeff	memcpy(cmd.dest.dgid, attr->ah_attr.grh.dgid.raw, 16);
899219820Sjeff	cmd.dest.flow_label 	    = attr->ah_attr.grh.flow_label;
900219820Sjeff	cmd.dest.dlid 		    = attr->ah_attr.dlid;
901219820Sjeff	cmd.dest.reserved	    = 0;
902219820Sjeff	cmd.dest.sgid_index 	    = attr->ah_attr.grh.sgid_index;
903219820Sjeff	cmd.dest.hop_limit 	    = attr->ah_attr.grh.hop_limit;
904219820Sjeff	cmd.dest.traffic_class      = attr->ah_attr.grh.traffic_class;
905219820Sjeff	cmd.dest.sl 		    = attr->ah_attr.sl;
906219820Sjeff	cmd.dest.src_path_bits      = attr->ah_attr.src_path_bits;
907219820Sjeff	cmd.dest.static_rate 	    = attr->ah_attr.static_rate;
908219820Sjeff	cmd.dest.is_global 	    = attr->ah_attr.is_global;
909219820Sjeff	cmd.dest.port_num 	    = attr->ah_attr.port_num;
910219820Sjeff
911219820Sjeff	memcpy(cmd.alt_dest.dgid, attr->alt_ah_attr.grh.dgid.raw, 16);
912219820Sjeff	cmd.alt_dest.flow_label    = attr->alt_ah_attr.grh.flow_label;
913219820Sjeff	cmd.alt_dest.dlid 	    = attr->alt_ah_attr.dlid;
914219820Sjeff	cmd.alt_dest.reserved	    = 0;
915219820Sjeff	cmd.alt_dest.sgid_index    = attr->alt_ah_attr.grh.sgid_index;
916219820Sjeff	cmd.alt_dest.hop_limit     = attr->alt_ah_attr.grh.hop_limit;
917219820Sjeff	cmd.alt_dest.traffic_class = attr->alt_ah_attr.grh.traffic_class;
918219820Sjeff	cmd.alt_dest.sl 	    = attr->alt_ah_attr.sl;
919219820Sjeff	cmd.alt_dest.src_path_bits = attr->alt_ah_attr.src_path_bits;
920219820Sjeff	cmd.alt_dest.static_rate   = attr->alt_ah_attr.static_rate;
921219820Sjeff	cmd.alt_dest.is_global     = attr->alt_ah_attr.is_global;
922219820Sjeff	cmd.alt_dest.port_num 	    = attr->alt_ah_attr.port_num;
923219820Sjeff
924219820Sjeff	cmd.reserved[0] = cmd.reserved[1] = 0;
925219820Sjeff
926219820Sjeff	if (write(d->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
927219820Sjeff		return errno;
928219820Sjeff
929219820Sjeff	return 0;
930219820Sjeff}
931219820Sjeff
932219820Sjeffint ibv_cmd_query_xrc_rcv_qp(struct ibv_xrc_domain *d, uint32_t xrc_qp_num,
933219820Sjeff			     struct ibv_qp_attr *attr, int attr_mask,
934219820Sjeff			     struct ibv_qp_init_attr *init_attr)
935219820Sjeff{
936219820Sjeff	struct ibv_query_xrc_rcv_qp cmd;
937219820Sjeff	struct ibv_query_qp_resp resp;
938219820Sjeff
939219820Sjeff	if (abi_ver < 6)
940219820Sjeff		return ENOSYS;
941219820Sjeff
942219820Sjeff	IBV_INIT_CMD_RESP(&cmd, sizeof cmd, QUERY_XRC_RCV_QP, &resp,
943219820Sjeff			  sizeof resp);
944219820Sjeff	cmd.xrc_domain_handle = d->handle;
945219820Sjeff	cmd.qp_num = xrc_qp_num;
946219820Sjeff	cmd.attr_mask = attr_mask;
947219820Sjeff
948219820Sjeff	if (write(d->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
949219820Sjeff		return errno;
950219820Sjeff
951219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
952219820Sjeff
953219820Sjeff	attr->qkey                          = resp.qkey;
954219820Sjeff	attr->rq_psn                        = resp.rq_psn;
955219820Sjeff	attr->sq_psn                        = resp.sq_psn;
956219820Sjeff	attr->dest_qp_num                   = resp.dest_qp_num;
957219820Sjeff	attr->qp_access_flags               = resp.qp_access_flags;
958219820Sjeff	attr->pkey_index                    = resp.pkey_index;
959219820Sjeff	attr->alt_pkey_index                = resp.alt_pkey_index;
960219820Sjeff	attr->qp_state                      = resp.qp_state;
961219820Sjeff	attr->cur_qp_state                  = resp.cur_qp_state;
962219820Sjeff	attr->path_mtu                      = resp.path_mtu;
963219820Sjeff	attr->path_mig_state                = resp.path_mig_state;
964219820Sjeff	attr->sq_draining                   = resp.sq_draining;
965219820Sjeff	attr->max_rd_atomic                 = resp.max_rd_atomic;
966219820Sjeff	attr->max_dest_rd_atomic            = resp.max_dest_rd_atomic;
967219820Sjeff	attr->min_rnr_timer                 = resp.min_rnr_timer;
968219820Sjeff	attr->port_num                      = resp.port_num;
969219820Sjeff	attr->timeout                       = resp.timeout;
970219820Sjeff	attr->retry_cnt                     = resp.retry_cnt;
971219820Sjeff	attr->rnr_retry                     = resp.rnr_retry;
972219820Sjeff	attr->alt_port_num                  = resp.alt_port_num;
973219820Sjeff	attr->alt_timeout                   = resp.alt_timeout;
974219820Sjeff	attr->cap.max_send_wr               = resp.max_send_wr;
975219820Sjeff	attr->cap.max_recv_wr               = resp.max_recv_wr;
976219820Sjeff	attr->cap.max_send_sge              = resp.max_send_sge;
977219820Sjeff	attr->cap.max_recv_sge              = resp.max_recv_sge;
978219820Sjeff	attr->cap.max_inline_data           = resp.max_inline_data;
979219820Sjeff
980219820Sjeff	memcpy(attr->ah_attr.grh.dgid.raw, resp.dest.dgid, 16);
981219820Sjeff	attr->ah_attr.grh.flow_label        = resp.dest.flow_label;
982219820Sjeff	attr->ah_attr.dlid                  = resp.dest.dlid;
983219820Sjeff	attr->ah_attr.grh.sgid_index        = resp.dest.sgid_index;
984219820Sjeff	attr->ah_attr.grh.hop_limit         = resp.dest.hop_limit;
985219820Sjeff	attr->ah_attr.grh.traffic_class     = resp.dest.traffic_class;
986219820Sjeff	attr->ah_attr.sl                    = resp.dest.sl;
987219820Sjeff	attr->ah_attr.src_path_bits         = resp.dest.src_path_bits;
988219820Sjeff	attr->ah_attr.static_rate           = resp.dest.static_rate;
989219820Sjeff	attr->ah_attr.is_global             = resp.dest.is_global;
990219820Sjeff	attr->ah_attr.port_num              = resp.dest.port_num;
991219820Sjeff
992219820Sjeff	memcpy(attr->alt_ah_attr.grh.dgid.raw, resp.alt_dest.dgid, 16);
993219820Sjeff	attr->alt_ah_attr.grh.flow_label    = resp.alt_dest.flow_label;
994219820Sjeff	attr->alt_ah_attr.dlid              = resp.alt_dest.dlid;
995219820Sjeff	attr->alt_ah_attr.grh.sgid_index    = resp.alt_dest.sgid_index;
996219820Sjeff	attr->alt_ah_attr.grh.hop_limit     = resp.alt_dest.hop_limit;
997219820Sjeff	attr->alt_ah_attr.grh.traffic_class = resp.alt_dest.traffic_class;
998219820Sjeff	attr->alt_ah_attr.sl                = resp.alt_dest.sl;
999219820Sjeff	attr->alt_ah_attr.src_path_bits     = resp.alt_dest.src_path_bits;
1000219820Sjeff	attr->alt_ah_attr.static_rate       = resp.alt_dest.static_rate;
1001219820Sjeff	attr->alt_ah_attr.is_global         = resp.alt_dest.is_global;
1002219820Sjeff	attr->alt_ah_attr.port_num          = resp.alt_dest.port_num;
1003219820Sjeff
1004219820Sjeff	init_attr->cap.max_send_wr          = resp.max_send_wr;
1005219820Sjeff	init_attr->cap.max_recv_wr          = resp.max_recv_wr;
1006219820Sjeff	init_attr->cap.max_send_sge         = resp.max_send_sge;
1007219820Sjeff	init_attr->cap.max_recv_sge         = resp.max_recv_sge;
1008219820Sjeff	init_attr->cap.max_inline_data      = resp.max_inline_data;
1009219820Sjeff	init_attr->sq_sig_all               = resp.sq_sig_all;
1010219820Sjeff
1011219820Sjeff	return 0;
1012219820Sjeff}
1013219820Sjeff
1014219820Sjeffstatic int ibv_cmd_destroy_qp_v1(struct ibv_qp *qp)
1015219820Sjeff{
1016219820Sjeff	struct ibv_destroy_qp_v1 cmd;
1017219820Sjeff
1018219820Sjeff	IBV_INIT_CMD(&cmd, sizeof cmd, DESTROY_QP);
1019219820Sjeff	cmd.qp_handle = qp->handle;
1020219820Sjeff
1021219820Sjeff	if (write(qp->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1022219820Sjeff		return errno;
1023219820Sjeff
1024219820Sjeff	return 0;
1025219820Sjeff}
1026219820Sjeff
1027219820Sjeffint ibv_cmd_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr,
1028219820Sjeff		      struct ibv_send_wr **bad_wr)
1029219820Sjeff{
1030219820Sjeff	struct ibv_post_send     *cmd;
1031219820Sjeff	struct ibv_post_send_resp resp;
1032219820Sjeff	struct ibv_send_wr       *i;
1033219820Sjeff	struct ibv_kern_send_wr  *n, *tmp;
1034219820Sjeff	struct ibv_sge           *s;
1035219820Sjeff	unsigned                  wr_count = 0;
1036219820Sjeff	unsigned                  sge_count = 0;
1037219820Sjeff	int                       cmd_size;
1038219820Sjeff	int                       ret = 0;
1039219820Sjeff
1040219820Sjeff	for (i = wr; i; i = i->next) {
1041219820Sjeff		wr_count++;
1042219820Sjeff		sge_count += i->num_sge;
1043219820Sjeff	}
1044219820Sjeff
1045219820Sjeff	cmd_size = sizeof *cmd + wr_count * sizeof *n + sge_count * sizeof *s;
1046219820Sjeff	cmd  = alloca(cmd_size);
1047219820Sjeff
1048219820Sjeff	IBV_INIT_CMD_RESP(cmd, cmd_size, POST_SEND, &resp, sizeof resp);
1049219820Sjeff	cmd->qp_handle = ibqp->handle;
1050219820Sjeff	cmd->wr_count  = wr_count;
1051219820Sjeff	cmd->sge_count = sge_count;
1052219820Sjeff	cmd->wqe_size  = sizeof *n;
1053219820Sjeff
1054219820Sjeff	n = (struct ibv_kern_send_wr *) ((void *) cmd + sizeof *cmd);
1055219820Sjeff	s = (struct ibv_sge *) (n + wr_count);
1056219820Sjeff
1057219820Sjeff	tmp = n;
1058219820Sjeff	for (i = wr; i; i = i->next) {
1059219820Sjeff		tmp->wr_id 	= i->wr_id;
1060219820Sjeff		tmp->num_sge 	= i->num_sge;
1061219820Sjeff		tmp->opcode 	= i->opcode;
1062219820Sjeff		tmp->send_flags = i->send_flags;
1063219820Sjeff		tmp->imm_data 	= i->imm_data;
1064219820Sjeff		if (ibqp->qp_type == IBV_QPT_UD) {
1065219820Sjeff			tmp->wr.ud.ah 	       = i->wr.ud.ah->handle;
1066219820Sjeff			tmp->wr.ud.remote_qpn  = i->wr.ud.remote_qpn;
1067219820Sjeff			tmp->wr.ud.remote_qkey = i->wr.ud.remote_qkey;
1068219820Sjeff		} else {
1069219820Sjeff			switch (i->opcode) {
1070219820Sjeff			case IBV_WR_RDMA_WRITE:
1071219820Sjeff			case IBV_WR_RDMA_WRITE_WITH_IMM:
1072219820Sjeff			case IBV_WR_RDMA_READ:
1073219820Sjeff				tmp->wr.rdma.remote_addr =
1074219820Sjeff					i->wr.rdma.remote_addr;
1075219820Sjeff				tmp->wr.rdma.rkey = i->wr.rdma.rkey;
1076219820Sjeff				break;
1077219820Sjeff			case IBV_WR_ATOMIC_CMP_AND_SWP:
1078219820Sjeff			case IBV_WR_ATOMIC_FETCH_AND_ADD:
1079219820Sjeff				tmp->wr.atomic.remote_addr =
1080219820Sjeff					i->wr.atomic.remote_addr;
1081219820Sjeff				tmp->wr.atomic.compare_add =
1082219820Sjeff					i->wr.atomic.compare_add;
1083219820Sjeff				tmp->wr.atomic.swap = i->wr.atomic.swap;
1084219820Sjeff				tmp->wr.atomic.rkey = i->wr.atomic.rkey;
1085219820Sjeff				break;
1086219820Sjeff			default:
1087219820Sjeff				break;
1088219820Sjeff			}
1089219820Sjeff		}
1090219820Sjeff
1091219820Sjeff		if (tmp->num_sge) {
1092219820Sjeff			memcpy(s, i->sg_list, tmp->num_sge * sizeof *s);
1093219820Sjeff			s += tmp->num_sge;
1094219820Sjeff		}
1095219820Sjeff
1096219820Sjeff		tmp++;
1097219820Sjeff	}
1098219820Sjeff
1099219820Sjeff	resp.bad_wr = 0;
1100219820Sjeff	if (write(ibqp->context->cmd_fd, cmd, cmd_size) != cmd_size)
1101219820Sjeff		ret = errno;
1102219820Sjeff
1103219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
1104219820Sjeff
1105219820Sjeff	wr_count = resp.bad_wr;
1106219820Sjeff	if (wr_count) {
1107219820Sjeff		i = wr;
1108219820Sjeff		while (--wr_count)
1109219820Sjeff			i = i->next;
1110219820Sjeff		*bad_wr = i;
1111219820Sjeff	} else if (ret)
1112219820Sjeff		*bad_wr = wr;
1113219820Sjeff
1114219820Sjeff	return ret;
1115219820Sjeff}
1116219820Sjeff
1117219820Sjeffint ibv_cmd_post_recv(struct ibv_qp *ibqp, struct ibv_recv_wr *wr,
1118219820Sjeff		      struct ibv_recv_wr **bad_wr)
1119219820Sjeff{
1120219820Sjeff	struct ibv_post_recv     *cmd;
1121219820Sjeff	struct ibv_post_recv_resp resp;
1122219820Sjeff	struct ibv_recv_wr       *i;
1123219820Sjeff	struct ibv_kern_recv_wr  *n, *tmp;
1124219820Sjeff	struct ibv_sge           *s;
1125219820Sjeff	unsigned                  wr_count = 0;
1126219820Sjeff	unsigned                  sge_count = 0;
1127219820Sjeff	int                       cmd_size;
1128219820Sjeff	int                       ret = 0;
1129219820Sjeff
1130219820Sjeff	for (i = wr; i; i = i->next) {
1131219820Sjeff		wr_count++;
1132219820Sjeff		sge_count += i->num_sge;
1133219820Sjeff	}
1134219820Sjeff
1135219820Sjeff	cmd_size = sizeof *cmd + wr_count * sizeof *n + sge_count * sizeof *s;
1136219820Sjeff	cmd  = alloca(cmd_size);
1137219820Sjeff
1138219820Sjeff	IBV_INIT_CMD_RESP(cmd, cmd_size, POST_RECV, &resp, sizeof resp);
1139219820Sjeff	cmd->qp_handle = ibqp->handle;
1140219820Sjeff	cmd->wr_count  = wr_count;
1141219820Sjeff	cmd->sge_count = sge_count;
1142219820Sjeff	cmd->wqe_size  = sizeof *n;
1143219820Sjeff
1144219820Sjeff	n = (struct ibv_kern_recv_wr *) ((void *) cmd + sizeof *cmd);
1145219820Sjeff	s = (struct ibv_sge *) (n + wr_count);
1146219820Sjeff
1147219820Sjeff	tmp = n;
1148219820Sjeff	for (i = wr; i; i = i->next) {
1149219820Sjeff		tmp->wr_id   = i->wr_id;
1150219820Sjeff		tmp->num_sge = i->num_sge;
1151219820Sjeff
1152219820Sjeff		if (tmp->num_sge) {
1153219820Sjeff			memcpy(s, i->sg_list, tmp->num_sge * sizeof *s);
1154219820Sjeff			s += tmp->num_sge;
1155219820Sjeff		}
1156219820Sjeff
1157219820Sjeff		tmp++;
1158219820Sjeff	}
1159219820Sjeff
1160219820Sjeff	resp.bad_wr = 0;
1161219820Sjeff	if (write(ibqp->context->cmd_fd, cmd, cmd_size) != cmd_size)
1162219820Sjeff		ret = errno;
1163219820Sjeff
1164219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
1165219820Sjeff
1166219820Sjeff	wr_count = resp.bad_wr;
1167219820Sjeff	if (wr_count) {
1168219820Sjeff		i = wr;
1169219820Sjeff		while (--wr_count)
1170219820Sjeff			i = i->next;
1171219820Sjeff		*bad_wr = i;
1172219820Sjeff	} else if (ret)
1173219820Sjeff		*bad_wr = wr;
1174219820Sjeff
1175219820Sjeff	return ret;
1176219820Sjeff}
1177219820Sjeff
1178219820Sjeffint ibv_cmd_post_srq_recv(struct ibv_srq *srq, struct ibv_recv_wr *wr,
1179219820Sjeff		      struct ibv_recv_wr **bad_wr)
1180219820Sjeff{
1181219820Sjeff	struct ibv_post_srq_recv *cmd;
1182219820Sjeff	struct ibv_post_srq_recv_resp resp;
1183219820Sjeff	struct ibv_recv_wr       *i;
1184219820Sjeff	struct ibv_kern_recv_wr  *n, *tmp;
1185219820Sjeff	struct ibv_sge           *s;
1186219820Sjeff	unsigned                  wr_count = 0;
1187219820Sjeff	unsigned                  sge_count = 0;
1188219820Sjeff	int                       cmd_size;
1189219820Sjeff	int                       ret = 0;
1190219820Sjeff
1191219820Sjeff	for (i = wr; i; i = i->next) {
1192219820Sjeff		wr_count++;
1193219820Sjeff		sge_count += i->num_sge;
1194219820Sjeff	}
1195219820Sjeff
1196219820Sjeff	cmd_size = sizeof *cmd + wr_count * sizeof *n + sge_count * sizeof *s;
1197219820Sjeff	cmd  = alloca(cmd_size);
1198219820Sjeff
1199219820Sjeff	IBV_INIT_CMD_RESP(cmd, cmd_size, POST_SRQ_RECV, &resp, sizeof resp);
1200219820Sjeff	cmd->srq_handle = srq->handle;
1201219820Sjeff	cmd->wr_count  = wr_count;
1202219820Sjeff	cmd->sge_count = sge_count;
1203219820Sjeff	cmd->wqe_size  = sizeof *n;
1204219820Sjeff
1205219820Sjeff	n = (struct ibv_kern_recv_wr *) ((void *) cmd + sizeof *cmd);
1206219820Sjeff	s = (struct ibv_sge *) (n + wr_count);
1207219820Sjeff
1208219820Sjeff	tmp = n;
1209219820Sjeff	for (i = wr; i; i = i->next) {
1210219820Sjeff		tmp->wr_id = i->wr_id;
1211219820Sjeff		tmp->num_sge = i->num_sge;
1212219820Sjeff
1213219820Sjeff		if (tmp->num_sge) {
1214219820Sjeff			memcpy(s, i->sg_list, tmp->num_sge * sizeof *s);
1215219820Sjeff			s += tmp->num_sge;
1216219820Sjeff		}
1217219820Sjeff
1218219820Sjeff		tmp++;
1219219820Sjeff	}
1220219820Sjeff
1221219820Sjeff	resp.bad_wr = 0;
1222219820Sjeff	if (write(srq->context->cmd_fd, cmd, cmd_size) != cmd_size)
1223219820Sjeff		ret = errno;
1224219820Sjeff
1225219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
1226219820Sjeff
1227219820Sjeff	wr_count = resp.bad_wr;
1228219820Sjeff	if (wr_count) {
1229219820Sjeff		i = wr;
1230219820Sjeff		while (--wr_count)
1231219820Sjeff			i = i->next;
1232219820Sjeff		*bad_wr = i;
1233219820Sjeff	} else if (ret)
1234219820Sjeff		*bad_wr = wr;
1235219820Sjeff
1236219820Sjeff	return ret;
1237219820Sjeff}
1238219820Sjeff
1239219820Sjeffint ibv_cmd_create_ah(struct ibv_pd *pd, struct ibv_ah *ah,
1240219820Sjeff		      struct ibv_ah_attr *attr)
1241219820Sjeff{
1242219820Sjeff	struct ibv_create_ah      cmd;
1243219820Sjeff	struct ibv_create_ah_resp resp;
1244219820Sjeff
1245219820Sjeff	IBV_INIT_CMD_RESP(&cmd, sizeof cmd, CREATE_AH, &resp, sizeof resp);
1246219820Sjeff	cmd.user_handle            = (uintptr_t) ah;
1247219820Sjeff	cmd.pd_handle              = pd->handle;
1248219820Sjeff	cmd.attr.dlid              = attr->dlid;
1249219820Sjeff	cmd.attr.sl                = attr->sl;
1250219820Sjeff	cmd.attr.src_path_bits     = attr->src_path_bits;
1251219820Sjeff	cmd.attr.static_rate       = attr->static_rate;
1252219820Sjeff	cmd.attr.is_global         = attr->is_global;
1253219820Sjeff	cmd.attr.port_num          = attr->port_num;
1254219820Sjeff	cmd.attr.grh.flow_label    = attr->grh.flow_label;
1255219820Sjeff	cmd.attr.grh.sgid_index    = attr->grh.sgid_index;
1256219820Sjeff	cmd.attr.grh.hop_limit     = attr->grh.hop_limit;
1257219820Sjeff	cmd.attr.grh.traffic_class = attr->grh.traffic_class;
1258219820Sjeff	memcpy(cmd.attr.grh.dgid, attr->grh.dgid.raw, 16);
1259219820Sjeff
1260219820Sjeff	if (write(pd->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1261219820Sjeff		return errno;
1262219820Sjeff
1263219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
1264219820Sjeff
1265219820Sjeff	ah->handle  = resp.handle;
1266219820Sjeff	ah->context = pd->context;
1267219820Sjeff
1268219820Sjeff	return 0;
1269219820Sjeff}
1270219820Sjeff
1271219820Sjeffint ibv_cmd_destroy_ah(struct ibv_ah *ah)
1272219820Sjeff{
1273219820Sjeff	struct ibv_destroy_ah cmd;
1274219820Sjeff
1275219820Sjeff	IBV_INIT_CMD(&cmd, sizeof cmd, DESTROY_AH);
1276219820Sjeff	cmd.ah_handle = ah->handle;
1277219820Sjeff
1278219820Sjeff	if (write(ah->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1279219820Sjeff		return errno;
1280219820Sjeff
1281219820Sjeff	return 0;
1282219820Sjeff}
1283219820Sjeff
1284219820Sjeffint ibv_cmd_destroy_qp(struct ibv_qp *qp)
1285219820Sjeff{
1286219820Sjeff	struct ibv_destroy_qp      cmd;
1287219820Sjeff	struct ibv_destroy_qp_resp resp;
1288219820Sjeff
1289219820Sjeff	if (abi_ver == 1)
1290219820Sjeff		return ibv_cmd_destroy_qp_v1(qp);
1291219820Sjeff
1292219820Sjeff	IBV_INIT_CMD_RESP(&cmd, sizeof cmd, DESTROY_QP, &resp, sizeof resp);
1293219820Sjeff	cmd.qp_handle = qp->handle;
1294219820Sjeff	cmd.reserved  = 0;
1295219820Sjeff
1296219820Sjeff	if (write(qp->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1297219820Sjeff		return errno;
1298219820Sjeff
1299219820Sjeff	VALGRIND_MAKE_MEM_DEFINED(&resp, sizeof resp);
1300219820Sjeff
1301219820Sjeff	pthread_mutex_lock(&qp->mutex);
1302219820Sjeff	while (qp->events_completed != resp.events_reported)
1303219820Sjeff		pthread_cond_wait(&qp->cond, &qp->mutex);
1304219820Sjeff	pthread_mutex_unlock(&qp->mutex);
1305219820Sjeff
1306219820Sjeff	return 0;
1307219820Sjeff}
1308219820Sjeff
1309219820Sjeffint ibv_cmd_attach_mcast(struct ibv_qp *qp, const union ibv_gid *gid, uint16_t lid)
1310219820Sjeff{
1311219820Sjeff	struct ibv_attach_mcast cmd;
1312219820Sjeff
1313219820Sjeff	IBV_INIT_CMD(&cmd, sizeof cmd, ATTACH_MCAST);
1314219820Sjeff	memcpy(cmd.gid, gid->raw, sizeof cmd.gid);
1315219820Sjeff	cmd.qp_handle = qp->handle;
1316219820Sjeff	cmd.mlid      = lid;
1317219820Sjeff	cmd.reserved  = 0;
1318219820Sjeff
1319219820Sjeff	if (write(qp->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1320219820Sjeff		return errno;
1321219820Sjeff
1322219820Sjeff	return 0;
1323219820Sjeff}
1324219820Sjeff
1325219820Sjeffint ibv_cmd_detach_mcast(struct ibv_qp *qp, const union ibv_gid *gid, uint16_t lid)
1326219820Sjeff{
1327219820Sjeff	struct ibv_detach_mcast cmd;
1328219820Sjeff
1329219820Sjeff	IBV_INIT_CMD(&cmd, sizeof cmd, DETACH_MCAST);
1330219820Sjeff	memcpy(cmd.gid, gid->raw, sizeof cmd.gid);
1331219820Sjeff	cmd.qp_handle = qp->handle;
1332219820Sjeff	cmd.mlid      = lid;
1333219820Sjeff	cmd.reserved  = 0;
1334219820Sjeff
1335219820Sjeff	if (write(qp->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1336219820Sjeff		return errno;
1337219820Sjeff
1338219820Sjeff	return 0;
1339219820Sjeff}
1340219820Sjeff
1341219820Sjeffint ibv_cmd_open_xrc_domain(struct ibv_context *context, int fd, int oflag,
1342219820Sjeff			    struct ibv_xrc_domain *d,
1343219820Sjeff			    struct ibv_open_xrc_domain_resp *resp,
1344219820Sjeff			    size_t resp_size)
1345219820Sjeff{
1346219820Sjeff	struct ibv_open_xrc_domain cmd;
1347219820Sjeff
1348219820Sjeff	if (abi_ver < 6)
1349219820Sjeff		return ENOSYS;
1350219820Sjeff
1351219820Sjeff	IBV_INIT_CMD_RESP(&cmd, sizeof cmd, OPEN_XRC_DOMAIN, resp, resp_size);
1352219820Sjeff	cmd.fd = fd;
1353219820Sjeff	cmd.oflags = oflag;
1354219820Sjeff
1355219820Sjeff	if (write(context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1356219820Sjeff		return errno;
1357219820Sjeff
1358219820Sjeff	d->handle = resp->xrcd_handle;
1359219820Sjeff
1360219820Sjeff	return 0;
1361219820Sjeff}
1362219820Sjeff
1363219820Sjeffint ibv_cmd_close_xrc_domain(struct ibv_xrc_domain *d)
1364219820Sjeff{
1365219820Sjeff	struct ibv_close_xrc_domain cmd;
1366219820Sjeff
1367219820Sjeff	if (abi_ver < 6)
1368219820Sjeff		return ENOSYS;
1369219820Sjeff
1370219820Sjeff	IBV_INIT_CMD(&cmd, sizeof cmd, CLOSE_XRC_DOMAIN);
1371219820Sjeff	cmd.xrcd_handle = d->handle;
1372219820Sjeff
1373219820Sjeff	if (write(d->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1374219820Sjeff		return errno;
1375219820Sjeff	return 0;
1376219820Sjeff}
1377219820Sjeff
1378219820Sjeffint ibv_cmd_reg_xrc_rcv_qp(struct ibv_xrc_domain *d, uint32_t xrc_qp_num)
1379219820Sjeff{
1380219820Sjeff	struct ibv_reg_xrc_rcv_qp cmd;
1381219820Sjeff
1382219820Sjeff	if (abi_ver < 6)
1383219820Sjeff		return ENOSYS;
1384219820Sjeff
1385219820Sjeff	IBV_INIT_CMD(&cmd, sizeof cmd, REG_XRC_RCV_QP);
1386219820Sjeff	cmd.xrc_domain_handle = d->handle;
1387219820Sjeff	cmd.qp_num = xrc_qp_num;
1388219820Sjeff
1389219820Sjeff	if (write(d->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1390219820Sjeff		return errno;
1391219820Sjeff	return 0;
1392219820Sjeff}
1393219820Sjeff
1394219820Sjeffint ibv_cmd_unreg_xrc_rcv_qp(struct ibv_xrc_domain *d, uint32_t xrc_qp_num)
1395219820Sjeff{
1396219820Sjeff	struct ibv_unreg_xrc_rcv_qp cmd;
1397219820Sjeff
1398219820Sjeff	if (abi_ver < 6)
1399219820Sjeff		return ENOSYS;
1400219820Sjeff
1401219820Sjeff	IBV_INIT_CMD(&cmd, sizeof cmd, UNREG_XRC_RCV_QP);
1402219820Sjeff	cmd.xrc_domain_handle = d->handle;
1403219820Sjeff	cmd.qp_num = xrc_qp_num;
1404219820Sjeff
1405219820Sjeff	if (write(d->context->cmd_fd, &cmd, sizeof cmd) != sizeof cmd)
1406219820Sjeff		return errno;
1407219820Sjeff	return 0;
1408219820Sjeff}
1409219820Sjeff
1410