xref: /trueos/contrib/ofed/management/opensm/osmtest/osmt_mtl_regular_qp.c (revision 8fe640108653f13042f1b15213769e338aa524f6)
1 /*
2  * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
3  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
4  *
5  * This software is available to you under a choice of one of two
6  * licenses.  You may choose to be licensed under the terms of the GNU
7  * General Public License (GPL) Version 2, available from the file
8  * COPYING in the main directory of this source tree, or the
9  * OpenIB.org BSD license below:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      - Redistributions of source code must retain the above
16  *        copyright notice, this list of conditions and the following
17  *        disclaimer.
18  *
19  *      - Redistributions in binary form must reproduce the above
20  *        copyright notice, this list of conditions and the following
21  *        disclaimer in the documentation and/or other materials
22  *        provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  *
33  */
34 
35 #ifdef OSM_VENDOR_INTF_MTL
36 
37 /*                  - Mellanox Confidential and Proprietary -
38  *
39  *  Copyright (C) Jul. 2001, Mellanox Technologies Ltd.  ALL RIGHTS RESERVED.
40  *
41  *  Except as specifically permitted herein, no portion of the information,
42  *  including but not limited to object code and source code, may be reproduced,
43  *  modified, distributed, republished or otherwise exploited in any form or by
44  *  any means for any purpose without the prior written permission of Mellanox
45  *  Technologies Ltd. Use of software subject to the terms and conditions
46  *  detailed in the file "LICENSE.txt".
47  *
48  *  End of legal section ......................................................
49  *
50  *  osmt_mtl_regular_qp.c -
51  *    Provide Simple Interface for Sending and Receiving MADS through a regular QP
52  *
53  *  Creation date:
54  *
55  *  Version: $Id$
56  *
57  *  Authors:
58  *    Eitan Zahavi
59  *
60  *  Changes:
61  */
62 
63 #include <stdio.h>
64 #include <stdlib.h>
65 #include <string.h>
66 #include <unistd.h>
67 #include <signal.h>
68 
69 #include <mtl_common.h>
70 #include <vapi.h>
71 #include <evapi.h>
72 #include <vapi_common.h>
73 #include <ib_defs.h>
74 #include <osmt_mtl_regular_qp.h>
75 #include <complib/cl_types.h>
76 /*
77  * Initialize the QP etc.
78  * Given in res: port_num, max_outs_sq, max_outs_rq
79  */
osmt_mtl_get_qp_resources(IN OUT osmt_mtl_mad_res_t * res)80 VAPI_ret_t osmt_mtl_get_qp_resources(IN OUT osmt_mtl_mad_res_t * res)
81 {
82 	VAPI_ret_t ret;
83 	VAPI_hca_port_t hca_port_info;
84 	VAPI_qp_init_attr_t qp_init_attr;
85 	VAPI_qp_prop_t qp_prop;
86 	VAPI_cqe_num_t act_num;
87 
88 	/* Get HCA LID */
89 	ret =
90 	    VAPI_query_hca_port_prop(res->hca_hndl, res->port_num,
91 				     &hca_port_info);
92 	VAPI_CHECK_RET;
93 	res->slid = hca_port_info.lid;
94 
95 	/* Get a PD */
96 	ret = VAPI_alloc_pd(res->hca_hndl, &(res->pd_hndl));
97 	VAPI_CHECK_RET;
98 
99 	/* Create CQ for RQ and SQ *//* TBD - Check we have enough act nums */
100 	ret =
101 	    VAPI_create_cq(res->hca_hndl, res->max_outs_sq + 1,
102 			   &(res->sq_cq_hndl), &act_num);
103 	VAPI_CHECK_RET;
104 	ret =
105 	    VAPI_create_cq(res->hca_hndl, res->max_outs_rq + 1,
106 			   &(res->rq_cq_hndl), &act_num);
107 	VAPI_CHECK_RET;
108 
109 	/* register event handlers for polling(block mode) internal use */
110 	/* ret= EVAPI_set_comp_eventh(res->hca_hndl,res->rq_cq_hndl, */
111 	/*                            EVAPI_POLL_CQ_UNBLOCK_HANDLER,NULL,&(res->rq_cq_eventh)); */
112 	/* VAPI_CHECK_RET; */
113 	/* ret= EVAPI_set_comp_eventh(res->hca_hndl,res->sq_cq_hndl, */
114 	/*                            EVAPI_POLL_CQ_UNBLOCK_HANDLER,NULL,&(res->sq_cq_eventh)); */
115 	/* VAPI_CHECK_RET; */
116 
117 	/* Create QP */
118 	qp_init_attr.cap.max_oust_wr_sq = res->max_outs_sq + 1;
119 	qp_init_attr.cap.max_oust_wr_rq = res->max_outs_rq + 1;
120 	qp_init_attr.cap.max_sg_size_sq = 4;
121 	qp_init_attr.cap.max_sg_size_rq = 4;
122 
123 	qp_init_attr.pd_hndl = res->pd_hndl;
124 	qp_init_attr.rdd_hndl = 0;
125 	qp_init_attr.rq_cq_hndl = res->rq_cq_hndl;
126 	qp_init_attr.rq_sig_type = VAPI_SIGNAL_ALL_WR;	/* That's default for IB */
127 	qp_init_attr.sq_cq_hndl = res->sq_cq_hndl;
128 	qp_init_attr.sq_sig_type = VAPI_SIGNAL_REQ_WR;
129 	qp_init_attr.ts_type = VAPI_TS_UD;
130 
131 	ret =
132 	    VAPI_create_qp(res->hca_hndl, &qp_init_attr, &(res->qp_hndl),
133 			   &qp_prop);
134 	VAPI_CHECK_RET;
135 	res->qp_id.qp_num = qp_prop.qp_num;
136 
137 	return (VAPI_OK);
138 }
139 
osmt_mtl_qp_init(osmt_mtl_mad_res_t * res)140 VAPI_ret_t osmt_mtl_qp_init(osmt_mtl_mad_res_t * res)
141 {
142 	VAPI_ret_t ret;
143 
144 	VAPI_qp_attr_t qp_attr;
145 	VAPI_qp_attr_mask_t qp_attr_mask;
146 	VAPI_qp_cap_t qp_cap;
147 
148 	/*
149 	 * Change QP to INIT
150 	 *
151 	 */
152 	QP_ATTR_MASK_CLR_ALL(qp_attr_mask);
153 	qp_attr.qp_state = VAPI_INIT;
154 	QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_QP_STATE);
155 	qp_attr.pkey_ix = 0;
156 	QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_PKEY_IX);
157 	qp_attr.port = res->port_num;
158 	QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_PORT);
159 	qp_attr.qkey = res->qkey;
160 	QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_QKEY);
161 
162 	/* If I do not set this mask, I get an error from HH. QPM should catch it */
163 	ret =
164 	    VAPI_modify_qp(res->hca_hndl, res->qp_hndl, &qp_attr, &qp_attr_mask,
165 			   &qp_cap);
166 	VAPI_CHECK_RET;
167 
168 	return (ret);
169 
170 }
171 
osmt_mtl_qp_2_rtr_rts(osmt_mtl_mad_res_t * res)172 VAPI_ret_t osmt_mtl_qp_2_rtr_rts(osmt_mtl_mad_res_t * res)
173 {
174 	VAPI_ret_t ret;
175 
176 	VAPI_qp_attr_t qp_attr;
177 	VAPI_qp_attr_mask_t qp_attr_mask;
178 	VAPI_qp_cap_t qp_cap;
179 
180 	/*
181 	 *  Change QP to RTR
182 	 *
183 	 */
184 	QP_ATTR_MASK_CLR_ALL(qp_attr_mask);
185 	qp_attr.qp_state = VAPI_RTR;
186 	QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_QP_STATE);
187 	/*   qp_attr.rq_psn   = 0;                */
188 	/*   QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_RQ_PSN); */
189 
190 	ret =
191 	    VAPI_modify_qp(res->hca_hndl, res->qp_hndl, &qp_attr, &qp_attr_mask,
192 			   &qp_cap);
193 	VAPI_CHECK_RET;
194 
195 	/*
196 	 * Change QP to RTS
197 	 *
198 	 */
199 	QP_ATTR_MASK_CLR_ALL(qp_attr_mask);
200 	qp_attr.qp_state = VAPI_RTS;
201 	QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_QP_STATE);
202 	qp_attr.sq_psn = 0;
203 	QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_SQ_PSN);
204 
205 	ret =
206 	    VAPI_modify_qp(res->hca_hndl, res->qp_hndl, &qp_attr, &qp_attr_mask,
207 			   &qp_cap);
208 	VAPI_CHECK_RET;
209 
210 	return (ret);
211 }
212 
osmt_mtl_mad_create_mr(osmt_mtl_mad_res_t * res)213 VAPI_ret_t osmt_mtl_mad_create_mr(osmt_mtl_mad_res_t * res)
214 {
215 
216 	VAPI_ret_t ret;
217 
218 	VAPI_mrw_t mr_in, mr_out;
219 
220 	res->buf_size =
221 	    (MAD_SIZE + GRH_LEN) * (res->max_outs_sq + res->max_outs_rq + 1);
222 
223 	/* Register single memory address region for all buffers */
224 	res->buf_ptr = VMALLOC(res->buf_size);
225 
226 	if (res->buf_ptr == ((VAPI_virt_addr_t) NULL)) {
227 		ret = VAPI_EAGAIN;
228 		VAPI_CHECK_RET;
229 	}
230 
231 	/* Enable local and remote access to memory region */
232 	mr_in.acl = VAPI_EN_LOCAL_WRITE | VAPI_EN_REMOTE_WRITE;
233 	mr_in.l_key = 0;
234 	mr_in.pd_hndl = res->pd_hndl;
235 	mr_in.r_key = 0;
236 	mr_in.size = res->buf_size;
237 	ASSERT_VOIDP2UINTN(res->buf_ptr);
238 	mr_in.start = (VAPI_virt_addr_t) (uintn_t) (res->buf_ptr);
239 	mr_in.type = VAPI_MR;
240 
241 	ret = VAPI_register_mr(res->hca_hndl, &mr_in, &(res->mr_hndl), &mr_out);
242 	VAPI_CHECK_RET;
243 
244 	res->l_key = mr_out.l_key;
245 
246 	return (ret);
247 }
248 
osmt_mtl_init_opened_hca(osmt_mtl_mad_res_t * res)249 VAPI_ret_t osmt_mtl_init_opened_hca(osmt_mtl_mad_res_t * res)
250 {
251 	VAPI_ret_t ret;
252 
253 	res->pd_hndl = VAPI_INVAL_HNDL;
254 	res->rq_cq_hndl = VAPI_INVAL_HNDL;
255 	res->sq_cq_hndl = VAPI_INVAL_HNDL;
256 	res->sq_cq_eventh = VAPI_INVAL_HNDL;
257 	res->rq_cq_eventh = VAPI_INVAL_HNDL;
258 	res->qp_hndl = VAPI_INVAL_HNDL;
259 	res->mr_hndl = VAPI_INVAL_HNDL;
260 
261 	/*
262 	 * Create QP
263 	 *
264 	 */
265 	ret = osmt_mtl_get_qp_resources(res);
266 	if (ret != VAPI_OK) {
267 		return ret;
268 	}
269 
270 	/*
271 	 * Move to init
272 	 *
273 	 */
274 	ret = osmt_mtl_qp_init(res);
275 	if (ret != VAPI_OK) {
276 		return ret;
277 	}
278 
279 	/*
280 	 * Initialize memory regions
281 	 *
282 	 */
283 	ret = osmt_mtl_mad_create_mr(res);
284 	if (ret != VAPI_OK) {
285 		return ret;
286 	}
287 
288 	/* only now move to RTR and RTS */
289 	ret = osmt_mtl_qp_2_rtr_rts(res);
290 	if (ret != VAPI_OK) {
291 		return ret;
292 	}
293 
294 	return VAPI_OK;
295 }
296 
osmt_mtl_mad_cleanup(osmt_mtl_mad_res_t * res)297 VAPI_ret_t osmt_mtl_mad_cleanup(osmt_mtl_mad_res_t * res)
298 {
299 	if (res->qp_hndl != VAPI_INVAL_HNDL) {
300 		VAPI_destroy_qp(res->hca_hndl, res->qp_hndl);
301 	}
302 	if (res->sq_cq_eventh != VAPI_INVAL_HNDL) {
303 		EVAPI_clear_comp_eventh(res->hca_hndl, res->sq_cq_eventh);
304 	}
305 	if (res->rq_cq_eventh != VAPI_INVAL_HNDL) {
306 		EVAPI_clear_comp_eventh(res->hca_hndl, res->rq_cq_eventh);
307 	}
308 	if (res->rq_cq_hndl != VAPI_INVAL_HNDL) {
309 		VAPI_destroy_cq(res->hca_hndl, res->rq_cq_hndl);
310 	}
311 	if (res->sq_cq_hndl != VAPI_INVAL_HNDL) {
312 		VAPI_destroy_cq(res->hca_hndl, res->sq_cq_hndl);
313 	}
314 	if (res->mr_hndl != VAPI_INVAL_HNDL) {
315 		VAPI_deregister_mr(res->hca_hndl, res->mr_hndl);
316 	}
317 	if (res->pd_hndl != VAPI_INVAL_HNDL) {
318 		VAPI_dealloc_pd(res->hca_hndl, res->pd_hndl);
319 	}
320 #if 0
321 	/* open/close of HCA should be done system wide - not per application */
322 	if (res->hca_hndl != VAPI_INVAL_HNDL) {
323 		VAPI_close_hca(res->hca_hndl);	/* TBD: HCA_open/close should be done on a system wide basis */
324 	}
325 #endif
326 	return VAPI_OK;
327 }
328 
osmt_mtl_create_av(osmt_mtl_mad_res_t * res,int16_t dlid,VAPI_ud_av_hndl_t * avh_p)329 VAPI_ret_t osmt_mtl_create_av(osmt_mtl_mad_res_t * res, int16_t dlid,
330 			      VAPI_ud_av_hndl_t * avh_p)
331 {
332 	VAPI_ud_av_t av;
333 	VAPI_ret_t ret;
334 
335 	av.dlid = dlid;
336 	av.port = res->port_num;
337 	av.sl = 0;		/* dest->sl; */
338 	av.src_path_bits = 0;	/*  dest->ee_dlid.dst_path_bits; */
339 	av.static_rate = 0;
340 	/* GRH ? */
341 	av.grh_flag = 0;
342 
343 	ret = VAPI_create_addr_hndl(res->hca_hndl, res->pd_hndl, &av, avh_p);
344 	if (ret != VAPI_OK) {
345 		MTL_ERROR1("%s: failed VAPI_create_addr_hndl (%s)\n", __func__,
346 			   VAPI_strerror_sym(ret));
347 		return ret;
348 	}
349 	return VAPI_OK;
350 }
351 
osmt_mtl_mad_send(osmt_mtl_mad_res_t * res,VAPI_wr_id_t id,void * mad,VAPI_qp_num_t dest_qp,IB_sl_t sl,u_int32_t dest_qkey,VAPI_ud_av_hndl_t avh)352 VAPI_ret_t osmt_mtl_mad_send(osmt_mtl_mad_res_t * res, VAPI_wr_id_t id,
353 			     void *mad, VAPI_qp_num_t dest_qp, IB_sl_t sl,
354 			     u_int32_t dest_qkey, VAPI_ud_av_hndl_t avh)
355 {
356 	VAPI_sr_desc_t sr;
357 	VAPI_sg_lst_entry_t sg_entry;
358 	VAPI_ret_t ret;
359 
360 	/* building SEND request */
361 	sr.opcode = VAPI_SEND;
362 	sr.remote_ah = avh;
363 	sr.remote_qp = dest_qp;
364 	sr.remote_qkey = dest_qkey;
365 
366 	sr.id = id;
367 	sr.set_se = FALSE;
368 	sr.fence = FALSE;
369 	sr.comp_type = VAPI_SIGNALED;
370 	sr.sg_lst_len = 1;
371 	sr.sg_lst_p = &sg_entry;
372 	ASSERT_VOIDP2UINTN(mad);
373 	sg_entry.addr = (VAPI_virt_addr_t) (uintn_t) (mad);
374 	sg_entry.len = MAD_SIZE;
375 	sg_entry.lkey = res->l_key;
376 
377 	ret = VAPI_post_sr(res->hca_hndl, res->qp_hndl, &sr);
378 	if (ret != VAPI_OK) {
379 		MTL_ERROR1(__FUNCTION__ ": failed VAPI_post_sr (%s)\n",
380 			   VAPI_strerror_sym(ret));
381 		return ret;
382 	}
383 
384 	return VAPI_OK;
385 }
386 
osmt_mtl_mad_post_recv_bufs(osmt_mtl_mad_res_t * res,void * buf_array,u_int32_t num_o_bufs,u_int32_t size,VAPI_wr_id_t start_id)387 int osmt_mtl_mad_post_recv_bufs(osmt_mtl_mad_res_t * res, void *buf_array,
388 				u_int32_t num_o_bufs, u_int32_t size,
389 				VAPI_wr_id_t start_id)
390 {
391 	uint32_t i;
392 	void *cur_buf;
393 	VAPI_rr_desc_t rr;
394 	VAPI_sg_lst_entry_t sg_entry;
395 	VAPI_ret_t ret;
396 
397 	rr.opcode = VAPI_RECEIVE;
398 	rr.comp_type = VAPI_SIGNALED;	/* All with CQE (IB compliant) */
399 	rr.sg_lst_len = 1;	/* single buffers */
400 	rr.sg_lst_p = &sg_entry;
401 	sg_entry.lkey = res->l_key;
402 	cur_buf = buf_array;
403 	for (i = 0; i < num_o_bufs; i++) {
404 		rr.id = start_id + i;	/* WQE id used is the index to buffers ptr array */
405 		ASSERT_VOIDP2UINTN(cur_buf);
406 		sg_entry.addr = (VAPI_virt_addr_t) (uintn_t) cur_buf;
407 		sg_entry.len = size;
408 		memset(cur_buf, 0x00, size);	/* fill with 0 */
409 		ret = VAPI_post_rr(res->hca_hndl, res->qp_hndl, &rr);
410 		if (ret != VAPI_OK) {
411 			MTL_ERROR1(__FUNCTION__
412 				   ": failed posting RQ WQE (%s)\n",
413 				   VAPI_strerror_sym(ret));
414 			return i;
415 		}
416 		MTL_DEBUG4(__FUNCTION__ ": posted buf at %p\n", cur_buf);
417 		cur_buf += size;
418 	}
419 
420 	return i;		/* num of buffers posted */
421 }
422 
osmt_mtl_mad_poll4cqe(VAPI_hca_hndl_t hca,VAPI_cq_hndl_t cq,VAPI_wc_desc_t * wc_desc_p,u_int32_t max_poll,u_int32_t poll_sleep,VAPI_ud_av_hndl_t * avh_p)423 VAPI_ret_t osmt_mtl_mad_poll4cqe(VAPI_hca_hndl_t hca, VAPI_cq_hndl_t cq,
424 				 VAPI_wc_desc_t * wc_desc_p,
425 				 u_int32_t max_poll, u_int32_t poll_sleep,
426 				 VAPI_ud_av_hndl_t * avh_p)
427 {
428 	VAPI_ret_t ret = VAPI_CQ_EMPTY;
429 	u_int32_t poll_cnt = 0;
430 
431 	/* wait for something to arrive */
432 	while ((ret == VAPI_CQ_EMPTY) && (poll_cnt < max_poll)) {
433 		ret = VAPI_poll_cq(hca, cq, wc_desc_p);
434 		/* don't sleep if we already succeeded) */
435 		if (ret != VAPI_CQ_EMPTY) {
436 			break;
437 		}
438 		usleep(poll_sleep);
439 		poll_cnt++;
440 	}
441 
442 	/* if passed an AVH to destory - do it */
443 	if (avh_p != NULL) {
444 		VAPI_destroy_addr_hndl(hca, *avh_p);
445 	}
446 
447 	if ((poll_cnt == max_poll) && (ret == VAPI_CQ_EMPTY)) {
448 		MTL_DEBUG1(__FUNCTION__
449 			   ": Failed to get completion on wq after %d polls.\n",
450 			   max_poll);
451 		return VAPI_CQ_EMPTY;
452 	}
453 
454 	if (ret != VAPI_OK) {
455 		MTL_DEBUG1(__FUNCTION__
456 			   ": VAPI_poll_cq failed with ret=%s on sq_cq\n",
457 			   mtl_strerror_sym(ret));
458 		return ret;
459 	}
460 
461 	if (wc_desc_p->status != VAPI_SUCCESS) {
462 		MTL_DEBUG1(__FUNCTION__ ": completion error (%d) detected\n",
463 			   wc_desc_p->status);
464 	}
465 
466 	return VAPI_OK;
467 }
468 
469 #endif				/*  OSM_VENDOR_INTF_MTL */
470