1cdcd52d4SBartosz Sobczak /*-
2cdcd52d4SBartosz Sobczak * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB
3cdcd52d4SBartosz Sobczak *
401fbb869SBartosz Sobczak * Copyright (C) 2019 - 2023 Intel Corporation
5cdcd52d4SBartosz Sobczak *
6cdcd52d4SBartosz Sobczak * This software is available to you under a choice of one of two
7cdcd52d4SBartosz Sobczak * licenses. You may choose to be licensed under the terms of the GNU
8cdcd52d4SBartosz Sobczak * General Public License (GPL) Version 2, available from the file
9cdcd52d4SBartosz Sobczak * COPYING in the main directory of this source tree, or the
10cdcd52d4SBartosz Sobczak * OpenFabrics.org BSD license below:
11cdcd52d4SBartosz Sobczak *
12cdcd52d4SBartosz Sobczak * Redistribution and use in source and binary forms, with or
13cdcd52d4SBartosz Sobczak * without modification, are permitted provided that the following
14cdcd52d4SBartosz Sobczak * conditions are met:
15cdcd52d4SBartosz Sobczak *
16cdcd52d4SBartosz Sobczak * - Redistributions of source code must retain the above
17cdcd52d4SBartosz Sobczak * copyright notice, this list of conditions and the following
18cdcd52d4SBartosz Sobczak * disclaimer.
19cdcd52d4SBartosz Sobczak *
20cdcd52d4SBartosz Sobczak * - Redistributions in binary form must reproduce the above
21cdcd52d4SBartosz Sobczak * copyright notice, this list of conditions and the following
22cdcd52d4SBartosz Sobczak * disclaimer in the documentation and/or other materials
23cdcd52d4SBartosz Sobczak * provided with the distribution.
24cdcd52d4SBartosz Sobczak *
25cdcd52d4SBartosz Sobczak * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26cdcd52d4SBartosz Sobczak * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27cdcd52d4SBartosz Sobczak * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28cdcd52d4SBartosz Sobczak * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29cdcd52d4SBartosz Sobczak * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30cdcd52d4SBartosz Sobczak * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31cdcd52d4SBartosz Sobczak * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32cdcd52d4SBartosz Sobczak * SOFTWARE.
33cdcd52d4SBartosz Sobczak */
34cdcd52d4SBartosz Sobczak
35cdcd52d4SBartosz Sobczak #include <config.h>
36cdcd52d4SBartosz Sobczak #include <stdlib.h>
37cdcd52d4SBartosz Sobczak #include <stdio.h>
38cdcd52d4SBartosz Sobczak #include <string.h>
39cdcd52d4SBartosz Sobczak #include <unistd.h>
40cdcd52d4SBartosz Sobczak #include <signal.h>
41cdcd52d4SBartosz Sobczak #include <errno.h>
42cdcd52d4SBartosz Sobczak #include <sys/param.h>
43cdcd52d4SBartosz Sobczak #include <sys/mman.h>
44cdcd52d4SBartosz Sobczak #include <netinet/in.h>
45cdcd52d4SBartosz Sobczak #include <sys/stat.h>
46cdcd52d4SBartosz Sobczak #include <fcntl.h>
47cdcd52d4SBartosz Sobczak #include <stdbool.h>
48777e472cSBartosz Sobczak #include <infiniband/opcode.h>
49cdcd52d4SBartosz Sobczak
50cdcd52d4SBartosz Sobczak #include "irdma_umain.h"
51cdcd52d4SBartosz Sobczak #include "abi.h"
52cdcd52d4SBartosz Sobczak
53cdcd52d4SBartosz Sobczak static inline void
print_fw_ver(uint64_t fw_ver,char * str,size_t len)54cdcd52d4SBartosz Sobczak print_fw_ver(uint64_t fw_ver, char *str, size_t len)
55cdcd52d4SBartosz Sobczak {
56cdcd52d4SBartosz Sobczak uint16_t major, minor;
57cdcd52d4SBartosz Sobczak
58cdcd52d4SBartosz Sobczak major = fw_ver >> 32 & 0xffff;
59cdcd52d4SBartosz Sobczak minor = fw_ver & 0xffff;
60cdcd52d4SBartosz Sobczak
61cdcd52d4SBartosz Sobczak snprintf(str, len, "%d.%d", major, minor);
62cdcd52d4SBartosz Sobczak }
63cdcd52d4SBartosz Sobczak
64cdcd52d4SBartosz Sobczak /**
65cdcd52d4SBartosz Sobczak * irdma_uquery_device_ex - query device attributes including extended properties
66cdcd52d4SBartosz Sobczak * @context: user context for the device
67cdcd52d4SBartosz Sobczak * @input: extensible input struct for ibv_query_device_ex verb
68cdcd52d4SBartosz Sobczak * @attr: extended device attribute struct
69cdcd52d4SBartosz Sobczak * @attr_size: size of extended device attribute struct
70cdcd52d4SBartosz Sobczak **/
71cdcd52d4SBartosz Sobczak int
irdma_uquery_device_ex(struct ibv_context * context,const struct ibv_query_device_ex_input * input,struct ibv_device_attr_ex * attr,size_t attr_size)72cdcd52d4SBartosz Sobczak irdma_uquery_device_ex(struct ibv_context *context,
73cdcd52d4SBartosz Sobczak const struct ibv_query_device_ex_input *input,
74cdcd52d4SBartosz Sobczak struct ibv_device_attr_ex *attr, size_t attr_size)
75cdcd52d4SBartosz Sobczak {
76cdcd52d4SBartosz Sobczak struct irdma_query_device_ex cmd = {};
77cdcd52d4SBartosz Sobczak struct irdma_query_device_ex_resp resp = {};
78cdcd52d4SBartosz Sobczak uint64_t fw_ver;
79cdcd52d4SBartosz Sobczak int ret;
80cdcd52d4SBartosz Sobczak
81cdcd52d4SBartosz Sobczak ret = ibv_cmd_query_device_ex(context, input, attr, attr_size, &fw_ver,
82cdcd52d4SBartosz Sobczak &cmd.ibv_cmd, sizeof(cmd.ibv_cmd), sizeof(cmd),
83cdcd52d4SBartosz Sobczak &resp.ibv_resp, sizeof(resp.ibv_resp), sizeof(resp));
84cdcd52d4SBartosz Sobczak if (ret)
85cdcd52d4SBartosz Sobczak return ret;
86cdcd52d4SBartosz Sobczak
87cdcd52d4SBartosz Sobczak print_fw_ver(fw_ver, attr->orig_attr.fw_ver, sizeof(attr->orig_attr.fw_ver));
88cdcd52d4SBartosz Sobczak
89cdcd52d4SBartosz Sobczak return 0;
90cdcd52d4SBartosz Sobczak }
91cdcd52d4SBartosz Sobczak
92cdcd52d4SBartosz Sobczak /**
93cdcd52d4SBartosz Sobczak * irdma_uquery_device - call driver to query device for max resources
94cdcd52d4SBartosz Sobczak * @context: user context for the device
95cdcd52d4SBartosz Sobczak * @attr: where to save all the mx resources from the driver
96cdcd52d4SBartosz Sobczak **/
97cdcd52d4SBartosz Sobczak int
irdma_uquery_device(struct ibv_context * context,struct ibv_device_attr * attr)98cdcd52d4SBartosz Sobczak irdma_uquery_device(struct ibv_context *context, struct ibv_device_attr *attr)
99cdcd52d4SBartosz Sobczak {
100cdcd52d4SBartosz Sobczak struct ibv_query_device cmd;
101cdcd52d4SBartosz Sobczak uint64_t fw_ver;
102cdcd52d4SBartosz Sobczak int ret;
103cdcd52d4SBartosz Sobczak
104cdcd52d4SBartosz Sobczak ret = ibv_cmd_query_device(context, attr, &fw_ver, &cmd, sizeof(cmd));
105cdcd52d4SBartosz Sobczak if (ret)
106cdcd52d4SBartosz Sobczak return ret;
107cdcd52d4SBartosz Sobczak
108cdcd52d4SBartosz Sobczak print_fw_ver(fw_ver, attr->fw_ver, sizeof(attr->fw_ver));
109cdcd52d4SBartosz Sobczak
110cdcd52d4SBartosz Sobczak return 0;
111cdcd52d4SBartosz Sobczak }
112cdcd52d4SBartosz Sobczak
113cdcd52d4SBartosz Sobczak /**
114cdcd52d4SBartosz Sobczak * irdma_uquery_port - get port attributes (msg size, lnk, mtu...)
115cdcd52d4SBartosz Sobczak * @context: user context of the device
116cdcd52d4SBartosz Sobczak * @port: port for the attributes
117cdcd52d4SBartosz Sobczak * @attr: to return port attributes
118cdcd52d4SBartosz Sobczak **/
119cdcd52d4SBartosz Sobczak int
irdma_uquery_port(struct ibv_context * context,uint8_t port,struct ibv_port_attr * attr)120cdcd52d4SBartosz Sobczak irdma_uquery_port(struct ibv_context *context, uint8_t port,
121cdcd52d4SBartosz Sobczak struct ibv_port_attr *attr)
122cdcd52d4SBartosz Sobczak {
123cdcd52d4SBartosz Sobczak struct ibv_query_port cmd;
124cdcd52d4SBartosz Sobczak
125cdcd52d4SBartosz Sobczak return ibv_cmd_query_port(context, port, attr, &cmd, sizeof(cmd));
126cdcd52d4SBartosz Sobczak }
127cdcd52d4SBartosz Sobczak
128cdcd52d4SBartosz Sobczak /**
129cdcd52d4SBartosz Sobczak * irdma_ualloc_pd - allocates protection domain and return pd ptr
130cdcd52d4SBartosz Sobczak * @context: user context of the device
131cdcd52d4SBartosz Sobczak **/
132cdcd52d4SBartosz Sobczak struct ibv_pd *
irdma_ualloc_pd(struct ibv_context * context)133cdcd52d4SBartosz Sobczak irdma_ualloc_pd(struct ibv_context *context)
134cdcd52d4SBartosz Sobczak {
135cdcd52d4SBartosz Sobczak struct ibv_alloc_pd cmd;
136cdcd52d4SBartosz Sobczak struct irdma_ualloc_pd_resp resp = {};
137cdcd52d4SBartosz Sobczak struct irdma_upd *iwupd;
138cdcd52d4SBartosz Sobczak int err;
139cdcd52d4SBartosz Sobczak
140777e472cSBartosz Sobczak iwupd = calloc(1, sizeof(*iwupd));
141cdcd52d4SBartosz Sobczak if (!iwupd)
142cdcd52d4SBartosz Sobczak return NULL;
143cdcd52d4SBartosz Sobczak
144cdcd52d4SBartosz Sobczak err = ibv_cmd_alloc_pd(context, &iwupd->ibv_pd, &cmd, sizeof(cmd),
145cdcd52d4SBartosz Sobczak &resp.ibv_resp, sizeof(resp));
146cdcd52d4SBartosz Sobczak if (err)
147cdcd52d4SBartosz Sobczak goto err_free;
148cdcd52d4SBartosz Sobczak
149cdcd52d4SBartosz Sobczak iwupd->pd_id = resp.pd_id;
150cdcd52d4SBartosz Sobczak
151cdcd52d4SBartosz Sobczak return &iwupd->ibv_pd;
152cdcd52d4SBartosz Sobczak
153cdcd52d4SBartosz Sobczak err_free:
154cdcd52d4SBartosz Sobczak free(iwupd);
155*5b5f7d0eSBartosz Sobczak
156cdcd52d4SBartosz Sobczak errno = err;
157cdcd52d4SBartosz Sobczak return NULL;
158cdcd52d4SBartosz Sobczak }
159cdcd52d4SBartosz Sobczak
160cdcd52d4SBartosz Sobczak /**
161cdcd52d4SBartosz Sobczak * irdma_ufree_pd - free pd resources
162cdcd52d4SBartosz Sobczak * @pd: pd to free resources
163cdcd52d4SBartosz Sobczak */
164cdcd52d4SBartosz Sobczak int
irdma_ufree_pd(struct ibv_pd * pd)165cdcd52d4SBartosz Sobczak irdma_ufree_pd(struct ibv_pd *pd)
166cdcd52d4SBartosz Sobczak {
167cdcd52d4SBartosz Sobczak struct irdma_upd *iwupd;
168cdcd52d4SBartosz Sobczak int ret;
169cdcd52d4SBartosz Sobczak
170cdcd52d4SBartosz Sobczak iwupd = container_of(pd, struct irdma_upd, ibv_pd);
171cdcd52d4SBartosz Sobczak ret = ibv_cmd_dealloc_pd(pd);
172cdcd52d4SBartosz Sobczak if (ret)
173cdcd52d4SBartosz Sobczak return ret;
174cdcd52d4SBartosz Sobczak
175cdcd52d4SBartosz Sobczak free(iwupd);
176cdcd52d4SBartosz Sobczak
177cdcd52d4SBartosz Sobczak return 0;
178cdcd52d4SBartosz Sobczak }
179cdcd52d4SBartosz Sobczak
180cdcd52d4SBartosz Sobczak /**
181cdcd52d4SBartosz Sobczak * irdma_ureg_mr - register user memory region
182cdcd52d4SBartosz Sobczak * @pd: pd for the mr
183cdcd52d4SBartosz Sobczak * @addr: user address of the memory region
184cdcd52d4SBartosz Sobczak * @length: length of the memory
185cdcd52d4SBartosz Sobczak * @hca_va: hca_va
186cdcd52d4SBartosz Sobczak * @access: access allowed on this mr
187cdcd52d4SBartosz Sobczak */
188cdcd52d4SBartosz Sobczak struct ibv_mr *
irdma_ureg_mr(struct ibv_pd * pd,void * addr,size_t length,int access)189cdcd52d4SBartosz Sobczak irdma_ureg_mr(struct ibv_pd *pd, void *addr, size_t length,
190cdcd52d4SBartosz Sobczak int access)
191cdcd52d4SBartosz Sobczak {
192777e472cSBartosz Sobczak struct verbs_mr *vmr;
193777e472cSBartosz Sobczak struct irdma_ureg_mr cmd = {};
194cdcd52d4SBartosz Sobczak struct ibv_reg_mr_resp resp;
195cdcd52d4SBartosz Sobczak int err;
196cdcd52d4SBartosz Sobczak
197777e472cSBartosz Sobczak vmr = malloc(sizeof(*vmr));
198777e472cSBartosz Sobczak if (!vmr)
199cdcd52d4SBartosz Sobczak return NULL;
200cdcd52d4SBartosz Sobczak
201cdcd52d4SBartosz Sobczak cmd.reg_type = IRDMA_MEMREG_TYPE_MEM;
202cdcd52d4SBartosz Sobczak err = ibv_cmd_reg_mr(pd, addr, length,
203777e472cSBartosz Sobczak (uintptr_t)addr, access, &vmr->ibv_mr, &cmd.ibv_cmd,
204cdcd52d4SBartosz Sobczak sizeof(cmd), &resp, sizeof(resp));
205cdcd52d4SBartosz Sobczak if (err) {
206777e472cSBartosz Sobczak free(vmr);
207cdcd52d4SBartosz Sobczak errno = err;
208cdcd52d4SBartosz Sobczak return NULL;
209cdcd52d4SBartosz Sobczak }
210cdcd52d4SBartosz Sobczak
211777e472cSBartosz Sobczak return &vmr->ibv_mr;
212777e472cSBartosz Sobczak }
213777e472cSBartosz Sobczak
214777e472cSBartosz Sobczak /*
215777e472cSBartosz Sobczak * irdma_urereg_mr - re-register memory region @vmr: mr that was allocated @flags: bit mask to indicate which of the
216777e472cSBartosz Sobczak * attr's of MR modified @pd: pd of the mr @addr: user address of the memory region @length: length of the memory
217777e472cSBartosz Sobczak * @access: access allowed on this mr
218777e472cSBartosz Sobczak */
219777e472cSBartosz Sobczak int
irdma_urereg_mr(struct verbs_mr * vmr,int flags,struct ibv_pd * pd,void * addr,size_t length,int access)220777e472cSBartosz Sobczak irdma_urereg_mr(struct verbs_mr *vmr, int flags, struct ibv_pd *pd,
221777e472cSBartosz Sobczak void *addr, size_t length, int access)
222777e472cSBartosz Sobczak {
223777e472cSBartosz Sobczak struct irdma_urereg_mr cmd = {};
224777e472cSBartosz Sobczak struct ibv_rereg_mr_resp resp;
225777e472cSBartosz Sobczak
226777e472cSBartosz Sobczak cmd.reg_type = IRDMA_MEMREG_TYPE_MEM;
227777e472cSBartosz Sobczak return ibv_cmd_rereg_mr(&vmr->ibv_mr, flags, addr, length, (uintptr_t)addr,
228777e472cSBartosz Sobczak access, pd, &cmd.ibv_cmd, sizeof(cmd), &resp,
229777e472cSBartosz Sobczak sizeof(resp));
230cdcd52d4SBartosz Sobczak }
231cdcd52d4SBartosz Sobczak
232cdcd52d4SBartosz Sobczak /**
233cdcd52d4SBartosz Sobczak * irdma_udereg_mr - re-register memory region
234cdcd52d4SBartosz Sobczak * @mr: mr that was allocated
235cdcd52d4SBartosz Sobczak */
236cdcd52d4SBartosz Sobczak int
irdma_udereg_mr(struct ibv_mr * mr)237cdcd52d4SBartosz Sobczak irdma_udereg_mr(struct ibv_mr *mr)
238cdcd52d4SBartosz Sobczak {
239cdcd52d4SBartosz Sobczak struct verbs_mr *vmr;
240cdcd52d4SBartosz Sobczak int ret;
241cdcd52d4SBartosz Sobczak
242cdcd52d4SBartosz Sobczak vmr = container_of(mr, struct verbs_mr, ibv_mr);
243cdcd52d4SBartosz Sobczak
244cdcd52d4SBartosz Sobczak ret = ibv_cmd_dereg_mr(mr);
245cdcd52d4SBartosz Sobczak if (ret)
246cdcd52d4SBartosz Sobczak return ret;
247cdcd52d4SBartosz Sobczak
248cdcd52d4SBartosz Sobczak return 0;
249cdcd52d4SBartosz Sobczak }
250cdcd52d4SBartosz Sobczak
251cdcd52d4SBartosz Sobczak /**
252cdcd52d4SBartosz Sobczak * irdma_ualloc_mw - allocate memory window
253cdcd52d4SBartosz Sobczak * @pd: protection domain
254cdcd52d4SBartosz Sobczak * @type: memory window type
255cdcd52d4SBartosz Sobczak */
256cdcd52d4SBartosz Sobczak struct ibv_mw *
irdma_ualloc_mw(struct ibv_pd * pd,enum ibv_mw_type type)257cdcd52d4SBartosz Sobczak irdma_ualloc_mw(struct ibv_pd *pd, enum ibv_mw_type type)
258cdcd52d4SBartosz Sobczak {
259cdcd52d4SBartosz Sobczak struct ibv_mw *mw;
260cdcd52d4SBartosz Sobczak struct ibv_alloc_mw cmd;
261cdcd52d4SBartosz Sobczak struct ibv_alloc_mw_resp resp;
262777e472cSBartosz Sobczak int err;
263cdcd52d4SBartosz Sobczak
264cdcd52d4SBartosz Sobczak mw = calloc(1, sizeof(*mw));
265cdcd52d4SBartosz Sobczak if (!mw)
266cdcd52d4SBartosz Sobczak return NULL;
267cdcd52d4SBartosz Sobczak
26801fbb869SBartosz Sobczak err = ibv_cmd_alloc_mw(pd, type, mw, &cmd, sizeof(cmd), &resp,
26901fbb869SBartosz Sobczak sizeof(resp));
27001fbb869SBartosz Sobczak if (err) {
271cdcd52d4SBartosz Sobczak printf("%s: Failed to alloc memory window\n",
272cdcd52d4SBartosz Sobczak __func__);
273cdcd52d4SBartosz Sobczak free(mw);
27401fbb869SBartosz Sobczak errno = err;
275cdcd52d4SBartosz Sobczak return NULL;
276cdcd52d4SBartosz Sobczak }
277cdcd52d4SBartosz Sobczak
278cdcd52d4SBartosz Sobczak return mw;
279cdcd52d4SBartosz Sobczak }
280cdcd52d4SBartosz Sobczak
281cdcd52d4SBartosz Sobczak /**
282cdcd52d4SBartosz Sobczak * irdma_ubind_mw - bind a memory window
283cdcd52d4SBartosz Sobczak * @qp: qp to post WR
284cdcd52d4SBartosz Sobczak * @mw: memory window to bind
285cdcd52d4SBartosz Sobczak * @mw_bind: bind info
286cdcd52d4SBartosz Sobczak */
287cdcd52d4SBartosz Sobczak int
irdma_ubind_mw(struct ibv_qp * qp,struct ibv_mw * mw,struct ibv_mw_bind * mw_bind)288cdcd52d4SBartosz Sobczak irdma_ubind_mw(struct ibv_qp *qp, struct ibv_mw *mw,
289cdcd52d4SBartosz Sobczak struct ibv_mw_bind *mw_bind)
290cdcd52d4SBartosz Sobczak {
291cdcd52d4SBartosz Sobczak struct ibv_mw_bind_info *bind_info = &mw_bind->bind_info;
292cdcd52d4SBartosz Sobczak struct verbs_mr *vmr;
293cdcd52d4SBartosz Sobczak
294cdcd52d4SBartosz Sobczak struct ibv_send_wr wr = {};
295cdcd52d4SBartosz Sobczak struct ibv_send_wr *bad_wr;
296cdcd52d4SBartosz Sobczak int err;
297cdcd52d4SBartosz Sobczak
298cdcd52d4SBartosz Sobczak if (!bind_info->mr && (bind_info->addr || bind_info->length))
299cdcd52d4SBartosz Sobczak return EINVAL;
300cdcd52d4SBartosz Sobczak
301cdcd52d4SBartosz Sobczak if (bind_info->mr) {
302cdcd52d4SBartosz Sobczak vmr = verbs_get_mr(bind_info->mr);
303cdcd52d4SBartosz Sobczak if (vmr->mr_type != IBV_MR_TYPE_MR)
304cdcd52d4SBartosz Sobczak return ENOTSUP;
305cdcd52d4SBartosz Sobczak
306777e472cSBartosz Sobczak if (vmr->access & IBV_ACCESS_ZERO_BASED)
307cdcd52d4SBartosz Sobczak return EINVAL;
308cdcd52d4SBartosz Sobczak
309cdcd52d4SBartosz Sobczak if (mw->pd != bind_info->mr->pd)
310cdcd52d4SBartosz Sobczak return EPERM;
311cdcd52d4SBartosz Sobczak }
312cdcd52d4SBartosz Sobczak
313cdcd52d4SBartosz Sobczak wr.opcode = IBV_WR_BIND_MW;
314cdcd52d4SBartosz Sobczak wr.bind_mw.bind_info = mw_bind->bind_info;
315cdcd52d4SBartosz Sobczak wr.bind_mw.mw = mw;
316cdcd52d4SBartosz Sobczak wr.bind_mw.rkey = ibv_inc_rkey(mw->rkey);
317cdcd52d4SBartosz Sobczak
318cdcd52d4SBartosz Sobczak wr.wr_id = mw_bind->wr_id;
319cdcd52d4SBartosz Sobczak wr.send_flags = mw_bind->send_flags;
320cdcd52d4SBartosz Sobczak
321cdcd52d4SBartosz Sobczak err = irdma_upost_send(qp, &wr, &bad_wr);
322cdcd52d4SBartosz Sobczak if (!err)
323cdcd52d4SBartosz Sobczak mw->rkey = wr.bind_mw.rkey;
324cdcd52d4SBartosz Sobczak
325cdcd52d4SBartosz Sobczak return err;
326cdcd52d4SBartosz Sobczak }
327cdcd52d4SBartosz Sobczak
328cdcd52d4SBartosz Sobczak /**
329cdcd52d4SBartosz Sobczak * irdma_udealloc_mw - deallocate memory window
330cdcd52d4SBartosz Sobczak * @mw: memory window to dealloc
331cdcd52d4SBartosz Sobczak */
332cdcd52d4SBartosz Sobczak int
irdma_udealloc_mw(struct ibv_mw * mw)333cdcd52d4SBartosz Sobczak irdma_udealloc_mw(struct ibv_mw *mw)
334cdcd52d4SBartosz Sobczak {
335cdcd52d4SBartosz Sobczak int ret;
336cdcd52d4SBartosz Sobczak struct ibv_dealloc_mw cmd;
337cdcd52d4SBartosz Sobczak
338cdcd52d4SBartosz Sobczak ret = ibv_cmd_dealloc_mw(mw, &cmd, sizeof(cmd));
339cdcd52d4SBartosz Sobczak if (ret)
340cdcd52d4SBartosz Sobczak return ret;
341cdcd52d4SBartosz Sobczak free(mw);
342cdcd52d4SBartosz Sobczak
343cdcd52d4SBartosz Sobczak return 0;
344cdcd52d4SBartosz Sobczak }
345cdcd52d4SBartosz Sobczak
346cdcd52d4SBartosz Sobczak static void *
irdma_alloc_hw_buf(size_t size)347cdcd52d4SBartosz Sobczak irdma_alloc_hw_buf(size_t size)
348cdcd52d4SBartosz Sobczak {
349cdcd52d4SBartosz Sobczak void *buf;
350cdcd52d4SBartosz Sobczak
351cdcd52d4SBartosz Sobczak buf = memalign(IRDMA_HW_PAGE_SIZE, size);
352cdcd52d4SBartosz Sobczak
353cdcd52d4SBartosz Sobczak if (!buf)
354cdcd52d4SBartosz Sobczak return NULL;
355cdcd52d4SBartosz Sobczak if (ibv_dontfork_range(buf, size)) {
356cdcd52d4SBartosz Sobczak free(buf);
357cdcd52d4SBartosz Sobczak return NULL;
358cdcd52d4SBartosz Sobczak }
359cdcd52d4SBartosz Sobczak
360cdcd52d4SBartosz Sobczak return buf;
361cdcd52d4SBartosz Sobczak }
362cdcd52d4SBartosz Sobczak
363cdcd52d4SBartosz Sobczak static void
irdma_free_hw_buf(void * buf,size_t size)364cdcd52d4SBartosz Sobczak irdma_free_hw_buf(void *buf, size_t size)
365cdcd52d4SBartosz Sobczak {
366cdcd52d4SBartosz Sobczak ibv_dofork_range(buf, size);
367cdcd52d4SBartosz Sobczak free(buf);
368cdcd52d4SBartosz Sobczak }
369cdcd52d4SBartosz Sobczak
370cdcd52d4SBartosz Sobczak /**
371cdcd52d4SBartosz Sobczak * get_cq_size - returns actual cqe needed by HW
372cdcd52d4SBartosz Sobczak * @ncqe: minimum cqes requested by application
373cdcd52d4SBartosz Sobczak * @hw_rev: HW generation
374777e472cSBartosz Sobczak * @cqe_64byte_ena: enable 64byte cqe
375cdcd52d4SBartosz Sobczak */
376cdcd52d4SBartosz Sobczak static inline int
get_cq_size(int ncqe,u8 hw_rev)377*5b5f7d0eSBartosz Sobczak get_cq_size(int ncqe, u8 hw_rev)
378cdcd52d4SBartosz Sobczak {
379cdcd52d4SBartosz Sobczak ncqe++;
380cdcd52d4SBartosz Sobczak
381cdcd52d4SBartosz Sobczak /* Completions with immediate require 1 extra entry */
382*5b5f7d0eSBartosz Sobczak if (hw_rev > IRDMA_GEN_1)
383cdcd52d4SBartosz Sobczak ncqe *= 2;
384cdcd52d4SBartosz Sobczak
385cdcd52d4SBartosz Sobczak if (ncqe < IRDMA_U_MINCQ_SIZE)
386cdcd52d4SBartosz Sobczak ncqe = IRDMA_U_MINCQ_SIZE;
387cdcd52d4SBartosz Sobczak
388cdcd52d4SBartosz Sobczak return ncqe;
389cdcd52d4SBartosz Sobczak }
390cdcd52d4SBartosz Sobczak
get_cq_total_bytes(u32 cq_size)391*5b5f7d0eSBartosz Sobczak static inline size_t get_cq_total_bytes(u32 cq_size) {
392cdcd52d4SBartosz Sobczak return roundup(cq_size * sizeof(struct irdma_cqe), IRDMA_HW_PAGE_SIZE);
393cdcd52d4SBartosz Sobczak }
394cdcd52d4SBartosz Sobczak
395cdcd52d4SBartosz Sobczak /**
396cdcd52d4SBartosz Sobczak * ucreate_cq - irdma util function to create a CQ
397cdcd52d4SBartosz Sobczak * @context: ibv context
398cdcd52d4SBartosz Sobczak * @attr_ex: CQ init attributes
399cdcd52d4SBartosz Sobczak * @ext_cq: flag to create an extendable or normal CQ
400cdcd52d4SBartosz Sobczak */
401cdcd52d4SBartosz Sobczak static struct ibv_cq_ex *
ucreate_cq(struct ibv_context * context,struct ibv_cq_init_attr_ex * attr_ex,bool ext_cq)402cdcd52d4SBartosz Sobczak ucreate_cq(struct ibv_context *context,
403cdcd52d4SBartosz Sobczak struct ibv_cq_init_attr_ex *attr_ex,
404cdcd52d4SBartosz Sobczak bool ext_cq)
405cdcd52d4SBartosz Sobczak {
406cdcd52d4SBartosz Sobczak struct irdma_cq_uk_init_info info = {};
407cdcd52d4SBartosz Sobczak struct irdma_ureg_mr reg_mr_cmd = {};
408cdcd52d4SBartosz Sobczak struct irdma_ucreate_cq_ex cmd = {};
409cdcd52d4SBartosz Sobczak struct irdma_ucreate_cq_ex_resp resp = {};
410cdcd52d4SBartosz Sobczak struct ibv_reg_mr_resp reg_mr_resp = {};
411cdcd52d4SBartosz Sobczak struct irdma_ureg_mr reg_mr_shadow_cmd = {};
412cdcd52d4SBartosz Sobczak struct ibv_reg_mr_resp reg_mr_shadow_resp = {};
413cdcd52d4SBartosz Sobczak struct irdma_uk_attrs *uk_attrs;
414cdcd52d4SBartosz Sobczak struct irdma_uvcontext *iwvctx;
415cdcd52d4SBartosz Sobczak struct irdma_ucq *iwucq;
416cdcd52d4SBartosz Sobczak size_t total_size;
417cdcd52d4SBartosz Sobczak u32 cq_pages;
418cdcd52d4SBartosz Sobczak int ret, ncqe;
419cdcd52d4SBartosz Sobczak u8 hw_rev;
420cdcd52d4SBartosz Sobczak
421cdcd52d4SBartosz Sobczak iwvctx = container_of(context, struct irdma_uvcontext, ibv_ctx);
422cdcd52d4SBartosz Sobczak uk_attrs = &iwvctx->uk_attrs;
423cdcd52d4SBartosz Sobczak hw_rev = uk_attrs->hw_rev;
424cdcd52d4SBartosz Sobczak
425777e472cSBartosz Sobczak if (ext_cq) {
426777e472cSBartosz Sobczak u32 supported_flags = IRDMA_STANDARD_WC_FLAGS_EX;
427777e472cSBartosz Sobczak
428777e472cSBartosz Sobczak if (hw_rev == IRDMA_GEN_1 || attr_ex->wc_flags & ~supported_flags) {
429cdcd52d4SBartosz Sobczak errno = EOPNOTSUPP;
430cdcd52d4SBartosz Sobczak return NULL;
431cdcd52d4SBartosz Sobczak }
432777e472cSBartosz Sobczak }
433cdcd52d4SBartosz Sobczak
434777e472cSBartosz Sobczak if (attr_ex->cqe < uk_attrs->min_hw_cq_size || attr_ex->cqe > uk_attrs->max_hw_cq_size - 1) {
435cdcd52d4SBartosz Sobczak errno = EINVAL;
436cdcd52d4SBartosz Sobczak return NULL;
437cdcd52d4SBartosz Sobczak }
438cdcd52d4SBartosz Sobczak
439cdcd52d4SBartosz Sobczak /* save the cqe requested by application */
440cdcd52d4SBartosz Sobczak ncqe = attr_ex->cqe;
441cdcd52d4SBartosz Sobczak
442cdcd52d4SBartosz Sobczak iwucq = calloc(1, sizeof(*iwucq));
443cdcd52d4SBartosz Sobczak if (!iwucq)
444cdcd52d4SBartosz Sobczak return NULL;
445cdcd52d4SBartosz Sobczak
44601fbb869SBartosz Sobczak ret = pthread_spin_init(&iwucq->lock, PTHREAD_PROCESS_PRIVATE);
44701fbb869SBartosz Sobczak if (ret) {
448cdcd52d4SBartosz Sobczak free(iwucq);
44901fbb869SBartosz Sobczak errno = ret;
450cdcd52d4SBartosz Sobczak return NULL;
451cdcd52d4SBartosz Sobczak }
452cdcd52d4SBartosz Sobczak
453*5b5f7d0eSBartosz Sobczak info.cq_size = get_cq_size(attr_ex->cqe, hw_rev);
454*5b5f7d0eSBartosz Sobczak total_size = get_cq_total_bytes(info.cq_size);
455cdcd52d4SBartosz Sobczak iwucq->comp_vector = attr_ex->comp_vector;
456cdcd52d4SBartosz Sobczak LIST_INIT(&iwucq->resize_list);
457cdcd52d4SBartosz Sobczak cq_pages = total_size >> IRDMA_HW_PAGE_SHIFT;
458cdcd52d4SBartosz Sobczak
459cdcd52d4SBartosz Sobczak if (!(uk_attrs->feature_flags & IRDMA_FEATURE_CQ_RESIZE))
460cdcd52d4SBartosz Sobczak total_size = (cq_pages << IRDMA_HW_PAGE_SHIFT) + IRDMA_DB_SHADOW_AREA_SIZE;
461cdcd52d4SBartosz Sobczak
462cdcd52d4SBartosz Sobczak iwucq->buf_size = total_size;
463cdcd52d4SBartosz Sobczak info.cq_base = irdma_alloc_hw_buf(total_size);
46401fbb869SBartosz Sobczak if (!info.cq_base) {
46501fbb869SBartosz Sobczak ret = ENOMEM;
466cdcd52d4SBartosz Sobczak goto err_cq_base;
46701fbb869SBartosz Sobczak }
468cdcd52d4SBartosz Sobczak
469cdcd52d4SBartosz Sobczak memset(info.cq_base, 0, total_size);
470cdcd52d4SBartosz Sobczak reg_mr_cmd.reg_type = IRDMA_MEMREG_TYPE_CQ;
471cdcd52d4SBartosz Sobczak reg_mr_cmd.cq_pages = cq_pages;
472cdcd52d4SBartosz Sobczak
473cdcd52d4SBartosz Sobczak ret = ibv_cmd_reg_mr(&iwvctx->iwupd->ibv_pd, info.cq_base,
474cdcd52d4SBartosz Sobczak total_size, (uintptr_t)info.cq_base,
475cdcd52d4SBartosz Sobczak IBV_ACCESS_LOCAL_WRITE, &iwucq->vmr.ibv_mr,
476cdcd52d4SBartosz Sobczak ®_mr_cmd.ibv_cmd, sizeof(reg_mr_cmd),
477cdcd52d4SBartosz Sobczak ®_mr_resp, sizeof(reg_mr_resp));
47801fbb869SBartosz Sobczak if (ret)
479cdcd52d4SBartosz Sobczak goto err_dereg_mr;
480cdcd52d4SBartosz Sobczak
481cdcd52d4SBartosz Sobczak iwucq->vmr.ibv_mr.pd = &iwvctx->iwupd->ibv_pd;
482cdcd52d4SBartosz Sobczak
483cdcd52d4SBartosz Sobczak if (uk_attrs->feature_flags & IRDMA_FEATURE_CQ_RESIZE) {
484cdcd52d4SBartosz Sobczak info.shadow_area = irdma_alloc_hw_buf(IRDMA_DB_SHADOW_AREA_SIZE);
48501fbb869SBartosz Sobczak if (!info.shadow_area) {
48601fbb869SBartosz Sobczak ret = ENOMEM;
487777e472cSBartosz Sobczak goto err_alloc_shadow;
48801fbb869SBartosz Sobczak }
489cdcd52d4SBartosz Sobczak
490cdcd52d4SBartosz Sobczak memset(info.shadow_area, 0, IRDMA_DB_SHADOW_AREA_SIZE);
491cdcd52d4SBartosz Sobczak reg_mr_shadow_cmd.reg_type = IRDMA_MEMREG_TYPE_CQ;
492cdcd52d4SBartosz Sobczak reg_mr_shadow_cmd.cq_pages = 1;
493cdcd52d4SBartosz Sobczak
494cdcd52d4SBartosz Sobczak ret = ibv_cmd_reg_mr(&iwvctx->iwupd->ibv_pd, info.shadow_area,
495cdcd52d4SBartosz Sobczak IRDMA_DB_SHADOW_AREA_SIZE, (uintptr_t)info.shadow_area,
496cdcd52d4SBartosz Sobczak IBV_ACCESS_LOCAL_WRITE, &iwucq->vmr_shadow_area.ibv_mr,
497cdcd52d4SBartosz Sobczak ®_mr_shadow_cmd.ibv_cmd, sizeof(reg_mr_shadow_cmd),
498cdcd52d4SBartosz Sobczak ®_mr_shadow_resp, sizeof(reg_mr_shadow_resp));
499cdcd52d4SBartosz Sobczak if (ret) {
500777e472cSBartosz Sobczak irdma_free_hw_buf(info.shadow_area, IRDMA_DB_SHADOW_AREA_SIZE);
501777e472cSBartosz Sobczak goto err_alloc_shadow;
502cdcd52d4SBartosz Sobczak }
503cdcd52d4SBartosz Sobczak
504cdcd52d4SBartosz Sobczak iwucq->vmr_shadow_area.ibv_mr.pd = &iwvctx->iwupd->ibv_pd;
505cdcd52d4SBartosz Sobczak
506cdcd52d4SBartosz Sobczak } else {
507cdcd52d4SBartosz Sobczak info.shadow_area = (__le64 *) ((u8 *)info.cq_base + (cq_pages << IRDMA_HW_PAGE_SHIFT));
508cdcd52d4SBartosz Sobczak }
509cdcd52d4SBartosz Sobczak
510cdcd52d4SBartosz Sobczak attr_ex->cqe = info.cq_size;
511cdcd52d4SBartosz Sobczak cmd.user_cq_buf = (__u64) ((uintptr_t)info.cq_base);
512cdcd52d4SBartosz Sobczak cmd.user_shadow_area = (__u64) ((uintptr_t)info.shadow_area);
513cdcd52d4SBartosz Sobczak
514cdcd52d4SBartosz Sobczak ret = ibv_cmd_create_cq_ex(context, attr_ex, &iwucq->verbs_cq.cq_ex,
515cdcd52d4SBartosz Sobczak &cmd.ibv_cmd, sizeof(cmd.ibv_cmd), sizeof(cmd), &resp.ibv_resp,
516cdcd52d4SBartosz Sobczak sizeof(resp.ibv_resp), sizeof(resp));
517777e472cSBartosz Sobczak attr_ex->cqe = ncqe;
51801fbb869SBartosz Sobczak if (ret)
519777e472cSBartosz Sobczak goto err_create_cq;
520cdcd52d4SBartosz Sobczak
521cdcd52d4SBartosz Sobczak if (ext_cq)
522cdcd52d4SBartosz Sobczak irdma_ibvcq_ex_fill_priv_funcs(iwucq, attr_ex);
523cdcd52d4SBartosz Sobczak info.cq_id = resp.cq_id;
524777e472cSBartosz Sobczak /* Do not report the CQE's reserved for immediate and burned by HW */
525cdcd52d4SBartosz Sobczak iwucq->verbs_cq.cq.cqe = ncqe;
526cdcd52d4SBartosz Sobczak info.cqe_alloc_db = (u32 *)((u8 *)iwvctx->db + IRDMA_DB_CQ_OFFSET);
527cdcd52d4SBartosz Sobczak irdma_uk_cq_init(&iwucq->cq, &info);
528cdcd52d4SBartosz Sobczak return &iwucq->verbs_cq.cq_ex;
529cdcd52d4SBartosz Sobczak
530777e472cSBartosz Sobczak err_create_cq:
531cdcd52d4SBartosz Sobczak if (iwucq->vmr_shadow_area.ibv_mr.handle) {
532cdcd52d4SBartosz Sobczak ibv_cmd_dereg_mr(&iwucq->vmr_shadow_area.ibv_mr);
533777e472cSBartosz Sobczak irdma_free_hw_buf(info.shadow_area, IRDMA_DB_SHADOW_AREA_SIZE);
534cdcd52d4SBartosz Sobczak }
535777e472cSBartosz Sobczak err_alloc_shadow:
536777e472cSBartosz Sobczak ibv_cmd_dereg_mr(&iwucq->vmr.ibv_mr);
537cdcd52d4SBartosz Sobczak err_dereg_mr:
538cdcd52d4SBartosz Sobczak irdma_free_hw_buf(info.cq_base, total_size);
539cdcd52d4SBartosz Sobczak err_cq_base:
540cdcd52d4SBartosz Sobczak printf("%s: failed to initialize CQ\n", __func__);
541cdcd52d4SBartosz Sobczak pthread_spin_destroy(&iwucq->lock);
542cdcd52d4SBartosz Sobczak
543cdcd52d4SBartosz Sobczak free(iwucq);
544cdcd52d4SBartosz Sobczak
54501fbb869SBartosz Sobczak errno = ret;
546cdcd52d4SBartosz Sobczak return NULL;
547cdcd52d4SBartosz Sobczak }
548cdcd52d4SBartosz Sobczak
549cdcd52d4SBartosz Sobczak struct ibv_cq *
irdma_ucreate_cq(struct ibv_context * context,int cqe,struct ibv_comp_channel * channel,int comp_vector)550cdcd52d4SBartosz Sobczak irdma_ucreate_cq(struct ibv_context *context, int cqe,
551cdcd52d4SBartosz Sobczak struct ibv_comp_channel *channel,
552cdcd52d4SBartosz Sobczak int comp_vector)
553cdcd52d4SBartosz Sobczak {
554cdcd52d4SBartosz Sobczak struct ibv_cq_init_attr_ex attr_ex = {
555cdcd52d4SBartosz Sobczak .cqe = cqe,
556cdcd52d4SBartosz Sobczak .channel = channel,
557cdcd52d4SBartosz Sobczak .comp_vector = comp_vector,
558cdcd52d4SBartosz Sobczak };
559cdcd52d4SBartosz Sobczak struct ibv_cq_ex *ibvcq_ex;
560cdcd52d4SBartosz Sobczak
561cdcd52d4SBartosz Sobczak ibvcq_ex = ucreate_cq(context, &attr_ex, false);
562cdcd52d4SBartosz Sobczak
563cdcd52d4SBartosz Sobczak return ibvcq_ex ? ibv_cq_ex_to_cq(ibvcq_ex) : NULL;
564cdcd52d4SBartosz Sobczak }
565cdcd52d4SBartosz Sobczak
566cdcd52d4SBartosz Sobczak struct ibv_cq_ex *
irdma_ucreate_cq_ex(struct ibv_context * context,struct ibv_cq_init_attr_ex * attr_ex)567cdcd52d4SBartosz Sobczak irdma_ucreate_cq_ex(struct ibv_context *context,
568cdcd52d4SBartosz Sobczak struct ibv_cq_init_attr_ex *attr_ex)
569cdcd52d4SBartosz Sobczak {
570cdcd52d4SBartosz Sobczak return ucreate_cq(context, attr_ex, true);
571cdcd52d4SBartosz Sobczak }
572cdcd52d4SBartosz Sobczak
573cdcd52d4SBartosz Sobczak /**
574cdcd52d4SBartosz Sobczak * irdma_free_cq_buf - free memory for cq buffer
575cdcd52d4SBartosz Sobczak * @cq_buf: cq buf to free
576cdcd52d4SBartosz Sobczak */
577cdcd52d4SBartosz Sobczak static void
irdma_free_cq_buf(struct irdma_cq_buf * cq_buf)578cdcd52d4SBartosz Sobczak irdma_free_cq_buf(struct irdma_cq_buf *cq_buf)
579cdcd52d4SBartosz Sobczak {
580cdcd52d4SBartosz Sobczak ibv_cmd_dereg_mr(&cq_buf->vmr.ibv_mr);
581*5b5f7d0eSBartosz Sobczak irdma_free_hw_buf(cq_buf->cq.cq_base, get_cq_total_bytes(cq_buf->cq.cq_size));
582cdcd52d4SBartosz Sobczak free(cq_buf);
583cdcd52d4SBartosz Sobczak }
584cdcd52d4SBartosz Sobczak
585cdcd52d4SBartosz Sobczak /**
586cdcd52d4SBartosz Sobczak * irdma_process_resize_list - process the cq list to remove buffers
587cdcd52d4SBartosz Sobczak * @iwucq: cq which owns the list
588cdcd52d4SBartosz Sobczak * @lcqe_buf: cq buf where the last cqe is found
589cdcd52d4SBartosz Sobczak */
590cdcd52d4SBartosz Sobczak static int
irdma_process_resize_list(struct irdma_ucq * iwucq,struct irdma_cq_buf * lcqe_buf)591cdcd52d4SBartosz Sobczak irdma_process_resize_list(struct irdma_ucq *iwucq,
592cdcd52d4SBartosz Sobczak struct irdma_cq_buf *lcqe_buf)
593cdcd52d4SBartosz Sobczak {
594cdcd52d4SBartosz Sobczak struct irdma_cq_buf *cq_buf, *next;
595cdcd52d4SBartosz Sobczak int cq_cnt = 0;
596cdcd52d4SBartosz Sobczak
597cdcd52d4SBartosz Sobczak LIST_FOREACH_SAFE(cq_buf, &iwucq->resize_list, list, next) {
598cdcd52d4SBartosz Sobczak if (cq_buf == lcqe_buf)
599cdcd52d4SBartosz Sobczak return cq_cnt;
600cdcd52d4SBartosz Sobczak
601cdcd52d4SBartosz Sobczak LIST_REMOVE(cq_buf, list);
602cdcd52d4SBartosz Sobczak irdma_free_cq_buf(cq_buf);
603cdcd52d4SBartosz Sobczak cq_cnt++;
604cdcd52d4SBartosz Sobczak }
605cdcd52d4SBartosz Sobczak
606cdcd52d4SBartosz Sobczak return cq_cnt;
607cdcd52d4SBartosz Sobczak }
608cdcd52d4SBartosz Sobczak
609cdcd52d4SBartosz Sobczak /**
610cdcd52d4SBartosz Sobczak * irdma_udestroy_cq - destroys cq
611cdcd52d4SBartosz Sobczak * @cq: ptr to cq to be destroyed
612cdcd52d4SBartosz Sobczak */
613cdcd52d4SBartosz Sobczak int
irdma_udestroy_cq(struct ibv_cq * cq)614cdcd52d4SBartosz Sobczak irdma_udestroy_cq(struct ibv_cq *cq)
615cdcd52d4SBartosz Sobczak {
616cdcd52d4SBartosz Sobczak struct irdma_uk_attrs *uk_attrs;
617cdcd52d4SBartosz Sobczak struct irdma_uvcontext *iwvctx;
618cdcd52d4SBartosz Sobczak struct irdma_ucq *iwucq;
619cdcd52d4SBartosz Sobczak int ret;
620cdcd52d4SBartosz Sobczak
621cdcd52d4SBartosz Sobczak iwucq = container_of(cq, struct irdma_ucq, verbs_cq.cq);
622cdcd52d4SBartosz Sobczak iwvctx = container_of(cq->context, struct irdma_uvcontext, ibv_ctx);
623cdcd52d4SBartosz Sobczak uk_attrs = &iwvctx->uk_attrs;
624cdcd52d4SBartosz Sobczak
625cdcd52d4SBartosz Sobczak ret = pthread_spin_destroy(&iwucq->lock);
626cdcd52d4SBartosz Sobczak if (ret)
627cdcd52d4SBartosz Sobczak goto err;
628cdcd52d4SBartosz Sobczak
629cdcd52d4SBartosz Sobczak irdma_process_resize_list(iwucq, NULL);
630cdcd52d4SBartosz Sobczak ret = ibv_cmd_destroy_cq(cq);
631cdcd52d4SBartosz Sobczak if (ret)
632cdcd52d4SBartosz Sobczak goto err;
633cdcd52d4SBartosz Sobczak
634cdcd52d4SBartosz Sobczak ibv_cmd_dereg_mr(&iwucq->vmr.ibv_mr);
635cdcd52d4SBartosz Sobczak irdma_free_hw_buf(iwucq->cq.cq_base, iwucq->buf_size);
636cdcd52d4SBartosz Sobczak
637cdcd52d4SBartosz Sobczak if (uk_attrs->feature_flags & IRDMA_FEATURE_CQ_RESIZE) {
638cdcd52d4SBartosz Sobczak ibv_cmd_dereg_mr(&iwucq->vmr_shadow_area.ibv_mr);
639cdcd52d4SBartosz Sobczak irdma_free_hw_buf(iwucq->cq.shadow_area, IRDMA_DB_SHADOW_AREA_SIZE);
640cdcd52d4SBartosz Sobczak }
641cdcd52d4SBartosz Sobczak free(iwucq);
642cdcd52d4SBartosz Sobczak return 0;
643cdcd52d4SBartosz Sobczak
644cdcd52d4SBartosz Sobczak err:
645cdcd52d4SBartosz Sobczak return ret;
646cdcd52d4SBartosz Sobczak }
647cdcd52d4SBartosz Sobczak
648cdcd52d4SBartosz Sobczak static enum ibv_wc_status
irdma_flush_err_to_ib_wc_status(enum irdma_flush_opcode opcode)649cdcd52d4SBartosz Sobczak irdma_flush_err_to_ib_wc_status(enum irdma_flush_opcode opcode)
650cdcd52d4SBartosz Sobczak {
651cdcd52d4SBartosz Sobczak switch (opcode) {
652cdcd52d4SBartosz Sobczak case FLUSH_PROT_ERR:
653cdcd52d4SBartosz Sobczak return IBV_WC_LOC_PROT_ERR;
654cdcd52d4SBartosz Sobczak case FLUSH_REM_ACCESS_ERR:
655cdcd52d4SBartosz Sobczak return IBV_WC_REM_ACCESS_ERR;
656cdcd52d4SBartosz Sobczak case FLUSH_LOC_QP_OP_ERR:
657cdcd52d4SBartosz Sobczak return IBV_WC_LOC_QP_OP_ERR;
658cdcd52d4SBartosz Sobczak case FLUSH_REM_OP_ERR:
659cdcd52d4SBartosz Sobczak return IBV_WC_REM_OP_ERR;
660cdcd52d4SBartosz Sobczak case FLUSH_LOC_LEN_ERR:
661cdcd52d4SBartosz Sobczak return IBV_WC_LOC_LEN_ERR;
662cdcd52d4SBartosz Sobczak case FLUSH_GENERAL_ERR:
663cdcd52d4SBartosz Sobczak return IBV_WC_WR_FLUSH_ERR;
664cdcd52d4SBartosz Sobczak case FLUSH_MW_BIND_ERR:
665cdcd52d4SBartosz Sobczak return IBV_WC_MW_BIND_ERR;
666cdcd52d4SBartosz Sobczak case FLUSH_REM_INV_REQ_ERR:
667cdcd52d4SBartosz Sobczak return IBV_WC_REM_INV_REQ_ERR;
668cdcd52d4SBartosz Sobczak case FLUSH_RETRY_EXC_ERR:
669cdcd52d4SBartosz Sobczak return IBV_WC_RETRY_EXC_ERR;
670cdcd52d4SBartosz Sobczak case FLUSH_FATAL_ERR:
671cdcd52d4SBartosz Sobczak default:
672cdcd52d4SBartosz Sobczak return IBV_WC_FATAL_ERR;
673cdcd52d4SBartosz Sobczak }
674cdcd52d4SBartosz Sobczak }
675cdcd52d4SBartosz Sobczak
676777e472cSBartosz Sobczak static inline void
set_ib_wc_op_sq(struct irdma_cq_poll_info * cur_cqe,struct ibv_wc * entry)677777e472cSBartosz Sobczak set_ib_wc_op_sq(struct irdma_cq_poll_info *cur_cqe, struct ibv_wc *entry)
678777e472cSBartosz Sobczak {
679777e472cSBartosz Sobczak switch (cur_cqe->op_type) {
680777e472cSBartosz Sobczak case IRDMA_OP_TYPE_RDMA_WRITE:
681777e472cSBartosz Sobczak case IRDMA_OP_TYPE_RDMA_WRITE_SOL:
682777e472cSBartosz Sobczak entry->opcode = IBV_WC_RDMA_WRITE;
683777e472cSBartosz Sobczak break;
684777e472cSBartosz Sobczak case IRDMA_OP_TYPE_RDMA_READ:
685777e472cSBartosz Sobczak entry->opcode = IBV_WC_RDMA_READ;
686777e472cSBartosz Sobczak break;
687777e472cSBartosz Sobczak case IRDMA_OP_TYPE_SEND_SOL:
688777e472cSBartosz Sobczak case IRDMA_OP_TYPE_SEND_SOL_INV:
689777e472cSBartosz Sobczak case IRDMA_OP_TYPE_SEND_INV:
690777e472cSBartosz Sobczak case IRDMA_OP_TYPE_SEND:
691777e472cSBartosz Sobczak entry->opcode = IBV_WC_SEND;
692777e472cSBartosz Sobczak break;
693777e472cSBartosz Sobczak case IRDMA_OP_TYPE_BIND_MW:
694777e472cSBartosz Sobczak entry->opcode = IBV_WC_BIND_MW;
695777e472cSBartosz Sobczak break;
696777e472cSBartosz Sobczak case IRDMA_OP_TYPE_INV_STAG:
697777e472cSBartosz Sobczak entry->opcode = IBV_WC_LOCAL_INV;
698777e472cSBartosz Sobczak break;
699777e472cSBartosz Sobczak default:
700777e472cSBartosz Sobczak entry->status = IBV_WC_GENERAL_ERR;
701777e472cSBartosz Sobczak printf("%s: Invalid opcode = %d in CQE\n",
702777e472cSBartosz Sobczak __func__, cur_cqe->op_type);
703777e472cSBartosz Sobczak }
704777e472cSBartosz Sobczak }
705777e472cSBartosz Sobczak
706777e472cSBartosz Sobczak static inline void
set_ib_wc_op_rq(struct irdma_cq_poll_info * cur_cqe,struct ibv_wc * entry,bool send_imm_support)707777e472cSBartosz Sobczak set_ib_wc_op_rq(struct irdma_cq_poll_info *cur_cqe,
708777e472cSBartosz Sobczak struct ibv_wc *entry, bool send_imm_support)
709777e472cSBartosz Sobczak {
710777e472cSBartosz Sobczak if (!send_imm_support) {
711777e472cSBartosz Sobczak entry->opcode = cur_cqe->imm_valid ? IBV_WC_RECV_RDMA_WITH_IMM :
712777e472cSBartosz Sobczak IBV_WC_RECV;
713777e472cSBartosz Sobczak return;
714777e472cSBartosz Sobczak }
715777e472cSBartosz Sobczak switch (cur_cqe->op_type) {
716777e472cSBartosz Sobczak case IBV_OPCODE_RDMA_WRITE_ONLY_WITH_IMMEDIATE:
717777e472cSBartosz Sobczak case IBV_OPCODE_RDMA_WRITE_LAST_WITH_IMMEDIATE:
718777e472cSBartosz Sobczak entry->opcode = IBV_WC_RECV_RDMA_WITH_IMM;
719777e472cSBartosz Sobczak break;
720777e472cSBartosz Sobczak default:
721777e472cSBartosz Sobczak entry->opcode = IBV_WC_RECV;
722777e472cSBartosz Sobczak }
723777e472cSBartosz Sobczak }
724777e472cSBartosz Sobczak
725cdcd52d4SBartosz Sobczak /**
726cdcd52d4SBartosz Sobczak * irdma_process_cqe_ext - process current cqe for extended CQ
727cdcd52d4SBartosz Sobczak * @cur_cqe - current cqe info
728cdcd52d4SBartosz Sobczak */
729cdcd52d4SBartosz Sobczak static void
irdma_process_cqe_ext(struct irdma_cq_poll_info * cur_cqe)730cdcd52d4SBartosz Sobczak irdma_process_cqe_ext(struct irdma_cq_poll_info *cur_cqe)
731cdcd52d4SBartosz Sobczak {
732cdcd52d4SBartosz Sobczak struct irdma_ucq *iwucq = container_of(cur_cqe, struct irdma_ucq, cur_cqe);
733cdcd52d4SBartosz Sobczak struct ibv_cq_ex *ibvcq_ex = &iwucq->verbs_cq.cq_ex;
734cdcd52d4SBartosz Sobczak
735cdcd52d4SBartosz Sobczak ibvcq_ex->wr_id = cur_cqe->wr_id;
736cdcd52d4SBartosz Sobczak if (cur_cqe->error)
737cdcd52d4SBartosz Sobczak ibvcq_ex->status = (cur_cqe->comp_status == IRDMA_COMPL_STATUS_FLUSHED) ?
738cdcd52d4SBartosz Sobczak irdma_flush_err_to_ib_wc_status(cur_cqe->minor_err) : IBV_WC_GENERAL_ERR;
739cdcd52d4SBartosz Sobczak else
740cdcd52d4SBartosz Sobczak ibvcq_ex->status = IBV_WC_SUCCESS;
741cdcd52d4SBartosz Sobczak }
742cdcd52d4SBartosz Sobczak
743cdcd52d4SBartosz Sobczak /**
744cdcd52d4SBartosz Sobczak * irdma_process_cqe - process current cqe info
745cdcd52d4SBartosz Sobczak * @entry - ibv_wc object to fill in for non-extended CQ
746cdcd52d4SBartosz Sobczak * @cur_cqe - current cqe info
747cdcd52d4SBartosz Sobczak */
748cdcd52d4SBartosz Sobczak static void
irdma_process_cqe(struct ibv_wc * entry,struct irdma_cq_poll_info * cur_cqe)749cdcd52d4SBartosz Sobczak irdma_process_cqe(struct ibv_wc *entry, struct irdma_cq_poll_info *cur_cqe)
750cdcd52d4SBartosz Sobczak {
751cdcd52d4SBartosz Sobczak struct irdma_qp_uk *qp;
752cdcd52d4SBartosz Sobczak struct ibv_qp *ib_qp;
753cdcd52d4SBartosz Sobczak
754cdcd52d4SBartosz Sobczak entry->wc_flags = 0;
755cdcd52d4SBartosz Sobczak entry->wr_id = cur_cqe->wr_id;
756cdcd52d4SBartosz Sobczak entry->qp_num = cur_cqe->qp_id;
757cdcd52d4SBartosz Sobczak qp = cur_cqe->qp_handle;
758cdcd52d4SBartosz Sobczak ib_qp = qp->back_qp;
759cdcd52d4SBartosz Sobczak
760cdcd52d4SBartosz Sobczak if (cur_cqe->error) {
761cdcd52d4SBartosz Sobczak entry->status = (cur_cqe->comp_status == IRDMA_COMPL_STATUS_FLUSHED) ?
762cdcd52d4SBartosz Sobczak irdma_flush_err_to_ib_wc_status(cur_cqe->minor_err) : IBV_WC_GENERAL_ERR;
763cdcd52d4SBartosz Sobczak entry->vendor_err = cur_cqe->major_err << 16 |
764cdcd52d4SBartosz Sobczak cur_cqe->minor_err;
765cdcd52d4SBartosz Sobczak } else {
766cdcd52d4SBartosz Sobczak entry->status = IBV_WC_SUCCESS;
767cdcd52d4SBartosz Sobczak }
768cdcd52d4SBartosz Sobczak
769cdcd52d4SBartosz Sobczak if (cur_cqe->imm_valid) {
770cdcd52d4SBartosz Sobczak entry->imm_data = htonl(cur_cqe->imm_data);
771cdcd52d4SBartosz Sobczak entry->wc_flags |= IBV_WC_WITH_IMM;
772cdcd52d4SBartosz Sobczak }
773cdcd52d4SBartosz Sobczak
774777e472cSBartosz Sobczak if (cur_cqe->q_type == IRDMA_CQE_QTYPE_SQ) {
775777e472cSBartosz Sobczak set_ib_wc_op_sq(cur_cqe, entry);
776777e472cSBartosz Sobczak } else {
777777e472cSBartosz Sobczak set_ib_wc_op_rq(cur_cqe, entry,
778777e472cSBartosz Sobczak qp->qp_caps & IRDMA_SEND_WITH_IMM ?
779777e472cSBartosz Sobczak true : false);
780cdcd52d4SBartosz Sobczak if (ib_qp->qp_type != IBV_QPT_UD &&
781cdcd52d4SBartosz Sobczak cur_cqe->stag_invalid_set) {
782cdcd52d4SBartosz Sobczak entry->invalidated_rkey = cur_cqe->inv_stag;
783cdcd52d4SBartosz Sobczak entry->wc_flags |= IBV_WC_WITH_INV;
784cdcd52d4SBartosz Sobczak }
785cdcd52d4SBartosz Sobczak }
786cdcd52d4SBartosz Sobczak
787cdcd52d4SBartosz Sobczak if (ib_qp->qp_type == IBV_QPT_UD) {
788cdcd52d4SBartosz Sobczak entry->src_qp = cur_cqe->ud_src_qpn;
789cdcd52d4SBartosz Sobczak entry->wc_flags |= IBV_WC_GRH;
790cdcd52d4SBartosz Sobczak } else {
791cdcd52d4SBartosz Sobczak entry->src_qp = cur_cqe->qp_id;
792cdcd52d4SBartosz Sobczak }
793cdcd52d4SBartosz Sobczak entry->byte_len = cur_cqe->bytes_xfered;
794cdcd52d4SBartosz Sobczak }
795cdcd52d4SBartosz Sobczak
796cdcd52d4SBartosz Sobczak /**
797cdcd52d4SBartosz Sobczak * irdma_poll_one - poll one entry of the CQ
798cdcd52d4SBartosz Sobczak * @ukcq: ukcq to poll
799cdcd52d4SBartosz Sobczak * @cur_cqe: current CQE info to be filled in
800cdcd52d4SBartosz Sobczak * @entry: ibv_wc object to be filled for non-extended CQ or NULL for extended CQ
801cdcd52d4SBartosz Sobczak *
802cdcd52d4SBartosz Sobczak * Returns the internal irdma device error code or 0 on success
803cdcd52d4SBartosz Sobczak */
804cdcd52d4SBartosz Sobczak static int
irdma_poll_one(struct irdma_cq_uk * ukcq,struct irdma_cq_poll_info * cur_cqe,struct ibv_wc * entry)805cdcd52d4SBartosz Sobczak irdma_poll_one(struct irdma_cq_uk *ukcq, struct irdma_cq_poll_info *cur_cqe,
806cdcd52d4SBartosz Sobczak struct ibv_wc *entry)
807cdcd52d4SBartosz Sobczak {
808cdcd52d4SBartosz Sobczak int ret = irdma_uk_cq_poll_cmpl(ukcq, cur_cqe);
809cdcd52d4SBartosz Sobczak
810cdcd52d4SBartosz Sobczak if (ret)
811cdcd52d4SBartosz Sobczak return ret;
812cdcd52d4SBartosz Sobczak
813cdcd52d4SBartosz Sobczak if (!entry)
814cdcd52d4SBartosz Sobczak irdma_process_cqe_ext(cur_cqe);
815cdcd52d4SBartosz Sobczak else
816cdcd52d4SBartosz Sobczak irdma_process_cqe(entry, cur_cqe);
817cdcd52d4SBartosz Sobczak
818cdcd52d4SBartosz Sobczak return 0;
819cdcd52d4SBartosz Sobczak }
820cdcd52d4SBartosz Sobczak
821cdcd52d4SBartosz Sobczak /**
822cdcd52d4SBartosz Sobczak * __irdma_upoll_cq - irdma util function to poll device CQ
823cdcd52d4SBartosz Sobczak * @iwucq: irdma cq to poll
824cdcd52d4SBartosz Sobczak * @num_entries: max cq entries to poll
825cdcd52d4SBartosz Sobczak * @entry: pointer to array of ibv_wc objects to be filled in for each completion or NULL if ext CQ
826cdcd52d4SBartosz Sobczak *
827cdcd52d4SBartosz Sobczak * Returns non-negative value equal to the number of completions
828cdcd52d4SBartosz Sobczak * found. On failure, EINVAL
829cdcd52d4SBartosz Sobczak */
830cdcd52d4SBartosz Sobczak static int
__irdma_upoll_cq(struct irdma_ucq * iwucq,int num_entries,struct ibv_wc * entry)831cdcd52d4SBartosz Sobczak __irdma_upoll_cq(struct irdma_ucq *iwucq, int num_entries,
832cdcd52d4SBartosz Sobczak struct ibv_wc *entry)
833cdcd52d4SBartosz Sobczak {
834cdcd52d4SBartosz Sobczak struct irdma_cq_buf *cq_buf, *next;
835cdcd52d4SBartosz Sobczak struct irdma_cq_buf *last_buf = NULL;
836cdcd52d4SBartosz Sobczak struct irdma_cq_poll_info *cur_cqe = &iwucq->cur_cqe;
837cdcd52d4SBartosz Sobczak bool cq_new_cqe = false;
838cdcd52d4SBartosz Sobczak int resized_bufs = 0;
839cdcd52d4SBartosz Sobczak int npolled = 0;
840cdcd52d4SBartosz Sobczak int ret;
841cdcd52d4SBartosz Sobczak
842cdcd52d4SBartosz Sobczak /* go through the list of previously resized CQ buffers */
843cdcd52d4SBartosz Sobczak LIST_FOREACH_SAFE(cq_buf, &iwucq->resize_list, list, next) {
844cdcd52d4SBartosz Sobczak while (npolled < num_entries) {
845cdcd52d4SBartosz Sobczak ret = irdma_poll_one(&cq_buf->cq, cur_cqe,
846cdcd52d4SBartosz Sobczak entry ? entry + npolled : NULL);
847cdcd52d4SBartosz Sobczak if (!ret) {
848cdcd52d4SBartosz Sobczak ++npolled;
849cdcd52d4SBartosz Sobczak cq_new_cqe = true;
850cdcd52d4SBartosz Sobczak continue;
851cdcd52d4SBartosz Sobczak }
852cdcd52d4SBartosz Sobczak if (ret == ENOENT)
853cdcd52d4SBartosz Sobczak break;
854cdcd52d4SBartosz Sobczak /* QP using the CQ is destroyed. Skip reporting this CQE */
855cdcd52d4SBartosz Sobczak if (ret == EFAULT) {
856cdcd52d4SBartosz Sobczak cq_new_cqe = true;
857cdcd52d4SBartosz Sobczak continue;
858cdcd52d4SBartosz Sobczak }
859cdcd52d4SBartosz Sobczak goto error;
860cdcd52d4SBartosz Sobczak }
861cdcd52d4SBartosz Sobczak
862cdcd52d4SBartosz Sobczak /* save the resized CQ buffer which received the last cqe */
863cdcd52d4SBartosz Sobczak if (cq_new_cqe)
864cdcd52d4SBartosz Sobczak last_buf = cq_buf;
865cdcd52d4SBartosz Sobczak cq_new_cqe = false;
866cdcd52d4SBartosz Sobczak }
867cdcd52d4SBartosz Sobczak
868cdcd52d4SBartosz Sobczak /* check the current CQ for new cqes */
869cdcd52d4SBartosz Sobczak while (npolled < num_entries) {
870cdcd52d4SBartosz Sobczak ret = irdma_poll_one(&iwucq->cq, cur_cqe,
871cdcd52d4SBartosz Sobczak entry ? entry + npolled : NULL);
872cdcd52d4SBartosz Sobczak if (!ret) {
873cdcd52d4SBartosz Sobczak ++npolled;
874cdcd52d4SBartosz Sobczak cq_new_cqe = true;
875cdcd52d4SBartosz Sobczak continue;
876cdcd52d4SBartosz Sobczak }
877cdcd52d4SBartosz Sobczak if (ret == ENOENT)
878cdcd52d4SBartosz Sobczak break;
879cdcd52d4SBartosz Sobczak /* QP using the CQ is destroyed. Skip reporting this CQE */
880cdcd52d4SBartosz Sobczak if (ret == EFAULT) {
881cdcd52d4SBartosz Sobczak cq_new_cqe = true;
882cdcd52d4SBartosz Sobczak continue;
883cdcd52d4SBartosz Sobczak }
884cdcd52d4SBartosz Sobczak goto error;
885cdcd52d4SBartosz Sobczak }
886cdcd52d4SBartosz Sobczak
887cdcd52d4SBartosz Sobczak if (cq_new_cqe)
888cdcd52d4SBartosz Sobczak /* all previous CQ resizes are complete */
889cdcd52d4SBartosz Sobczak resized_bufs = irdma_process_resize_list(iwucq, NULL);
890cdcd52d4SBartosz Sobczak else if (last_buf)
891cdcd52d4SBartosz Sobczak /* only CQ resizes up to the last_buf are complete */
892cdcd52d4SBartosz Sobczak resized_bufs = irdma_process_resize_list(iwucq, last_buf);
893cdcd52d4SBartosz Sobczak if (resized_bufs)
894cdcd52d4SBartosz Sobczak /* report to the HW the number of complete CQ resizes */
895cdcd52d4SBartosz Sobczak irdma_uk_cq_set_resized_cnt(&iwucq->cq, resized_bufs);
896cdcd52d4SBartosz Sobczak
897cdcd52d4SBartosz Sobczak return npolled;
898cdcd52d4SBartosz Sobczak
899cdcd52d4SBartosz Sobczak error:
900cdcd52d4SBartosz Sobczak printf("%s: Error polling CQ, irdma_err: %d\n", __func__, ret);
901cdcd52d4SBartosz Sobczak
902cdcd52d4SBartosz Sobczak return EINVAL;
903cdcd52d4SBartosz Sobczak }
904cdcd52d4SBartosz Sobczak
905cdcd52d4SBartosz Sobczak /**
906cdcd52d4SBartosz Sobczak * irdma_upoll_cq - verb API callback to poll device CQ
907cdcd52d4SBartosz Sobczak * @cq: ibv_cq to poll
908cdcd52d4SBartosz Sobczak * @num_entries: max cq entries to poll
909cdcd52d4SBartosz Sobczak * @entry: pointer to array of ibv_wc objects to be filled in for each completion
910cdcd52d4SBartosz Sobczak *
911cdcd52d4SBartosz Sobczak * Returns non-negative value equal to the number of completions
912cdcd52d4SBartosz Sobczak * found and a negative error code on failure
913cdcd52d4SBartosz Sobczak */
914cdcd52d4SBartosz Sobczak int
irdma_upoll_cq(struct ibv_cq * cq,int num_entries,struct ibv_wc * entry)915cdcd52d4SBartosz Sobczak irdma_upoll_cq(struct ibv_cq *cq, int num_entries, struct ibv_wc *entry)
916cdcd52d4SBartosz Sobczak {
917cdcd52d4SBartosz Sobczak struct irdma_ucq *iwucq;
918cdcd52d4SBartosz Sobczak int ret;
919cdcd52d4SBartosz Sobczak
920cdcd52d4SBartosz Sobczak iwucq = container_of(cq, struct irdma_ucq, verbs_cq.cq);
921cdcd52d4SBartosz Sobczak ret = pthread_spin_lock(&iwucq->lock);
922cdcd52d4SBartosz Sobczak if (ret)
923cdcd52d4SBartosz Sobczak return -ret;
924cdcd52d4SBartosz Sobczak
925cdcd52d4SBartosz Sobczak ret = __irdma_upoll_cq(iwucq, num_entries, entry);
926cdcd52d4SBartosz Sobczak
927cdcd52d4SBartosz Sobczak pthread_spin_unlock(&iwucq->lock);
928cdcd52d4SBartosz Sobczak
929cdcd52d4SBartosz Sobczak return ret;
930cdcd52d4SBartosz Sobczak }
931cdcd52d4SBartosz Sobczak
932cdcd52d4SBartosz Sobczak /**
933cdcd52d4SBartosz Sobczak * irdma_start_poll - verb_ex API callback to poll batch of WC's
934cdcd52d4SBartosz Sobczak * @ibvcq_ex: ibv extended CQ
935cdcd52d4SBartosz Sobczak * @attr: attributes (not used)
936cdcd52d4SBartosz Sobczak *
937cdcd52d4SBartosz Sobczak * Start polling batch of work completions. Return 0 on success, ENONENT when
938cdcd52d4SBartosz Sobczak * no completions are available on CQ. And an error code on errors
939cdcd52d4SBartosz Sobczak */
940cdcd52d4SBartosz Sobczak static int
irdma_start_poll(struct ibv_cq_ex * ibvcq_ex,struct ibv_poll_cq_attr * attr)941cdcd52d4SBartosz Sobczak irdma_start_poll(struct ibv_cq_ex *ibvcq_ex, struct ibv_poll_cq_attr *attr)
942cdcd52d4SBartosz Sobczak {
943cdcd52d4SBartosz Sobczak struct irdma_ucq *iwucq;
944cdcd52d4SBartosz Sobczak int ret;
945cdcd52d4SBartosz Sobczak
946cdcd52d4SBartosz Sobczak iwucq = container_of(ibvcq_ex, struct irdma_ucq, verbs_cq.cq_ex);
947cdcd52d4SBartosz Sobczak ret = pthread_spin_lock(&iwucq->lock);
948cdcd52d4SBartosz Sobczak if (ret)
949cdcd52d4SBartosz Sobczak return ret;
950cdcd52d4SBartosz Sobczak
951cdcd52d4SBartosz Sobczak ret = __irdma_upoll_cq(iwucq, 1, NULL);
952cdcd52d4SBartosz Sobczak if (ret == 1)
953cdcd52d4SBartosz Sobczak return 0;
954cdcd52d4SBartosz Sobczak
955cdcd52d4SBartosz Sobczak /* No Completions on CQ */
956cdcd52d4SBartosz Sobczak if (!ret)
957cdcd52d4SBartosz Sobczak ret = ENOENT;
958cdcd52d4SBartosz Sobczak
959cdcd52d4SBartosz Sobczak pthread_spin_unlock(&iwucq->lock);
960cdcd52d4SBartosz Sobczak
961cdcd52d4SBartosz Sobczak return ret;
962cdcd52d4SBartosz Sobczak }
963cdcd52d4SBartosz Sobczak
964cdcd52d4SBartosz Sobczak /**
965cdcd52d4SBartosz Sobczak * irdma_next_poll - verb_ex API callback to get next WC
966cdcd52d4SBartosz Sobczak * @ibvcq_ex: ibv extended CQ
967cdcd52d4SBartosz Sobczak *
968cdcd52d4SBartosz Sobczak * Return 0 on success, ENONENT when no completions are available on CQ.
969cdcd52d4SBartosz Sobczak * And an error code on errors
970cdcd52d4SBartosz Sobczak */
971cdcd52d4SBartosz Sobczak static int
irdma_next_poll(struct ibv_cq_ex * ibvcq_ex)972cdcd52d4SBartosz Sobczak irdma_next_poll(struct ibv_cq_ex *ibvcq_ex)
973cdcd52d4SBartosz Sobczak {
974cdcd52d4SBartosz Sobczak struct irdma_ucq *iwucq;
975cdcd52d4SBartosz Sobczak int ret;
976cdcd52d4SBartosz Sobczak
977cdcd52d4SBartosz Sobczak iwucq = container_of(ibvcq_ex, struct irdma_ucq, verbs_cq.cq_ex);
978cdcd52d4SBartosz Sobczak ret = __irdma_upoll_cq(iwucq, 1, NULL);
979cdcd52d4SBartosz Sobczak if (ret == 1)
980cdcd52d4SBartosz Sobczak return 0;
981cdcd52d4SBartosz Sobczak
982cdcd52d4SBartosz Sobczak /* No Completions on CQ */
983cdcd52d4SBartosz Sobczak if (!ret)
984cdcd52d4SBartosz Sobczak ret = ENOENT;
985cdcd52d4SBartosz Sobczak
986cdcd52d4SBartosz Sobczak return ret;
987cdcd52d4SBartosz Sobczak }
988cdcd52d4SBartosz Sobczak
989cdcd52d4SBartosz Sobczak /**
990cdcd52d4SBartosz Sobczak * irdma_end_poll - verb_ex API callback to end polling of WC's
991cdcd52d4SBartosz Sobczak * @ibvcq_ex: ibv extended CQ
992cdcd52d4SBartosz Sobczak */
993cdcd52d4SBartosz Sobczak static void
irdma_end_poll(struct ibv_cq_ex * ibvcq_ex)994cdcd52d4SBartosz Sobczak irdma_end_poll(struct ibv_cq_ex *ibvcq_ex)
995cdcd52d4SBartosz Sobczak {
996cdcd52d4SBartosz Sobczak struct irdma_ucq *iwucq = container_of(ibvcq_ex, struct irdma_ucq,
997cdcd52d4SBartosz Sobczak verbs_cq.cq_ex);
998cdcd52d4SBartosz Sobczak
999cdcd52d4SBartosz Sobczak pthread_spin_unlock(&iwucq->lock);
1000cdcd52d4SBartosz Sobczak }
1001cdcd52d4SBartosz Sobczak
1002cdcd52d4SBartosz Sobczak static enum ibv_wc_opcode
irdma_wc_read_opcode(struct ibv_cq_ex * ibvcq_ex)1003cdcd52d4SBartosz Sobczak irdma_wc_read_opcode(struct ibv_cq_ex *ibvcq_ex)
1004cdcd52d4SBartosz Sobczak {
1005cdcd52d4SBartosz Sobczak struct irdma_ucq *iwucq = container_of(ibvcq_ex, struct irdma_ucq,
1006cdcd52d4SBartosz Sobczak verbs_cq.cq_ex);
1007cdcd52d4SBartosz Sobczak
1008cdcd52d4SBartosz Sobczak switch (iwucq->cur_cqe.op_type) {
1009cdcd52d4SBartosz Sobczak case IRDMA_OP_TYPE_RDMA_WRITE:
1010cdcd52d4SBartosz Sobczak case IRDMA_OP_TYPE_RDMA_WRITE_SOL:
1011cdcd52d4SBartosz Sobczak return IBV_WC_RDMA_WRITE;
1012cdcd52d4SBartosz Sobczak case IRDMA_OP_TYPE_RDMA_READ:
1013cdcd52d4SBartosz Sobczak return IBV_WC_RDMA_READ;
1014cdcd52d4SBartosz Sobczak case IRDMA_OP_TYPE_SEND_SOL:
1015cdcd52d4SBartosz Sobczak case IRDMA_OP_TYPE_SEND_SOL_INV:
1016cdcd52d4SBartosz Sobczak case IRDMA_OP_TYPE_SEND_INV:
1017cdcd52d4SBartosz Sobczak case IRDMA_OP_TYPE_SEND:
1018cdcd52d4SBartosz Sobczak return IBV_WC_SEND;
1019cdcd52d4SBartosz Sobczak case IRDMA_OP_TYPE_BIND_MW:
1020cdcd52d4SBartosz Sobczak return IBV_WC_BIND_MW;
1021cdcd52d4SBartosz Sobczak case IRDMA_OP_TYPE_REC:
1022cdcd52d4SBartosz Sobczak return IBV_WC_RECV;
1023cdcd52d4SBartosz Sobczak case IRDMA_OP_TYPE_REC_IMM:
1024cdcd52d4SBartosz Sobczak return IBV_WC_RECV_RDMA_WITH_IMM;
1025cdcd52d4SBartosz Sobczak case IRDMA_OP_TYPE_INV_STAG:
1026cdcd52d4SBartosz Sobczak return IBV_WC_LOCAL_INV;
1027cdcd52d4SBartosz Sobczak }
1028cdcd52d4SBartosz Sobczak
1029cdcd52d4SBartosz Sobczak printf("%s: Invalid opcode = %d in CQE\n", __func__,
1030cdcd52d4SBartosz Sobczak iwucq->cur_cqe.op_type);
1031cdcd52d4SBartosz Sobczak
1032cdcd52d4SBartosz Sobczak return 0;
1033cdcd52d4SBartosz Sobczak }
1034cdcd52d4SBartosz Sobczak
irdma_wc_read_vendor_err(struct ibv_cq_ex * ibvcq_ex)1035cdcd52d4SBartosz Sobczak static uint32_t irdma_wc_read_vendor_err(struct ibv_cq_ex *ibvcq_ex){
1036cdcd52d4SBartosz Sobczak struct irdma_cq_poll_info *cur_cqe;
1037cdcd52d4SBartosz Sobczak struct irdma_ucq *iwucq;
1038cdcd52d4SBartosz Sobczak
1039cdcd52d4SBartosz Sobczak iwucq = container_of(ibvcq_ex, struct irdma_ucq, verbs_cq.cq_ex);
1040cdcd52d4SBartosz Sobczak cur_cqe = &iwucq->cur_cqe;
1041cdcd52d4SBartosz Sobczak
1042cdcd52d4SBartosz Sobczak return cur_cqe->error ? cur_cqe->major_err << 16 | cur_cqe->minor_err : 0;
1043cdcd52d4SBartosz Sobczak }
1044cdcd52d4SBartosz Sobczak
1045cdcd52d4SBartosz Sobczak static int
irdma_wc_read_wc_flags(struct ibv_cq_ex * ibvcq_ex)1046cdcd52d4SBartosz Sobczak irdma_wc_read_wc_flags(struct ibv_cq_ex *ibvcq_ex)
1047cdcd52d4SBartosz Sobczak {
1048cdcd52d4SBartosz Sobczak struct irdma_cq_poll_info *cur_cqe;
1049cdcd52d4SBartosz Sobczak struct irdma_ucq *iwucq;
1050cdcd52d4SBartosz Sobczak struct irdma_qp_uk *qp;
1051cdcd52d4SBartosz Sobczak struct ibv_qp *ib_qp;
1052cdcd52d4SBartosz Sobczak int wc_flags = 0;
1053cdcd52d4SBartosz Sobczak
1054cdcd52d4SBartosz Sobczak iwucq = container_of(ibvcq_ex, struct irdma_ucq, verbs_cq.cq_ex);
1055cdcd52d4SBartosz Sobczak cur_cqe = &iwucq->cur_cqe;
1056cdcd52d4SBartosz Sobczak qp = cur_cqe->qp_handle;
1057cdcd52d4SBartosz Sobczak ib_qp = qp->back_qp;
1058cdcd52d4SBartosz Sobczak
1059cdcd52d4SBartosz Sobczak if (cur_cqe->imm_valid)
1060cdcd52d4SBartosz Sobczak wc_flags |= IBV_WC_WITH_IMM;
1061cdcd52d4SBartosz Sobczak
1062cdcd52d4SBartosz Sobczak if (ib_qp->qp_type == IBV_QPT_UD) {
1063cdcd52d4SBartosz Sobczak wc_flags |= IBV_WC_GRH;
1064cdcd52d4SBartosz Sobczak } else {
1065cdcd52d4SBartosz Sobczak if (cur_cqe->stag_invalid_set) {
1066cdcd52d4SBartosz Sobczak switch (cur_cqe->op_type) {
1067cdcd52d4SBartosz Sobczak case IRDMA_OP_TYPE_REC:
1068cdcd52d4SBartosz Sobczak wc_flags |= IBV_WC_WITH_INV;
1069cdcd52d4SBartosz Sobczak break;
1070cdcd52d4SBartosz Sobczak case IRDMA_OP_TYPE_REC_IMM:
1071cdcd52d4SBartosz Sobczak wc_flags |= IBV_WC_WITH_INV;
1072cdcd52d4SBartosz Sobczak break;
1073cdcd52d4SBartosz Sobczak }
1074cdcd52d4SBartosz Sobczak }
1075cdcd52d4SBartosz Sobczak }
1076cdcd52d4SBartosz Sobczak
1077cdcd52d4SBartosz Sobczak return wc_flags;
1078cdcd52d4SBartosz Sobczak }
1079cdcd52d4SBartosz Sobczak
irdma_wc_read_byte_len(struct ibv_cq_ex * ibvcq_ex)1080cdcd52d4SBartosz Sobczak static uint32_t irdma_wc_read_byte_len(struct ibv_cq_ex *ibvcq_ex){
1081cdcd52d4SBartosz Sobczak struct irdma_ucq *iwucq = container_of(ibvcq_ex, struct irdma_ucq,
1082cdcd52d4SBartosz Sobczak verbs_cq.cq_ex);
1083cdcd52d4SBartosz Sobczak
1084cdcd52d4SBartosz Sobczak return iwucq->cur_cqe.bytes_xfered;
1085cdcd52d4SBartosz Sobczak }
1086cdcd52d4SBartosz Sobczak
irdma_wc_read_imm_data(struct ibv_cq_ex * ibvcq_ex)1087cdcd52d4SBartosz Sobczak static __be32 irdma_wc_read_imm_data(struct ibv_cq_ex *ibvcq_ex){
1088cdcd52d4SBartosz Sobczak struct irdma_cq_poll_info *cur_cqe;
1089cdcd52d4SBartosz Sobczak struct irdma_ucq *iwucq;
1090cdcd52d4SBartosz Sobczak
1091cdcd52d4SBartosz Sobczak iwucq = container_of(ibvcq_ex, struct irdma_ucq, verbs_cq.cq_ex);
1092cdcd52d4SBartosz Sobczak cur_cqe = &iwucq->cur_cqe;
1093cdcd52d4SBartosz Sobczak
1094cdcd52d4SBartosz Sobczak return cur_cqe->imm_valid ? htonl(cur_cqe->imm_data) : 0;
1095cdcd52d4SBartosz Sobczak }
1096cdcd52d4SBartosz Sobczak
irdma_wc_read_qp_num(struct ibv_cq_ex * ibvcq_ex)1097cdcd52d4SBartosz Sobczak static uint32_t irdma_wc_read_qp_num(struct ibv_cq_ex *ibvcq_ex){
1098cdcd52d4SBartosz Sobczak struct irdma_ucq *iwucq = container_of(ibvcq_ex, struct irdma_ucq,
1099cdcd52d4SBartosz Sobczak verbs_cq.cq_ex);
1100cdcd52d4SBartosz Sobczak
1101cdcd52d4SBartosz Sobczak return iwucq->cur_cqe.qp_id;
1102cdcd52d4SBartosz Sobczak }
1103cdcd52d4SBartosz Sobczak
irdma_wc_read_src_qp(struct ibv_cq_ex * ibvcq_ex)1104cdcd52d4SBartosz Sobczak static uint32_t irdma_wc_read_src_qp(struct ibv_cq_ex *ibvcq_ex){
1105cdcd52d4SBartosz Sobczak struct irdma_cq_poll_info *cur_cqe;
1106cdcd52d4SBartosz Sobczak struct irdma_ucq *iwucq;
1107cdcd52d4SBartosz Sobczak struct irdma_qp_uk *qp;
1108cdcd52d4SBartosz Sobczak struct ibv_qp *ib_qp;
1109cdcd52d4SBartosz Sobczak
1110cdcd52d4SBartosz Sobczak iwucq = container_of(ibvcq_ex, struct irdma_ucq, verbs_cq.cq_ex);
1111cdcd52d4SBartosz Sobczak cur_cqe = &iwucq->cur_cqe;
1112cdcd52d4SBartosz Sobczak qp = cur_cqe->qp_handle;
1113cdcd52d4SBartosz Sobczak ib_qp = qp->back_qp;
1114cdcd52d4SBartosz Sobczak
1115cdcd52d4SBartosz Sobczak return ib_qp->qp_type == IBV_QPT_UD ? cur_cqe->ud_src_qpn : cur_cqe->qp_id;
1116cdcd52d4SBartosz Sobczak }
1117cdcd52d4SBartosz Sobczak
irdma_wc_read_sl(struct ibv_cq_ex * ibvcq_ex)1118cdcd52d4SBartosz Sobczak static uint8_t irdma_wc_read_sl(struct ibv_cq_ex *ibvcq_ex){
1119cdcd52d4SBartosz Sobczak return 0;
1120cdcd52d4SBartosz Sobczak }
1121cdcd52d4SBartosz Sobczak
1122cdcd52d4SBartosz Sobczak void
irdma_ibvcq_ex_fill_priv_funcs(struct irdma_ucq * iwucq,struct ibv_cq_init_attr_ex * attr_ex)1123cdcd52d4SBartosz Sobczak irdma_ibvcq_ex_fill_priv_funcs(struct irdma_ucq *iwucq,
1124cdcd52d4SBartosz Sobczak struct ibv_cq_init_attr_ex *attr_ex)
1125cdcd52d4SBartosz Sobczak {
1126cdcd52d4SBartosz Sobczak struct ibv_cq_ex *ibvcq_ex = &iwucq->verbs_cq.cq_ex;
1127cdcd52d4SBartosz Sobczak
1128cdcd52d4SBartosz Sobczak ibvcq_ex->start_poll = irdma_start_poll;
1129cdcd52d4SBartosz Sobczak ibvcq_ex->end_poll = irdma_end_poll;
1130cdcd52d4SBartosz Sobczak ibvcq_ex->next_poll = irdma_next_poll;
1131cdcd52d4SBartosz Sobczak
1132cdcd52d4SBartosz Sobczak ibvcq_ex->read_opcode = irdma_wc_read_opcode;
1133cdcd52d4SBartosz Sobczak ibvcq_ex->read_vendor_err = irdma_wc_read_vendor_err;
1134cdcd52d4SBartosz Sobczak ibvcq_ex->read_wc_flags = irdma_wc_read_wc_flags;
1135cdcd52d4SBartosz Sobczak
1136cdcd52d4SBartosz Sobczak if (attr_ex->wc_flags & IBV_WC_EX_WITH_BYTE_LEN)
1137cdcd52d4SBartosz Sobczak ibvcq_ex->read_byte_len = irdma_wc_read_byte_len;
1138cdcd52d4SBartosz Sobczak if (attr_ex->wc_flags & IBV_WC_EX_WITH_IMM)
1139cdcd52d4SBartosz Sobczak ibvcq_ex->read_imm_data = irdma_wc_read_imm_data;
1140cdcd52d4SBartosz Sobczak if (attr_ex->wc_flags & IBV_WC_EX_WITH_QP_NUM)
1141cdcd52d4SBartosz Sobczak ibvcq_ex->read_qp_num = irdma_wc_read_qp_num;
1142cdcd52d4SBartosz Sobczak if (attr_ex->wc_flags & IBV_WC_EX_WITH_SRC_QP)
1143cdcd52d4SBartosz Sobczak ibvcq_ex->read_src_qp = irdma_wc_read_src_qp;
1144cdcd52d4SBartosz Sobczak if (attr_ex->wc_flags & IBV_WC_EX_WITH_SL)
1145cdcd52d4SBartosz Sobczak ibvcq_ex->read_sl = irdma_wc_read_sl;
1146cdcd52d4SBartosz Sobczak }
1147cdcd52d4SBartosz Sobczak
1148cdcd52d4SBartosz Sobczak /**
1149cdcd52d4SBartosz Sobczak * irdma_arm_cq - arm of cq
1150cdcd52d4SBartosz Sobczak * @iwucq: cq to which arm
1151cdcd52d4SBartosz Sobczak * @cq_notify: notification params
1152cdcd52d4SBartosz Sobczak */
1153cdcd52d4SBartosz Sobczak static void
irdma_arm_cq(struct irdma_ucq * iwucq,enum irdma_cmpl_notify cq_notify)1154cdcd52d4SBartosz Sobczak irdma_arm_cq(struct irdma_ucq *iwucq,
1155cdcd52d4SBartosz Sobczak enum irdma_cmpl_notify cq_notify)
1156cdcd52d4SBartosz Sobczak {
1157cdcd52d4SBartosz Sobczak iwucq->is_armed = true;
1158cdcd52d4SBartosz Sobczak iwucq->arm_sol = true;
1159cdcd52d4SBartosz Sobczak iwucq->skip_arm = false;
1160cdcd52d4SBartosz Sobczak iwucq->skip_sol = true;
1161cdcd52d4SBartosz Sobczak irdma_uk_cq_request_notification(&iwucq->cq, cq_notify);
1162cdcd52d4SBartosz Sobczak }
1163cdcd52d4SBartosz Sobczak
1164cdcd52d4SBartosz Sobczak /**
1165cdcd52d4SBartosz Sobczak * irdma_uarm_cq - callback for arm of cq
1166cdcd52d4SBartosz Sobczak * @cq: cq to arm
1167cdcd52d4SBartosz Sobczak * @solicited: to get notify params
1168cdcd52d4SBartosz Sobczak */
1169cdcd52d4SBartosz Sobczak int
irdma_uarm_cq(struct ibv_cq * cq,int solicited)1170cdcd52d4SBartosz Sobczak irdma_uarm_cq(struct ibv_cq *cq, int solicited)
1171cdcd52d4SBartosz Sobczak {
1172cdcd52d4SBartosz Sobczak struct irdma_ucq *iwucq;
1173cdcd52d4SBartosz Sobczak enum irdma_cmpl_notify cq_notify = IRDMA_CQ_COMPL_EVENT;
1174cdcd52d4SBartosz Sobczak int ret;
1175cdcd52d4SBartosz Sobczak
1176cdcd52d4SBartosz Sobczak iwucq = container_of(cq, struct irdma_ucq, verbs_cq.cq);
1177cdcd52d4SBartosz Sobczak if (solicited)
1178cdcd52d4SBartosz Sobczak cq_notify = IRDMA_CQ_COMPL_SOLICITED;
1179cdcd52d4SBartosz Sobczak
1180cdcd52d4SBartosz Sobczak ret = pthread_spin_lock(&iwucq->lock);
1181cdcd52d4SBartosz Sobczak if (ret)
1182cdcd52d4SBartosz Sobczak return ret;
1183cdcd52d4SBartosz Sobczak
1184cdcd52d4SBartosz Sobczak if (iwucq->is_armed) {
1185cdcd52d4SBartosz Sobczak if (iwucq->arm_sol && !solicited) {
1186cdcd52d4SBartosz Sobczak irdma_arm_cq(iwucq, cq_notify);
1187cdcd52d4SBartosz Sobczak } else {
1188cdcd52d4SBartosz Sobczak iwucq->skip_arm = true;
1189cdcd52d4SBartosz Sobczak iwucq->skip_sol = solicited ? true : false;
1190cdcd52d4SBartosz Sobczak }
1191cdcd52d4SBartosz Sobczak } else {
1192cdcd52d4SBartosz Sobczak irdma_arm_cq(iwucq, cq_notify);
1193cdcd52d4SBartosz Sobczak }
1194cdcd52d4SBartosz Sobczak
1195cdcd52d4SBartosz Sobczak pthread_spin_unlock(&iwucq->lock);
1196cdcd52d4SBartosz Sobczak
1197cdcd52d4SBartosz Sobczak return 0;
1198cdcd52d4SBartosz Sobczak }
1199cdcd52d4SBartosz Sobczak
1200cdcd52d4SBartosz Sobczak /**
1201cdcd52d4SBartosz Sobczak * irdma_cq_event - cq to do completion event
1202cdcd52d4SBartosz Sobczak * @cq: cq to arm
1203cdcd52d4SBartosz Sobczak */
1204cdcd52d4SBartosz Sobczak void
irdma_cq_event(struct ibv_cq * cq)1205cdcd52d4SBartosz Sobczak irdma_cq_event(struct ibv_cq *cq)
1206cdcd52d4SBartosz Sobczak {
1207cdcd52d4SBartosz Sobczak struct irdma_ucq *iwucq;
1208cdcd52d4SBartosz Sobczak
1209cdcd52d4SBartosz Sobczak iwucq = container_of(cq, struct irdma_ucq, verbs_cq.cq);
1210cdcd52d4SBartosz Sobczak if (pthread_spin_lock(&iwucq->lock))
1211cdcd52d4SBartosz Sobczak return;
1212cdcd52d4SBartosz Sobczak
1213cdcd52d4SBartosz Sobczak if (iwucq->skip_arm)
1214cdcd52d4SBartosz Sobczak irdma_arm_cq(iwucq, IRDMA_CQ_COMPL_EVENT);
1215cdcd52d4SBartosz Sobczak else
1216cdcd52d4SBartosz Sobczak iwucq->is_armed = false;
1217cdcd52d4SBartosz Sobczak
1218cdcd52d4SBartosz Sobczak pthread_spin_unlock(&iwucq->lock);
1219cdcd52d4SBartosz Sobczak }
1220cdcd52d4SBartosz Sobczak
1221cdcd52d4SBartosz Sobczak void *
irdma_mmap(int fd,off_t offset)1222cdcd52d4SBartosz Sobczak irdma_mmap(int fd, off_t offset)
1223cdcd52d4SBartosz Sobczak {
1224cdcd52d4SBartosz Sobczak void *map;
1225cdcd52d4SBartosz Sobczak
1226cdcd52d4SBartosz Sobczak map = mmap(NULL, IRDMA_HW_PAGE_SIZE, PROT_WRITE | PROT_READ, MAP_SHARED,
1227cdcd52d4SBartosz Sobczak fd, offset);
1228cdcd52d4SBartosz Sobczak if (map == MAP_FAILED)
1229cdcd52d4SBartosz Sobczak return map;
1230cdcd52d4SBartosz Sobczak
1231cdcd52d4SBartosz Sobczak if (ibv_dontfork_range(map, IRDMA_HW_PAGE_SIZE)) {
1232cdcd52d4SBartosz Sobczak munmap(map, IRDMA_HW_PAGE_SIZE);
1233cdcd52d4SBartosz Sobczak return MAP_FAILED;
1234cdcd52d4SBartosz Sobczak }
1235cdcd52d4SBartosz Sobczak
1236cdcd52d4SBartosz Sobczak return map;
1237cdcd52d4SBartosz Sobczak }
1238cdcd52d4SBartosz Sobczak
1239cdcd52d4SBartosz Sobczak void
irdma_munmap(void * map)1240cdcd52d4SBartosz Sobczak irdma_munmap(void *map)
1241cdcd52d4SBartosz Sobczak {
1242cdcd52d4SBartosz Sobczak ibv_dofork_range(map, IRDMA_HW_PAGE_SIZE);
1243cdcd52d4SBartosz Sobczak munmap(map, IRDMA_HW_PAGE_SIZE);
1244cdcd52d4SBartosz Sobczak }
1245cdcd52d4SBartosz Sobczak
1246cdcd52d4SBartosz Sobczak /**
1247cdcd52d4SBartosz Sobczak * irdma_destroy_vmapped_qp - destroy resources for qp
1248cdcd52d4SBartosz Sobczak * @iwuqp: qp struct for resources
1249cdcd52d4SBartosz Sobczak */
1250cdcd52d4SBartosz Sobczak static int
irdma_destroy_vmapped_qp(struct irdma_uqp * iwuqp)1251cdcd52d4SBartosz Sobczak irdma_destroy_vmapped_qp(struct irdma_uqp *iwuqp)
1252cdcd52d4SBartosz Sobczak {
1253cdcd52d4SBartosz Sobczak int ret;
1254cdcd52d4SBartosz Sobczak
1255cdcd52d4SBartosz Sobczak ret = ibv_cmd_destroy_qp(&iwuqp->ibv_qp);
1256cdcd52d4SBartosz Sobczak if (ret)
1257cdcd52d4SBartosz Sobczak return ret;
1258cdcd52d4SBartosz Sobczak
1259cdcd52d4SBartosz Sobczak if (iwuqp->qp.push_db)
1260cdcd52d4SBartosz Sobczak irdma_munmap(iwuqp->qp.push_db);
1261cdcd52d4SBartosz Sobczak if (iwuqp->qp.push_wqe)
1262cdcd52d4SBartosz Sobczak irdma_munmap(iwuqp->qp.push_wqe);
1263cdcd52d4SBartosz Sobczak
1264cdcd52d4SBartosz Sobczak ibv_cmd_dereg_mr(&iwuqp->vmr.ibv_mr);
1265cdcd52d4SBartosz Sobczak
1266cdcd52d4SBartosz Sobczak return 0;
1267cdcd52d4SBartosz Sobczak }
1268cdcd52d4SBartosz Sobczak
1269cdcd52d4SBartosz Sobczak /**
1270cdcd52d4SBartosz Sobczak * irdma_vmapped_qp - create resources for qp
1271cdcd52d4SBartosz Sobczak * @iwuqp: qp struct for resources
1272cdcd52d4SBartosz Sobczak * @pd: pd for the qp
1273cdcd52d4SBartosz Sobczak * @attr: attributes of qp passed
1274cdcd52d4SBartosz Sobczak * @resp: response back from create qp
1275777e472cSBartosz Sobczak * @info: uk info for initializing user level qp
1276cdcd52d4SBartosz Sobczak * @abi_ver: abi version of the create qp command
1277cdcd52d4SBartosz Sobczak */
1278cdcd52d4SBartosz Sobczak static int
irdma_vmapped_qp(struct irdma_uqp * iwuqp,struct ibv_pd * pd,struct ibv_qp_init_attr * attr,struct irdma_qp_uk_init_info * info,bool legacy_mode)1279cdcd52d4SBartosz Sobczak irdma_vmapped_qp(struct irdma_uqp *iwuqp, struct ibv_pd *pd,
1280777e472cSBartosz Sobczak struct ibv_qp_init_attr *attr,
1281777e472cSBartosz Sobczak struct irdma_qp_uk_init_info *info,
1282cdcd52d4SBartosz Sobczak bool legacy_mode)
1283cdcd52d4SBartosz Sobczak {
1284cdcd52d4SBartosz Sobczak struct irdma_ucreate_qp cmd = {};
1285cdcd52d4SBartosz Sobczak size_t sqsize, rqsize, totalqpsize;
1286cdcd52d4SBartosz Sobczak struct irdma_ucreate_qp_resp resp = {};
1287cdcd52d4SBartosz Sobczak struct irdma_ureg_mr reg_mr_cmd = {};
1288cdcd52d4SBartosz Sobczak struct ibv_reg_mr_resp reg_mr_resp = {};
1289cdcd52d4SBartosz Sobczak int ret;
1290cdcd52d4SBartosz Sobczak
1291777e472cSBartosz Sobczak sqsize = roundup(info->sq_depth * IRDMA_QP_WQE_MIN_SIZE, IRDMA_HW_PAGE_SIZE);
1292777e472cSBartosz Sobczak rqsize = roundup(info->rq_depth * IRDMA_QP_WQE_MIN_SIZE, IRDMA_HW_PAGE_SIZE);
1293cdcd52d4SBartosz Sobczak totalqpsize = rqsize + sqsize + IRDMA_DB_SHADOW_AREA_SIZE;
1294cdcd52d4SBartosz Sobczak info->sq = irdma_alloc_hw_buf(totalqpsize);
1295cdcd52d4SBartosz Sobczak iwuqp->buf_size = totalqpsize;
1296cdcd52d4SBartosz Sobczak
1297cdcd52d4SBartosz Sobczak if (!info->sq)
1298cdcd52d4SBartosz Sobczak return ENOMEM;
1299cdcd52d4SBartosz Sobczak
1300cdcd52d4SBartosz Sobczak memset(info->sq, 0, totalqpsize);
1301cdcd52d4SBartosz Sobczak info->rq = &info->sq[sqsize / IRDMA_QP_WQE_MIN_SIZE];
1302cdcd52d4SBartosz Sobczak info->shadow_area = info->rq[rqsize / IRDMA_QP_WQE_MIN_SIZE].elem;
1303cdcd52d4SBartosz Sobczak
1304cdcd52d4SBartosz Sobczak reg_mr_cmd.reg_type = IRDMA_MEMREG_TYPE_QP;
1305cdcd52d4SBartosz Sobczak reg_mr_cmd.sq_pages = sqsize >> IRDMA_HW_PAGE_SHIFT;
1306cdcd52d4SBartosz Sobczak reg_mr_cmd.rq_pages = rqsize >> IRDMA_HW_PAGE_SHIFT;
1307cdcd52d4SBartosz Sobczak
1308cdcd52d4SBartosz Sobczak ret = ibv_cmd_reg_mr(pd, info->sq, totalqpsize,
1309cdcd52d4SBartosz Sobczak (uintptr_t)info->sq, IBV_ACCESS_LOCAL_WRITE,
1310cdcd52d4SBartosz Sobczak &iwuqp->vmr.ibv_mr, ®_mr_cmd.ibv_cmd,
1311cdcd52d4SBartosz Sobczak sizeof(reg_mr_cmd), ®_mr_resp,
1312cdcd52d4SBartosz Sobczak sizeof(reg_mr_resp));
1313cdcd52d4SBartosz Sobczak if (ret)
1314cdcd52d4SBartosz Sobczak goto err_dereg_mr;
1315cdcd52d4SBartosz Sobczak
1316cdcd52d4SBartosz Sobczak cmd.user_wqe_bufs = (__u64) ((uintptr_t)info->sq);
1317cdcd52d4SBartosz Sobczak cmd.user_compl_ctx = (__u64) (uintptr_t)&iwuqp->qp;
1318*5b5f7d0eSBartosz Sobczak cmd.comp_mask |= IRDMA_CREATE_QP_USE_START_WQE_IDX;
1319*5b5f7d0eSBartosz Sobczak
1320cdcd52d4SBartosz Sobczak ret = ibv_cmd_create_qp(pd, &iwuqp->ibv_qp, attr, &cmd.ibv_cmd,
1321cdcd52d4SBartosz Sobczak sizeof(cmd), &resp.ibv_resp,
1322cdcd52d4SBartosz Sobczak sizeof(struct irdma_ucreate_qp_resp));
1323cdcd52d4SBartosz Sobczak if (ret)
1324cdcd52d4SBartosz Sobczak goto err_qp;
1325cdcd52d4SBartosz Sobczak
1326cdcd52d4SBartosz Sobczak info->sq_size = resp.actual_sq_size;
1327cdcd52d4SBartosz Sobczak info->rq_size = resp.actual_rq_size;
1328cdcd52d4SBartosz Sobczak info->first_sq_wq = legacy_mode ? 1 : resp.lsmm;
1329*5b5f7d0eSBartosz Sobczak if (resp.comp_mask & IRDMA_CREATE_QP_USE_START_WQE_IDX)
1330*5b5f7d0eSBartosz Sobczak info->start_wqe_idx = resp.start_wqe_idx;
1331cdcd52d4SBartosz Sobczak info->qp_caps = resp.qp_caps;
1332cdcd52d4SBartosz Sobczak info->qp_id = resp.qp_id;
1333cdcd52d4SBartosz Sobczak iwuqp->irdma_drv_opt = resp.irdma_drv_opt;
1334cdcd52d4SBartosz Sobczak iwuqp->ibv_qp.qp_num = resp.qp_id;
1335cdcd52d4SBartosz Sobczak
1336cdcd52d4SBartosz Sobczak iwuqp->send_cq = container_of(attr->send_cq, struct irdma_ucq,
1337cdcd52d4SBartosz Sobczak verbs_cq.cq);
1338cdcd52d4SBartosz Sobczak iwuqp->recv_cq = container_of(attr->recv_cq, struct irdma_ucq,
1339cdcd52d4SBartosz Sobczak verbs_cq.cq);
1340cdcd52d4SBartosz Sobczak iwuqp->send_cq->uqp = iwuqp;
1341cdcd52d4SBartosz Sobczak iwuqp->recv_cq->uqp = iwuqp;
1342cdcd52d4SBartosz Sobczak
1343cdcd52d4SBartosz Sobczak return 0;
1344cdcd52d4SBartosz Sobczak err_qp:
1345cdcd52d4SBartosz Sobczak ibv_cmd_dereg_mr(&iwuqp->vmr.ibv_mr);
1346cdcd52d4SBartosz Sobczak err_dereg_mr:
1347cdcd52d4SBartosz Sobczak printf("%s: failed to create QP, status %d\n", __func__, ret);
1348cdcd52d4SBartosz Sobczak irdma_free_hw_buf(info->sq, iwuqp->buf_size);
1349cdcd52d4SBartosz Sobczak return ret;
1350cdcd52d4SBartosz Sobczak }
1351cdcd52d4SBartosz Sobczak
1352cdcd52d4SBartosz Sobczak /**
1353cdcd52d4SBartosz Sobczak * irdma_ucreate_qp - create qp on user app
1354cdcd52d4SBartosz Sobczak * @pd: pd for the qp
1355cdcd52d4SBartosz Sobczak * @attr: attributes of the qp to be created (sizes, sge, cq)
1356cdcd52d4SBartosz Sobczak */
1357cdcd52d4SBartosz Sobczak struct ibv_qp *
irdma_ucreate_qp(struct ibv_pd * pd,struct ibv_qp_init_attr * attr)1358cdcd52d4SBartosz Sobczak irdma_ucreate_qp(struct ibv_pd *pd,
1359cdcd52d4SBartosz Sobczak struct ibv_qp_init_attr *attr)
1360cdcd52d4SBartosz Sobczak {
1361cdcd52d4SBartosz Sobczak struct irdma_qp_uk_init_info info = {};
1362cdcd52d4SBartosz Sobczak struct irdma_uk_attrs *uk_attrs;
1363cdcd52d4SBartosz Sobczak struct irdma_uvcontext *iwvctx;
1364cdcd52d4SBartosz Sobczak struct irdma_uqp *iwuqp;
1365cdcd52d4SBartosz Sobczak int status;
1366cdcd52d4SBartosz Sobczak
1367cdcd52d4SBartosz Sobczak if (attr->qp_type != IBV_QPT_RC && attr->qp_type != IBV_QPT_UD) {
1368cdcd52d4SBartosz Sobczak printf("%s: failed to create QP, unsupported QP type: 0x%x\n",
1369cdcd52d4SBartosz Sobczak __func__, attr->qp_type);
1370cdcd52d4SBartosz Sobczak errno = EOPNOTSUPP;
1371cdcd52d4SBartosz Sobczak return NULL;
1372cdcd52d4SBartosz Sobczak }
1373cdcd52d4SBartosz Sobczak
1374cdcd52d4SBartosz Sobczak iwvctx = container_of(pd->context, struct irdma_uvcontext, ibv_ctx);
1375cdcd52d4SBartosz Sobczak uk_attrs = &iwvctx->uk_attrs;
1376cdcd52d4SBartosz Sobczak
1377cdcd52d4SBartosz Sobczak if (attr->cap.max_send_sge > uk_attrs->max_hw_wq_frags ||
1378cdcd52d4SBartosz Sobczak attr->cap.max_recv_sge > uk_attrs->max_hw_wq_frags ||
1379*5b5f7d0eSBartosz Sobczak attr->cap.max_send_wr > uk_attrs->max_hw_wq_quanta ||
1380*5b5f7d0eSBartosz Sobczak attr->cap.max_recv_wr > uk_attrs->max_hw_rq_quanta ||
1381cdcd52d4SBartosz Sobczak attr->cap.max_inline_data > uk_attrs->max_hw_inline) {
1382cdcd52d4SBartosz Sobczak errno = EINVAL;
1383cdcd52d4SBartosz Sobczak return NULL;
1384cdcd52d4SBartosz Sobczak }
1385cdcd52d4SBartosz Sobczak
1386777e472cSBartosz Sobczak info.uk_attrs = uk_attrs;
1387777e472cSBartosz Sobczak info.sq_size = attr->cap.max_send_wr;
1388777e472cSBartosz Sobczak info.rq_size = attr->cap.max_recv_wr;
1389777e472cSBartosz Sobczak info.max_sq_frag_cnt = attr->cap.max_send_sge;
1390777e472cSBartosz Sobczak info.max_rq_frag_cnt = attr->cap.max_recv_sge;
1391777e472cSBartosz Sobczak info.max_inline_data = attr->cap.max_inline_data;
1392777e472cSBartosz Sobczak info.abi_ver = iwvctx->abi_ver;
1393777e472cSBartosz Sobczak
1394777e472cSBartosz Sobczak status = irdma_uk_calc_depth_shift_sq(&info, &info.sq_depth, &info.sq_shift);
1395cdcd52d4SBartosz Sobczak if (status) {
1396cdcd52d4SBartosz Sobczak printf("%s: invalid SQ attributes, max_send_wr=%d max_send_sge=%d max_inline=%d\n",
1397cdcd52d4SBartosz Sobczak __func__, attr->cap.max_send_wr, attr->cap.max_send_sge,
1398cdcd52d4SBartosz Sobczak attr->cap.max_inline_data);
1399cdcd52d4SBartosz Sobczak errno = status;
1400cdcd52d4SBartosz Sobczak return NULL;
1401cdcd52d4SBartosz Sobczak }
1402cdcd52d4SBartosz Sobczak
1403777e472cSBartosz Sobczak status = irdma_uk_calc_depth_shift_rq(&info, &info.rq_depth, &info.rq_shift);
1404cdcd52d4SBartosz Sobczak if (status) {
1405cdcd52d4SBartosz Sobczak printf("%s: invalid RQ attributes, recv_wr=%d recv_sge=%d\n",
1406cdcd52d4SBartosz Sobczak __func__, attr->cap.max_recv_wr, attr->cap.max_recv_sge);
1407cdcd52d4SBartosz Sobczak errno = status;
1408cdcd52d4SBartosz Sobczak return NULL;
1409cdcd52d4SBartosz Sobczak }
1410cdcd52d4SBartosz Sobczak
1411cdcd52d4SBartosz Sobczak iwuqp = memalign(1024, sizeof(*iwuqp));
1412cdcd52d4SBartosz Sobczak if (!iwuqp)
1413cdcd52d4SBartosz Sobczak return NULL;
1414cdcd52d4SBartosz Sobczak
1415cdcd52d4SBartosz Sobczak memset(iwuqp, 0, sizeof(*iwuqp));
1416cdcd52d4SBartosz Sobczak
141701fbb869SBartosz Sobczak status = pthread_spin_init(&iwuqp->lock, PTHREAD_PROCESS_PRIVATE);
141801fbb869SBartosz Sobczak if (status)
1419cdcd52d4SBartosz Sobczak goto err_free_qp;
1420cdcd52d4SBartosz Sobczak
1421777e472cSBartosz Sobczak info.sq_size = info.sq_depth >> info.sq_shift;
1422777e472cSBartosz Sobczak info.rq_size = info.rq_depth >> info.rq_shift;
1423777e472cSBartosz Sobczak /**
142435105900SBartosz Sobczak * Maintain backward compatibility with older ABI which pass sq
142535105900SBartosz Sobczak * and rq depth (in quanta) in cap.max_send_wr a cap.max_recv_wr
1426777e472cSBartosz Sobczak */
142735105900SBartosz Sobczak if (!iwvctx->use_raw_attrs) {
1428cdcd52d4SBartosz Sobczak attr->cap.max_send_wr = info.sq_size;
1429cdcd52d4SBartosz Sobczak attr->cap.max_recv_wr = info.rq_size;
1430777e472cSBartosz Sobczak }
1431cdcd52d4SBartosz Sobczak
1432cdcd52d4SBartosz Sobczak info.wqe_alloc_db = (u32 *)iwvctx->db;
1433cdcd52d4SBartosz Sobczak info.legacy_mode = iwvctx->legacy_mode;
1434777e472cSBartosz Sobczak info.sq_wrtrk_array = calloc(info.sq_depth, sizeof(*info.sq_wrtrk_array));
143501fbb869SBartosz Sobczak if (!info.sq_wrtrk_array) {
143601fbb869SBartosz Sobczak status = errno; /* preserve errno */
1437*5b5f7d0eSBartosz Sobczak goto err_destroy_lock;
143801fbb869SBartosz Sobczak }
1439cdcd52d4SBartosz Sobczak
1440777e472cSBartosz Sobczak info.rq_wrid_array = calloc(info.rq_depth, sizeof(*info.rq_wrid_array));
144101fbb869SBartosz Sobczak if (!info.rq_wrid_array) {
144201fbb869SBartosz Sobczak status = errno; /* preserve errno */
1443cdcd52d4SBartosz Sobczak goto err_free_sq_wrtrk;
144401fbb869SBartosz Sobczak }
1445cdcd52d4SBartosz Sobczak
1446cdcd52d4SBartosz Sobczak iwuqp->sq_sig_all = attr->sq_sig_all;
1447cdcd52d4SBartosz Sobczak iwuqp->qp_type = attr->qp_type;
1448777e472cSBartosz Sobczak status = irdma_vmapped_qp(iwuqp, pd, attr, &info, iwvctx->legacy_mode);
144901fbb869SBartosz Sobczak if (status)
1450cdcd52d4SBartosz Sobczak goto err_free_rq_wrid;
1451cdcd52d4SBartosz Sobczak
1452cdcd52d4SBartosz Sobczak iwuqp->qp.back_qp = iwuqp;
1453cdcd52d4SBartosz Sobczak iwuqp->qp.lock = &iwuqp->lock;
1454cdcd52d4SBartosz Sobczak
1455cdcd52d4SBartosz Sobczak status = irdma_uk_qp_init(&iwuqp->qp, &info);
145601fbb869SBartosz Sobczak if (status)
1457cdcd52d4SBartosz Sobczak goto err_free_vmap_qp;
1458cdcd52d4SBartosz Sobczak
1459777e472cSBartosz Sobczak attr->cap.max_send_wr = (info.sq_depth - IRDMA_SQ_RSVD) >> info.sq_shift;
1460777e472cSBartosz Sobczak attr->cap.max_recv_wr = (info.rq_depth - IRDMA_RQ_RSVD) >> info.rq_shift;
1461777e472cSBartosz Sobczak
1462cdcd52d4SBartosz Sobczak return &iwuqp->ibv_qp;
1463cdcd52d4SBartosz Sobczak
1464cdcd52d4SBartosz Sobczak err_free_vmap_qp:
1465cdcd52d4SBartosz Sobczak irdma_destroy_vmapped_qp(iwuqp);
1466cdcd52d4SBartosz Sobczak irdma_free_hw_buf(info.sq, iwuqp->buf_size);
1467cdcd52d4SBartosz Sobczak err_free_rq_wrid:
1468cdcd52d4SBartosz Sobczak free(info.rq_wrid_array);
1469cdcd52d4SBartosz Sobczak err_free_sq_wrtrk:
1470cdcd52d4SBartosz Sobczak free(info.sq_wrtrk_array);
1471cdcd52d4SBartosz Sobczak err_destroy_lock:
1472cdcd52d4SBartosz Sobczak pthread_spin_destroy(&iwuqp->lock);
1473cdcd52d4SBartosz Sobczak err_free_qp:
1474cdcd52d4SBartosz Sobczak printf("%s: failed to create QP\n", __func__);
1475cdcd52d4SBartosz Sobczak free(iwuqp);
1476cdcd52d4SBartosz Sobczak
147701fbb869SBartosz Sobczak errno = status;
1478cdcd52d4SBartosz Sobczak return NULL;
1479cdcd52d4SBartosz Sobczak }
1480cdcd52d4SBartosz Sobczak
1481cdcd52d4SBartosz Sobczak /**
1482cdcd52d4SBartosz Sobczak * irdma_uquery_qp - query qp for some attribute
1483cdcd52d4SBartosz Sobczak * @qp: qp for the attributes query
1484cdcd52d4SBartosz Sobczak * @attr: to return the attributes
1485cdcd52d4SBartosz Sobczak * @attr_mask: mask of what is query for
1486cdcd52d4SBartosz Sobczak * @init_attr: initial attributes during create_qp
1487cdcd52d4SBartosz Sobczak */
1488cdcd52d4SBartosz Sobczak int
irdma_uquery_qp(struct ibv_qp * qp,struct ibv_qp_attr * attr,int attr_mask,struct ibv_qp_init_attr * init_attr)1489cdcd52d4SBartosz Sobczak irdma_uquery_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr, int attr_mask,
1490cdcd52d4SBartosz Sobczak struct ibv_qp_init_attr *init_attr)
1491cdcd52d4SBartosz Sobczak {
1492cdcd52d4SBartosz Sobczak struct ibv_query_qp cmd;
1493cdcd52d4SBartosz Sobczak
1494cdcd52d4SBartosz Sobczak return ibv_cmd_query_qp(qp, attr, attr_mask, init_attr, &cmd,
1495cdcd52d4SBartosz Sobczak sizeof(cmd));
1496cdcd52d4SBartosz Sobczak }
1497cdcd52d4SBartosz Sobczak
1498cdcd52d4SBartosz Sobczak /**
1499cdcd52d4SBartosz Sobczak * irdma_umodify_qp - send qp modify to driver
1500cdcd52d4SBartosz Sobczak * @qp: qp to modify
1501cdcd52d4SBartosz Sobczak * @attr: attribute to modify
1502cdcd52d4SBartosz Sobczak * @attr_mask: mask of the attribute
1503cdcd52d4SBartosz Sobczak */
1504cdcd52d4SBartosz Sobczak int
irdma_umodify_qp(struct ibv_qp * qp,struct ibv_qp_attr * attr,int attr_mask)1505cdcd52d4SBartosz Sobczak irdma_umodify_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr, int attr_mask)
1506cdcd52d4SBartosz Sobczak {
1507cdcd52d4SBartosz Sobczak struct irdma_umodify_qp_resp resp = {};
1508cdcd52d4SBartosz Sobczak struct ibv_modify_qp cmd = {};
1509cdcd52d4SBartosz Sobczak struct irdma_modify_qp_cmd cmd_ex = {};
1510cdcd52d4SBartosz Sobczak struct irdma_uvcontext *iwvctx;
1511cdcd52d4SBartosz Sobczak struct irdma_uqp *iwuqp;
1512cdcd52d4SBartosz Sobczak
1513cdcd52d4SBartosz Sobczak iwuqp = container_of(qp, struct irdma_uqp, ibv_qp);
1514cdcd52d4SBartosz Sobczak iwvctx = container_of(qp->context, struct irdma_uvcontext, ibv_ctx);
1515cdcd52d4SBartosz Sobczak
1516cdcd52d4SBartosz Sobczak if (iwuqp->qp.qp_caps & IRDMA_PUSH_MODE && attr_mask & IBV_QP_STATE &&
1517cdcd52d4SBartosz Sobczak iwvctx->uk_attrs.hw_rev > IRDMA_GEN_1) {
1518cdcd52d4SBartosz Sobczak u64 offset;
1519cdcd52d4SBartosz Sobczak void *map;
1520cdcd52d4SBartosz Sobczak int ret;
1521cdcd52d4SBartosz Sobczak
1522cdcd52d4SBartosz Sobczak ret = ibv_cmd_modify_qp_ex(qp, attr, attr_mask, &cmd_ex.ibv_cmd,
1523cdcd52d4SBartosz Sobczak sizeof(cmd_ex.ibv_cmd),
1524cdcd52d4SBartosz Sobczak sizeof(cmd_ex), &resp.ibv_resp,
1525cdcd52d4SBartosz Sobczak sizeof(resp.ibv_resp),
1526cdcd52d4SBartosz Sobczak sizeof(resp));
1527cdcd52d4SBartosz Sobczak if (!ret)
1528cdcd52d4SBartosz Sobczak iwuqp->qp.rd_fence_rate = resp.rd_fence_rate;
1529cdcd52d4SBartosz Sobczak if (ret || !resp.push_valid)
1530cdcd52d4SBartosz Sobczak return ret;
1531cdcd52d4SBartosz Sobczak
1532cdcd52d4SBartosz Sobczak if (iwuqp->qp.push_wqe)
1533cdcd52d4SBartosz Sobczak return ret;
1534cdcd52d4SBartosz Sobczak
1535cdcd52d4SBartosz Sobczak offset = resp.push_wqe_mmap_key;
1536cdcd52d4SBartosz Sobczak map = irdma_mmap(qp->context->cmd_fd, offset);
1537cdcd52d4SBartosz Sobczak if (map == MAP_FAILED)
1538cdcd52d4SBartosz Sobczak return ret;
1539cdcd52d4SBartosz Sobczak
1540cdcd52d4SBartosz Sobczak iwuqp->qp.push_wqe = map;
1541cdcd52d4SBartosz Sobczak
1542cdcd52d4SBartosz Sobczak offset = resp.push_db_mmap_key;
1543cdcd52d4SBartosz Sobczak map = irdma_mmap(qp->context->cmd_fd, offset);
1544cdcd52d4SBartosz Sobczak if (map == MAP_FAILED) {
1545cdcd52d4SBartosz Sobczak irdma_munmap(iwuqp->qp.push_wqe);
1546cdcd52d4SBartosz Sobczak iwuqp->qp.push_wqe = NULL;
1547cdcd52d4SBartosz Sobczak printf("failed to map push page, errno %d\n", errno);
1548cdcd52d4SBartosz Sobczak return ret;
1549cdcd52d4SBartosz Sobczak }
1550cdcd52d4SBartosz Sobczak iwuqp->qp.push_wqe += resp.push_offset;
1551cdcd52d4SBartosz Sobczak iwuqp->qp.push_db = map + resp.push_offset;
1552cdcd52d4SBartosz Sobczak
1553cdcd52d4SBartosz Sobczak return ret;
1554cdcd52d4SBartosz Sobczak } else {
1555ffafa6a4SBartosz Sobczak return ibv_cmd_modify_qp(qp, attr, attr_mask, &cmd, sizeof(cmd));
1556cdcd52d4SBartosz Sobczak }
1557cdcd52d4SBartosz Sobczak }
1558cdcd52d4SBartosz Sobczak
1559cdcd52d4SBartosz Sobczak static void
irdma_issue_flush(struct ibv_qp * qp,bool sq_flush,bool rq_flush)1560cdcd52d4SBartosz Sobczak irdma_issue_flush(struct ibv_qp *qp, bool sq_flush, bool rq_flush)
1561cdcd52d4SBartosz Sobczak {
1562cdcd52d4SBartosz Sobczak struct irdma_umodify_qp_resp resp = {};
1563cdcd52d4SBartosz Sobczak struct irdma_modify_qp_cmd cmd_ex = {};
1564777e472cSBartosz Sobczak struct ibv_qp_attr attr = {};
1565cdcd52d4SBartosz Sobczak
1566777e472cSBartosz Sobczak attr.qp_state = IBV_QPS_ERR;
1567cdcd52d4SBartosz Sobczak cmd_ex.sq_flush = sq_flush;
1568cdcd52d4SBartosz Sobczak cmd_ex.rq_flush = rq_flush;
1569cdcd52d4SBartosz Sobczak
1570777e472cSBartosz Sobczak ibv_cmd_modify_qp_ex(qp, &attr, IBV_QP_STATE,
1571cdcd52d4SBartosz Sobczak &cmd_ex.ibv_cmd,
1572cdcd52d4SBartosz Sobczak sizeof(cmd_ex.ibv_cmd),
1573cdcd52d4SBartosz Sobczak sizeof(cmd_ex), &resp.ibv_resp,
1574cdcd52d4SBartosz Sobczak sizeof(resp.ibv_resp),
1575cdcd52d4SBartosz Sobczak sizeof(resp));
1576cdcd52d4SBartosz Sobczak }
1577cdcd52d4SBartosz Sobczak
1578cdcd52d4SBartosz Sobczak /**
1579cdcd52d4SBartosz Sobczak * irdma_clean_cqes - clean cq entries for qp
1580cdcd52d4SBartosz Sobczak * @qp: qp for which completions are cleaned
1581cdcd52d4SBartosz Sobczak * @iwcq: cq to be cleaned
1582cdcd52d4SBartosz Sobczak */
1583cdcd52d4SBartosz Sobczak static void
irdma_clean_cqes(struct irdma_qp_uk * qp,struct irdma_ucq * iwucq)1584cdcd52d4SBartosz Sobczak irdma_clean_cqes(struct irdma_qp_uk *qp, struct irdma_ucq *iwucq)
1585cdcd52d4SBartosz Sobczak {
1586cdcd52d4SBartosz Sobczak struct irdma_cq_uk *ukcq = &iwucq->cq;
1587cdcd52d4SBartosz Sobczak int ret;
1588cdcd52d4SBartosz Sobczak
1589cdcd52d4SBartosz Sobczak ret = pthread_spin_lock(&iwucq->lock);
1590cdcd52d4SBartosz Sobczak if (ret)
1591cdcd52d4SBartosz Sobczak return;
1592cdcd52d4SBartosz Sobczak
1593cdcd52d4SBartosz Sobczak irdma_uk_clean_cq(qp, ukcq);
1594cdcd52d4SBartosz Sobczak pthread_spin_unlock(&iwucq->lock);
1595cdcd52d4SBartosz Sobczak }
1596cdcd52d4SBartosz Sobczak
1597cdcd52d4SBartosz Sobczak /**
1598cdcd52d4SBartosz Sobczak * irdma_udestroy_qp - destroy qp
1599cdcd52d4SBartosz Sobczak * @qp: qp to destroy
1600cdcd52d4SBartosz Sobczak */
1601cdcd52d4SBartosz Sobczak int
irdma_udestroy_qp(struct ibv_qp * qp)1602cdcd52d4SBartosz Sobczak irdma_udestroy_qp(struct ibv_qp *qp)
1603cdcd52d4SBartosz Sobczak {
1604cdcd52d4SBartosz Sobczak struct irdma_uqp *iwuqp;
1605cdcd52d4SBartosz Sobczak int ret;
1606cdcd52d4SBartosz Sobczak
1607cdcd52d4SBartosz Sobczak iwuqp = container_of(qp, struct irdma_uqp, ibv_qp);
1608cdcd52d4SBartosz Sobczak ret = pthread_spin_destroy(&iwuqp->lock);
1609cdcd52d4SBartosz Sobczak if (ret)
1610cdcd52d4SBartosz Sobczak goto err;
1611cdcd52d4SBartosz Sobczak
1612cdcd52d4SBartosz Sobczak ret = irdma_destroy_vmapped_qp(iwuqp);
1613cdcd52d4SBartosz Sobczak if (ret)
1614cdcd52d4SBartosz Sobczak goto err;
1615cdcd52d4SBartosz Sobczak
1616cdcd52d4SBartosz Sobczak /* Clean any pending completions from the cq(s) */
1617cdcd52d4SBartosz Sobczak if (iwuqp->send_cq)
1618cdcd52d4SBartosz Sobczak irdma_clean_cqes(&iwuqp->qp, iwuqp->send_cq);
1619cdcd52d4SBartosz Sobczak
1620cdcd52d4SBartosz Sobczak if (iwuqp->recv_cq && iwuqp->recv_cq != iwuqp->send_cq)
1621cdcd52d4SBartosz Sobczak irdma_clean_cqes(&iwuqp->qp, iwuqp->recv_cq);
1622cdcd52d4SBartosz Sobczak
1623cdcd52d4SBartosz Sobczak if (iwuqp->qp.sq_wrtrk_array)
1624cdcd52d4SBartosz Sobczak free(iwuqp->qp.sq_wrtrk_array);
1625cdcd52d4SBartosz Sobczak if (iwuqp->qp.rq_wrid_array)
1626cdcd52d4SBartosz Sobczak free(iwuqp->qp.rq_wrid_array);
1627cdcd52d4SBartosz Sobczak
1628cdcd52d4SBartosz Sobczak irdma_free_hw_buf(iwuqp->qp.sq_base, iwuqp->buf_size);
1629cdcd52d4SBartosz Sobczak free(iwuqp);
1630cdcd52d4SBartosz Sobczak return 0;
1631cdcd52d4SBartosz Sobczak
1632cdcd52d4SBartosz Sobczak err:
1633cdcd52d4SBartosz Sobczak printf("%s: failed to destroy QP, status %d\n",
1634cdcd52d4SBartosz Sobczak __func__, ret);
1635cdcd52d4SBartosz Sobczak return ret;
1636cdcd52d4SBartosz Sobczak }
1637cdcd52d4SBartosz Sobczak
1638cdcd52d4SBartosz Sobczak /**
1639cdcd52d4SBartosz Sobczak * calc_type2_mw_stag - calculate type 2 MW stag
1640cdcd52d4SBartosz Sobczak * @rkey: desired rkey of the MW
1641cdcd52d4SBartosz Sobczak * @mw_rkey: type2 memory window rkey
1642cdcd52d4SBartosz Sobczak *
1643cdcd52d4SBartosz Sobczak * compute type2 memory window stag by taking lower 8 bits
1644cdcd52d4SBartosz Sobczak * of the desired rkey and leaving 24 bits if mw->rkey unchanged
1645cdcd52d4SBartosz Sobczak */
calc_type2_mw_stag(u32 rkey,u32 mw_rkey)1646cdcd52d4SBartosz Sobczak static inline u32 calc_type2_mw_stag(u32 rkey, u32 mw_rkey) {
1647cdcd52d4SBartosz Sobczak const u32 mask = 0xff;
1648cdcd52d4SBartosz Sobczak
1649cdcd52d4SBartosz Sobczak return (rkey & mask) | (mw_rkey & ~mask);
1650cdcd52d4SBartosz Sobczak }
1651cdcd52d4SBartosz Sobczak
1652cdcd52d4SBartosz Sobczak /**
1653cdcd52d4SBartosz Sobczak * irdma_post_send - post send wr for user application
1654cdcd52d4SBartosz Sobczak * @ib_qp: qp to post wr
1655cdcd52d4SBartosz Sobczak * @ib_wr: work request ptr
1656cdcd52d4SBartosz Sobczak * @bad_wr: return of bad wr if err
1657cdcd52d4SBartosz Sobczak */
1658cdcd52d4SBartosz Sobczak int
irdma_upost_send(struct ibv_qp * ib_qp,struct ibv_send_wr * ib_wr,struct ibv_send_wr ** bad_wr)1659cdcd52d4SBartosz Sobczak irdma_upost_send(struct ibv_qp *ib_qp, struct ibv_send_wr *ib_wr,
1660cdcd52d4SBartosz Sobczak struct ibv_send_wr **bad_wr)
1661cdcd52d4SBartosz Sobczak {
1662cdcd52d4SBartosz Sobczak struct irdma_post_sq_info info;
1663cdcd52d4SBartosz Sobczak struct irdma_uvcontext *iwvctx;
1664cdcd52d4SBartosz Sobczak struct irdma_uk_attrs *uk_attrs;
1665cdcd52d4SBartosz Sobczak struct irdma_uqp *iwuqp;
1666cdcd52d4SBartosz Sobczak bool reflush = false;
1667cdcd52d4SBartosz Sobczak int err = 0;
1668cdcd52d4SBartosz Sobczak
1669cdcd52d4SBartosz Sobczak iwuqp = container_of(ib_qp, struct irdma_uqp, ibv_qp);
1670cdcd52d4SBartosz Sobczak iwvctx = container_of(ib_qp->context, struct irdma_uvcontext, ibv_ctx);
1671cdcd52d4SBartosz Sobczak uk_attrs = &iwvctx->uk_attrs;
1672cdcd52d4SBartosz Sobczak
1673cdcd52d4SBartosz Sobczak err = pthread_spin_lock(&iwuqp->lock);
1674cdcd52d4SBartosz Sobczak if (err)
1675cdcd52d4SBartosz Sobczak return err;
1676cdcd52d4SBartosz Sobczak
1677cdcd52d4SBartosz Sobczak if (!IRDMA_RING_MORE_WORK(iwuqp->qp.sq_ring) &&
1678cdcd52d4SBartosz Sobczak ib_qp->state == IBV_QPS_ERR)
1679cdcd52d4SBartosz Sobczak reflush = true;
1680cdcd52d4SBartosz Sobczak
1681cdcd52d4SBartosz Sobczak while (ib_wr) {
1682cdcd52d4SBartosz Sobczak memset(&info, 0, sizeof(info));
1683cdcd52d4SBartosz Sobczak info.wr_id = (u64)(ib_wr->wr_id);
1684cdcd52d4SBartosz Sobczak if ((ib_wr->send_flags & IBV_SEND_SIGNALED) ||
1685cdcd52d4SBartosz Sobczak iwuqp->sq_sig_all)
1686cdcd52d4SBartosz Sobczak info.signaled = true;
1687cdcd52d4SBartosz Sobczak if (ib_wr->send_flags & IBV_SEND_FENCE)
1688cdcd52d4SBartosz Sobczak info.read_fence = true;
1689cdcd52d4SBartosz Sobczak
1690cdcd52d4SBartosz Sobczak switch (ib_wr->opcode) {
1691cdcd52d4SBartosz Sobczak case IBV_WR_SEND_WITH_IMM:
1692cdcd52d4SBartosz Sobczak if (iwuqp->qp.qp_caps & IRDMA_SEND_WITH_IMM) {
1693cdcd52d4SBartosz Sobczak info.imm_data_valid = true;
1694cdcd52d4SBartosz Sobczak info.imm_data = ntohl(ib_wr->imm_data);
1695cdcd52d4SBartosz Sobczak } else {
1696cdcd52d4SBartosz Sobczak err = EINVAL;
1697cdcd52d4SBartosz Sobczak break;
1698cdcd52d4SBartosz Sobczak }
1699cdcd52d4SBartosz Sobczak /* fallthrough */
1700cdcd52d4SBartosz Sobczak case IBV_WR_SEND:
1701cdcd52d4SBartosz Sobczak case IBV_WR_SEND_WITH_INV:
1702cdcd52d4SBartosz Sobczak if (ib_wr->opcode == IBV_WR_SEND ||
1703cdcd52d4SBartosz Sobczak ib_wr->opcode == IBV_WR_SEND_WITH_IMM) {
1704cdcd52d4SBartosz Sobczak if (ib_wr->send_flags & IBV_SEND_SOLICITED)
1705cdcd52d4SBartosz Sobczak info.op_type = IRDMA_OP_TYPE_SEND_SOL;
1706cdcd52d4SBartosz Sobczak else
1707cdcd52d4SBartosz Sobczak info.op_type = IRDMA_OP_TYPE_SEND;
1708cdcd52d4SBartosz Sobczak } else {
1709cdcd52d4SBartosz Sobczak if (ib_wr->send_flags & IBV_SEND_SOLICITED)
1710cdcd52d4SBartosz Sobczak info.op_type = IRDMA_OP_TYPE_SEND_SOL_INV;
1711cdcd52d4SBartosz Sobczak else
1712cdcd52d4SBartosz Sobczak info.op_type = IRDMA_OP_TYPE_SEND_INV;
1713cdcd52d4SBartosz Sobczak info.stag_to_inv = ib_wr->imm_data;
1714cdcd52d4SBartosz Sobczak }
1715cdcd52d4SBartosz Sobczak info.op.send.num_sges = ib_wr->num_sge;
1716*5b5f7d0eSBartosz Sobczak info.op.send.sg_list = (struct ibv_sge *)ib_wr->sg_list;
1717cdcd52d4SBartosz Sobczak if (ib_qp->qp_type == IBV_QPT_UD) {
1718cdcd52d4SBartosz Sobczak struct irdma_uah *ah = container_of(ib_wr->wr.ud.ah,
1719cdcd52d4SBartosz Sobczak struct irdma_uah, ibv_ah);
1720cdcd52d4SBartosz Sobczak
1721777e472cSBartosz Sobczak info.op.send.ah_id = ah->ah_id;
1722777e472cSBartosz Sobczak info.op.send.qkey = ib_wr->wr.ud.remote_qkey;
1723777e472cSBartosz Sobczak info.op.send.dest_qp = ib_wr->wr.ud.remote_qpn;
1724cdcd52d4SBartosz Sobczak }
1725777e472cSBartosz Sobczak
1726777e472cSBartosz Sobczak if (ib_wr->send_flags & IBV_SEND_INLINE)
1727777e472cSBartosz Sobczak err = irdma_uk_inline_send(&iwuqp->qp, &info, false);
1728777e472cSBartosz Sobczak else
1729cdcd52d4SBartosz Sobczak err = irdma_uk_send(&iwuqp->qp, &info, false);
1730cdcd52d4SBartosz Sobczak break;
1731cdcd52d4SBartosz Sobczak case IBV_WR_RDMA_WRITE_WITH_IMM:
1732cdcd52d4SBartosz Sobczak if (iwuqp->qp.qp_caps & IRDMA_WRITE_WITH_IMM) {
1733cdcd52d4SBartosz Sobczak info.imm_data_valid = true;
1734cdcd52d4SBartosz Sobczak info.imm_data = ntohl(ib_wr->imm_data);
1735cdcd52d4SBartosz Sobczak } else {
1736cdcd52d4SBartosz Sobczak err = EINVAL;
1737cdcd52d4SBartosz Sobczak break;
1738cdcd52d4SBartosz Sobczak }
1739cdcd52d4SBartosz Sobczak /* fallthrough */
1740cdcd52d4SBartosz Sobczak case IBV_WR_RDMA_WRITE:
1741cdcd52d4SBartosz Sobczak if (ib_wr->send_flags & IBV_SEND_SOLICITED)
1742cdcd52d4SBartosz Sobczak info.op_type = IRDMA_OP_TYPE_RDMA_WRITE_SOL;
1743cdcd52d4SBartosz Sobczak else
1744cdcd52d4SBartosz Sobczak info.op_type = IRDMA_OP_TYPE_RDMA_WRITE;
1745cdcd52d4SBartosz Sobczak
1746cdcd52d4SBartosz Sobczak info.op.rdma_write.num_lo_sges = ib_wr->num_sge;
1747*5b5f7d0eSBartosz Sobczak info.op.rdma_write.lo_sg_list = ib_wr->sg_list;
1748*5b5f7d0eSBartosz Sobczak info.op.rdma_write.rem_addr.addr = ib_wr->wr.rdma.remote_addr;
1749*5b5f7d0eSBartosz Sobczak info.op.rdma_write.rem_addr.lkey = ib_wr->wr.rdma.rkey;
1750777e472cSBartosz Sobczak if (ib_wr->send_flags & IBV_SEND_INLINE)
1751777e472cSBartosz Sobczak err = irdma_uk_inline_rdma_write(&iwuqp->qp, &info, false);
1752777e472cSBartosz Sobczak else
1753cdcd52d4SBartosz Sobczak err = irdma_uk_rdma_write(&iwuqp->qp, &info, false);
1754cdcd52d4SBartosz Sobczak break;
1755cdcd52d4SBartosz Sobczak case IBV_WR_RDMA_READ:
1756cdcd52d4SBartosz Sobczak if (ib_wr->num_sge > uk_attrs->max_hw_read_sges) {
1757cdcd52d4SBartosz Sobczak err = EINVAL;
1758cdcd52d4SBartosz Sobczak break;
1759cdcd52d4SBartosz Sobczak }
1760cdcd52d4SBartosz Sobczak info.op_type = IRDMA_OP_TYPE_RDMA_READ;
1761*5b5f7d0eSBartosz Sobczak info.op.rdma_read.rem_addr.addr = ib_wr->wr.rdma.remote_addr;
1762*5b5f7d0eSBartosz Sobczak info.op.rdma_read.rem_addr.lkey = ib_wr->wr.rdma.rkey;
1763cdcd52d4SBartosz Sobczak
1764*5b5f7d0eSBartosz Sobczak info.op.rdma_read.lo_sg_list = ib_wr->sg_list;
1765cdcd52d4SBartosz Sobczak info.op.rdma_read.num_lo_sges = ib_wr->num_sge;
1766cdcd52d4SBartosz Sobczak err = irdma_uk_rdma_read(&iwuqp->qp, &info, false, false);
1767cdcd52d4SBartosz Sobczak break;
1768cdcd52d4SBartosz Sobczak case IBV_WR_BIND_MW:
1769cdcd52d4SBartosz Sobczak if (ib_qp->qp_type != IBV_QPT_RC) {
1770cdcd52d4SBartosz Sobczak err = EINVAL;
1771cdcd52d4SBartosz Sobczak break;
1772cdcd52d4SBartosz Sobczak }
1773cdcd52d4SBartosz Sobczak info.op_type = IRDMA_OP_TYPE_BIND_MW;
1774cdcd52d4SBartosz Sobczak info.op.bind_window.mr_stag = ib_wr->bind_mw.bind_info.mr->rkey;
1775cdcd52d4SBartosz Sobczak if (ib_wr->bind_mw.mw->type == IBV_MW_TYPE_1) {
1776cdcd52d4SBartosz Sobczak info.op.bind_window.mem_window_type_1 = true;
1777cdcd52d4SBartosz Sobczak info.op.bind_window.mw_stag = ib_wr->bind_mw.rkey;
1778cdcd52d4SBartosz Sobczak } else {
1779cdcd52d4SBartosz Sobczak struct verbs_mr *vmr = verbs_get_mr(ib_wr->bind_mw.bind_info.mr);
1780cdcd52d4SBartosz Sobczak
1781777e472cSBartosz Sobczak if (vmr->access & IBV_ACCESS_ZERO_BASED) {
1782cdcd52d4SBartosz Sobczak err = EINVAL;
1783cdcd52d4SBartosz Sobczak break;
1784cdcd52d4SBartosz Sobczak }
1785cdcd52d4SBartosz Sobczak info.op.bind_window.mw_stag =
1786cdcd52d4SBartosz Sobczak calc_type2_mw_stag(ib_wr->bind_mw.rkey, ib_wr->bind_mw.mw->rkey);
1787cdcd52d4SBartosz Sobczak ib_wr->bind_mw.mw->rkey = info.op.bind_window.mw_stag;
1788cdcd52d4SBartosz Sobczak
1789cdcd52d4SBartosz Sobczak }
1790cdcd52d4SBartosz Sobczak
1791cdcd52d4SBartosz Sobczak if (ib_wr->bind_mw.bind_info.mw_access_flags & IBV_ACCESS_ZERO_BASED) {
1792cdcd52d4SBartosz Sobczak info.op.bind_window.addressing_type = IRDMA_ADDR_TYPE_ZERO_BASED;
1793cdcd52d4SBartosz Sobczak info.op.bind_window.va = NULL;
1794cdcd52d4SBartosz Sobczak } else {
1795cdcd52d4SBartosz Sobczak info.op.bind_window.addressing_type = IRDMA_ADDR_TYPE_VA_BASED;
1796cdcd52d4SBartosz Sobczak info.op.bind_window.va = (void *)(uintptr_t)ib_wr->bind_mw.bind_info.addr;
1797cdcd52d4SBartosz Sobczak }
1798cdcd52d4SBartosz Sobczak info.op.bind_window.bind_len = ib_wr->bind_mw.bind_info.length;
1799cdcd52d4SBartosz Sobczak info.op.bind_window.ena_reads =
1800cdcd52d4SBartosz Sobczak (ib_wr->bind_mw.bind_info.mw_access_flags & IBV_ACCESS_REMOTE_READ) ? 1 : 0;
1801cdcd52d4SBartosz Sobczak info.op.bind_window.ena_writes =
1802cdcd52d4SBartosz Sobczak (ib_wr->bind_mw.bind_info.mw_access_flags & IBV_ACCESS_REMOTE_WRITE) ? 1 : 0;
1803cdcd52d4SBartosz Sobczak
1804cdcd52d4SBartosz Sobczak err = irdma_uk_mw_bind(&iwuqp->qp, &info, false);
1805cdcd52d4SBartosz Sobczak break;
1806cdcd52d4SBartosz Sobczak case IBV_WR_LOCAL_INV:
1807cdcd52d4SBartosz Sobczak info.op_type = IRDMA_OP_TYPE_INV_STAG;
1808cdcd52d4SBartosz Sobczak info.op.inv_local_stag.target_stag = ib_wr->imm_data;
1809cdcd52d4SBartosz Sobczak err = irdma_uk_stag_local_invalidate(&iwuqp->qp, &info, true);
1810cdcd52d4SBartosz Sobczak break;
1811cdcd52d4SBartosz Sobczak default:
1812cdcd52d4SBartosz Sobczak /* error */
1813cdcd52d4SBartosz Sobczak err = EINVAL;
1814cdcd52d4SBartosz Sobczak printf("%s: post work request failed, invalid opcode: 0x%x\n",
1815cdcd52d4SBartosz Sobczak __func__, ib_wr->opcode);
1816cdcd52d4SBartosz Sobczak break;
1817cdcd52d4SBartosz Sobczak }
1818cdcd52d4SBartosz Sobczak if (err)
1819cdcd52d4SBartosz Sobczak break;
1820cdcd52d4SBartosz Sobczak
1821cdcd52d4SBartosz Sobczak ib_wr = ib_wr->next;
1822cdcd52d4SBartosz Sobczak }
1823cdcd52d4SBartosz Sobczak
1824cdcd52d4SBartosz Sobczak if (err)
1825cdcd52d4SBartosz Sobczak *bad_wr = ib_wr;
1826cdcd52d4SBartosz Sobczak
1827cdcd52d4SBartosz Sobczak irdma_uk_qp_post_wr(&iwuqp->qp);
1828cdcd52d4SBartosz Sobczak if (reflush)
1829cdcd52d4SBartosz Sobczak irdma_issue_flush(ib_qp, 1, 0);
1830cdcd52d4SBartosz Sobczak
1831cdcd52d4SBartosz Sobczak pthread_spin_unlock(&iwuqp->lock);
1832cdcd52d4SBartosz Sobczak
1833cdcd52d4SBartosz Sobczak return err;
1834cdcd52d4SBartosz Sobczak }
1835cdcd52d4SBartosz Sobczak
1836cdcd52d4SBartosz Sobczak /**
1837cdcd52d4SBartosz Sobczak * irdma_post_recv - post receive wr for user application
1838cdcd52d4SBartosz Sobczak * @ib_wr: work request for receive
1839cdcd52d4SBartosz Sobczak * @bad_wr: bad wr caused an error
1840cdcd52d4SBartosz Sobczak */
1841cdcd52d4SBartosz Sobczak int
irdma_upost_recv(struct ibv_qp * ib_qp,struct ibv_recv_wr * ib_wr,struct ibv_recv_wr ** bad_wr)1842cdcd52d4SBartosz Sobczak irdma_upost_recv(struct ibv_qp *ib_qp, struct ibv_recv_wr *ib_wr,
1843cdcd52d4SBartosz Sobczak struct ibv_recv_wr **bad_wr)
1844cdcd52d4SBartosz Sobczak {
1845cdcd52d4SBartosz Sobczak struct irdma_post_rq_info post_recv = {};
1846cdcd52d4SBartosz Sobczak struct irdma_uqp *iwuqp;
1847cdcd52d4SBartosz Sobczak bool reflush = false;
1848cdcd52d4SBartosz Sobczak int err = 0;
1849cdcd52d4SBartosz Sobczak
1850cdcd52d4SBartosz Sobczak iwuqp = container_of(ib_qp, struct irdma_uqp, ibv_qp);
1851cdcd52d4SBartosz Sobczak err = pthread_spin_lock(&iwuqp->lock);
1852cdcd52d4SBartosz Sobczak if (err)
1853cdcd52d4SBartosz Sobczak return err;
1854cdcd52d4SBartosz Sobczak
1855cdcd52d4SBartosz Sobczak if (!IRDMA_RING_MORE_WORK(iwuqp->qp.rq_ring) &&
1856cdcd52d4SBartosz Sobczak ib_qp->state == IBV_QPS_ERR)
1857cdcd52d4SBartosz Sobczak reflush = true;
1858cdcd52d4SBartosz Sobczak
1859cdcd52d4SBartosz Sobczak while (ib_wr) {
1860cdcd52d4SBartosz Sobczak if (ib_wr->num_sge > iwuqp->qp.max_rq_frag_cnt) {
1861cdcd52d4SBartosz Sobczak *bad_wr = ib_wr;
1862cdcd52d4SBartosz Sobczak err = EINVAL;
1863cdcd52d4SBartosz Sobczak goto error;
1864cdcd52d4SBartosz Sobczak }
1865cdcd52d4SBartosz Sobczak post_recv.num_sges = ib_wr->num_sge;
1866cdcd52d4SBartosz Sobczak post_recv.wr_id = ib_wr->wr_id;
1867*5b5f7d0eSBartosz Sobczak post_recv.sg_list = ib_wr->sg_list;
1868cdcd52d4SBartosz Sobczak err = irdma_uk_post_receive(&iwuqp->qp, &post_recv);
1869cdcd52d4SBartosz Sobczak if (err) {
1870cdcd52d4SBartosz Sobczak *bad_wr = ib_wr;
1871cdcd52d4SBartosz Sobczak goto error;
1872cdcd52d4SBartosz Sobczak }
1873cdcd52d4SBartosz Sobczak
1874cdcd52d4SBartosz Sobczak if (reflush)
1875cdcd52d4SBartosz Sobczak irdma_issue_flush(ib_qp, 0, 1);
1876cdcd52d4SBartosz Sobczak
1877cdcd52d4SBartosz Sobczak ib_wr = ib_wr->next;
1878cdcd52d4SBartosz Sobczak }
1879cdcd52d4SBartosz Sobczak error:
1880cdcd52d4SBartosz Sobczak pthread_spin_unlock(&iwuqp->lock);
1881cdcd52d4SBartosz Sobczak
1882cdcd52d4SBartosz Sobczak return err;
1883cdcd52d4SBartosz Sobczak }
1884cdcd52d4SBartosz Sobczak
1885cdcd52d4SBartosz Sobczak /**
1886cdcd52d4SBartosz Sobczak * irdma_ucreate_ah - create address handle associated with a pd
1887cdcd52d4SBartosz Sobczak * @ibpd: pd for the address handle
1888cdcd52d4SBartosz Sobczak * @attr: attributes of address handle
1889cdcd52d4SBartosz Sobczak */
1890cdcd52d4SBartosz Sobczak struct ibv_ah *
irdma_ucreate_ah(struct ibv_pd * ibpd,struct ibv_ah_attr * attr)1891cdcd52d4SBartosz Sobczak irdma_ucreate_ah(struct ibv_pd *ibpd, struct ibv_ah_attr *attr)
1892cdcd52d4SBartosz Sobczak {
1893cdcd52d4SBartosz Sobczak struct irdma_uah *ah;
1894cdcd52d4SBartosz Sobczak union ibv_gid sgid;
1895777e472cSBartosz Sobczak struct irdma_ucreate_ah_resp resp = {};
1896cdcd52d4SBartosz Sobczak int err;
1897cdcd52d4SBartosz Sobczak
189801fbb869SBartosz Sobczak if (ibv_query_gid(ibpd->context, attr->port_num, attr->grh.sgid_index,
189901fbb869SBartosz Sobczak &sgid)) {
1900cdcd52d4SBartosz Sobczak fprintf(stderr, "irdma: Error from ibv_query_gid.\n");
190101fbb869SBartosz Sobczak errno = ENOENT;
1902cdcd52d4SBartosz Sobczak return NULL;
1903cdcd52d4SBartosz Sobczak }
1904cdcd52d4SBartosz Sobczak
1905cdcd52d4SBartosz Sobczak ah = calloc(1, sizeof(*ah));
1906cdcd52d4SBartosz Sobczak if (!ah)
1907cdcd52d4SBartosz Sobczak return NULL;
1908cdcd52d4SBartosz Sobczak
1909cdcd52d4SBartosz Sobczak err = ibv_cmd_create_ah(ibpd, &ah->ibv_ah, attr, &resp.ibv_resp,
1910cdcd52d4SBartosz Sobczak sizeof(resp));
1911cdcd52d4SBartosz Sobczak if (err) {
1912cdcd52d4SBartosz Sobczak free(ah);
1913cdcd52d4SBartosz Sobczak errno = err;
1914cdcd52d4SBartosz Sobczak return NULL;
1915cdcd52d4SBartosz Sobczak }
1916cdcd52d4SBartosz Sobczak
1917cdcd52d4SBartosz Sobczak ah->ah_id = resp.ah_id;
1918cdcd52d4SBartosz Sobczak
1919cdcd52d4SBartosz Sobczak return &ah->ibv_ah;
1920cdcd52d4SBartosz Sobczak }
1921cdcd52d4SBartosz Sobczak
1922cdcd52d4SBartosz Sobczak /**
1923cdcd52d4SBartosz Sobczak * irdma_udestroy_ah - destroy the address handle
1924cdcd52d4SBartosz Sobczak * @ibah: address handle
1925cdcd52d4SBartosz Sobczak */
1926cdcd52d4SBartosz Sobczak int
irdma_udestroy_ah(struct ibv_ah * ibah)1927cdcd52d4SBartosz Sobczak irdma_udestroy_ah(struct ibv_ah *ibah)
1928cdcd52d4SBartosz Sobczak {
1929cdcd52d4SBartosz Sobczak struct irdma_uah *ah;
1930cdcd52d4SBartosz Sobczak int ret;
1931cdcd52d4SBartosz Sobczak
1932cdcd52d4SBartosz Sobczak ah = container_of(ibah, struct irdma_uah, ibv_ah);
1933cdcd52d4SBartosz Sobczak
1934cdcd52d4SBartosz Sobczak ret = ibv_cmd_destroy_ah(ibah);
1935cdcd52d4SBartosz Sobczak if (ret)
1936cdcd52d4SBartosz Sobczak return ret;
1937cdcd52d4SBartosz Sobczak
1938cdcd52d4SBartosz Sobczak free(ah);
1939cdcd52d4SBartosz Sobczak
1940cdcd52d4SBartosz Sobczak return 0;
1941cdcd52d4SBartosz Sobczak }
1942cdcd52d4SBartosz Sobczak
1943cdcd52d4SBartosz Sobczak /**
1944cdcd52d4SBartosz Sobczak * irdma_uattach_mcast - Attach qp to multicast group implemented
1945cdcd52d4SBartosz Sobczak * @qp: The queue pair
1946cdcd52d4SBartosz Sobczak * @gid:The Global ID for multicast group
1947cdcd52d4SBartosz Sobczak * @lid: The Local ID
1948cdcd52d4SBartosz Sobczak */
1949cdcd52d4SBartosz Sobczak int
irdma_uattach_mcast(struct ibv_qp * qp,const union ibv_gid * gid,uint16_t lid)1950cdcd52d4SBartosz Sobczak irdma_uattach_mcast(struct ibv_qp *qp, const union ibv_gid *gid,
1951cdcd52d4SBartosz Sobczak uint16_t lid)
1952cdcd52d4SBartosz Sobczak {
1953cdcd52d4SBartosz Sobczak return ibv_cmd_attach_mcast(qp, gid, lid);
1954cdcd52d4SBartosz Sobczak }
1955cdcd52d4SBartosz Sobczak
1956cdcd52d4SBartosz Sobczak /**
1957cdcd52d4SBartosz Sobczak * irdma_udetach_mcast - Detach qp from multicast group
1958cdcd52d4SBartosz Sobczak * @qp: The queue pair
1959cdcd52d4SBartosz Sobczak * @gid:The Global ID for multicast group
1960cdcd52d4SBartosz Sobczak * @lid: The Local ID
1961cdcd52d4SBartosz Sobczak */
1962cdcd52d4SBartosz Sobczak int
irdma_udetach_mcast(struct ibv_qp * qp,const union ibv_gid * gid,uint16_t lid)1963cdcd52d4SBartosz Sobczak irdma_udetach_mcast(struct ibv_qp *qp, const union ibv_gid *gid,
1964cdcd52d4SBartosz Sobczak uint16_t lid)
1965cdcd52d4SBartosz Sobczak {
1966cdcd52d4SBartosz Sobczak return ibv_cmd_detach_mcast(qp, gid, lid);
1967cdcd52d4SBartosz Sobczak }
1968cdcd52d4SBartosz Sobczak
1969cdcd52d4SBartosz Sobczak /**
1970cdcd52d4SBartosz Sobczak * irdma_uresize_cq - resizes a cq
1971cdcd52d4SBartosz Sobczak * @cq: cq to resize
1972cdcd52d4SBartosz Sobczak * @cqe: the number of cqes of the new cq
1973cdcd52d4SBartosz Sobczak */
1974cdcd52d4SBartosz Sobczak int
irdma_uresize_cq(struct ibv_cq * cq,int cqe)1975cdcd52d4SBartosz Sobczak irdma_uresize_cq(struct ibv_cq *cq, int cqe)
1976cdcd52d4SBartosz Sobczak {
1977cdcd52d4SBartosz Sobczak struct irdma_uvcontext *iwvctx;
1978cdcd52d4SBartosz Sobczak struct irdma_uk_attrs *uk_attrs;
1979cdcd52d4SBartosz Sobczak struct irdma_uresize_cq cmd = {};
1980cdcd52d4SBartosz Sobczak struct ibv_resize_cq_resp resp = {};
1981cdcd52d4SBartosz Sobczak struct irdma_ureg_mr reg_mr_cmd = {};
1982cdcd52d4SBartosz Sobczak struct ibv_reg_mr_resp reg_mr_resp = {};
1983cdcd52d4SBartosz Sobczak struct irdma_cq_buf *cq_buf = NULL;
1984cdcd52d4SBartosz Sobczak struct irdma_cqe *cq_base = NULL;
1985cdcd52d4SBartosz Sobczak struct verbs_mr new_mr = {};
1986cdcd52d4SBartosz Sobczak struct irdma_ucq *iwucq;
1987cdcd52d4SBartosz Sobczak size_t cq_size;
1988cdcd52d4SBartosz Sobczak u32 cq_pages;
1989cdcd52d4SBartosz Sobczak int cqe_needed;
1990cdcd52d4SBartosz Sobczak int ret = 0;
1991cdcd52d4SBartosz Sobczak
1992cdcd52d4SBartosz Sobczak iwucq = container_of(cq, struct irdma_ucq, verbs_cq.cq);
1993cdcd52d4SBartosz Sobczak iwvctx = container_of(cq->context, struct irdma_uvcontext, ibv_ctx);
1994cdcd52d4SBartosz Sobczak uk_attrs = &iwvctx->uk_attrs;
1995cdcd52d4SBartosz Sobczak
1996cdcd52d4SBartosz Sobczak if (!(uk_attrs->feature_flags & IRDMA_FEATURE_CQ_RESIZE))
1997cdcd52d4SBartosz Sobczak return EOPNOTSUPP;
1998cdcd52d4SBartosz Sobczak
1999777e472cSBartosz Sobczak if (cqe < uk_attrs->min_hw_cq_size || cqe > uk_attrs->max_hw_cq_size - 1)
2000cdcd52d4SBartosz Sobczak return EINVAL;
2001cdcd52d4SBartosz Sobczak
2002*5b5f7d0eSBartosz Sobczak cqe_needed = get_cq_size(cqe, uk_attrs->hw_rev);
2003cdcd52d4SBartosz Sobczak if (cqe_needed == iwucq->cq.cq_size)
2004cdcd52d4SBartosz Sobczak return 0;
2005cdcd52d4SBartosz Sobczak
2006*5b5f7d0eSBartosz Sobczak cq_size = get_cq_total_bytes(cqe_needed);
2007cdcd52d4SBartosz Sobczak cq_pages = cq_size >> IRDMA_HW_PAGE_SHIFT;
2008cdcd52d4SBartosz Sobczak cq_base = irdma_alloc_hw_buf(cq_size);
2009cdcd52d4SBartosz Sobczak if (!cq_base)
2010cdcd52d4SBartosz Sobczak return ENOMEM;
2011cdcd52d4SBartosz Sobczak
2012cdcd52d4SBartosz Sobczak memset(cq_base, 0, cq_size);
2013cdcd52d4SBartosz Sobczak
2014cdcd52d4SBartosz Sobczak cq_buf = malloc(sizeof(*cq_buf));
2015cdcd52d4SBartosz Sobczak if (!cq_buf) {
2016cdcd52d4SBartosz Sobczak ret = ENOMEM;
2017cdcd52d4SBartosz Sobczak goto err_buf;
2018cdcd52d4SBartosz Sobczak }
2019cdcd52d4SBartosz Sobczak
2020cdcd52d4SBartosz Sobczak new_mr.ibv_mr.pd = iwucq->vmr.ibv_mr.pd;
2021cdcd52d4SBartosz Sobczak reg_mr_cmd.reg_type = IRDMA_MEMREG_TYPE_CQ;
2022cdcd52d4SBartosz Sobczak reg_mr_cmd.cq_pages = cq_pages;
2023cdcd52d4SBartosz Sobczak
2024cdcd52d4SBartosz Sobczak ret = ibv_cmd_reg_mr(new_mr.ibv_mr.pd, cq_base, cq_size,
2025cdcd52d4SBartosz Sobczak (uintptr_t)cq_base, IBV_ACCESS_LOCAL_WRITE,
2026cdcd52d4SBartosz Sobczak &new_mr.ibv_mr, ®_mr_cmd.ibv_cmd, sizeof(reg_mr_cmd),
2027cdcd52d4SBartosz Sobczak ®_mr_resp, sizeof(reg_mr_resp));
2028cdcd52d4SBartosz Sobczak if (ret)
2029cdcd52d4SBartosz Sobczak goto err_dereg_mr;
2030cdcd52d4SBartosz Sobczak
2031cdcd52d4SBartosz Sobczak ret = pthread_spin_lock(&iwucq->lock);
2032cdcd52d4SBartosz Sobczak if (ret)
2033cdcd52d4SBartosz Sobczak goto err_lock;
2034cdcd52d4SBartosz Sobczak
2035cdcd52d4SBartosz Sobczak cmd.user_cq_buffer = (__u64) ((uintptr_t)cq_base);
2036cdcd52d4SBartosz Sobczak ret = ibv_cmd_resize_cq(&iwucq->verbs_cq.cq, cqe_needed, &cmd.ibv_cmd,
2037cdcd52d4SBartosz Sobczak sizeof(cmd), &resp, sizeof(resp));
2038cdcd52d4SBartosz Sobczak if (ret)
2039cdcd52d4SBartosz Sobczak goto err_resize;
2040cdcd52d4SBartosz Sobczak
2041cdcd52d4SBartosz Sobczak memcpy(&cq_buf->cq, &iwucq->cq, sizeof(cq_buf->cq));
2042cdcd52d4SBartosz Sobczak cq_buf->vmr = iwucq->vmr;
2043cdcd52d4SBartosz Sobczak iwucq->vmr = new_mr;
2044cdcd52d4SBartosz Sobczak irdma_uk_cq_resize(&iwucq->cq, cq_base, cqe_needed);
2045cdcd52d4SBartosz Sobczak iwucq->verbs_cq.cq.cqe = cqe;
2046cdcd52d4SBartosz Sobczak LIST_INSERT_HEAD(&iwucq->resize_list, cq_buf, list);
2047cdcd52d4SBartosz Sobczak
2048cdcd52d4SBartosz Sobczak pthread_spin_unlock(&iwucq->lock);
2049cdcd52d4SBartosz Sobczak
2050cdcd52d4SBartosz Sobczak return ret;
2051cdcd52d4SBartosz Sobczak
2052cdcd52d4SBartosz Sobczak err_resize:
2053cdcd52d4SBartosz Sobczak pthread_spin_unlock(&iwucq->lock);
2054cdcd52d4SBartosz Sobczak err_lock:
2055cdcd52d4SBartosz Sobczak ibv_cmd_dereg_mr(&new_mr.ibv_mr);
2056cdcd52d4SBartosz Sobczak err_dereg_mr:
2057cdcd52d4SBartosz Sobczak free(cq_buf);
2058cdcd52d4SBartosz Sobczak err_buf:
2059cdcd52d4SBartosz Sobczak fprintf(stderr, "failed to resize CQ cq_id=%d ret=%d\n", iwucq->cq.cq_id, ret);
2060cdcd52d4SBartosz Sobczak irdma_free_hw_buf(cq_base, cq_size);
2061cdcd52d4SBartosz Sobczak return ret;
2062cdcd52d4SBartosz Sobczak }
2063