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